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
44 
45 //------------------------------------------------------------------------------
47 public:
49  ~SiStripLorentzAnglePCLHarvester() override = default;
50  void beginRun(const edm::Run&, const edm::EventSetup&) override;
51 
53 
54 private:
56  void endRun(const edm::Run&, const edm::EventSetup&) override;
57  std::string getStem(const std::string& histoName, bool isFolder);
58 
59  // es tokens
65 
66  // member data
67 
70 
71  const bool debug_;
73 
75  const std::vector<double> fitRange_;
77  float theMagField_{0.f};
78 
79  static constexpr float teslaToInverseGeV_ = 2.99792458e-3f;
80  std::pair<double, double> theFitRange_{0., 0.};
81 
84  std::unique_ptr<TrackerTopology> theTrackerTopology_;
85 };
86 
87 //------------------------------------------------------------------------------
89  : geomEsToken_(esConsumes<edm::Transition::BeginRun>()),
90  topoEsTokenBR_(esConsumes<edm::Transition::BeginRun>()),
91  topoEsTokenER_(esConsumes<edm::Transition::EndRun>()),
92  latencyToken_(esConsumes<edm::Transition::BeginRun>()),
93  siStripLAEsToken_(esConsumes<edm::Transition::BeginRun>()),
94  magneticFieldToken_(esConsumes<edm::Transition::BeginRun>()),
95  mismatchedBField_{false},
96  mismatchedLatency_{false},
97  debug_(iConfig.getParameter<bool>("debugMode")),
98  dqmDir_(iConfig.getParameter<std::string>("dqmDir")),
99  fitRange_(iConfig.getParameter<std::vector<double>>("fitRange")),
100  recordName_(iConfig.getParameter<std::string>("record")) {
101  // initialize the fit range
102  if (fitRange_.size() == 2) {
103  theFitRange_.first = fitRange_[0];
104  theFitRange_.second = fitRange_[1];
105  } else {
106  throw cms::Exception("SiStripLorentzAnglePCLHarvester") << "Too many fit range parameters specified";
107  }
108 
109  // first ensure DB output service is available
111  if (!poolDbService.isAvailable())
112  throw cms::Exception("SiStripLorentzAnglePCLHarvester") << "PoolDBService required";
113 }
114 
115 //------------------------------------------------------------------------------
117  // geometry
118  const TrackerGeometry* geom = &iSetup.getData(geomEsToken_);
119  const TrackerTopology* tTopo = &iSetup.getData(topoEsTokenBR_);
120 
121  const MagneticField* magField = &iSetup.getData(magneticFieldToken_);
123 
124  // B-field value
125  // inverseBzAtOriginInGeV() returns the inverse of field z component for this map in GeV
126  // for the conversion please consult https://github.com/cms-sw/cmssw/blob/master/MagneticField/Engine/src/MagneticField.cc#L17
127  // theInverseBzAtOriginInGeV = 1.f / (at0z * 2.99792458e-3f);
128  // ==> at0z = 1.f / (theInverseBzAtOriginInGeV * 2.99792458e-3f)
129 
131 
132  if (iHists_.bfield_.empty()) {
134  } else {
136  mismatchedBField_ = true;
137  }
138  }
139 
140  const SiStripLatency* apvlat = &iSetup.getData(latencyToken_);
141  if (iHists_.apvmode_.empty()) {
143  } else {
145  mismatchedLatency_ = true;
146  }
147  }
148 
149  auto dets = geom->detsTIB();
150  dets.insert(dets.end(), geom->detsTID().begin(), geom->detsTID().end());
151  dets.insert(dets.end(), geom->detsTOB().begin(), geom->detsTOB().end());
152  dets.insert(dets.end(), geom->detsTEC().begin(), geom->detsTEC().end());
153 
154  for (auto det : dets) {
155  auto detid = det->geographicalId().rawId();
156  const StripGeomDetUnit* stripDet = dynamic_cast<const StripGeomDetUnit*>(geom->idToDet(det->geographicalId()));
157  if (stripDet) {
160  }
161  }
162 }
163 
164 //------------------------------------------------------------------------------
166  if (!theTrackerTopology_) {
167  theTrackerTopology_ = std::make_unique<TrackerTopology>(isetup.getData(topoEsTokenER_));
168  }
169 }
170 
171 //------------------------------------------------------------------------------
173  if (mismatchedBField_) {
174  throw cms::Exception("SiStripLorentzAnglePCLHarvester") << "Trying to harvest runs with different B-field values!";
175  }
176 
177  if (mismatchedLatency_) {
178  throw cms::Exception("SiStripLorentzAnglePCLHarvester") << "Trying to harvest runs with diffent APV modes!";
179  }
180 
181  // go in the right directory
182  iGetter.cd();
183  std::string bvalue = (iHists_.bfield_ == "3.8") ? "B-ON" : "B-OFF";
184  std::string folderToHarvest = fmt::format("{}/{}_{}", dqmDir_, bvalue, iHists_.apvmode_);
185  edm::LogPrint(moduleDescription().moduleName()) << "Harvesting in " << folderToHarvest;
186  iGetter.setCurrentFolder(folderToHarvest);
187 
188  // fill in the module types
189  iHists_.nlayers_["TIB"] = 4;
190  iHists_.nlayers_["TOB"] = 6;
191  iHists_.modtypes_.push_back("s");
192  iHists_.modtypes_.push_back("a");
193 
194  std::vector<std::string> MEtoHarvest = {"tanthcosphtrk_nstrip",
195  "thetatrk_nstrip",
196  "tanthcosphtrk_var2",
197  "tanthcosphtrk_var3",
198  "thcosphtrk_var2",
199  "thcosphtrk_var3"};
200 
201  // prepare the histograms to be harvested
202  for (auto& layers : iHists_.nlayers_) {
203  std::string subdet = layers.first;
204  for (int l = 1; l <= layers.second; ++l) {
205  for (auto& t : iHists_.modtypes_) {
206  // do not fill stereo where there aren't
207  if (l > 2 && t == "s")
208  continue;
209  std::string locationtype = Form("%s_L%d%s", subdet.c_str(), l, t.c_str());
210  for (const auto& toHarvest : MEtoHarvest) {
211  const char* address = Form(
212  "%s/%s/L%d/%s_%s", folderToHarvest.c_str(), subdet.c_str(), l, locationtype.c_str(), toHarvest.c_str());
213 
214  LogDebug(moduleDescription().moduleName()) << "harvesting at: " << address << std::endl;
215 
216  iHists_.h2_[Form("%s_%s", locationtype.c_str(), toHarvest.c_str())] = iGetter.get(address);
217  if (iHists_.h2_[Form("%s_%s", locationtype.c_str(), toHarvest.c_str())] == nullptr) {
219  << "could not retrieve: " << Form("%s_%s", locationtype.c_str(), toHarvest.c_str());
220  }
221  }
222  }
223  }
224  }
225 
226  // prepare the profiles
227  for (const auto& ME : iHists_.h2_) {
228  if (!ME.second)
229  continue;
230  TProfile* hp = (TProfile*)ME.second->getTH2F()->ProfileX();
231  iBooker.setCurrentFolder(folderToHarvest + "/" + getStem(ME.first, /* isFolder = */ true));
232  iHists_.p_[hp->GetName()] = iBooker.bookProfile(hp->GetName(), hp);
233  iHists_.p_[hp->GetName()]->setAxisTitle(ME.second->getAxisTitle(2), 2);
234  delete hp;
235  }
236 
237  if (iHists_.p_.empty()) {
238  edm::LogError(moduleDescription().moduleName()) << "None of the input histograms could be retrieved. Aborting";
239  return;
240  }
241 
242  std::map<std::string, std::pair<double, double>> LAMap_;
243 
244  // do the fits
245  for (const auto& prof : iHists_.p_) {
246  //fit only this type of profile
247  if ((prof.first).find("thetatrk_nstrip") != std::string::npos) {
248  // Create the TF1 function
249 
250  // fitting range (take full axis by default)
251  double low = prof.second->getAxisMin(1);
252  double high = prof.second->getAxisMax(1);
253  if (theFitRange_.first > theFitRange_.second) {
254  low = theFitRange_.first;
255  high = theFitRange_.second;
256  }
257 
258  TF1* fitFunc = new TF1("fitFunc", siStripLACalibration::fitFunction, low, high, 3);
259 
260  // Fit the function to the data
261  prof.second->getTProfile()->Fit(fitFunc, "F"); // "F" option performs a least-squares fit
262 
263  // Get the fit results
264  Double_t a_fit = fitFunc->GetParameter(0);
265  Double_t thetaL_fit = fitFunc->GetParameter(1);
266  Double_t b_fit = fitFunc->GetParameter(2);
267 
268  Double_t a_fitError = fitFunc->GetParError(0);
269  Double_t thetaL_fitError = fitFunc->GetParError(1);
270  Double_t b_fitError = fitFunc->GetParError(2);
271 
272  if (debug_) {
274  << prof.first << " fit result: "
275  << " a=" << a_fit << " +/ " << a_fitError << " theta_L=" << thetaL_fit << " +/- " << thetaL_fitError
276  << " b=" << b_fit << " +/- " << b_fitError;
277  }
278 
279  LAMap_[getStem(prof.first, /* isFolder = */ false)] = std::make_pair(thetaL_fit, thetaL_fitError);
280  }
281  }
282 
283  if (debug_) {
284  for (const auto& element : LAMap_) {
286  << element.first << " thetaLA = " << element.second.first << "+/-" << element.second.second;
287  }
288  }
289 
290  // now prepare the output LA
291  std::shared_ptr<SiStripLorentzAngle> OutLorentzAngle = std::make_shared<SiStripLorentzAngle>();
292 
293  for (const auto& loc : iHists_.moduleLocationType_) {
294  if (debug_) {
295  edm::LogInfo(moduleDescription().moduleName()) << "modId: " << loc.first << " " << loc.second;
296  }
297 
298  if (!(loc.second).empty()) {
299  OutLorentzAngle->putLorentzAngle(loc.first, std::abs(LAMap_[loc.second].first / theMagField_));
300  } else {
301  OutLorentzAngle->putLorentzAngle(loc.first, iHists_.la_db_[loc.first]);
302  }
303  }
304 
306  if (mydbservice.isAvailable()) {
307  try {
308  mydbservice->writeOneIOV(*OutLorentzAngle, mydbservice->currentTime(), recordName_);
309  } catch (const cond::Exception& er) {
310  edm::LogError("SiStripLorentzAngleDB") << er.what();
311  } catch (const std::exception& er) {
312  edm::LogError("SiStripLorentzAngleDB") << "caught std::exception " << er.what();
313  }
314  } else {
315  edm::LogError("SiStripLorentzAngleDB") << "Service is unavailable";
316  }
317 }
318 
319 //------------------------------------------------------------------------------
321  std::vector<std::string> tokens;
322 
324  // Create a string stream from the input string
325  std::istringstream iss(histoName);
326 
328  while (std::getline(iss, token, '_')) {
329  // Add each token to the vector
330  tokens.push_back(token);
331  }
332 
333  if (isFolder) {
334  output = tokens[0] + "/" + tokens[1];
335  output.pop_back();
336  } else {
337  output = tokens[0] + "_" + tokens[1];
338  }
339  return output;
340 }
341 
342 //------------------------------------------------------------------------------
345  desc.setComment("Harvester module of the SiStrip Lorentz Angle PCL monitoring workflow");
346  desc.add<bool>("debugMode", false)->setComment("determines if it's in debug mode");
347  desc.add<std::string>("dqmDir", "AlCaReco/SiStripLorentzAngle")->setComment("the directory of PCL Worker output");
348  desc.add<std::vector<double>>("fitRange", {0., 0.})->setComment("range of depths to perform the LA fit");
349  desc.add<std::string>("record", "SiStripLorentzAngleRcd")->setComment("target DB record");
350  descriptions.addWithDefaultLabel(desc);
351 }
352 
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
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_