Example #1
0
        /// <summary>
        /// Creates an analyis from preprocessed spectra and preprocessed concentrations.
        /// </summary>
        /// <param name="matrixX">The spectral matrix (each spectrum is a row in the matrix). They must at least be centered.</param>
        /// <param name="matrixY">The matrix of concentrations (each experiment is a row in the matrix). They must at least be centered.</param>
        /// <param name="maxFactors">Maximum number of factors for analysis.</param>
        /// <returns>A regression object, which holds all the loads and weights neccessary for further calculations.</returns>
        protected override void AnalyzeFromPreprocessedWithoutReset(IROMatrix matrixX, IROMatrix matrixY, int maxFactors)
        {
            int     numberOfFactors = _calib.NumberOfFactors = Math.Min(matrixX.Columns, maxFactors);
            IMatrix helperY         = new MatrixMath.BEMatrix(matrixY.Rows, 1);

            _PRESS = null;

            for (int i = 0; i < matrixY.Columns; i++)
            {
                MatrixMath.Submatrix(matrixY, helperY, 0, i);

                PLS2Regression r = PLS2Regression.CreateFromPreprocessed(matrixX, helperY, maxFactors);

                IPLS2CalibrationModel cal = r.CalibrationModel;
                _calib.NumberOfFactors = Math.Min(_calib.NumberOfFactors, cal.NumberOfFactors);
                _calib.XLoads[i]       = cal.XLoads;
                _calib.YLoads[i]       = cal.YLoads;
                _calib.XWeights[i]     = cal.XWeights;
                _calib.CrossProduct[i] = cal.CrossProduct;

                if (_PRESS == null)
                {
                    _PRESS = VectorMath.CreateExtensibleVector(r.PRESS.Length);
                }
                VectorMath.Add(_PRESS, r.PRESS, _PRESS);
            }
        }
    /// <summary>
    /// Creates an analyis from preprocessed spectra and preprocessed concentrations.
    /// </summary>
    /// <param name="matrixX">The spectral matrix (each spectrum is a row in the matrix). They must at least be centered.</param>
    /// <param name="matrixY">The matrix of concentrations (each experiment is a row in the matrix). They must at least be centered.</param>
    /// <param name="maxFactors">Maximum number of factors for analysis.</param>
    /// <returns>A regression object, which holds all the loads and weights neccessary for further calculations.</returns>
    protected override void AnalyzeFromPreprocessedWithoutReset(IROMatrix matrixX, IROMatrix matrixY, int maxFactors)
    {
      int numberOfFactors = _calib.NumberOfFactors = Math.Min(matrixX.Columns, maxFactors);
      IMatrix helperY = new MatrixMath.BEMatrix(matrixY.Rows,1);
      
      _PRESS = null;

      for(int i=0;i<matrixY.Columns;i++)
      {
        MatrixMath.Submatrix(matrixY,helperY,0,i);
       
        PLS2Regression r = PLS2Regression.CreateFromPreprocessed(matrixX, helperY, maxFactors);

        IPLS2CalibrationModel cal = r.CalibrationModel;
        _calib.NumberOfFactors = Math.Min(_calib.NumberOfFactors,cal.NumberOfFactors);
        _calib.XLoads[i] = cal.XLoads;
        _calib.YLoads[i] = cal.YLoads;
        _calib.XWeights[i] = cal.XWeights;
        _calib.CrossProduct[i] = cal.CrossProduct;

        if(_PRESS==null)
          _PRESS = VectorMath.CreateExtensibleVector(r.PRESS.Length);
        VectorMath.Add(_PRESS,r.PRESS,_PRESS);
      }
    }
Example #3
0
        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);
            }
        }
Example #4
0
        /// <summary>
        /// Creates an analyis from preprocessed spectra and preprocessed concentrations.
        /// </summary>
        /// <param name="matrixX">The spectral matrix (each spectrum is a row in the matrix). They must at least be centered.</param>
        /// <param name="matrixY">The matrix of concentrations (each experiment is a row in the matrix). They must at least be centered.</param>
        /// <param name="maxFactors">Maximum number of factors for analysis.</param>
        /// <returns>A regression object, which holds all the loads and weights neccessary for further calculations.</returns>
        protected override void AnalyzeFromPreprocessedWithoutReset(IROMatrix matrixX, IROMatrix matrixY, int maxFactors)
        {
            int numberOfFactors = _calib.NumberOfFactors = Math.Min(matrixX.Columns, maxFactors);

            MatrixMath.BEMatrix _xLoads = new MatrixMath.BEMatrix(0, 0);
            MatrixMath.BEMatrix _yLoads = new MatrixMath.BEMatrix(0, 0);
            MatrixMath.BEMatrix _W      = new MatrixMath.BEMatrix(0, 0);
            MatrixMath.REMatrix _V      = new MatrixMath.REMatrix(0, 0);
            _PRESS = VectorMath.CreateExtensibleVector(0);

            ExecuteAnalysis(matrixX, matrixY, ref numberOfFactors, _xLoads, _yLoads, _W, _V, _PRESS);
            _calib.NumberOfFactors = Math.Min(_calib.NumberOfFactors, numberOfFactors);
            _calib.XLoads          = _xLoads;
            _calib.YLoads          = _yLoads;
            _calib.XWeights        = _W;
            _calib.CrossProduct    = _V;
        }
