Skip to content
Snippets Groups Projects
Select Git revision
  • 0f49232b0f3e30815bf9952d66ebb735f5568c5b
  • master default protected
  • file_refactoring
  • 1.1.0
4 results

spectra.cs

Blame
  • user avatar
    Carl Philipp Klemm authored
    These functions check if the lib is able to service requests as currently loaded
    Also use these functions to check if everything is ok at entry points to the various other classes
    add Utils.FloatEq() that uses the same logic as libeisgenerator to compare float values
    0f49232b
    History
    spectra.cs 6.29 KiB
    using System;
    using System.Runtime.InteropServices;
    
    namespace Kiss
    {
    
    /// <summary>
    /// This Class holds an impedance spectra and provides various transformations that are required to get the values into a form expected by kiss networks
    /// </summary>
    public class Spectra
    {
    	/// <summary>
    	/// The real part of the spectra
    	/// </summary>
    	public float[] Real;
    
    	/// <summary>
    	/// The imaginary part of the spectra
    	/// </summary>
    	public float[] Imaginary;
    
    	/// <summary>
    	/// The frequencys of the datapoints of the spectra
    	/// </summary>
    	public float[] Omega;
    
    	/// <summary>
    	/// This constructor constructs a spectra from a series of arrays
    	/// </summary>
    	/// <param name="Real">
    	/// The real part of the spectra
    	/// </param>
    	/// <param name="Imaginary">
    	/// The imaginary part of the spectra, its length must be the same as <paramref name="Real"/>
    	/// </param>
    	/// <param name="Omega">
    	/// The frequency values in rad/s of eatch datapoint, its lenght must be the same as <paramref name="Real"/>
    	/// </param>
    	/// <exception cref="Kiss.EnviromentException">
    	/// Thrown if the enviroment is unacceptable for the operation of this libaray
    	/// </exception>
    	public Spectra(float[] Real, float[] Imaginary, float[] Omega)
    	{
    		Utils.CheckEnvThrow();
    		if(Real.Length != Imaginary.Length || Real.Length != Omega.Length)
    			throw new ArgumentException("the real, imaginary and omega parts of the spectra have to be of the same size");
    		this.Real = Real;
    		this.Imaginary = Imaginary;
    		this.Omega = Omega;
    	}
    
    	/// <summary>
    	/// This constructor constructs a spectra from a series of arrays
    	/// </summary>
    	/// <param name="Real">
    	/// The real part of the spectra
    	/// </param>
    	/// <param name="Imaginary">
    	/// The imaginary part of the spectra, its length must be the same as <paramref name="Real"/>
    	/// </param>
    	/// <param name="Omega">
    	/// The frequency values in rad/s of eatch datapoint, its lenght must be the same as <paramref name="Real"/>
    	/// </param>
    	public Spectra(double[] Real, double[] Imaginary, double[] Omega)
    	{
    		if(Real.Length != Imaginary.Length || Real.Length != Omega.Length)
    			throw new ArgumentException("the real, imaginary and omega parts of the spectra have to be of the same size");
    		this.Real = DoubleToFloat(Real);
    		this.Imaginary = DoubleToFloat(Imaginary);
    		this.Omega = DoubleToFloat(Omega);
    	}
    
    	/// <summary>
    	/// This method normalizes the data into the range [0, 1]
    	/// </summary>
    	public void Normalize()
    	{
    		Capi.kiss_normalize_spectra(Real, Imaginary, (UIntPtr)Real.Length);
    	}
    
    	/// <summary>
    	/// This method resamples the spectra to the size given in newSize.
    	/// Upsampling is achived via linear interpolation, downsampling is achived via the nearest-neighbor method.
    	/// </summary>
    	/// <param name="newSize">
    	/// The size to resample the spectra to
    	/// </param>
    	public void Resample(int newSize)
    	{
    		var ret_ptr_real = new IntPtr();
    		var ret_ptr_imag = new IntPtr();
    		Capi.kiss_resample_spectra(Real, Imaginary, (UIntPtr)Real.Length, ref ret_ptr_real, ref ret_ptr_imag, (UIntPtr)newSize);
    
    		Real = new float[newSize];
    		Imaginary = new float[newSize];
    		Marshal.Copy(ret_ptr_real, Real, 0, newSize);
    		Marshal.Copy(ret_ptr_imag, Imaginary, 0, newSize);
    
    		Capi.free(ret_ptr_real);
    		Capi.free(ret_ptr_imag);
    	}
    
    	/// <summary>
    	/// Approximate the element wise absolute gradient at the given point of the sepctra in the place given
    	/// </summary>
    	/// <param name="index">
    	/// The index at which to aproxmiate the gradiant
    	/// </param>
    	/// <returns>
    	/// The element wise absolute of the gradiant as a tuple of floats
    	/// </returns>
    	public Tuple<float, float> Absgrad(int index)
    	{
    		var resultArray = new float[2];
    		IntPtr ptr = Capi.kiss_absgrad(Real, Imaginary, Omega, (UIntPtr)Real.Length, (UIntPtr)index);
    		Marshal.Copy(ptr, resultArray, 0, 2);
    		Capi.free(ptr);
    		return new Tuple<float, float>(resultArray[0], resultArray[1]);
    	}
    
    	/// <summary>
    	/// Applies the same series of filteres used by kiss networks (applied by TorchKissAnn) during training.
    	///
    	/// In almost all cases this function should be called before a sepctra is given to a kiss network.
    	/// </summary>
    	/// <param name="outputSize">
    	/// the length the spectra should have after filtering
    	/// </param>
    	/// <returns>
    	/// True if sucessfull, false otherwise
    	/// </returns>
    	public bool Filter(int outputSize)
    	{
    		var ret_ptr_real = new IntPtr();
    		var ret_ptr_imag = new IntPtr();
    		byte ret = Capi.kiss_filter_spectra(Real, Imaginary, Omega, (UIntPtr)Real.Length, ref ret_ptr_real, ref ret_ptr_imag, (UIntPtr)outputSize);
    
    		if(ret == 1)
    		{
    			Real = new float[(int)outputSize];
    			Imaginary = new float[(int)outputSize];
    			Marshal.Copy(ret_ptr_real, Real, 0, (int)outputSize);
    			Marshal.Copy(ret_ptr_imag, Imaginary, 0, (int)outputSize);
    			Capi.free(ret_ptr_real);
    			Capi.free(ret_ptr_imag);
    		}
    
    		return Convert.ToBoolean(ret);
    	}
    
    	/// <summary>
    	/// Applies the same series of filteres used by kiss networks (applied by TorchKissAnn) during training.
    	///
    	/// In almost all cases this function should be called before a sepctra is given to a kiss network.
    	/// </summary>
    	/// <param name="outputSize">
    	/// the length the spectra should have after filtering
    	/// </param>
    	/// <returns>
    	/// True if sucessfull, false otherwise
    	/// </returns>
    	public bool Reduce(float threshFactor, bool useSecondDeriv)
    	{
    		var ret_ptr_real = new IntPtr();
    		var ret_ptr_imag = new IntPtr();
    		var lengthPtr = new UIntPtr();
    		byte ret = Capi.kiss_reduce_spectra(Real, Imaginary, Omega, (UIntPtr)Real.Length, threshFactor, Convert.ToByte(useSecondDeriv), ref ret_ptr_real, ref ret_ptr_imag, ref lengthPtr);
    
    		if(ret == 1)
    		{
    			Real = new float[(int)lengthPtr];
    			Imaginary = new float[(int)lengthPtr];
    			Marshal.Copy(ret_ptr_real, Real, 0, (int)lengthPtr);
    			Marshal.Copy(ret_ptr_imag, Imaginary, 0, (int)lengthPtr);
    			Capi.free(ret_ptr_real);
    			Capi.free(ret_ptr_imag);
    		}
    
    		return Convert.ToBoolean(ret);
    	}
    
    	/// <summary>
    	/// Converts an array of doubles to an array of floats.
    	/// </summary>
    	/// <param name="input">
    	/// The input array.
    	/// </param>
    	/// <returns>
    	/// An array with the same values as the input truncated to floats.
    	/// </returns>
    	private static float[] DoubleToFloat(double[] input)
    	{
    		var res = new float[input.Length];
    		for(int i = 0; i < input.Length; ++i)
    			res[i] = (float)input[i];
    		return res;
    	}
    
    }
    
    }