DTTTrigSyncFromDB

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 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
/** \class DTTTrigSyncFromDB
 *  Concrete implementation of a DTTTrigBaseSync.
 *  This class define the offset for RecHit building
 *  of data and simulation.
 *  The offset is computes as: 
 *  <br>
 *  offset = t0 + tTrig + wirePropCorr - tofCorr 
 *  <br>
 *  where: <br>
 *     - t0 from test pulses (taken from DB, it is assumed to be in ns; can be switched off)
 *     - ttrig from the fit of time boxrising edge (taken from DB, it is assumed to be in ns)
 *       (At the moment a single value is read for ttrig offset 
 *       but this may change in the future)
 *     - signal propagation along the wire (can be switched off):
 *       it is assumed the ttrig accounts on average for
 *       correction from the center of the wire to the frontend.
 *       Here we just have to correct for the distance of the hit from the wire center.
 *     - TOF correction (can be switched off for cosmics):
 *       the ttrig already accounts for average TOF correction, 
 *       depending on the granularity used for the ttrig computation we just have to correct for the
 *       TOF from the center of the chamber, SL, layer or wire to the hit position.
 *       NOTE: particles are assumed as coming from the IP.
 *
 *  The emulatorOffset is computed as:
 *  <br>
 *  offset = int(ttrig/BXspace)*BXspace + t0
 *  <br>
 *  where: <br>
 *     - t0 from test pulses (taken from DB, it is assumed to be in ns; can be switched off)
 *     - ttrig from the fit of time box rising edge (taken from DB, it is assumed to be in ns)
 *     - BXspace BX spacing (in ns). Can be configured.
 *   
 *  NOTE: this should approximate what is seen online by the BTI
 *
 *  \author G. Cerminara - INFN Torino
 */

#include "CalibMuon/DTDigiSync/interface/DTTTrigBaseSync.h"
#include "FWCore/Framework/interface/ConsumesCollector.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/Framework/interface/EventSetup.h"
#include "FWCore/Framework/interface/ESHandle.h"
#include "Geometry/DTGeometry/interface/DTLayer.h"
#include "Geometry/DTGeometry/interface/DTSuperLayer.h"
#include "DataFormats/MuonDetId/interface/DTWireId.h"
#include "CondFormats/DTObjects/interface/DTT0.h"
#include "CondFormats/DataRecord/interface/DTT0Rcd.h"
#include "CondFormats/DTObjects/interface/DTTtrig.h"
#include "CondFormats/DataRecord/interface/DTTtrigRcd.h"

#include <iostream>

namespace edm {
  class ParameterSet;
}

class DTTTrigSyncFromDB : public DTTTrigBaseSync {
public:
  /// Constructor
  DTTTrigSyncFromDB(const edm::ParameterSet& config, edm::ConsumesCollector);

  /// Destructor
  ~DTTTrigSyncFromDB() override;

  // Operations

  /// Pass the Event Setup to the algo at each event
  void setES(const edm::EventSetup& setup) override;

  /// Time (ns) to be subtracted to the digi time,
  /// Parameters are the layer and the wireId to which the
  /// digi is referred and the estimation of
  /// the 3D hit position (globPos)
  double offset(const DTLayer* layer,
                const DTWireId& wireId,
                const GlobalPoint& globPos,
                double& tTrig,
                double& wirePropCorr,
                double& tofCorr) const override;

  /// Time (ns) to be subtracted to the digi time.
  /// It does not take into account TOF and signal propagation along the wire
  double offset(const DTWireId& wireId) const override;

  /// Time (ns) to be subtracted to the digi time for emulation purposes
  /// It does not take into account TOF and signal propagation along the wire
  /// It also returns the different contributions separately:
  ///     - tTrig is the offset (t_trig)
  ///     - t0cell is the t0 from pulses
  double emulatorOffset(const DTWireId& wireId, double& tTrig, double& t0cell) const override;

private:
  edm::ESGetToken<DTT0, DTT0Rcd> t0Token_;
  const edm::ESGetToken<DTTtrig, DTTtrigRcd> ttrigToken_;
  const DTT0* tZeroMap;
  const DTTtrig* tTrigMap;
  // Set the verbosity level
  const bool debug;
  // The velocity of signal propagation along the wire (cm/ns)
  double theVPropWire;
  // Switch on/off the T0 correction from pulses
  bool doT0Correction;
  // Switch on/off the TOF correction for particles from IP
  bool doTOFCorrection;
  int theTOFCorrType;
  // Switch on/off the correction for the signal propagation along the wire
  bool doWirePropCorrection;
  int theWirePropCorrType;
  // spacing of BX in ns
  double theBXspace;
};

