Author: [log in to unmask] Date: Thu Feb 5 19:17:21 2015 New Revision: 2058 Log: First version of GBL fits with global derivatives on all size trivial degrees of freedom. Still work in progress, needs to cleanup and fix of a sign-problem and test binary result. Modified: java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/HpsGblRefitter.java Modified: java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/HpsGblRefitter.java ============================================================================= --- java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/HpsGblRefitter.java (original) +++ java/trunk/tracking/src/main/java/org/hps/recon/tracking/gbl/HpsGblRefitter.java Thu Feb 5 19:17:21 2015 @@ -5,6 +5,7 @@ import static java.lang.Math.sqrt; import hep.physics.vec.BasicHep3Vector; import hep.physics.vec.Hep3Vector; +import hep.physics.vec.VecOp; import java.util.ArrayList; import java.util.HashMap; @@ -20,6 +21,7 @@ import org.lcsim.event.LCRelation; import org.lcsim.event.Track; import org.lcsim.geometry.Detector; +import org.lcsim.geometry.compact.converter.MilleParameter; import org.lcsim.util.Driver; import org.lcsim.util.log.LogUtil; @@ -29,6 +31,7 @@ * be present in the event. * * @author Norman A Graf + * @author Per Hansson Adrian <[log in to unmask]> * * @version $Id$ */ @@ -214,14 +217,21 @@ if (_debug) { System.out.println("HpsGblFitter: " + "Path length step " + step + " from " + s + " to " + strip.getPath3D()); } + + // get measurement frame unit vectors + Hep3Vector u = strip.getU(); + Hep3Vector v = strip.getV(); + Hep3Vector w = strip.getW(); + + // Measurement direction (perpendicular and parallel to strip direction) Matrix mDir = new Matrix(2, 3); - mDir.set(0, 0, strip.getUx()); - mDir.set(0, 1, strip.getUy()); - mDir.set(0, 2, strip.getUz()); - mDir.set(1, 0, strip.getVx()); - mDir.set(1, 1, strip.getVy()); - mDir.set(1, 2, strip.getVz()); + mDir.set(0, 0, u.x()); + mDir.set(0, 1, u.y()); + mDir.set(0, 2, u.z()); + mDir.set(1, 0, v.x()); + mDir.set(1, 1, v.y()); + mDir.set(1, 2, v.z()); if (_debug) { System.out.println("HpsGblFitter: " + "mDir"); mDir.print(4, 6); @@ -359,37 +369,85 @@ msCov.set(1, 1, msCov.get(1, 1) + scatErr.get(0) * scatErr.get(0)); msCov.set(2, 2, msCov.get(2, 2) + scatErr.get(1) * scatErr.get(1)); + + + //// Calculate global derivatives for this point + + // track direction in tracking/global frame + Hep3Vector tDirGlobal = new BasicHep3Vector(cosPhi * cosLambda, sinPhi * cosLambda, sinLambda); + + // Cross-check that the input is consistent + if( VecOp.sub(tDirGlobal, strip.getTrackDirection()).magnitude() > 0.00001) { + throw new RuntimeException("track directions are inconsistent: " + tDirGlobal.toString() + " and " + strip.getTrackDirection().toString()); + } + // rotate track direction to measurement frame + Hep3Vector tDirMeas = new BasicHep3Vector(VecOp.dot(tDirGlobal, u), VecOp.dot(tDirGlobal, v), VecOp.dot(tDirGlobal, w)); + // TODO this is a trivial one. Fix it. + Hep3Vector normalMeas = new BasicHep3Vector(VecOp.dot(w, u), VecOp.dot(w, v), VecOp.dot(w, w)); + + // vector coplanar with measurement plane from origin to prediction + Hep3Vector tPosMeas = strip.getTrackPos(); + + // measurements: non-measured directions + double vmeas = 0.; + double wmeas = 0.; + + // calculate and add derivatives to point + GlobalDers glDers = new GlobalDers(strip.getId(), meas.get(0), vmeas, wmeas, tDirMeas, tPosMeas, normalMeas); + + //TODO find a more robust way to get half. + boolean isTop = Math.sin(strip.getTrackLambda()) > 0 ? true : false; + + // Get the list of millepede parameters + List<MilleParameter> milleParameters = glDers.getDers(isTop); + + // need to make vector and matrices for interface + List<Integer> labGlobal = new ArrayList<Integer>(); + Matrix addDer = new Matrix(1, milleParameters.size()); + for(int i=0; i < milleParameters.size(); ++i) { + labGlobal.add(milleParameters.get(i).getId()); + addDer.set(0, i, milleParameters.get(i).getValue()); + } + point.addGlobals(labGlobal, addDer); + + for(int i=0; i < milleParameters.size(); ++i) { + logger.info(labGlobal.get(i) + "\t" + addDer.get(0, i)); + } + + + /* - - ##### - ## 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) + ##### + + */ + + logger.info("uRes " + strip.getId() + " uRes " + uRes + " pred (" + strip.getTrackPos().x() + "," + strip.getTrackPos().y() + "," + strip.getTrackPos().z() + ") s(3D) " + strip.getPath3D()); //go to next point @@ -471,54 +529,253 @@ return jac; } - public static class FittedGblTrajectory { - public static enum GBLPARIDX { - QOVERP(0),XTPRIME(1),YTPRIME(2),XT(3),YT(4); - private int _value; - private GBLPARIDX(int value) { - _value = value; - } - public int getValue() { - return _value; - } - }; - private GblTrajectory _traj; - private double _chi2; - private double _lost; - private int _ndf; - private Track _seed = null; - private GBLTrackData _t = null; - public FittedGblTrajectory(GblTrajectory traj, double chi2, int ndf, double lost) { - _traj = traj; - _chi2 = chi2; - _ndf = ndf; - _lost = lost; - } - public void set_track_data(GBLTrackData t) { - _t = t; - } - public GBLTrackData get_track_data() { - return _t; - } - public void set_seed(Track seed) { - _seed = seed; - } - public Track get_seed() { - return _seed; - } - public GblTrajectory get_traj() { - return _traj; - } - public double get_chi2() { - return _chi2; - } - public double get_lost() { - return _lost; - } - public int get_ndf() { - return _ndf; - } - - } - + + private static class GlobalDers { + private int _layer; + private double _umeas; // measurement direction + private double _vmeas; // unmeasured direction + private double _wmeas; // normal to plane + private Hep3Vector _t; // track direction + private Hep3Vector _p; // track prediction + private Hep3Vector _n; // normal to plane + private Matrix _dm_dg; //Global derivaties of the local measurements + private Matrix _dr_dm; //Derivatives of residuals w.r.t. measurement + private Matrix _dr_dg; //Derivatives of residuals w.r.t. global parameters + + public GlobalDers(int layer,double umeas, double vmeas, double wmeas, Hep3Vector tDir, Hep3Vector tPred, Hep3Vector normal) { + _layer = layer; + _umeas = umeas; + _vmeas = vmeas; + _wmeas = wmeas; + _t = tDir; + _p = tPred; + _n = normal; + // Derivatives of residuals w.r.t. perturbed measurement + _dr_dm = getResDers(); + // Derivatives of perturbed measurement w.r.t. global parameters + _dm_dg = getMeasDers(); + // Calculate, by chain rule, derivatives of residuals w.r.t. global parameters + _dr_dg = _dr_dm.times(_dm_dg); + //print 'dm_dg' + //print dm_dg + //print 'dr_dm' + //print dr_dm + //print 'dr_dg' + //print self.dr_dg + } + + + /** + * Derivative of mt, the perturbed measured coordinate vector m w.r.t. to global parameters: u,v,w,alpha,beta,gamma + */ + private Matrix getMeasDers() { + + //Derivative of the local measurement for a translation in u + double dmu_du = 1.; + double dmv_du = 0.; + double dmw_du = 0.; + // Derivative of the local measurement for a translation in v + double dmu_dv = 0.; + double dmv_dv = 1.; + double dmw_dv = 0.; + // Derivative of the local measurement for a translation in w + double dmu_dw = 0.; + double dmv_dw = 0.; + double dmw_dw = 1.; + // Derivative of the local measurement for a rotation around u-axis (alpha) + double dmu_dalpha = 0.; + double dmv_dalpha = _p.z(); // self.wmeas + double dmw_dalpha = -1.0 * _p.y(); // -1.0 * self.vmeas + // Derivative of the local measurement for a rotation around v-axis (beta) + double dmu_dbeta = -1.0 * _p.z(); //-1.0 * self.wmeas + double dmv_dbeta = 0.; + double dmw_dbeta = _p.x(); //self.umeas + // Derivative of the local measurement for a rotation around w-axis (gamma) + double dmu_dgamma = _p.y(); // self.vmeas + double dmv_dgamma = -1.0 * _p.x(); // -1.0 * self.umeas + double dmw_dgamma = 0.; + // put into matrix + Matrix dm_dg = new Matrix(3, 6); + dm_dg.set(0, 0, dmu_du); + dm_dg.set(0, 1, dmu_dv); + dm_dg.set(0, 2, dmu_dw); + dm_dg.set(0, 3, dmu_dalpha); + dm_dg.set(0, 4, dmu_dbeta); + dm_dg.set(0, 5, dmu_dgamma); + dm_dg.set(1, 0, dmv_du); + dm_dg.set(1, 1, dmv_dv); + dm_dg.set(1, 2, dmv_dw); + dm_dg.set(1, 3, dmv_dalpha); + dm_dg.set(1, 4, dmv_dbeta); + dm_dg.set(1, 5, dmv_dgamma); + dm_dg.set(2, 0, dmw_du); + dm_dg.set(2, 1, dmw_dv); + dm_dg.set(2, 2, dmw_dw); + dm_dg.set(2, 3, dmw_dalpha); + dm_dg.set(2, 4, dmw_dbeta); + dm_dg.set(2, 5, dmw_dgamma); + //dmdg = np.array([[dmu_du, dmu_dv, dmu_dw, dmu_dalpha, dmu_dbeta, dmu_dgamma],[dmv_du, dmv_dv, dmv_dw, dmv_dalpha, dmv_dbeta, dmv_dgamma],[dmw_du, dmw_dv, dmw_dw, dmw_dalpha, dmw_dbeta, dmw_dgamma]]) + return dm_dg; + } + + /** + * Derivatives of the local perturbed residual w.r.t. the measurements m (u,v,w)' + */ + private Matrix getResDers() { + double tdotn = VecOp.dot(_t, _n); + Matrix dr_dm = Matrix.identity(3,3); + //print 't ', self.t, ' n ', self.n, ' dot(t,n) ', tdotn + double delta, val; + for(int i=0; i<3; ++i) { + for(int j=0; j<3; ++j) { + delta = i==j ? 1. : 0.; + val = delta - _t.v()[i] * _n.v()[j]/tdotn; + dr_dm.set(i, j, val); + } + } + return dr_dm; + } + + + /** + * Turn derivative matrix into @Milleparameter + * @param isTop - top or bottom track + * @return list of @Milleparameters + */ + private List<MilleParameter> getDers(boolean isTop) { + int transRot; + int direction; + int label; + double value; + List<MilleParameter> milleParameters = new ArrayList<MilleParameter>(); + int topBot = isTop == true ? 1 : 2; + for(int ip=1; ip<7; ++ip) { + if(ip > 3) { + transRot = 2; + direction = ((ip-1) % 3) + 1; + } else { + transRot = 1; + direction = ip; + } + label = topBot * MilleParameter.half_offset + transRot * MilleParameter.type_offset + direction * MilleParameter.dimension_offset + _layer; + value = _dr_dg.get(0, ip-1); + MilleParameter milleParameter = new MilleParameter(label, value, 0.0); + milleParameters.add(milleParameter); + } + return milleParameters; + } + + + /* + + class globalDers: + def __init__(self,layer,umeas,vmeas,wmeas, tDir, tPred, normal): + self.layer = layer # measurement direction + self.umeas = umeas # measurement direction + self.vmeas = vmeas # unmeasured direction + self.wmeas = wmeas # normal to plane + self.t = tDir # track direction + self.p = tPred # track prediction + self.n = normal # normal to plane + # Global derivaties of the local measurements + self.dm_dg = self.getMeasDers() + # Derivatives of residuals w.r.t. measurement + self.dr_dm = self.getResDers() + # Derivatives of residuals w.r.t. global parameters + self.dr_dg = np.dot(self.dr_dm, self.dm_dg) + #print 'dm_dg' + #print dm_dg + #print 'dr_dm' + #print dr_dm + #print 'dr_dg' + #print self.dr_dg + + def dump(self): + print 'globalDers:' + print 'layer ', self.layer + print 'umeas ', self.umeas, ' vmeas ', self.vmeas, ' wmeas ', self.wmeas + print 't ', self.t, ' p ', self.p, ' n ', self.n + print 'dm_dg\n',self.dm_dg, '\ndr_dm\n',self.dr_dm,'\ndr_dg\n',self.dr_dg + + def getDers(self,isTop): + half_offset = 10000 + translation_offset = 1000 + direction_offset = 100 + topBot = 1 + transRot = 1 + direction = 1 + if not isTop: + topBot = 2 + res = {} + labels = [] + ders = [] + for ip, name in global_params.iteritems(): + if ip > 3: + transRot = 2 + direction = ((ip-1) % 3) + 1 + else: + direction = ip + label = (int)(topBot * half_offset + transRot * translation_offset + direction * direction_offset + self.layer) + labels.append(label) + ders.append(self.dr_dg[0,ip-1]) + + return {'labels':np.array([labels]) , 'ders':np.array([ders])} + + + + + def getResDers(self): + # Derivatives of the local perturbed residual w.r.t. the measurements m (u,v,w)' + tdotn = np.dot(self.t.T,self.n) + drdg = np.eye(3) + #print 't ', self.t, ' n ', self.n, ' dot(t,n) ', tdotn + for i in range(3): + for j in range(3): + delta = 0. + if i==j: + delta = 1. + drdg[i][j] = delta - self.t[i]*self.n[j]/tdotn[0] + return drdg + + + + + def getMeasDers(self): + # Derivative of mt, the perturbed measured coordinate vector m + # w.r.t. to global parameters: u,v,w,alpha,beta,gamma + + # Derivative of the local measurement for a translation in u + dmu_du = 1. + dmv_du = 0. + dmw_du = 0. + # Derivative of the local measurement for a translation in v + dmu_dv = 0. + dmv_dv = 1. + dmw_dv = 0. + # Derivative of the local measurement for a translation in w + dmu_dw = 0. + dmv_dw = 0. + dmw_dw = 1. + # Derivative of the local measurement for a rotation around u-axis (alpha) + dmu_dalpha = 0. + dmv_dalpha = self.p[2] # self.wmeas + dmw_dalpha = -1.0 * self.p[1] # -1.0 * self.vmeas + # Derivative of the local measurement for a rotation around v-axis (beta) + dmu_dbeta = -1.0 * self.p[2] #-1.0 * self.wmeas + dmv_dbeta = 0. + dmw_dbeta = self.p[0] #self.umeas + # Derivative of the local measurement for a rotation around w-axis (gamma) + dmu_dgamma = self.p[1] # self.vmeas + dmv_dgamma = -1.0 * self.p[0] # -1.0 * self.umeas + dmw_dgamma = 0. + # put into matrix + dmdg = np.array([[dmu_du, dmu_dv, dmu_dw, dmu_dalpha, dmu_dbeta, dmu_dgamma],[dmv_du, dmv_dv, dmv_dw, dmv_dalpha, dmv_dbeta, dmv_dgamma],[dmw_du, dmw_dv, dmw_dw, dmw_dalpha, dmw_dbeta, dmw_dgamma]]) + #print dmw_dbeta + #dmdg = np.array([[dmu_du, dmu_dv],[dmu_dw, dmu_dalpha], [dmw_dbeta, dmw_dgamma]]) + return dmdg + */ + } } + + +