/// <summary> /// Calculates the Ring as a % of Ips /// </summary> private void CalculateRing() { double positiveLeadingEdgeNoiseValue = 0; double negativeLeadingEdgeNoiseValue = 0; if (this.compensateForNoise) { // (R&D experiment) A flag indicating that the noise reduction should use the peak-to-peak found in the zero line bool useZeroLineStrategy = true; // (R&D experiment) A flag indicating that the noise reduction should use a bessel-filtered waveform to remove the noise bool useBesselFilterStrategy = false; if (useZeroLineStrategy) { Waveform zeroLineBeforeTriggerWaveform = this.AbsoluteWaveform.TrimEnd(this.compensateForNoiseCutoffTime); positiveLeadingEdgeNoiseValue = zeroLineBeforeTriggerWaveform.Maximum().Y; negativeLeadingEdgeNoiseValue = zeroLineBeforeTriggerWaveform.Minimum().Y; } else if (useBesselFilterStrategy) { Waveform rawWaveform = this.AbsoluteIpsPlusPeakCurrentDerivationOffsetWaveform; Waveform besselWaveform = BesselDigitalFilter.FilterWaveform(rawWaveform); for (int i = 0; i < rawWaveform.DataPoints.Count(); i++) { positiveLeadingEdgeNoiseValue = System.Math.Max(positiveLeadingEdgeNoiseValue, rawWaveform.DataPoints.ElementAt(i).Y - besselWaveform.DataPoints.ElementAt(i).Y); negativeLeadingEdgeNoiseValue = System.Math.Min(negativeLeadingEdgeNoiseValue, rawWaveform.DataPoints.ElementAt(i).Y - besselWaveform.DataPoints.ElementAt(i).Y); } } } // Find Ring1 Data point (max positive ring) this.Ring1PeakDataPoint = this.AbsoluteIpsPlusPeakCurrentDerivationOffsetWaveform.DataPointAtHBM0OhmJS001MaximumRing(this.AbsoluteIpsPolynomial, positiveLeadingEdgeNoiseValue, true); // Find Y-value of FifthDegreePolynomial at the time of Ring1 double positiveRingLeastSquaresFitValue = this.AbsoluteIpsPolynomial.Evaluate(this.Ring1PeakDataPoint.X); // Find the difference between Ring1 and Ring1FDP double positiveRingCurrentDifference = this.Ring1PeakDataPoint.Y - positiveRingLeastSquaresFitValue; // Find the absolute value of the difference between Ring1 and Ring1FDP double positiveRingCurrentDifferenceAbs = System.Math.Abs(positiveRingCurrentDifference); // Find Ring2 Data point (max negative ring) this.Ring2PeakDataPoint = this.AbsoluteIpsPlusPeakCurrentDerivationOffsetWaveform.DataPointAtHBM0OhmJS001MaximumRing(this.AbsoluteIpsPolynomial, negativeLeadingEdgeNoiseValue, false); // Output the Ring2 DataPoint (max negative ring) // Find Y-value of FifthDegreePolynomial at the time of Ring2 double negativeRingLeastSquaresFitValue = this.AbsoluteIpsPolynomial.Evaluate(this.Ring2PeakDataPoint.X); // Find the difference between Ring2 and Ring2FDP double negativeRingCurrentDifference = this.Ring2PeakDataPoint.Y - negativeRingLeastSquaresFitValue; // Find the absolute value of the difference between Ring2 and Ring2FDP double negativeRingCurrentDifferenceAbs = System.Math.Abs(negativeRingCurrentDifference); // Add the two differences to get Ir double totalRingCurrent = positiveRingCurrentDifferenceAbs + negativeRingCurrentDifferenceAbs; // Determine the ringing % compared to Ips this.TotalRingPercentValue = totalRingCurrent / System.Math.Abs(this.PeakCurrentValue); // Determine whether the ringing % is passing this.TotalRingIsPassing = this.TotalRingPercentValue <= this.TotalRingAllowedMaximum; }
/// <summary> /// Returns a new waveform that has been filtered using the Bessel algorithm. /// </summary> /// <param name="waveform">The original waveform.</param> /// <returns>The Bessel filtered waveform.</returns> internal static Waveform FilterWaveform(Waveform waveform) { // If there are not more than 3 data points, then no bessel filtering can occur if (waveform == null || waveform.DataPoints.Count() <= 3) { return(new Waveform(waveform.DataPoints)); } double samplingFrequency = waveform.SamplingFrequency(); int paddingCount = 3; List <DataPoint> inputDataPoints = new List <DataPoint>(waveform.DataPoints); // The filter should be started in the prepulse noise with y[0]=y[1]=y[2]=average of (x[0],x[1],x[2]). double paddingY = 0.0; for (int i = 0; i < paddingCount; i++) { paddingY += inputDataPoints[i].Y; } paddingY = paddingY / (double)paddingCount; for (int i = 0; i < paddingCount; i++) { inputDataPoints.Insert(0, new DataPoint(inputDataPoints[0].X, paddingY)); } List <DataPoint> outputDataPoints = new List <DataPoint>(inputDataPoints.Count); Tuple <double, double, double, double, int> coefficientSet = BesselDigitalFilter.GetCorrectSamplingCoefficientSet(samplingFrequency); double a1 = coefficientSet.Item1; double a3 = coefficientSet.Item1 * 3.0; double b = coefficientSet.Item2; double c = coefficientSet.Item3; double d = coefficientSet.Item4; int delay = coefficientSet.Item5; // Calculate how much each datapoint's X value must be shifted by double horizontalShift = (1 / samplingFrequency) * delay * -1; for (int n = 0; n < inputDataPoints.Count; n++) { DataPoint newDataPoint; if (n < 3) { newDataPoint = new DataPoint(inputDataPoints[n].X + horizontalShift, inputDataPoints[n].Y); } else { double y = (a1 * inputDataPoints[n - 3].Y) + (a3 * inputDataPoints[n - 2].Y) + (a3 * inputDataPoints[n - 1].Y) + (a1 * inputDataPoints[n - 0].Y) + (b * outputDataPoints[n - 3].Y) + (c * outputDataPoints[n - 2].Y) + (d * outputDataPoints[n - 1].Y); newDataPoint = new DataPoint(inputDataPoints[n].X + horizontalShift, y); } outputDataPoints.Add(newDataPoint); } // Remove the 3 data points that were padding to get the digital filter started outputDataPoints.RemoveRange(0, paddingCount); return(new Waveform(outputDataPoints)); }