using namespace std;
using namespace edm;

DTTTrigSyncFromDB::DTTTrigSyncFromDB(const ParameterSet& config, edm::ConsumesCollector cc)
    : ttrigToken_(cc.esConsumes(edm::ESInputTag("", config.getParameter<string>("tTrigLabel")))),
      debug(config.getUntrackedParameter<bool>("debug")),
      // The velocity of signal propagation along the wire (cm/ns)
      theVPropWire(config.getParameter<double>("vPropWire")),
      // Switch on/off the T0 correction from pulses
      doT0Correction(config.getParameter<bool>("doT0Correction")),
      // Switch on/off the TOF correction for particles from IP
      doTOFCorrection(config.getParameter<bool>("doTOFCorrection")),
      theTOFCorrType(config.getParameter<int>("tofCorrType")),
      // Switch on/off the correction for the signal propagation along the wire
      doWirePropCorrection(config.getParameter<bool>("doWirePropCorrection")),
      theWirePropCorrType(config.getParameter<int>("wirePropCorrType")),
      // spacing of BX in ns
      theBXspace(config.getUntrackedParameter<double>("bxSpace", 25.)) {
  if (doT0Correction) {
    t0Token_ = cc.esConsumes(edm::ESInputTag("", config.getParameter<string>("t0Label")));
  }
}

DTTTrigSyncFromDB::~DTTTrigSyncFromDB() {}

void DTTTrigSyncFromDB::setES(const EventSetup& setup) {
  if (doT0Correction) {
    // Get the map of t0 from pulses from the Setup
    tZeroMap = &setup.getData(t0Token_);
    if (debug) {
      cout << "[DTTTrigSyncFromDB] t0 version: " << tZeroMap->version() << endl;
    }
  }

  // Get the map of ttrig from the Setup
  tTrigMap = &setup.getData(ttrigToken_);
  if (debug) {
    cout << "[DTTTrigSyncFromDB] ttrig version: " << tTrigMap->version() << endl;
  }
}