Example #5
0
        /// <summary>
        /// Creates an analyis from preprocessed spectra and preprocessed concentrations.
        /// </summary>
        /// <param name="matrixX">The spectral matrix (each spectrum is a row in the matrix). They must at least be centered.</param>
        /// <param name="matrixY">The matrix of concentrations (each experiment is a row in the matrix). They must at least be centered.</param>
        /// <param name="maxFactors">Maximum number of factors for analysis.</param>
        /// <returns>A regression object, which holds all the loads and weights neccessary for further calculations.</returns>
        protected override void AnalyzeFromPreprocessedWithoutReset(IROMatrix <double> matrixX, IROMatrix <double> matrixY, int maxFactors)
        {
            int numberOfFactors = _calib.NumberOfFactors = Math.Min(matrixX.ColumnCount, maxFactors);

            var _xLoads = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(0, 0);
            var _yLoads = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(0, 0);
            var _W      = new MatrixMath.LeftSpineJaggedArrayMatrix <double>(0, 0);
            var _V      = new MatrixMath.TopSpineJaggedArrayMatrix <double>(0, 0);

            _PRESS = VectorMath.CreateExtensibleVector <double>(0);

            ExecuteAnalysis(matrixX, matrixY, ref numberOfFactors, _xLoads, _yLoads, _W, _V, _PRESS);
            _calib.NumberOfFactors = Math.Min(_calib.NumberOfFactors, numberOfFactors);
            _calib.XLoads          = _xLoads;
            _calib.YLoads          = _yLoads;
            _calib.XWeights        = _W;
            _calib.CrossProduct    = _V;
        }
