Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
#include "DQM/SiStripCommissioningSources/plugins/tracking/SiStripFineDelayTOF.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include <DataFormats/TrackReco/interface/Track.h>
#include <iostream>
#include "TVector3.h"
#include "TMath.h"

//#define TIF_COSMIC_SETUP

double SiStripFineDelayTOF::timeOfFlight(
    bool cosmics, bool field, double* trackParameters, double* hit, double* phit, bool onDisk) {
  // case 1: cosmics with no field.
  if (cosmics && !field) {
    return timeOfFlightCosmic(hit, phit);
  }
  // case 2: cosmics with field.
  else if (cosmics && field) {
    return timeOfFlightCosmicB(trackParameters, hit, phit, onDisk);
  }
  // case 3: beam with no field.
  else if (!cosmics && !field) {
    return timeOfFlightBeam(hit, phit);
  }
  // case 4: beam with field.
  else {
    return timeOfFlightBeamB(trackParameters, hit, phit, onDisk);
  }
}

double SiStripFineDelayTOF::timeOfFlightCosmic(double* hit, double* phit) {
  // constants
  const double c = 30;  // cm/ns
#ifndef TIF_COSMIC_SETUP
  const double Rmu = 385;  // cm
  const double zmu = 560;  // cm
  // estimate the time for crossing the barrel
  TVector3 r0(hit[0], hit[1], hit[2]);
  TVector3 pr(phit[0], phit[1], phit[2]);
  TVector2 r0_xy = r0.XYvector();
  TVector2 pr_xy = pr.Unit().XYvector();
  double t_barrel =
      ((r0_xy * pr_xy) + sqrt((r0_xy * pr_xy) * (r0_xy * pr_xy) - r0_xy.Mod2() + Rmu * Rmu)) / c * pr.Mag() / pr.Perp();
  // estimate the time for crossing endcaps
  double t_endcap = fabs(((phit[2] / fabs(phit[2]) * zmu) + hit[2]) / c * pr.Mag() / pr.Pz());
  // take the minimum
  return t_barrel < t_endcap ? t_barrel : t_endcap;
#else
  const double y_trigger = 100;  //cm
  double p = sqrt(phit[0] * phit[0] + phit[1] * phit[1] + phit[2] * phit[2]);
  //  LogDebug("TOF") << "momentum:" << phit[0] << " " << phit[1] << " " << phit[2];
  //  LogDebug("TOF") << "p/py=" << p/phit[1] << "  Y0,Y,dY = " << y_trigger << " " << hit[1] << " " << (y_trigger-hit[1]);
  //  LogDebug("TOF") << "d, t=d/c : " << ((y_trigger-hit[1])*(p/phit[1])) << " " << ((y_trigger-hit[1])*(p/phit[1])/c);
  return fabs((y_trigger - hit[1]) * (p / phit[1]) / c);
#endif
}

double SiStripFineDelayTOF::timeOfFlightCosmicB(double* trackParameters, double* hit, double* phit, bool onDisk) {
  // constants
  const double Rmu = 385;  // cm
  const double zmu = 560;  // cm
  const double c = 30;     // cm/ns
  // track parameters
  double& kappa = trackParameters[0];
  double& theta = trackParameters[1];
  double& phi_0 = trackParameters[2];
  double& d_0 = trackParameters[3];
  double& z_0 = trackParameters[4];
  double invkappa = 1 / kappa;
  // computes the value of the track parameter that correspond to the hit, relative to phi_0
  //double phi = kappa*tan(theta)*(hit[2]-z_0);
  double phi = getPhi(trackParameters, hit, onDisk) - phi_0;
  // computes the value of the track parameter that correspond to the muon system, relative to phi_0
  // phi_mu = phi_mu0 - phi_0
  double phi_mu_b = (kappa > 0 ? -1 : 1) * acos((Rmu * Rmu - d_0 * d_0 - 2 * invkappa * invkappa + 2 * invkappa * d_0) /
                                                (2 * invkappa * d_0 - 2 * invkappa * invkappa));
  double phi_mu_e = kappa * tan(theta) * ((phit[2] < 0 ? 1 : -1) * zmu - z_0);
  // estimate the time for crossing the barrel
  double t_barrel = fabs(invkappa / (c * sin(theta)) * (phi - phi_mu_b));
  // estimate the time for crossing endcaps
  double t_endcap = fabs(invkappa / (c * sin(theta)) * (phi - phi_mu_e));
  // take the minimum
  return t_barrel < t_endcap ? t_barrel : t_endcap;
}

