Author: [log in to unmask] Date: Wed Aug 10 12:31:35 2016 New Revision: 4458 Log: re-calculates the invariant mass by combining ecal and svt information Added: java/trunk/analysis/src/main/java/org/hps/analysis/ecal/MassCalculator.java Added: java/trunk/analysis/src/main/java/org/hps/analysis/ecal/MassCalculator.java ============================================================================= --- java/trunk/analysis/src/main/java/org/hps/analysis/ecal/MassCalculator.java (added) +++ java/trunk/analysis/src/main/java/org/hps/analysis/ecal/MassCalculator.java Wed Aug 10 12:31:35 2016 @@ -0,0 +1,234 @@ +package org.hps.analysis.ecal; + +import hep.physics.vec.Hep3Vector; + +import org.hps.recon.ecal.cluster.ClusterUtilities; +import org.hps.recon.tracking.TrackUtils; +import org.lcsim.event.Cluster; +import org.lcsim.event.ReconstructedParticle; +import org.lcsim.event.Track; +import org.lcsim.event.TrackState; + +/** + * This code contains all of the calculations, as found in the 2015 data, for combining the Ecal energy and SVT + * momentum. + * + * @author Holly Szumila-Vance <[log in to unmask]> + **/ +public class MassCalculator { + + // TODO: BEAMGAPTOP and BEAMGAPBOT need to come from detector definitions: + static final double BEAMGAPTOP = 22.7;// mm + static final double BEAMGAPBOT = -22.9;// mm + static final double BEAMGAPTOPC = BEAMGAPTOP + 13.0;// mm + static final double BEAMGAPBOTC = BEAMGAPBOT - 13.0;// mm + static final double par[] = {35, 0.02871, -0.3046, -9.997, 0.1401, -0.00077, 55.09, -0.4651}; + + /** + * Calculates the y position of a cluster in the Ecal relative to the inner beam gap edge of the Ecal. + * + * @param ix + * @param y0 + * @return |yrel| + */ + static double getY(int ix, double y0) { + if (ix > -11 && ix < -1) { + // if (x0<-113 || x0>49){ + if (y0 > 0) { + if (y0 < 55) { + return Math.abs(y0 - BEAMGAPTOPC); + } else { + return Math.abs(y0 - BEAMGAPTOP); + } + } else { + if (y0 > -55) { + return Math.abs(y0 - BEAMGAPBOTC); + } else { + return Math.abs(y0 - BEAMGAPBOT); + } + } + } else { + if (y0 > 0) { + return Math.abs(y0 - BEAMGAPTOP); + } else { + return Math.abs(y0 - BEAMGAPBOT); + } + } + } + + /** + * Calculates the parameter, B, as a function of position for understanding the resolution of the energy in the + * Ecal. + * + * @param ypos + * @return B + */ + static double calcBpar(double ypos) { + if (ypos > 3) { + int ii = (ypos < par[0]) ? 2 : 5; + return par[1] - par[ii] * Math.exp(-(ypos - par[ii + 1]) * par[ii + 2]); + } else { + return 0.2; + } + } + + /** + * Calculates the energy resolution accounting for position relative to the edge in the Ecal/ + * + * @param energy + * @param ix + * @param ypos + * @return sigma E + */ + static double sigE(double energy, int ix, double ypos) { + + // return energy*(sqrt(pow(0.0165,2)/pow(energy,2)+pow(calcBpar(getY(ix,ypos)),2)/energy+pow(0.0181,2))); + return energy + * (Math.sqrt(Math.pow(0.0162, 2) / Math.pow(energy, 2) + Math.pow(calcBpar(getY(ix, ypos)), 2) / energy + + Math.pow(0.025, 2))); + } + + /** + * Calculates the momentum resolution. Fixed for 2015 data. + * + * @param mom + * @return sigma P + */ + static double sigP(double mom) { + + return 0.067 * mom; + + } + + /** + * Calculates the sigma of the E/P distribution in order to check if the cluster energy is in the peak or tail of + * the distribution before combining. + * + * @param energy + * @param mom + * @param ix + * @param ypos + * @return E/P sigma + */ + static double sigmaFrac(double energy, double mom, int ix, double ypos) { + + return Math.sqrt(Math.pow(sigE(energy, ix, ypos) / energy, 2) + Math.pow(sigP(mom) / mom, 2)); + + } + + /** + * Calculates the cosine of the opening angle of the vertex + * + * @param v0 + * @return cosine of the opening angle + */ + static double cosTheta(ReconstructedParticle v0) { + double px1 = v0.getStartVertex().getParameters().get("p1X"); + double py1 = v0.getStartVertex().getParameters().get("p1Y"); + double pz1 = v0.getStartVertex().getParameters().get("p1Z"); + double px2 = v0.getStartVertex().getParameters().get("p2X"); + double py2 = v0.getStartVertex().getParameters().get("p2Y"); + double pz2 = v0.getStartVertex().getParameters().get("p2Z"); + + return (px1 * px2 + py1 * py2 + pz1 * pz2) + / (Math.sqrt(Math.pow(px1, 2) + Math.pow(py1, 2) + Math.pow(pz1, 2)) * Math.sqrt(Math.pow(px2, 2) + + Math.pow(py2, 2) + Math.pow(pz2, 2))); + } + + /** + * This takes in a cluster, track, refit momentum and outputs the combined, weighted momentum if it satisfies + * conditions. + * + * @return combined momentum (GeV) + */ + public static double combinedMomentum(Cluster cluster, Track track, double momentum) { + double energy = cluster.getEnergy(); + TrackState trackState = track.getTrackStates().get(0); + Hep3Vector posAtEcal = TrackUtils.getTrackPositionAtEcal(trackState); + + int ix = ClusterUtilities.findSeedHit(cluster).getIdentifierFieldValue("ix"); + double yraw = posAtEcal.y(); + double ypos = getY(ix, yraw); + double sigmaE = sigE(energy, ix, ypos); + double sigmaP = sigP(momentum); + + double ff = (1 - energy / momentum) / sigmaFrac(energy, momentum, ix, ypos); + + if (ff > -2 && ff < 1.8 && ypos > 8 && (energy / momentum) > 0.82 && (energy / momentum) < 1.2) { + + return (energy / (Math.pow(sigmaE, 2)) + momentum / Math.pow(sigmaP, 2)) + / (1. / (Math.pow(sigmaE, 2)) + 1. / Math.pow(sigmaP, 2)); + + } else { + return momentum; + } + } + + /** + * This takes in the clusters of two particles and the associated vertex and calculates the invariant mass. The + * cluster order must match the track order as listed in the vertex. + * + * @return weighted invariant mass (GeV) + */ + public static double combinedMass(Cluster clusterA, Cluster clusterB, ReconstructedParticle v0) { + double momentumA = Math.sqrt(Math.pow(v0.getStartVertex().getParameters().get("p1X"), 2) + + Math.pow(v0.getStartVertex().getParameters().get("p1Y"), 2) + Math.pow(v0.getStartVertex().getParameters().get("p1Z"), 2)); + double momentumB = Math.sqrt(Math.pow(v0.getStartVertex().getParameters().get("p2X"), 2) + + Math.pow(v0.getStartVertex().getParameters().get("p2Y"), 2) + Math.pow(v0.getStartVertex().getParameters().get("p2Z"), 2)); + + double energyA = combinedMomentum(clusterA, v0.getParticles().get(0).getTracks().get(0), momentumA); + double energyB = combinedMomentum(clusterB, v0.getParticles().get(1).getTracks().get(0), momentumB); + + double cosT = cosTheta(v0); + double mass = Math.sqrt(2 * energyA * energyB * (1 - cosT)); + + return mass; + + } + + /** + * This takes in the clusters of two particles and the associated vertex and calculates the invariant mass. The + * cluster order must match the track order as listed in the vertex. + * + * Use if electron has no cluster + * + * @return weighted invariant mass (GeV) + */ + public static double combinedMass(Track trackA, Cluster clusterB, ReconstructedParticle v0) { + double momentumA = Math.sqrt(Math.pow(v0.getStartVertex().getParameters().get("p1X"), 2) + + Math.pow(v0.getStartVertex().getParameters().get("p1Y"), 2) + Math.pow(v0.getStartVertex().getParameters().get("p1Z"), 2)); + double momentumB = Math.sqrt(Math.pow(v0.getStartVertex().getParameters().get("p2X"), 2) + + Math.pow(v0.getStartVertex().getParameters().get("p2Y"), 2) + Math.pow(v0.getStartVertex().getParameters().get("p2Z"), 2)); + double energyA = momentumA; + double energyB = combinedMomentum(clusterB, v0.getParticles().get(1).getTracks().get(0), momentumB); + + double cosT = cosTheta(v0); + double mass = Math.sqrt(2 * energyA * energyB * (1 - cosT)); + + return mass; + + } + /** + * This takes in the clusters of two particles and the associated vertex and calculates the invariant mass. The + * cluster order must match the track order as listed in the vertex. + * + * Use if positron has no cluster + * + * @return weighted invariant mass (GeV) + */ + public static double combinedMass(Cluster clusterA, Track trackB, ReconstructedParticle v0) { + double momentumA = Math.sqrt(Math.pow(v0.getStartVertex().getParameters().get("p1X"), 2) + + Math.pow(v0.getStartVertex().getParameters().get("p1Y"), 2) + Math.pow(v0.getStartVertex().getParameters().get("p1Z"), 2)); + double momentumB = Math.sqrt(Math.pow(v0.getStartVertex().getParameters().get("p2X"), 2) + + Math.pow(v0.getStartVertex().getParameters().get("p2Y"), 2) + Math.pow(v0.getStartVertex().getParameters().get("p2Z"), 2)); + double energyA = combinedMomentum(clusterA, v0.getParticles().get(0).getTracks().get(0), momentumA); + double energyB = momentumB; + + double cosT = cosTheta(v0); + double mass = Math.sqrt(2 * energyA * energyB * (1 - cosT)); + + return mass; + + } + +}