/// <summary> /// Calculates the Decay Time related values /// </summary> private void CalculateDecayTime() { // The percentage of the Peak Current to be the end of the decay time (1/e) double decayTimeEndPercentOfIps = 1.0 / System.Math.E; // Trim the waveform, removing everything before the max peak Waveform absoluteWaveformAfterPeakCurrentTime = this.AbsoluteWaveform.TrimStart(this.PeakCurrentDataPoint.X); // Find the start/stop times for the noise-reducing exponential fit waveform DataPoint?expFitStartDataPoint = absoluteWaveformAfterPeakCurrentTime.DataPointAtYThreshold(0.5 * System.Math.Abs(this.PeakCurrentValue), true); if (expFitStartDataPoint.HasValue) { double expFitStartTimeThreshold = expFitStartDataPoint.Value.X; DataPoint?expFitEndDataPoint = absoluteWaveformAfterPeakCurrentTime.DataPointAtYThreshold(0.3 * System.Math.Abs(this.PeakCurrentValue), true); // The waveform was truncated before the lower end of the decaying region, // however there might be enough data to calculate by using the last data point instead. if (!expFitEndDataPoint.HasValue) { expFitEndDataPoint = absoluteWaveformAfterPeakCurrentTime.DataPoints.Last(); } double expFitEndTimeThreshold = expFitEndDataPoint.Value.X; // Gate the waveform to just the area for the noise-reducing exponential fit waveform Waveform absoluteWaveformDecayingRegion = this.AbsoluteWaveform.Gates(expFitStartTimeThreshold, expFitEndTimeThreshold); if (absoluteWaveformDecayingRegion.DataPoints.Any()) { // Find the exponential fit constants of the waveform from 0.5 * Ips to 0.3 * Ips to eliminate noise Tuple <double, double> expFitAbsoluteWaveformDecayingRegionConstants = absoluteWaveformDecayingRegion.ExponentialFit(); // Create time values that go out far enough to ensure the decay time end threshold can be found List <double> timeValues = (from dp in absoluteWaveformDecayingRegion.DataPoints select dp.X).ToList(); double samplingTime = absoluteWaveformDecayingRegion.SamplingTime(); while (timeValues.Last() < 0.000000800 && samplingTime > 0) { timeValues.Add(timeValues.Last() + samplingTime); } // Create the exponential fit equivalent waveform which has noise eliminated Waveform expFitAbsoluteWaveformDecayingRegion = WaveformExtensions.CreateExponentialFitWaveform( expFitAbsoluteWaveformDecayingRegionConstants.Item1, expFitAbsoluteWaveformDecayingRegionConstants.Item2, timeValues); // Calculate what the decay time end threshold is (1/e % of Ips) double decayTimeEndThreshold = System.Math.Abs(this.PeakCurrentValue) * decayTimeEndPercentOfIps; // Find the first (interpolated) data point that is at 1/e % of Ips value (of the absolute value waveform) DataPoint?decayTimeEndDataPointAbsolute = expFitAbsoluteWaveformDecayingRegion.DataPointAtYThreshold(decayTimeEndThreshold, true); if (decayTimeEndDataPointAbsolute.HasValue) { // Convert the Decay Time end DataPoint to the signed value this.DecayTimeEndDataPoint = decayTimeEndDataPointAbsolute.Value.InvertYValueIfNegativePolarity(this.WaveformIsPositivePolarity); // Calculate the Decay Time this.DecayTimeValue = this.DecayTimeEndDataPoint.X - this.PeakCurrentDataPoint.X; // Determine if the Decay Time is passing this.DecayTimeIsPassing = DoubleRangeExtensions.BetweenInclusive(this.DecayTimeAllowedMinimum, this.DecayTimeAllowedMaximum, this.DecayTimeValue); } else { // The derived exponential fit waveform didn't go out to a far enough time to capture the 1/e time. } } else { // Could not find any data points in the decay time window. Likely due to a malformed waveform. } } else { // Since the waveform was truncated before even the start of the window to calculate the decaying region, the decay time cannot be calculated. } }