/**************************************************************************** * GetfittingMetrics * calculate the fitting parameters that the user is interested in ****************************************************************************/ public FittingMetrics GetFittingMetrics(LorentzParams lp, FFTSettings fftSettings) { FittingMetrics fm = new FittingMetrics { amplitude = lp.A / lp.gamma / lp.gamma + lp.up, f0 = lp.f0 }; double ampPrime = 0; switch (fftSettings.Fftstyle) { case 0: //Log (dB) ampPrime = fm.amplitude - 3; break; case 1: // Log - Complex Conjugate (dB) ampPrime = fm.amplitude - 3; break; case 2: // Magnitude (V) ampPrime = fm.amplitude * 0.5; break; case 3: // Magnitude - Complex Conjugate (V) ampPrime = fm.amplitude * 0.5; break; } try { fm.f1 = fm.f0 + Math.Sqrt((lp.A + lp.gamma * lp.gamma * (lp.up - ampPrime)) / (ampPrime - lp.up)); fm.f2 = fm.f0 - Math.Sqrt((lp.A + lp.gamma * lp.gamma * (lp.up - ampPrime)) / (ampPrime - lp.up)); } catch (Exception) { fm.f1 = 0; fm.f2 = 0; } if (fm.f1 - fm.f2 > 0) { fm.Q = fm.f0 / (fm.f1 - fm.f2); } else { fm.Q = 0; } return(fm); }
// FFT CALCULATIONS // /**************************************************************************** * GetFFT * Get the raw FFT of an array ****************************************************************************/ private FFTData GetFFT(int[] amp, int[] time, FFTSettings fftSettings, double[] lastfft, int SampleCount) { FFTData fftData = new FFTData(); double[] fft = new double[amp.Length]; double[] freq = new double[amp.Length / 2]; //AForge.Math.Complex[] fftComplex = new AForge.Math.Complex[amp.Length]; Complex[] fftComplex = new Complex[amp.Length]; // if FFT style has changed, reset the averaging by making last FFT null. if (fftSettings.isFftStyleChange) { lastfft = null; } //calculate fft for (int i = 0; i < amp.Length; i++) { //fftComplex[i] = new AForge.Math.Complex(); fftComplex[i] = new Complex(amp[i], 0); } //AForge.Math.FourierTransform.FFT(fftComplex, AForge.Math.FourierTransform.Direction.Forward); Accord.Math.Transforms.FourierTransform2.FFT(fftComplex, Accord.Math.FourierTransform.Direction.Forward); // transform fft based on user selected style for (int i = 0; i < amp.Length; i++) { time[i] = time[i] - time.Min(); switch (fftSettings.Fftstyle) { case 0: //Log fft[i] = 20 * Math.Log10(fftComplex[i].Magnitude); // decibels=20Log, http://www.arrl.org/files/file/Instructor%20resources/A%20Tutorial%20on%20the%20Dec-N0AX.pdf if (fft[i] == Double.NegativeInfinity || fft[i] == Double.NaN) { fft[i] = 0; } break; case 1: // Log - Complex Conjugate fft[i] = 20 * Math.Log10(Complex.Conjugate(fftComplex[i]).Magnitude *fftComplex[i].Magnitude); if (fft[i] == Double.NegativeInfinity || fft[i] == Double.NaN) { fft[i] = 0; } break; case 2: // Magnitude fft[i] = fftComplex[i].Magnitude; break; case 3: // Magnitude - Complex Conjugate fft[i] = Complex.Conjugate(fftComplex[i]).Magnitude *fftComplex[i].Magnitude; break; default: break; } if (i % 2 == 0) { freq[i / 2] = /*Math.Pow(2,1024/SampleCount-1) */ (1024 / SampleCount) * Convert.ToDouble(i / 2) * 1e3 / (time[9] - time[8]); } } fft = fft.Take(fft.Length / 2).ToArray(); // transform FFT based on user selected averaging technique- New Average = (New Spectrum • 1/N) + (Old Average) • (N−1)/N if (lastfft == null) { fftSettings.isFftMovAvg = false; fftSettings.isFftContAvg = false; } if (fftSettings.isFftMovAvg) { for (int i = 0; i < fft.Length; i++) { fft[i] = fft[i] * 1 / fftSettings.nFftMovAvg + lastfft[i] * (fftSettings.nFftMovAvg - 1) / fftSettings.nFftMovAvg; } } if (fftSettings.isFftContAvg) { for (int i = 0; i < fft.Length; i++) { try { fft[i] = fft[i] * 1 / fftSettings.nFftContAvg + lastfft[i] * (fftSettings.nFftContAvg - 1) / fftSettings.nFftContAvg; } catch (Exception) { } } fftSettings.nFftContAvg++; } fftData.fft = fft; fftData.freq = freq; return(fftData); }
/**************************************************************************** * GetPlottableData * this function demonstrates how to collect a single block of data * from the unit (start collecting immediately) ****************************************************************************/ public PlottableData GetPlottableData(short handle, Pico.ChannelSettings[] channelSettings, FFTSettings fftSettings, double[] lastfft, ref ProcessTimes processTimes, ref System.Windows.Forms.Timer WaveFormTimer, int SampleCount, bool isChanelB) { Stopwatch sw = new Stopwatch(); //sw.Start(); WaveFormData waveFormData = new WaveFormData(); // Method that communicates with Pico to get blocked data HandlePicoBlockData(0, channelSettings, handle, ref waveFormData, ref processTimes, ref WaveFormTimer, SampleCount, isChanelB); //sw.Stop(); //return if it's chanel B if (isChanelB) { return new PlottableData { fftData = new FFTData(), WaveFormData = waveFormData } } ; // calculate fft data if is not chanel B sw.Restart(); PlottableData plottableData = new PlottableData { fftData = GetFFT(waveFormData.amp, waveFormData.time, fftSettings, lastfft, SampleCount), WaveFormData = waveFormData }; sw.Stop(); processTimes.fftTime = sw.Elapsed; return(plottableData); }