Belle II Software  release-08-01-10
TestCalibrationAlgorithm.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #include <calibration/example_caf_lib/TestCalibrationAlgorithm.h>
9 
10 #include <memory>
11 
12 #include <TTree.h>
13 #include <TH1F.h>
14 #include <TClonesArray.h>
15 #include <TRandom.h>
16 
17 
18 #include <alignment/dataobjects/MilleData.h>
19 #include <calibration/dbobjects/TestCalibObject.h>
20 #include <calibration/dbobjects/TestCalibMean.h>
21 
22 using namespace Belle2;
23 using namespace Calibration;
24 
26 {
28  " -------------------------- Test Calibration Algoritm -------------------------\n"
29  " \n"
30  " Testing algorithm which just gets mean of a test histogram collected by \n"
31  " CaTest module and provides a DB object with another histogram with one \n"
32  " entry at calibrated value. \n"
33  " ------------------------------------------------------------------------------\n"
34  );
35 }
36 
38 {
39  std::string debugFileName = (this->getPrefix()) + "debug.root";
40  B2INFO("Storing histograms in " << debugFileName);
41 
42  // Save the current directory to change back later
43  TDirectory* currentDir = gDirectory;
44  TFile* debugFile = new TFile(debugFileName.c_str(), "RECREATE");
45  debugFile->cd();
46  TH1F* debugHisto = new TH1F("h1", "h1", 30, -3., 3.);
47  for (int i = 0; i < 1000; ++i) {
48  debugHisto->Fill(gRandom->Gaus());
49  }
50 
51  debugHisto->Write();
52  debugFile->Close();
53  currentDir->cd();
54 }
55 
57 {
58  // Some calibrations may want to pass information from one execution to the next.
59  // We do this via a json object that is created like a std::map (or Python dictionary).
60  // You will have set this json object up manually by calling loadInputJson(string),
61  // or the Python CAF may do this for you.
62  //
63  // USING THIS FEATURE IS OPTIONAL!!!
64  //
65  // It is only for cases where you really need to pass a message from one execution of the algorithm
66  // to the next. It is not supposed to be for all of your config variables. Use member variables for
67  // configuring your algorithm!
68 
69  // You can pull in from the Input JSON like so
70  // First you must know the string used to label the value, in this case we save the previous calculated mean
71  const std::string previousMeanKey = "previous_mean";
72  // Test if the key exists in our inputJson object (was it set?)
73  if (inputJsonKeyExists(previousMeanKey)) {
74  const float prevMean = getOutputJsonValue<float>(previousMeanKey);
75  B2INFO("An input JSON object was set with the previous calculated mean = " << prevMean);
76  }
77 
78  // Pulling in data from collector output. It now returns shared_ptr<T> so the underlying pointer
79  // will delete itself automatically at the end of this scope unless you do something
80  auto ttree = getObjectPtr<TTree>("MyTree");
81  auto hist = getObjectPtr<TH1F>("MyHisto");
82  auto mille = getObjectPtr<MilleData>("test_mille");
83  if (!ttree) return c_Failure;
84  if (!hist) return c_Failure;
85  if (!mille) return c_Failure;
86  B2INFO("Number of Entries in MyTree was " << ttree->GetEntries());
87  B2INFO("Number of Entries in MyHisto was " << hist->GetEntries());
88 
89  float mean = hist->GetMean();
90  float meanError = hist->GetMeanError();
91 
92  B2INFO("Mean of MyHisto was " << mean);
93  B2INFO("Mean Error of MyHisto was " << meanError);
94 
95  // Create debugging histo if we asked for it
97 
98  // Fail if we we're asked to. Useful for testing
99  if (getForceFail()) {
100  B2WARNING("We were asked to fail by the m_willFail flag. Failing");
101  return c_Failure;
102  }
103 
104  for (auto& fileName : mille->getFiles()) {
105  B2INFO("Stored Mille binary file: " << fileName);
106  }
107 
108  if (hist->GetEntries() < 100 || ttree->GetEntries() < getMinEntries() || mille->getFiles().empty())
109  return c_NotEnoughData;
110 
111  // Example of saving a DBObject.
112  TestCalibMean* correction = new TestCalibMean(mean, meanError);
113  saveCalibration(correction, "TestCalibMean");
114 
115  // Example of saving a Belle2 DBArray of DBObjects defined in the dbobjects directory
116  TClonesArray* exampleDBArrayConstants = new TClonesArray("Belle2::TestCalibObject", 2);
117  float val = 0.0;
118  for (int i = 0; i < 2; i++) {
119  val += 1.0;
120  new((*exampleDBArrayConstants)[i]) TestCalibObject(val);
121  }
122  saveCalibration(exampleDBArrayConstants, "TestCalibObjects");
123  // Iterate until we find answer to the most fundamental question...
124  B2INFO("mean: " << mean);
125  B2INFO("meanError: " << meanError);
126 
127  // Remember how we optionally had an input JSON object? Well this is how you can pass out JSON information
128  // to the Python CAF. You need to set the information into the object
129  setOutputJsonValue<float>(previousMeanKey, mean);
130 
131  // Decide if we need to iterate or if this value was fine
132  if (mean - 42. >= 1.) {
133  return c_Iterate;
134  } else {
135  return c_OK;
136  }
137 }
138 
140 {
141  auto hist = getObjectPtr<TH1F>("MyHisto");
142  float mean = hist->GetMean();
143  // First run?
144  if (!m_previousMean) {
145  B2INFO("This is the first run encountered, let's say it is a boundary.");
146  B2INFO("Initial mean was " << mean);
147  m_previousMean.emplace(mean);
148  return true;
149  }
150  // Shifted since last time?
151  else if ((mean - m_previousMean.value()) > m_allowedMeanShift) {
152  B2INFO("Histogram mean has shifted from " << m_previousMean.value()
153  << " to " << mean << ". We are requesting a new payload boundary for ("
154  << currentRun.first << "," << currentRun.second << ")");
155  m_previousMean.emplace(mean);
156  return true;
157  } else {
158  return false;
159  }
160 }
Base class for calibration algorithms.
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
bool inputJsonKeyExists(const std::string &key) const
Test for a key in the input JSON object.
void setDescription(const std::string &description)
Set algorithm description (in constructor)
std::string getPrefix() const
Get the prefix used for getting calibration data.
EResult
The result of calibration.
@ c_OK
Finished successfuly =0 in Python.
@ c_Iterate
Needs iteration =1 in Python.
@ c_NotEnoughData
Needs more data =2 in Python.
@ c_Failure
Failed =3 in Python.
Test DBObject.
Definition: TestCalibMean.h:17
bool getForceFail()
getter for m_willFail
int m_debugHisto
Set if a debugging histogram should be created in the algorithm output directory.
std::optional< float > m_previousMean
During isBoundaryRequired this is used to define the previous run's mean.
virtual EResult calibrate() override
Run algo on data.
float m_allowedMeanShift
Configurable parameter for deciding when to choose a new payload boundary (if used)
virtual bool isBoundaryRequired(const Calibration::ExpRun &currentRun) override
Decide if a run should be a payload boundary. Only used in certain Python Algorithm Starategies.
void createDebugHistogram()
Perform debug histogram file creation.
TestCalibrationAlgorithm()
Constructor set the prefix to TestCalibration.
int getMinEntries()
getter for m_minEntries
Abstract base class for different kinds of events.
Struct containing exp number and run number.
Definition: Splitter.h:51