/// <summary> /// Processes the spectra in matrix xMatrix according to the set-up options. /// </summary> /// <param name="xMatrix">The matrix of spectra. Each spectrum is a row of the matrix.</param> /// <param name="xMean">Will be filled with the spectral mean.</param> /// <param name="xScale">Will be filled with the inverse spectral variance.(Or with 1 if the user has not choosen this option).</param> public void Process(IMatrix <double> xMatrix, IVector <double> xMean, IVector <double> xScale) { // before processing, fill xScale with 1 VectorMath.FillWith(xScale, 1); GetPreprocessingMethod().Process(xMatrix, xMean, xScale, _regions); if (UseDetrending) { new DetrendingCorrection(_detrendingOrder).Process(xMatrix, xMean, xScale, _regions); } if (EnsembleMeanAfterProcessing || EnsembleScale) { new EnsembleMeanAndScaleCorrection(EnsembleMeanAfterProcessing, EnsembleScale).Process(xMatrix, xMean, xScale, _regions); } }
/// <summary> /// Fits data provided as xcolumn and ycolumn with a polynomial base. Here special measures are taken (scaling of the x-variable) in order /// to keep the precision high. /// </summary> /// <param name="order">The order of the fit (1:linear, 2:quadratic, etc.)</param> /// <param name="xValues">The array of x-values. The values of the array are destroyed (altered) during the evaluation!</param> /// <param name="yValues">The array of y-values.</param> /// <param name="errorValues">The column of errorValues. If null, errorValues are set to 1 for each element.</param> /// <param name="count">Number of values to use (array[0] ... array[count-1].</param> /// <returns>The fit.</returns> public static LinearFitBySvd FitPolymomialDestructive(int order, double[] xValues, double[] yValues, double[] errorValues, int count) { if (!(xValues != null)) { throw new ArgumentNullException(nameof(xValues)); } if (!(yValues != null)) { throw new ArgumentNullException(nameof(yValues)); } if (!(count > 0)) { throw new ArgumentOutOfRangeException(nameof(count), "must be >0"); } if (!(count <= xValues.Length)) { throw new ArgumentOutOfRangeException(nameof(count), "exceeds capacity of array " + nameof(xValues)); } if (!(count <= yValues.Length)) { throw new ArgumentOutOfRangeException(nameof(count), "exceeds capacity of array " + nameof(yValues)); } if (null != errorValues && !(count <= errorValues.Length)) { throw new ArgumentOutOfRangeException(nameof(count), "exceeds capacity of array " + nameof(errorValues)); } double[] xarr = xValues; double[] yarr = yValues; double[] earr = errorValues; if (null == earr) { earr = new double[count]; VectorMath.FillWith(earr, 1); } int numberOfDataPoints = count; // we scale the x-values in order to keep the Condition number reasonable var xmin = Altaxo.Calc.LinearAlgebra.VectorMath.Min(xarr, 0, numberOfDataPoints); var xmax = Altaxo.Calc.LinearAlgebra.VectorMath.Max(xarr, 0, numberOfDataPoints); double xscale = Math.Max(-xmin, xmax); double xinvscale = 1 / xscale; if (0 == xscale) { xscale = xinvscale = 1; } for (int i = 0; i < numberOfDataPoints; ++i) { xarr[i] *= xinvscale; } var fit = new LinearFitBySvd( xarr, yarr, earr, numberOfDataPoints, order + 1, new FunctionBaseEvaluator(GetPolynomialFunctionBase(order)), 1E-15); // rescale parameter of fit in order to account for rescaled x variable for (int i = 0; i <= order; ++i) { fit._parameter[i] *= RMath.Pow(xinvscale, i); for (int j = 0; j <= order; ++j) { fit._covarianceMatrix[i][j] *= RMath.Pow(xinvscale, i + j); } } return(fit); }
private void EvaluateInternally(double?tout, out double t_result, double[] result) { if (_initializationState == InitializationState.NotInitialized) // not initialized so far { _initializationState = InitializationState.InitialValueReturned; if (null == tout) { last_tout = t_result = currstate._tn; currstate._zn.CopyColumn(0, result); return; } } else if (_initializationState == InitializationState.Initialized) { // we have to clone some of the code from below to here // this is no good style, but a goto statement with a jump inside another code block will not work here. if (tout.HasValue) { // Output data, but only if (i) we have requested a certain time point, // and ii) as long as we can interpolate this point from the previous point and the current point if (currstate._tn <= tout.Value && tout.Value <= currstate._tn + currstate._dt) { // VectorMath.Lerp(tout.Value, currstate.tn, xout, currstate.tn + currstate.dt, currstate.xn, result); currstate.EvaluateYAtTime(tout.Value, result); last_tout = t_result = tout.Value; return; } } else { if (currstate._tn == last_tout) { last_tout = t_result = currstate._tn + currstate._dt; VectorMath.Copy(currstate._xn, result); return; } } VectorMath.Copy(currstate._xn, xout); // save x of this step currstate._tn = currstate._tn + currstate._dt; if (opts.MaxStep < double.MaxValue) { r = Math.Min(r, opts.MaxStep / currstate._dt); } if (opts.MinStep > 0) { r = Math.Max(r, opts.MinStep / currstate._dt); } r = Math.Min(r, opts.MaxScale); r = Math.Max(r, opts.MinScale); currstate._dt = currstate._dt * r; currstate.Rescale(r); } _initializationState = InitializationState.Initialized; //Can produce any number of solution points while (true) { // Reset fail flag isIterationFailed = false; // Predictor step _zn_saved.CopyFrom(currstate._zn); currstate.ZNew(); VectorMath.FillWith(currstate._en, 0); // TODO find out if this statement is neccessary currstate._zn.CopyColumn(0, currstate._xn); // Corrector step currstate.PredictorCorrectorScheme(ref isIterationFailed, f, _denseJacobianEvaluation, _sparseJacobianEvaluation, opts); if (isIterationFailed) // If iterations are not finished - bad convergence { currstate._zn.CopyFrom(_zn_saved); // copy saved state back currstate._nsuccess = 0; currstate.DivideStepBy2(); } else // Iterations finished, i.e. did not fail { r = Math.Min(1.1d, Math.Max(0.2d, currstate._rFactor)); if (currstate._delta >= 1.0d) { if (opts.MaxStep < double.MaxValue) { r = Math.Min(r, opts.MaxStep / currstate._dt); } if (opts.MinStep > 0) { r = Math.Max(r, opts.MinStep / currstate._dt); } r = Math.Min(r, opts.MaxScale); r = Math.Max(r, opts.MinScale); currstate._dt = currstate._dt * r; // Decrease step currstate.Rescale(r); } else // Iteration finished successfully { // Output data if (tout.HasValue) { if (currstate._tn <= tout.Value && tout.Value <= currstate._tn + currstate._dt) { // VectorMath.Lerp(tout.Value, currstate.tn, xout, currstate.tn + currstate.dt, currstate.xn, result); currstate.EvaluateYAtTime(tout.Value, result); t_result = tout.Value; return; } } else { VectorMath.Copy(currstate._xn, result); t_result = last_tout = currstate._tn + currstate._dt; return; } VectorMath.Copy(currstate._xn, xout); currstate._tn = currstate._tn + currstate._dt; if (opts.MaxStep < double.MaxValue) { r = Math.Min(r, opts.MaxStep / currstate._dt); } if (opts.MinStep > 0) { r = Math.Max(r, opts.MinStep / currstate._dt); } r = Math.Min(r, opts.MaxScale); r = Math.Max(r, opts.MinScale); currstate._dt = currstate._dt * r; currstate.Rescale(r); } } } }