double SiStripFineDelayTOF::timeOfFlightBeam(double* hit, double*) {
  // constants
  const double c = 30;  // cm/ns
  TVector3 r0(hit[0], hit[1], hit[2]);
  return r0.Mag() / c;
}

double SiStripFineDelayTOF::timeOfFlightBeamB(double* trackParameters, double* hit, double* phit, bool onDisk) {
  // constants
  const double c = 30;  // cm/ns
  // track parameters
  double& theta = trackParameters[1];
  // returns the time of flight from the origin
  return onDisk ? fabs(hit[2] / (c * cos(theta))) : fabs(sqrt(hit[0] * hit[0] + hit[1] * hit[1]) / (c * sin(theta)));
}

double SiStripFineDelayTOF::x(double* trackParameters, double phi) {
  return trackParameters[3] * sin(trackParameters[2]) + (1 / trackParameters[0]) * (sin(phi) - sin(trackParameters[2]));
}

double SiStripFineDelayTOF::y(double* trackParameters, double phi) {
  return -trackParameters[3] * cos(trackParameters[2]) -
         (1 / trackParameters[0]) * (cos(phi) - cos(trackParameters[2]));
}

double SiStripFineDelayTOF::z(double* trackParameters, double phi) {
  return trackParameters[4] + (phi - trackParameters[2]) / (trackParameters[0] * tan(trackParameters[1]));
}

double SiStripFineDelayTOF::getPhi(double* trackParameters, double* hit, bool onDisk) {
  if (onDisk)  //use z coordinate to find phi
    return trackParameters[2] + trackParameters[0] * tan(trackParameters[1]) * (hit[2] - trackParameters[4]);
  else  // use x,y coordinate to find phi
  {
    double phi = 0;
    if (trackParameters[2] > -2.35 && trackParameters[2] < -0.78) {
      // first use y
      phi = acos(-trackParameters[0] *
                 (hit[1] - (trackParameters[3] - 1 / trackParameters[0]) * (-cos(trackParameters[2]))));
      // use x to resolve the ambiguity
      if (fabs(x(trackParameters, phi) - hit[0]) > fabs(x(trackParameters, -phi) - hit[0]))
        phi *= -1.;
    } else {
      // first use x
      phi =
          asin(trackParameters[0] * (hit[0] - (trackParameters[3] - 1 / trackParameters[0]) * sin(trackParameters[2])));
      // use y to resolve the ambiguity
      if ((fabs(y(trackParameters, phi) - hit[1]) > fabs(y(trackParameters, TMath::Pi() - phi) - hit[1])))
        phi = phi > 0 ? TMath::Pi() - phi : -TMath::Pi() - phi;
    }
    return phi;
  }
  return 0.;
}

void SiStripFineDelayTOF::trackParameters(const reco::Track& tk, double* trackParameters) {
  math::XYZPoint position = tk.outerPosition();
  const math::XYZVector& momentum = tk.outerMomentum();
  LogDebug("trackParameters") << "outer position: " << position.x() << " " << position.y() << " " << position.z();
  LogDebug("trackParameters") << "outer momentum: " << momentum.x() << " " << momentum.y() << " " << momentum.z();
  math::XYZVector fieldDirection(0, 0, 1);
  // computes the center of curvature
  math::XYZVector radius = momentum.Cross(fieldDirection).Unit();
  position -= radius / trackParameters[0];
  LogDebug("trackParameters") << "center of curvature: " << position.x() << " " << position.y() << " " << position.z();
  // the transverse IP
  trackParameters[3] = position.rho() - fabs(1 / trackParameters[0]);
  if (trackParameters[0] > 0)
    trackParameters[3] *= -1.;
  // phi_0
  double phi_out = trackParameters[2];
  double phi_0 = position.phi() - TMath::Pi() / 2;
  if (trackParameters[0] < 0)
    phi_0 -= TMath::Pi();
  if (phi_0 < -2 * TMath::Pi())
    phi_0 += 2 * TMath::Pi();
  if (phi_0 > 2 * TMath::Pi())
    phi_0 -= 2 * TMath::Pi();
  if (phi_0 > 0)
    phi_0 -= 2 * TMath::Pi();
  LogDebug("trackParameters") << "phi_0: " << phi_0;
  trackParameters[2] = phi_0;
  // z_0
  trackParameters[4] = tk.outerPosition().z() - (phi_out - phi_0) / TMath::Tan(trackParameters[1]) / trackParameters[0];
  LogDebug("trackParameters") << "z_0: " << tk.outerPosition().z() << " " << trackParameters[4] << " "
                              << tk.innerPosition().z();
}