/// <summary> /// 获取线性调频信号中的 IQ数据 /// </summary> /// <param name="isIdata"></param> /// <returns></returns> private double[] LFMSingnal(bool isIdata = true) { double T = 10 * 1e-6; // 0.00001; double B = 1 * 1e6; // 1000000; double k = B / T; // 调频斜率 double t = 5 * 1e-6; // 0.000005;% 空信号时长5us double fs = 4 * 1e9; // 4000000000; // 生成200Msa线性调频信号 5us空 + 10us线性调频 double fs1 = 200 * 1e6; int n1 = (int)Math.Round(T * fs1); //采样点个数 //double[] t1 = new double[n1]; double tspan = T / n1; MathNet.Numerics.Complex32[] y1 = new MathNet.Numerics.Complex32[n1]; for (int i = 0; i < n1; i++) { MathNet.Numerics.Complex32 tempComple = new MathNet.Numerics.Complex32(0, (float)(Math.PI * k * (i * tspan) * (i * tspan))); // double aa= tempComple* k; y1[i] = MathNet.Numerics.Complex32.Exp(tempComple); } double[] idata = y1.Select(a => (double)a.Real).ToArray(); double[] qdata = y1.Select(a => (double)a.Imaginary).ToArray(); // freqDomi("LFM_freq.csv", idata, qdata, 200 * 1e6); double[] result = new double[1000 + n1]; if (isIdata) { Array.Copy(idata, 0, result, 1000, n1); //result = idata; } else { Array.Copy(qdata, 0, result, 1000, n1); //result = qdata; } return(result); //y1 = exp(1j * pi * k * t1.^ 2);% LFM信号 // MathNet.Numerics.Complex32.Exp() }
/** * 广义互相关频域补零时延估计算法 * @param zeroWaveData * 零应力波形 * @param testWaveData * 测试应力波形 * @param sampleTime * 采样间隔 * @param interTimes * 插值倍数 * @return TDETuple * [时延,互相关系数数组] * 时延,单位:s 拉应力时返回正数,压应力返回负数 */ public Tuple <double, double[]> GCC_FZPTDE(double[] zeroWaveData, double[] testWaveData, double sampleTime, int interTimes) { Tuple <double, double[]> TDETuple; double timeDelay = 9999.09; double[] abs_xCorr; if (zeroWaveData.Length != testWaveData.Length) { abs_xCorr = new double[128]; TDETuple = new Tuple <double, double[]>(timeDelay, abs_xCorr); return(TDETuple); } int realLength = zeroWaveData.Length; //将数据长度补零为2的幂 int fftDataLen = 1 << ((int)(Math.Log(realLength - 1) / Math.Log(2)) + 1); double[] pad_zeroWaveData = new double[fftDataLen]; //zeropadding double[] pad_testWaveData = new double[fftDataLen]; //zeropadding Array.Copy(zeroWaveData, pad_zeroWaveData, realLength); Array.Copy(testWaveData, pad_testWaveData, realLength); //傅里叶变换 MathNet.Numerics.Complex32[] zeroWaveFFTData = new MathNet.Numerics.Complex32[fftDataLen]; MathNet.Numerics.Complex32[] testWaveFFTData = new MathNet.Numerics.Complex32[fftDataLen]; for (int i = 0; i < fftDataLen; i++) //转为复数 { zeroWaveFFTData[i] = new MathNet.Numerics.Complex32((float)pad_zeroWaveData[i], 0); testWaveFFTData[i] = new MathNet.Numerics.Complex32((float)pad_testWaveData[i], 0); } Fourier.Forward(zeroWaveFFTData); //傅里叶变换 Fourier.Forward(testWaveFFTData); //傅里叶变换 //计算zeroWaveFFTData*(testWaveFFTData的共轭复数) MathNet.Numerics.Complex32[] xCorrFFT = new MathNet.Numerics.Complex32[fftDataLen * interTimes]; MathNet.Numerics.Complex32 testWaveFFTDataConj; for (int i = 0; i < fftDataLen / 2; i++) //正域赋值 { testWaveFFTDataConj = MathNet.Numerics.Complex32.Conjugate(testWaveFFTData[i]); xCorrFFT[i] = MathNet.Numerics.Complex32.Multiply(zeroWaveFFTData[i], testWaveFFTDataConj); } int n = 0; for (int i = fftDataLen / 2; i < fftDataLen; i++) //负域赋值 { n = i + (fftDataLen * interTimes - fftDataLen); xCorrFFT[n] = MathNet.Numerics.Complex32.Multiply(zeroWaveFFTData[i], MathNet.Numerics.Complex32.Conjugate(testWaveFFTData[i])); } //逆傅里叶变换 Fourier.Inverse(xCorrFFT); fftDataLen = fftDataLen * interTimes; abs_xCorr = new double[fftDataLen]; double scaling_factor = NormL2(zeroWaveData) * NormL2(testWaveData); //归一化缩放因子为2范数积 for (int i = 0; i < fftDataLen; i++) { abs_xCorr[i] = MathNet.Numerics.Complex32.Abs(xCorrFFT[i]); abs_xCorr[i] = abs_xCorr[i] * (Math.Sqrt((float)fftDataLen)) / scaling_factor; //归一化 } //查找abs_xCorr最大值对应位置 int maxPos = MaxIndex(abs_xCorr); //计算时延 单位:s timeDelay = (fftDataLen - maxPos); if (timeDelay > (double)fftDataLen / 2) { timeDelay = -1 * maxPos; } timeDelay = timeDelay * sampleTime / interTimes; TDETuple = new Tuple <double, double[]>(timeDelay, abs_xCorr); return(TDETuple); }
protected void UpdateSCI() { int nFFT = 32; while (maindisplaythread.IsAlive) { Thread.Sleep(3000); // update rate (default 500ms) for (int i = 0; i < nirsdata.Count; i++) { try { if (nirsdata[i].data[0].Count > nFFT + 15) { double fs = MainClass.devices[i].GetSampleRate(); double[] SCI = new double[realtimeEngine.mBLLmappings[i].distances.Length]; for (int ch = 0; ch < realtimeEngine.mBLLmappings[i].distances.Length; ch++) { MathNet.Numerics.Complex32[] w1 = new MathNet.Numerics.Complex32[nFFT]; MathNet.Numerics.Complex32[] w2 = new MathNet.Numerics.Complex32[nFFT]; int ntps = nirsdata[i].data[realtimeEngine.mBLLmappings[i].measurementPairs[ch][0]].Count - 5; double a = 0; double b = 0; int cc = 0; for (int tpt = ntps - nFFT; tpt < ntps; tpt++) { w1[cc] = new MathNet.Numerics.Complex32((float)nirsdata[i].data[realtimeEngine.mBLLmappings[i].measurementPairs[ch][0]][tpt], 0f); w2[cc] = new MathNet.Numerics.Complex32((float)nirsdata[i].data[realtimeEngine.mBLLmappings[i].measurementPairs[ch][1]][tpt], 0f); a += nirsdata[i].data[realtimeEngine.mBLLmappings[i].measurementPairs[ch][0]][tpt] * nirsdata[i].data[realtimeEngine.mBLLmappings[i].measurementPairs[ch][0]][tpt]; b += nirsdata[i].data[realtimeEngine.mBLLmappings[i].measurementPairs[ch][1]][tpt] * nirsdata[i].data[realtimeEngine.mBLLmappings[i].measurementPairs[ch][1]][tpt]; cc++; } Fourier.Forward(w1); Fourier.Forward(w2); cc = 0; for (double ii = -fs / 2; ii < fs / 2; ii += fs / nFFT) { if (Math.Abs(ii) < 0.5 | Math.Abs(ii) > 2) { w1[cc] = new MathNet.Numerics.Complex32(0f, w1[cc].Imaginary); w2[cc] = new MathNet.Numerics.Complex32(0f, w2[cc].Imaginary); } w1[cc] = w1[cc] * w2[cc].Conjugate(); } Fourier.Inverse(w1); SCI[ch] = w1[(int)Math.Round((double)nFFT / 2)].Real / Math.Sqrt(a * b); } double[] avgDetVal = new double[nirsdata[i].probe.numDet]; int[] cnt = new int[nirsdata[i].probe.numDet]; for (int ch = 0; ch < nirsdata[i].probe.numDet; ch++) { cnt[ch] = 0; avgDetVal[ch] = 0; } for (int ch = 0; ch < nirsdata[i].probe.numChannels / nirsdata[i].probe.numWavelengths; ch++) { int dIDx = nirsdata[i].probe.ChannelMap[ch].detectorindex; cnt[dIDx]++; avgDetVal[dIDx] += SCI[ch]; } for (int ch = 0; ch < MainClass.win._handles.detectors.Count; ch++) { Gdk.Color col; if (SCI[ch] < .3) { col = new Gdk.Color(255, 0, 0); } else if (SCI[ch] < .6) { col = new Gdk.Color(255, 255, 0); } else { col = new Gdk.Color(0, 255, 0); } MainClass.win._handles.detectors[ch].led.Color = col; } } } catch { Console.WriteLine("Updating SCI error"); } } } }
/// <summary> /// Converts the string representation of a complex number to a single-precision complex number equivalent. /// A return value indicates whether the conversion succeeded or failed. /// </summary> /// <param name="value"> /// A string containing a complex number to convert. /// </param> /// <param name="result"> /// The parsed value. /// </param> /// <returns> /// If the conversion succeeds, the result will contain a complex number equivalent to value. /// Otherwise the result will contain complex32.Zero. This parameter is passed uninitialized. /// </returns> public static bool TryToComplex32(this string value, out Complex32 result) { return(Complex32.TryParse(value, out result)); }
/// <summary> /// Converts the string representation of a complex number to single-precision complex number equivalent. /// A return value indicates whether the conversion succeeded or failed. /// </summary> /// <param name="value"> /// A string containing a complex number to convert. /// </param> /// <param name="formatProvider"> /// An <see cref="IFormatProvider"/> that supplies culture-specific formatting information about value. /// </param> /// <param name="result"> /// The parsed value. /// </param> /// <returns> /// If the conversion succeeds, the result will contain a complex number equivalent to value. /// Otherwise the result will contain Complex.Zero. This parameter is passed uninitialized. /// </returns> public static bool TryToComplex32(this string value, IFormatProvider formatProvider, out Complex32 result) { return(Complex32.TryParse(value, formatProvider, out result)); }
/// <summary> /// Creates a <c>Complex32</c> number based on a string. The string can be in the /// following formats (without the quotes): 'n', 'ni', 'n +/- ni', /// 'ni +/- n', 'n,n', 'n,ni,' '(n,n)', or '(n,ni)', where n is a double. /// </summary> /// <returns> /// A complex number containing the value specified by the given string. /// </returns> /// <param name="value"> /// the string to parse. /// </param> public static Complex32 ToComplex32(this string value) { return(Complex32.Parse(value)); }
/// <summary> /// Creates a <c>Complex32</c> number based on a string. The string can be in the /// following formats (without the quotes): 'n', 'ni', 'n +/- ni', /// 'ni +/- n', 'n,n', 'n,ni,' '(n,n)', or '(n,ni)', where n is a double. /// </summary> /// <returns> /// A complex number containing the value specified by the given string. /// </returns> /// <param name="value"> /// the string to parse. /// </param> /// <param name="formatProvider"> /// An <see cref="IFormatProvider"/> that supplies culture-specific /// formatting information. /// </param> public static Complex32 ToComplex32(this string value, IFormatProvider formatProvider) { return(Complex32.Parse(value, formatProvider)); }
/// <summary> /// Returns a Norm of the difference of two values of this type, which is /// appropriate for measuring how close together these two values are. /// </summary> public static double NormOfDifference(this Complex32 complex, Complex32 otherValue) { return((complex - otherValue).MagnitudeSquared); }
/// <summary> /// Gets the squared magnitude of the <c>Complex</c> number. /// </summary> /// <param name="complex">The <see cref="Complex32"/> number to perform this operation on.</param> /// <returns>The squared magnitude of the <c>Complex</c> number.</returns> public static double MagnitudeSquared(this Complex32 complex) { return((complex.Real * complex.Real) + (complex.Imaginary * complex.Imaginary)); }
/// <summary> /// Returns a Norm of a value of this type, which is appropriate for measuring how /// close this value is to zero. /// </summary> public static double Norm(this Complex32 complex) { return(complex.MagnitudeSquared); }
/// <summary> /// Compares two doubles and determines if they are equal to within the specified number of decimal places or not. If the numbers /// are very close to zero an absolute difference is compared, otherwise the relative difference is compared. /// </summary> /// <param name="a">The first value.</param> /// <param name="b">The second value.</param> /// <param name="decimalPlaces">The number of decimal places.</param> public static bool AlmostEqualRelative(this Complex32 a, Complex32 b, int decimalPlaces) { return(AlmostEqualNormRelative(a.Norm(), b.Norm(), a.NormOfDifference(b), decimalPlaces)); }
/// <summary> /// Checks whether two Compex numbers are almost equal. /// </summary> /// <param name="a">The first number</param> /// <param name="b">The second number</param> /// <returns>true if the two values differ by no more than 10 * 2^(-52); false otherwise.</returns> public static bool AlmostEqualRelative(this Complex32 a, Complex32 b) { return(AlmostEqualNormRelative(a.Norm(), b.Norm(), a.NormOfDifference(b), DefaultSingleAccuracy)); }
/// <summary> /// Compares two complex and determines if they are equal within /// the specified maximum error. /// </summary> /// <param name="a">The first value.</param> /// <param name="b">The second value.</param> /// <param name="maximumError">The accuracy required for being almost equal.</param> public static bool AlmostEqualRelative(this Complex32 a, Complex32 b, double maximumError) { return(AlmostEqualNormRelative(a.Norm(), b.Norm(), a.NormOfDifference(b), maximumError)); }
/// <summary> /// Compares two complex and determines if they are equal within /// the specified maximum error. /// </summary> /// <param name="a">The first value.</param> /// <param name="b">The second value.</param> /// <param name="maximumAbsoluteError">The accuracy required for being almost equal.</param> public static bool AlmostEqual(this Complex32 a, Complex32 b, double maximumAbsoluteError) { return(AlmostEqualNorm(a.Norm(), b.Norm(), a.NormOfDifference(b), maximumAbsoluteError)); }