11 added + 3 modified, total 14 files
java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/GblData.java (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/GblData.java 2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,289 @@
+package org.hps.recon.tracking.gbl;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.hps.recon.tracking.gbl.matrix.VVector;
+
+
+/**
+ *
+ * @author Norman A Graf
+ *
+ * @version $Id:
+ */
+public class GblData
+{
+
+ int theLabel; ///< Label (of measurements point)
+ double theValue; ///< Value (residual)
+ double thePrecision; ///< Precision (1/sigma**2)
+ double theDownWeight; ///< Down-weighting factor (0-1)
+ double thePrediction; ///< Prediction from fit
+ List<Integer> theParameters = new ArrayList<Integer>(); ///< List of fit parameters (with non zero derivatives)
+ List<Double> theDerivatives = new ArrayList<Double>(); ///< List of derivatives for fit
+ List<Integer> globalLabels = new ArrayList<Integer>(); ///< Labels for global derivatives
+ List<Double> globalDerivatives = new ArrayList<Double>(); ///< Global derivatives
+
+/// Create data block.
+ /**
+ * \param [in] aLabel Label of corresponding point \param [in] aValue Value
+ * of (scalar) measurement \param [in] aPrec Precision of (scalar)
+ * measurement
+ */
+ GblData(int aLabel, double aValue, double aPrec)
+ {
+
+ theLabel = aLabel;
+ theValue = aValue;
+ thePrecision = aPrec;
+ theDownWeight = 1.;
+ thePrediction = 0.;
+ }
+
+///// Add derivatives from measurement.
+///**
+// * Add (non-zero) derivatives to data block. Fill list of labels of used fit parameters.
+// * \param [in] iRow Row index (0-4) in up to 5D measurement
+// * \param [in] labDer Labels for derivatives
+// * \param [in] matDer Derivatives (matrix) 'measurement vs track fit parameters'
+// * \param [in] iOff Offset for row index for additional parameters
+// * \param [in] derLocal Derivatives (matrix) for additional local parameters
+// * \param [in] labGlobal Labels for additional global (MP-II) parameters
+// * \param [in] derGlobal Derivatives (matrix) for additional global (MP-II) parameters
+// * \param [in] extOff Offset for external parameters
+// * \param [in] extDer Derivatives for external Parameters
+// */
+//void addDerivatives(unsigned int iRow,
+// const std::vector<unsigned int> &labDer, const SMatrix55 &matDer,
+// unsigned int iOff, const TMatrixD &derLocal,
+// const std::vector<int> &labGlobal, const TMatrixD &derGlobal,
+// unsigned int extOff, const TMatrixD &extDer) {
+//
+// unsigned int nParMax = 5 + derLocal.GetNcols() + extDer.GetNcols();
+// theParameters.reserve(nParMax); // have to be sorted
+// theDerivatives.reserve(nParMax);
+//
+// for (int i = 0; i < derLocal.GetNcols(); ++i) // local derivatives
+// {
+// if (derLocal(iRow - iOff, i)) {
+// theParameters.push_back(i + 1);
+// theDerivatives.push_back(derLocal(iRow - iOff, i));
+// }
+// }
+//
+// for (int i = 0; i < extDer.GetNcols(); ++i) // external derivatives
+// {
+// if (extDer(iRow - iOff, i)) {
+// theParameters.push_back(extOff + i + 1);
+// theDerivatives.push_back(extDer(iRow - iOff, i));
+// }
+// }
+//
+// for (unsigned int i = 0; i < 5; ++i) // curvature, offset derivatives
+// {
+// if (labDer[i] && matDer(iRow, i)) {
+// theParameters.push_back(labDer[i]);
+// theDerivatives.push_back(matDer(iRow, i));
+// }
+// }
+//
+// globalLabels = labGlobal;
+// for (int i = 0; i < derGlobal.GetNcols(); ++i) // global derivatives
+// globalDerivatives.push_back(derGlobal(iRow - iOff, i));
+//}
+//
+///// Add derivatives from kink.
+///**
+// * Add (non-zero) derivatives to data block. Fill list of labels of used fit parameters.
+// * \param [in] iRow Row index (0-1) in 2D kink
+// * \param [in] labDer Labels for derivatives
+// * \param [in] matDer Derivatives (matrix) 'kink vs track fit parameters'
+// * \param [in] extOff Offset for external parameters
+// * \param [in] extDer Derivatives for external Parameters
+// */
+//void addDerivatives(unsigned int iRow,
+// const std::vector<unsigned int> &labDer, const SMatrix27 &matDer,
+// unsigned int extOff, const TMatrixD &extDer) {
+//
+// unsigned int nParMax = 7 + extDer.GetNcols();
+// theParameters.reserve(nParMax); // have to be sorted
+// theDerivatives.reserve(nParMax);
+//
+// for (int i = 0; i < extDer.GetNcols(); ++i) // external derivatives
+// {
+// if (extDer(iRow, i)) {
+// theParameters.push_back(extOff + i + 1);
+// theDerivatives.push_back(extDer(iRow, i));
+// }
+// }
+//
+// for (unsigned int i = 0; i < 7; ++i) // curvature, offset derivatives
+// {
+// if (labDer[i] && matDer(iRow, i)) {
+// theParameters.push_back(labDer[i]);
+// theDerivatives.push_back(matDer(iRow, i));
+// }
+// }
+//}
+//
+///// Add derivatives from external seed.
+///**
+// * Add (non-zero) derivatives to data block. Fill list of labels of used fit parameters.
+// * \param [in] index Labels for derivatives
+// * \param [in] derivatives Derivatives (vector)
+// */
+//void addDerivatives(const std::vector<unsigned int> &index,
+// const std::vector<double> &derivatives) {
+// for (unsigned int i = 0; i < derivatives.size(); ++i) // any derivatives
+// {
+// if (derivatives[i]) {
+// theParameters.push_back(index[i]);
+// theDerivatives.push_back(derivatives[i]);
+// }
+// }
+//}
+/// Calculate prediction for data from fit (by GblTrajectory::fit).
+ void setPrediction(VVector aVector)
+ {
+
+ thePrediction = 0.;
+ for (int i = 0; i < theDerivatives.size(); ++i) {
+ thePrediction += theDerivatives.get(i) * aVector.get(theParameters.get(i) - 1);
+ }
+ }
+
+///// Outlier down weighting with M-estimators (by GblTrajectory::fit).
+///**
+// * \param [in] aMethod M-estimator (1: Tukey, 2:Huber, 3:Cauchy)
+// */
+//double setDownWeighting(unsigned int aMethod) {
+//
+// double aWeight = 1.;
+// double scaledResidual = fabs(theValue - thePrediction) * sqrt(thePrecision);
+// if (aMethod == 1) // Tukey
+// {
+// if (scaledResidual < 4.6851) {
+// aWeight = (1.0 - 0.045558 * scaledResidual * scaledResidual);
+// aWeight *= aWeight;
+// } else {
+// aWeight = 0.;
+// }
+// } else if (aMethod == 2) //Huber
+// {
+// if (scaledResidual >= 1.345) {
+// aWeight = 1.345 / scaledResidual;
+// }
+// } else if (aMethod == 3) //Cauchy
+// {
+// aWeight = 1.0 / (1.0 + (scaledResidual * scaledResidual / 5.6877));
+// }
+// theDownWeight = aWeight;
+// return aWeight;
+//}
+//
+/// Calculate Chi2 contribution.
+ /**
+ * \return (down-weighted) Chi2
+ */
+ double getChi2()
+ {
+ double aDiff = theValue - thePrediction;
+ return aDiff * aDiff * thePrecision * theDownWeight;
+ }
+
+///// Print data block.
+//void printData() const {
+//
+// std::cout << " measurement at label " << theLabel << ": " << theValue
+// << ", " << thePrecision << std::endl;
+// std::cout << " param " << theParameters.size() << ":";
+// for (unsigned int i = 0; i < theParameters.size(); ++i)
+// std::cout << " " << theParameters[i];
+// }
+// std::cout << std::endl;
+// std::cout << " deriv " << theDerivatives.size() << ":";
+// for (unsigned int i = 0; i < theDerivatives.size(); ++i) {
+// std::cout << " " << theDerivatives[i];
+// }
+// std::cout << std::endl;
+//}
+//
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer(" measurement at label " + theLabel + ": " + theValue + ", " + thePrecision + "\n");
+ sb.append(" param " + theParameters.size() + ":");
+ for (int i = 0; i < theParameters.size(); ++i) {
+ sb.append(" " + theParameters.get(i));
+ }
+ sb.append("\n");
+ return sb.toString();
+ }
+
+/// Get Data for local fit.
+ /**
+ * \param [out] aValue Value \param [out] aWeight Weight \param [out]
+ * indLocal List of labels of used (local) fit parameters \param [out]
+ * derLocal List of derivatives for used (local) fit parameters
+ */
+ void getLocalData(double[] retVal, List<Integer> indLocal, List<Double> derLocal)
+ {
+
+ retVal[0] = theValue;
+ retVal[1] = thePrecision * theDownWeight;
+ indLocal = theParameters;
+ derLocal = theDerivatives;
+ }
+
+ void getLocalData(double[] retVal, int[] indLocal, double[] derLocal)
+ {
+
+ retVal[0] = theValue;
+ retVal[1] = thePrecision * theDownWeight;
+ indLocal = new int[theParameters.size()];
+ derLocal = new double[theParameters.size()];
+ for (int i = 0; i < theParameters.size(); ++i) {
+ indLocal[i] = theParameters.get(i);
+ derLocal[i] = theDerivatives.get(i);
+ }
+
+ }
+
+//
+///// Get all Data for MP-II binary record.
+///**
+// * \param [out] fValue Value
+// * \param [out] fErr Error
+// * \param [out] indLocal List of labels of local parameters
+// * \param [out] derLocal List of derivatives for local parameters
+// * \param [out] labGlobal List of labels of global parameters
+// * \param [out] derGlobal List of derivatives for global parameters
+// */
+//void getAllData(float &fValue, float &fErr,
+// std::vector<unsigned int>* &indLocal, std::vector<double>* &derLocal,
+// std::vector<int>* &labGlobal, std::vector<double>* &derGlobal) {
+// fValue = theValue;
+// fErr = 1.0 / sqrt(thePrecision);
+// indLocal = &theParameters;
+// derLocal = &theDerivatives;
+// labGlobal = &globalLabels;
+// derGlobal = &globalDerivatives;
+//}
+//
+///// Get data for residual (and errors).
+///**
+// * \param [out] aResidual Measurement-Prediction
+// * \param [out] aVariance Variance (of measurement)
+// * \param [out] aDownWeight Down-weighting factor
+// * \param [out] indLocal List of labels of used (local) fit parameters
+// * \param [out] derLocal List of derivatives for used (local) fit parameters
+// */
+//void getResidual(double &aResidual, double &aVariance,
+// double &aDownWeight, std::vector<unsigned int>* &indLocal,
+// std::vector<double>* &derLocal) {
+// aResidual = theValue - thePrediction;
+// aVariance = 1.0 / thePrecision;
+// aDownWeight = theDownWeight;
+// indLocal = &theParameters;
+// derLocal = &theDerivatives;
+//}
+}
java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/GblPoint.java 2014-08-28 08:14:53 UTC (rev 918)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/GblPoint.java 2014-08-28 15:31:06 UTC (rev 919)
@@ -1,22 +1,590 @@
package org.hps.recon.tracking.gbl;
-import hep.physics.matrix.BasicMatrix;
-import hep.physics.matrix.Matrix;
+import java.util.ArrayList;
+import java.util.List;
+import org.hps.recon.tracking.gbl.matrix.EigenvalueDecomposition;
+import org.hps.recon.tracking.gbl.matrix.Matrix;
+import org.hps.recon.tracking.gbl.matrix.SymMatrix;
+import org.hps.recon.tracking.gbl.matrix.Vector;
+/**
+ *
+ * @author phansson
+ * @author Norman A Graf
+ *
+ * @version $Id:
+ */
public class GblPoint {
- public GblPoint(BasicMatrix jacPointToPoint) {
- // TODO Auto-generated constructor stub
- }
+ public GblPoint(hep.physics.matrix.BasicMatrix jacPointToPoint) {
+ theLabel = 0;
+ theOffset = 0;
+ measDim = 0;
+ transFlag = false;
+ //measTransformation()
+ scatFlag = false;
+ //localDerivatives()
+ //globalLabels()
+ //globalDerivatives()
- public void addMeasurement(Matrix proL2m, BasicMatrix meas, BasicMatrix measPrec) {
- // TODO Auto-generated method stub
-
- }
+ for (int i = 0; i < 5; ++i) {
+ for (int j = 0; j < 5; ++j) {
+ p2pJacobian.set(i, j, jacPointToPoint.e(i, j));
+ }
+ }
+ }
- public void addScatterer(BasicMatrix scat, BasicMatrix scatPrec) {
- // TODO Auto-generated method stub
-
- }
+ public void addMeasurement(hep.physics.matrix.Matrix proL2m, hep.physics.matrix.BasicMatrix meas, hep.physics.matrix.BasicMatrix measPrec) {
+ int ncols = proL2m.getNColumns();
+ int nrows = proL2m.getNRows();
+ System.out.println("proL2m has "+nrows+" rows and "+ ncols+ "columns");
+ Matrix a = new Matrix(nrows, ncols);
+ for(int i=0; i<nrows; ++i)
+ {
+ for(int j=0; j<ncols; ++j)
+ {
+ a.set(i,j,proL2m.e(i, j));
+ }
+ }
+ System.out.println("GblPoint add matrix: ");
+ a.print(10, 6);
+
+
+
+ int measnrows = meas.getNRows();
+ int measncols = meas.getNColumns();
+ System.out.println("meas has "+measnrows+" rows and "+measncols+" columns");
+
+ Vector measvec = new Vector(measncols);
+ for(int i=0; i<measnrows; ++i)
+ {
+ measvec.set(i, meas.e(0, i));
+ }
+ System.out.println("GblPoint add meas: ");
+ measvec.print(10, 6);
+
+
+ int measPrecnrows = measPrec.getNRows();
+ int measPrecncols = measPrec.getNColumns();
+
+ System.out.println("measPrec has "+measPrecnrows+" rows and "+measPrecncols+" columns");
+ Vector measPrecvec = new Vector(measPrecncols);
+ for(int i=0; i<measPrecnrows; ++i)
+ {
+ measPrecvec.set(i, measPrec.e(0, i));
+ }
+ System.out.println("GblPoint add measPrec: ");
+ measPrecvec.print(10, 6);
+
+ addMeasurement(a, measvec, measPrecvec, 0.);
+ }
+
+ public void addScatterer(hep.physics.matrix.BasicMatrix scat, hep.physics.matrix.BasicMatrix scatPrec) {
+ // TODO Auto-generated method stub
+
+ }
+
+ private int theLabel; ///< Label identifying point
+ private int theOffset; ///< Offset number at point if not negative (else interpolation needed)
+ private Matrix p2pJacobian = new SymMatrix(5); ///< Point-to-point jacobian from previous point
+ private Matrix prevJacobian = new SymMatrix(5); ///< Jacobian to previous scatterer (or first measurement)
+ private Matrix nextJacobian = new SymMatrix(5); ///< Jacobian to next scatterer (or last measurement)
+ private int measDim; ///< Dimension of measurement (1-5), 0 indicates absence of measurement
+ private SymMatrix measProjection = new SymMatrix(5); ///< Projection from measurement to local system
+ private Vector measResiduals = new Vector(5); ///< Measurement residuals
+ private Vector measPrecision = new Vector(5); ///< Measurement precision (diagonal of inverse covariance matrix)
+ private boolean transFlag; ///< Transformation exists?
+ private Matrix measTransformation; ///< Transformation of diagonalization (of meas. precision matrix)
+ private boolean scatFlag; ///< Scatterer present?
+ private SymMatrix scatTransformation = new SymMatrix(2); ///< Transformation of diagonalization (of scat. precision matrix)
+ private Vector scatResiduals = new Vector(2); ///< Scattering residuals (initial kinks if iterating)
+ private Vector scatPrecision = new Vector(2); ///< Scattering precision (diagonal of inverse covariance matrix)
+ private Matrix localDerivatives = new Matrix(0, 0); ///< Derivatives of measurement vs additional local (fit) parameters
+ private List<Integer> globalLabels = new ArrayList<Integer>(); ///< Labels of global (MP-II) derivatives
+ private Matrix globalDerivatives = new Matrix(0, 0); ///< Derivatives of measurement vs additional global (MP-II) parameters
+
+/// Create a point.
+ /**
+ * Create point on (initial) trajectory. Needs transformation jacobian from
+ * previous point. \param [in] aJacobian Transformation jacobian from
+ * previous point
+ */
+ public GblPoint(Matrix aJacobian) {
+
+ theLabel = 0;
+ theOffset = 0;
+ measDim = 0;
+ transFlag = false;
+ //measTransformation()
+ scatFlag = false;
+ //localDerivatives()
+ //globalLabels()
+ //globalDerivatives()
+
+ for (int i = 0; i < 5; ++i) {
+ for (int j = 0; j < 5; ++j) {
+ p2pJacobian.set(i, j, aJacobian.get(i, j));
+ }
+ }
+ }
+
+ public GblPoint(SymMatrix aJacobian) {
+ theLabel = 0;
+ theOffset = 0;
+ p2pJacobian = new SymMatrix(aJacobian);
+ measDim = 0;
+ transFlag = false;
+ //measTransformation()
+ scatFlag = false;
+ //localDerivatives()
+ //globalLabels()
+ //globalDerivatives()
+
+ }
+
+/// Add a measurement to a point.
+ /**
+ * Add measurement (in meas. system) with diagonal precision (inverse
+ * covariance) matrix. ((up to) 2D: position, 4D: slope+position, 5D:
+ * curvature+slope+position) \param [in] aProjection Projection from local
+ * to measurement system \param [in] aResiduals Measurement residuals \param
+ * [in] aPrecision Measurement precision (diagonal) \param [in] minPrecision
+ * Minimal precision to accept measurement
+ */
+ public void addMeasurement(Matrix aProjection,
+ Vector aResiduals, Vector aPrecision,
+ double minPrecision) {
+ measDim = aResiduals.getRowDimension();
+ int iOff = 5 - measDim;
+ for (int i = 0; i < measDim; ++i) {
+ measResiduals.set(iOff + i, aResiduals.get(i));
+ measPrecision.set(iOff + i, (aPrecision.get(i) >= minPrecision ? aPrecision.get(i) : 0.));
+ for (int j = 0; j < measDim; ++j) {
+ measProjection.set(iOff + i, iOff + j, aProjection.get(i, j));
+ }
+ }
+ }
+/// Add a measurement to a point.
+
+ /**
+ * Add measurement (in meas. system) with arbitrary precision (inverse
+ * covariance) matrix. Will be diagonalized. ((up to) 2D: position, 4D:
+ * slope+position, 5D: curvature+slope+position) \param [in] aProjection
+ * Projection from local to measurement system \param [in] aResiduals
+ * Measurement residuals \param [in] aPrecision Measurement precision
+ * (matrix) \param [in] minPrecision Minimal precision to accept measurement
+ */
+ public void addMeasurement(Matrix aProjection,
+ Vector aResiduals, SymMatrix aPrecision,
+ double minPrecision) {
+ measDim = aResiduals.getRowDimension();
+ EigenvalueDecomposition measEigen = new EigenvalueDecomposition(aPrecision);
+ measTransformation.ResizeTo(measDim, measDim);
+ measTransformation = measEigen.getV();
+ measTransformation.transposeInPlace();
+ transFlag = true;
+ Vector transResiduals = measTransformation.times(aResiduals);
+ Vector transPrecision = new Vector(measEigen.getRealEigenvalues());
+ Matrix transProjection = measTransformation.times(aProjection);
+ int iOff = 5 - measDim;
+ for (int i = 0; i < measDim; ++i) {
+ measResiduals.set(iOff + i, transResiduals.get(i));
+ measPrecision.set(iOff + i, (transPrecision.get(i) >= minPrecision ? transPrecision.get(i) : 0.));
+ for (int j = 0; j < measDim; ++j) {
+ measProjection.set(iOff + i, iOff + j, transProjection.get(i, j));
+ }
+ }
+ }
+
+/// Add a measurement to a point.
+ /**
+ * Add measurement in local system with diagonal precision (inverse
+ * covariance) matrix. ((up to) 2D: position, 4D: slope+position, 5D:
+ * curvature+slope+position) \param [in] aResiduals Measurement residuals
+ * \param [in] aPrecision Measurement precision (diagonal) \param [in]
+ * minPrecision Minimal precision to accept measurement
+ */
+ public void addMeasurement(Vector aResiduals,
+ Vector aPrecision, double minPrecision) {
+ measDim = aResiduals.getRowDimension();
+ int iOff = 5 - measDim;
+ for (int i = 0; i < measDim; ++i) {
+ measResiduals.set(iOff + i, aResiduals.get(i));
+ measPrecision.set(iOff + i,
+ aPrecision.get(i) >= minPrecision ? aPrecision.get(i) : 0.);
+ }
+ measProjection.setToIdentity();
+ }
+
+/// Add a measurement to a point.
+ /**
+ * Add measurement in local system with arbitrary precision (inverse
+ * covariance) matrix. Will be diagonalized. ((up to) 2D: position, 4D:
+ * slope+position, 5D: curvature+slope+position) \param [in] aResiduals
+ * Measurement residuals \param [in] aPrecision Measurement precision
+ * (matrix) \param [in] minPrecision Minimal precision to accept measurement
+ */
+ public void addMeasurement(Vector aResiduals,
+ SymMatrix aPrecision, double minPrecision) {
+ measDim = aResiduals.getRowDimension();
+ EigenvalueDecomposition measEigen = new EigenvalueDecomposition(aPrecision);
+ measTransformation.ResizeTo(measDim, measDim);
+ measTransformation = measEigen.getV();
+ measTransformation.transposeInPlace();
+ transFlag = true;
+ Vector transResiduals = measTransformation.times(aResiduals);
+ Vector transPrecision = new Vector(measEigen.getRealEigenvalues());
+ int iOff = 5 - measDim;
+ for (int i = 0; i < measDim; ++i) {
+ measResiduals.set(iOff + i, transResiduals.get(i));
+ measPrecision.set(iOff + i, (transPrecision.get(i)) >= minPrecision ? transPrecision.get(i) : 0.);
+ for (int j = 0; j < measDim; ++j) {
+ measProjection.set(iOff + i, iOff + j, measTransformation.get(i, j));
+ }
+ }
+ }
+
+/// Check for measurement at a point.
+ /**
+ * Get dimension of measurement (0 = none). \return measurement dimension
+ */
+ int hasMeasurement() {
+ return measDim;
+ }
+
+/// Retrieve measurement of a point.
+ /**
+ * \param [out] aProjection Projection from (diagonalized) measurement to
+ * local system \param [out] aResiduals Measurement residuals \param [out]
+ * aPrecision Measurement precision (diagonal)
+ */
+ public void getMeasurement(SymMatrix aProjection, Vector aResiduals,
+ Vector aPrecision) {
+ aProjection = measProjection;
+ aResiduals = measResiduals;
+ aPrecision = measPrecision;
+ }
+
+/// Get measurement transformation (from diagonalization).
+ /**
+ * \param [out] aTransformation Transformation matrix
+ */
+ public void getMeasTransformation(Matrix aTransformation) {
+ aTransformation.ResizeTo(measDim, measDim);
+ if (transFlag) {
+ aTransformation = measTransformation;
+ } else {
+ aTransformation.UnitMatrix();
+ }
+ }
+
+/// Add a (thin) scatterer to a point.
+ /**
+ * Add scatterer with diagonal precision (inverse covariance) matrix.
+ * Changes local track direction.
+ *
+ * \param [in] aResiduals Scatterer residuals \param [in] aPrecision
+ * Scatterer precision (diagonal of inverse covariance matrix)
+ */
+ public void addScatterer(Vector aResiduals,
+ Vector aPrecision) {
+ scatFlag = true;
+ scatResiduals.set(0, aResiduals.get(0));
+ scatResiduals.set(1, aResiduals.get(1));
+ scatPrecision.set(0, aPrecision.get(0));
+ scatPrecision.set(1, aPrecision.get(1));
+ scatTransformation.setToIdentity();
+ }
+
+/// Add a (thin) scatterer to a point.
+ /**
+ * Add scatterer with arbitrary precision (inverse covariance) matrix. Will
+ * be diagonalized. Changes local track direction.
+ *
+ * The precision matrix for the local slopes is defined by the angular
+ * scattering error theta_0 and the scalar products c_1, c_2 of the offset
+ * directions in the local frame with the track direction:
+ *
+ * (1 - c_1*c_1 - c_2*c_2) | 1 - c_1*c_1 - c_1*c_2 | P =
+ * ~~~~~~~~~~~~~~~~~~~~~~~ * | | theta_0*theta_0 | - c_1*c_2 1 - c_2*c_2 |
+ *
+ * \param [in] aResiduals Scatterer residuals \param [in] aPrecision
+ * Scatterer precision (matrix)
+ */
+ public void addScatterer(Vector aResiduals,
+ SymMatrix aPrecision) {
+ scatFlag = true;
+ EigenvalueDecomposition scatEigen = new EigenvalueDecomposition(aPrecision);
+ Matrix aTransformation = scatEigen.getEigenVectors();
+ aTransformation.transposeInPlace();
+ Vector transResiduals = aTransformation.times(aResiduals);
+ Vector transPrecision = new Vector(scatEigen.getRealEigenvalues());
+ for (int i = 0; i < 2; ++i) {
+ scatResiduals.set(i, transResiduals.get(i));
+ scatPrecision.set(i, transPrecision.get(i));
+ for (int j = 0; j < 2; ++j) {
+ scatTransformation.set(i, j, aTransformation.get(i, j));
+ }
+ }
+ }
+
+/// Check for scatterer at a point.
+ boolean hasScatterer() {
+ return scatFlag;
+ }
+
+/// Retrieve scatterer of a point.
+ /**
+ * \param [out] aTransformation Scatterer transformation from
+ * diagonalization \param [out] aResiduals Scatterer residuals \param [out]
+ * aPrecision Scatterer precision (diagonal)
+ */
+ public void getScatterer(SymMatrix aTransformation, Vector aResiduals,
+ Vector aPrecision) {
+ aTransformation = scatTransformation;
+ aResiduals = scatResiduals;
+ aPrecision = scatPrecision;
+ }
+
+/// Get scatterer transformation (from diagonalization).
+ /**
+ * \param [out] aTransformation Transformation matrix
+ */
+ public void getScatTransformation(Matrix aTransformation) {
+ aTransformation.ResizeTo(2, 2);
+ if (scatFlag) {
+ for (int i = 0; i < 2; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ aTransformation.set(i, j, scatTransformation.get(i, j));
+ }
+ }
+ } else {
+ aTransformation.UnitMatrix();
+ }
+ }
+
+/// Add local derivatives to a point.
+ /**
+ * Point needs to have a measurement. \param [in] aDerivatives Local
+ * derivatives (matrix)
+ */
+ public void addLocals(Matrix aDerivatives) {
+ if (measDim != 0) {
+ localDerivatives.ResizeTo(aDerivatives.getRowDimension(), aDerivatives.getColumnDimension());
+ if (transFlag) {
+ localDerivatives = measTransformation.times(aDerivatives);
+ } else {
+ localDerivatives = aDerivatives;
+ }
+ }
+ }
+
+/// Retrieve number of local derivatives from a point.
+ int getNumLocals() {
+ return localDerivatives.getColumnDimension();
+ }
+
+/// Retrieve local derivatives from a point.
+ Matrix getLocalDerivatives() {
+ return localDerivatives;
+ }
+
+/// Add global derivatives to a point.
+ /**
+ * Point needs to have a measurement. \param [in] aLabels Global derivatives
+ * labels \param [in] aDerivatives Global derivatives (matrix)
+ */
+ public void addGlobals(List<Integer> aLabels,
+ Matrix aDerivatives) {
+ if (measDim != 0) {
+ globalLabels = aLabels;
+ globalDerivatives.ResizeTo(aDerivatives.getRowDimension(), aDerivatives.getColumnDimension());
+ if (transFlag) {
+ globalDerivatives = measTransformation.times(aDerivatives);
+ } else {
+ globalDerivatives = aDerivatives;
+ }
+
+ }
+ }
+
+/// Retrieve number of global derivatives from a point.
+ int getNumGlobals() {
+ return globalDerivatives.getColumnDimension();
+ }
+
+/// Retrieve global derivatives labels from a point.
+ List<Integer> getGlobalLabels() {
+ return globalLabels;
+ }
+
+/// Retrieve global derivatives from a point.
+ Matrix getGlobalDerivatives() {
+ return globalDerivatives;
+ }
+
+/// Define label of point (by GBLTrajectory constructor)
+ /**
+ * \param [in] aLabel Label identifying point
+ */
+ public void setLabel(int aLabel) {
+ theLabel = aLabel;
+ }
+
+/// Retrieve label of point
+ int getLabel() {
+ return theLabel;
+ }
+
+/// Define offset for point (by GBLTrajectory constructor)
+ /**
+ * \param [in] anOffset Offset number
+ */
+ public void setOffset(int anOffset) {
+ theOffset = anOffset;
+ }
+
+/// Retrieve offset for point
+ int getOffset() {
+ return theOffset;
+ }
+
+/// Retrieve point-to-(previous)point jacobian
+ Matrix getP2pJacobian() {
+ return p2pJacobian;
+ }
+
+/// Define jacobian to previous scatterer (by GBLTrajectory constructor)
+ /**
+ * \param [in] aJac Jacobian
+ */
+ public void addPrevJacobian(Matrix aJac) {
+ int ifail = 0;
+// to optimize: need only two last rows of inverse
+// prevJacobian = aJac.InverseFast(ifail);
+// block matrix algebra
+ Matrix CA = aJac.sub(2, 3, 3, 0).times(aJac.sub(3, 0, 0).inverse()); // C*A^-1
+ Matrix DCAB = aJac.sub(2, 3, 3).minus(CA.times(aJac.sub(3, 2, 0, 3))); // D - C*A^-1 *B
+ DCAB = DCAB.inverse();
+ prevJacobian.placeAt(DCAB, 3, 3);
+ prevJacobian.placeAt(DCAB.times(CA).uminus(), 3, 0);
+ }
+//
+/// Define jacobian to next scatterer (by GBLTrajectory constructor)
+
+ /**
+ * \param [in] aJac Jacobian
+ */
+ public void addNextJacobian(Matrix aJac) {
+ nextJacobian = aJac;
+ }
+
+/// Retrieve derivatives of local track model
+ /**
+ * Linearized track model: F_u(q/p,u',u) = J*u + S*u' + d*q/p, W is inverse
+ * of S, negated for backward propagation. \param [in] aDirection
+ * Propagation direction (>0 forward, else backward) \param [out] matW W
+ * \param [out] matWJ W*J \param [out] vecWd W*d \exception
+ * std::overflow_error : matrix S is singular.
+ */
+ public void getDerivatives(int aDirection, Matrix matW, Matrix matWJ,
+ Vector vecWd) {
+
+ Matrix matJ;
+ Vector vecd;
+ if (aDirection < 1) {
+ matJ = prevJacobian.sub(2, 3, 3);
+ matW = prevJacobian.sub(2, 3, 1).uminus();
+ vecd = prevJacobian.subCol(2, 0, 3);
+ } else {
+ matJ = nextJacobian.sub(2, 3, 3);
+ matW = nextJacobian.sub(2, 3, 1);
+ vecd = nextJacobian.subCol(2, 0, 3);
+ }
+
+ matW = matW.inverse();
+// if (!matW.InvertFast()) {
+// std::cout << " getDerivatives failed to invert matrix: "
+// << matW << "\n";
+// std::cout
+// << " Possible reason for singular matrix: multiple GblPoints at same arc-length"
+// << "\n";
+// throw std::overflow_error("Singular matrix inversion exception");
+// }
+ matWJ = matW.times(matJ);
+ vecWd = matW.times(vecd);
+
+ }
+//
+/// Print GblPoint
+
+ /**
+ * \param [in] level print level (0: minimum, >0: more)
+ */
+ public void printPoint(int level) {
+ StringBuffer sb = new StringBuffer("GblPoint");
+ if (theLabel != 0) {
+ sb.append(", label " + theLabel);
+ if (theOffset >= 0) {
+ sb.append(", offset " + theOffset);
+ }
+ }
+ if (measDim != 0) {
+ sb.append(", " + measDim + " measurements");
+ }
+ if (scatFlag) {
+ sb.append(", scatterer");
+ }
+ if (transFlag) {
+ sb.append(", diagonalized");
+ }
+ if (localDerivatives != null) {
+ sb.append(", " + localDerivatives.getColumnDimension()
+ + " local derivatives");
+ }
+ if (globalDerivatives != null) {
+ sb.append(", " + globalDerivatives.getColumnDimension()
+ + " global derivatives");
+ }
+ sb.append("\n");
+ if (level > 0) {
+ if (measDim != 0) {
+ sb.append(" Measurement" + "\n");
+ sb.append(" Projection: " + "\n" + measProjection
+ + "\n");
+ sb.append(" Residuals: " + measResiduals + "\n");
+ sb.append(" Precision: " + measPrecision + "\n");
+ }
+ if (scatFlag) {
+ sb.append(" Scatterer" + "\n");
+ sb.append(" Residuals: " + scatResiduals + "\n");
+ sb.append(" Precision: " + scatPrecision + "\n");
+ }
+ if (localDerivatives.getColumnDimension() != 0) {
+ sb.append(" Local Derivatives:" + "\n");
+ localDerivatives.print(4, 6);
+ }
+ if (globalDerivatives.getColumnDimension() != 0) {
+ sb.append(" Global Labels:");
+ for (int i = 0; i < globalLabels.size(); ++i) {
+ sb.append(" " + globalLabels.get(i));
+ }
+ sb.append("\n");
+ sb.append(" Global Derivatives:" + "\n");
+ globalDerivatives.print(4, 6);
+ }
+ sb.append(" Jacobian " + "\n");
+ sb.append(" Point-to-point " + "\n" + p2pJacobian
+ + "\n");
+ if (theLabel != 0) {
+ sb.append(" To previous offset " + "\n" + prevJacobian
+ + "\n");
+ sb.append(" To next offset " + "\n" + nextJacobian
+ + "\n");
+ }
+ }
+ System.out.println(sb.toString());
+ }
+
}
java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/GblTrajectory.java 2014-08-28 08:14:53 UTC (rev 918)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/GblTrajectory.java 2014-08-28 15:31:06 UTC (rev 919)
@@ -5,20 +5,28 @@
*
* @author Per Hansson Adrian <[log in to unmask]>
*
+ * @author Norman A Graf
+ *
+ * @version $Id:
+ *
*/
+import static java.lang.Math.max;
+import java.util.ArrayList;
import java.util.List;
+import org.hps.recon.tracking.gbl.matrix.BorderedBandMatrix;
+import org.hps.recon.tracking.gbl.matrix.Matrix;
+import org.hps.recon.tracking.gbl.matrix.SymMatrix;
+import org.hps.recon.tracking.gbl.matrix.VVector;
+import org.hps.recon.tracking.gbl.matrix.Vector;
+
public class GblTrajectory {
public GblTrajectory(List<GblPoint> listOfPoints) {
- // TODO Auto-generated constructor stub
+ this(listOfPoints, 0, new SymMatrix(0), false, false, false);
}
- public boolean isValid() {
- // TODO Auto-generated method stub
- return false;
- }
public void fit(double m_chi2, int m_ndf, int m_lost_weight) {
// TODO Auto-generated method stub
@@ -30,4 +38,1283 @@
}
+ /**
+ * \mainpage General information
+ *
+ * \section intro_sec Introduction
+ *
+ * For a track with an initial trajectory from a prefit of the measurements
+ * (internal seed) or an external prediction (external seed) the description
+ * of multiple scattering is added by offsets in a local system. Along the
+ * initial trajectory points are defined with can describe a measurement or
+ * a (thin) scatterer or both. Measurements are arbitrary functions of the
+ * local track parameters at a point (e.g. 2D: position, 4D:
+ * direction+position). The refit provides corrections to the local track
+ * parameters (in the local system) and the corresponding covariance matrix
+ * at any of those points. Non-diagonal covariance matrices will be
+ * diagonalized internally. Outliers can be down-weighted by use of
+ * M-estimators.
+ *
+ * The broken lines trajectory is defined by (2D) offsets at the first and
+ * last point and all points with a scatterer. The prediction for a
+ * measurement is obtained by interpolation of the enclosing offsets and for
+ * triplets of adjacent offsets kink angles are determined. This requires
+ * for all points the jacobians for propagation to the previous and next
+ * offset. These are calculated from the point-to-point jacobians along the
+ * initial trajectory. The sequence of points has to be strictly monotonic
+ * in arc-length.
+ *
+ * Additional local or global parameters can be added and the trajectories
+ * can be written to special binary files for calibration and alignment with
+ * Millepede-II. (V. Blobel, NIM A, 566 (2006), pp. 5-13).
+ *
+ * Besides simple trajectories describing the path of a single particle
+ * composed trajectories are supported. These are constructed from the
+ * trajectories of multiple particles and some external parameters (like
+ * those describing a decay) and transformations at the first points from
+ * the external to the local track parameters.
+ *
+ * The conventions for the coordinate systems follow: Derivation of
+ * Jacobians for the propagation of covariance matrices of track parameters
+ * in homogeneous magnetic fields A. Strandlie, W. Wittek, NIM A, 566 (2006)
+ * 687-698.
+ *
+ * \section call_sec Calling sequence
+ *
+ * -# Create list of points on initial trajectory:\n
+ * <tt>List<GblPoint> list</tt>
+ * -# For all points on initial trajectory: - Create points and add
+ * appropriate attributes:\n - <tt>point = gbl::GblPoint(..)</tt>
+ * - <tt>point.addMeasurement(..)</tt>
+ * - Add additional local or global parameters to measurement:\n -
+ * <tt>point.addLocals(..)</tt>
+ * - <tt>point.addGlobals(..)</tt>
+ * - <tt>point.addScatterer(..)</tt>
+ * - Add point (ordered by arc length) to list:\n
+ * <tt>list.add(point)</tt>
+ * -# Create (simple) trajectory from list of points:\n
+ * <tt>traj = gbl::GblTrajectory (list)</tt>
+ * -# Optionally with external seed:\n
+ * <tt>traj = gbl::GblTrajectory (list,seed)</tt>
+ * -# Optionally check validity of trajectory:\n
+ * <tt>if (not traj.isValid()) .. //abort</tt>
+ * -# Fit trajectory, return error code, get Chi2, Ndf (and weight lost by
+ * M-estimators):\n
+ * <tt>ierr = traj.fit(..)</tt>
+ * -# For any point on initial trajectory: - Get corrections and covariance
+ * matrix for track parameters:\n
+ * <tt>[..] = traj.getResults(label)</tt>
+ * -# Optionally write trajectory to MP binary file:\n
+ * <tt>traj.milleOut(..)</tt>
+ *
+ * \section loc_sec Local system and local parameters At each point on the
+ * trajectory a local coordinate system with local track parameters has to
+ * be defined. The first of the five parameters describes the bending, the
+ * next two the direction and the last two the position (offsets). The
+ * curvilinear system (T,U,V) with parameters (q/p, lambda, phi, x_t, y_t)
+ * is well suited.
+ *
+ * \section impl_sec Implementation
+ *
+ * Matrices are implemented with ROOT (root.cern.ch). User input or output
+ * is in the form of TMatrices. Internally SMatrices are used for fixes
+ * sized and simple matrices based on List<> for variable sized matrices.
+ *
+ * \section ref_sec References - V. Blobel, C. Kleinwort, F. Meier, Fast
+ * alignment of a complex tracking detector using advanced track models,
+ * Computer Phys. Communications (2011), doi:10.1016/j.cpc.2011.03.017 - C.
+ * Kleinwort, General Broken Lines as advanced track fitting method, NIM A,
+ * 673 (2012), 107-110, doi:10.1016/j.nima.2012.01.024
+ */
+ int numAllPoints; ///< Number of all points on trajectory
+ List< Integer> numPoints = new ArrayList<Integer>(); ///< Number of points on (sub)trajectory
+ int numTrajectories; ///< Number of trajectories (in composed trajectory)
+ int numOffsets; ///< Number of (points with) offsets on trajectory
+ int numInnerTrans; ///< Number of inner transformations to external parameters
+ int numCurvature; ///< Number of curvature parameters (0 or 1) or external parameters
+ int numParameters; ///< Number of fit parameters
+ int numLocals; ///< Total number of (additional) local parameters
+ int numMeasurements; ///< Total number of measurements
+ int externalPoint; ///< Label of external point (or 0)
+ boolean constructOK; ///< Trajectory has been successfully constructed (ready for fit/output)
+ boolean fitOK; ///< Trajectory has been successfully fitted (results are valid)
+ List< Integer> theDimension = new ArrayList<Integer>(); ///< List of active dimensions (0=u1, 1=u2) in fit
+ List<List<GblPoint>> thePoints = new ArrayList<List<GblPoint>>(); ///< (list of) List of points on trajectory
+ List<GblData> theData = new ArrayList<GblData>(); ///< List of data blocks
+ List<Integer> measDataIndex = new ArrayList<Integer>(); ///< mapping points to data blocks from measurements
+ List<Integer> scatDataIndex; ///< mapping points to data blocks from scatterers
+ List<Integer> externalIndex; ///< List of fit parameters used by external seed
+ SymMatrix externalSeed; ///< Precision (inverse covariance matrix) of external seed
+ List<Matrix> innerTransformations; ///< Transformations at innermost points of
+ // composed trajectory (from common external parameters)
+ Matrix externalDerivatives; // Derivatives for external measurements of composed trajectory
+ Vector externalMeasurements; // Residuals for external measurements of composed trajectory
+ Vector externalPrecisions; // Precisions for external measurements of composed trajectory
+ VVector theVector; ///< Vector of linear equation system
+ BorderedBandMatrix theMatrix = new BorderedBandMatrix(); ///< (Bordered band) matrix of linear equation system
+
+///// Create new (simple) trajectory from list of points.
+// /**
+// * Curved trajectory in space (default) or without curvature (q/p) or in one
+// * plane (u-direction) only. \param [in] aPointList List of points \param
+// * [in] flagCurv Use q/p \param [in] flagU1dir Use in u1 direction \param
+// * [in] flagU2dir Use in u2 direction
+// */
+// GblTrajectory(List<GblPoint> aPointList,
+// boolean flagCurv, boolean flagU1dir, boolean flagU2dir)
+// {
+// numAllPoints = aPointList.size();
+// //numPoints()
+// numOffsets = 0;
+// numInnerTrans = 0;
+// numCurvature = (flagCurv ? 1 : 0);
+// numParameters = 0;
+// numLocals = 0;
+// numMeasurements = 0;
+// externalPoint = 0;
+// //externalSeed()
+// //innerTransformations()
+// //externalDerivatives()
+// //externalMeasurements()
+// // externalPrecisions()
+//
+// if (flagU1dir)
+// {
+// theDimension.add(0);
+// }
+// if (flagU2dir)
+// {
+// theDimension.add(1);
+// }
+// // simple (single) trajectory
+// thePoints.add(aPointList);
+// numPoints.add(numAllPoints);
+//// construct(); // construct trajectory
+// }
+/// Create new (simple) trajectory from list of points with external seed.
+ /**
+ * Curved trajectory in space (default) or without curvature (q/p) or in one
+ * plane (u-direction) only. \param [in] aPointList List of points \param
+ * [in] aLabel (Signed) label of point for external seed (<0: in front, >0:
+ * after point, slope changes at scatterer!) \param [in] aSeed Precision
+ * matrix of external seed \param [in] flagCurv Use q/p \param [in]
+ * flagU1dir Use in u1 direction \param [in] flagU2dir Use in u2 direction
+ */
+ GblTrajectory(List<GblPoint> aPointList,
+ int aLabel, SymMatrix aSeed, boolean flagCurv,
+ boolean flagU1dir, boolean flagU2dir)
+ {
+ numAllPoints = aPointList.size();
+ //numPoints(),
+ numOffsets = 0;
+ numInnerTrans = 0;
+ numCurvature = (flagCurv ? 1 : 0);
+ numParameters = 0;
+ numLocals = 0;
+ numMeasurements = 0;
+ //externalPoint(aLabel)
+ //theDimension(),
+ //thePoints(),
+ //theData(),
+ //measDataIndex(),
+ //scatDataIndex(),
+ //externalIndex(),
+ //externalSeed(aSeed),
+ //innerTransformations(),
+ //externalDerivatives(),
+ //externalMeasurements(),
+ //externalPrecisions() {
+
+ if (flagU1dir)
+ {
+ theDimension.add(0);
+ }
+ if (flagU2dir)
+ {
+ theDimension.add(1);
+ }
+ // simple (single) trajectory
+ thePoints.add(aPointList);
+ numPoints.add(numAllPoints);
+ construct(); // construct trajectory
+ }
+
+///// Create new composed trajectory from list of points and transformations.
+///**
+// * Composed of curved trajectory in space.
+// * \param [in] aPointsAndTransList List containing pairs with list of points and transformation (at inner (first) point)
+// */
+//GblTrajectory(
+// const List<std::pair<List<GblPoint>, TMatrixD> > &aPointsAndTransList) :
+// numAllPoints(), numPoints(), numOffsets(0), numInnerTrans(
+// aPointsAndTransList.size()), numParameters(0), numLocals(0), numMeasurements(
+// 0), externalPoint(0), theDimension(0), thePoints(), theData(), measDataIndex(), scatDataIndex(), externalIndex(), externalSeed(), innerTransformations(), externalDerivatives(), externalMeasurements(), externalPrecisions() {
+//
+// for ( int iTraj = 0; iTraj < aPointsAndTransList.size(); ++iTraj) {
+// thePoints.add(aPointsAndTransList[iTraj].first);
+// numPoints.add(thePoints.back().size());
+// numAllPoints += numPoints.back();
+// innerTransformations.add(aPointsAndTransList[iTraj].second);
+// }
+// theDimension.add(0);
+// theDimension.add(1);
+// numCurvature = innerTransformations[0].GetNcols();
+// construct(); // construct (composed) trajectory
+//}
+//
+///// Create new composed trajectory from list of points and transformations with (independent) external measurements.
+///**
+// * Composed of curved trajectory in space.
+// * \param [in] aPointsAndTransList List containing pairs with list of points and transformation (at inner (first) point)
+// * \param [in] extDerivatives Derivatives of external measurements vs external parameters
+// * \param [in] extMeasurements External measurements (residuals)
+// * \param [in] extPrecisions Precision of external measurements
+// */
+//GblTrajectory(
+// const List<std::pair<List<GblPoint>, TMatrixD> > &aPointsAndTransList,
+// const TMatrixD &extDerivatives, const TVectorD &extMeasurements,
+// const TVectorD &extPrecisions) :
+// numAllPoints(), numPoints(), numOffsets(0), numInnerTrans(
+// aPointsAndTransList.size()), numParameters(0), numLocals(0), numMeasurements(
+// 0), externalPoint(0), theDimension(0), thePoints(), theData(), measDataIndex(), scatDataIndex(), externalIndex(), externalSeed(), innerTransformations(), externalDerivatives(
+// extDerivatives), externalMeasurements(extMeasurements), externalPrecisions(
+// extPrecisions) {
+//
+// for ( int iTraj = 0; iTraj < aPointsAndTransList.size(); ++iTraj) {
+// thePoints.add(aPointsAndTransList[iTraj].first);
+// numPoints.add(thePoints.back().size());
+// numAllPoints += numPoints.back();
+// innerTransformations.add(aPointsAndTransList[iTraj].second);
+// }
+// theDimension.add(0);
+// theDimension.add(1);
+// numCurvature = innerTransformations[0].GetNcols();
+// construct(); // construct (composed) trajectory
+//}
+//
+//~GblTrajectory() {
+//}
+//
+/// Retrieve validity of trajectory
+ boolean isValid()
+ {
+ return constructOK;
+ }
+
+/// Retrieve number of point from trajectory
+ int getNumPoints()
+ {
+ return numAllPoints;
+ }
+
+/// Construct trajectory from list of points.
+ /**
+ * Trajectory is prepared for fit or output to binary file, may consists of
+ * sub-trajectories.
+ */
+ void construct()
+ {
+
+ constructOK = false;
+ fitOK = false;
+ int aLabel = 0;
+ // loop over trajectories
+ numTrajectories = thePoints.size();
+ //std::cout << " numTrajectories: " << numTrajectories << ", "<< innerTransformations.size() << std::endl;
+// for ( int iTraj = 0; iTraj < numTrajectories; ++iTraj) {
+// List<GblPoint>::iterator itPoint;
+// for (itPoint = thePoints[iTraj].begin();
+// itPoint < thePoints[iTraj].end(); ++itPoint) {
+// numLocals = std::max(numLocals, itPoint->getNumLocals());
+// numMeasurements += itPoint->hasMeasurement();
+// itPoint->setLabel(++aLabel);
+// }
+// }
+ for (List<GblPoint> list : thePoints)
+ {
+ for (GblPoint p : list)
+ {
+ numLocals = max(numLocals, p.getNumLocals());
+ numMeasurements += p.hasMeasurement();
+ p.setLabel(++aLabel);
+ }
+ }
+ defineOffsets();
+ calcJacobians();
+// try {
+ prepare();
+// } catch (std::overflow_error &e) {
+// std::cout << " GblTrajectory construction failed: " << e.what()
+// << std::endl;
+// return;
+// }
+ constructOK = true;
+ // number of fit parameters
+ numParameters = (numOffsets - 2 * numInnerTrans) * theDimension.size()
+ + numCurvature + numLocals;
+ }
+//
+/// Define offsets from list of points.
+
+ /**
+ * Define offsets at points with scatterers and first and last point. All
+ * other points need interpolation from adjacent points with offsets.
+ */
+ void defineOffsets()
+ {
+
+ // loop over trajectories
+ for (int iTraj = 0; iTraj < numTrajectories; ++iTraj)
+ {
+ List<GblPoint> list = thePoints.get(iTraj);
+ int size = list.size();
+ // first point is offset
+// thePoints[iTraj].front().setOffset(numOffsets++);
+ list.get(0).setOffset(numOffsets++); // intermediate scatterers are offsets
+// List<GblPoint>::iterator itPoint;
+// for (itPoint = thePoints[iTraj].begin() + 1;
+// itPoint < thePoints[iTraj].end() - 1; ++itPoint) {
+// if (itPoint->hasScatterer()) {
+// itPoint->setOffset(numOffsets++);
+// } else {
+// itPoint->setOffset(-numOffsets);
+// }
+// }
+ for (int i = 1; i < size - 1; ++i)
+ {
+ GblPoint p = list.get(i);
+ if (p.hasScatterer())
+ {
+ p.setOffset(numOffsets++);
+ } else
+ {
+ p.setOffset(-numOffsets);
+ }
+
+ }
+ // last point is offset
+// thePoints[iTraj].back().setOffset(numOffsets++);
+ list.get(size - 1).setOffset(numOffsets++);
+ }
+ }
+
+/// Calculate Jacobians to previous/next scatterer from point to point ones.
+ void calcJacobians()
+ {
+
+ Matrix scatJacobian = new Matrix(5, 5);
+ // loop over trajectories
+ for (int iTraj = 0; iTraj < numTrajectories; ++iTraj)
+ {
+ List<GblPoint> list = thePoints.get(iTraj);
+ int size = list.size();
+ // forward propagation (all)
+ GblPoint previousPoint = list.get(0);
+ int numStep = 0;
+ for (int i = 1; i < size; ++i)
+ {
+ GblPoint p = list.get(i);
+ if (numStep == 0)
+ {
+ scatJacobian = p.getP2pJacobian();
+ } else
+ {
+ scatJacobian = p.getP2pJacobian().times(scatJacobian);
+ }
+ numStep++;
+ p.addPrevJacobian(scatJacobian);// iPoint -> previous scatterer
+ if (p.getOffset() >= 0)
+ {
+ previousPoint.addNextJacobian(scatJacobian); // lastPoint -> next scatterer
+ numStep = 0;
+ previousPoint = p;
+ }
+ }
+// List<GblPoint>::iterator itPoint;
+// for (itPoint = thePoints[iTraj].begin() + 1;
+// itPoint < thePoints[iTraj].end(); ++itPoint)
+// {
+// if (numStep == 0)
+// {
+// scatJacobian = itPoint -> getP2pJacobian();
+// } else
+// {
+// scatJacobian = itPoint -> getP2pJacobian() * scatJacobian;
+// }
+// numStep++;
+// itPoint -> addPrevJacobian(scatJacobian); // iPoint -> previous scatterer
+// if (itPoint -> getOffset() >= 0)
+// {
+// previousPoint -> addNextJacobian(scatJacobian); // lastPoint -> next scatterer
+// numStep = 0;
+// previousPoint = & ( * itPoint);
+// }
+// }
+// // backward propagation (without scatterers)
+// for (itPoint = thePoints[iTraj].end() - 1;
+// itPoint > thePoints[iTraj].begin(); --itPoint)
+// {
+// if (itPoint -> getOffset() >= 0)
+// {
+// scatJacobian = itPoint -> getP2pJacobian();
+// continue; // skip offsets
+// }
+// itPoint -> addNextJacobian(scatJacobian); // iPoint -> next scatterer
+// scatJacobian = scatJacobian * itPoint -> getP2pJacobian();
+// }
+ // backward propagation (without scatterers)
+ for (int i = size - 1; i > 0; --i)
+ {
+ GblPoint p = list.get(i);
+ if (p.getOffset() >= 0)
+ {
+ scatJacobian = p.getP2pJacobian();
+ continue; // skip offsets
+ }
+ p.addNextJacobian(scatJacobian); // iPoint -> next scatterer
+ scatJacobian = scatJacobian.times(p.getP2pJacobian());
+ }
+ }
+ }
+//
+///// Get jacobian for transformation from fit to track parameters at point.
+///**
+// * Jacobian broken lines (q/p,..,u_i,u_i+1..) to track (q/p,u',u) parameters
+// * including additional local parameters.
+// * \param [in] aSignedLabel (Signed) label of point for external seed
+// * (<0: in front, >0: after point, slope changes at scatterer!)
+// * \return List of fit parameters with non zero derivatives and
+// * corresponding transformation matrix
+// */
+//std::pair<List< int>, TMatrixD> getJacobian(
+// int aSignedLabel) const {
+//
+// int nDim = theDimension.size();
+// int nCurv = numCurvature;
+// int nLocals = numLocals;
+// int nBorder = nCurv + nLocals;
+// int nParBRL = nBorder + 2 * nDim;
+// int nParLoc = nLocals + 5;
+// List< int> anIndex;
+// anIndex.reserve(nParBRL);
+// TMatrixD aJacobian(nParLoc, nParBRL);
+// aJacobian.Zero();
+//
+// int aLabel = abs(aSignedLabel);
+// int firstLabel = 1;
+// int lastLabel = 0;
+// int aTrajectory = 0;
+// // loop over trajectories
+// for ( int iTraj = 0; iTraj < numTrajectories; ++iTraj) {
+// aTrajectory = iTraj;
+// lastLabel += numPoints[iTraj];
+// if (aLabel <= lastLabel)
+// break;
+// if (iTraj < numTrajectories - 1)
+// firstLabel += numPoints[iTraj];
+// }
+// int nJacobian; // 0: prev, 1: next
+// // check consistency of (index, direction)
+// if (aSignedLabel > 0) {
+// nJacobian = 1;
+// if (aLabel >= lastLabel) {
+// aLabel = lastLabel;
+// nJacobian = 0;
+// }
+// } else {
+// nJacobian = 0;
+// if (aLabel <= firstLabel) {
+// aLabel = firstLabel;
+// nJacobian = 1;
+// }
+// }
+// const GblPoint aPoint = thePoints[aTrajectory][aLabel - firstLabel];
+// List< int> labDer(5);
+// SMatrix55 matDer;
+// getFitToLocalJacobian(labDer, matDer, aPoint, 5, nJacobian);
+//
+// // from local parameters
+// for ( int i = 0; i < nLocals; ++i) {
+// aJacobian(i + 5, i) = 1.0;
+// anIndex.add(i + 1);
+// }
+// // from trajectory parameters
+// int iCol = nLocals;
+// for ( int i = 0; i < 5; ++i) {
+// if (labDer[i] > 0) {
+// anIndex.add(labDer[i]);
+// for ( int j = 0; j < 5; ++j) {
+// aJacobian(j, iCol) = matDer(j, i);
+// }
+// ++iCol;
+// }
+// }
+// return std::make_pair(anIndex, aJacobian);
+//}
+
+/// Get (part of) jacobian for transformation from (trajectory) fit to track parameters at point.
+ /**
+ * Jacobian broken lines (q/p,..,u_i,u_i+1..) to local (q/p,u',u)
+ * parameters. \param [out] anIndex List of fit parameters with non zero
+ * derivatives \param [out] aJacobian Corresponding transformation matrix
+ * \param [in] aPoint Point to use \param [in] measDim Dimension of
+ * 'measurement' (<=2: calculate only offset part, >2: complete matrix)
+ * \param [in] nJacobian Direction (0: to previous offset, 1: to next
+ * offset)
+ */
+ void getFitToLocalJacobian(List<Integer> anIndex,
+ Matrix aJacobian, GblPoint aPoint, int measDim,
+ int nJacobian)
+ {
+
+ int nDim = theDimension.size();
+ int nCurv = numCurvature;
+ int nLocals = numLocals;
+
+ int nOffset = aPoint.getOffset();
+
+ if (nOffset < 0) // need interpolation
+ {
+ Matrix prevW = new Matrix(2, 2);
+ Matrix prevWJ = new Matrix(2, 2);
+ Matrix nextW = new Matrix(2, 2);
+ Matrix nextWJ = new Matrix(2, 2);
+ Matrix matN = new Matrix(2, 2);
+ Vector prevWd = new Vector(2);
+ Vector nextWd = new Vector(2);
+ int ierr;
+ aPoint.getDerivatives(0, prevW, prevWJ, prevWd); // W-, W- * J-, W- * d-
+ aPoint.getDerivatives(1, nextW, nextWJ, nextWd); // W-, W- * J-, W- * d-
+ Matrix sumWJ = prevWJ.plus(nextWJ);
+//? matN = sumWJ.inverse(ierr); // N = (W- * J- + W+ * J+)^-1
+ // derivatives for u_int
+ Matrix prevNW = matN.times(prevW); // N * W-
+ Matrix nextNW = matN.times(nextW); // N * W+
+ Vector prevNd = matN.times(prevWd); // N * W- * d-
+ Vector nextNd = matN.times(nextWd); // N * W+ * d+
+
+ int iOff = nDim * (-nOffset - 1) + nLocals + nCurv + 1; // first offset ('i' in u_i)
+
+ // local offset
+ if (nCurv > 0)
+ {
+ Vector negDiff = prevNd.minus(nextNd).uminus();
+ aJacobian.placeInCol(negDiff, 3, 0); // from curvature
+ anIndex.set(0, nLocals + 1);
+ }
+ aJacobian.placeAt(prevNW, 3, 1); // from 1st Offset
+ aJacobian.placeAt(nextNW, 3, 3); // from 2nd Offset
+ for (int i = 0; i < nDim; ++i)
+ {
+ anIndex.set(1 + theDimension.get(i), iOff + i);
+ anIndex.set(3 + theDimension.get(i), iOff + nDim + i);
+ }
+//
+//// // local slope and curvature
+//// if (measDim > 2) {
+//// // derivatives for u'_int
+//// const SMatrix22 prevWPN(nextWJ * prevNW); // W+ * J+ * N * W-
+//// const SMatrix22 nextWPN(prevWJ * nextNW); // W- * J- * N * W+
+//// const SVector2 prevWNd(nextWJ * prevNd); // W+ * J+ * N * W- * d-
+//// const SVector2 nextWNd(prevWJ * nextNd); // W- * J- * N * W+ * d+
+//// if (nCurv > 0) {
+//// aJacobian(0, 0) = 1.0;
+//// aJacobian.Place_in_col(prevWNd - nextWNd, 1, 0); // from curvature
+//// }
+//// aJacobian.Place_at(-prevWPN, 1, 1); // from 1st Offset
+//// aJacobian.Place_at(nextWPN, 1, 3); // from 2nd Offset
+//// }
+// } else { // at point
+ // anIndex must be sorted
+ // forward : iOff2 = iOff1 + nDim, index1 = 1, index2 = 3
+ // backward: iOff2 = iOff1 - nDim, index1 = 3, index2 = 1
+ int iOff1 = nDim * nOffset + nCurv + nLocals + 1; // first offset ('i' in u_i)
+ int index1 = 3 - 2 * nJacobian; // index of first offset
+ int iOff2 = iOff1 + nDim * (nJacobian * 2 - 1); // second offset ('i' in u_i)
+ int index2 = 1 + 2 * nJacobian; // index of second offset
+ // local offset
+ aJacobian.set(3, index1, 1.0); // from 1st Offset
+ aJacobian.set(4, index1 + 1, 1.0);
+ for (int i = 0; i < nDim; ++i)
+ {
+ anIndex.set(index1 + theDimension.get(i), iOff1 + i);
+ }
+
+ // local slope and curvature
+ if (measDim > 2)
+ {
+ Matrix matW = new Matrix(2, 2);
+ Matrix matWJ = new Matrix(2, 2);
+ Vector vecWd = new Vector(2);
+ aPoint.getDerivatives(nJacobian, matW, matWJ, vecWd); // W, W * J, W * d
+ double sign = (nJacobian > 0) ? 1. : -1.;
+ if (nCurv > 0)
+ {
+ aJacobian.set(0, 0, 1.0);
+ aJacobian.placeInCol(vecWd.timesScalar(-sign), 1, 0); // from curvature
+ anIndex.set(0, nLocals + 1);
+ }
+ aJacobian.placeAt(matWJ.times(-sign), 1, index1); // from 1st Offset
+ aJacobian.placeAt(matW.times(sign), 1, index2); // from 2nd Offset
+ for (int i = 0; i < nDim; ++i)
+ {
+ anIndex.set(index2 + theDimension.get(i), iOff2 + i);
+ }
+ }
+ }
+ }
+
+/// Get jacobian for transformation from (trajectory) fit to kink parameters at point.
+ /**
+ * Jacobian broken lines (q/p,..,u_i-1,u_i,u_i+1..) to kink (du')
+ * parameters. \param [out] anIndex List of fit parameters with non zero
+ * derivatives \param [out] aJacobian Corresponding transformation matrix
+ * \param [in] aPoint Point to use
+ */
+ void getFitToKinkJacobian(List< Integer> anIndex,
+ Matrix aJacobian, GblPoint aPoint)
+ {
+
+ //nb aJacobian has dimension 2,7
+ int nDim = theDimension.size();
+ int nCurv = numCurvature;
+ int nLocals = numLocals;
+
+ int nOffset = aPoint.getOffset();
+
+ Matrix prevW = new Matrix(2, 2);
+ Matrix prevWJ = new Matrix(2, 2);
+ Matrix nextW = new Matrix(2, 2);
+ Matrix nextWJ = new Matrix(2, 2);
+ Vector prevWd = new Vector(2);
+ Vector nextWd = new Vector(2);
+ aPoint.getDerivatives(0, prevW, prevWJ, prevWd); // W-, W- * J-, W- * d-
+ aPoint.getDerivatives(1, nextW, nextWJ, nextWd); // W-, W- * J-, W- * d-
+ Matrix sumWJ = prevWJ.plus(nextWJ); // W- * J- + W+ * J+
+ Vector sumWd = prevWd.plus(nextWd); // W+ * d+ + W- * d-
+
+ int iOff = (nOffset - 1) * nDim + nCurv + nLocals + 1; // first offset ('i' in u_i)
+
+ // local offset
+ if (nCurv > 0)
+ {
+ aJacobian.placeInCol(sumWd.uminus(), 0, 0); // from curvature
+ anIndex.set(0, nLocals + 1);
+ }
+ aJacobian.placeAt(prevW, 0, 1); // from 1st Offset
+ aJacobian.placeAt(sumWJ.uminus(), 0, 3); // from 2nd Offset
+ aJacobian.placeAt(nextW, 0, 5); // from 1st Offset
+ for (int i = 0; i < nDim; ++i)
+ {
+ anIndex.set(1 + theDimension.get(i), iOff + i);
+ anIndex.set(3 + theDimension.get(i), iOff + nDim + i);
+ anIndex.set(5 + theDimension.get(i), iOff + nDim * 2 + i);
+ }
+ }
+
+///// Get fit results at point.
+///**
+// * Get corrections and covariance matrix for local track and additional parameters
+// * in forward or backward direction.
+// * \param [in] aSignedLabel (Signed) label of point on trajectory
+// * (<0: in front, >0: after point, slope changes at scatterer!)
+// * \param [out] localPar Corrections for local parameters
+// * \param [out] localCov Covariance for local parameters
+// * \return error code (non-zero if trajectory not fitted successfully)
+// */
+// int getResults(int aSignedLabel, TVectorD &localPar,
+// SymMatrix &localCov) const {
+// if (! fitOK)
+// return 1;
+// std::pair<List< int>, TMatrixD> indexAndJacobian =
+// getJacobian(aSignedLabel);
+// int nParBrl = indexAndJacobian.first.size();
+// TVectorD aVec(nParBrl); // compressed vector
+// for ( int i = 0; i < nParBrl; ++i) {
+// aVec[i] = theVector(indexAndJacobian.first[i] - 1);
+// }
+// SymMatrix aMat = theMatrix.getBlockMatrix(indexAndJacobian.first); // compressed matrix
+// localPar = indexAndJacobian.second * aVec;
+// localCov = aMat.Similarity(indexAndJacobian.second);
+// return 0;
+//}
+//
+///// Get residuals at point from measurement.
+///**
+// * Get (diagonalized) residual, error of measurement and residual and down-weighting
+// * factor for measurement at point
+// *
+// * \param [in] aLabel Label of point on trajectory
+// * \param [out] numData Number of data blocks from measurement at point
+// * \param [out] aResiduals Measurements-Predictions
+// * \param [out] aMeasErrors Errors of Measurements
+// * \param [out] aResErrors Errors of Residuals (including correlations from track fit)
+// * \param [out] aDownWeights Down-Weighting factors
+// * \return error code (non-zero if trajectory not fitted successfully)
+// */
+// int getMeasResults( int aLabel,
+// int &numData, TVectorD &aResiduals, TVectorD &aMeasErrors,
+// TVectorD &aResErrors, TVectorD &aDownWeights) {
+// numData = 0;
+// if (! fitOK)
+// return 1;
+//
+// int firstData = measDataIndex[aLabel - 1]; // first data block with measurement
+// numData = measDataIndex[aLabel] - firstData; // number of data blocks
+// for ( int i = 0; i < numData; ++i) {
+// getResAndErr(firstData + i, aResiduals[i], aMeasErrors[i],
+// aResErrors[i], aDownWeights[i]);
+// }
+// return 0;
+//}
+//
+///// Get (kink) residuals at point from scatterer.
+///**
+// * Get (diagonalized) residual, error of measurement and residual and down-weighting
+// * factor for scatterering kinks at point
+// *
+// * \param [in] aLabel Label of point on trajectory
+// * \param [out] numData Number of data blocks from scatterer at point
+// * \param [out] aResiduals (kink)Measurements-(kink)Predictions
+// * \param [out] aMeasErrors Errors of (kink)Measurements
+// * \param [out] aResErrors Errors of Residuals (including correlations from track fit)
+// * \param [out] aDownWeights Down-Weighting factors
+// * \return error code (non-zero if trajectory not fitted successfully)
+// */
+// int getScatResults( int aLabel,
+// int &numData, TVectorD &aResiduals, TVectorD &aMeasErrors,
+// TVectorD &aResErrors, TVectorD &aDownWeights) {
+// numData = 0;
+// if (! fitOK)
+// return 1;
+//
+// int firstData = scatDataIndex[aLabel - 1]; // first data block with scatterer
+// numData = scatDataIndex[aLabel] - firstData; // number of data blocks
+// for ( int i = 0; i < numData; ++i) {
+// getResAndErr(firstData + i, aResiduals[i], aMeasErrors[i],
+// aResErrors[i], aDownWeights[i]);
+// }
+// return 0;
+//}
+//
+///// Get (list of) labels of points on (simple) trajectory
+///**
+// * \param [out] aLabelList List of labels (aLabelList[i] = i+1)
+// */
+//void getLabels(List< int> &aLabelList) {
+// int aLabel = 0;
+// int nPoint = thePoints[0].size();
+// aLabelList.resize(nPoint);
+// for ( i = 0; i < nPoint; ++i) {
+// aLabelList[i] = ++aLabel;
+// }
+//}
+//
+///// Get (list of lists of) labels of points on (composed) trajectory
+///**
+// * \param [out] aLabelList List of of lists of labels
+// */
+//void getLabels(
+// List<List< int> > &aLabelList) {
+// int aLabel = 0;
+// aLabelList.resize(numTrajectories);
+// for ( int iTraj = 0; iTraj < numTrajectories; ++iTraj) {
+// int nPoint = thePoints[iTraj].size();
+// aLabelList[iTraj].resize(nPoint);
+// for ( i = 0; i < nPoint; ++i) {
+// aLabelList[iTraj][i] = ++aLabel;
+// }
+// }
+//}
+//
+///// Get residual and errors from data block.
+///**
+// * Get residual, error of measurement and residual and down-weighting
+// * factor for (single) data block
+// * \param [in] aData Label of data block
+// * \param [out] aResidual Measurement-Prediction
+// * \param [out] aMeasError Error of Measurement
+// * \param [out] aResError Error of Residual (including correlations from track fit)
+// * \param [out] aDownWeight Down-Weighting factor
+// */
+//void getResAndErr( int aData, double &aResidual,
+// double &aMeasError, double &aResError, double &aDownWeight) {
+//
+// double aMeasVar;
+// List< int>* indLocal;
+// List<double>* derLocal;
+// theData[aData].getResidual(aResidual, aMeasVar, aDownWeight, indLocal,
+// derLocal);
+// int nParBrl = (*indLocal).size();
+// TVectorD aVec(nParBrl); // compressed vector of derivatives
+// for ( int j = 0; j < nParBrl; ++j) {
+// aVec[j] = (*derLocal)[j];
+// }
+// SymMatrix aMat = theMatrix.getBlockMatrix(*indLocal); // compressed (covariance) matrix
+// double aFitVar = aMat.Similarity(aVec); // variance from track fit
+// aMeasError = sqrt(aMeasVar); // error of measurement
+// aResError = (aFitVar < aMeasVar ? sqrt(aMeasVar - aFitVar) : 0.); // error of residual
+//}
+/// Build linear equation system from data (blocks).
+ void buildLinearEquationSystem()
+ {
+ int nBorder = numCurvature + numLocals;
+// theVector. resize(numParameters);
+ theMatrix.resize(numParameters, nBorder, 5);
+ double[] retVals = new double[2];
+ double aValue, aWeight;
+ int[] indLocal = null;
+ double[] derLocal = null;
+ for (GblData d : theData)
+ {
+ d.getLocalData(retVals, indLocal, derLocal);
+ aValue = retVals[0];
+ aWeight = retVals[1];
+ for (int j = 0; j < indLocal.length; ++j)
+ {
+ theVector.addTo(indLocal[j] - 1, derLocal[j] * aWeight * aValue);
+ }
+ theMatrix.addBlockMatrix(aWeight, indLocal, derLocal);
+ }
+ }
+//}
+
+/// Prepare fit for simple or composed trajectory
+/**
+ * Generate data (blocks) from measurements, kinks, external seed and measurements.
+ */
+void prepare() {
+ int nDim = theDimension.size();
+ // upper limit
+ int maxData = numMeasurements + nDim * (numOffsets - 2);
+//cng + externalSeed.getRowDimension();
+// theData.reserve(maxData);
+// measDataIndex.resize(numAllPoints + 3); // include external seed and measurements
+ //cng
+ for(int i = 0; i<numAllPoints + 3; ++i) measDataIndex.add(i,0);
+ //cng
+// scatDataIndex.resize(numAllPoints + 1);
+ int nData = 0;
+ List<Matrix> innerTransDer = new ArrayList<Matrix>();
+ List<List<Integer> > innerTransLab = new ArrayList<List<Integer>>();
+// // composed trajectory ?
+// if (numInnerTrans > 0) {
+// //std::cout << "composed trajectory" << std::endl;
+// for ( int iTraj = 0; iTraj < numTrajectories; ++iTraj) {
+// // innermost point
+// GblPoint* innerPoint = &thePoints[iTraj].front();
+// // transformation fit to local track parameters
+// List< int> firstLabels(5);
+// SMatrix55 matFitToLocal, matLocalToFit;
+// getFitToLocalJacobian(firstLabels, matFitToLocal, *innerPoint, 5);
+// // transformation local track to fit parameters
+// int ierr;
+// matLocalToFit = matFitToLocal.Inverse(ierr);
+// TMatrixD localToFit(5, 5);
+// for ( int i = 0; i < 5; ++i) {
+// for ( int j = 0; j < 5; ++j) {
+// localToFit(i, j) = matLocalToFit(i, j);
+// }
+// }
+// // transformation external to fit parameters at inner (first) point
+// innerTransDer.add(localToFit * innerTransformations[iTraj]);
+// innerTransLab.add(firstLabels);
+// }
+// }
+ // measurements
+ Matrix matP = new Matrix(5,5);
+// // loop over trajectories
+// List<GblPoint>::iterator itPoint;
+// for ( int iTraj = 0; iTraj < numTrajectories; ++iTraj) {
+// for (itPoint = thePoints[iTraj].begin();
+// itPoint < thePoints[iTraj].end(); ++itPoint) {
+// SVector5 aMeas, aPrec;
+// int nLabel = itPoint->getLabel();
+// int measDim = itPoint->hasMeasurement();
+// if (measDim) {
+// const TMatrixD localDer = itPoint->getLocalDerivatives();
+// const List<int> globalLab = itPoint->getGlobalLabels();
+// const TMatrixD globalDer = itPoint->getGlobalDerivatives();
+// TMatrixD transDer;
+// itPoint->getMeasurement(matP, aMeas, aPrec);
+// int iOff = 5 - measDim; // first active component
+// List< int> labDer(5);
+// SMatrix55 matDer, matPDer;
+// int nJacobian =
+// (itPoint < thePoints[iTraj].end() - 1) ? 1 : 0; // last point needs backward propagation
+// getFitToLocalJacobian(labDer, matDer, *itPoint, measDim,
+// nJacobian);
+// if (measDim > 2) {
+// matPDer = matP * matDer;
+// } else { // 'shortcut' for position measurements
+// matPDer.Place_at(
+// matP.Sub<SMatrix22>(3, 3)
+// * matDer.Sub<SMatrix25>(3, 0), 3, 0);
+// }
+//
+//// if (numInnerTrans > 0) {
+//// // transform for external parameters
+//// TMatrixD proDer(measDim, 5);
+//// // match parameters
+//// int ifirst = 0;
+//// int ilabel = 0;
+//// while (ilabel < 5) {
+//// if (labDer[ilabel] > 0) {
+//// while (innerTransLab[iTraj][ifirst]
+//// != labDer[ilabel] && ifirst < 5) {
+//// ++ifirst;
+//// }
+//// if (ifirst >= 5) {
+//// labDer[ilabel] -= 2 * nDim * (iTraj + 1); // adjust label
+//// } else {
+//// // match
+//// labDer[ilabel] = 0; // mark as related to external parameters
+//// for ( int k = iOff; k < 5; ++k) {
+//// proDer(k - iOff, ifirst) = matPDer(k,
+//// ilabel);
+//// }
+//// }
+//// }
+//// ++ilabel;
+//// }
+//// transDer.ResizeTo(measDim, numCurvature);
+//// transDer = proDer * innerTransDer[iTraj];
+//// }
+// for ( int i = iOff; i < 5; ++i) {
+// if (aPrec(i) > 0.) {
+// GblData aData(nLabel, aMeas(i), aPrec(i));
+// aData.addDerivatives(i, labDer, matPDer, iOff, localDer,
+// globalLab, globalDer, numLocals, transDer);
+// theData.add(aData);
+// nData++;
+// }
+// }
+//
+// }
+// measDataIndex[nLabel] = nData;
+// }
+// } // end loop over trajectories
+
+// // pseudo measurements from kinks
+// SMatrix22 matT;
+// scatDataIndex[0] = nData;
[truncated at 1000 lines; 320 more skipped]
java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/HpsGblFitter.java 2014-08-28 08:14:53 UTC (rev 918)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/HpsGblFitter.java 2014-08-28 15:31:06 UTC (rev 919)
@@ -35,249 +35,245 @@
import org.lcsim.recon.tracking.seedtracker.SeedCandidate;
import org.lcsim.recon.tracking.seedtracker.SeedTrack;
-
/**
* Class to running GBL on HPS track.
- *
+ *
* @author phansson
+ *
+ * @version $Id:
*
*/
public class HpsGblFitter {
-
- private boolean _debug = false;
- private double _B = 0.;
- private double _bfac = 0.;
- private boolean isMC = false;
- TrackerHitUtils _trackHitUtils = null;
- MultipleScattering _scattering = null;
- private double m_chi2 = -1.;
- private int m_ndf = -1;
- private int m_lost_weight = -1;
- GblTrajectory _traj = null;
- MilleBinary _mille = null;
-
+ private boolean _debug = true;
+ private double _B = 0.;
+ private double _bfac = 0.;
+ private boolean isMC = false;
+ TrackerHitUtils _trackHitUtils = null;
+ MultipleScattering _scattering = null;
+ private double m_chi2 = -1.;
+ private int m_ndf = -1;
+ private int m_lost_weight = -1;
+ GblTrajectory _traj = null;
+ MilleBinary _mille = null;
-
- public HpsGblFitter(double Bz, MultipleScattering scattering, boolean isMCFlag) {
- isMC = isMCFlag;
- _B = Bz;
- _bfac = Bz * Constants.fieldConversion;
- _trackHitUtils = new TrackerHitUtils();
- _scattering = scattering;
- }
-
- public void setMilleBinary(MilleBinary mille) {
- _mille = mille;
- }
-
- public void clear() {
- m_chi2 = -1.;
- m_ndf = -1;
- m_lost_weight = -1;
- _traj = null;
- }
+ public HpsGblFitter() {
+ _B = -0.5;
+ _bfac = _B * Constants.fieldConversion;
+ _trackHitUtils = new TrackerHitUtils();
+ _scattering = new MultipleScattering(new MaterialSupervisor());
+ System.out.println("Default constructor");
+ }
- public int Fit(Track track) {
-
+ public HpsGblFitter(double Bz, MultipleScattering scattering, boolean isMCFlag) {
+ isMC = isMCFlag;
+ _B = Bz;
+ _bfac = Bz * Constants.fieldConversion;
+ _trackHitUtils = new TrackerHitUtils();
+ _scattering = scattering;
+ System.out.println("Constructor");
+ }
- // Check that things are setup
- if(_B == 0.) {
- System.out.printf("%s: B-field not set!\n", this.getClass().getSimpleName());
- return -1;
- }
- if(_scattering == null) {
- System.out.printf("%s: Multiple scattering calculator not set!\n", this.getClass().getSimpleName());
- return -2;
- }
-
- // Time the fits
- //clock_t startTime = clock();
+ public void setMilleBinary(MilleBinary mille) {
+ _mille = mille;
+ }
-
-
- // path length along trajectory
- double s = 0.;
- // jacobian to transport errors between points along the path
- BasicMatrix jacPointToPoint = GblUtils.getInstance().unitMatrix(5, 5);
- // Option to use uncorrelated MS errors
- // This is similar to what is done in lcsim seedtracker
- // The msCov below holds the MS errors
- // This is for testing purposes only.
- boolean useUncorrMS = false;
- BasicMatrix msCov = GblUtils.getInstance().zeroMatrix(5, 5);
-
- // Vector of the strip clusters used for the GBL fit
- List<GblPoint> listOfPoints = new ArrayList<GblPoint>();
-
- // Store the projection from local to measurement frame for each strip cluster
- // need to use pointer for TMatrix here?
- Map<Integer, Matrix> proL2m_list = new HashMap<Integer, Matrix>();
- // Save the association between strip cluster and label
- Map<HelicalTrackStrip, Integer> stripLabelMap = new HashMap<HelicalTrackStrip, Integer>();
-
- //start trajectory at refence point (s=0) - this point has no measurement
- GblPoint ref_point = new GblPoint(jacPointToPoint);
- listOfPoints.add(ref_point);
-
- //Create a list of all the strip clusters making up the track
- List<HelicalTrackStrip> stripClusters = new ArrayList<HelicalTrackStrip>();
- SeedCandidate seed = ((SeedTrack) track).getSeedCandidate();
- HelicalTrackFit htf = seed.getHelix();
- List<HelicalTrackHit> stereoHits = seed.getHits();
- for(int ihit = 0; ihit < stereoHits.size(); ++ihit) {
- HelicalTrackCross cross = (HelicalTrackCross) stereoHits.get(ihit);
- stripClusters.add(cross.getStrips().get(0));
- stripClusters.add(cross.getStrips().get(1));
- }
-
- // sort the clusters along path
- // TODO use actual path length and not layer id!
- //Collections.sort(stripClusters, new HelicalTrackStripComparer());
- Collections.sort(stripClusters, new Comparator<HelicalTrackStrip>() {
- public int compare(HelicalTrackStrip o1, HelicalTrackStrip o2) {
- return o1.layer() < o2.layer() ? -1 : o1.layer() > o2.layer() ? 1 : 0;
- }
- });
+ public void clear() {
+ m_chi2 = -1.;
+ m_ndf = -1;
+ m_lost_weight = -1;
+ _traj = null;
+ }
- if(_debug ) {
- System.out.printf("%s: %d strip clusters:\n", stripClusters.size());
- for(int istrip=0;istrip<stripClusters.size();++istrip) {
- System.out.printf("%s: layer %d origin %s\n", stripClusters.get(istrip).layer(),stripClusters.get(istrip).origin().toString());
- }
- }
+ public int Fit(Track track) {
-
- // Find scatter points along the path of the track
+ // Check that things are setup
+ if (_B == 0.) {
+ System.out.printf("%s: B-field not set!\n", this.getClass().getSimpleName());
+ return -1;
+ }
+ if (_scattering == null) {
+ System.out.printf("%s: Multiple scattering calculator not set!\n", this.getClass().getSimpleName());
+ return -2;
+ }
+
+ // Time the fits
+ //clock_t startTime = clock();
+ // path length along trajectory
+ double s = 0.;
+ // jacobian to transport errors between points along the path
+ BasicMatrix jacPointToPoint = GblUtils.getInstance().unitMatrix(5, 5);
+ // Option to use uncorrelated MS errors
+ // This is similar to what is done in lcsim seedtracker
+ // The msCov below holds the MS errors
+ // This is for testing purposes only.
+ boolean useUncorrMS = false;
+ BasicMatrix msCov = GblUtils.getInstance().zeroMatrix(5, 5);
+
+ // Vector of the strip clusters used for the GBL fit
+ List<GblPoint> listOfPoints = new ArrayList<GblPoint>();
+
+ // Store the projection from local to measurement frame for each strip cluster
+ // need to use pointer for TMatrix here?
+ Map<Integer, Matrix> proL2m_list = new HashMap<Integer, Matrix>();
+ // Save the association between strip cluster and label
+ Map<HelicalTrackStrip, Integer> stripLabelMap = new HashMap<HelicalTrackStrip, Integer>();
+
+ //start trajectory at refence point (s=0) - this point has no measurement
+ GblPoint ref_point = new GblPoint(jacPointToPoint);
+ listOfPoints.add(ref_point);
+
+ //Create a list of all the strip clusters making up the track
+ List<HelicalTrackStrip> stripClusters = new ArrayList<HelicalTrackStrip>();
+ SeedCandidate seed = ((SeedTrack) track).getSeedCandidate();
+ HelicalTrackFit htf = seed.getHelix();
+ List<HelicalTrackHit> stereoHits = seed.getHits();
+ for (int ihit = 0; ihit < stereoHits.size(); ++ihit) {
+ HelicalTrackCross cross = (HelicalTrackCross) stereoHits.get(ihit);
+ stripClusters.add(cross.getStrips().get(0));
+ stripClusters.add(cross.getStrips().get(1));
+ }
+
+ // sort the clusters along path
+ // TODO use actual path length and not layer id!
+ //Collections.sort(stripClusters, new HelicalTrackStripComparer());
+ Collections.sort(stripClusters, new Comparator<HelicalTrackStrip>() {
+ public int compare(HelicalTrackStrip o1, HelicalTrackStrip o2) {
+ return o1.layer() < o2.layer() ? -1 : o1.layer() > o2.layer() ? 1 : 0;
+ }
+ });
+
+ if (_debug) {
+ System.out.printf(" %d strip clusters:\n", stripClusters.size());
+ for (int istrip = 0; istrip < stripClusters.size(); ++istrip) {
+ System.out.printf("layer %d origin %s\n", stripClusters.get(istrip).layer(), stripClusters.get(istrip).origin().toString());
+ }
+ }
+
+ // Find scatter points along the path of the track
ScatterPoints scatters = _scattering.FindHPSScatterPoints(htf);
-
-
- if(_debug ) {
- System.out.printf("%s: Process %d strip clusters\n", stripClusters.size());
- }
- for(int istrip=0;istrip<stripClusters.size();++istrip) {
-
- HelicalTrackStrip strip = stripClusters.get(istrip);
-
- if(_debug) {
- System.out.printf("%s: layer %d origin %s\n", strip.layer(),strip.origin().toString());
- }
-
- //Find intercept point with sensor in tracking frame
+
+ if (_debug) {
+ System.out.printf(" Process %d strip clusters\n", stripClusters.size());
+ }
+ for (int istrip = 0; istrip < stripClusters.size(); ++istrip) {
+
+ HelicalTrackStrip strip = stripClusters.get(istrip);
+
+ if (_debug) {
+ System.out.printf(" layer %d origin %s\n", strip.layer(), strip.origin().toString());
+ }
+
+ //Find intercept point with sensor in tracking frame
Hep3Vector trkpos = TrackUtils.getHelixPlaneIntercept(htf, strip, Math.abs(_B));
- if(_debug) {
- System.out.printf("trkpos at intercept [%.10f %.10f %.10f]\n",trkpos.x(),trkpos.y(),trkpos.z());
+ if (_debug) {
+ System.out.printf("trkpos at intercept [%.10f %.10f %.10f]\n", trkpos.x(), trkpos.y(), trkpos.z());
}
-
- //path length to intercept
- double path = HelixUtils.PathToXPlane(htf,trkpos.x(),0,0).get(0);
+
+ //path length to intercept
+ double path = HelixUtils.PathToXPlane(htf, trkpos.x(), 0, 0).get(0);
double path3D = path / Math.cos(Math.atan(htf.slope()));
-
-
- // Path length step for this cluster
- double step = path3D - s;
-
- if( _debug ) {
- System.out.printf("%s: Path length step %f from %f to %f\n",this.getClass().getSimpleName(),step, s, path3D);
- }
-
- // Measurement direction (perpendicular and parallel to strip direction)
- BasicMatrix mDir = new BasicMatrix(2,3);
- mDir.setElement(0, 0, strip.u().x());
- mDir.setElement(0, 1, strip.u().y());
- mDir.setElement(0, 2, strip.u().z());
- mDir.setElement(1, 0, strip.v().x());
- mDir.setElement(1, 1, strip.v().y());
- mDir.setElement(1, 2, strip.v().z());
-
- Matrix mDirT = MatrixOp.transposed(mDir); //new BasicMatrix(MatrixOp.transposed(mDir));
- if(_debug) {
- System.out.printf("%s: mDir \n%s\n",this.getClass().getSimpleName(),mDir.toString());
- System.out.printf("%s: mDirT \n%s\n",this.getClass().getSimpleName(),mDirT.toString());
- }
-
- // Track direction
- double sinLambda = Math.sin(Math.atan(htf.slope()));
- double cosLambda = Math.sqrt(1.0 - sinLambda*sinLambda);
- double sinPhi = Math.sin(htf.phi0());
- double cosPhi = Math.sqrt(1.0 - sinPhi*sinPhi);
-
- // Track direction in curvilinear frame (U,V,T)
- // U = Z x T / |Z x T|, V = T x U
- BasicMatrix uvDir = new BasicMatrix(2,3);
- uvDir.setElement(0, 0, -sinPhi);
- uvDir.setElement(0, 1, cosPhi);
- uvDir.setElement(0, 2, 0.);
- uvDir.setElement(1, 0, -sinLambda * cosPhi);
- uvDir.setElement(1, 1, -sinLambda * sinPhi);
- uvDir.setElement(1, 2, cosLambda);
-
- if(_debug) {
- System.out.printf("%s: uvDir \n%s\n",this.getClass().getSimpleName(),uvDir.toString());
- }
+ // Path length step for this cluster
+ double step = path3D - s;
- // projection from measurement to local (curvilinear uv) directions (duv/dm)
- Matrix proM2l = MatrixOp.mult(uvDir, mDirT); //uvDir * mDirT;
-
- //projection from local (curvilinear uv) to measurement directions (dm/duv)
- Matrix proL2m = MatrixOp.inverse(proM2l);
-
- //proL2m_list[strip->GetId()] = new TMatrixD(proL2m);
+ if (_debug) {
+ System.out.printf("%s Path length step %f from %f to %f\n", this.getClass().getSimpleName(), step, s, path3D);
+ }
- if(_debug) {
- System.out.printf("%s: proM2l \n%s\n",this.getClass().getSimpleName(),proM2l.toString());
- System.out.printf("%s: proL2m \n%s\n",this.getClass().getSimpleName(),proL2m.toString());
- }
-
- // measurement/residual in the measurement system
-
+ // Measurement direction (perpendicular and parallel to strip direction)
+ BasicMatrix mDir = new BasicMatrix(2, 3);
+ mDir.setElement(0, 0, strip.u().x());
+ mDir.setElement(0, 1, strip.u().y());
+ mDir.setElement(0, 2, strip.u().z());
+ mDir.setElement(1, 0, strip.v().x());
+ mDir.setElement(1, 1, strip.v().y());
+ mDir.setElement(1, 2, strip.v().z());
+
+ Matrix mDirT = MatrixOp.transposed(mDir); //new BasicMatrix(MatrixOp.transposed(mDir));
+ if (_debug) {
+ System.out.printf(" mDir \n%s\n", this.getClass().getSimpleName(), mDir.toString());
+ System.out.printf(" mDirT \n%s\n", this.getClass().getSimpleName(), mDirT.toString());
+ }
+
+ // Track direction
+ double sinLambda = Math.sin(Math.atan(htf.slope()));
+ double cosLambda = Math.sqrt(1.0 - sinLambda * sinLambda);
+ double sinPhi = Math.sin(htf.phi0());
+ double cosPhi = Math.sqrt(1.0 - sinPhi * sinPhi);
+
+ // Track direction in curvilinear frame (U,V,T)
+ // U = Z x T / |Z x T|, V = T x U
+ BasicMatrix uvDir = new BasicMatrix(2, 3);
+ uvDir.setElement(0, 0, -sinPhi);
+ uvDir.setElement(0, 1, cosPhi);
+ uvDir.setElement(0, 2, 0.);
+ uvDir.setElement(1, 0, -sinLambda * cosPhi);
+ uvDir.setElement(1, 1, -sinLambda * sinPhi);
+ uvDir.setElement(1, 2, cosLambda);
+
+ if (_debug) {
+ System.out.printf(" uvDir \n%s\n", this.getClass().getSimpleName(), uvDir.toString());
+ }
+
+ // projection from measurement to local (curvilinear uv) directions (duv/dm)
+ Matrix proM2l = MatrixOp.mult(uvDir, mDirT); //uvDir * mDirT;
+
+ //projection from local (curvilinear uv) to measurement directions (dm/duv)
+ Matrix proL2m = MatrixOp.inverse(proM2l);
+
+ //proL2m_list[strip->GetId()] = new TMatrixD(proL2m);
+ if (_debug) {
+ System.out.printf(" proM2l \n%s\n", this.getClass().getSimpleName(), proM2l.toString());
+ System.out.printf(" proL2m \n%s\n", this.getClass().getSimpleName(), proL2m.toString());
+ }
+
+ // measurement/residual in the measurement system
// start by find the distance vector between the center and the track position
Hep3Vector vdiffTrk = VecOp.sub(trkpos, strip.origin());
-
+
// then find the rotation from tracking to measurement frame
Hep3Matrix trkToStripRot = _trackHitUtils.getTrackToStripRotation(strip);
-
+
// then rotate that vector into the measurement frame to get the predicted measurement position
Hep3Vector trkpos_meas = VecOp.mult(trkToStripRot, vdiffTrk);
-
+
// hit measurement and uncertainty in measurement frame
- Hep3Vector m_meas = new BasicHep3Vector(strip.umeas(),0.,0.);
-
+ Hep3Vector m_meas = new BasicHep3Vector(strip.umeas(), 0., 0.);
+
// finally the residual
Hep3Vector res_meas = VecOp.sub(m_meas, trkpos_meas);
- Hep3Vector res_err_meas = new BasicHep3Vector(strip.du(),(strip.vmax() - strip.vmin()) / Math.sqrt(12),10.0/Math.sqrt(12));
+ Hep3Vector res_err_meas = new BasicHep3Vector(strip.du(), (strip.vmax() - strip.vmin()) / Math.sqrt(12), 10.0 / Math.sqrt(12));
// Move to matrix objects instead of 3D vectors
// TODO use only one type
-
- // only 1D measurement in u-direction, set strip measurement direction to zero
- BasicMatrix meas = new BasicMatrix(0,2);
- meas.setElement(0, 0, res_meas.x());
- meas.setElement(0, 1, 0.);
+ // only 1D measurement in u-direction, set strip measurement direction to zero
+ BasicMatrix meas = new BasicMatrix(1, 2);
+ meas.setElement(0, 0, res_meas.x());
+ meas.setElement(0, 1, 0.);
// //meas[0][0] += deltaU[iLayer] # misalignment
- BasicMatrix measErr = new BasicMatrix(0,2);
- measErr.setElement(0, 0, res_err_meas.x());
- measErr.setElement(0, 1, 0.);
+ BasicMatrix measErr = new BasicMatrix(1, 2);
+ measErr.setElement(0, 0, res_err_meas.x());
+ measErr.setElement(0, 1, 0.);
- BasicMatrix measPrec = new BasicMatrix(0,2);
- measPrec.setElement(0, 0, 1.0/( measErr.e(0, 0) * measErr.e(0, 0)));
- measPrec.setElement(0, 1, 0.);
- if (_debug) {
- System.out.printf("%s: meas \n%s\n",this.getClass().getSimpleName(),meas.toString());
- System.out.printf("%s: measErr \n%s\n",this.getClass().getSimpleName(),measErr.toString());
- System.out.printf("%s: measPrec \n%s\n",this.getClass().getSimpleName(),measPrec.toString());
+ BasicMatrix measPrec = new BasicMatrix(1, 2);
+ measPrec.setElement(0, 0, 1.0 / (measErr.e(0, 0) * measErr.e(0, 0)));
+ measPrec.setElement(0, 1, 0.);
+ if (_debug) {
+ System.out.printf("%s: meas \n%s\n", this.getClass().getSimpleName(), meas.toString());
+ System.out.printf("%s: measErr \n%s\n", this.getClass().getSimpleName(), measErr.toString());
+ System.out.printf("%s: measPrec \n%s\n", this.getClass().getSimpleName(), measPrec.toString());
}
//Find the Jacobian to be able to propagate the covariance matrix to this strip position
jacPointToPoint = GblUtils.getInstance().gblSimpleJacobianLambdaPhi(step, cosLambda, Math.abs(_bfac));
-
- if(_debug) {
- System.out.printf("%s: jacPointToPoint \n%s\n",this.getClass().getSimpleName(),jacPointToPoint.toString());
+
+ if (_debug) {
+ System.out.printf("%s: jacPointToPoint \n%s\n", this.getClass().getSimpleName(), jacPointToPoint.toString());
}
-
- //propagate MS covariance matrix (in the curvilinear frame) to this strip position
+
+ //propagate MS covariance matrix (in the curvilinear frame) to this strip position
//msCov = np.dot(jacPointToPoint, np.dot(msCov, jacPointToPoint.T))
//measMsCov = np.dot(proL2m, np.dot(msCov[3:, 3:], proL2m.T))
// if (m_debug) {
@@ -286,187 +282,172 @@
// //cout << "HpsGblFitter: " << "measMsCov at this point:" << endl;
// //measMsCov.Print();
// }
-
//Option to blow up measurement error according to multiple scattering
//if useUncorrMS:
//measPrec[0] = 1.0 / (measErr[0] ** 2 + measMsCov[0, 0])
// if debug:
//print 'Adding measMsCov ', measMsCov[0,0]
-
// point with independent measurement
GblPoint point = new GblPoint(jacPointToPoint);
//Add measurement to the point
- point.addMeasurement(proL2m,meas,measPrec);
+ point.addMeasurement(proL2m, meas, measPrec);
-
//Add scatterer in curvilinear frame to the point
// no direction in this frame as it moves along the track
- BasicMatrix scat = GblUtils.getInstance().zeroMatrix(0,2);
+ BasicMatrix scat = GblUtils.getInstance().zeroMatrix(0, 2);
// find scattering angle
- ScatterPoint scatter = scatters.getScatterPoint(((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement());
+ ScatterPoint scatter = scatters.getScatterPoint(((RawTrackerHit) strip.rawhits().get(0)).getDetectorElement());
double scatAngle;
-
- if(scatter != null) {
- scatAngle = scatter.getScatterAngle().Angle();
- }
- else {
- System.out.printf("%s: WARNING cannot find scatter for detector %s with strip cluster at %s\n",this.getClass(),((RawTrackerHit)strip.rawhits().get(0)).getDetectorElement().getName(),strip.origin().toString());
+
+ if (scatter != null) {
+ scatAngle = scatter.getScatterAngle().Angle();
+ } else {
+ System.out.printf("%s: WARNING cannot find scatter for detector %s with strip cluster at %s\n", this.getClass(), ((RawTrackerHit) strip.rawhits().get(0)).getDetectorElement().getName(), strip.origin().toString());
//can be edge case where helix is outside, but close to sensor, so use hack with the sensor origin closest to hit
//TODO check if this really makes sense to do
DetectorPlane closest = null;
double dx = 999999.9;
- if(MaterialSupervisor.class.isInstance(_scattering.getMaterialManager())) {
- MaterialSupervisor matSup = (MaterialSupervisor)_scattering.getMaterialManager();
- for(ScatteringDetectorVolume vol : matSup.getMaterialVolumes()) {
- DetectorPlane plane = (DetectorPlane)vol;
+ if (MaterialSupervisor.class.isInstance(_scattering.getMaterialManager())) {
+ MaterialSupervisor matSup = (MaterialSupervisor) _scattering.getMaterialManager();
+ for (ScatteringDetectorVolume vol : matSup.getMaterialVolumes()) {
+ DetectorPlane plane = (DetectorPlane) vol;
double dx_loop = Math.abs(strip.origin().x() - plane.origin().x());
- if(dx_loop<dx) {
+ if (dx_loop < dx) {
dx = dx_loop;
closest = plane;
}
}
- if(closest==null) {
+ if (closest == null) {
throw new RuntimeException("cannot find any plane that is close to strip!");
} else {
// find scatterlength
- double s_closest = HelixUtils.PathToXPlane(htf,closest.origin().x(), 0., 0).get(0);
+ double s_closest = HelixUtils.PathToXPlane(htf, closest.origin().x(), 0., 0).get(0);
double X0 = closest.getMaterialTraversedInRL(HelixUtils.Direction(htf, s_closest));
- ScatterAngle scatterAngle = new ScatterAngle(s_closest, _scattering.msangle(htf.p(Math.abs(_B)),X0));
+ ScatterAngle scatterAngle = new ScatterAngle(s_closest, _scattering.msangle(htf.p(Math.abs(_B)), X0));
scatAngle = scatterAngle.Angle();
}
- }
- else {
+ } else {
throw new UnsupportedOperationException("Should not happen. This problem is only solved with the MaterialSupervisor.");
}
}
-
-
+
// Scattering angle in the curvilinear frame
//Note the cosLambda to correct for the projection in the phi direction
- BasicMatrix scatErr = new BasicMatrix(0,2);
+ BasicMatrix scatErr = new BasicMatrix(1, 2);
scatErr.setElement(0, 0, scatAngle);
scatErr.setElement(0, 1, scatAngle / cosLambda);
- BasicMatrix scatPrec = new BasicMatrix(0,2);
+ BasicMatrix scatPrec = new BasicMatrix(1, 2);
scatPrec.setElement(0, 0, 1.0 / (scatErr.e(0, 0) * scatErr.e(0, 0)));
scatPrec.setElement(0, 1, 1.0 / (scatErr.e(0, 1) * scatErr.e(0, 1)));
-
+
// add scatterer if not using the uncorrelated MS covariances for testing
- if (! useUncorrMS) {
- point.addScatterer(scat, scatPrec);
- if (_debug) {
- System.out.printf("%s: scatError to this point \n%s\n",this.getClass().getSimpleName(),scatErr.toString());
- }
+ if (!useUncorrMS) {
+ point.addScatterer(scat, scatPrec);
+ if (_debug) {
+ System.out.printf("%s: scatError to this point \n%s\n", this.getClass().getSimpleName(), scatErr.toString());
+ }
}
-
+
// Add this GBL point to list that will be used in fit
listOfPoints.add(point);
int iLabel = listOfPoints.size();
-
+
// Update MS covariance matrix
- msCov.setElement(1, 1, msCov.e(1, 1) + scatErr.e(0, 0)*scatErr.e(0, 0));
- msCov.setElement(2, 2, msCov.e(2, 2) + scatErr.e(0, 1)*scatErr.e(0, 1));
-
-
-
+ msCov.setElement(1, 1, msCov.e(1, 1) + scatErr.e(0, 0) * scatErr.e(0, 0));
+ msCov.setElement(2, 2, msCov.e(2, 2) + scatErr.e(0, 1) * scatErr.e(0, 1));
+
/*
- #####
- ## Calculate global derivatives for this point
- # track direction in tracking/global frame
- tDirGlobal = np.array( [ [cosPhi * cosLambda, sinPhi * cosLambda, sinLambda] ] )
- # Cross-check that the input is consistent
- if( np.linalg.norm( tDirGlobal - strip.tDir) > 0.00001):
- print 'ERROR: tDirs are not consistent!'
- sys.exit(1)
- # rotate track direction to measurement frame
- tDirMeas = np.dot( tDirGlobal, np.array([strip.u, strip.v, strip.w]) )
- #tDirMeas = utils.rotateGlToMeas(strip,tDirGlobal)
- normalMeas = np.dot( strip.w , np.array([strip.u, strip.v, strip.w]) )
- #normalMeas = utils.rotateGlToMeas(strip,strip.w)
- # non-measured directions
- vmeas = 0.
- wmeas = 0.
- # calculate and add derivatives to point
- glDers = utils.globalDers(strip.layer,strip.meas,vmeas,wmeas,tDirMeas,normalMeas)
- ders = glDers.getDers(track.isTop())
- labGlobal = ders['labels']
- addDer = ders['ders']
- if debug:
- print 'global derivatives:'
- print labGlobal
- print addDer
- point.addGlobals(labGlobal, addDer)
- #####
+ #####
+ ## Calculate global derivatives for this point
+ # track direction in tracking/global frame
+ tDirGlobal = np.array( [ [cosPhi * cosLambda, sinPhi * cosLambda, sinLambda] ] )
+ # Cross-check that the input is consistent
+ if( np.linalg.norm( tDirGlobal - strip.tDir) > 0.00001):
+ print 'ERROR: tDirs are not consistent!'
+ sys.exit(1)
+ # rotate track direction to measurement frame
+ tDirMeas = np.dot( tDirGlobal, np.array([strip.u, strip.v, strip.w]) )
+ #tDirMeas = utils.rotateGlToMeas(strip,tDirGlobal)
+ normalMeas = np.dot( strip.w , np.array([strip.u, strip.v, strip.w]) )
+ #normalMeas = utils.rotateGlToMeas(strip,strip.w)
+ # non-measured directions
+ vmeas = 0.
+ wmeas = 0.
+ # calculate and add derivatives to point
+ glDers = utils.globalDers(strip.layer,strip.meas,vmeas,wmeas,tDirMeas,normalMeas)
+ ders = glDers.getDers(track.isTop())
+ labGlobal = ders['labels']
+ addDer = ders['ders']
+ if debug:
+ print 'global derivatives:'
+ print labGlobal
+ print addDer
+ point.addGlobals(labGlobal, addDer)
+ #####
*/
-
-
-
//move on to next point
s += step;
-
+
// save strip and label map
//stripLabelMap[strip] = iLabel;
+ }
+
+ //create the trajectory
+ _traj = new GblTrajectory(listOfPoints); //,seedLabel, clSeed);
+
+ if (!_traj.isValid()) {
+ System.out.printf("%s: Invalid GblTrajectory -> skip \n", this.getClass().getSimpleName());
+ return -3;
+ }
+
+ // fit trajectory
+ _traj.fit(m_chi2, m_ndf, m_lost_weight);
-
-
+ //cng
+// System.out.println("fitting the traectory...");
+// double[] retDVals = new double[2];
+// int[] retIVals = new int[1];
+// int success = _traj.fit(retDVals, retIVals, "");
+ //cng
-
-
-
- }
-
+ if (_debug) {
+ System.out.printf("%s: Chi2 Fit: %f , %d , %d\n", this.getClass().getSimpleName(), m_chi2, m_ndf, m_lost_weight);
+ }
- //create the trajectory
- _traj = new GblTrajectory(listOfPoints); //,seedLabel, clSeed);
-
- if (! _traj.isValid()) {
- System.out.printf("%s: Invalid GblTrajectory -> skip \n",this.getClass().getSimpleName());
- return -3;
- }
-
- // fit trajectory
- _traj.fit(m_chi2, m_ndf, m_lost_weight);
-
- if( _debug ) {
- System.out.printf("%s: Chi2 Fit: %f , %d , %d\n",this.getClass().getSimpleName(), m_chi2, m_ndf,m_lost_weight);
- }
-
- // write to MP binary file
- if(_mille != null) {
- _traj.milleOut(_mille);
- }
-
- //stop the clock
- //clock_t endTime = clock();
- //double diff = endTime - startTime;
- //double cps = CLOCKS_PER_SEC;
- //if( m_debug ) {
- // std::cout << "HpsGblFitter: " << " Time elapsed " << diff / cps << " s" << std::endl;
- //}
+ // write to MP binary file
+ if (_mille != null) {
+ _traj.milleOut(_mille);
+ }
- if(_debug) {
- System.out.printf("%s: Fit() done successfully.\n",this.getClass().getSimpleName());
- }
-
- return 0;
- }
-
+ //stop the clock
+ //clock_t endTime = clock();
+ //double diff = endTime - startTime;
+ //double cps = CLOCKS_PER_SEC;
+ //if( m_debug ) {
+ // std::cout << "HpsGblFitter: " << " Time elapsed " << diff / cps << " s" << std::endl;
+ //}
+ if (_debug) {
+ System.out.printf("%s: Fit() done successfully.\n", this.getClass().getSimpleName());
+ }
- public static class HelicalTrackStripComparer implements Comparator<HelicalTrackStrip> {
- public int compare(HelicalTrackStrip o1, HelicalTrackStrip o2) {
- // TODO Change this to path length!?
- return compare(o1.layer(),o2.layer());
- }
-
- private static int compare(int s1, int s2) {
- return s1 < s2 ? -1 : s2 > s1 ? 1 : 0;
- }
-
-
- }
+ return 0;
+ }
+ public static class HelicalTrackStripComparer implements Comparator<HelicalTrackStrip> {
+ public int compare(HelicalTrackStrip o1, HelicalTrackStrip o2) {
+ // TODO Change this to path length!?
+ return compare(o1.layer(), o2.layer());
+ }
+
+ private static int compare(int s1, int s2) {
+ return s1 < s2 ? -1 : s2 > s1 ? 1 : 0;
+ }
+
+ }
+
}
java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/BorderedBandMatrix.java (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/BorderedBandMatrix.java 2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,360 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+import static java.lang.Math.abs;
+import static java.lang.Math.min;
+import static java.lang.Math.max;
+
+/**
+ *
+ * @author Norman A. Graf
+ *
+ * @version $Id$
+ */
+/// (Symmetric) Bordered Band Matrix.
+/**
+ * Separate storage of border, mixed and band parts (as vector<double>).
+ *
+ * \verbatim Example for matrix size=8 with border size and band width of two
+ *
+ * +- -+ | B11 B12 M13 M14 M15 M16 M17 M18 | | B12 B22 M23 M24 M25 M26 M27 M28 |
+ * | M13 M23 C33 C34 C35 0. 0. 0. | | M14 M24 C34 C44 C45 C46 0. 0. | | M15 M25
+ * C35 C45 C55 C56 C57 0. | | M16 M26 0. C46 C56 C66 C67 C68 | | M17 M27 0. 0.
+ * C57 C67 C77 C78 | | M18 M28 0. 0. 0. C68 C78 C88 | +- -+
+ *
+ * Is stored as::
+ *
+ * +- -+ +- -+ | B11 B12 | | M13 M14 M15 M16 M17 M18 | | B12 B22 | | M23 M24 M25
+ * M26 M27 M28 | +- -+ +- -+
+ *
+ * +- -+ | C33 C44 C55 C66 C77 C88 | | C34 C45 C56 C67 C78 0. | | C35 C46 C57
+ * C68 0. 0. | +- -+ \endverbatim
+ */
+public class BorderedBandMatrix
+{
+
+ private int numSize; ///< Matrix size
+ private int numBorder; ///< Border size
+ private int numBand; ///< Band width
+ private int numCol; ///< Band matrix size
+ private VSymMatrix theBorder = new VSymMatrix(0); ///< Border part
+ private VMatrix theMixed = new VMatrix(0,0); ///< Mixed part
+ private VMatrix theBand = new VMatrix(0,0); ///< Band part
+
+/// Resize bordered band matrix.
+ /**
+ * \param nSize [in] Size of matrix \param nBorder [in] Size of border (=1
+ * for q/p + additional local parameters) \param nBand [in] Band width
+ * (usually = 5, for simplified jacobians = 4)
+ */
+ public void resize(int nSize, int nBorder, int nBand)
+ {
+ numSize = nSize;
+ numBorder = nBorder;
+ numCol = nSize - nBorder;
+ numBand = 0;
+ theBorder.resize(numBorder);
+ theMixed.resize(numBorder, numCol);
+ theBand.resize((nBand + 1), numCol);
+ }
+
+/// Add symmetric block matrix.
+ /**
+ * Add (extended) block matrix defined by 'aVector * aWeight * aVector.T' to
+ * bordered band matrix: BBmatrix(anIndex(i),anIndex(j)) += aVector(i) *
+ * aWeight * aVector(j). \param aWeight [in] Weight \param anIndex [in] List
+ * of rows/colums to be used \param aVector [in] Vector
+ */
+ public void addBlockMatrix(double aWeight,
+ int[] anIndex,
+ double[] aVector)
+ {
+ int nBorder = numBorder;
+ for (int i = 0; i < anIndex.length; ++i)
+ {
+ int iIndex = (anIndex)[i] - 1; // anIndex has to be sorted
+ for (int j = 0; j <= i; ++j)
+ {
+ int jIndex = (anIndex)[j] - 1;
+ if (iIndex < nBorder)
+ {
+ theBorder.addTo(iIndex, jIndex, aVector[i] * aWeight
+ * aVector[j]);
+ } else if (jIndex < nBorder)
+ {
+ theMixed.addTo(jIndex, iIndex - nBorder, aVector[i] * aWeight
+ * aVector[j]);
+ } else
+ {
+ int nBand = iIndex - jIndex;
+ theBand.addTo(nBand, jIndex - nBorder, aVector[i] * aWeight
+ * aVector[j]);
+ numBand = max(numBand, nBand); // update band width
+ }
+ }
+ }
+ }
+
+///// Retrieve symmetric block matrix.
+///**
+// * Get (compressed) block from bordered band matrix: aMatrix(i,j) = BBmatrix(anIndex(i),anIndex(j)).
+// * \param anIndex [in] List of rows/colums to be used
+// */
+//TMatrixDSym BorderedBandMatrix::getBlockMatrix(
+// const std::vector<unsigned int> anIndex) const {
+//
+// TMatrixDSym aMatrix(anIndex.size());
+// int nBorder = numBorder;
+// for (unsigned int i = 0; i < anIndex.size(); ++i) {
+// int iIndex = anIndex[i] - 1; // anIndex has to be sorted
+// for (unsigned int j = 0; j <= i; ++j) {
+// int jIndex = anIndex[j] - 1;
+// if (iIndex < nBorder) {
+// aMatrix(i, j) = theBorder(iIndex, jIndex); // border part of inverse
+// } else if (jIndex < nBorder) {
+// aMatrix(i, j) = -theMixed(jIndex, iIndex - nBorder); // mixed part of inverse
+// } else {
+// unsigned int nBand = iIndex - jIndex;
+// aMatrix(i, j) = theBand(nBand, jIndex - nBorder); // band part of inverse
+// }
+// aMatrix(j, i) = aMatrix(i, j);
+// }
+// }
+// return aMatrix;
+//}
+/// Solve linear equation system, partially calculate inverse.
+ /**
+ * Solve linear equation A*x=b system with bordered band matrix A, calculate
+ * bordered band part of inverse of A. Use decomposition in border and band
+ * part for block matrix algebra:
+ *
+ * | A Ct | | x1 | | b1 | , A is the border part | | * | | = | | , Ct is the
+ * mixed part | C D | | x2 | | b2 | , D is the band part
+ *
+ * Explicit inversion of D is avoided by using solution X of D*X=C
+ * (X=D^-1*C, obtained from Cholesky decomposition and forward/backward
+ * substitution)
+ *
+ * | x1 | | E*b1 - E*Xt*b2 | , E^-1 = A-Ct*D^-1*C = A-Ct*X | | = | | | x2 |
+ * | x - X*x1 | , x is solution of D*x=b2 (x=D^-1*b2)
+ *
+ * Inverse matrix is:
+ *
+ * | E -E*Xt | | | , only band part of (D^-1 + X*E*Xt) | -X*E D^-1 + X*E*Xt
+ * | is calculated
+ *
+ *
+ * \param [in] aRightHandSide Right hand side (vector) 'b' of A*x=b \param
+ * [out] aSolution Solution (vector) x of A*x=b
+ */
+public void solveAndInvertBorderedBand(
+ VVector aRightHandSide, VVector aSolution) {
+
+ // decompose band
+ decomposeBand();
+ // invert band
+ VMatrix inverseBand = invertBand();
+ if (numBorder > 0) { // need to use block matrix decomposition to solve
+ // solve for mixed part
+ VMatrix auxMat = solveBand(theMixed); // = Xt
+ VMatrix auxMatT = auxMat.transpose(); // = X
+ // solve for border part
+ VVector auxVec = aRightHandSide.getVec(numBorder,0).minus(
+ auxMat.times( aRightHandSide.getVec(numCol, numBorder) ) ); // = b1 - Xt*b2
+ VSymMatrix inverseBorder = theBorder.minus(theMixed.times(auxMatT) );
+ inverseBorder.invert(); // = E
+ VVector borderSolution = inverseBorder.times(auxVec); // = x1
+ // solve for band part
+ VVector bandSolution = solveBand(
+ aRightHandSide.getVec(numCol, numBorder)); // = x
+ aSolution.putVec(borderSolution,0);
+ aSolution.putVec(bandSolution.minus(auxMatT.times(borderSolution)), numBorder); // = x2
+ // parts of inverse
+ theBorder = inverseBorder; // E
+ theMixed = inverseBorder.times(auxMat); // E*Xt (-mixed part of inverse) !!!
+ theBand = inverseBand.plus(bandOfAVAT(auxMatT, inverseBorder)); // band(D^-1 + X*E*Xt)
+ } else {
+ aSolution.putVec(solveBand(aRightHandSide),0);
+ theBand = inverseBand;
+ }
+}
+/// Print bordered band matrix.
+ public void printMatrix()
+ {
+ System.out.println("Border part ");
+ theBorder.print();
+ System.out.println("Mixed part ");
+ theMixed.print();
+ System.out.println("Band part ");
+ theBand.print();
+ }
+
+ /*============================================================================
+ from Dbandmatrix.F (MillePede-II by V. Blobel, Univ. Hamburg)
+ ============================================================================*/
+/// (root free) Cholesky decomposition of band part: C=LDL^T
+ /**
+ * Decompose band matrix into diagonal matrix D and lower triangular band
+ * matrix L (diagonal=1). Overwrite band matrix with D and off-diagonal part
+ * of L. \exception 2 : matrix is singular. \exception 3 : matrix is not
+ * positive definite.
+ */
+ private void decomposeBand()
+ {
+
+ int nRow = numBand + 1;
+ int nCol = numCol;
+ VVector auxVec = new VVector(nCol);
+ for (int i = 0; i < nCol; ++i)
+ {
+ auxVec.set(i, theBand.get(0, i) * 16.0); // save diagonal elements
+ }
+ for (int i = 0; i < nCol; ++i)
+ {
+ if ((theBand.get(0, i) + auxVec.get(i)) != theBand.get(0, i))
+ {
+ theBand.set(0, i, 1.0 / theBand.get(0, i));
+ if (theBand.get(0, i) < 0.)
+ {
+ throw new RuntimeException("BorderedBandMatrix decomposeBand not positive definite");
+ }
+ } else
+ {
+ theBand.set(0, i, 0.0);
+ throw new RuntimeException("BorderedBandMatrix decomposeBand singular");
+ }
+ for (int j = 1; j < min(nRow, nCol - i); ++j)
+ {
+ double rxw = theBand.get(j, i) * theBand.get(0, i);
+ for (int k = 0; k < min(nRow, nCol - i) - j; ++k)
+ {
+ theBand.subFrom(k, i + j, theBand.get(k + j, i) * rxw);
+ }
+ theBand.set(j, i, rxw);
+ }
+ }
+ }
+
+/// Invert band part.
+ /**
+ * \return Inverted band
+ */
+ private VMatrix invertBand()
+ {
+
+ int nRow = numBand + 1;
+ int nCol = numCol;
+ VMatrix inverseBand = new VMatrix(nRow, nCol);
+
+ for (int i = nCol - 1; i >= 0; i--)
+ {
+ double rxw = theBand.get(0, i);
+ for (int j = i; j >= max(0, i - nRow + 1); j--)
+ {
+ for (int k = j + 1; k < min(nCol, j + nRow); ++k)
+ {
+ rxw -= inverseBand.get(abs(i - k), min(i, k))
+ * theBand.get(k - j, j);
+ }
+ inverseBand.set(i - j, j, rxw);
+ rxw = 0.;
+ }
+ }
+ return inverseBand;
+ }
+
+/// Solve for band part.
+ /**
+ * Solve C*x=b for band part using decomposition C=LDL^T and forward (L*z=b)
+ * and backward substitution (L^T*x=D^-1*z). \param [in] aRightHandSide
+ * Right hand side (vector) 'b' of C*x=b \return Solution (vector) 'x' of
+ * C*x=b
+ */
+ private VVector solveBand(VVector aRightHandSide)
+ {
+
+ int nRow = theBand.getNumRows();
+ int nCol = theBand.getNumCols();
+ VVector aSolution = new VVector(aRightHandSide);
+ for (int i = 0; i < nCol; ++i) // forward substitution
+ {
+ for (int j = 1; j < min(nRow, nCol - i); ++j)
+ {
+ aSolution.subFrom(j + i, theBand.get(j, i) * aSolution.get(i));
+ }
+ }
+ for (int i = nCol - 1; i >= 0; i--) // backward substitution
+ {
+ double rxw = theBand.get(0, i) * aSolution.get(i);
+ for (int j = 1; j < min(nRow, nCol - i); ++j)
+ {
+ rxw -= theBand.get(j, i) * aSolution.get(j + i);
+ }
+ aSolution.set(i, rxw);
+ }
+ return aSolution;
+ }
+
+/// solve band part for mixed part (border rows).
+ /**
+ * Solve C*X=B for mixed part using decomposition C=LDL^T and forward and
+ * backward substitution. \param [in] aRightHandSide Right hand side
+ * (matrix) 'B' of C*X=B \return Solution (matrix) 'X' of C*X=B
+ */
+ private VMatrix solveBand(VMatrix aRightHandSide)
+ {
+
+ int nRow = theBand.getNumRows();
+ int nCol = theBand.getNumCols();
+ VMatrix aSolution = new VMatrix(aRightHandSide);
+ for (int iBorder = 0; iBorder < numBorder; iBorder++)
+ {
+ for (int i = 0; i < nCol; ++i) // forward substitution
+ {
+ for (int j = 1; j < min(nRow, nCol - i); ++j)
+ {
+ aSolution.subFrom(iBorder, j + i, theBand.get(j, i)
+ * aSolution.get(iBorder, i));
+ }
+ }
+ for (int i = nCol - 1; i >= 0; i--) // backward substitution
+ {
+ double rxw = theBand.get(0, i) * aSolution.get(iBorder, i);
+ for (int j = 1; j < min(nRow, nCol - i); ++j)
+ {
+ rxw -= theBand.get(j, i) * aSolution.get(iBorder, j + i);
+ }
+ aSolution.set(iBorder, i, rxw);
+ }
+ }
+ return aSolution;
+ }
+
+
+ /// Calculate band part of: 'anArray * aSymArray * anArray.T'.
+/**
+ * \return Band part of product
+ */
+private VMatrix bandOfAVAT( VMatrix anArray,
+ VSymMatrix aSymArray) {
+ int nBand = numBand;
+ int nCol = numCol;
+ int nBorder = numBorder;
+ double sum;
+ VMatrix aBand = new VMatrix((nBand + 1), nCol);
+ for (int i = 0; i < nCol; ++i) {
+ for (int j = max(0, i - nBand); j <= i; ++j) {
+ sum = 0.;
+ for (int l = 0; l < nBorder; ++l) { // diagonal
+ sum += anArray.get(i, l) * aSymArray.get(l, l) * anArray.get(j, l);
+ for (int k = 0; k < l; ++k) { // off diagonal
+ sum += anArray.get(i, l) * aSymArray.get(l, k) * anArray.get(j, k)
+ + anArray.get(i, k) * aSymArray.get(l, k) * anArray.get(j, l);
+ }
+ }
+ aBand.set(i - j, j, sum);
+ }
+ }
+ return aBand;
+}
+
+}
java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/EigenvalueDecomposition.java (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/EigenvalueDecomposition.java 2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,959 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+/** Eigenvalues and eigenvectors of a real matrix.
+<P>
+ If A is symmetric, then A = V*D*V' where the eigenvalue matrix D is
+ diagonal and the eigenvector matrix V is orthogonal.
+ I.e. A = V.times(D.times(V.transpose())) and
+ V.times(V.transpose()) equals the identity matrix.
+<P>
+ If A is not symmetric, then the eigenvalue matrix D is block diagonal
+ with the real eigenvalues in 1-by-1 blocks and any complex eigenvalues,
+ lambda + i*mu, in 2-by-2 blocks, [lambda, mu; -mu, lambda]. The
+ columns of V represent the eigenvectors in the sense that A*V = V*D,
+ i.e. A.times(V) equals V.times(D). The matrix V may be badly
+ conditioned, or even singular, so the validity of the equation
+ A = V*D*inverse(V) depends upon V.cond().
+ @version $Id: EigenvalueDecomposition.java,v 1.1.1.1 2010/11/30 21:31:59 jeremy Exp $
+*/
+
+public class EigenvalueDecomposition implements java.io.Serializable {
+
+/* ------------------------
+ Class variables
+ * ------------------------ */
+
+ /** Row and column dimension (square matrix).
+ @serial matrix dimension.
+ */
+ private int n;
+
+ /** Symmetry flag.
+ @serial internal symmetry flag.
+ */
+ private boolean issymmetric;
+
+ /** Arrays for internal storage of eigenvalues.
+ @serial internal storage of eigenvalues.
+ */
+ private double[] d, e;
+
+ /** Array for internal storage of eigenvectors.
+ @serial internal storage of eigenvectors.
+ */
+ private double[][] V;
+
+ /** Array for internal storage of nonsymmetric Hessenberg form.
+ @serial internal storage of nonsymmetric Hessenberg form.
+ */
+ private double[][] H;
+
+ /** Working storage for nonsymmetric algorithm.
+ @serial working storage for nonsymmetric algorithm.
+ */
+ private double[] ort;
+
+/* ------------------------
+ Private Methods
+ * ------------------------ */
+
+ // Symmetric Householder reduction to tridiagonal form.
+
+ private void tred2 () {
+
+ // This is derived from the Algol procedures tred2 by
+ // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+ // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+ // Fortran subroutine in EISPACK.
+
+ for (int j = 0; j < n; j++) {
+ d[j] = V[n-1][j];
+ }
+
+ // Householder reduction to tridiagonal form.
+
+ for (int i = n-1; i > 0; i--) {
+
+ // Scale to avoid under/overflow.
+
+ double scale = 0.0;
+ double h = 0.0;
+ for (int k = 0; k < i; k++) {
+ scale = scale + Math.abs(d[k]);
+ }
+ if (scale == 0.0) {
+ e[i] = d[i-1];
+ for (int j = 0; j < i; j++) {
+ d[j] = V[i-1][j];
+ V[i][j] = 0.0;
+ V[j][i] = 0.0;
+ }
+ } else {
+
+ // Generate Householder vector.
+
+ for (int k = 0; k < i; k++) {
+ d[k] /= scale;
+ h += d[k] * d[k];
+ }
+ double f = d[i-1];
+ double g = Math.sqrt(h);
+ if (f > 0) {
+ g = -g;
+ }
+ e[i] = scale * g;
+ h = h - f * g;
+ d[i-1] = f - g;
+ for (int j = 0; j < i; j++) {
+ e[j] = 0.0;
+ }
+
+ // Apply similarity transformation to remaining columns.
+
+ for (int j = 0; j < i; j++) {
+ f = d[j];
+ V[j][i] = f;
+ g = e[j] + V[j][j] * f;
+ for (int k = j+1; k <= i-1; k++) {
+ g += V[k][j] * d[k];
+ e[k] += V[k][j] * f;
+ }
+ e[j] = g;
+ }
+ f = 0.0;
+ for (int j = 0; j < i; j++) {
+ e[j] /= h;
+ f += e[j] * d[j];
+ }
+ double hh = f / (h + h);
+ for (int j = 0; j < i; j++) {
+ e[j] -= hh * d[j];
+ }
+ for (int j = 0; j < i; j++) {
+ f = d[j];
+ g = e[j];
+ for (int k = j; k <= i-1; k++) {
+ V[k][j] -= (f * e[k] + g * d[k]);
+ }
+ d[j] = V[i-1][j];
+ V[i][j] = 0.0;
+ }
+ }
+ d[i] = h;
+ }
+
+ // Accumulate transformations.
+
+ for (int i = 0; i < n-1; i++) {
+ V[n-1][i] = V[i][i];
+ V[i][i] = 1.0;
+ double h = d[i+1];
+ if (h != 0.0) {
+ for (int k = 0; k <= i; k++) {
+ d[k] = V[k][i+1] / h;
+ }
+ for (int j = 0; j <= i; j++) {
+ double g = 0.0;
+ for (int k = 0; k <= i; k++) {
+ g += V[k][i+1] * V[k][j];
+ }
+ for (int k = 0; k <= i; k++) {
+ V[k][j] -= g * d[k];
+ }
+ }
+ }
+ for (int k = 0; k <= i; k++) {
+ V[k][i+1] = 0.0;
+ }
+ }
+ for (int j = 0; j < n; j++) {
+ d[j] = V[n-1][j];
+ V[n-1][j] = 0.0;
+ }
+ V[n-1][n-1] = 1.0;
+ e[0] = 0.0;
+ }
+
+ // Symmetric tridiagonal QL algorithm.
+
+ private void tql2 () {
+
+ // This is derived from the Algol procedures tql2, by
+ // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+ // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+ // Fortran subroutine in EISPACK.
+
+ for (int i = 1; i < n; i++) {
+ e[i-1] = e[i];
+ }
+ e[n-1] = 0.0;
+
+ double f = 0.0;
+ double tst1 = 0.0;
+ double eps = Math.pow(2.0,-52.0);
+ for (int l = 0; l < n; l++) {
+
+ // Find small subdiagonal element
+
+ tst1 = Math.max(tst1,Math.abs(d[l]) + Math.abs(e[l]));
+ int m = l;
+ while (m < n) {
+ if (Math.abs(e[m]) <= eps*tst1) {
+ break;
+ }
+ m++;
+ }
+
+ // If m == l, d[l] is an eigenvalue,
+ // otherwise, iterate.
+
+ if (m > l) {
+ int iter = 0;
+ do {
+ iter = iter + 1; // (Could check iteration count here.)
+
+ // Compute implicit shift
+
+ double g = d[l];
+ double p = (d[l+1] - g) / (2.0 * e[l]);
+ double r = Matrix.hypot(p,1.0);
+ if (p < 0) {
+ r = -r;
+ }
+ d[l] = e[l] / (p + r);
+ d[l+1] = e[l] * (p + r);
+ double dl1 = d[l+1];
+ double h = g - d[l];
+ for (int i = l+2; i < n; i++) {
+ d[i] -= h;
+ }
+ f = f + h;
+
+ // Implicit QL transformation.
+
+ p = d[m];
+ double c = 1.0;
+ double c2 = c;
+ double c3 = c;
+ double el1 = e[l+1];
+ double s = 0.0;
+ double s2 = 0.0;
+ for (int i = m-1; i >= l; i--) {
+ c3 = c2;
+ c2 = c;
+ s2 = s;
+ g = c * e[i];
+ h = c * p;
+ r = Matrix.hypot(p,e[i]);
+ e[i+1] = s * r;
+ s = e[i] / r;
+ c = p / r;
+ p = c * d[i] - s * g;
+ d[i+1] = h + s * (c * g + s * d[i]);
+
+ // Accumulate transformation.
+
+ for (int k = 0; k < n; k++) {
+ h = V[k][i+1];
+ V[k][i+1] = s * V[k][i] + c * h;
+ V[k][i] = c * V[k][i] - s * h;
+ }
+ }
+ p = -s * s2 * c3 * el1 * e[l] / dl1;
+ e[l] = s * p;
+ d[l] = c * p;
+
+ // Check for convergence.
+
+ } while (Math.abs(e[l]) > eps*tst1);
+ }
+ d[l] = d[l] + f;
+ e[l] = 0.0;
+ }
+
+ // Sort eigenvalues and corresponding vectors.
+
+ for (int i = 0; i < n-1; i++) {
+ int k = i;
+ double p = d[i];
+ for (int j = i+1; j < n; j++) {
+ if (d[j] < p) {
+ k = j;
+ p = d[j];
+ }
+ }
+ if (k != i) {
+ d[k] = d[i];
+ d[i] = p;
+ for (int j = 0; j < n; j++) {
+ p = V[j][i];
+ V[j][i] = V[j][k];
+ V[j][k] = p;
+ }
+ }
+ }
+ }
+
+ // Nonsymmetric reduction to Hessenberg form.
+
+ private void orthes () {
+
+ // This is derived from the Algol procedures orthes and ortran,
+ // by Martin and Wilkinson, Handbook for Auto. Comp.,
+ // Vol.ii-Linear Algebra, and the corresponding
+ // Fortran subroutines in EISPACK.
+
+ int low = 0;
+ int high = n-1;
+
+ for (int m = low+1; m <= high-1; m++) {
+
+ // Scale column.
+
+ double scale = 0.0;
+ for (int i = m; i <= high; i++) {
+ scale = scale + Math.abs(H[i][m-1]);
+ }
+ if (scale != 0.0) {
+
+ // Compute Householder transformation.
+
+ double h = 0.0;
+ for (int i = high; i >= m; i--) {
+ ort[i] = H[i][m-1]/scale;
+ h += ort[i] * ort[i];
+ }
+ double g = Math.sqrt(h);
+ if (ort[m] > 0) {
+ g = -g;
+ }
+ h = h - ort[m] * g;
+ ort[m] = ort[m] - g;
+
+ // Apply Householder similarity transformation
+ // H = (I-u*u'/h)*H*(I-u*u')/h)
+
+ for (int j = m; j < n; j++) {
+ double f = 0.0;
+ for (int i = high; i >= m; i--) {
+ f += ort[i]*H[i][j];
+ }
+ f = f/h;
+ for (int i = m; i <= high; i++) {
+ H[i][j] -= f*ort[i];
+ }
+ }
+
+ for (int i = 0; i <= high; i++) {
+ double f = 0.0;
+ for (int j = high; j >= m; j--) {
+ f += ort[j]*H[i][j];
+ }
+ f = f/h;
+ for (int j = m; j <= high; j++) {
+ H[i][j] -= f*ort[j];
+ }
+ }
+ ort[m] = scale*ort[m];
+ H[m][m-1] = scale*g;
+ }
+ }
+
+ // Accumulate transformations (Algol's ortran).
+
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < n; j++) {
+ V[i][j] = (i == j ? 1.0 : 0.0);
+ }
+ }
+
+ for (int m = high-1; m >= low+1; m--) {
+ if (H[m][m-1] != 0.0) {
+ for (int i = m+1; i <= high; i++) {
+ ort[i] = H[i][m-1];
+ }
+ for (int j = m; j <= high; j++) {
+ double g = 0.0;
+ for (int i = m; i <= high; i++) {
+ g += ort[i] * V[i][j];
+ }
+ // Double division avoids possible underflow
+ g = (g / ort[m]) / H[m][m-1];
+ for (int i = m; i <= high; i++) {
+ V[i][j] += g * ort[i];
+ }
+ }
+ }
+ }
+ }
+
+
+ // Complex scalar division.
+
+ private transient double cdivr, cdivi;
+ private void cdiv(double xr, double xi, double yr, double yi) {
+ double r,d;
+ if (Math.abs(yr) > Math.abs(yi)) {
+ r = yi/yr;
+ d = yr + r*yi;
+ cdivr = (xr + r*xi)/d;
+ cdivi = (xi - r*xr)/d;
+ } else {
+ r = yr/yi;
+ d = yi + r*yr;
+ cdivr = (r*xr + xi)/d;
+ cdivi = (r*xi - xr)/d;
+ }
+ }
+
+
+ // Nonsymmetric reduction from Hessenberg to real Schur form.
+
+ private void hqr2 () {
+
+ // This is derived from the Algol procedure hqr2,
+ // by Martin and Wilkinson, Handbook for Auto. Comp.,
+ // Vol.ii-Linear Algebra, and the corresponding
+ // Fortran subroutine in EISPACK.
+
+ // Initialize
+
+ int nn = this.n;
+ int n = nn-1;
+ int low = 0;
+ int high = nn-1;
+ double eps = Math.pow(2.0,-52.0);
+ double exshift = 0.0;
+ double p=0,q=0,r=0,s=0,z=0,t,w,x,y;
+
+ // Store roots isolated by balanc and compute matrix norm
+
+ double norm = 0.0;
+ for (int i = 0; i < nn; i++) {
+ if (i < low | i > high) {
+ d[i] = H[i][i];
+ e[i] = 0.0;
+ }
+ for (int j = Math.max(i-1,0); j < nn; j++) {
+ norm = norm + Math.abs(H[i][j]);
+ }
+ }
+
+ // Outer loop over eigenvalue index
+
+ int iter = 0;
+ while (n >= low) {
+
+ // Look for single small sub-diagonal element
+
+ int l = n;
+ while (l > low) {
+ s = Math.abs(H[l-1][l-1]) + Math.abs(H[l][l]);
+ if (s == 0.0) {
+ s = norm;
+ }
+ if (Math.abs(H[l][l-1]) < eps * s) {
+ break;
+ }
+ l--;
+ }
+
+ // Check for convergence
+ // One root found
+
+ if (l == n) {
+ H[n][n] = H[n][n] + exshift;
+ d[n] = H[n][n];
+ e[n] = 0.0;
+ n--;
+ iter = 0;
+
+ // Two roots found
+
+ } else if (l == n-1) {
+ w = H[n][n-1] * H[n-1][n];
+ p = (H[n-1][n-1] - H[n][n]) / 2.0;
+ q = p * p + w;
+ z = Math.sqrt(Math.abs(q));
+ H[n][n] = H[n][n] + exshift;
+ H[n-1][n-1] = H[n-1][n-1] + exshift;
+ x = H[n][n];
+
+ // Real pair
+
+ if (q >= 0) {
+ if (p >= 0) {
+ z = p + z;
+ } else {
+ z = p - z;
+ }
+ d[n-1] = x + z;
+ d[n] = d[n-1];
+ if (z != 0.0) {
+ d[n] = x - w / z;
+ }
+ e[n-1] = 0.0;
+ e[n] = 0.0;
+ x = H[n][n-1];
+ s = Math.abs(x) + Math.abs(z);
+ p = x / s;
+ q = z / s;
+ r = Math.sqrt(p * p+q * q);
+ p = p / r;
+ q = q / r;
+
+ // Row modification
+
+ for (int j = n-1; j < nn; j++) {
+ z = H[n-1][j];
+ H[n-1][j] = q * z + p * H[n][j];
+ H[n][j] = q * H[n][j] - p * z;
+ }
+
+ // Column modification
+
+ for (int i = 0; i <= n; i++) {
+ z = H[i][n-1];
+ H[i][n-1] = q * z + p * H[i][n];
+ H[i][n] = q * H[i][n] - p * z;
+ }
+
+ // Accumulate transformations
+
+ for (int i = low; i <= high; i++) {
+ z = V[i][n-1];
+ V[i][n-1] = q * z + p * V[i][n];
+ V[i][n] = q * V[i][n] - p * z;
+ }
+
+ // Complex pair
+
+ } else {
+ d[n-1] = x + p;
+ d[n] = x + p;
+ e[n-1] = z;
+ e[n] = -z;
+ }
+ n = n - 2;
+ iter = 0;
+
+ // No convergence yet
+
+ } else {
+
+ // Form shift
+
+ x = H[n][n];
+ y = 0.0;
+ w = 0.0;
+ if (l < n) {
+ y = H[n-1][n-1];
+ w = H[n][n-1] * H[n-1][n];
+ }
+
+ // Wilkinson's original ad hoc shift
+
+ if (iter == 10) {
+ exshift += x;
+ for (int i = low; i <= n; i++) {
+ H[i][i] -= x;
+ }
+ s = Math.abs(H[n][n-1]) + Math.abs(H[n-1][n-2]);
+ x = y = 0.75 * s;
+ w = -0.4375 * s * s;
+ }
+
+ // MATLAB's new ad hoc shift
+
+ if (iter == 30) {
+ s = (y - x) / 2.0;
+ s = s * s + w;
+ if (s > 0) {
+ s = Math.sqrt(s);
+ if (y < x) {
+ s = -s;
+ }
+ s = x - w / ((y - x) / 2.0 + s);
+ for (int i = low; i <= n; i++) {
+ H[i][i] -= s;
+ }
+ exshift += s;
+ x = y = w = 0.964;
+ }
+ }
+
+ iter = iter + 1; // (Could check iteration count here.)
+
+ // Look for two consecutive small sub-diagonal elements
+
+ int m = n-2;
+ while (m >= l) {
+ z = H[m][m];
+ r = x - z;
+ s = y - z;
+ p = (r * s - w) / H[m+1][m] + H[m][m+1];
+ q = H[m+1][m+1] - z - r - s;
+ r = H[m+2][m+1];
+ s = Math.abs(p) + Math.abs(q) + Math.abs(r);
+ p = p / s;
+ q = q / s;
+ r = r / s;
+ if (m == l) {
+ break;
+ }
+ if (Math.abs(H[m][m-1]) * (Math.abs(q) + Math.abs(r)) <
+ eps * (Math.abs(p) * (Math.abs(H[m-1][m-1]) + Math.abs(z) +
+ Math.abs(H[m+1][m+1])))) {
+ break;
+ }
+ m--;
+ }
+
+ for (int i = m+2; i <= n; i++) {
+ H[i][i-2] = 0.0;
+ if (i > m+2) {
+ H[i][i-3] = 0.0;
+ }
+ }
+
+ // Double QR step involving rows l:n and columns m:n
+
+ for (int k = m; k <= n-1; k++) {
+ boolean notlast = (k != n-1);
+ if (k != m) {
+ p = H[k][k-1];
+ q = H[k+1][k-1];
+ r = (notlast ? H[k+2][k-1] : 0.0);
+ x = Math.abs(p) + Math.abs(q) + Math.abs(r);
+ if (x != 0.0) {
+ p = p / x;
+ q = q / x;
+ r = r / x;
+ }
+ }
+ if (x == 0.0) {
+ break;
+ }
+ s = Math.sqrt(p * p + q * q + r * r);
+ if (p < 0) {
+ s = -s;
+ }
+ if (s != 0) {
+ if (k != m) {
+ H[k][k-1] = -s * x;
+ } else if (l != m) {
+ H[k][k-1] = -H[k][k-1];
+ }
+ p = p + s;
+ x = p / s;
+ y = q / s;
+ z = r / s;
+ q = q / p;
+ r = r / p;
+
+ // Row modification
+
+ for (int j = k; j < nn; j++) {
+ p = H[k][j] + q * H[k+1][j];
+ if (notlast) {
+ p = p + r * H[k+2][j];
+ H[k+2][j] = H[k+2][j] - p * z;
+ }
+ H[k][j] = H[k][j] - p * x;
+ H[k+1][j] = H[k+1][j] - p * y;
+ }
+
+ // Column modification
+
+ for (int i = 0; i <= Math.min(n,k+3); i++) {
+ p = x * H[i][k] + y * H[i][k+1];
+ if (notlast) {
+ p = p + z * H[i][k+2];
+ H[i][k+2] = H[i][k+2] - p * r;
+ }
+ H[i][k] = H[i][k] - p;
+ H[i][k+1] = H[i][k+1] - p * q;
+ }
+
+ // Accumulate transformations
+
+ for (int i = low; i <= high; i++) {
+ p = x * V[i][k] + y * V[i][k+1];
+ if (notlast) {
+ p = p + z * V[i][k+2];
+ V[i][k+2] = V[i][k+2] - p * r;
+ }
+ V[i][k] = V[i][k] - p;
+ V[i][k+1] = V[i][k+1] - p * q;
+ }
+ } // (s != 0)
+ } // k loop
+ } // check convergence
+ } // while (n >= low)
+
+ // Backsubstitute to find vectors of upper triangular form
+
+ if (norm == 0.0) {
+ return;
+ }
+
+ for (n = nn-1; n >= 0; n--) {
+ p = d[n];
+ q = e[n];
+
+ // Real vector
+
+ if (q == 0) {
+ int l = n;
+ H[n][n] = 1.0;
+ for (int i = n-1; i >= 0; i--) {
+ w = H[i][i] - p;
+ r = 0.0;
+ for (int j = l; j <= n; j++) {
+ r = r + H[i][j] * H[j][n];
+ }
+ if (e[i] < 0.0) {
+ z = w;
+ s = r;
+ } else {
+ l = i;
+ if (e[i] == 0.0) {
+ if (w != 0.0) {
+ H[i][n] = -r / w;
+ } else {
+ H[i][n] = -r / (eps * norm);
+ }
+
+ // Solve real equations
+
+ } else {
+ x = H[i][i+1];
+ y = H[i+1][i];
+ q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
+ t = (x * s - z * r) / q;
+ H[i][n] = t;
+ if (Math.abs(x) > Math.abs(z)) {
+ H[i+1][n] = (-r - w * t) / x;
+ } else {
+ H[i+1][n] = (-s - y * t) / z;
+ }
+ }
+
+ // Overflow control
+
+ t = Math.abs(H[i][n]);
+ if ((eps * t) * t > 1) {
+ for (int j = i; j <= n; j++) {
+ H[j][n] = H[j][n] / t;
+ }
+ }
+ }
+ }
+
+ // Complex vector
+
+ } else if (q < 0) {
+ int l = n-1;
+
+ // Last vector component imaginary so matrix is triangular
+
+ if (Math.abs(H[n][n-1]) > Math.abs(H[n-1][n])) {
+ H[n-1][n-1] = q / H[n][n-1];
+ H[n-1][n] = -(H[n][n] - p) / H[n][n-1];
+ } else {
+ cdiv(0.0,-H[n-1][n],H[n-1][n-1]-p,q);
+ H[n-1][n-1] = cdivr;
+ H[n-1][n] = cdivi;
+ }
+ H[n][n-1] = 0.0;
+ H[n][n] = 1.0;
+ for (int i = n-2; i >= 0; i--) {
+ double ra,sa,vr,vi;
+ ra = 0.0;
+ sa = 0.0;
+ for (int j = l; j <= n; j++) {
+ ra = ra + H[i][j] * H[j][n-1];
+ sa = sa + H[i][j] * H[j][n];
+ }
+ w = H[i][i] - p;
+
+ if (e[i] < 0.0) {
+ z = w;
+ r = ra;
+ s = sa;
+ } else {
+ l = i;
+ if (e[i] == 0) {
+ cdiv(-ra,-sa,w,q);
+ H[i][n-1] = cdivr;
+ H[i][n] = cdivi;
+ } else {
+
+ // Solve complex equations
+
+ x = H[i][i+1];
+ y = H[i+1][i];
+ vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
+ vi = (d[i] - p) * 2.0 * q;
+ if (vr == 0.0 & vi == 0.0) {
+ vr = eps * norm * (Math.abs(w) + Math.abs(q) +
+ Math.abs(x) + Math.abs(y) + Math.abs(z));
+ }
+ cdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
+ H[i][n-1] = cdivr;
+ H[i][n] = cdivi;
+ if (Math.abs(x) > (Math.abs(z) + Math.abs(q))) {
+ H[i+1][n-1] = (-ra - w * H[i][n-1] + q * H[i][n]) / x;
+ H[i+1][n] = (-sa - w * H[i][n] - q * H[i][n-1]) / x;
+ } else {
+ cdiv(-r-y*H[i][n-1],-s-y*H[i][n],z,q);
+ H[i+1][n-1] = cdivr;
+ H[i+1][n] = cdivi;
+ }
+ }
+
+ // Overflow control
+
+ t = Math.max(Math.abs(H[i][n-1]),Math.abs(H[i][n]));
+ if ((eps * t) * t > 1) {
+ for (int j = i; j <= n; j++) {
+ H[j][n-1] = H[j][n-1] / t;
+ H[j][n] = H[j][n] / t;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Vectors of isolated roots
+
+ for (int i = 0; i < nn; i++) {
+ if (i < low | i > high) {
+ for (int j = i; j < nn; j++) {
+ V[i][j] = H[i][j];
+ }
+ }
+ }
+
+ // Back transformation to get eigenvectors of original matrix
+
+ for (int j = nn-1; j >= low; j--) {
+ for (int i = low; i <= high; i++) {
+ z = 0.0;
+ for (int k = low; k <= Math.min(j,high); k++) {
+ z = z + V[i][k] * H[k][j];
+ }
+ V[i][j] = z;
+ }
+ }
+ }
+
+
+/* ------------------------
+ Constructor
+ * ------------------------ */
+
+ /** Check for symmetry, then construct the eigenvalue decomposition
+ @param Arg Square matrix
+ */
+
+ public EigenvalueDecomposition (Matrix Arg) {
+ double[][] A = Arg.getArray();
+ n = Arg.getColumnDimension();
+ V = new double[n][n];
+ d = new double[n];
+ e = new double[n];
+
+ issymmetric = true;
+ for (int j = 0; (j < n) & issymmetric; j++) {
+ for (int i = 0; (i < n) & issymmetric; i++) {
+ issymmetric = (A[i][j] == A[j][i]);
+ }
+ }
+
+ if (issymmetric) {
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < n; j++) {
+ V[i][j] = A[i][j];
+ }
+ }
+
+ // Tridiagonalize.
+ tred2();
+
+ // Diagonalize.
+ tql2();
+
+ } else {
+ H = new double[n][n];
+ ort = new double[n];
+
+ for (int j = 0; j < n; j++) {
+ for (int i = 0; i < n; i++) {
+ H[i][j] = A[i][j];
+ }
+ }
+
+ // Reduce to Hessenberg form.
+ orthes();
+
+ // Reduce Hessenberg to real Schur form.
+ hqr2();
+ }
+ }
+
+/* ------------------------
+ Public Methods
+ * ------------------------ */
+
+ /** Return the eigenvector matrix
+ @return V
+ */
+
+ public Matrix getV () {
+ return new Matrix(V,n,n);
+ }
+
+ public Matrix getEigenVectors()
+ {
+ return getV();
+ }
+
+ /** Return the real parts of the eigenvalues
+ @return real(diag(D))
+ */
+
+ public double[] getRealEigenvalues () {
+ return d;
+ }
+
+ /** Return the imaginary parts of the eigenvalues
+ @return imag(diag(D))
+ */
+
+ public double[] getImagEigenvalues () {
+ return e;
+ }
+
+ /** Return the block diagonal eigenvalue matrix
+ @return D
+ */
+
+ public Matrix getD () {
+ Matrix X = new Matrix(n,n);
+ double[][] D = X.getArray();
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < n; j++) {
+ D[i][j] = 0.0;
+ }
+ D[i][i] = d[i];
+ if (e[i] > 0) {
+ D[i][i+1] = e[i];
+ } else if (e[i] < 0) {
+ D[i][i-1] = e[i];
+ }
+ }
+ return X;
+ }
+}
java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/LUDecomposition.java (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/LUDecomposition.java 2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,310 @@
+package org.hps.recon.tracking.gbl.matrix;
+ /** LU Decomposition.
+ <P>
+ For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n
+ unit lower triangular matrix L, an n-by-n upper triangular matrix U,
+ and a permutation vector piv of length m so that A(piv,:) = L*U.
+ If m < n, then L is m-by-m and U is m-by-n.
+ <P>
+ The LU decompostion with pivoting always exists, even if the matrix is
+ singular, so the constructor will never fail. The primary use of the
+ LU decomposition is in the solution of square systems of simultaneous
+ linear equations. This will fail if isNonsingular() returns false.
+ @version $Id: LUDecomposition.java,v 1.1.1.1 2010/11/30 21:31:59 jeremy Exp $
+ */
+
+public class LUDecomposition implements java.io.Serializable {
+
+/* ------------------------
+ Class variables
+ * ------------------------ */
+
+ /** Array for internal storage of decomposition.
+ @serial internal array storage.
+ */
+ private double[][] LU;
+
+ /** Row and column dimensions, and pivot sign.
+ @serial column dimension.
+ @serial row dimension.
+ @serial pivot sign.
+ */
+ private int m, n, pivsign;
+
+ /** Internal storage of pivot vector.
+ @serial pivot vector.
+ */
+ private int[] piv;
+
+/* ------------------------
+ Constructor
+ * ------------------------ */
+
+ /** LU Decomposition
+ @param A Rectangular matrix
+ */
+
+ public LUDecomposition (Matrix A) {
+
+ // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
+
+ LU = A.getArrayCopy();
+ m = A.getRowDimension();
+ n = A.getColumnDimension();
+ piv = new int[m];
+ for (int i = 0; i < m; i++) {
+ piv[i] = i;
+ }
+ pivsign = 1;
+ double[] LUrowi;
+ double[] LUcolj = new double[m];
+
+ // Outer loop.
+
+ for (int j = 0; j < n; j++) {
+
+ // Make a copy of the j-th column to localize references.
+
+ for (int i = 0; i < m; i++) {
+ LUcolj[i] = LU[i][j];
+ }
+
+ // Apply previous transformations.
+
+ for (int i = 0; i < m; i++) {
+ LUrowi = LU[i];
+
+ // Most of the time is spent in the following dot product.
+
+ int kmax = Math.min(i,j);
+ double s = 0.0;
+ for (int k = 0; k < kmax; k++) {
+ s += LUrowi[k]*LUcolj[k];
+ }
+
+ LUrowi[j] = LUcolj[i] -= s;
+ }
+
+ // Find pivot and exchange if necessary.
+
+ int p = j;
+ for (int i = j+1; i < m; i++) {
+ if (Math.abs(LUcolj[i]) > Math.abs(LUcolj[p])) {
+ p = i;
+ }
+ }
+ if (p != j) {
+ for (int k = 0; k < n; k++) {
+ double t = LU[p][k]; LU[p][k] = LU[j][k]; LU[j][k] = t;
+ }
+ int k = piv[p]; piv[p] = piv[j]; piv[j] = k;
+ pivsign = -pivsign;
+ }
+
+ // Compute multipliers.
+
+ if (j < m & LU[j][j] != 0.0) {
+ for (int i = j+1; i < m; i++) {
+ LU[i][j] /= LU[j][j];
+ }
+ }
+ }
+ }
+
+/* ------------------------
+ Temporary, experimental code.
+ ------------------------ *\
+
+ \** LU Decomposition, computed by Gaussian elimination.
+ <P>
+ This constructor computes L and U with the "daxpy"-based elimination
+ algorithm used in LINPACK and MATLAB. In Java, we suspect the dot-product,
+ Crout algorithm will be faster. We have temporarily included this
+ constructor until timing experiments confirm this suspicion.
+ <P>
+ @param A Rectangular matrix
+ @param linpackflag Use Gaussian elimination. Actual value ignored.
+ @return Structure to access L, U and piv.
+ *\
+
+ public LUDecomposition (Matrix A, int linpackflag) {
+ // Initialize.
+ LU = A.getArrayCopy();
+ m = A.getRowDimension();
+ n = A.getColumnDimension();
+ piv = new int[m];
+ for (int i = 0; i < m; i++) {
+ piv[i] = i;
+ }
+ pivsign = 1;
+ // Main loop.
+ for (int k = 0; k < n; k++) {
+ // Find pivot.
+ int p = k;
+ for (int i = k+1; i < m; i++) {
+ if (Math.abs(LU[i][k]) > Math.abs(LU[p][k])) {
+ p = i;
+ }
+ }
+ // Exchange if necessary.
+ if (p != k) {
+ for (int j = 0; j < n; j++) {
+ double t = LU[p][j]; LU[p][j] = LU[k][j]; LU[k][j] = t;
+ }
+ int t = piv[p]; piv[p] = piv[k]; piv[k] = t;
+ pivsign = -pivsign;
+ }
+ // Compute multipliers and eliminate k-th column.
+ if (LU[k][k] != 0.0) {
+ for (int i = k+1; i < m; i++) {
+ LU[i][k] /= LU[k][k];
+ for (int j = k+1; j < n; j++) {
+ LU[i][j] -= LU[i][k]*LU[k][j];
+ }
+ }
+ }
+ }
+ }
+
+\* ------------------------
+ End of temporary code.
+ * ------------------------ */
+
+/* ------------------------
+ Public Methods
+ * ------------------------ */
+
+ /** Is the matrix nonsingular?
+ @return true if U, and hence A, is nonsingular.
+ */
+
+ public boolean isNonsingular () {
+ for (int j = 0; j < n; j++) {
+ if (LU[j][j] == 0)
+ return false;
+ }
+ return true;
+ }
+
+ /** Return lower triangular factor
+ @return L
+ */
+
+ public Matrix getL () {
+ Matrix X = new Matrix(m,n);
+ double[][] L = X.getArray();
+ for (int i = 0; i < m; i++) {
+ for (int j = 0; j < n; j++) {
+ if (i > j) {
+ L[i][j] = LU[i][j];
+ } else if (i == j) {
+ L[i][j] = 1.0;
+ } else {
+ L[i][j] = 0.0;
+ }
+ }
+ }
+ return X;
+ }
+
+ /** Return upper triangular factor
+ @return U
+ */
+
+ public Matrix getU () {
+ Matrix X = new Matrix(n,n);
+ double[][] U = X.getArray();
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < n; j++) {
+ if (i <= j) {
+ U[i][j] = LU[i][j];
+ } else {
+ U[i][j] = 0.0;
+ }
+ }
+ }
+ return X;
+ }
+
+ /** Return pivot permutation vector
+ @return piv
+ */
+
+ public int[] getPivot () {
+ int[] p = new int[m];
+ for (int i = 0; i < m; i++) {
+ p[i] = piv[i];
+ }
+ return p;
+ }
+
+ /** Return pivot permutation vector as a one-dimensional double array
+ @return (double) piv
+ */
+
+ public double[] getDoublePivot () {
+ double[] vals = new double[m];
+ for (int i = 0; i < m; i++) {
+ vals[i] = (double) piv[i];
+ }
+ return vals;
+ }
+
+ /** Determinant
+ @return det(A)
+ @exception IllegalArgumentException Matrix must be square
+ */
+
+ public double det () {
+ if (m != n) {
+ throw new IllegalArgumentException("Matrix must be square.");
+ }
+ double d = (double) pivsign;
+ for (int j = 0; j < n; j++) {
+ d *= LU[j][j];
+ }
+ return d;
+ }
+
+ /** Solve A*X = B
+ @param B A Matrix with as many rows as A and any number of columns.
+ @return X so that L*U*X = B(piv,:)
+ @exception IllegalArgumentException Matrix row dimensions must agree.
+ @exception RuntimeException Matrix is singular.
+ */
+
+ public Matrix solve (Matrix B) {
+ if (B.getRowDimension() != m) {
+ throw new IllegalArgumentException("Matrix row dimensions must agree.");
+ }
+ if (!this.isNonsingular()) {
+ throw new RuntimeException("Matrix is singular.");
+ }
+
+ // Copy right hand side with pivoting
+ int nx = B.getColumnDimension();
+ Matrix Xmat = B.getMatrix(piv,0,nx-1);
+ double[][] X = Xmat.getArray();
+
+ // Solve L*Y = B(piv,:)
+ for (int k = 0; k < n; k++) {
+ for (int i = k+1; i < n; i++) {
+ for (int j = 0; j < nx; j++) {
+ X[i][j] -= X[k][j]*LU[i][k];
+ }
+ }
+ }
+ // Solve U*X = Y;
+ for (int k = n-1; k >= 0; k--) {
+ for (int j = 0; j < nx; j++) {
+ X[k][j] /= LU[k][k];
+ }
+ for (int i = 0; i < k; i++) {
+ for (int j = 0; j < nx; j++) {
+ X[i][j] -= X[k][j]*LU[i][k];
+ }
+ }
+ }
+ return Xmat;
+ }
+}
\ No newline at end of file
java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/Matrix.java (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/Matrix.java 2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,1553 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+import java.io.BufferedReader;
+import java.io.PrintWriter;
+import java.io.StreamTokenizer;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.util.Locale;
+
+///**
+// * Jama = Java Matrix class.
+// * <P>
+// * The Java Matrix Class provides the fundamental operations of numerical linear
+// * algebra. Various constructors create Matrices from two dimensional arrays of
+// * double precision floating point numbers. Various "gets" and "sets" provide
+// * access to submatrices and matrix elements. Several methods implement basic
+// * matrix arithmetic, including matrix addition and multiplication, matrix
+// * norms, and element-by-element array operations. Methods for reading and
+// * printing matrices are also included. All the operations in this version of
+// * the Matrix Class involve real matrices. Complex matrices may be handled in a
+// * future version.
+// * <P>
+// * Five fundamental matrix decompositions, which consist of pairs or triples of
+// * matrices, permutation vectors, and the like, produce results in five
+// * decomposition classes. These decompositions are accessed by the Matrix class
+// * to compute solutions of simultaneous linear equations, determinants, inverses
+// * and other matrix functions. The five decompositions are:
+// * <P>
+// * <UL>
+// * <LI>Cholesky Decomposition of symmetric, positive definite matrices.
+// * <LI>LU Decomposition of rectangular matrices.
+// * <LI>QR Decomposition of rectangular matrices.
+// * <LI>Singular Value Decomposition of rectangular matrices.
+// * <LI>Eigenvalue Decomposition of both symmetric and nonsymmetric square
+// * matrices.
+// * </UL>
+// * <DL>
+// * <DT><B>Example of use:</B></DT>
+// * <P>
+// * <DD>Solve a linear system A x = b and compute the residual norm, ||b - A x||.
+// * <P>
+// * <
+// * PRE>
+// * double[][] vals = {{1.,2.,3},{4.,5.,6.},{7.,8.,10.}};
+// * Matrix A = new Matrix(vals);
+// * Matrix b = Matrix.random(3,1);
+// * Matrix x = A.solve(b);
+// * Matrix r = A.times(x).minus(b);
+// * double rnorm = r.normInf();
+// * </PRE></DD>
+// * </DL>
+// *
+// * @author The MathWorks, Inc. and the National Institute of Standards and
+// * Technology.
+// * @author Norman A. Graf (modifications for the gbl package)
+// * @version 5 August 1998 $Id: Matrix.java,v 1.1.1.1 2010/11/30 21:31:59 jeremy
+// * Exp $
+// */
+public class Matrix implements Cloneable, java.io.Serializable
+{
+
+ /* ------------------------
+ Class variables
+ * ------------------------ */
+ /**
+ * Array for internal storage of elements.
+ *
+ * @serial internal array storage.
+ */
+ protected double[][] A;
+
+ /**
+ * Row and column dimensions.
+ *
+ * @serial row dimension.
+ * @serial column dimension.
+ */
+ protected int m, n;
+
+ /* ------------------------
+ Constructors
+ * ------------------------ */
+ /**
+ * Construct an m-by-n matrix of zeros.
+ *
+ * @param m Number of rows.
+ * @param n Number of columns.
+ */
+ public Matrix(int m, int n)
+ {
+ this.m = m;
+ this.n = n;
+ A = new double[m][n];
+ }
+//
+// /**
+// * Construct an m-by-n constant matrix.
+// *
+// * @param m Number of rows.
+// * @param n Number of colums.
+// * @param s Fill the matrix with this scalar value.
+// */
+// public Matrix(int m, int n, double s)
+// {
+// this.m = m;
+// this.n = n;
+// A = new double[m][n];
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// A[i][j] = s;
+// }
+// }
+// }
+//
+// /**
+// * Construct a matrix from a 2-D array.
+// *
+// * @param A Two-dimensional array of doubles.
+// * @exception IllegalArgumentException All rows must have the same length
+// * @see #constructWithCopy
+// */
+// public Matrix(double[][] A)
+// {
+// m = A.length;
+// n = A[0].length;
+// for (int i = 0; i < m; i++)
+// {
+// if (A[i].length != n)
+// {
+// throw new IllegalArgumentException("All rows must have the same length.");
+// }
+// }
+// this.A = A;
+// }
+//
+ /**
+ * Construct a matrix quickly without checking arguments.
+ *
+ * @param A Two-dimensional array of doubles.
+ * @param m Number of rows.
+ * @param n Number of colums.
+ */
+ public Matrix(double[][] A, int m, int n)
+ {
+ this.A = A;
+ this.m = m;
+ this.n = n;
+ }
+
+// /**
+// * Construct a matrix from a one-dimensional packed array
+// *
+// * @param vals One-dimensional array of doubles, packed by columns (ala
+// * Fortran).
+// * @param m Number of rows.
+// * @exception IllegalArgumentException Array length must be a multiple of m.
+// */
+// public Matrix(double vals[], int m)
+// {
+// this.m = m;
+// n = (m != 0 ? vals.length / m : 0);
+// if (m * n != vals.length)
+// {
+// throw new IllegalArgumentException("Array length must be a multiple of m.");
+// }
+// A = new double[m][n];
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// A[i][j] = vals[i + j * m];
+// }
+// }
+// }
+//
+// /* ------------------------
+// Public Methods
+// * ------------------------ */
+// /**
+// * Construct a matrix from a copy of a 2-D array.
+// *
+// * @param A Two-dimensional array of doubles.
+// * @exception IllegalArgumentException All rows must have the same length
+// */
+// public static Matrix constructWithCopy(double[][] A)
+// {
+// int m = A.length;
+// int n = A[0].length;
+// Matrix X = new Matrix(m, n);
+// double[][] C = X.getArray();
+// for (int i = 0; i < m; i++)
+// {
+// if (A[i].length != n)
+// {
+// throw new IllegalArgumentException("All rows must have the same length.");
+// }
+// for (int j = 0; j < n; j++)
+// {
+// C[i][j] = A[i][j];
+// }
+// }
+// return X;
+// }
+//
+// /**
+// * Make a deep copy of a matrix
+// */
+// public Matrix copy()
+// {
+// Matrix X = new Matrix(m, n);
+// double[][] C = X.getArray();
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// C[i][j] = A[i][j];
+// }
+// }
+// return X;
+// }
+//
+// /**
+// * Clone the Matrix object.
+// */
+// public Object clone()
+// {
+// return this.copy();
+// }
+//
+ /**
+ * Access the internal two-dimensional array.
+ *
+ * @return Pointer to the two-dimensional array of matrix elements.
+ * TODO should this return a copy?
+ */
+ public double[][] getArray()
+ {
+ return A;
+ }
+
+ /**
+ * Copy the internal two-dimensional array.
+ *
+ * @return Two-dimensional array copy of matrix elements.
+ */
+ public double[][] getArrayCopy()
+ {
+ double[][] C = new double[m][n];
+ for (int i = 0; i < m; i++)
+ {
+ for (int j = 0; j < n; j++)
+ {
+ C[i][j] = A[i][j];
+ }
+ }
+ return C;
+ }
+
+// /**
+// * Make a one-dimensional column packed copy of the internal array.
+// *
+// * @return Matrix elements packed in a one-dimensional array by columns.
+// */
+// public double[] getColumnPackedCopy()
+// {
+// double[] vals = new double[m * n];
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// vals[i + j * m] = A[i][j];
+// }
+// }
+// return vals;
+// }
+//
+// /**
+// * Make a one-dimensional row packed copy of the internal array.
+// *
+// * @return Matrix elements packed in a one-dimensional array by rows.
+// */
+// public double[] getRowPackedCopy()
+// {
+// double[] vals = new double[m * n];
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// vals[i * n + j] = A[i][j];
+// }
+// }
+// return vals;
+// }
+//
+ /**
+ * @return the number of rows.
+ */
+ public int getRowDimension()
+ {
+ return m;
+ }
+
+ /**
+ * @return the number of columns.
+ */
+ public int getColumnDimension()
+ {
+ return n;
+ }
+
+ /**
+ * @param i Row index.
+ * @param j Column index.
+ * @return A(i,j)
+ * @exception ArrayIndexOutOfBoundsException
+ */
+ public double get(int i, int j)
+ {
+ return A[i][j];
+ }
+
+ //for symmetric matrices
+public Matrix sub(int size, int rIndex, int cIndex)
+{
+ return getMatrix(rIndex, rIndex+size-1,cIndex, cIndex+size-1);
+}
+
+//non-symmetric Matrix
+public Matrix sub(int rSize, int cSize, int rIndex, int cIndex)
+{
+ return getMatrix(rIndex, rIndex+rSize-1,cIndex, cIndex+cSize-1);
+}
+
+public Vector subCol(int size, int colIndex, int rStart)
+{
+ return new Vector(getMatrix(rStart, rStart+size-1, colIndex, colIndex));
+}
+
+public void placeAt(Matrix a, int rIndex, int cIndex)
+{
+ for(int i=0; i<a.getRowDimension(); ++i)
+ {
+ for(int j=0; j<a.getColumnDimension(); ++j)
+ {
+ A[rIndex+i][cIndex+j] = a.get(i,j);
+ }
+ }
+}
+
+public void placeInCol(Vector v, int rIndex, int cIndex)
+{
+ for(int i=0; i < v.size(); ++i)
+ {
+ A[rIndex+i][cIndex] = v.get(i);
+ }
+}
+
+
+ /**
+ * Returns a submatrix.
+ *
+ * @param i0 Initial row index
+ * @param i1 Final row index
+ * @param j0 Initial column index
+ * @param j1 Final column index
+ * @return A(i0:i1,j0:j1)
+ * @exception ArrayIndexOutOfBoundsException Submatrix indices
+ */
+ public Matrix getMatrix(int i0, int i1, int j0, int j1)
+ {
+ Matrix X = new Matrix(i1 - i0 + 1, j1 - j0 + 1);
+ double[][] B = X.getArray();
+ try
+ {
+ for (int i = i0; i <= i1; i++)
+ {
+ for (int j = j0; j <= j1; j++)
+ {
+ B[i - i0][j - j0] = A[i][j];
+ }
+ }
+ } catch (ArrayIndexOutOfBoundsException e)
+ {
+ throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+ }
+ return X;
+ }
+
+// /**
+// * Returns a submatrix.
+// *
+// * @param r Array of row indices.
+// * @param c Array of column indices.
+// * @return A(r(:),c(:))
+// * @exception ArrayIndexOutOfBoundsException Submatrix indices
+// */
+// public Matrix getMatrix(int[] r, int[] c)
+// {
+// Matrix X = new Matrix(r.length, c.length);
+// double[][] B = X.getArray();
+// try
+// {
+// for (int i = 0; i < r.length; i++)
+// {
+// for (int j = 0; j < c.length; j++)
+// {
+// B[i][j] = A[r[i]][c[j]];
+// }
+// }
+// } catch (ArrayIndexOutOfBoundsException e)
+// {
+// throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+// }
+// return X;
+// }
+//
+// /**
+// * Returns a submatrix.
+// *
+// * @param i0 Initial row index
+// * @param i1 Final row index
+// * @param c Array of column indices.
+// * @return A(i0:i1,c(:))
+// * @exception ArrayIndexOutOfBoundsException Submatrix indices
+// */
+// public Matrix getMatrix(int i0, int i1, int[] c)
+// {
+// Matrix X = new Matrix(i1 - i0 + 1, c.length);
+// double[][] B = X.getArray();
+// try
+// {
+// for (int i = i0; i <= i1; i++)
+// {
+// for (int j = 0; j < c.length; j++)
+// {
+// B[i - i0][j] = A[i][c[j]];
+// }
+// }
+// } catch (ArrayIndexOutOfBoundsException e)
+// {
+// throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+// }
+// return X;
+// }
+//
+ /**
+ * Returns a submatrix.
+ *
+ * @param r Array of row indices.
+ * @param j0 Initial column index
+ * @param j1 Final column index
+ * @return A(r(:),j0:j1)
+ * @exception ArrayIndexOutOfBoundsException Submatrix indices
+ */
+ public Matrix getMatrix(int[] r, int j0, int j1)
+ {
+ Matrix X = new Matrix(r.length, j1 - j0 + 1);
+ double[][] B = X.getArray();
+ try
+ {
+ for (int i = 0; i < r.length; i++)
+ {
+ for (int j = j0; j <= j1; j++)
+ {
+ B[i][j - j0] = A[r[i]][j];
+ }
+ }
+ } catch (ArrayIndexOutOfBoundsException e)
+ {
+ throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+ }
+ return X;
+ }
+
+ /**
+ * Sets a single element.
+ *
+ * @param i Row index.
+ * @param j Column index.
+ * @param s A(i,j).
+ * @exception ArrayIndexOutOfBoundsException
+ */
+ public void set(int i, int j, double s)
+ {
+ A[i][j] = s;
+ }
+
+// /**
+// * Sets a submatrix.
+// *
+// * @param i0 Initial row index
+// * @param i1 Final row index
+// * @param j0 Initial column index
+// * @param j1 Final column index
+// * @param X A(i0:i1,j0:j1)
+// * @exception ArrayIndexOutOfBoundsException Submatrix indices
+// */
+// public void setMatrix(int i0, int i1, int j0, int j1, Matrix X)
+// {
+// try
+// {
+// for (int i = i0; i <= i1; i++)
+// {
+// for (int j = j0; j <= j1; j++)
+// {
+// A[i][j] = X.get(i - i0, j - j0);
+// }
+// }
+// } catch (ArrayIndexOutOfBoundsException e)
+// {
+// throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+// }
+// }
+//
+// /**
+// * Sets a submatrix.
+// *
+// * @param r Array of row indices.
+// * @param c Array of column indices.
+// * @param X A(r(:),c(:))
+// * @exception ArrayIndexOutOfBoundsException Submatrix indices
+// */
+// public void setMatrix(int[] r, int[] c, Matrix X)
+// {
+// try
+// {
+// for (int i = 0; i < r.length; i++)
+// {
+// for (int j = 0; j < c.length; j++)
+// {
+// A[r[i]][c[j]] = X.get(i, j);
+// }
+// }
+// } catch (ArrayIndexOutOfBoundsException e)
+// {
+// throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+// }
+// }
+//
+// /**
+// * Sets a submatrix.
+// *
+// * @param r Array of row indices.
+// * @param j0 Initial column index
+// * @param j1 Final column index
+// * @param X A(r(:),j0:j1)
+// * @exception ArrayIndexOutOfBoundsException Submatrix indices
+// */
+// public void setMatrix(int[] r, int j0, int j1, Matrix X)
+// {
+// try
+// {
+// for (int i = 0; i < r.length; i++)
+// {
+// for (int j = j0; j <= j1; j++)
+// {
+// A[r[i]][j] = X.get(i, j - j0);
+// }
+// }
+// } catch (ArrayIndexOutOfBoundsException e)
+// {
+// throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+// }
+// }
+//
+// /**
+// * Sets a submatrix.
+// *
+// * @param i0 Initial row index
+// * @param i1 Final row index
+// * @param c Array of column indices.
+// * @param X A(i0:i1,c(:))
+// * @exception ArrayIndexOutOfBoundsException Submatrix indices
+// */
+// public void setMatrix(int i0, int i1, int[] c, Matrix X)
+// {
+// try
+// {
+// for (int i = i0; i <= i1; i++)
+// {
+// for (int j = 0; j < c.length; j++)
+// {
+// A[i][c[j]] = X.get(i - i0, j);
+// }
+// }
+// } catch (ArrayIndexOutOfBoundsException e)
+// {
+// throw new ArrayIndexOutOfBoundsException("Submatrix indices");
+// }
+// }
+//
+ /**
+ * Returns the transpose of the matrix. The elements of this matrix remain
+ * unchanged.
+ *
+ * @return a new matrix A<sup>T</sup>
+ */
+ public Matrix transpose()
+ {
+ Matrix X = new Matrix(n, m);
+ double[][] C = X.getArray();
+ for (int i = 0; i < m; i++)
+ {
+ for (int j = 0; j < n; j++)
+ {
+ C[j][i] = A[i][j];
+ }
+ }
+ return X;
+ }
+
+ /**
+ * Transpose the matrix. The elements of this matrix
+ * are changed in place.
+ *
+ */
+ public void transposeInPlace()
+ {
+ double[][] C = getArrayCopy();
+ for (int i = 0; i < m; i++)
+ {
+ for (int j = 0; j < n; j++)
+ {
+ A[j][i] = C[i][j];
+ }
+ }
+ }
+
+// /**
+// * One norm
+// *
+// * @return maximum column sum.
+// */
+// public double norm1()
+// {
+// double f = 0;
+// for (int j = 0; j < n; j++)
+// {
+// double s = 0;
+// for (int i = 0; i < m; i++)
+// {
+// s += Math.abs(A[i][j]);
+// }
+// f = Math.max(f, s);
+// }
+// return f;
+// }
+//
+// /**
+// * Two norm
+// *
+// * @return maximum singular value.
+// */
+// public double norm2()
+// {
+// return (new SingularValueDecomposition(this).norm2());
+// }
+//
+// /**
+// * Infinity norm
+// *
+// * @return maximum row sum.
+// */
+// public double normInf()
+// {
+// double f = 0;
+// for (int i = 0; i < m; i++)
+// {
+// double s = 0;
+// for (int j = 0; j < n; j++)
+// {
+// s += Math.abs(A[i][j]);
+// }
+// f = Math.max(f, s);
+// }
+// return f;
+// }
+//
+// /**
+// * Frobenius norm
+// *
+// * @return sqrt of sum of squares of all elements.
+// */
+// public double normF()
+// {
+// double f = 0;
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// f = hypot(f, A[i][j]);
+// }
+// }
+// return f;
+// }
+//
+ /**
+ * Unary minus
+ *
+ * @return -A
+ */
+ public Matrix uminus()
+ {
+ Matrix X = new Matrix(m, n);
+ double[][] C = X.getArray();
+ for (int i = 0; i < m; i++)
+ {
+ for (int j = 0; j < n; j++)
+ {
+ C[i][j] = -A[i][j];
+ }
+ }
+ return X;
+ }
+
+ /**
+ * C = A + B
+ *
+ * @param B another matrix
+ * @return A + B
+ */
+ public Matrix plus(Matrix B)
+ {
+ checkMatrixDimensions(B);
+ Matrix X = new Matrix(m, n);
+ double[][] C = X.getArray();
+ for (int i = 0; i < m; i++)
+ {
+ for (int j = 0; j < n; j++)
+ {
+ C[i][j] = A[i][j] + B.A[i][j];
+ }
+ }
+ return X;
+ }
+
+// /**
+// * A = A + B
+// *
+// * @param B another matrix
+// * @return A + B
+// */
+// public Matrix plusEquals(Matrix B)
+// {
+// checkMatrixDimensions(B);
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// A[i][j] = A[i][j] + B.A[i][j];
+// }
+// }
+// return this;
+// }
+//
+ /**
+ * C = A - B
+ *
+ * @param B another matrix
+ * @return A - B
+ */
+ public Matrix minus(Matrix B)
+ {
+ checkMatrixDimensions(B);
+ Matrix X = new Matrix(m, n);
+ double[][] C = X.getArray();
+ for (int i = 0; i < m; i++)
+ {
+ for (int j = 0; j < n; j++)
+ {
+ C[i][j] = A[i][j] - B.A[i][j];
+ }
+ }
+ return X;
+ }
+
+// /**
+// * A = A - B
+// *
+// * @param B another matrix
+// * @return A - B
+// */
+// public Matrix minusEquals(Matrix B)
+// {
+// checkMatrixDimensions(B);
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// A[i][j] = A[i][j] - B.A[i][j];
+// }
+// }
+// return this;
+// }
+//
+// /**
+// * Element-by-element multiplication, C = A.*B
+// *
+// * @param B another matrix
+// * @return A.*B
+// */
+// public Matrix arrayTimes(Matrix B)
+// {
+// checkMatrixDimensions(B);
+// Matrix X = new Matrix(m, n);
+// double[][] C = X.getArray();
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// C[i][j] = A[i][j] * B.A[i][j];
+// }
+// }
+// return X;
+// }
+//
+// /**
+// * Element-by-element multiplication in place, A = A.*B
+// *
+// * @param B another matrix
+// * @return A.*B
+// */
+// public Matrix arrayTimesEquals(Matrix B)
+// {
+// checkMatrixDimensions(B);
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// A[i][j] = A[i][j] * B.A[i][j];
+// }
+// }
+// return this;
+// }
+//
+// /**
+// * Element-by-element right division, C = A./B
+// *
+// * @param B another matrix
+// * @return A./B
+// */
+// public Matrix arrayRightDivide(Matrix B)
+// {
+// checkMatrixDimensions(B);
+// Matrix X = new Matrix(m, n);
+// double[][] C = X.getArray();
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// C[i][j] = A[i][j] / B.A[i][j];
+// }
+// }
+// return X;
+// }
+//
+// /**
+// * Element-by-element right division in place, A = A./B
+// *
+// * @param B another matrix
+// * @return A./B
+// */
+// public Matrix arrayRightDivideEquals(Matrix B)
+// {
+// checkMatrixDimensions(B);
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// A[i][j] = A[i][j] / B.A[i][j];
+// }
+// }
+// return this;
+// }
+//
+// /**
+// * Element-by-element left division, C = A.\B
+// *
+// * @param B another matrix
+// * @return A.\B
+// */
+// public Matrix arrayLeftDivide(Matrix B)
+// {
+// checkMatrixDimensions(B);
+// Matrix X = new Matrix(m, n);
+// double[][] C = X.getArray();
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// C[i][j] = B.A[i][j] / A[i][j];
+// }
+// }
+// return X;
+// }
+//
+// /**
+// * Element-by-element left division in place, A = A.\B
+// *
+// * @param B another matrix
+// * @return A.\B
+// */
+// public Matrix arrayLeftDivideEquals(Matrix B)
+// {
+// checkMatrixDimensions(B);
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// A[i][j] = B.A[i][j] / A[i][j];
+// }
+// }
+// return this;
+// }
+//
+ /**
+ * Multiply a matrix by a scalar, C = s*A
+ *
+ * @param s scalar
+ * @return s*A
+ */
+ public Matrix times(double s)
+ {
+ Matrix X = new Matrix(m, n);
+ double[][] C = X.getArray();
+ for (int i = 0; i < m; i++)
+ {
+ for (int j = 0; j < n; j++)
+ {
+ C[i][j] = s * A[i][j];
+ }
+ }
+ return X;
+ }
+
+// /**
+// * Multiply a matrix by a scalar in place, A = s*A
+// *
+// * @param s scalar
+// * @return replace A by s*A
+// */
+// public Matrix timesEquals(double s)
+// {
+// for (int i = 0; i < m; i++)
+// {
+// for (int j = 0; j < n; j++)
+// {
+// A[i][j] = s * A[i][j];
+// }
+// }
+// return this;
+// }
+//
+ /**
+ * Linear algebraic matrix multiplication, A * B
+ *
+ * @param B another matrix
+ * @return Matrix product, A * B
+ * @exception IllegalArgumentException Matrix inner dimensions must agree.
+ */
+ public Matrix times(Matrix B)
+ {
+ if (B.m != n)
+ {
+ throw new IllegalArgumentException("Matrix inner dimensions must agree.");
+ }
+ Matrix X = new Matrix(m, B.n);
+ double[][] C = X.getArray();
+ double[] Bcolj = new double[n];
+ for (int j = 0; j < B.n; j++)
+ {
+ for (int k = 0; k < n; k++)
+ {
+ Bcolj[k] = B.A[k][j];
+ }
+ for (int i = 0; i < m; i++)
+ {
+ double[] Arowi = A[i];
+ double s = 0;
+ for (int k = 0; k < n; k++)
+ {
+ s += Arowi[k] * Bcolj[k];
+ }
+ C[i][j] = s;
+ }
+ }
+ return X;
+ }
+
+// /**
+// * Calculates the vector y = A.x
+// *
+// * @param x
+// * @return a new vector y
[truncated at 1000 lines; 556 more skipped]
java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/QRDecomposition.java (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/QRDecomposition.java 2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,218 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+
+/** QR Decomposition.
+<P>
+ For an m-by-n matrix A with m >= n, the QR decomposition is an m-by-n
+ orthogonal matrix Q and an n-by-n upper triangular matrix R so that
+ A = Q*R.
+<P>
+ The QR decompostion always exists, even if the matrix does not have
+ full rank, so the constructor will never fail. The primary use of the
+ QR decomposition is in the least squares solution of nonsquare systems
+ of simultaneous linear equations. This will fail if isFullRank()
+ returns false.
+ @version $Id: QRDecomposition.java,v 1.1.1.1 2010/11/30 21:31:59 jeremy Exp $
+*/
+
+public class QRDecomposition implements java.io.Serializable {
+
+/* ------------------------
+ Class variables
+ * ------------------------ */
+
+ /** Array for internal storage of decomposition.
+ @serial internal array storage.
+ */
+ private double[][] QR;
+
+ /** Row and column dimensions.
+ @serial column dimension.
+ @serial row dimension.
+ */
+ private int m, n;
+
+ /** Array for internal storage of diagonal of R.
+ @serial diagonal of R.
+ */
+ private double[] Rdiag;
+
+/* ------------------------
+ Constructor
+ * ------------------------ */
+
+ /** QR Decomposition, computed by Householder reflections.
+ @param A Rectangular matrix
+ */
+
+ public QRDecomposition (Matrix A) {
+ // Initialize.
+ QR = A.getArrayCopy();
+ m = A.getRowDimension();
+ n = A.getColumnDimension();
+ Rdiag = new double[n];
+
+ // Main loop.
+ for (int k = 0; k < n; k++) {
+ // Compute 2-norm of k-th column without under/overflow.
+ double nrm = 0;
+ for (int i = k; i < m; i++) {
+ nrm = Matrix.hypot(nrm,QR[i][k]);
+ }
+
+ if (nrm != 0.0) {
+ // Form k-th Householder vector.
+ if (QR[k][k] < 0) {
+ nrm = -nrm;
+ }
+ for (int i = k; i < m; i++) {
+ QR[i][k] /= nrm;
+ }
+ QR[k][k] += 1.0;
+
+ // Apply transformation to remaining columns.
+ for (int j = k+1; j < n; j++) {
+ double s = 0.0;
+ for (int i = k; i < m; i++) {
+ s += QR[i][k]*QR[i][j];
+ }
+ s = -s/QR[k][k];
+ for (int i = k; i < m; i++) {
+ QR[i][j] += s*QR[i][k];
+ }
+ }
+ }
+ Rdiag[k] = -nrm;
+ }
+ }
+
+/* ------------------------
+ Public Methods
+ * ------------------------ */
+
+ /** Is the matrix full rank?
+ @return true if R, and hence A, has full rank.
+ */
+
+ public boolean isFullRank () {
+ for (int j = 0; j < n; j++) {
+ if (Rdiag[j] == 0)
+ return false;
+ }
+ return true;
+ }
+
+ /** Return the Householder vectors
+ @return Lower trapezoidal matrix whose columns define the reflections
+ */
+
+ public Matrix getH () {
+ Matrix X = new Matrix(m,n);
+ double[][] H = X.getArray();
+ for (int i = 0; i < m; i++) {
+ for (int j = 0; j < n; j++) {
+ if (i >= j) {
+ H[i][j] = QR[i][j];
+ } else {
+ H[i][j] = 0.0;
+ }
+ }
+ }
+ return X;
+ }
+
+ /** Return the upper triangular factor
+ @return R
+ */
+
+ public Matrix getR () {
+ Matrix X = new Matrix(n,n);
+ double[][] R = X.getArray();
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < n; j++) {
+ if (i < j) {
+ R[i][j] = QR[i][j];
+ } else if (i == j) {
+ R[i][j] = Rdiag[i];
+ } else {
+ R[i][j] = 0.0;
+ }
+ }
+ }
+ return X;
+ }
+
+ /** Generate and return the (economy-sized) orthogonal factor
+ @return Q
+ */
+
+ public Matrix getQ () {
+ Matrix X = new Matrix(m,n);
+ double[][] Q = X.getArray();
+ for (int k = n-1; k >= 0; k--) {
+ for (int i = 0; i < m; i++) {
+ Q[i][k] = 0.0;
+ }
+ Q[k][k] = 1.0;
+ for (int j = k; j < n; j++) {
+ if (QR[k][k] != 0) {
+ double s = 0.0;
+ for (int i = k; i < m; i++) {
+ s += QR[i][k]*Q[i][j];
+ }
+ s = -s/QR[k][k];
+ for (int i = k; i < m; i++) {
+ Q[i][j] += s*QR[i][k];
+ }
+ }
+ }
+ }
+ return X;
+ }
+
+ /** Least squares solution of A*X = B
+ @param B A Matrix with as many rows as A and any number of columns.
+ @return X that minimizes the two norm of Q*R*X-B.
+ @exception IllegalArgumentException Matrix row dimensions must agree.
+ @exception RuntimeException Matrix is rank deficient.
+ */
+
+ public Matrix solve (Matrix B) {
+ if (B.getRowDimension() != m) {
+ throw new IllegalArgumentException("Matrix row dimensions must agree.");
+ }
+ if (!this.isFullRank()) {
+ throw new RuntimeException("Matrix is rank deficient.");
+ }
+
+ // Copy right hand side
+ int nx = B.getColumnDimension();
+ double[][] X = B.getArrayCopy();
+
+ // Compute Y = transpose(Q)*B
+ for (int k = 0; k < n; k++) {
+ for (int j = 0; j < nx; j++) {
+ double s = 0.0;
+ for (int i = k; i < m; i++) {
+ s += QR[i][k]*X[i][j];
+ }
+ s = -s/QR[k][k];
+ for (int i = k; i < m; i++) {
+ X[i][j] += s*QR[i][k];
+ }
+ }
+ }
+ // Solve R*X = Y;
+ for (int k = n-1; k >= 0; k--) {
+ for (int j = 0; j < nx; j++) {
+ X[k][j] /= Rdiag[k];
+ }
+ for (int i = 0; i < k; i++) {
+ for (int j = 0; j < nx; j++) {
+ X[i][j] -= X[k][j]*QR[i][k];
+ }
+ }
+ }
+ return (new Matrix(X,n,nx).getMatrix(0,n-1,0,nx-1));
+ }
+}
java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/SymMatrix.java (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/SymMatrix.java 2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,66 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+/**
+ *
+ * @author Norman A Graf
+ *
+ * @version $Id:
+ */
+public class SymMatrix extends Matrix implements java.io.Serializable
+{
+
+ public SymMatrix(int n)
+ {
+ super(n, n);
+ }
+
+ public SymMatrix(SymMatrix smat)
+ {
+ super(smat.getRowDimension(), smat.getColumnDimension());
+ for (int i = 0; i < m; i++)
+ {
+ for (int j = 0; j < n; j++)
+ {
+ A[i][j] = smat.get(i, j);
+ }
+ }
+ }
+
+ public SymMatrix(Matrix mat)
+ {
+ super(mat.getRowDimension(), mat.getColumnDimension());
+ for (int i = 0; i < m; i++)
+ {
+ for (int j = 0; j < n; j++)
+ {
+ A[i][j] = mat.get(i, j);
+ }
+ }
+ }
+
+ @Override
+ public void set(int i, int j, double s)
+ {
+ super.set(i, j, s);
+ super.set(j, i, s);
+ }
+
+ public void setToIdentity()
+ {
+ for (int i = 0; i < m; i++)
+ {
+ for (int j = 0; j < n; j++)
+ {
+ A[i][j] = (i == j ? 1.0 : 0.0);
+ }
+ }
+ }
+
+ //Calculate B * (this) * B^T , final matrix will be (nrowsb x nrowsb)
+ //TODO see if this needs to be made more efficient
+ public SymMatrix Similarity(Matrix b)
+ {
+ SymMatrix X = new SymMatrix(b.times(this.times(b.transpose())));
+ return X;
+ }
+}
java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/VMatrix.java (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/VMatrix.java 2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,201 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+import static java.lang.Math.min;
+import java.util.ArrayList;
+
+/**
+ * Simple Vector based on ArrayList
+ *
+ * @author Norman A. Graf
+ *
+ * @version $Id$
+ */
+public class VMatrix
+{
+
+ private int numRows;
+ private int numCols;
+ //TODO replace with a simple double[]
+ private ArrayList theVec;
+
+ public VMatrix(int nRows, int nCols)
+ {
+ numRows = nRows;
+ numCols = nCols;
+ theVec = new ArrayList(nRows * nCols);
+ for (int i = 0; i < numRows * nCols; ++i)
+ {
+ theVec.add(0.);
+ }
+ }
+
+public VMatrix(VMatrix m)
+ {
+ numRows = m.numRows;
+ numCols = m.numCols;
+ theVec = new ArrayList(numRows * numCols);
+ for (int i = 0; i < numRows; ++i)
+ {
+ for(int j=0; j<numCols; ++j)
+ {
+ theVec.set(numCols * i + j, m.get(i, j));
+ }
+ }
+ }
+
+ public VMatrix copy()
+ {
+ VMatrix aResult = new VMatrix(numRows, numCols);
+ for (int i = 0; i < numRows; ++i)
+ {
+ for (int j = 0; j < numCols; ++j)
+ {
+ {
+ aResult.set(i, j, get(i, j));
+ }
+ }
+ }
+ return aResult;
+ }
+
+ /// Resize Matrix.
+ /**
+ * \param [in] nRows Number of rows. \param [in] nCols Number of columns.
+ */
+ // TODO understand what this method is supposed to do.
+ // may not need it as ArrayList already automatically resizes...
+ public void resize(int nRows, int nCols)
+ {
+ numRows = nRows;
+ numCols = nCols;
+ theVec = new ArrayList(numRows * nCols);
+ for (int i = 0; i < numRows * nCols; ++i)
+ {
+ theVec.add(0.);
+ }
+ }
+
+/// Get transposed matrix.
+ /**
+ * \return Transposed matrix.
+ */
+ public VMatrix transpose()
+ {
+ VMatrix aResult = new VMatrix(numCols, numRows);
+ for (int i = 0; i < numRows; ++i)
+ {
+ for (int j = 0; j < numCols; ++j)
+ {
+ //System.out.println("row: "+i+" col: "+j+" val: "+theVec.get(numCols * i + j));
+ aResult.set(j, i, (double) theVec.get(numCols * i + j));
+ }
+ }
+ return aResult;
+ }
+
+ public void set(int row, int col, double val)
+ {
+ theVec.set(numCols * row + col, val);
+ }
+
+ public void addTo(int row, int col, double val)
+ {
+ theVec.set(numCols * row + col, (double) theVec.get(numCols * row + col)+val);
+ }
+ public void subFrom(int row, int col, double val)
+ {
+ theVec.set(numCols * row + col, (double) theVec.get(numCols * row + col)-val);
+ }
+
+ public double get(int row, int col)
+ {
+ return (double) theVec.get(numCols * row + col);
+ }
+
+/// Get number of rows.
+ /**
+ * \return Number of rows.
+ */
+ int getNumRows()
+ {
+ return numRows;
+ }
+
+/// Get number of columns.
+ /**
+ * \return Number of columns.
+ */
+ int getNumCols()
+ {
+ return numCols;
+ }
+
+/// Multiplication Matrix*Vector.
+ VVector times(VVector aVector)
+ {
+ VVector aResult = new VVector(numRows);
+ for (int i = 0; i < numRows; ++i)
+ {
+ double sum = 0.0;
+ for (int j = 0; j < numCols; ++j)
+ {
+ sum += (double) theVec.get(numCols * i + j) * aVector.get(j);
+ }
+ aResult.set(i, sum);
+ }
+ return aResult;
+ }
+
+// Multiplication Matrix*Matrix.
+ VMatrix times(VMatrix aMatrix)
+ {
+
+ VMatrix aResult = new VMatrix(numRows, aMatrix.numCols);
+ for (int i = 0; i < numRows; ++i)
+ {
+ for (int j = 0; j < aMatrix.numCols; ++j)
+ {
+ double sum = 0.0;
+ for (int k = 0; k < numCols; ++k)
+ {
+ sum += (double) theVec.get(numCols * i + k) * aMatrix.get(k, j);
+ }
+ aResult.set(i, j, sum);
+ }
+ }
+ return aResult;
+ }
+
+/// Addition Matrix+Matrix.
+ VMatrix plus(VMatrix aMatrix)
+ {
+ VMatrix aResult = new VMatrix(numRows, numCols);
+ for (int i = 0; i < numRows; ++i)
+ {
+ for (int j = 0; j < numCols; ++j)
+ {
+ aResult.set(i, j, (double) theVec.get(numCols * i + j) + (double) aMatrix.get(i, j));
+ }
+ }
+ return aResult;
+ }
+
+/// Print matrix.
+ public void print()
+ {
+ System.out.println(" VMatrix: " + numRows + "*" + numCols);
+ for (int i = 0; i < numRows; ++i)
+ {
+ for (int j = 0; j < numCols; ++j)
+ {
+ if (j % 5 == 0)
+ {
+ System.out.format("%n%4d " + "," + "%4d" + " - " + "%4d" + " : ", i, j, min(j + 4, numCols));
+ }
+ System.out.format("%13f", theVec.get(numCols * i + j));
+ }
+ }
+ System.out.print("\n\n\n");
+ }
+
+}
java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/VSymMatrix.java (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/VSymMatrix.java 2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,303 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+import static java.lang.Math.min;
+import static java.lang.Math.max;
+import static java.lang.Math.abs;
+import java.util.ArrayList;
+
+/**
+ * Simple symmetric Matrix based on ArrayList
+ *
+ * @author Norman A. Graf
+ *
+ * @version $Id$
+ */
+public class VSymMatrix
+{
+
+ private int numRows;
+ //TODO replace with a simple double[]
+ private ArrayList theVec;
+
+ public VSymMatrix(int nRows)
+ {
+ numRows = nRows;
+ theVec = new ArrayList((nRows * nRows + nRows) / 2);
+ for (int i = 0; i < (nRows * nRows + nRows) / 2; ++i)
+ {
+ theVec.add(i, 0.);
+ }
+ }
+
+ public VSymMatrix copy()
+ {
+ VSymMatrix aResult = new VSymMatrix(numRows);
+ for (int i = 0; i < numRows; ++i)
+ {
+ for (int j = 0; j < numRows; ++j)
+ {
+ {
+ aResult.set(i, j, get(i, j));
+ }
+ }
+ }
+ return aResult;
+ }
+
+/// Resize symmetric matrix.
+ /**
+ * \param [in] nRows Number of rows.
+ */
+ // TODO understand what this method is supposed to do.
+ // may not need it as ArrayList already automatically resizes...
+ void resize(int nRows)
+ {
+ numRows = nRows;
+ theVec = new ArrayList(nRows * nRows + nRows);
+ for (int i = 0; i < nRows * nRows + nRows; ++i)
+ {
+ theVec.add(0.);
+ }
+ }
+
+/// Get number of rows (= number of colums).
+ /**
+ * \return Number of rows.
+ */
+ int getNumRows()
+ {
+ return numRows;
+ }
+
+ public void set(int row, int col, double val)
+ {
+ theVec.set((row * row + row) / 2 + col, val);
+ }
+
+ public void addTo(int row, int col, double val)
+ {
+ theVec.set((row * row + row) / 2 + col, (double) theVec.get((row * row + row) / 2 + col) + val);
+ }
+
+ public void subFrom(int row, int col, double val)
+ {
+ theVec.set((row * row + row) / 2 + col, (double) theVec.get((row * row + row) / 2 + col) - val);
+ }
+
+ public double get(int row, int col)
+ {
+ return (double) theVec.get((row * row + row) / 2 + col);
+ }
+
+/// Print matrix.
+ void print()
+ {
+ System.out.println(" VSymMatrix: " + numRows + "*" + numRows);
+ for (int i = 0; i < numRows; ++i)
+ {
+ for (int j = 0; j <= i; ++j)
+ {
+ if (j % 5 == 0)
+ {
+ System.out.format("%n%4d " + "," + "%4d" + " - " + "%4d" + " : ", i, j, min(j + 4, i));
+ }
+ System.out.format("%13f", theVec.get((i * i + i) / 2 + j));
+ }
+ }
+ System.out.print("\n\n\n");
+ }
+
+/// Subtraction SymMatrix-(sym)Matrix.
+ VSymMatrix minus(VMatrix aMatrix)
+ {
+ VSymMatrix aResult = new VSymMatrix(numRows);
+ for (int i = 0; i < numRows; ++i)
+ {
+ for (int j = 0; j <= i; ++j)
+ {
+ aResult.set(i, j, (double) theVec.get((i * i + i) / 2 + j) - (double) aMatrix.get(i, j));
+ }
+ }
+ return aResult;
+ }
+
+/// Multiplication SymMatrix*Vector.
+ VVector times(VVector aVector)
+ {
+ VVector aResult = new VVector(numRows);
+ for (int i = 0; i < numRows; ++i)
+ {
+ aResult.set(i, (double) theVec.get((i * i + i) / 2 + i) * (double) aVector.get(i));
+ for (int j = 0; j < i; ++j)
+ {
+ aResult.set(j, aResult.get(j) + (double) theVec.get((i * i + i) / 2 + j) * aVector.get(i));
+ aResult.set(i, aResult.get(i) + (double) theVec.get((i * i + i) / 2 + j) * aVector.get(j));
+ }
+ }
+ return aResult;
+ }
+
+/// Multiplication SymMatrix*Matrix.
+ VMatrix times(VMatrix aMatrix)
+ {
+ int nCol = aMatrix.getNumCols();
+ VMatrix aResult = new VMatrix(numRows, nCol);
+ for (int l = 0; l < nCol; ++l)
+ {
+ for (int i = 0; i < numRows; ++i)
+ {
+ aResult.set(i, l, (double) theVec.get((i * i + i) / 2 + i) * (double) aMatrix.get(i, l));
+ for (int j = 0; j < i; ++j)
+ {
+ aResult.set(j, l, aResult.get(j, l) + (double) theVec.get((i * i + i) / 2 + j) * aMatrix.get(i, l));
+ aResult.set(i, l, aResult.get(i, l) + (double) theVec.get((i * i + i) / 2 + j) * aMatrix.get(j, l));
+ }
+ }
+ }
+ return aResult;
+ }
+
+ /*============================================================================
+ from mpnum.F (MillePede-II by V. Blobel, Univ. Hamburg)
+ ============================================================================*/
+/// Matrix inversion.
+ /**
+ * Invert symmetric N-by-N matrix V in symmetric storage mode V(1) = V11,
+ * V(2) = V12, V(3) = V22, V(4) = V13, . . . replaced by inverse matrix
+ *
+ * Method of solution is by elimination selecting the pivot on the diagonal
+ * each stage. The rank of the matrix is returned in NRANK. For NRANK ne N,
+ * all remaining rows and cols of the resulting matrix V are set to zero.
+ * \exception 1 : matrix is singular. \return Rank of matrix.
+ */
+ public int invert()
+ {
+
+ final double eps = 1.0E-10;
+ int aSize = numRows;
+ int[] next = new int[aSize];
+ double[] diag = new double[aSize];
+ int nSize = aSize;
+
+ int first = 1;
+ for (int i = 1; i <= nSize; ++i)
+ {
+ next[i - 1] = i + 1; // set "next" pointer
+ diag[i - 1] = abs((double) theVec.get((i * i + i) / 2 - 1)); // save abs of diagonal elements
+ }
+ next[aSize - 1] = -1; // end flag
+
+ int nrank = 0;
+ for (int i = 1; i <= nSize; ++i)
+ { // start of loop
+ int k1 = 0;
+ double vkk = 0.0;
+
+ int j1 = first;
+ int previous = 0;
+ int last = previous;
+ // look for pivot
+ while (j1 > 0)
+ {
+ int jj = (j1 * j1 + j1) / 2 - 1;
+ if (abs((double) theVec.get(jj)) > max(abs(vkk), eps * diag[j1 - 1]))
+ {
+ vkk = (double) theVec.get(jj);
+ k1 = j1;
+ last = previous;
+ }
+ previous = j1;
+ j1 = next[j1 - 1];
+ }
+ // pivot found
+ if (k1 > 0)
+ {
+ int kk = (k1 * k1 + k1) / 2 - 1;
+ if (last <= 0)
+ {
+ first = next[k1 - 1];
+ } else
+ {
+ next[last - 1] = next[k1 - 1];
+ }
+ next[k1 - 1] = 0; // index is used, reset
+ nrank++; // increase rank and ...
+
+ vkk = 1.0 / vkk;
+ theVec.set(kk, -vkk);
+ int jk = kk - k1;
+ int jl = -1;
+ for (int j = 1; j <= nSize; ++j)
+ { // elimination
+ if (j == k1)
+ {
+ jk = kk;
+ jl += j;
+ } else
+ {
+ if (j < k1)
+ {
+ ++jk;
+ } else
+ {
+ jk += j - 1;
+ }
+
+ double vjk = (double) theVec.get(jk);
+ theVec.set(jk, vkk * vjk);
+ int lk = kk - k1;
+ if (j >= k1)
+ {
+ for (int l = 1; l <= k1 - 1; ++l)
+ {
+ ++jl;
+ ++lk;
+ theVec.set(jl, (double) theVec.get(jl) - (double) theVec.get(lk) * vjk);
+ }
+ ++jl;
+ lk = kk;
+ for (int l = k1 + 1; l <= j; ++l)
+ {
+ ++jl;
+ lk += l - 1;
+ theVec.set(jl, (double) theVec.get(jl) - (double) theVec.get(lk) * vjk);
+ }
+ } else
+ {
+ for (int l = 1; l <= j; ++l)
+ {
+ ++jl;
+ ++lk;
+ theVec.set(jl, (double) theVec.get(jl) - (double) theVec.get(lk) * vjk);
+ }
+ }
+ }
+ }
+
+ } else
+ {
+ for (int k = 1; k <= nSize; ++k)
+ {
+ if (next[k - 1] >= 0)
+ {
+ int kk = (k * k - k) / 2 - 1;
+ for (int j = 1; j <= nSize; ++j)
+ {
+ if (next[j - 1] >= 0)
+ {
+ theVec.set(kk + j, 0.0); // clear matrix row/col
+ }
+ }
+ }
+ }
+ throw new RuntimeException("Symmetric matrix inversion is singular");//1; // singular
+ }
+ }
+ for (int ij = 0; ij < (nSize * nSize + nSize) / 2; ++ij)
+ {
+ theVec.set(ij, -(double) theVec.get(ij)); // finally reverse sign of all matrix elements
+ }
+ return nrank;
+ }
+
+}
java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/VVector.java (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/VVector.java 2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,129 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+import java.util.ArrayList;
+import java.util.List;
+import static java.lang.Math.min;
+
+/**
+ * Simple Vector based on ArrayList
+ *
+ * @author Norman A. Graf
+ *
+ * @version $Id$
+ */
+public class VVector
+{
+
+ private int numRows;
+ private ArrayList theVec;
+
+ public VVector(int nRows)
+ {
+ numRows = nRows;
+ theVec = new ArrayList(nRows);
+ for (int i = 0; i < numRows; ++i)
+ {
+ theVec.add(0.);
+ }
+ }
+
+ public VVector(VVector old)
+ {
+ numRows = old.numRows;
+ theVec = new ArrayList(old.theVec);
+ }
+
+ public VVector(List list)
+ {
+ theVec = new ArrayList(list);
+ theVec.trimToSize();
+ numRows = theVec.size();
+ }
+
+ public void set(int row, double val)
+ {
+ theVec.set(row, val);
+ }
+
+ public void addTo(int row, double val)
+ {
+ theVec.set(row, (double) theVec.get(row) + val);
+ }
+
+ public void subFrom(int row, double val)
+ {
+ theVec.set(row, (double) theVec.get(row) - val);
+ }
+
+ public double get(int row)
+ {
+ return (double) theVec.get(row);
+ }
+
+ //Get part of vector.
+ /**
+ * \param [in] len Length of part. \param [in] start Offset of part. \return
+ * Part of vector.
+ */
+ public VVector getVec(int len, int start)
+ {
+ return new VVector(theVec.subList(start, start + len - 1));
+
+ }
+
+/// Put part of vector.
+ /**
+ * \param [in] aVector Vector with part. \param [in] start Offset of part.
+ */
+ public void putVec(VVector aVector, int start)
+ {
+ theVec.addAll(start, aVector.theVec);
+ }
+
+/// Get number of rows.
+ /**
+ * \return Number of rows.
+ */
+ int getNumRows()
+ {
+ return numRows;
+ }
+
+/// Print vector.
+ public void print()
+ {
+ System.out.println(theVec.size());
+ for (int i = 0; i < numRows; ++i)
+ {
+ if (i % 5 == 0)
+ {
+ System.out.format("%n%4d " + " - " + "%4d" + " : ", i, min(i + 4, numRows));
+ }
+ System.out.format("%13f", theVec.get(i));
+ }
+ System.out.print("\n\n\n");
+ }
+
+/// Subtraction Vector-Vector.
+ VVector minus(VVector aVector)
+ {
+ VVector aResult = new VVector(numRows);
+ for (int i = 0; i < numRows; ++i)
+ {
+ aResult.set(i, (double) theVec.get(i) - aVector.get(i));
+ }
+ return aResult;
+ }
+
+/// Assignment Vector=Vector.
+ public VVector copy()
+ {
+ VVector aResult = new VVector(numRows);
+ for (int i = 0; i < numRows; ++i)
+ {
+ aResult.set(i, get(i));
+ }
+ return aResult;
+ }
+
+}
java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix
--- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/Vector.java (rev 0)
+++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/matrix/Vector.java 2014-08-28 15:31:06 UTC (rev 919)
@@ -0,0 +1,337 @@
+package org.hps.recon.tracking.gbl.matrix;
+
+import java.io.PrintWriter;
+
+/**
+ * Specializes the Matrix class to a vector.
+ *
+ * @author CKAllen
+ * @author Norman A. Graf (modifications for the gbl package)
+ * @version $Id$
+ */
+public class Vector extends Matrix implements java.io.Serializable
+{
+//
+ /**
+ * Constructs a column vector of zeros
+ *
+ *
+ * @param nSize vector size
+ *
+ */
+ public Vector(int nSize)
+ {
+ super(nSize, 1);
+ }
+
+// /**
+// * Constructs a constant column vector
+// *
+// * @param nSize vector size
+// * @param dblVal constant value
+// */
+// public Vector(int nSize, double dblVal)
+// {
+// super(nSize, 1, dblVal);
+// }
+//
+ public int size()
+ {
+ return getRowDimension();
+ }
+
+// public Vector getSub(int start, int end)
+// {
+// int size = end - start + 1;
+// Vector X = new Vector(size);
+// for (int i = 0; i < size; ++i) {
+// X.set(i, get(i + start, 0));
+// }
+// return X;
+// }
+//
+ public Vector minus(Vector v)
+ {
+ Vector x = copyVector();
+ for (int i = 0; i < v.size(); ++i) {
+ x.minusEquals(i, v.get(i));
+ }
+ return x;
+ }
+
+ public void plusEquals(int i, double val)
+ {
+ A[i][0] += val;
+ }
+
+ public void minusEquals(int i, double val)
+ {
+ A[i][0] -= val;
+ }
+
+ public Vector uminus()
+ {
+ Vector x = copyVector();
+ for (int i = 0; i < size(); ++i) {
+ A[i][0] = -A[i][0];
+ }
+ return x;
+ }
+
+ /**
+ * Constructs a Vector specified by the double array
+ *
+ * @param arrVals element values for vector
+ */
+ public Vector(double[] arrVals)
+ {
+ super(arrVals.length, 1);
+ for (int i = 0; i < arrVals.length; i++) {
+ super.set(i, 0, arrVals[i]);
+ }
+ }
+
+// /**
+// * Copy Constructor Constructs a new Vector initialized to the argument.
+// *
+// * @param vecInit initial value
+// */
+// public Vector(Vector vecInit)
+// {
+// this(vecInit.getSize());
+// for (int i = 0; i < vecInit.getSize(); i++) {
+// this.set(i, vecInit.get(i));
+// }
+// }
+//
+ /**
+ * Constructs a new Vector from a Matrix object. Vector is initialized to
+ * the first column of the matrix. This constructor is meant to take a
+ * column vector in Matrix form to the standard vector format.
+ *
+ * @param mat initial values
+ */
+ public Vector(Matrix mat)
+ {
+ super(mat.getRowDimension(), 1);
+ for (int i = 0; i < mat.getRowDimension(); i++) {
+ this.set(i, mat.get(i, 0));
+ }
+ }
+
+ /**
+ * Perform a deep copy of this Vector object
+ */
+ public Vector copyVector()
+ {
+ return new Vector(this);
+ }
+
+ /**
+ * Get size of Vector (number of elements)
+ */
+ public int getSize()
+ {
+ return super.getRowDimension();
+ }
+
+ /**
+ * Get individual element of a vector
+ *
+ * @param iIndex index of element
+ * @return value of element
+ * @exception ArrayIndexOutOfBoundsException iIndex is larger than vector
+ * size
+ */
+ public double get(int iIndex) throws ArrayIndexOutOfBoundsException
+ {
+ return this.get(iIndex, 0);
+ }
+//
+ /**
+ * Set individual element of a vector
+ *
+ * @param iIndex index of element
+ * @param dblVal new value of element
+ *
+ * @exception ArrayIndexOutOfBoundsException iIndex is larger than the
+ * vector
+ */
+ public void set(int iIndex, double dblVal) throws ArrayIndexOutOfBoundsException
+ {
+ super.set(iIndex, 0, dblVal);
+ }
+
+// /**
+// * Vector in-place addition
+// *
+// * @param vec Vector to add to this vector
+// *
+// * @exception IllegalArgumentException vec is not proper dimension
+// */
+// public void plusEquals(Vector vec) throws IllegalArgumentException
+// {
+// super.plusEquals(vec);
+// }
+//
+ /**
+ * Vector addition without destruction
+ *
+ * @param vec vector to add
+ *
+ * @exception IllegalArgumentException vec is not proper dimension
+ */
+
+ public Vector plus(Vector vec) throws IllegalArgumentException
+ {
+ return (Vector) super.plus(vec);
+ }
+
+ /**
+ * Scalar multiplication
+ *
+ * @param s scalar value
+ *
+ * @return result of scalar multiplication
+ */
+ public Vector timesScalar(double s)
+ {
+ return (Vector) super.times(s);
+ }
+
+// /**
+// * In place scalar multiplication
+// *
+// * @param s scalar
+// */
+// public void timesScalarEqual(double s)
+// {
+// this.timesEquals(s);
+// }
+//
+// /**
+// * Vector inner product.
+// *
+// * Computes the inner product of two vectors of the same dimension.
+// *
+// * @param vec second vector
+// *
+// * @return inner product of this vector and argument
+// *
+// * @exception IllegalArgumentException dimensions must agree
+// */
+// public double innerProd(Vector vec) throws IllegalArgumentException
+// {
+// int N; // vector dimensions
+// int n; // coordinate index
+// double dblSum; // running sum
+// N = vec.getSize();
+// if (this.getSize() != N) {
+// throw new IllegalArgumentException("Vector#innerProd() - unequal dimensions.");
+// }
+// dblSum = 0.0;
+// for (n = 0; n < N; n++) {
+// dblSum += this.get(n) * vec.get(n);
+// }
+// return dblSum;
+// }
+//
+// /**
+// *
+// * Vector outer product - computes the tensor product of two vector objects.
+// *
+// *
+// *
+// * Returns the value this*vec' where the prime indicates transposition
+// *
+// *
+// *
+// * @param vec right argument
+// *
+// *
+// *
+// * @return outer product *
+// *
+// *
+// * @exception IllegalArgumentException vector dimension must agree
+// *
+// */
+// public Matrix outerProd(Vector vec) throws IllegalArgumentException
+// {
+// return super.times(vec.transpose());
+// }
+//
+// /**
+// * *
+// * Vector left multiplication (post-multiply vector by matrix).
+// *
+// *
+// *
+// * @param mat matrix operator
+// *
+// *
+// *
+// * @return result of vector-matrix product
+// *
+// *
+// *
+// * @exception IllegalArgumentException dimensions must agree
+// *
+// */
+// public Vector leftMultiply(Matrix mat) throws IllegalArgumentException
+// {
+// Matrix matRes = this.times(mat).transpose();
+// return new Vector(matRes);
+// }
+//
+// /**
+// * Vector right multiplication (pre-multiply vector by matrix).
+// *
+// * @param mat matrix operator
+// *
+// * @return result of vector-matrix product
+// *
+// * @exception IllegalArgumentException dimensions must agree
+// */
+// public Vector rightMultiply(Matrix mat) throws IllegalArgumentException
+// {
+// Matrix matRes = mat.times(this);
+// return new Vector(matRes);
+// }
+//
+// /**
+// * Print the vector contents to an output stream, does not add new line.
+// *
+// * @param os output stream object
+// */
+// public void print(PrintWriter os)
+// {
+// // Create vector string
+// int indLast = this.getSize() - 1;
+// String strVec = "(";
+// for (int i = 0; i < indLast; i++) {
+// strVec = strVec + this.get(i) + ",";
+// }
+// strVec = strVec + this.get(indLast) + ")";
+// // Send to output stream
+// os.print(strVec);
+// }
+//
+// /**
+// * Print the vector contents to an output stream, add new line character.
+// *
+// * @param os output stream object
+// */
+// public void println(PrintWriter os)
+// {
+// // Create vector string
+// int indLast = this.getSize() - 1;
+// String strVec = "(";
+// for (int i = 0; i < indLast; i++) {
+// strVec = strVec + this.get(i) + ",";
+// }
+// strVec = strVec + this.get(indLast) + ")";
+// // Send to output stream
+// os.println(strVec);
+// }
+}
SVNspam 0.1