CMS 3D CMS Logo

SiStripLorentzAnglePCLHarvester.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: CalibTracker/SiStripLorentzAnglePCLHarvester
4 // Class: SiStripLorentzAnglePCLHarvester
5 //
9 //
10 // Original Author: mmusich
11 // Created: Sat, 29 May 2021 14:46:19 GMT
12 //
13 //
14 
15 // system includes
16 #include <fmt/format.h>
17 #include <fmt/printf.h>
18 #include <fstream>
19 #include <iostream>
20 #include <sstream>
21 #include <string>
22 #include <vector>
23 
24 // user includes
43 
44 //------------------------------------------------------------------------------
46 public:
48  ~SiStripLorentzAnglePCLHarvester() override = default;
49  void beginRun(const edm::Run&, const edm::EventSetup&) override;
50 
52 
53 private:
55  void endRun(const edm::Run&, const edm::EventSetup&) override;
56  std::string getStem(const std::string& histoName, bool isFolder);
57 
58  // es tokens
64 
65  // member data
66 
69 
70  const bool debug_;
72 
74  const std::vector<double> fitRange_;
76  float theMagField_{0.f};
77 
78  static constexpr float teslaToInverseGeV_ = 2.99792458e-3f;
79  std::pair<double, double> theFitRange_{0., 0.};
80 
83  std::unique_ptr<TrackerTopology> theTrackerTopology_;
84 };
85 
86 //------------------------------------------------------------------------------
88  : geomEsToken_(esConsumes<edm::Transition::BeginRun>()),
89  topoEsTokenBR_(esConsumes<edm::Transition::BeginRun>()),
90  topoEsTokenER_(esConsumes<edm::Transition::EndRun>()),
91  latencyToken_(esConsumes<edm::Transition::BeginRun>()),
92  siStripLAEsToken_(esConsumes<edm::Transition::BeginRun>()),
93  magneticFieldToken_(esConsumes<edm::Transition::BeginRun>()),
94  mismatchedBField_{false},
95  mismatchedLatency_{false},
96  debug_(iConfig.getParameter<bool>("debugMode")),
97  dqmDir_(iConfig.getParameter<std::string>("dqmDir")),
98  fitRange_(iConfig.getParameter<std::vector<double>>("fitRange")),
99  recordName_(iConfig.getParameter<std::string>("record")) {
100  // initialize the fit range
101  if (fitRange_.size() == 2) {
102  theFitRange_.first = fitRange_[0];
103  theFitRange_.second = fitRange_[1];
104  } else {
105  throw cms::Exception("SiStripLorentzAnglePCLHarvester") << "Too many fit range parameters specified";
106  }
107 
108  // first ensure DB output service is available
110  if (!poolDbService.isAvailable())
111  throw cms::Exception("SiStripLorentzAnglePCLHarvester") << "PoolDBService required";
112 }
113 
114 //------------------------------------------------------------------------------
116  // geometry
117  const TrackerGeometry* geom = &iSetup.getData(geomEsToken_);
118  const TrackerTopology* tTopo = &iSetup.getData(topoEsTokenBR_);
119 
120  const MagneticField* magField = &iSetup.getData(magneticFieldToken_);
122 
123  // B-field value
124  // inverseBzAtOriginInGeV() returns the inverse of field z component for this map in GeV
125  // for the conversion please consult https://github.com/cms-sw/cmssw/blob/master/MagneticField/Engine/src/MagneticField.cc#L17
126  // theInverseBzAtOriginInGeV = 1.f / (at0z * 2.99792458e-3f);
127  // ==> at0z = 1.f / (theInverseBzAtOriginInGeV * 2.99792458e-3f)
128 
130 
131  if (iHists_.bfield_.empty()) {
133  } else {
135  mismatchedBField_ = true;
136  }
137  }
138 
139  const SiStripLatency* apvlat = &iSetup.getData(latencyToken_);
140  if (iHists_.apvmode_.empty()) {
142  } else {
144  mismatchedLatency_ = true;
145  }
146  }
147 
148  auto dets = geom->detsTIB();
149  dets.insert(dets.end(), geom->detsTID().begin(), geom->detsTID().end());
150  dets.insert(dets.end(), geom->detsTOB().begin(), geom->detsTOB().end());
151  dets.insert(dets.end(), geom->detsTEC().begin(), geom->detsTEC().end());
152 
153  for (auto det : dets) {
154  auto detid = det->geographicalId().rawId();
155  const StripGeomDetUnit* stripDet = dynamic_cast<const StripGeomDetUnit*>(geom->idToDet(det->geographicalId()));
156  if (stripDet) {
159  }
160  }
161 }
162 
163 //------------------------------------------------------------------------------
165  if (!theTrackerTopology_) {
166  theTrackerTopology_ = std::make_unique<TrackerTopology>(isetup.getData(topoEsTokenER_));
167  }
168 }
169 
170 //------------------------------------------------------------------------------
172  if (mismatchedBField_) {
173  throw cms::Exception("SiStripLorentzAnglePCLHarvester") << "Trying to harvest runs with different B-field values!";
174  }
175 
176  if (mismatchedLatency_) {
177  throw cms::Exception("SiStripLorentzAnglePCLHarvester") << "Trying to harvest runs with diffent APV modes!";
178  }
179 
180  // go in the right directory
181  iGetter.cd();
182  std::string bvalue = (iHists_.bfield_ == "3.8") ? "B-ON" : "B-OFF";
183  std::string folderToHarvest = fmt::format("{}/{}_{}", dqmDir_, bvalue, iHists_.apvmode_);
184  edm::LogPrint(moduleDescription().moduleName()) << "Harvesting in " << folderToHarvest;
185  iGetter.setCurrentFolder(folderToHarvest);
186 
187  // fill in the module types
188  iHists_.nlayers_["TIB"] = 4;
189  iHists_.nlayers_["TOB"] = 6;
190  iHists_.modtypes_.push_back("s");
191  iHists_.modtypes_.push_back("a");
192 
193  std::vector<std::string> MEtoHarvest = {"tanthcosphtrk_nstrip",
194  "thetatrk_nstrip",
195  "tanthcosphtrk_var2",
196  "tanthcosphtrk_var3",
197  "thcosphtrk_var2",
198  "thcosphtrk_var3"};
199 
200  // prepare the histograms to be harvested
201  for (auto& layers : iHists_.nlayers_) {
202  std::string subdet = layers.first;
203  for (int l = 1; l <= layers.second; ++l) {
204  for (auto& t : iHists_.modtypes_) {
205  // do not fill stereo where there aren't
206  if (l > 2 && t == "s")
207  continue;
208  std::string locationtype = Form("%s_L%d%s", subdet.c_str(), l, t.c_str());
209  for (const auto& toHarvest : MEtoHarvest) {
210  const char* address = Form(
211  "%s/%s/L%d/%s_%s", folderToHarvest.c_str(), subdet.c_str(), l, locationtype.c_str(), toHarvest.c_str());
212 
213  LogDebug(moduleDescription().moduleName()) << "harvesting at: " << address << std::endl;
214 
215  iHists_.h2_[Form("%s_%s", locationtype.c_str(), toHarvest.c_str())] = iGetter.get(address);
216  if (iHists_.h2_[Form("%s_%s", locationtype.c_str(), toHarvest.c_str())] == nullptr) {
218  << "could not retrieve: " << Form("%s_%s", locationtype.c_str(), toHarvest.c_str());
219  }
220  }
221  }
222  }
223  }
224 
225  // prepare the profiles
226  for (const auto& ME : iHists_.h2_) {
227  if (!ME.second)
228  continue;
229  // draw colored 2D plots
230  ME.second->setOption("colz");
231  TProfile* hp = (TProfile*)ME.second->getTH2F()->ProfileX();
232  iBooker.setCurrentFolder(folderToHarvest + "/" + getStem(ME.first, /* isFolder = */ true));
233  iHists_.p_[hp->GetName()] = iBooker.bookProfile(hp->GetName(), hp);
234  iHists_.p_[hp->GetName()]->setAxisTitle(ME.second->getAxisTitle(2), 2);
235  delete hp;
236  }
237 
238  if (iHists_.p_.empty()) {
239  edm::LogError(moduleDescription().moduleName()) << "None of the input histograms could be retrieved. Aborting";
240  return;
241  }
242 
243  std::map<std::string, std::pair<double, double>> LAMap_;
244 
245  // do the fits
246  for (const auto& prof : iHists_.p_) {
247  //fit only this type of profile
248  if ((prof.first).find("thetatrk_nstrip") != std::string::npos) {
249  // Create the TF1 function
250 
251  // fitting range (take full axis by default)
252  double low = prof.second->getAxisMin(1);
253  double high = prof.second->getAxisMax(1);
254  if (theFitRange_.first > theFitRange_.second) {
255  low = theFitRange_.first;
256  high = theFitRange_.second;
257  }
258 
259  TF1* fitFunc = new TF1("fitFunc", siStripLACalibration::fitFunction, low, high, 3);
260 
261  // Fit the function to the data
262  prof.second->getTProfile()->Fit(fitFunc, "F"); // "F" option performs a least-squares fit
263 
264  // Get the fit results
265  Double_t a_fit = fitFunc->GetParameter(0);
266  Double_t thetaL_fit = fitFunc->GetParameter(1);
267  Double_t b_fit = fitFunc->GetParameter(2);
268 
269  Double_t a_fitError = fitFunc->GetParError(0);
270  Double_t thetaL_fitError = fitFunc->GetParError(1);
271  Double_t b_fitError = fitFunc->GetParError(2);
272 
273  if (debug_) {
275  << prof.first << " fit result: "
276  << " a=" << a_fit << " +/ " << a_fitError << " theta_L=" << thetaL_fit << " +/- " << thetaL_fitError
277  << " b=" << b_fit << " +/- " << b_fitError;
278  }
279 
280  LAMap_[getStem(prof.first, /* isFolder = */ false)] = std::make_pair(thetaL_fit, thetaL_fitError);
281  }
282  }
283 
284  if (debug_) {
285  for (const auto& element : LAMap_) {
287  << element.first << " thetaLA = " << element.second.first << "+/-" << element.second.second;
288  }
289  }
290 
291  // now prepare the output LA
292  std::shared_ptr<SiStripLorentzAngle> OutLorentzAngle = std::make_shared<SiStripLorentzAngle>();
293 
294  for (const auto& loc : iHists_.moduleLocationType_) {
295  if (debug_) {
296  edm::LogInfo(moduleDescription().moduleName()) << "modId: " << loc.first << " " << loc.second;
297  }
298 
299  if (!(loc.second).empty()) {
300  OutLorentzAngle->putLorentzAngle(loc.first, std::abs(LAMap_[loc.second].first / theMagField_));
301  } else {
302  OutLorentzAngle->putLorentzAngle(loc.first, iHists_.la_db_[loc.first]);
303  }
304  }
305 
307  if (mydbservice.isAvailable()) {
308  try {
309  mydbservice->writeOneIOV(*OutLorentzAngle, mydbservice->currentTime(), recordName_);
310  } catch (const cond::Exception& er) {
311  edm::LogError("SiStripLorentzAngleDB") << er.what();
312  } catch (const std::exception& er) {
313  edm::LogError("SiStripLorentzAngleDB") << "caught std::exception " << er.what();
314  }
315  } else {
316  edm::LogError("SiStripLorentzAngleDB") << "Service is unavailable";
317  }
318 }
319 
320 //------------------------------------------------------------------------------
322  std::vector<std::string> tokens;
323 
325  // Create a string stream from the input string
326  std::istringstream iss(histoName);
327 
329  while (std::getline(iss, token, '_')) {
330  // Add each token to the vector
331  tokens.push_back(token);
332  }
333 
334  if (isFolder) {
335  output = tokens[0] + "/" + tokens[1];
336  output.pop_back();
337  } else {
338  output = tokens[0] + "_" + tokens[1];
339  }
340  return output;
341 }
342 
343 //------------------------------------------------------------------------------
346  desc.setComment("Harvester module of the SiStrip Lorentz Angle PCL monitoring workflow");
347  desc.add<bool>("debugMode", false)->setComment("determines if it's in debug mode");
348  desc.add<std::string>("dqmDir", "AlCaReco/SiStripLorentzAngle")->setComment("the directory of PCL Worker output");
349  desc.add<std::vector<double>>("fitRange", {0., 0.})->setComment("range of depths to perform the LA fit");
350  desc.add<std::string>("record", "SiStripLorentzAngleRcd")->setComment("target DB record");
351  descriptions.addWithDefaultLabel(desc);
352 }
353 
void addWithDefaultLabel(ParameterSetDescription const &psetDescription)
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
Base exception class for the object to relational access.
Definition: Exception.h:11
const edm::ESGetToken< TrackerGeometry, TrackerDigiGeometryRecord > geomEsToken_
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
void beginRun(const edm::Run &, const edm::EventSetup &) override
virtual void setCurrentFolder(std::string const &fullpath)
Definition: DQMStore.cc:36
ModuleDescription const & moduleDescription() const
double fitFunction(double *x, double *par)
Log< level::Error, false > LogError
float inverseBzAtOriginInGeV() const
The inverse of field z component for this map in GeV.
Definition: MagneticField.h:52
Definition: ME.h:11
std::map< std::string, dqm::reco::MonitorElement * > p_
SiStripLorentzAngleCalibrationHistograms iHists_
std::map< std::string, dqm::reco::MonitorElement * > h2_
MonitorElement * bookProfile(TString const &name, TString const &title, int nchX, double lowX, double highX, int, double lowY, double highY, char const *option="s", FUNC onbooking=NOOP())
Definition: DQMStore.h:399
const std::string fieldAsString(const float &inputField)
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
Hash writeOneIOV(const T &payload, Time_t time, const std::string &recordName)
SiStripLorentzAngleCalibrationHistograms hists_
Transition
Definition: Transition.h:12
static void fillDescriptions(edm::ConfigurationDescriptions &)
double f[11][100]
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
std::unique_ptr< TrackerTopology > theTrackerTopology_
const std::string apvModeAsString(const SiStripLatency *latency)
Log< level::Warning, true > LogPrint
Log< level::Info, false > LogInfo
const edm::ESGetToken< TrackerTopology, TrackerTopologyRcd > topoEsTokenBR_
float getLorentzAngle(const uint32_t &) const
std::string getStem(const std::string &histoName, bool isFolder)
const edm::ESGetToken< MagneticField, IdealMagneticFieldRecord > magneticFieldToken_
void dqmEndJob(DQMStore::IBooker &, DQMStore::IGetter &) override
const SiStripLorentzAngle * currentLorentzAngle_
virtual MonitorElement * get(std::string const &fullpath) const
Definition: DQMStore.cc:712
SiStripLorentzAnglePCLHarvester(const edm::ParameterSet &)
void endRun(const edm::Run &, const edm::EventSetup &) override
HLT enums.
~SiStripLorentzAnglePCLHarvester() override=default
bool isAvailable() const
Definition: Service.h:40
Definition: output.py:1
char const * what() const noexcept override
Definition: Exception.cc:107
std::string moduleLocationType(const uint32_t &mod, const TrackerTopology *tTopo)
const edm::ESGetToken< SiStripLorentzAngle, SiStripLorentzAngleDepRcd > siStripLAEsToken_
Definition: Run.h:45
const edm::ESGetToken< TrackerTopology, TrackerTopologyRcd > topoEsTokenER_
#define LogDebug(id)
const edm::ESGetToken< SiStripLatency, SiStripLatencyRcd > latencyToken_