/// <summary> /// Calculates the Undershoot related values /// </summary> /// <param name="undershootMaxTimeFWHMMultiplier">(Optional) The multiplier of the FWHM time to determine how long after the peak current time to search for undershoot (Default: 2.5x)</param> private void CalculateUndershoot(double undershootMaxTimeFWHMMultiplier = 2.5) { if (undershootMaxTimeFWHMMultiplier <= 0) { throw new ArgumentOutOfRangeException("The Undershoot Max Time multiplier cannot be less than or equal to 0"); } // Determine how much time after the max data point of the waveform to keep for Undershoot double timeForUndershootDetectionAfterMaxTime = this.FullWidthHalfMaxValue * undershootMaxTimeFWHMMultiplier; // Add the undershoot allowed time to the max data point time double endTimeForUndershootDetection = this.PeakCurrentDataPoint.X + timeForUndershootDetectionAfterMaxTime; // Trim the waveform, removing everything before the max peak Waveform absoluteWaveformAfterPeakCurrentTime = this.AbsoluteWaveform.TrimStart(this.PeakCurrentDataPoint.X); // Trim the end of the waveform from the max time until 2.5x the FWHM time Waveform absoluteUndershootApplicableWaveform = absoluteWaveformAfterPeakCurrentTime.TrimEnd(endTimeForUndershootDetection); // Find the (absolute) undershoot data point of the absolute Current waveform after the max time DataPoint absoluteUndershootDataPoint = absoluteUndershootApplicableWaveform.Minimum(); // Look up what the undershoot max percent can be (it is a negative value) this.UndershootAllowedMaximumPercent = CDMJS002WaveformCharacteristics.UndershootMaxPercent(this.SignedVoltage, this.IsLargeTarget, this.OscilloscopeIsHighBandwidth); // Calculate what the maximum undershoot value can be (it is a negative number since we are referring to undershoot) this.UndershootAllowedMaximumValue = this.PeakCurrentValue * this.UndershootAllowedMaximumPercent; // Convert the absolute undershoot value to the signed value double absoluteUndershootValue = absoluteUndershootDataPoint.Y; // If the absolute undershoot is greater than zero, set it to zero. Otherwise set it to the signed value if (absoluteUndershootValue > 0) { this.UndershootValue = 0; } else { this.UndershootValue = absoluteUndershootValue.InvertValueIfNegativePolarity(this.WaveformIsPositivePolarity); } // Determine if the Undershoot is passing if (this.WaveformIsPositivePolarity) { this.UndershootIsPassing = this.UndershootValue >= this.UndershootAllowedMaximumValue; } else { this.UndershootIsPassing = this.UndershootValue <= this.UndershootAllowedMaximumValue; } // Create the undershoot signed Data Point this.UndershootDataPoint = absoluteUndershootDataPoint.InvertYValueIfNegativePolarity(this.WaveformIsPositivePolarity); }
/// <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; }