Example #6
0
        /// <summary>
        /// Partial least squares (PLS) decomposition of the matrizes X and Y.
        /// </summary>
        /// <param name="_X">The X ("spectrum") matrix, centered and preprocessed.</param>
        /// <param name="_Y">The Y ("concentration") matrix (centered).</param>
        /// <param name="numFactors">Number of factors to calculate.</param>
        /// <param name="xLoads">Returns the matrix of eigenvectors of X. Should be initially empty.</param>
        /// <param name="yLoads">Returns the matrix of eigenvectors of Y. Should be initially empty. </param>
        /// <param name="W">Returns the matrix of weighting values. Should be initially empty.</param>
        /// <param name="V">Returns the vector of cross products. Should be initially empty.</param>
        /// <param name="PRESS">If not null, the PRESS value of each factor is stored (vertically) here. </param>
        public static void ExecuteAnalysis(
            IROMatrix _X,                   // matrix of spectra (a spectra is a row of this matrix)
            IROMatrix _Y,                   // matrix of concentrations (a mixture is a row of this matrix)
            ref int numFactors,
            IBottomExtensibleMatrix xLoads, // out: the loads of the X matrix
            IBottomExtensibleMatrix yLoads, // out: the loads of the Y matrix
            IBottomExtensibleMatrix W,      // matrix of weighting values
            IRightExtensibleMatrix V,       // matrix of cross products
            IExtensibleVector PRESS         //vector of Y PRESS values
            )
        {
            // used variables:
            // n: number of spectra (number of tests, number of experiments)
            // p: number of slots (frequencies, ..) in each spectrum
            // m: number of constitutents (number of y values in each measurement)

            // X : n-p matrix of spectra (each spectra is a horizontal row)
            // Y : n-m matrix of concentrations


            const int    maxIterations = 1500;  // max number of iterations in one factorization step
            const double accuracy      = 1E-12; // accuracy that should be reached between subsequent calculations of the u-vector



            // use the mean spectrum as first row of the W matrix
            MatrixMath.HorizontalVector mean = new MatrixMath.HorizontalVector(_X.Columns);
            //  MatrixMath.ColumnsToZeroMean(X,mean);
            //W.AppendBottom(mean);

            IMatrix X = new MatrixMath.BEMatrix(_X.Rows, _X.Columns);

            MatrixMath.Copy(_X, X);
            IMatrix Y = new MatrixMath.BEMatrix(_Y.Rows, _Y.Columns);

            MatrixMath.Copy(_Y, Y);

            IMatrix u_prev = null;
            IMatrix w      = new MatrixMath.HorizontalVector(X.Columns); // horizontal vector of X (spectral) weighting
            IMatrix t      = new MatrixMath.VerticalVector(X.Rows);      // vertical vector of X  scores
            IMatrix u      = new MatrixMath.VerticalVector(X.Rows);      // vertical vector of Y scores
            IMatrix p      = new MatrixMath.HorizontalVector(X.Columns); // horizontal vector of X loads
            IMatrix q      = new MatrixMath.HorizontalVector(Y.Columns); // horizontal vector of Y loads

            int maxFactors = Math.Min(X.Columns, X.Rows);

            numFactors = numFactors <= 0 ? maxFactors : Math.Min(numFactors, maxFactors);

            if (PRESS != null)
            {
                PRESS.Append(new MatrixMath.Scalar(MatrixMath.SumOfSquares(Y))); // Press value for not decomposed Y
            }

            for (int nFactor = 0; nFactor < numFactors; nFactor++)
            {
                //Console.WriteLine("Factor_{0}:",nFactor);
                //Console.WriteLine("X:"+X.ToString());
                //Console.WriteLine("Y:"+Y.ToString());


                // 1. Use as start vector for the y score the first column of the
                // y-matrix
                MatrixMath.Submatrix(Y, u); // u is now a vertical vector of concentrations of the first constituents

                for (int iter = 0; iter < maxIterations; iter++)
                {
                    // 2. Calculate the X (spectrum) weighting vector
                    MatrixMath.MultiplyFirstTransposed(u, X, w); // w is a horizontal vector

                    // 3. Normalize w to unit length
                    MatrixMath.NormalizeRows(w); // w now has unit length

                    // 4. Calculate X (spectral) scores
                    MatrixMath.MultiplySecondTransposed(X, w, t); // t is a vertical vector of n numbers

                    // 5. Calculate the Y (concentration) loading vector
                    MatrixMath.MultiplyFirstTransposed(t, Y, q); // q is a horizontal vector of m (number of constitutents)

                    // 5.1 Normalize q to unit length
                    MatrixMath.NormalizeRows(q);

                    // 6. Calculate the Y (concentration) score vector u
                    MatrixMath.MultiplySecondTransposed(Y, q, u); // u is a vertical vector of n numbers

                    // 6.1 Compare
                    // Compare this with the previous one
                    if (u_prev != null && MatrixMath.IsEqual(u_prev, u, accuracy))
                    {
                        break;
                    }
                    if (u_prev == null)
                    {
                        u_prev = new MatrixMath.VerticalVector(X.Rows);
                    }
                    MatrixMath.Copy(u, u_prev); // stores the content of u in u_prev
                } // for all iterations

                // Store the scores of X
                //factors.AppendRight(t);


                // 7. Calculate the inner scalar (cross product)
                double            length_of_t = MatrixMath.LengthOf(t);
                MatrixMath.Scalar v           = new MatrixMath.Scalar(0);
                MatrixMath.MultiplyFirstTransposed(u, t, v);
                if (length_of_t != 0)
                {
                    v = v / MatrixMath.Square(length_of_t);
                }

                // 8. Calculate the new loads for the X (spectral) matrix
                MatrixMath.MultiplyFirstTransposed(t, X, p); // p is a horizontal vector of loads
                // Normalize p by the spectral scores

                if (length_of_t != 0)
                {
                    MatrixMath.MultiplyScalar(p, 1 / MatrixMath.Square(length_of_t), p);
                }

                // 9. Calculate the new residua for the X (spectral) and Y (concentration) matrix
                //MatrixMath.MultiplyScalar(t,length_of_t*v,t); // original t times the cross product

                MatrixMath.SubtractProductFromSelf(t, p, X);

                MatrixMath.MultiplyScalar(t, v, t);          // original t times the cross product
                MatrixMath.SubtractProductFromSelf(t, q, Y); // to calculate residual Y

                // Store the loads of X and Y in the output result matrix
                xLoads.AppendBottom(p);
                yLoads.AppendBottom(q);
                W.AppendBottom(w);
                V.AppendRight(v);

                if (PRESS != null)
                {
                    double pressValue = MatrixMath.SumOfSquares(Y);
                    PRESS.Append(new MatrixMath.Scalar(pressValue));
                }
                // Calculate SEPcv. If SEPcv is greater than for the actual number of factors,
                // break since the optimal number of factors was found. If not, repeat the calculations
                // with the residual matrizes for the next factor.
            } // for all factors
        }
    /// <summary>
    /// Creates an analyis from preprocessed spectra and preprocessed concentrations.
    /// </summary>
    /// <param name="matrixX">The spectral matrix (each spectrum is a row in the matrix). They must at least be centered.</param>
    /// <param name="matrixY">The matrix of concentrations (each experiment is a row in the matrix). They must at least be centered.</param>
    /// <param name="maxFactors">Maximum number of factors for analysis.</param>
    /// <returns>A regression object, which holds all the loads and weights neccessary for further calculations.</returns>
    protected override void AnalyzeFromPreprocessedWithoutReset(IROMatrix matrixX, IROMatrix matrixY, int maxFactors)
    {
      int numberOfFactors = _calib.NumberOfFactors = Math.Min(matrixX.Columns, maxFactors);

      MatrixMath.BEMatrix _xLoads   = new MatrixMath.BEMatrix(0,0);
      MatrixMath.BEMatrix _yLoads   = new MatrixMath.BEMatrix(0,0);
      MatrixMath.BEMatrix _W       = new MatrixMath.BEMatrix(0,0);
      MatrixMath.REMatrix _V       = new MatrixMath.REMatrix(0,0);
      _PRESS   = VectorMath.CreateExtensibleVector(0);

      ExecuteAnalysis(matrixX, matrixY, ref numberOfFactors, _xLoads, _yLoads, _W, _V, _PRESS);
      _calib.NumberOfFactors = Math.Min(_calib.NumberOfFactors,numberOfFactors);
      _calib.XLoads = _xLoads;
      _calib.YLoads = _yLoads;
      _calib.XWeights = _W;
      _calib.CrossProduct = _V;
    }
    /// <summary>
    /// Partial least squares (PLS) decomposition of the matrizes X and Y.
    /// </summary>
    /// <param name="_X">The X ("spectrum") matrix, centered and preprocessed.</param>
    /// <param name="_Y">The Y ("concentration") matrix (centered).</param>
    /// <param name="numFactors">Number of factors to calculate.</param>
    /// <param name="xLoads">Returns the matrix of eigenvectors of X. Should be initially empty.</param>
    /// <param name="yLoads">Returns the matrix of eigenvectors of Y. Should be initially empty. </param>
    /// <param name="W">Returns the matrix of weighting values. Should be initially empty.</param>
    /// <param name="V">Returns the vector of cross products. Should be initially empty.</param>
    /// <param name="PRESS">If not null, the PRESS value of each factor is stored (vertically) here. </param>
    public static void ExecuteAnalysis(
      IROMatrix _X, // matrix of spectra (a spectra is a row of this matrix)
      IROMatrix _Y, // matrix of concentrations (a mixture is a row of this matrix)
      ref int numFactors,
      IBottomExtensibleMatrix xLoads, // out: the loads of the X matrix
      IBottomExtensibleMatrix yLoads, // out: the loads of the Y matrix
      IBottomExtensibleMatrix W, // matrix of weighting values
      IRightExtensibleMatrix V,  // matrix of cross products
      IExtensibleVector PRESS //vector of Y PRESS values
      )
    {
      // used variables:
      // n: number of spectra (number of tests, number of experiments)
      // p: number of slots (frequencies, ..) in each spectrum
      // m: number of constitutents (number of y values in each measurement)
      
      // X : n-p matrix of spectra (each spectra is a horizontal row)
      // Y : n-m matrix of concentrations


      const int maxIterations = 1500; // max number of iterations in one factorization step
      const double accuracy = 1E-12; // accuracy that should be reached between subsequent calculations of the u-vector



      // use the mean spectrum as first row of the W matrix
      MatrixMath.HorizontalVector mean = new MatrixMath.HorizontalVector(_X.Columns);
      //  MatrixMath.ColumnsToZeroMean(X,mean);
      //W.AppendBottom(mean);

      IMatrix X = new MatrixMath.BEMatrix(_X.Rows,_X.Columns);
      MatrixMath.Copy(_X,X);
      IMatrix Y = new MatrixMath.BEMatrix(_Y.Rows,_Y.Columns);
      MatrixMath.Copy(_Y,Y);

      IMatrix u_prev = null;
      IMatrix w = new MatrixMath.HorizontalVector(X.Columns); // horizontal vector of X (spectral) weighting
      IMatrix t = new MatrixMath.VerticalVector(X.Rows); // vertical vector of X  scores
      IMatrix u = new MatrixMath.VerticalVector(X.Rows); // vertical vector of Y scores
      IMatrix p = new MatrixMath.HorizontalVector(X.Columns); // horizontal vector of X loads
      IMatrix q = new MatrixMath.HorizontalVector(Y.Columns); // horizontal vector of Y loads

      int maxFactors = Math.Min(X.Columns,X.Rows);
      numFactors = numFactors<=0 ? maxFactors : Math.Min(numFactors,maxFactors);

      if(PRESS!=null)
      {
        PRESS.Append(new MatrixMath.Scalar(MatrixMath.SumOfSquares(Y))); // Press value for not decomposed Y
      }

      for(int nFactor=0; nFactor<numFactors; nFactor++)
      {
        //Console.WriteLine("Factor_{0}:",nFactor);
        //Console.WriteLine("X:"+X.ToString());
        //Console.WriteLine("Y:"+Y.ToString());

  
        // 1. Use as start vector for the y score the first column of the 
        // y-matrix
        MatrixMath.Submatrix(Y,u); // u is now a vertical vector of concentrations of the first constituents

        for(int iter=0;iter<maxIterations;iter++)
        {
          // 2. Calculate the X (spectrum) weighting vector
          MatrixMath.MultiplyFirstTransposed(u,X,w); // w is a horizontal vector

          // 3. Normalize w to unit length
          MatrixMath.NormalizeRows(w); // w now has unit length

          // 4. Calculate X (spectral) scores
          MatrixMath.MultiplySecondTransposed(X,w,t); // t is a vertical vector of n numbers

          // 5. Calculate the Y (concentration) loading vector
          MatrixMath.MultiplyFirstTransposed(t,Y,q); // q is a horizontal vector of m (number of constitutents)

          // 5.1 Normalize q to unit length
          MatrixMath.NormalizeRows(q);

          // 6. Calculate the Y (concentration) score vector u
          MatrixMath.MultiplySecondTransposed(Y,q,u); // u is a vertical vector of n numbers

          // 6.1 Compare
          // Compare this with the previous one 
          if(u_prev!=null && MatrixMath.IsEqual(u_prev,u,accuracy))
            break;
          if(u_prev==null)
            u_prev = new MatrixMath.VerticalVector(X.Rows);
          MatrixMath.Copy(u,u_prev); // stores the content of u in u_prev
        } // for all iterations

        // Store the scores of X
        //factors.AppendRight(t);


        // 7. Calculate the inner scalar (cross product)
        double length_of_t = MatrixMath.LengthOf(t); 
        MatrixMath.Scalar v = new MatrixMath.Scalar(0);
        MatrixMath.MultiplyFirstTransposed(u,t,v);
        if(length_of_t!=0)
          v = v/MatrixMath.Square(length_of_t); 
      
        // 8. Calculate the new loads for the X (spectral) matrix
        MatrixMath.MultiplyFirstTransposed(t,X,p); // p is a horizontal vector of loads
        // Normalize p by the spectral scores

        if(length_of_t!=0)
          MatrixMath.MultiplyScalar(p,1/MatrixMath.Square(length_of_t),p);

        // 9. Calculate the new residua for the X (spectral) and Y (concentration) matrix
        //MatrixMath.MultiplyScalar(t,length_of_t*v,t); // original t times the cross product

        MatrixMath.SubtractProductFromSelf(t,p,X);
        
        MatrixMath.MultiplyScalar(t,v,t); // original t times the cross product
        MatrixMath.SubtractProductFromSelf(t,q,Y); // to calculate residual Y

        // Store the loads of X and Y in the output result matrix
        xLoads.AppendBottom(p);
        yLoads.AppendBottom(q);
        W.AppendBottom(w);
        V.AppendRight(v);
    
        if(PRESS!=null)
        {
          double pressValue=MatrixMath.SumOfSquares(Y);
          PRESS.Append(new MatrixMath.Scalar(pressValue));
        }
        // Calculate SEPcv. If SEPcv is greater than for the actual number of factors,
        // break since the optimal number of factors was found. If not, repeat the calculations
        // with the residual matrizes for the next factor.
      } // for all factors
    }