CMS 3D CMS Logo

DTVDriftCalibration.cc
Go to the documentation of this file.
1 
2 /*
3  * See header file for a description of this class.
4  *
5  * \author M. Giunta
6  */
7 
11 
15 
18 
21 
23 
26 
27 /* C++ Headers */
28 #include <map>
29 #include <iostream>
30 #include <fstream>
31 #include <string>
32 #include <sstream>
33 #include "TFile.h"
34 #include "TH1.h"
35 #include "TF1.h"
36 #include "TROOT.h"
37 
38 // Declare histograms.
39 TH1F* hChi2;
40 extern void bookHistos();
41 
42 using namespace std;
43 using namespace edm;
44 using namespace dttmaxenums;
45 
47  : // Get the synchronizer
48  theSync{DTTTrigSyncFactory::get()->create(pset.getParameter<string>("tTrigMode"),
49  pset.getParameter<ParameterSet>("tTrigModeConfig"))}
50 
51 {
53  select_ = std::make_unique<DTSegmentSelector>(pset, collector);
54 
55  // The name of the 4D rec hits collection
56  theRecHits4DToken = (consumes<DTRecSegment4DCollection>(pset.getParameter<InputTag>("recHits4DLabel")));
57 
58  // The root file which will contain the histos
59  string rootFileName = pset.getUntrackedParameter<string>("rootFileName");
60  theFile = new TFile(rootFileName.c_str(), "RECREATE");
61  theFile->cd();
62 
63  debug = pset.getUntrackedParameter<bool>("debug", false);
64 
65  theFitter = std::make_unique<DTMeanTimerFitter>(theFile);
66  if (debug)
67  theFitter->setVerbosity(1);
68 
69  hChi2 = new TH1F("hChi2", "Chi squared tracks", 100, 0, 100);
70  h2DSegmRPhi = new h2DSegm("SLRPhi");
71  h2DSegmRZ = new h2DSegm("SLRZ");
72  h4DSegmAllCh = new h4DSegm("AllCh");
73  bookHistos();
74 
75  findVDriftAndT0 = pset.getUntrackedParameter<bool>("fitAndWrite", false);
76 
77  // Chamber/s to calibrate
78  theCalibChamber = pset.getUntrackedParameter<string>("calibChamber", "All");
79 
80  // the txt file which will contain the calibrated constants
81  theVDriftOutputFile = pset.getUntrackedParameter<string>("vDriftFileName");
82 
83  // get parameter set for DTCalibrationMap constructor
84  theCalibFilePar = pset.getUntrackedParameter<ParameterSet>("calibFileConfig");
85 
86  // the granularity to be used for tMax
87  string tMaxGranularity = pset.getUntrackedParameter<string>("tMaxGranularity", "bySL");
88 
89  // Enforce it to be by SL since rest is not implemented
90  if (tMaxGranularity != "bySL") {
91  LogError("Calibration") << "[DTVDriftCalibration] tMaxGranularity will be fixed to bySL.";
92  tMaxGranularity = "bySL";
93  }
94  // Initialize correctly the enum which specify the granularity for the calibration
95  if (tMaxGranularity == "bySL") {
97  } else if (tMaxGranularity == "byChamber") {
99  } else if (tMaxGranularity == "byPartition") {
101  } else
102  throw cms::Exception("Configuration")
103  << "[DTVDriftCalibration] Check parameter tMaxGranularity: " << tMaxGranularity << " option not available";
104 
105  LogVerbatim("Calibration") << "[DTVDriftCalibration]Constructor called!";
106 }
107 
109  theFile->Close();
110  LogVerbatim("Calibration") << "[DTVDriftCalibration]Destructor called!";
111 }
112 
113 void DTVDriftCalibration::analyze(const Event& event, const EventSetup& eventSetup) {
114  LogTrace("Calibration") << "--- [DTVDriftCalibration] Event analysed #Run: " << event.id().run()
115  << " #Event: " << event.id().event();
116  theFile->cd();
117  DTChamberId chosenChamberId;
118 
119  if (theCalibChamber != "All") {
120  stringstream linestr;
121  int selWheel, selStation, selSector;
122  linestr << theCalibChamber;
123  linestr >> selWheel >> selStation >> selSector;
124  chosenChamberId = DTChamberId(selWheel, selStation, selSector);
125  LogTrace("Calibration") << "chosen chamber " << chosenChamberId;
126  }
127 
128  // Get the DT Geometry
129  ESHandle<DTGeometry> dtGeom;
130  eventSetup.get<MuonGeometryRecord>().get(dtGeom);
131 
132  // Get the rechit collection from the event
133  Handle<DTRecSegment4DCollection> all4DSegments;
134  event.getByToken(theRecHits4DToken, all4DSegments);
135 
136  // Get the map of noisy channels
137  /*ESHandle<DTStatusFlag> statusMap;
138  if(checkNoisyChannels) {
139  eventSetup.get<DTStatusFlagRcd>().get(statusMap);
140  }*/
141 
142  // Set the event setup in the Synchronizer
143  theSync->setES(eventSetup);
144 
145  // Loop over segments by chamber
147  for (chamberIdIt = all4DSegments->id_begin(); chamberIdIt != all4DSegments->id_end(); ++chamberIdIt) {
148  // Get the chamber from the setup
149  const DTChamber* chamber = dtGeom->chamber(*chamberIdIt);
150  LogTrace("Calibration") << "Chamber Id: " << *chamberIdIt;
151 
152  // Calibrate just the chosen chamber/s
153  if ((theCalibChamber != "All") && ((*chamberIdIt) != chosenChamberId))
154  continue;
155 
156  // Get the range for the corresponding ChamberId
157  DTRecSegment4DCollection::range range = all4DSegments->get((*chamberIdIt));
158 
159  // Loop over the rechits of this DetUnit
160  for (DTRecSegment4DCollection::const_iterator segment = range.first; segment != range.second; ++segment) {
161  if (!(*segment).hasZed() && !(*segment).hasPhi()) {
162  LogError("Calibration") << "4D segment without Z and Phi segments";
163  continue;
164  }
165 
166  LogTrace("Calibration") << "Segment local pos (in chamber RF): " << (*segment).localPosition()
167  << "\nSegment global pos: " << chamber->toGlobal((*segment).localPosition());
168 
169  if (!((*select_)(*segment, event, eventSetup)))
170  continue;
171 
172  LocalPoint phiSeg2DPosInCham;
173  LocalVector phiSeg2DDirInCham;
174  map<DTSuperLayerId, vector<DTRecHit1D> > hitsBySLMap;
175  if ((*segment).hasPhi()) {
176  const DTChamberRecSegment2D* phiSeg = (*segment).phiSegment(); // phiSeg lives in the chamber RF
177  phiSeg2DPosInCham = phiSeg->localPosition();
178  phiSeg2DDirInCham = phiSeg->localDirection();
179  vector<DTRecHit1D> phiHits = phiSeg->specificRecHits();
180  for (vector<DTRecHit1D>::const_iterator hit = phiHits.begin(); hit != phiHits.end(); ++hit) {
181  DTWireId wireId = (*hit).wireId();
182  DTSuperLayerId slId = wireId.superlayerId();
183  hitsBySLMap[slId].push_back(*hit);
184  }
185  }
186  // Get the Theta 2D segment and plot the angle in the chamber RF
187  LocalVector zSeg2DDirInCham;
188  LocalPoint zSeg2DPosInCham;
189  if ((*segment).hasZed()) {
190  const DTSLRecSegment2D* zSeg = (*segment).zSegment(); // zSeg lives in the SL RF
191  const DTSuperLayer* sl = chamber->superLayer(zSeg->superLayerId());
192  zSeg2DPosInCham = chamber->toLocal(sl->toGlobal((*zSeg).localPosition()));
193  zSeg2DDirInCham = chamber->toLocal(sl->toGlobal((*zSeg).localDirection()));
194  hitsBySLMap[zSeg->superLayerId()] = zSeg->specificRecHits();
195  }
196 
197  LocalPoint segment4DLocalPos = (*segment).localPosition();
198  LocalVector segment4DLocalDir = (*segment).localDirection();
199  double chiSquare = ((*segment).chi2() / (*segment).degreesOfFreedom());
200 
201  hChi2->Fill(chiSquare);
202  if ((*segment).hasPhi())
203  h2DSegmRPhi->Fill(phiSeg2DPosInCham.x(), phiSeg2DDirInCham.x() / phiSeg2DDirInCham.z());
204  if ((*segment).hasZed())
205  h2DSegmRZ->Fill(zSeg2DPosInCham.y(), zSeg2DDirInCham.y() / zSeg2DDirInCham.z());
206 
207  if ((*segment).hasZed() && (*segment).hasPhi())
208  h4DSegmAllCh->Fill(segment4DLocalPos.x(),
209  segment4DLocalPos.y(),
210  atan(segment4DLocalDir.x() / segment4DLocalDir.z()) * 180. / Geom::pi(),
211  atan(segment4DLocalDir.y() / segment4DLocalDir.z()) * 180. / Geom::pi(),
212  180 - segment4DLocalDir.theta() * 180. / Geom::pi());
213  else if ((*segment).hasPhi())
214  h4DSegmAllCh->Fill(segment4DLocalPos.x(),
215  atan(segment4DLocalDir.x() / segment4DLocalDir.z()) * 180. / Geom::pi());
216  else if ((*segment).hasZed())
217  LogWarning("Calibration") << "4d segment with only Z";
218 
219  //loop over the segments
220  for (map<DTSuperLayerId, vector<DTRecHit1D> >::const_iterator slIdAndHits = hitsBySLMap.begin();
221  slIdAndHits != hitsBySLMap.end();
222  ++slIdAndHits) {
223  if (slIdAndHits->second.size() < 3)
224  continue;
225  DTSuperLayerId slId = slIdAndHits->first;
226 
227  // Create the DTTMax, that computes the 4 TMax
228  DTTMax slSeg(slIdAndHits->second,
229  *(chamber->superLayer(slIdAndHits->first)),
230  chamber->toGlobal((*segment).localDirection()),
231  chamber->toGlobal((*segment).localPosition()),
232  *theSync);
233 
234  if (theGranularity == bySL) {
235  vector<const TMax*> tMaxes = slSeg.getTMax(slId);
236  DTWireId wireId(slId, 0, 0);
237  theFile->cd();
238  cellInfo* cell = theWireIdAndCellMap[wireId];
239  if (cell == nullptr) {
240  TString name = (((((TString) "TMax" + (long)slId.wheel()) + (long)slId.station()) + (long)slId.sector()) +
241  (long)slId.superLayer());
242  cell = new cellInfo(name);
243  theWireIdAndCellMap[wireId] = cell;
244  }
245  cell->add(tMaxes);
246  cell->update(); // FIXME to reset the counter to avoid triple counting, which actually is not used...
247  } else {
248  LogWarning("Calibration") << "[DTVDriftCalibration] ###Warning: the chosen granularity is not implemented "
249  "yet, only bySL available!";
250  }
251  // to be implemented: granularity different from bySL
252 
253  // else if (theGranularity == byPartition) {
254  // // Use the custom granularity defined by partition();
255  // // in this case, add() should be called once for each Tmax of each layer
256  // // and triple counting should be avoided within add()
257  // vector<cellInfo*> cells;
258  // for (int i=1; i<=4; i++) {
259  // const DTTMax::InfoLayer* iLayer = slSeg.getInfoLayer(i);
260  // if(iLayer == 0) continue;
261  // cellInfo * cell = partition(iLayer->idWire);
262  // cells.push_back(cell);
263  // vector<const TMax*> tMaxes = slSeg.getTMax(iLayer->idWire);
264  // cell->add(tMaxes);
265  // }
266  // //reset the counter to avoid triple counting
267  // for (vector<cellInfo*>::const_iterator i = cells.begin();
268  // i!= cells.end(); i++) {
269  // (*i)->update();
270  // }
271  // }
272  }
273  }
274  }
275 }
276 
278  theFile->cd();
279  gROOT->GetList()->Write();
280  h2DSegmRPhi->Write();
281  h2DSegmRZ->Write();
282  h4DSegmAllCh->Write();
283  hChi2->Write();
284  // Instantiate a DTCalibrationMap object if you want to calculate the calibration constants
285  DTCalibrationMap calibValuesFile(theCalibFilePar);
286  // Create the object to be written to DB
287  DTMtime* mTime = new DTMtime();
288 
289  // write the TMax histograms of each SL to the root file
290  if (theGranularity == bySL) {
291  for (map<DTWireId, cellInfo*>::const_iterator wireCell = theWireIdAndCellMap.begin();
292  wireCell != theWireIdAndCellMap.end();
293  ++wireCell) {
294  cellInfo* cell = theWireIdAndCellMap[(*wireCell).first];
295  hTMaxCell* cellHists = cell->getHists();
296  theFile->cd();
297  cellHists->Write();
298  if (findVDriftAndT0) { // if TRUE: evaluate calibration constants from TMax hists filled in this job
299  // evaluate v_drift and sigma from the TMax histograms
300  DTWireId wireId = (*wireCell).first;
301  vector<float> newConstants;
302  TString N = (((((TString) "TMax" + (long)wireId.wheel()) + (long)wireId.station()) + (long)wireId.sector()) +
303  (long)wireId.superLayer());
304  vector<float> vDriftAndReso = theFitter->evaluateVDriftAndReso(N);
305 
306  // Don't write the constants for the SL if the vdrift was not computed
307  if (vDriftAndReso.front() == -1)
308  continue;
309  const DTCalibrationMap::CalibConsts* oldConstants = calibValuesFile.getConsts(wireId);
310  if (oldConstants != nullptr) {
311  newConstants.push_back((*oldConstants)[0]);
312  newConstants.push_back((*oldConstants)[1]);
313  newConstants.push_back((*oldConstants)[2]);
314  } else {
315  newConstants.push_back(-1);
316  newConstants.push_back(-1);
317  newConstants.push_back(-1);
318  }
319  for (int ivd = 0; ivd <= 5; ivd++) {
320  // 0=vdrift, 1=reso, 2=(3deltat0-2deltat0), 3=(2deltat0-1deltat0),
321  // 4=(1deltat0-0deltat0), 5=deltat0 from hists with max entries,
322  newConstants.push_back(vDriftAndReso[ivd]);
323  }
324 
325  calibValuesFile.addCell(calibValuesFile.getKey(wireId), newConstants);
326 
327  // vdrift is cm/ns , resolution is cm
328  mTime->set((wireId.layerId()).superlayerId(), vDriftAndReso[0], vDriftAndReso[1], DTVelocityUnits::cm_per_ns);
329  LogTrace("Calibration") << " SL: " << (wireId.layerId()).superlayerId() << " vDrift = " << vDriftAndReso[0]
330  << " reso = " << vDriftAndReso[1];
331  }
332  }
333  }
334 
335  // to be implemented: granularity different from bySL
336 
337  // if(theGranularity == "byChamber") {
338  // const vector<DTChamber*> chambers = dMap.chambers();
339 
340  // // Loop over all chambers
341  // for(vector<MuBarChamber*>::const_iterator chamber = chambers.begin();
342  // chamber != chambers.end(); chamber ++) {
343  // MuBarChamberId chamber_id = (*chamber)->id();
344  // MuBarDigiParameters::Key wire_id(chamber_id, 0, 0, 0);
345  // vector<float> newConstants;
346  // vector<float> vDriftAndReso = evaluateVDriftAndReso(wire_id, f);
347  // const CalibConsts* oldConstants = digiParams.getConsts(wire_id);
348  // if(oldConstants !=0) {
349  // newConstants = *oldConstants;
350  // newConstants.push_back(vDriftAndReso[0]);
351  // newConstants.push_back(vDriftAndReso[1]);
352  // newConstants.push_back(vDriftAndReso[2]);
353  // newConstants.push_back(vDriftAndReso[3]);
354  // } else {
355  // newConstants.push_back(-1);
356  // newConstants.push_back(-1);
357  // newConstants.push_back(vDriftAndReso[0]);
358  // newConstants.push_back(vDriftAndReso[1]);
359  // newConstants.push_back(vDriftAndReso[2]);
360  // newConstants.push_back(vDriftAndReso[3]);
361  // }
362  // digiParams.addCell(wire_id, newConstants);
363  // }
364  // }
365 
366  // Write values to a table
367  calibValuesFile.writeConsts(theVDriftOutputFile);
368 
369  LogVerbatim("Calibration") << "[DTVDriftCalibration]Writing vdrift object to DB!";
370 
371  // Write the vdrift object to DB
372  string record = "DTMtimeRcd";
373  DTCalibDBUtils::writeToDB<DTMtime>(record, mTime);
374 }
375 
376 // to be implemented: granularity different from bySL
377 
378 // // Create partitions
379 // DTVDriftCalibration::cellInfo* DTVDriftCalibration::partition(const DTWireId& wireId) {
380 // for( map<MuBarWireId, cellInfo*>::const_iterator iter =
381 // mapCellTmaxPart.begin(); iter != mapCellTmaxPart.end(); iter++) {
382 // // Divide wires per SL (with phi symmetry)
383 // if(iter->first.wheel() == wireId.wheel() &&
384 // iter->first.station() == wireId.station() &&
385 // // iter->first.sector() == wireId.sector() && // phi symmetry!
386 // iter->first.superlayer() == wireId.superlayer()) {
387 // return iter->second;
388 // }
389 // }
390 // cellInfo * result = new cellInfo("dummy string"); // FIXME: change constructor; create tree?
391 // mapCellTmaxPart.insert(make_pair(wireId, result));
392 // return result;
393 //}
394 
395 void DTVDriftCalibration::cellInfo::add(const vector<const TMax*>& _tMaxes) {
396  vector<const TMax*> tMaxes = _tMaxes;
397  float tmax123 = -1.;
398  float tmax124 = -1.;
399  float tmax134 = -1.;
400  float tmax234 = -1.;
401  SigmaFactor s124 = noR;
402  SigmaFactor s134 = noR;
403  unsigned t0_123 = 0;
404  unsigned t0_124 = 0;
405  unsigned t0_134 = 0;
406  unsigned t0_234 = 0;
407  unsigned hSubGroup = 0;
408  for (vector<const TMax*>::const_iterator it = tMaxes.begin(); it != tMaxes.end(); ++it) {
409  if (*it == nullptr) {
410  continue;
411  } else {
412  //FIXME check cached,
413  if (addedCells.size() == 4 || find(addedCells.begin(), addedCells.end(), (*it)->cells) != addedCells.end()) {
414  continue;
415  }
416  addedCells.push_back((*it)->cells);
417  SigmaFactor sigma = (*it)->sigma;
418  float t = (*it)->t;
419  TMaxCells cells = (*it)->cells;
420  unsigned t0Factor = (*it)->t0Factor;
421  hSubGroup = (*it)->hSubGroup;
422  if (t < 0.)
423  continue;
424  switch (cells) {
425  case notInit:
426  cout << "Error: no cell type assigned to TMax" << endl;
427  break;
428  case c123:
429  tmax123 = t;
430  t0_123 = t0Factor;
431  break;
432  case c124:
433  tmax124 = t;
434  s124 = sigma;
435  t0_124 = t0Factor;
436  break;
437  case c134:
438  tmax134 = t;
439  s134 = sigma;
440  t0_134 = t0Factor;
441  break;
442  case c234:
443  tmax234 = t;
444  t0_234 = t0Factor;
445  break;
446  }
447  }
448  }
449  //add entries to the TMax histograms
450  histos->Fill(tmax123, tmax124, tmax134, tmax234, s124, s134, t0_123, t0_124, t0_134, t0_234, hSubGroup);
451 }
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
const DTSuperLayer * superLayer(const DTSuperLayerId &id) const
Return the superlayer corresponding to the given id.
Definition: DTChamber.cc:53
Key getKey(DTWireId wireId) const
void writeConsts(const std::string &outputFileName) const
std::pair< const_iterator, const_iterator > range
iterator range
Definition: RangeMap.h:50
TMaxGranularity theGranularity
const DTChamber * chamber(const DTChamberId &id) const
Return a DTChamber given its id.
Definition: DTGeometry.cc:90
JetCorrectorParameters::Record record
Definition: classes.h:7
int set(int wheelId, int stationId, int sectorId, int slId, float mTime, float mTrms, DTTimeUnits::type unit)
Definition: DTMtime.cc:168
GlobalPoint toGlobal(const Local2DPoint &lp) const
Conversion to the global R.F. from the R.F. of the GeomDet.
Definition: GeomDet.h:49
std::unique_ptr< DTTTrigBaseSync > theSync
Definition: DTTMax.h:31
T y() const
Definition: PV3DBase.h:60
void Fill(float x, float y, float phi, float theta, float impact)
Definition: vDriftHistos.h:40
LocalPoint toLocal(const GlobalPoint &gp) const
Conversion to the R.F. of the GeomDet.
Definition: GeomDet.h:58
identifier iterator
Definition: RangeMap.h:130
void Fill(float pos, float localAngle)
Definition: vDriftHistos.h:91
void Write()
Definition: vDriftHistos.h:96
DTSuperLayerId superlayerId() const
Return the corresponding SuperLayerId.
Definition: DTLayerId.h:45
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
std::vector< const TMax * > getTMax(const DTWireId &idWire)
Definition: DTTMax.cc:302
Geom::Theta< T > theta() const
Definition: PV3DBase.h:72
C::const_iterator const_iterator
constant access iterator type
Definition: RangeMap.h:43
std::map< DTWireId, cellInfo * > theWireIdAndCellMap
void bookHistos()
Definition: Histogram.h:33
edm::ParameterSet theCalibFilePar
ConsumesCollector consumesCollector()
Use a ConsumesCollector to gather consumes information from helper functions.
T z() const
Definition: PV3DBase.h:61
std::vector< float > CalibConsts
int superLayer() const
Return the superlayer number.
void addCell(Key wireId, const CalibConsts &calibConst)
edm::EDGetTokenT< DTRecSegment4DCollection > theRecHits4DToken
void add(const std::vector< const TMax * > &tMaxes)
TH1F * hChi2
void Write()
Definition: vDriftHistos.h:463
#define LogTrace(id)
std::vector< DTRecHit1D > specificRecHits() const
Access to specific components.
DTSuperLayerId superLayerId() const
The id of the superlayer on which reside the segment.
std::unique_ptr< DTMeanTimerFitter > theFitter
#define N
Definition: blowfish.cc:9
LocalPoint localPosition() const override
local position in SL frame
~DTVDriftCalibration() override
Destructor.
std::unique_ptr< DTSegmentSelector > select_
void analyze(const edm::Event &event, const edm::EventSetup &eventSetup) override
const CalibConsts * getConsts(DTWireId wireId) const
histos
Definition: combine.py:4
DTLayerId layerId() const
Return the corresponding LayerId.
Definition: DTWireId.h:45
HLT enums.
int sector() const
Definition: DTChamberId.h:49
LocalVector localDirection() const override
the local direction in SL frame
T get() const
Definition: EventSetup.h:73
DTVDriftCalibration(const edm::ParameterSet &pset)
Constructor.
constexpr double pi()
Definition: Pi.h:31
int station() const
Return the station number.
Definition: DTChamberId.h:42
int wheel() const
Return the wheel number.
Definition: DTChamberId.h:39
T x() const
Definition: PV3DBase.h:59
void Write()
Definition: vDriftHistos.h:51
Definition: event.py:1