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
/*
 *  See header file for a description of this class.
 */

#include "DTT0FEBPathCorrection.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/Framework/interface/EventSetup.h"
#include "FWCore/Framework/interface/ESHandle.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"

#include "Geometry/Records/interface/MuonGeometryRecord.h"
#include "Geometry/DTGeometry/interface/DTGeometry.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 "FWCore/Framework/interface/ConsumesCollector.h"

#include <string>
#include <sstream>

using namespace std;
using namespace edm;

namespace dtCalibration {

  DTT0FEBPathCorrection::DTT0FEBPathCorrection(const ParameterSet& pset, edm::ConsumesCollector cc)
      : calibChamber_(pset.getParameter<string>("calibChamber")), t0Token_(cc.esConsumes<edm::Transition::BeginRun>()) {
    //DTChamberId chosenChamberId;
    if (!calibChamber_.empty() && calibChamber_ != "None" && calibChamber_ != "All") {
      stringstream linestr;
      int selWheel, selStation, selSector;
      linestr << calibChamber_;
      linestr >> selWheel >> selStation >> selSector;
      chosenChamberId_ = DTChamberId(selWheel, selStation, selSector);
      LogVerbatim("Calibration") << "[DTT0FEBPathCorrection] Chosen chamber: " << chosenChamberId_ << endl;
    }
    //FIXME: Check if chosen chamber is valid.
  }

  DTT0FEBPathCorrection::~DTT0FEBPathCorrection() {}

  void DTT0FEBPathCorrection::setES(const EventSetup& setup) {
    // Get t0 record from DB
    ESHandle<DTT0> t0H;
    t0H = setup.getHandle(t0Token_);
    t0Map_ = &setup.getData(t0Token_);
    LogVerbatim("Calibration") << "[DTT0FEBPathCorrection] T0 version: " << t0H->version();
  }

  DTT0Data DTT0FEBPathCorrection::correction(const DTWireId& wireId) {
    // Compute for selected chamber (or All) correction using as reference chamber mean

    DTChamberId chamberId = wireId.layerId().superlayerId().chamberId();

    if (calibChamber_.empty() || calibChamber_ == "None")
      return defaultT0(wireId);
    if (calibChamber_ != "All" && chamberId != chosenChamberId_)
      return defaultT0(wireId);

    // Access DB
    float t0Mean, t0RMS;
    int status = t0Map_->get(wireId, t0Mean, t0RMS, DTTimeUnits::counts);
    if (status != 0)
      throw cms::Exception("[DTT0FEBPathCorrection]") << "Could not find t0 entry in DB for" << wireId << endl;
    int wheel = chamberId.wheel();
    int station = chamberId.station();
    int sector = chamberId.sector();
    int sl = wireId.layerId().superlayerId().superlayer();
    int l = wireId.layerId().layer();
    int wire = wireId.wire();
    float t0MeanNew = t0Mean - t0FEBPathCorrection(wheel, station, sector, sl, l, wire);
    float t0RMSNew = t0RMS;
    return DTT0Data(t0MeanNew, t0RMSNew);
  }

  DTT0Data DTT0FEBPathCorrection::defaultT0(const DTWireId& wireId) {
    // Access default DB
    float t0Mean, t0RMS;
    int status = t0Map_->get(wireId, t0Mean, t0RMS, DTTimeUnits::counts);
    if (!status) {
      return DTT0Data(t0Mean, t0RMS);
    } else {
      //...
      throw cms::Exception("[DTT0FEBPathCorrection]") << "Could not find t0 entry in DB for" << wireId << endl;
    }
  }

  /**

  Return the value to be subtracted to t0s to correct for the difference of 
  path lenght for TP signals within the FEB, from the TP input connector 
  to the MAD.

  FEBs are alternately connected on the right (J9) and left (J8) TP 
  input connectors.
  Path lenghts (provided from Franco Gonella) for FEB-16 channels 
  for FEB-16s connected on the right TP connector (J9) are:
 
  CH0,1 = 32 mm 
  CH2,3 = 42 mm 
  CH4,5 = 52 mm 
  CH6,7 = 62 mm 

  CH8,9 = 111 mm 
  CH10,11 = 121 mm 
  CH12,13 = 131 mm 
  CH14,15 = 141 mm

  Given that ttrig calibration absorbs average offsets, 
  we assume thate only differences w.r.t. the average lenght (86.5 mm) remain.

  For FEBs connected on the right connector, values are swapped; so there is 
  a periodicity of 2 FEBS (8 cells)

  The mapping of FEB channels to wires, for the first two FEBs, is: 

         FEB 0 (J9)     FEB 1 (J8)     
  Wire | 1  2  3  4  |  5  6  7  8
  --------------------------------  
   L1  | 3  7 11 15  |  3  7 11 15 
   L2  | 1  5  9 13  |  1  5  9 13
   L3  | 2  6 10 14  |  2  6 10 14
   L4  | 0  4  8 12  |  0  4  8 12


  For FEB-20, distances from the left connector (J8) are:
  CH16,17 = 171 mm  
  CH18,19 = 181 mm

  We do not include a correction for this additional row of channels since
  they are at the edge of the SL so the effect cannot be seen on data (and moreover 
  the channel in L1 is usually not existing in the chamber)

*/

  float DTT0FEBPathCorrection::t0FEBPathCorrection(int wheel, int st, int sec, int sl, int l, int w) {
    // Skip correction for the last row of cells of FEB20 (see above)
    if ((st == 1 && ((sl != 2 && w == 49) || (sl == 2 && w == 57))) || ((st == 2 || st == 3) && (sl == 2 && w == 57)))
      return 0.;

    float dist[8] = {};

    // Path lenght differences for L1 and L3 (cm)
    if (l == 1 || l == 3) {
      dist[0] = +4.45;
      dist[1] = +2.45;
      dist[2] = -3.45;
      dist[3] = -5.45;
      dist[4] = -4.45;
      dist[5] = -2.45;
      dist[6] = +3.45;
      dist[7] = +5.45;
    }

    // Path lenght differences for L2 and L4 (cm)
    else {
      dist[0] = +5.45;
      dist[1] = +3.45;
      dist[2] = -2.45;
      dist[3] = -4.45;
      dist[4] = -5.45;
      dist[5] = -3.45;
      dist[6] = +2.45;
      dist[7] = +4.45;
    }

    // Wire position within the 8-cell period (2 FEBs).
    // Note that wire numbers start from 1.
    int pos = (w - 1) % 8;

    // Special case: in MB2 phi and MB4-10, the periodicity is broken at cell 49, as there is
    // an odd number of FEDs (15): the 13th FEB is connected on the left,
    // and not on the right; i.e. one FEB (4 colums of cells) is skipped from what would
    // be the regular structure.
    // The same happens in MB4-8/12 at cell 81.
    if ((st == 2 && sl != 2 && w >= 49) || (st == 4 && sec == 10 && w >= 49) ||
        (st == 4 && (sec == 8 || sec == 12) && w >= 81))
      pos = (w - 1 + 4) % 8;

    // Inverse of the signal propagation speed, determined from the
    // observed amplitude of the modulation. This matches what is found
    // with CAD simulation using reasonable assumptions on the PCB specs.

    return dist[pos] * 0.075;
  }

}  // namespace dtCalibration