private void smoothOneSubSeries(double[] weights, double[] rawData, double[] smoothedData) { int cycleLength = rawData.Length; // Smooth the cyclic sub-series with LOESS and then extrapolate one place beyond each end. this.fLoessSmootherFactory.Data = rawData; this.fLoessSmootherFactory.ExternalWeights = weights; LoessSmoother smoother = this.fLoessSmootherFactory.build(); //Copy, shifting by 1 to leave room for the extrapolated point at the beginning. // System.arraycopy(smoother.smooth(), 0, smoothedData, this.fNumPeriodsToExtrapolateBackward, cycleLength); var ss = smoother.smooth(); for (int i = 0; i < cycleLength; i++) { smoothedData[this.fNumPeriodsToExtrapolateBackward + i] = ss[i]; } LoessInterpolator interpolator = smoother.Interpolator; // Extrapolate from the leftmost "width" points to the "-1" position int left = 0; int right = (left + (this.fWidth - 1)); right = Math.Min(right, (cycleLength - 1)); int leftValue = this.fNumPeriodsToExtrapolateBackward; for (int i = 1; (i <= this.fNumPeriodsToExtrapolateBackward); i++) { double ys = interpolator.smoothOnePoint((i * -1), left, right); // smoothedData[(leftValue - i)] = ys == 0 ? smoothedData[leftValue] : ys; } // Extrapolate from the rightmost "width" points to the "length" position (one past the array end). right = (cycleLength - 1); left = ((right - this.fWidth) + 1); left = Math.Max(0, left); int rightValue = (this.fNumPeriodsToExtrapolateBackward + right); for (int i = 1; (i <= this.fNumPeriodsToExtrapolateForward); i++) { Double ys = interpolator.smoothOnePoint((right + i), left, right); //smoothedData[(rightValue + i)] = (ys == null); smoothedData[rightValue + i] = ys == 0 ? smoothedData[rightValue] : ys; } }
public LoessSmoother(int width, int jump, int degree, double[] data, double[] externalWeights) { InterpolatorBuilder b = new InterpolatorBuilder(); b.Width = width; b.Degree = degree; b.ExternalWeights = externalWeights; this.fInterpolator = b.interpolate(data); this.fData = data; this.fJump = Math.Min(jump, (data.Length - 1)); this.fWidth = width; this.fSmoothed = new double[data.Length]; }