Belle II Software development
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
22using namespace Belle2;
23using 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