/// <summary> /// Processes the spectra in matrix xMatrix for prediction. /// </summary> /// <param name="xMatrix">The matrix of spectra. Each spectrum is a row of the matrix.</param> /// <param name="xMean">Not used.</param> /// <param name="xScale">Not used.</param> /// <param name="regionstart">Starting index of the region to process.</param> /// <param name="regionend">End index of the region to process.</param> public void ProcessForPrediction(IMatrix xMatrix, IROVector xMean, IROVector xScale, int regionstart, int regionend) { int regionlength = regionend - regionstart; for(int n=0;n<xMatrix.Rows;n++) { // 1.) Get the mean response of a spectrum double mean = 0; for(int i=regionstart;i<regionend;i++) mean += xMatrix[n,i]; mean /= regionlength; // 2.) Subtract mean response for(int i=regionstart;i<regionend;i++) xMatrix[n,i] -= mean; // 3.) Get the standard deviation double dev = 0; for(int i=regionstart;i<regionend;i++) dev += xMatrix[n,i]*xMatrix[n,i]; dev = Math.Sqrt(dev/(regionlength-1)); // 4. Divide by standard deviation for(int i=regionstart;i<regionend;i++) xMatrix[n,i] /= dev; } }
/// <summary> /// Copies elements of a source vector to a destination vector. /// </summary> /// <param name="src">The source vector.</param> /// <param name="srcstart">First element of the source vector to copy.</param> /// <param name="dest">The destination vector.</param> /// <param name="deststart">First element of the destination vector to copy to.</param> /// <param name="count">Number of elements to copy.</param> public static void Copy(IROVector src, int srcstart, IVector dest, int deststart, int count) { for (int i = 0; i < count; i++) { dest[i + deststart] = src[i + srcstart]; } }
/// <summary> /// Constructor. Takes an read only vector and evaluates the spaces between /// the vector elements. /// </summary> /// <param name="vec">The vector.</param> public VectorSpacingEvaluator(IROVector vec) { int lower = vec.LowerBound; int upper = vec.UpperBound; _numtotalsteps = upper-lower; for(int i=lower;i<upper;i++) { double step = vec[i+1]-vec[i]; if(!double.IsNaN(step)) { _numvalidsteps++; if(step>_stepmax) _stepmax = step; if(step<_stepmin) _stepmin = step; _sumsteps += step; } } // if all steps are valid, we calculate sumsteps from the boundaries // to enhance the accuracy. if(_numvalidsteps>0 && _numtotalsteps == _numvalidsteps) _sumsteps = vec[upper] - vec[lower]; }
/// <summary> /// Constructor of a bivariate linear spline. The vectors and the data matrix are not cloned, so make sure that they don't change during usage of this instance. /// </summary> /// <param name="x">Vector of x values corresponding to the rows of the data matrix. Must be strongly increasing or decreasing.</param> /// <param name="y">Vector of y values corresponding to the columns of the data matrix. Must be strongly increasing or decreasing.</param> /// <param name="datamatrix"></param> public BivariateLinearSpline(IROVector x, IROVector y, IROMatrix datamatrix) { _x = x; _y = y; _vmatrix = datamatrix; // check the arguments if (_x.Length < 2) throw new ArgumentException("x.Length is less or equal 1 (you can use univariate interpolation instead)"); if (_y.Length < 2) throw new ArgumentException("y.Length is less or equal 1 (you can use univariate interpolation instead)"); if (_x.Length != _vmatrix.Rows) throw new ArgumentException("Length of vector x is not equal to datamatrix.Rows"); if (_y.Length != _vmatrix.Columns) throw new ArgumentException("Length of vector y is not equal to datamatrix.Columns"); if (!VectorMath.IsStrictlyIncreasingOrDecreasing(_x, out _isXDecreasing)) throw new ArgumentException("Vector x is not strictly increasing or decreasing"); if (!VectorMath.IsStrictlyIncreasingOrDecreasing(_y, out _isYDecreasing)) throw new ArgumentException("Vector y is not strictly increasing or decreasing"); _lastIX = 0; _lastIY = 0; }
/// <summary> /// Processes the spectra in matrix xMatrix for prediction. /// </summary> /// <param name="xMatrix">The matrix of spectra. Each spectrum is a row of the matrix.</param> /// <param name="xMean">Not used.</param> /// <param name="xScale">Not used.</param> /// <param name="regions">Vector of spectal regions. Each element is the index of the start of a new region.</param> public override void ProcessForPrediction(IMatrix xMatrix, IROVector xMean, IROVector xScale, int[] regions) { for(int i=0;i<=regions.Length;i++) { ProcessForPrediction(xMatrix,xMean,xScale,RegionStart(i,regions),RegionEnd(i,regions,xMatrix.Columns)); } }
/// <summary> /// Constructor. Takes an read only vector and evaluates the spaces between /// the vector elements. /// </summary> /// <param name="vec">The vector.</param> public VectorSpacingEvaluator(IROVector vec) { int lower = vec.LowerBound; int upper = vec.UpperBound; _numtotalsteps = upper - lower; for (int i = lower; i < upper; i++) { double step = vec[i + 1] - vec[i]; if (!double.IsNaN(step)) { _numvalidsteps++; if (step > _stepmax) { _stepmax = step; } if (step < _stepmin) { _stepmin = step; } _sumsteps += step; } } // if all steps are valid, we calculate sumsteps from the boundaries // to enhance the accuracy. if (_numvalidsteps > 0 && _numtotalsteps == _numvalidsteps) { _sumsteps = vec[upper] - vec[lower]; } }
public static void CalculatePRESS( IROMatrix <double> yLoads, IROMatrix <double> xScores, int numberOfFactors, out IROVector <double> press) { int numMeasurements = yLoads.RowCount; IExtensibleVector <double> PRESS = VectorMath.CreateExtensibleVector <double>(numberOfFactors + 1); var UtY = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(yLoads.RowCount, yLoads.ColumnCount); var predictedY = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(yLoads.RowCount, yLoads.ColumnCount); press = PRESS; MatrixMath.MultiplyFirstTransposed(xScores, yLoads, UtY); // now calculate PRESS by predicting the y // using yp = U (w*(1/w)) U' y // of course w*1/w is the identity matrix, but we use only the first factors, so using a cutted identity matrix // we precalculate the last term U'y = UtY // and multiplying with one row of U in every factor step, summing up the predictedY PRESS[0] = MatrixMath.SumOfSquares(yLoads); for (int nf = 0; nf < numberOfFactors; nf++) { for (int cn = 0; cn < yLoads.ColumnCount; cn++) { for (int k = 0; k < yLoads.RowCount; k++) { predictedY[k, cn] += xScores[k, nf] * UtY[nf, cn]; } } PRESS[nf + 1] = MatrixMath.SumOfSquaredDifferences(yLoads, predictedY); } }
/// <summary> /// Constructor. Takes an read only vector and evaluates the spaces between /// the vector elements. /// </summary> /// <param name="vec">The vector.</param> public VectorSpacingEvaluator(IROVector vec) { _numtotalsteps = vec.Length - 1; for (int i = 0; i < _numtotalsteps; i++) { double step = vec[i + 1] - vec[i]; if (!double.IsNaN(step)) { _numvalidsteps++; if (step > _stepmax) _stepmax = step; if (step < _stepmin) _stepmin = step; _sumsteps += step; } } // if all steps are valid, we calculate sumsteps from the boundaries // to enhance the accuracy. if (_numvalidsteps > 0 && _numtotalsteps == _numvalidsteps) _sumsteps = vec[_numtotalsteps] - vec[0]; }
/// <summary> /// Extrapolates y-values until the end of the vector by using linear prediction. /// </summary> /// <param name="yTraining">Input vector of y values used to calculated the prediction coefficients. /// <param name="yPredValues">Input/output vector of y values to extrapolate. /// The fields beginning from 0 to <c>len-1</c> must contain valid values used for initialization of the extrapolation. /// At the end of the procedure, the upper end (<c>len</c> .. <c>yPredValues.Count-1</c> contain the /// extrapolated data.</param> /// </param> /// <param name="len">Number of valid input data points for extrapolation (not for the training data!).</param> /// <param name="yOrder">Number of history samples used for prediction. Must be greater or equal to 1.</param> public static DynamicParameterEstimation Extrapolate(IROVector yTraining, IVector yPredValues, int len, int yOrder) { if (yOrder < 1) { throw new ArgumentException("yOrder must be at least 1"); } if (yOrder >= (yTraining.Length - yOrder)) { throw new ArgumentException("Not enough data points for this degree (yOrder must be less than yTraining.Length/2)."); } DynamicParameterEstimation est = new DynamicParameterEstimation(); est.Calculate(null, yTraining, 0, yOrder, 0); // now calculate the extrapolation data for (int i = len; i < yPredValues.Length; i++) { double sum = 0; for (int j = 0; j < yOrder; j++) { sum += yPredValues[i - j - 1] * est._parameter[j]; } yPredValues[i] = sum; } return(est); }
public static void GetPredictionScoreMatrix( IROMatrix xLoads, IROMatrix yLoads, IROMatrix xScores, IROVector crossProduct, int numberOfFactors, IMatrix predictionScores) { int numX = xLoads.Columns; int numY = yLoads.Columns; int numM = yLoads.Rows; MatrixMath.BEMatrix UtY = new MatrixMath.BEMatrix(xScores.Columns, yLoads.Columns); MatrixMath.MultiplyFirstTransposed(xScores, yLoads, UtY); MatrixMath.ZeroMatrix(predictionScores); for (int nf = 0; nf < numberOfFactors; nf++) { double scale = 1 / crossProduct[nf]; for (int cn = 0; cn < numY; cn++) { for (int k = 0; k < numX; k++) { predictionScores[k, cn] += scale * xLoads[nf, k] * UtY[nf, cn]; } } } }
public static void GetSpectralResiduals( IROMatrix matrixX, IROMatrix xLoads, IROMatrix yLoads, IROMatrix xScores, IROVector crossProduct, int numberOfFactors, IMatrix spectralResiduals) { int numX = xLoads.Columns; int numY = yLoads.Columns; int numM = yLoads.Rows; MatrixMath.BEMatrix reconstructedSpectra = new MatrixMath.BEMatrix(matrixX.Rows, matrixX.Columns); MatrixMath.ZeroMatrix(reconstructedSpectra); for (int nf = 0; nf < numberOfFactors; nf++) { double scale = crossProduct[nf]; for (int m = 0; m < numM; m++) { for (int k = 0; k < numX; k++) { reconstructedSpectra[m, k] += scale * xScores[m, nf] * xLoads[nf, k]; } } } for (int m = 0; m < numM; m++) { spectralResiduals[m, 0] = MatrixMath.SumOfSquaredDifferences( MatrixMath.ToROSubMatrix(matrixX, m, 0, 1, matrixX.Columns), MatrixMath.ToROSubMatrix(reconstructedSpectra, m, 0, 1, matrixX.Columns)); } }
public static void SetContentFromMatrix(DataTable destinationTable, IROMatrix matrix, string columnBaseName, IROVector rowHeaderColumn, string rowHeaderColumnName, IROVector colHeaderColumn, string colHeaderColumnName) { var c = new MatrixToDataTableConverter(matrix, destinationTable); c.ColumnBaseName = columnBaseName; c.AddMatrixColumnHeaderData(rowHeaderColumn, rowHeaderColumnName); c.AddMatrixColumnHeaderData(colHeaderColumn, colHeaderColumnName); c.Execute(); }
/// <summary> /// Copies the source vector to the destination vector. Both vectors must have the same length. /// </summary> /// <param name="src">The source vector.</param> /// <param name="dest">The destination vector.</param> public static void Copy(IROVector src, IVector dest) { if (src.Length != dest.Length) { throw new ArgumentException("src and destination vector have unequal length!"); } Copy(src, src.LowerBound, dest, dest.LowerBound, src.Length); }
private DoubleVector Pivot(IROVector B) { DoubleVector ret = new DoubleVector(B.Length); for (int i = 0; i < pivots.Length; i++) { ret.data[i] = B[pivots[i]]; } return(ret); }
/// <summary> /// Resizes the vector to the same boundaries as the provided vector and copies the elements from it. /// </summary> /// <param name="a">The vector to copy the data from.</param> public void CopyFrom(IROVector a) { Resize(a.LowerBound, a.UpperBound); int lo = a.LowerBound; for (int i = 0; i < data.Length; ++i) { data[i] = a[i + lo]; } }
/// <summary> /// This applies the set-up filter to an array of numbers. The left and right side is special treated by /// applying Savitzky-Golay with appropriate adjusted left and right number of points. /// </summary> /// <param name="array">The array of numbers to filter.</param> /// <param name="result">The resulting array. Must not be identical to the input array!</param> public void Apply(IROVector array, IVector result) { int filterPoints = _middle.Length; int sidePoints = (filterPoints - 1) / 2; if (object.ReferenceEquals(array, result)) { throw new ArgumentException("Argument array and result must not be identical!"); } if (array.Length < filterPoints) { throw new ArgumentException("Input array must have same or greater length than the filter!"); } // left side for (int n = 0; n < sidePoints; n++) { double[] filter = _left[n]; double sum = 0; for (int i = 0; i < filterPoints; i++) { sum += array[i] * filter[i]; } result[n] = sum; } // middle int middleend = array.Length - filterPoints; for (int n = 0; n <= middleend; n++) { double sum = 0; for (int i = 0; i < filterPoints; i++) { sum += array[n + i] * _middle[i]; } result[n + sidePoints] = sum; } // right side int arrayOffset = array.Length - filterPoints; int resultOffset = array.Length - 1; for (int n = 0; n < sidePoints; n++) { double[] filter = _right[n]; double sum = 0; for (int i = 0; i < filterPoints; i++) { sum += array[arrayOffset + i] * filter[i]; } result[resultOffset - n] = sum; } }
/// <summary> /// Processes the spectra in matrix xMatrix for prediction. /// </summary> /// <param name="xMatrix">The matrix of spectra. Each spectrum is a row of the matrix.</param> /// <param name="xMean">Must be supplied, and will be subtracted from all spectra (if option set).</param> /// <param name="xScale">Must be supplied, and will be multiplied to all spectra (if option set).</param> /// <param name="regions">Vector of spectal regions. Each element is the index of the start of a new region.</param> public override void ProcessForPrediction(IMatrix xMatrix, IROVector xMean, IROVector xScale, int[] regions) { if(_ensembleMean) { MatrixMath.SubtractRow(xMatrix, xMean,xMatrix); } if(_ensembleScale) { MatrixMath.MultiplyRow(xMatrix,xScale,xMatrix); } }
/// <summary> /// Processes the spectra in matrix xMatrix for prediction. /// </summary> /// <param name="xMatrix">The matrix of spectra. Each spectrum is a row of the matrix.</param> /// <param name="xMean">Not used.</param> /// <param name="xScale">Not used.</param> /// <param name="regionstart">Starting index of the region.</param> /// <param name="regionend">End index of the region (one behind the last region element).</param> public void Process(IMatrix xMatrix, IROVector xMean, IROVector xScale, int regionstart, int regionend) { int regionlength = regionend-regionstart; int currentorder = Math.Min(_order,regionlength); switch(currentorder) { case 0: // Detrending of order 0 - subtract mean for(int n=0;n<xMatrix.Rows;n++) { // 1.) Get the mean response of a spectrum double mean = 0; for(int i=regionstart;i<regionend;i++) mean += xMatrix[n,i]; mean /= regionlength; for(int i=regionstart;i<regionend;i++) xMatrix[n,i] -= mean; } break; case 1: // Detrending of order 1 - subtract linear regression line for(int n=0;n<xMatrix.Rows;n++) { QuickLinearRegression regression = new QuickLinearRegression(); for(int i=regionstart;i<regionend;i++) regression.Add(i,xMatrix[n,i]); double a0 = regression.GetA0(); double a1 = regression.GetA1(); for(int i=regionstart;i<regionend;i++) xMatrix[n,i] -= (a1*i+a0); } break; case 2: // Detrending of order 2 - subtract quadratic regression line for(int n=0;n<xMatrix.Rows;n++) { QuickQuadraticRegression regression = new QuickQuadraticRegression(); for(int i=regionstart;i<regionend;i++) regression.Add(i,xMatrix[n,i]); double a0 = regression.GetA0(); double a1 = regression.GetA1(); double a2 = regression.GetA2(); for(int i=regionstart;i<regionend;i++) xMatrix[n,i] -= (((a2*i)+a1)*i+a0); } break; default: throw new NotImplementedException(string.Format("Detrending of order {0} is not implemented yet",_order)); } }
public static void Interpolation(WorksheetController ctrl) { if (ctrl.SelectedDataColumns.Count == 0) { return; } object paramobject = new InterpolationParameters(); if (!Current.Gui.ShowDialog(ref paramobject, "Interpolation")) { return; } InterpolationParameters parameters = (InterpolationParameters)paramobject; Altaxo.Data.DataColumn yCol = ctrl.Doc.DataColumns[ctrl.SelectedDataColumns[0]]; Altaxo.Data.DataColumn xCol = ctrl.Doc.DataColumns.FindXColumnOf(yCol); if (!(yCol is INumericColumn)) { Current.Gui.ErrorMessageBox("The selected column is not numeric!"); return; } if (!(xCol is INumericColumn)) { Current.Gui.ErrorMessageBox("The x-column of the selected column is not numeric!"); return; } int rows = Math.Min(xCol.Count, yCol.Count); IROVector yVec = DataColumnWrapper.ToROVector((INumericColumn)yCol, rows); IROVector xVec = DataColumnWrapper.ToROVector((INumericColumn)xCol, rows); parameters.InterpolationInstance.Interpolate(xVec, yVec); DoubleColumn xRes = new DoubleColumn(); DoubleColumn yRes = new DoubleColumn(); for (int i = 0; i < parameters.NumberOfPoints; i++) { double r = i / (double)(parameters.NumberOfPoints - 1); double x = parameters.XOrg * (1 - r) + parameters.XEnd * (r); double y = ((IInterpolationFunction)parameters.InterpolationInstance).GetYOfX(x); xRes[i] = x; yRes[i] = y; } int newgroup = ctrl.DataTable.DataColumns.GetUnusedColumnGroupNumber(); ctrl.DataTable.DataColumns.Add(xRes, xCol.Name + ".I", ColumnKind.X, newgroup); ctrl.DataTable.DataColumns.Add(yRes, yCol.Name + ".I", ColumnKind.V, newgroup); }
///// <summary> ///// Returns the sum of the elements in the vector. ///// </summary> ///// <param name="xarray">The vector.</param> ///// <returns>The sum of all elements in xarray.</returns> public static double Sum(this IROVector xarray) { double sum = 0; for (int i = 0; i < xarray.Length; i++) { sum += xarray[i]; } return(sum); }
/// <summary> /// Processes the spectra in matrix xMatrix for prediction. /// </summary> /// <param name="xMatrix">The matrix of spectra. Each spectrum is a row of the matrix.</param> /// <param name="xMean">Not used.</param> /// <param name="xScale">Not used.</param> /// <param name="regionstart">Starting index of the region to process.</param> /// <param name="regionend">End index of the region to process.</param> public void ProcessForPrediction(IMatrix xMatrix, IROVector xMean, IROVector xScale, int regionstart, int regionend) { int regionlength = regionend - regionstart; IVector helpervector = VectorMath.ToVector(new double[regionlength]); for(int n=0;n<xMatrix.Rows;n++) { IVector vector = MatrixMath.RowToVector(xMatrix,n,regionstart,regionlength); _filter.Apply(vector,helpervector); VectorMath.Copy(helpervector,vector); } }
/// <summary> /// Returns the maximum of the elements in xarray. /// </summary> /// <param name="xarray">The array to search for maximum element.</param> /// <returns>Maximum element of xarray. Returns NaN if the array is empty.</returns> public static double Max(IROVector xarray) { double max = xarray.Length == 0 ? double.NaN : xarray[xarray.LowerBound]; int last = xarray.UpperBound; for (int i = xarray.LowerBound + 1; i <= last; i++) { max = Math.Max(max, xarray[i]); } return(max); }
void WriteVector(string name, IROVector col, int numberOfData) { _writer.WriteStartElement(name); for (int i = 0; i < numberOfData; i++) { _writer.WriteElementString("e", System.Xml.XmlConvert.ToString(col[i])); } _writer.WriteEndElement(); // name }
public void Append(IROVector <T> vector) { if (_length + vector.Length >= _arr.Length) { Redim((int)(32 + 1.3 * (_length + vector.Length))); } for (int i = 0; i < vector.Length; i++) { _arr[i + _length] = vector[i]; } _length += vector.Length; }
///<summary>Solves a system on linear equations, AX=B, where A is the factored matrixed.</summary> ///<param name="B">RHS side of the system.</param> ///<returns>the solution vector, X.</returns> ///<exception cref="ArgumentNullException">B is null.</exception> ///<exception cref="NotPositiveDefiniteException">A is not positive definite.</exception> ///<exception cref="ArgumentException">The number of rows of A and the length of B must be the same.</exception> public DoubleVector Solve(IROVector B) { if (B == null) { throw new System.ArgumentNullException("B cannot be null."); } Compute(); if (!ispd) { throw new NotPositiveDefiniteException(); } else { if (B.Length != order) { throw new System.ArgumentException("The length of B must be the same as the order of the matrix."); } #if MANAGED // Copy right hand side. DoubleVector X = new DoubleVector(B); // Solve L*Y = B; for (int i = 0; i < order; i++) { double sum = B[i]; for (int k = i - 1; k >= 0; k--) { sum -= l.data[i][k] * X.data[k]; } X.data[i] = sum / l.data[i][i]; } // Solve L'*X = Y; for (int i = order - 1; i >= 0; i--) { double sum = X.data[i]; for (int k = i + 1; k < order; k++) { sum -= l.data[k][i] * X.data[k]; } X.data[i] = sum / l.data[i][i]; } return(X); #else double[] rhs = DoubleMatrix.ToLinearArray(B); Lapack.Potrs.Compute(Lapack.UpLo.Lower, order, 1, l.data, order, rhs, B.Length); DoubleVector ret = new DoubleVector(order, B.Length); ret.data = rhs; return(ret); #endif } }
public void Append(IROVector a) { if (_length + a.Length >= _arr.Length) { Redim((int)(32 + 1.3 * (_length + a.Length))); } for (int i = 0; i < a.Length; i++) { _arr[i + _length] = a[i + a.LowerBound]; } _length += a.Length; }
/// <summary> /// Processes the spectra in matrix xMatrix according to the set-up options for prediction. /// Since it is prediction, the xMean and xScale vectors must be supplied here! /// </summary> /// <param name="xMatrix">The matrix of spectra. Each spectrum is a row of the matrix.</param> /// <param name="xMean">Vector of spectral mean, must be supplied here.</param> /// <param name="xScale">Vector of inverse spectral variance, must be supplied here.</param> public void ProcessForPrediction(IMatrix xMatrix, IROVector xMean, IROVector xScale) { GetPreprocessingMethod().ProcessForPrediction(xMatrix, xMean, xScale, _regions); if (UseDetrending) { new DetrendingCorrection(_detrendingOrder).ProcessForPrediction(xMatrix, xMean, xScale, _regions); } if (EnsembleMeanAfterProcessing || EnsembleScale) { new EnsembleMeanAndScaleCorrection(EnsembleMeanAfterProcessing, EnsembleScale).ProcessForPrediction(xMatrix, xMean, xScale, _regions); } }
private static int FindIndex(IROVector v, bool isDecreasing, int lastIdx, double x) { if (isDecreasing) // strictly decreasing { if (x > v[lastIdx]) { if (lastIdx == 0) return -1; if (x <= v[lastIdx - 1]) return lastIdx - 1; return BinarySearchForIndex(v, isDecreasing, x); } else if (x < v[lastIdx + 1]) { if (lastIdx + 2 <= v.Length) return -1; if (x >= v[lastIdx + 2]) return lastIdx + 1; return BinarySearchForIndex(v, isDecreasing, x); } else { return lastIdx; } } else // strictly increasing { if (x < v[lastIdx]) { if (lastIdx == 0) return -1; if (x >= v[lastIdx - 1]) return lastIdx - 1; return BinarySearchForIndex(v, isDecreasing, x); } else if (x > v[lastIdx + 1]) { if (lastIdx + 2 >= v.Length) return -1; if (x <= v[lastIdx + 2]) return lastIdx + 1; return BinarySearchForIndex(v, isDecreasing, x); } else { return lastIdx; } } }
/// <summary> /// Constructor, takes a double array for wrapping. /// </summary> /// <param name="x"></param> /// <param name="start">Start index of the section to wrap.</param> /// <param name="len">Length of the section to wrap.</param> public ROVectorSectionWrapper(IROVector x, int start, int len) { if (start >= x.Length) { throw new ArgumentException("Start of the section is beyond length of the vector"); } if (start + len > x.Length) { throw new ArgumentException("End of the section is beyond length of the vector"); } _x = x; _start = start; _length = len; }
/// <summary> /// Returns the sum of squared differences of the elements of xarray and yarray. /// </summary> /// <param name="xarray">The first array.</param> /// <param name="yarray">The other array.</param> /// <returns>The sum of squared differences all elements of xarray and yarray.</returns> public static double SumOfSquaredDifferences(IROVector xarray, IROVector yarray) { if (xarray.Length != yarray.Length) { throw new ArgumentException("Length of xarray is unequal length of yarray"); } double sum = 0; for (int i = 0; i < xarray.Length; i++) { sum += Square(xarray[i] - yarray[i]); } return(sum); }
///<summary>Solves a system on linear equations, AX=B, where A is the factored matrixed.</summary> ///<param name="B">RHS side of the system.</param> ///<returns>the solution vector, X.</returns> ///<exception cref="ArgumentNullException">B is null.</exception> ///<exception cref="SingularMatrixException">A is singular.</exception> ///<exception cref="ArgumentException">The number of rows of A and the length of B must be the same.</exception> public DoubleVector Solve(IROVector B) { if (B == null) { throw new System.ArgumentNullException("B cannot be null."); } Compute(); if (singular) { throw new SingularMatrixException(); } else { if (B.Length != order) { throw new System.ArgumentException("The length of B must be the same as the order of the matrix."); } #if MANAGED // Copy right hand side with pivoting DoubleVector X = Pivot(B); // Solve L*Y = B(piv,:) for (int k = 0; k < order; k++) { for (int i = k + 1; i < order; i++) { X[i] -= X[k] * factor[i][k]; } } // Solve U*X = Y; for (int k = order - 1; k >= 0; k--) { X[k] /= factor[k][k]; for (int i = 0; i < k; i++) { X[i] -= X[k] * factor[i][k]; } } return(X); #else double[] rhs = DoubleMatrix.ToLinearArray(B); Lapack.Getrs.Compute(Lapack.Transpose.NoTrans, order, 1, factor, order, pivots, rhs, rhs.Length); return(new DoubleVector(rhs)); #endif } }
public static double Nrd0(IROVector x) { if (x.Length < 2) throw new ArgumentException("need at least 2 data points"); double hi = Statistics.StandardDeviation(x); double lo = Math.Min(hi, Statistics.InterQuartileRange(x) / 1.34); // qnorm(.75) - qnorm(.25) = 1.34898 if (lo.IsNaN()) { lo = hi; if (lo.IsNaN()) { lo = Math.Abs(x[0]); if (lo.IsNaN()) lo = 1; } } return 0.9 * lo * Math.Pow(x.Length, (-0.2)); }
/// <summary> /// Processes the spectra in matrix xMatrix. /// </summary> /// <param name="xMatrix">The matrix of spectra. Each spectrum is a row of the matrix.</param> /// <param name="xMean">Output: On return, contains the ensemble mean of the spectra.</param> /// <param name="xScale">Not used.</param> /// <param name="regionstart">Starting index of the region to process.</param> /// <param name="regionend">End index of the region to process.</param> void ProcessForPrediction(IMatrix xMatrix, IROVector xMean, IROVector xScale, int regionstart, int regionend) { int regionlength = regionend - regionstart; for(int n=0;n<xMatrix.Rows;n++) { // 2.) Do linear regression of the current spectrum versus the mean spectrum QuickLinearRegression regression = new QuickLinearRegression(); for(int i=regionstart;i<regionend;i++) regression.Add(xMean[i],xMatrix[n,i]); double intercept = regression.GetA0(); double slope = regression.GetA1(); // 3.) Subtract intercept and divide by slope for(int i=regionstart;i<regionend;i++) xMatrix[n,i] = (xMatrix[n,i]-intercept)/slope; } }
///<summary>Constructor for <c>DoubleVector</c> to deep copy from a <see cref="IROVector" /></summary> ///<param name="src"><c>Vector</c> to deep copy into <c>DoubleVector</c>.</param> ///<exception cref="ArgumentNullException">Exception thrown if null passed as 'src' parameter.</exception> public DoubleVector(IROVector src) { if (src == null) { throw new ArgumentNullException("IROVector cannot be null"); } if (src is DoubleVector) { data = (double[])(((DoubleVector)src).data.Clone()); } else { data = new double[src.Length]; for (int i = 0; i < src.Length; ++i) { data[i] = src[i]; } } }
/// <summary> /// Trys to identify spectral regions by supplying the spectral x values. /// A end_of_region is recognized when the gap between two x-values is ten times higher /// than the previous gap, or if the sign of the gap value changes. /// This method fails if a spectral region contains only a single point (since no gap value can be obtained then). /// (But in this case almost all spectral correction methods also fails). /// </summary> /// <param name="xvalues">The vector of x values for the spectra (wavelength, frequencies...).</param> /// <returns>The array of regions. Each element in the array is the starting index of a new region into the vector xvalues.</returns> public static int[] IdentifyRegions(IROVector xvalues) { System.Collections.ArrayList list = new System.Collections.ArrayList(); int len = xvalues.Length; for (int i = 0; i < len - 2; i++) { double gap = Math.Abs(xvalues[i + 1] - xvalues[i]); double nextgap = Math.Abs(xvalues[i + 2] - xvalues[i + 1]); if (gap != 0 && (Math.Sign(gap) == -Math.Sign(nextgap) || Math.Abs(nextgap) > 10 * Math.Abs(gap))) { list.Add(i + 2); i++; } } return((int[])list.ToArray(typeof(int))); }
/// <summary> /// Constructs an Akima bivariate spline. /// </summary> /// <param name="x">ARRAY OF DIMENSION LX STORING THE X COORDINATES OF INPUT GRID POINTS (IN ASCENDING ORDER)</param> /// <param name="y">ARRAY OF DIMENSION LY STORING THE Y COORDINATES OF INPUT GRID POINTS (IN ASCENDING ORDER)</param> /// <param name="z">DOUBLY-DIMENSIONED ARRAY OF DIMENSION (LX,LY) STORING THE VALUES OF THE FUNCTION (Z VALUES) AT INPUT GRID POINTS</param> /// <param name="copyDataLocally">If true, the data where cloned before stored here in this instance. If false, the data /// are stored directly. Make sure then, that the data are not changed outside.</param> public BivariateAkimaSpline(IROVector x, IROVector y, IROMatrix z, bool copyDataLocally) { if (copyDataLocally) { _myX = VectorMath.ToVector(new double[x.Length]); VectorMath.Copy(x, (IVector)_myX); _myY = VectorMath.ToVector(new double[y.Length]); VectorMath.Copy(y, (IVector)_myY); _myZ = new MatrixMath.BEMatrix(_myZ.Rows, _myZ.Columns); MatrixMath.Copy(z, (IMatrix)_myZ); } else { _myX = x; _myY = y; _myZ = z; } }
/// <summary> /// Copies the source vector to the destination vector. Both vectors must have the same length. /// </summary> /// <param name="src">The source vector.</param> /// <param name="dest">The destination vector.</param> public static void Copy(IROVector src, IVector dest) { if(src.Length!=dest.Length) throw new ArgumentException("src and destination vector have unequal length!"); Copy(src,src.LowerBound,dest,dest.LowerBound,src.Length); }
/// <summary> /// Copies elements of a source vector to a destination vector. /// </summary> /// <param name="src">The source vector.</param> /// <param name="srcstart">First element of the source vector to copy.</param> /// <param name="dest">The destination vector.</param> /// <param name="deststart">First element of the destination vector to copy to.</param> /// <param name="count">Number of elements to copy.</param> public static void Copy(IROVector src, int srcstart, IVector dest, int deststart, int count) { for(int i=0;i<count;i++) dest[i+deststart] = src[i+srcstart]; }
public void Append(IROVector a) { if(_length+a.Length>=_arr.Length) Redim((int)(32+1.3*(_length+a.Length))); for(int i=0;i<a.Length;i++) _arr[i+_length] = a[i+a.LowerBound]; _length += a.Length; }
/// <summary> /// Wraps a section of a original vector <c>x</c> into a new vector. /// </summary> /// <param name="x">Original vector.</param> /// <param name="start">Index of the start of the section to wrap.</param> /// <param name="len">Length (=number of elements) of the section to wrap.</param> /// <returns>A IROVector that contains the section from <c>start</c> to <c>start+len-1</c> of the original vector.</returns> public static IROVector ToROVector(IROVector x, int start, int len) { return new ROVectorSectionWrapper(x, start, len); }
/// <summary> /// Execute an analysis and stores the result in the provided table. /// </summary> /// <param name="matrixX">The matrix of spectra (horizontal oriented), centered and preprocessed.</param> /// <param name="matrixY">The matrix of concentrations, centered.</param> /// <param name="plsOptions">Information how to perform the analysis.</param> /// <param name="plsContent">A structure to store information about the results of the analysis.</param> /// <param name="table">The table where to store the results to.</param> /// <param name="press">On return, gives a vector holding the PRESS values of the analysis.</param> public virtual void ExecuteAnalysis( IMatrix matrixX, IMatrix matrixY, MultivariateAnalysisOptions plsOptions, MultivariateContentMemento plsContent, DataTable table, out IROVector press ) { int numFactors = Math.Min(matrixX.Columns, plsOptions.MaxNumberOfFactors); MultivariateRegression regress = this.CreateNewRegressionObject(); regress.AnalyzeFromPreprocessed(matrixX, matrixY, numFactors); plsContent.NumberOfFactors = regress.NumberOfFactors; plsContent.CrossValidationType = plsOptions.CrossPRESSCalculation; press = regress.GetPRESSFromPreprocessed(matrixX); Import(regress.CalibrationModel, table); }
public virtual void StorePreprocessedData( IROVector meanX, IROVector scaleX, IROVector meanY, IROVector scaleY, DataTable table) { // Store X-Mean and X-Scale Altaxo.Data.DoubleColumn colXMean = new Altaxo.Data.DoubleColumn(); Altaxo.Data.DoubleColumn colXScale = new Altaxo.Data.DoubleColumn(); for (int i = 0; i < meanX.Length; i++) { colXMean[i] = meanX[i]; colXScale[i] = scaleX[i]; } table.DataColumns.Add(colXMean, _XMean_ColumnName, Altaxo.Data.ColumnKind.V, 0); table.DataColumns.Add(colXScale, _XScale_ColumnName, Altaxo.Data.ColumnKind.V, 0); // store the y-mean and y-scale Altaxo.Data.DoubleColumn colYMean = new Altaxo.Data.DoubleColumn(); Altaxo.Data.DoubleColumn colYScale = new Altaxo.Data.DoubleColumn(); for (int i = 0; i < meanY.Length; i++) { colYMean[i] = meanY[i]; colYScale[i] = 1; } table.DataColumns.Add(colYMean, _YMean_ColumnName, Altaxo.Data.ColumnKind.V, 1); table.DataColumns.Add(colYScale, _YScale_ColumnName, Altaxo.Data.ColumnKind.V, 1); }
/// <summary> /// Resizes the vector to the same boundaries as the provided vector and copies the elements from it. /// </summary> /// <param name="a">The vector to copy the data from.</param> public void CopyFrom(IROVector a) { if (object.ReferenceEquals(this, a)) return; Resize(a.Length); for (int i = 0; i < data.Length; ++i) data[i] = a[i]; }
/// <summary> /// Returns the sum of squared differences of the elements of xarray and yarray. /// </summary> /// <param name="xarray">The first array.</param> /// <param name="yarray">The other array.</param> /// <returns>The sum of squared differences all elements of xarray and yarray.</returns> public static double SumOfSquaredDifferences(IROVector xarray, IROVector yarray) { if(xarray.Length!=yarray.Length) throw new ArgumentException("Length of xarray is unequal length of yarray"); double sum = 0; for(int i=0;i<xarray.Length;i++) sum += Square(xarray[i]-yarray[i]); return sum; }
/// <summary> /// This maps the indices of a master x column to the indices of a column to map. /// </summary> /// <param name="xmaster">The master column containing x-values, for instance the spectral wavelength of the PLS calibration model.</param> /// <param name="xtomap">The column to map containing x-values, for instance the spectral wavelength of an unknown spectra to predict.</param> /// <param name="failureMessage">In case of a mapping error, contains detailed information about the error.</param> /// <returns>The indices of the mapping column that matches those of the master column. Contains as many indices as items in xmaster. In case of mapping error, returns null.</returns> public static Altaxo.Collections.AscendingIntegerCollection MapSpectralX(IROVector xmaster, IROVector xtomap, out string failureMessage) { failureMessage = null; int mastercount = xmaster.Length; int mapcount = xtomap.Length; if (mapcount < mastercount) { failureMessage = string.Format("More items to map ({0} than available ({1}", mastercount, mapcount); return null; } Altaxo.Collections.AscendingIntegerCollection result = new Altaxo.Collections.AscendingIntegerCollection(); // return an empty collection if there is nothing to map if (mastercount == 0) return result; // there is only one item to map - we can not check this - return a 1:1 map if (mastercount == 1) { result.Add(0); return result; } // presumtion here (checked before): mastercount>=2, mapcount>=1 double distanceback, distancecurrent, distanceforward; int i, j; for (i = 0, j = 0; i < mastercount && j < mapcount; j++) { distanceback = j == 0 ? double.MaxValue : Math.Abs(xtomap[j - 1] - xmaster[i]); distancecurrent = Math.Abs(xtomap[j] - xmaster[i]); distanceforward = (j + 1) >= mapcount ? double.MaxValue : Math.Abs(xtomap[j + 1] - xmaster[i]); if (distanceback < distancecurrent) { failureMessage = string.Format("Mapping error - distance of master[{0}] to current map[{1}] is greater than to previous map[{2}]", i, j, j - 1); return null; } else if (distanceforward < distancecurrent) continue; else { result.Add(j); i++; } } if (i != mastercount) { failureMessage = string.Format("Mapping error- no mapping found for current master[{0}]", i - 1); return null; } return result; }
public static void Interpolation(Altaxo.Data.DataColumn xCol, Altaxo.Data.DataColumn yCol, Calc.Interpolation.IInterpolationFunction interpolInstance, IROVector samplePoints, Altaxo.Data.DataColumn xRes, Altaxo.Data.DataColumn yRes) { int rows = Math.Min(xCol.Count, yCol.Count); IROVector yVec = DataColumnWrapper.ToROVector((INumericColumn)yCol, rows); IROVector xVec = DataColumnWrapper.ToROVector((INumericColumn)xCol, rows); interpolInstance.Interpolate(xVec, yVec); using (var suspendToken_xRes = xRes.SuspendGetToken()) { using (var suspendToken_yRes = yRes.SuspendGetToken()) { for (int i = 0; i < samplePoints.Length; i++) { //double r = i / (double)(parameters.NumberOfPoints - 1); //double x = parameters.XOrg * (1 - r) + parameters.XEnd * (r); double x = samplePoints[i]; double y = interpolInstance.GetYOfX(x); xRes[i] = x; yRes[i] = y; } suspendToken_yRes.Resume(); } suspendToken_xRes.Resume(); } }
/// <summary> /// Get the matrix of x and y values (raw data). /// </summary> /// <param name="srctable">The table where the data come from.</param> /// <param name="selectedColumns">The selected columns.</param> /// <param name="selectedRows">The selected rows.</param> /// <param name="selectedPropertyColumns">The selected property column(s).</param> /// <param name="bHorizontalOrientedSpectrum">True if a spectrum is a single row, False if a spectrum is a single column.</param> /// <param name="matrixX">On return, gives the matrix of spectra (each spectra is a row in the matrix).</param> /// <param name="matrixY">On return, gives the matrix of y-values (each measurement is a row in the matrix).</param> /// <param name="plsContent">Holds information about the analysis results.</param> /// <param name="xOfX">On return, this is the vector of values corresponding to each spectral bin, i.e. wavelength values, frequencies etc.</param> /// <returns></returns> public static string GetXYMatrices( Altaxo.Data.DataTable srctable, IAscendingIntegerCollection selectedColumns, IAscendingIntegerCollection selectedRows, IAscendingIntegerCollection selectedPropertyColumns, bool bHorizontalOrientedSpectrum, MultivariateContentMemento plsContent, out IMatrix matrixX, out IMatrix matrixY, out IROVector xOfX ) { matrixX = null; matrixY = null; xOfX = null; plsContent.SpectrumIsRow = bHorizontalOrientedSpectrum; Altaxo.Data.DataColumn xColumnOfX = null; Altaxo.Data.DataColumn labelColumnOfX = new Altaxo.Data.DoubleColumn(); Altaxo.Data.DataColumnCollection concentration = bHorizontalOrientedSpectrum ? srctable.DataColumns : srctable.PropertyColumns; // we presume for now that the spectrum is horizontally, // if not we exchange the collections later AscendingIntegerCollection numericDataCols = new AscendingIntegerCollection(); AscendingIntegerCollection numericDataRows = new AscendingIntegerCollection(); AscendingIntegerCollection concentrationIndices = new AscendingIntegerCollection(); AscendingIntegerCollection spectralIndices = bHorizontalOrientedSpectrum ? numericDataCols : numericDataRows; AscendingIntegerCollection measurementIndices = bHorizontalOrientedSpectrum ? numericDataRows : numericDataCols; plsContent.ConcentrationIndices = concentrationIndices; plsContent.MeasurementIndices = measurementIndices; plsContent.SpectralIndices = spectralIndices; plsContent.SpectrumIsRow = bHorizontalOrientedSpectrum; plsContent.OriginalDataTableName = srctable.Name; bool bUseSelectedColumns = (null != selectedColumns && 0 != selectedColumns.Count); // this is the number of columns (for now), but it can be less than this in case // not all columns are numeric int prenumcols = bUseSelectedColumns ? selectedColumns.Count : srctable.DataColumns.ColumnCount; // check for the number of numeric columns int numcols = 0; for (int i = 0; i < prenumcols; i++) { int idx = bUseSelectedColumns ? selectedColumns[i] : i; if (srctable[idx] is Altaxo.Data.INumericColumn) { numericDataCols.Add(idx); numcols++; } } // check the number of rows bool bUseSelectedRows = (null != selectedRows && 0 != selectedRows.Count); int numrows; if (bUseSelectedRows) { numrows = selectedRows.Count; numericDataRows.Add(selectedRows); } else { numrows = 0; for (int i = 0; i < numcols; i++) { int idx = bUseSelectedColumns ? selectedColumns[i] : i; numrows = Math.Max(numrows, srctable[idx].Count); } numericDataRows.Add(ContiguousIntegerRange.FromStartAndCount(0, numrows)); } if (bHorizontalOrientedSpectrum) { if (numcols < 2) return "At least two numeric columns are neccessary to do Partial Least Squares (PLS) analysis!"; // check that the selected columns are in exactly two groups // the group which has more columns is then considered to have // the spectrum, the other group is the y-values int group0 = -1; int group1 = -1; int groupcount0 = 0; int groupcount1 = 0; for (int i = 0; i < numcols; i++) { int grp = srctable.DataColumns.GetColumnGroup(numericDataCols[i]); if (group0 < 0) { group0 = grp; groupcount0 = 1; } else if (group0 == grp) { groupcount0++; } else if (group1 < 0) { group1 = grp; groupcount1 = 1; } else if (group1 == grp) { groupcount1++; } else { return "The columns you selected must be members of two groups (y-values and spectrum), but actually there are more than two groups!"; } } // end for all columns if (groupcount1 <= 0) return "The columns you selected must be members of two groups (y-values and spectrum), but actually only one group was detected!"; if (groupcount1 < groupcount0) { int hlp; hlp = groupcount1; groupcount1 = groupcount0; groupcount0 = hlp; hlp = group1; group1 = group0; group0 = hlp; } // group0 is now the group of y-values (concentrations) // group1 is now the group of x-values (spectra) // we delete group0 from numericDataCols and add it to concentrationIndices for (int i = numcols - 1; i >= 0; i--) { int index = numericDataCols[i]; if (group0 == srctable.DataColumns.GetColumnGroup(index)) { numericDataCols.Remove(index); concentrationIndices.Add(index); } } // fill the corresponding X-Column of the spectra xColumnOfX = Altaxo.Data.DataColumn.CreateColumnOfSelectedRows( srctable.PropertyColumns.FindXColumnOfGroup(group1), spectralIndices); } else // vertically oriented spectrum -> one spectrum is one data column { // we have to exchange measurementIndices and // if PLS on columns, than we should have property columns selected // that designates the y-values // so count all property columns bool bUseSelectedPropCols = (null != selectedPropertyColumns && 0 != selectedPropertyColumns.Count); // this is the number of property columns (for now), but it can be less than this in case // not all columns are numeric int prenumpropcols = bUseSelectedPropCols ? selectedPropertyColumns.Count : srctable.PropCols.ColumnCount; // check for the number of numeric property columns for (int i = 0; i < prenumpropcols; i++) { int idx = bUseSelectedPropCols ? selectedPropertyColumns[i] : i; if (srctable.PropCols[idx] is Altaxo.Data.INumericColumn) { concentrationIndices.Add(idx); } } if (concentrationIndices.Count < 1) return "At least one numeric property column must exist to hold the y-values!"; // fill the corresponding X-Column of the spectra xColumnOfX = Altaxo.Data.DataColumn.CreateColumnOfSelectedRows( srctable.DataColumns.FindXColumnOf(srctable[measurementIndices[0]]), spectralIndices); } // else vertically oriented spectrum IVector xOfXRW = VectorMath.CreateExtensibleVector(xColumnOfX.Count); xOfX = xOfXRW; if (xColumnOfX is INumericColumn) { for (int i = 0; i < xOfX.Length; i++) xOfXRW[i] = ((INumericColumn)xColumnOfX)[i]; } else { for (int i = 0; i < xOfX.Length; i++) xOfXRW[i] = spectralIndices[i]; } // now fill the matrix // fill in the y-values matrixY = new MatrixMath.BEMatrix(measurementIndices.Count, concentrationIndices.Count); for (int i = 0; i < concentrationIndices.Count; i++) { Altaxo.Data.INumericColumn col = concentration[concentrationIndices[i]] as Altaxo.Data.INumericColumn; for (int j = 0; j < measurementIndices.Count; j++) { matrixY[j, i] = col[measurementIndices[j]]; } } // end fill in yvalues matrixX = new MatrixMath.BEMatrix(measurementIndices.Count, spectralIndices.Count); if (bHorizontalOrientedSpectrum) { for (int i = 0; i < spectralIndices.Count; i++) { labelColumnOfX[i] = spectralIndices[i]; Altaxo.Data.INumericColumn col = srctable[spectralIndices[i]] as Altaxo.Data.INumericColumn; for (int j = 0; j < measurementIndices.Count; j++) { matrixX[j, i] = col[measurementIndices[j]]; } } // end fill in x-values } else // vertical oriented spectrum { for (int i = 0; i < spectralIndices.Count; i++) { labelColumnOfX[i] = spectralIndices[i]; } for (int i = 0; i < measurementIndices.Count; i++) { Altaxo.Data.INumericColumn col = srctable[measurementIndices[i]] as Altaxo.Data.INumericColumn; for (int j = 0; j < spectralIndices.Count; j++) { matrixX[i, j] = col[spectralIndices[j]]; } } // end fill in x-values } return null; }
/// <summary> /// /// </summary> /// <param name="mcalib"></param> /// <param name="groupingStrategy"></param> /// <param name="preprocessOptions"></param> /// <param name="xOfX"></param> /// <param name="matrixX">Matrix of horizontal spectra, centered and preprocessed.</param> /// <param name="matrixY">Matrix of concentrations, centered.</param> /// <param name="numberOfFactors"></param> /// <param name="predictedY"></param> /// <param name="spectralResiduals"></param> public virtual void CalculateCrossPredictedY( IMultivariateCalibrationModel mcalib, ICrossValidationGroupingStrategy groupingStrategy, SpectralPreprocessingOptions preprocessOptions, IROVector xOfX, IMatrix matrixX, IMatrix matrixY, int numberOfFactors, IMatrix predictedY, IMatrix spectralResiduals) { MultivariateRegression.GetCrossYPredicted(xOfX, matrixX, matrixY, numberOfFactors, groupingStrategy, preprocessOptions, this.CreateNewRegressionObject(), predictedY); }
/// <summary> /// Calculate the cross PRESS values and stores the results in the provided table. /// </summary> /// <param name="xOfX">Vector of spectral wavelengths. Necessary to divide the spectras in different regions.</param> /// <param name="matrixX">Matrix of spectra (horizontal oriented).</param> /// <param name="matrixY">Matrix of concentrations.</param> /// <param name="plsOptions">Analysis options.</param> /// <param name="plsContent">Information about this analysis.</param> /// <param name="table">Table to store the results.</param> public virtual void CalculateCrossPRESS( IROVector xOfX, IMatrix matrixX, IMatrix matrixY, MultivariateAnalysisOptions plsOptions, MultivariateContentMemento plsContent, DataTable table ) { IROVector crossPRESSMatrix; Altaxo.Data.DoubleColumn crosspresscol = new Altaxo.Data.DoubleColumn(); double meanNumberOfExcludedSpectra = 0; if (plsOptions.CrossPRESSCalculation != CrossPRESSCalculationType.None) { // now a cross validation - this can take a long time for bigger matrices MultivariateRegression.GetCrossPRESS( xOfX, matrixX, matrixY, plsOptions.MaxNumberOfFactors, GetGroupingStrategy(plsOptions), plsContent.SpectralPreprocessing, this.CreateNewRegressionObject(), out crossPRESSMatrix); VectorMath.Copy(crossPRESSMatrix, DataColumnWrapper.ToVector(crosspresscol, crossPRESSMatrix.Length)); table.DataColumns.Add(crosspresscol, GetCrossPRESSValue_ColumnName(), Altaxo.Data.ColumnKind.V, 4); plsContent.MeanNumberOfMeasurementsInCrossPRESSCalculation = plsContent.NumberOfMeasurements - meanNumberOfExcludedSpectra; } else { table.DataColumns.Add(crosspresscol, GetCrossPRESSValue_ColumnName(), Altaxo.Data.ColumnKind.V, 4); } }
/// <summary> /// Adds (elementwise) two vectors a and b and stores the result in c. All vectors must have the same length. /// </summary> /// <param name="a">First summand.</param> /// <param name="b">Second summand.</param> /// <param name="c">The resulting vector.</param> public static void Add(IROVector a, IROVector b, IVector c) { if(a.Length != b.Length) throw new ArgumentException("Length of vectors a and b unequal"); if(c.Length != b.Length) throw new ArgumentException("Length of vectors a and c unequal"); if(a.LowerBound != b.LowerBound || a.LowerBound != c.LowerBound) throw new ArgumentException("Vectors a, b, and c have not the same LowerBound property"); int end = c.UpperBound; for(int i=c.LowerBound;i<=end;i++) c[i]=a[i]+b[i]; }
public virtual void StoreXOfX(IROVector xOfX, DataTable table) { DoubleColumn xColOfX = new DoubleColumn(); VectorMath.Copy(xOfX, DataColumnWrapper.ToVector(xColOfX, xOfX.Length)); table.DataColumns.Add(xColOfX, _XOfX_ColumnName, Altaxo.Data.ColumnKind.X, 0); }
/// <summary> /// Returns the maximum of the elements in xarray. /// </summary> /// <param name="xarray">The array to search for maximum element.</param> /// <returns>Maximum element of xarray. Returns NaN if the array is empty.</returns> public static double Max(IROVector xarray) { double max = xarray.Length==0 ? double.NaN : xarray[xarray.LowerBound]; int last = xarray.UpperBound; for(int i=xarray.LowerBound+1;i<=last;i++) { max = Math.Max(max,xarray[i]); } return max; }
public void SetErrorVariance(IROVector dyy, double errvar) { dy.CopyFrom(dyy); var = errvar; }
public virtual void StorePRESSData( IROVector PRESS, DataTable table) { StoreNumberOfFactors(PRESS.Length, table); Altaxo.Data.DoubleColumn presscol = new Altaxo.Data.DoubleColumn(); for (int i = 0; i < PRESS.Length; i++) presscol[i] = PRESS[i]; table.DataColumns.Add(presscol, GetPRESSValue_ColumnName(), Altaxo.Data.ColumnKind.V, 4); }
/// <summary> /// Processes the spectra in matrix xMatrix. /// </summary> /// <param name="xMatrix">The matrix of spectra. Each spectrum is a row of the matrix.</param> /// <param name="xMean">Output: On return, contains the ensemble mean of the spectra.</param> /// <param name="xScale">Not used.</param> /// <param name="regions">Vector of spectal regions. Each element is the index of the start of a new region.</param> public virtual void ProcessForPrediction(IMatrix xMatrix, IROVector xMean, IROVector xScale, int[] regions) { }
/// <summary> /// Constructor, takes a double array for wrapping. /// </summary> /// <param name="x"></param> /// <param name="start">Start index of the section to wrap.</param> /// <param name="len">Length of the section to wrap.</param> public ROVectorSectionWrapper(IROVector x, int start, int len) { if(start>=x.Length) throw new ArgumentException("Start of the section is beyond length of the vector"); if (start+len>=x.Length) throw new ArgumentException("End of the section is beyond length of the vector"); _x = x; _start = start; _length = len; }
//----------------------------------------------------------------------------// // // int MpCrossValidatedSpline (const Vector &X, // const Vector &F, // Vector &DF, // Vector &Y, Vector &C1, Vector &C2, Vector &C3, // double& var, Vector &SE, Vector &WK) // // Arguments: // // X Vector of length n containing the abscissae of the // n data points (x[i],f[i]). // x must be ordered so that x[i] < x[i+1]. // // F Vector of length n containing the ordinates // of the n data points (x[i],f[i]). // // DF Vector df[i] is the relative standard // deviation of the error associated with data point i. // Each df[i] must be positive. The values in df are // scaled by the subroutine so that their mean square // value is 1, and unscaled again on normal exit. // The mean square value of the df[i] is returned in // wk[6] on normal exit. // If the absolute standard deviations are known, // these should be provided in df and the error // variance parameter var (see below) should then be // set to 1. // If the relative standard deviations are unknown, // set each df[i]=1. // // Y,C1,C2,C3 Spline coefficient arrays of length n. (output) // The value of the spline approximation at t is // // s(t) = ((c3[i]*d+c2[i])*d+c1[i])*d+y[i] // // where x[i] <= t < x[i+1] and d = t-x[i]. // // That means // y[i] contains the function value y(x[i]) // c1[i] contains the 1st derivative y'(x[i]) // c2[i] contains the 2nd derivative y''(x[i]) // of the smoothing spline. // // var Error variance. (input/output) // If var is negative (i.e. unknown) then // the smoothing parameter is determined // by minimizing the generalized cross validation // and an estimate of the error variance is returned in var. // If var is non-negative (i.e. known) then the // smoothing parameter is determined to minimize // an estimate, which depends on var, of the true // mean square error, and var is unchanged. // In particular, if var is zero, then an // interpolating natural cubic spline is calculated. // var should be set to 1 if absolute standard // deviations have been provided in df (see above). // // SE Vector se of length n returning Bayesian standard // error estimates of the fitted spline values in y. // If a NullVector is passed to the subroutine // then no standard error estimates are computed. // // WK Work vector of length 7*(n+2)+1, arbitrary offset. // On normal exit the first 7 values of wk are assigned // as follows: // // ( here we arbitrarily start numbering from 0) // // wk[0] = smoothing parameter = rho/(rho+1) // If w[1]=0 (rho=0) an interpolating natural // cubic spline has been calculated. // If wk[1]=1 (rho=infinite) a least squares // regression line has been calculated. // wk[1] = estimate of the number of degrees of // freedom of the residual sum of squares // which reduces to the usual value of n-2 // when a least squares regression line // is calculated. // wk[2] = generalized cross validation // wk[3] = mean square residual // wk[4] = estimate of the true mean square error // at the data points // wk[5] = estimate of the error variance // wk[6] coincides with the output value of // var if var is negative on input. It is // calculated with the unscaled values of the // df[i] to facilitate comparisons with a // priori variance estimates. // wk[6] = mean square value of the df[i] // // wk[2],wk[3],wk[4] are calculated with the df[i] // scaled to have mean square value 1. The unscaled // values of wk[2],wk[3],wk[4] may be calculated by // dividing by wk[6]. // // Return value: // = 0 if no errors occured. // = 1 if number of data points n is less than 3. // = 2 if input abscissae are not ordered x[i] < x[i+1]. // = 3 if standard deviation df[i] not positive for some i. // public override int Interpolate(IROVector x, IROVector y) { // check input parameters if (!MatchingIndexRange(x, y)) throw new ArgumentException("index range mismatch of vectors"); // here we must use a copy of the original vectors // Empty data vectors - free auxilliary storage if (x.Length == 0) { xstore.Clear(); ystore.Clear(); y0.Clear(); y1.Clear(); y2.Clear(); y3.Clear(); se.Clear(); wkr.Clear(); wkt.Clear(); wku.Clear(); wkv.Clear(); return 0; } xstore.CopyFrom(x); ystore.CopyFrom(y); // link original data vectors into base class base.x = xstore; base.y = ystore; var n = x.Length; // Resize the auxilliary vectors. Note, that there is no reallocation if the // vector already has the appropriate dimension. y0.Resize(n); y1.Resize(n); y2.Resize(n); y3.Resize(n); // se.Resize(lo,hi); // currently zero wkr.Resize(3 * (n + 2)); wkt.Resize(2 * (n + 2)); wku.Resize(1 * (n + 2)); wkv.Resize(1 * (n + 2)); if (calculateErrorEstimates) se.Resize(n); // set derivatives for a single point if (x.Length == 1) { y0[0] = y[0]; y1[0] = y2[0] = y3[0] = 0.0; return 0; } // set derivatives for a line if (x.Length == 2) { y0[0] = y[0]; y0[n - 1] = y[n - 1]; y1[0] = y1[n - 1] = (y[n - 1] - y[0]) / (x[n - 1] - x[0]); y2[0] = y2[n - 1] = y3[0] = y3[n - 1] = 0.0; return 0; } // set standard deviation of the points to 1 if dy is not set or has // the wrong length if (dy.Store() == null || dy.Length != xstore.Length) { dy.Resize(n); for (int k = 0; k < n; ++k) dy[k] = 1; } // adjust pointers to vectors so that indexing starts from 1 double[] xx = xstore.Store(); double[] f = ystore.Store(); double[] yy = y0.Store(); // coefficients calculated double[] c1 = y1.Store(); double[] c2 = y2.Store(); double[] c3 = y3.Store(); double[] df = dy.Store(); // index starts from 0 double[] wwr = wkr.Store(); double[] wwt = wkt.Store(); double[] wwu = wku.Store(); double[] wwv = wkv.Store(); // set ss to (double*)0 if a NullVector is given double[] ss = null; if (se.Length > 0) ss = se.Store(); return cubgcv(xx, f, df, n, yy, c1, c2, c3, ss, wwr, wwt, wwu, wwv); }
///<summary>Solves a system on linear equations, AX=B, where A is the factored matrixed.</summary> ///<param name="B">RHS side of the system.</param> ///<returns>the solution vector, X.</returns> ///<exception cref="ArgumentNullException">B is null.</exception> ///<exception cref="NotPositiveDefiniteException">A is not positive definite.</exception> ///<exception cref="ArgumentException">The number of rows of A and the length of B must be the same.</exception> public DoubleVector Solve (IROVector B) { if ( B == null ) { throw new System.ArgumentNullException("B cannot be null."); } Compute(); if ( !ispd ) { throw new NotPositiveDefiniteException(); } else { if ( B.Length != order ) { throw new System.ArgumentException("The length of B must be the same as the order of the matrix." ); } #if MANAGED // Copy right hand side. DoubleVector X = new DoubleVector(B); // Solve L*Y = B; for (int i = 0; i < order; i++) { double sum = B[i]; for (int k = i-1; k >= 0; k--) { sum -= l.data[i][k] * X.data[k]; } X.data[i] = sum / l.data[i][i]; } // Solve L'*X = Y; for (int i =order-1; i >= 0; i--) { double sum = X.data[i]; for (int k = i+1; k < order; k++) { sum -= l.data[k][i] * X.data[k]; } X.data[i] = sum / l.data[i][i]; } return X; #else double[] rhs = DoubleMatrix.ToLinearArray(B); Lapack.Potrs.Compute(Lapack.UpLo.Lower,order,1,l.data,order,rhs,B.Length); DoubleVector ret = new DoubleVector(order,B.Length); ret.data = rhs; return ret; #endif } }