double DTTTrigSyncFromDB::offset(const DTLayer* layer,
                                 const DTWireId& wireId,
                                 const GlobalPoint& globPos,
                                 double& tTrig,
                                 double& wirePropCorr,
                                 double& tofCorr) const {
  // Correction for the float to int conversion while writeing the ttrig in ns into an int variable
  // (half a bin on average)
  // FIXME: this should disappear as soon as the ttrig object will become a float
  //   static const float f2i_convCorr = (25./64.); // ns //FIXME: check how the conversion is performed

  tTrig = offset(wireId);

  // Compute the time spent in signal propagation along wire.
  // NOTE: the FE is always at y>0
  wirePropCorr = 0;
  if (doWirePropCorrection) {
    switch (theWirePropCorrType) {
        // The ttrig computed from the timebox accounts on average for the signal propagation time
        // from the center of the wire to the frontend. Here we just have to correct for
        // the distance of the hit from the wire center.
      case 0: {
        float wireCoord = layer->toLocal(globPos).y();
        wirePropCorr = -wireCoord / theVPropWire;
        break;
        // FIXME: What if hits used for the time box are not distributed uniformly along the wire?
      }
      //On simulated data you need to subtract the total propagation time
      case 1: {
        float halfL = layer->specificTopology().cellLenght() / 2;
        float wireCoord = layer->toLocal(globPos).y();
        float propgL = halfL - wireCoord;
        wirePropCorr = propgL / theVPropWire;
        break;
      }
      default: {
        throw cms::Exception("[DTTTrigSyncFromDB]")
            << " Invalid parameter: wirePropCorrType = " << theWirePropCorrType << std::endl;
        break;
      }
    }
  }

  // Compute TOF correction:
  tofCorr = 0.;
  // TOF Correction can be switched off with appropriate parameter
  if (doTOFCorrection) {
    float flightToHit = globPos.mag();
    static const float cSpeed = 29.9792458;  // cm/ns
    switch (theTOFCorrType) {
      case 0: {
        // The ttrig computed from the real data accounts on average for the TOF correction
        // Depending on the granularity used for the ttrig computation we just have to correct for the
        // TOF from the center of the chamber, SL, layer or wire to the hit position.
        // At the moment only SL granularity is considered
        // Correction for TOF from the center of the SL to hit position
        const DTSuperLayer* sl = layer->superLayer();
        double flightToSL = sl->surface().position().mag();
        tofCorr = (flightToSL - flightToHit) / cSpeed;
        break;
      }
      case 1: {
        // On simulated data you need to consider only the TOF from 3D center of the wire to hit position
        // (because the TOF from the IP to the wire has been already subtracted in the digitization:
        // SimMuon/DTDigitizer/DTDigiSyncTOFCorr.cc corrType=2)
        float flightToWire =
            layer->toGlobal(LocalPoint(layer->specificTopology().wirePosition(wireId.wire()), 0., 0.)).mag();
        tofCorr = (flightToWire - flightToHit) / cSpeed;
        break;
      }
      default: {
        throw cms::Exception("[DTTTrigSyncFromDB]")
            << " Invalid parameter: tofCorrType = " << theTOFCorrType << std::endl;
        break;
      }
    }
  }

  if (debug) {
    cout << "[DTTTrigSyncFromDB] Channel: " << wireId << endl
         << "      Offset (ns): " << tTrig + wirePropCorr - tofCorr << endl
         << "      various contributions are: " << endl
         << "      tTrig + t0 (ns):   " << tTrig
         << endl
         //<< "      tZero (ns):   " << t0 << endl
         << "      Propagation along wire delay (ns): " << wirePropCorr << endl
         << "      TOF correction (ns): " << tofCorr << endl
         << endl;
  }
  //The global offset is the sum of various contributions
  return tTrig + wirePropCorr - tofCorr;
}

double DTTTrigSyncFromDB::offset(const DTWireId& wireId) const {
  float t0 = 0;
  float t0rms = 0;
  if (doT0Correction) {
    // Read the t0 from pulses for this wire (ns)
    tZeroMap->get(wireId, t0, t0rms, DTTimeUnits::ns);
  }

  // Read the ttrig for this wire
  float ttrigMean = 0;
  float ttrigSigma = 0;
  float kFactor = 0;
  // FIXME: should check the return value of the DTTtrigRcd::get(..) method
  if (tTrigMap->get(wireId.superlayerId(), ttrigMean, ttrigSigma, kFactor, DTTimeUnits::ns) != 0) {
    cout << "[DTTTrigSyncFromDB]*Error: ttrig not found for SL: " << wireId.superlayerId() << endl;
    //     FIXME: LogError.....
  }

  return t0 + ttrigMean + kFactor * ttrigSigma;
}

double DTTTrigSyncFromDB::emulatorOffset(const DTWireId& wireId, double& tTrig, double& t0cell) const {
  float t0 = 0;
  float t0rms = 0;
  if (doT0Correction) {
    // Read the t0 from pulses for this wire (ns)
    tZeroMap->get(wireId, t0, t0rms, DTTimeUnits::ns);
  }

  // Read the ttrig for this wire
  float ttrigMean = 0;
  float ttrigSigma = 0;
  float kFactor = 0;
  // FIXME: should check the return value of the DTTtrigRcd::get(..) method
  if (tTrigMap->get(wireId.superlayerId(), ttrigMean, ttrigSigma, kFactor, DTTimeUnits::ns) != 0) {
    cout << "[DTTTrigSyncFromDB]*Error: ttrig not found for SL: " << wireId.superlayerId() << endl;
    //     FIXME: LogError.....
  }

  tTrig = ttrigMean + kFactor * ttrigSigma;
  t0cell = t0;

  return int(tTrig / theBXspace) * theBXspace + t0cell;
}

#include "FWCore/PluginManager/interface/PluginFactory.h"
#include "CalibMuon/DTDigiSync/interface/DTTTrigSyncFactory.h"

DEFINE_EDM_PLUGIN(DTTTrigSyncFactory, DTTTrigSyncFromDB, "DTTTrigSyncFromDB");