CreateTestShowerCalibrationFromPID.cxx
Go to the documentation of this file.
1 /**
2  * @file CreateTestShowerCalibrationFromPID.cxx
3  * @brief Creates a test calibration file for ShowerCalibrationGaloreFromPID
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date April 28, 2016
6  * @see ShowerCalibrationGaloreFromPID.h
7  *
8  * Command line arguments:
9  *
10  * CreateTestCalibrationFromPID [OutputPath]
11  *
12  * OutputPath is a full ROOT directory path made of a UNIX path and a ROOT
13  * directory path. For example, "data/calibrations.root:Showers/ByType" will
14  * create a directory "data" and a "calibrations.root" ROOT file in it (or
15  * update it if exists), create a structure of two nested ROOT directories,
16  * "Showers/ByType", and write all the calibration graphs in there.
17  *
18  * Currently the following calibration objects are written:
19  *
20  * * `"Pi0"` (`TGraphErrors`):
21  * neutral pion calibration vs. reconstructed energy, [ 0; 2 ] GeV range
22  * * `"Photon"` (`TGraphErrors`):
23  * photon calibration vs. reconstructed energy, [ 0; 2 ] GeV range
24  * * `"Electron"` (`TGraphErrors`):
25  * electron/positron calibration vs. reconstructed energy, [ 0; 2 ] GeV range
26  * * `"Muon"` (`TGraphErrors`):
27  * muon/antimuon calibration vs. reconstructed energy, [ 0; 2 ] GeV range
28  * * `"Default"` (`TGraphErrors`):
29  * other particle calibration vs. reconstructed energy, [ 0; 5 ] GeV range
30  *
31  */
32 
33 
34 // LArSoft libraries
36 
37 // ROOT
38 #include "RtypesCore.h"
39 #include "TMath.h"
40 #include "TSystem.h"
41 #include "TClass.h"
42 #include "TFile.h"
43 #include "TDirectory.h"
44 #include "TGraphErrors.h"
45 
46 // C/C++ standard libraries
47 #include <string>
48 #include <iostream>
49 #include <tuple> // std::pair<>, std::tie()
50 #include <stdexcept> // std::runtime_error
51 #include <memory> // std::make_unique()
52 
53 
54 namespace {
55 
56  //---------------------------------------------------------------------------
57 
58  /// Returns a pair with first what precedes sep in s (can be empty), second
59  /// what follows sep (may be everything)
60  std::pair<std::string, std::string> rsplit
61  (std::string const& s, std::string const& sep)
62  {
63  auto iSep = s.rfind(sep);
64  if (iSep == std::string::npos)
65  return { {}, s };
66  else {
67  return
68  { s.substr(0, iSep), s.substr(iSep + sep.length(), s.length()) };
69  }
70  } // rsplit()
71 
72 
73  /// Creates a ROOT directory from a path "path/to/file.root:dirA/dirB/dirC"
74  TDirectory* CreateROOTdir(std::string path) {
75 
76  const std::string suffix = ".root";
77 
78  std::string filePath, rootDirPath;
79 
80  // find the ROOT file name
81  std::string::size_type iSuffix = std::string::npos;
82  do {
83  iSuffix = path.rfind(suffix, iSuffix);
84  if (iSuffix == std::string::npos) return nullptr;
85 
86  // if it's not "suffix:" or "suffix/" or at end of string, it's not it
87  auto iAfter = iSuffix + suffix.length();
88  if ((iAfter < path.length())
89  && (path[iAfter] != '/')
90  && (path[iAfter] != ':')
91  )
92  {
93  if (iSuffix == 0) return nullptr;
94  --iSuffix;
95  continue;
96  }
97 
98  filePath = path.substr(0U, iAfter);
99  if (iAfter < path.length())
100  rootDirPath = path.substr(iAfter + 1, path.length());
101 
102  break;
103  } while (true);
104 
105  // split the file name path
106  std::string fileDir, fileName;
107  std::tie(fileDir, fileName) = rsplit(filePath, "/");
108 
109  std::cout << "Writing to output file: '" << filePath << "'";
110  if (!rootDirPath.empty())
111  std::cout << " (directory: '" << rootDirPath << "')";
112  std::cout << std::endl;
113 
114  // create the directory; the result is the same error code (-1)
115  // whether it already exists or if creation failed;
116  // we don't check it and rely on file creation later to report errors
117  if (!fileDir.empty()) gSystem->mkdir(fileDir.c_str(), true);
118 
119  // we delete the TFile whatever bad happens;
120  // we'll override this (release()) when we know we are keeping the file
121  auto pFile = std::make_unique<TFile>(filePath.c_str(), "UPDATE");
122 
123  if (pFile->IsZombie() || !pFile->IsOpen()) return nullptr;
124  if (rootDirPath.empty()) return pFile.release();
125 
126  if (!pFile->mkdir(rootDirPath.c_str())) return nullptr;
127 
128  TDirectory* pOutputDir = pFile->GetDirectory(rootDirPath.c_str());
129  if (!pOutputDir) return nullptr;
130 
131  pFile.release(); // do not delete the file any more
132  return pOutputDir;
133  } // CreateROOTdir()
134 
135 
136 
137  //---------------------------------------------------------------------------
138  void WriteCalibrationObject
139  (TObject* pObj, std::string title = "calibration object")
140  {
141  if (!pObj) throw std::runtime_error("Can't write " + title);
142 
143  auto written = pObj->Write();
144  if (written == 0) {
145  throw std::runtime_error("Writing of " + title + " "
146  + pObj->IsA()->GetName() + "[\"" + pObj->GetName() + "\"] failed!");
147  }
148  std::cout << "Written " << title << " \"" << pObj->GetName()
149  << "\" (" << pObj->IsA()->GetName() << ") [" << written << " bytes]"
150  << std::endl;
151  } // WriteCalibrationObject()
152 
153 
154  //---------------------------------------------------------------------------
155  TObject* CreateNeutralPionCalibration(std::string name = "Pi0") {
156 
157  constexpr Int_t NPoints = 21;
158  constexpr Double_t MinE = 0.0; // GeV
159  constexpr Double_t MaxE = 2.0; // GeV
160 
161  constexpr Double_t ERange = MaxE - MinE; // GeV
162  constexpr Double_t BinWidth = ERange / (NPoints - 1); // GeV
163 
164 
165  TGraphErrors* pGCorr = new TGraphErrors(NPoints);
166  pGCorr->SetNameTitle(
167  name.c_str(),
168  "#pi^{0} energy calibration"
169  ";reconstructed energy [ GeV ]"
170  ";correction factor"
171  );
172 
173  for (Int_t i = 0; i < NPoints; ++i) {
174  Double_t const E = MinE + BinWidth * i; // GeV
175 
176  Double_t const f
177  = 1.1 - 0.2 * std::sin((E - MinE) / ERange * TMath::Pi() * 2.);
178 
179  pGCorr->SetPoint(i, E, f);
180 
181  pGCorr->SetPointError(i, BinWidth / 2., f * 0.1);
182 
183  } // for
184 
185  return pGCorr;
186  } // CreateNeutralPionCalibration()
187 
188 
189  //---------------------------------------------------------------------------
190  TObject* CreatePhotonCalibration(std::string name = "Photon") {
191 
192  constexpr Int_t NPoints = 21;
193  constexpr Double_t MinE = 0.0; // GeV
194  constexpr Double_t MaxE = 2.0; // GeV
195 
196  constexpr Double_t ERange = MaxE - MinE; // GeV
197  constexpr Double_t BinWidth = ERange / (NPoints - 1); // GeV
198 
199 
200  TGraphErrors* pGCorr = new TGraphErrors(NPoints);
201  pGCorr->SetNameTitle(
202  name.c_str(),
203  "#gamma energy calibration"
204  ";reconstructed energy [ GeV ]"
205  ";correction factor"
206  );
207 
208  for (Int_t i = 0; i < NPoints; ++i) {
209  Double_t const E = MinE + BinWidth * i; // GeV
210 
211  Double_t const f
212  = 1.1 + 0.1 * std::sin((E - MinE) / ERange * TMath::Pi() / 2.);
213 
214  pGCorr->SetPoint(i, E, f);
215 
216  pGCorr->SetPointError(i, BinWidth / 2., f * 0.1);
217 
218  } // for
219 
220  return pGCorr;
221  } // CreatePhotonCalibration()
222 
223 
224  //---------------------------------------------------------------------------
225  TObject* CreateElectronCalibration(std::string name = "Electron") {
226 
227  constexpr Int_t NPoints = 21;
228  constexpr Double_t MinE = 0.0; // GeV
229  constexpr Double_t MaxE = 2.0; // GeV
230 
231  constexpr Double_t ERange = MaxE - MinE; // GeV
232  constexpr Double_t BinWidth = ERange / (NPoints - 1); // GeV
233 
234 
235  TGraphErrors* pGCorr = new TGraphErrors(NPoints);
236  pGCorr->SetNameTitle(
237  name.c_str(),
238  "e^{#pm} energy calibration"
239  ";reconstructed energy [ GeV ]"
240  ";correction factor"
241  );
242 
243  for (Int_t i = 0; i < NPoints; ++i) {
244  Double_t const E = MinE + BinWidth * i; // GeV
245 
246  Double_t const f
247  = 1.15 + 0.1 * std::sin((E - MinE) / ERange * TMath::Pi());
248 
249  pGCorr->SetPoint(i, E, f);
250 
251  pGCorr->SetPointError(i, BinWidth / 2., f * 0.1);
252 
253  } // for
254 
255  return pGCorr;
256  } // CreateElectronCalibration()
257 
258 
259  //---------------------------------------------------------------------------
260  TObject* CreateMuonCalibration(std::string name = "Muon") {
261 
262  constexpr Int_t NPoints = 21;
263  constexpr Double_t MinE = 0.0; // GeV
264  constexpr Double_t MaxE = 2.0; // GeV
265 
266  constexpr Double_t ERange = MaxE - MinE; // GeV
267  constexpr Double_t BinWidth = ERange / (NPoints - 1); // GeV
268 
269 
270  TGraphErrors* pGCorr = new TGraphErrors(NPoints);
271  pGCorr->SetNameTitle(
272  name.c_str(),
273  "#mu^{#pm} energy calibration"
274  ";reconstructed energy [ GeV ]"
275  ";correction factor"
276  );
277 
278  for (Int_t i = 0; i < NPoints; ++i) {
279  Double_t const E = MinE + BinWidth * i; // GeV
280 
281  Double_t const f
282  = 1.05 + 0.02 * std::sin((E - MinE) / ERange * TMath::Pi() * 1.5);
283 
284  pGCorr->SetPoint(i, E, f);
285 
286  pGCorr->SetPointError(i, BinWidth / 2., f * 0.1);
287 
288  } // for
289 
290  return pGCorr;
291  } // CreateMuonCalibration()
292 
293 
294  //---------------------------------------------------------------------------
295  TObject* CreateGeneralCalibration(std::string name = "Default") {
296 
297  constexpr Double_t MinE = 0.0; // GeV
298  constexpr Double_t MaxE = 2.2; // GeV
299 
300  constexpr Double_t ERange = MaxE - MinE; // GeV
301 
302  TGraphErrors* pGCorr = new TGraphErrors(1);
303  pGCorr->SetNameTitle(
304  name.c_str(),
305  "Generic energy calibration"
306  ";reconstructed energy [ GeV ]"
307  ";correction factor"
308  );
309 
310 
311  Double_t const E = MinE + ERange / 2.; // GeV
312  Double_t const f = 1.10;
313 
314  pGCorr->SetPoint(0, E, f);
315 
316  pGCorr->SetPointError(0, ERange / 2., f * 0.1);
317 
318  return pGCorr;
319  } // CreateGeneralCalibration()
320 
321  //---------------------------------------------------------------------------
322 
323 } // local namespace
324 
325 
326 //------------------------------------------------------------------------------
328  (std::string outputPath)
329 {
330 
331  //
332  // create output file
333  //
334  TDirectory* pOutputDir = CreateROOTdir(outputPath);
335  if (!pOutputDir) {
336  std::cerr << "Can't create ROOT directory '" << outputPath << "'"
337  << std::endl;
338  return 1;
339  }
340  TFile* pOutputFile = pOutputDir->GetFile();
341 
342  //
343  // create the calibration histograms
344  //
345  pOutputDir->cd();
346  try {
347  WriteCalibrationObject
348  (CreateNeutralPionCalibration(), "pion calibration");
349  WriteCalibrationObject(CreatePhotonCalibration(), "photon calibration");
350  WriteCalibrationObject
351  (CreateElectronCalibration(), "electron calibration");
352  WriteCalibrationObject(CreateMuonCalibration(), "muon calibration");
353  WriteCalibrationObject(CreateGeneralCalibration(), "generic calibration");
354  }
355  catch (std::runtime_error const& e) {
356  std::cerr << "An error occurred: " << e.what() << std::endl;
357  return 1;
358  }
359 
360  //
361  // close output and leave (deliberately ONLY if writing above was successful)
362  //
363  pOutputDir->Write();
364  pOutputFile->Write();
365  delete pOutputFile;
366 
367  return 0;
368 } // lar::example::tests::CreateTestShowerCalibrationFromPID()
369 
370 
371 //------------------------------------------------------------------------------
static QCString name
Definition: declinfo.cpp:673
std::string string
Definition: nybbler.cc:12
const double e
fileName
Definition: dumpTree.py:9
int CreateTestShowerCalibrationFromPID(std::string outputPath)
Creates a test calibration file for ShowerCalibrationGaloreFromPID.
Creates a test calibration file for ShowerCalibrationGaloreFromPID.
static QCString * s
Definition: config.cpp:1042
QTextStream & endl(QTextStream &s)