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 Algorithm -------------------------\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}
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 successfully =0 in Python.
@ c_Iterate
Needs iteration =1 in Python.
@ c_NotEnoughData
Needs more data =2 in Python.
const T getOutputJsonValue(const std::string &key) const
Get a value using a key from the JSON output object, not sure why you would want to do this.
void setOutputJsonValue(const std::string &key, const T &value)
Set a key:value pair for the outputJson object, expected to used internally during calibrate()
CalibrationAlgorithm(const std::string &collectorModuleName)
Constructor - sets the prefix for collected objects (won't be accesses until execute(....
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
std::shared_ptr< T > getObjectPtr(const std::string &name, const std::vector< Calibration::ExpRun > &requestedRuns)
Get calibration data object by name and list of runs, the Merge function will be called to generate t...
Abstract base class for different kinds of events.
Struct containing exp number and run number.
Definition Splitter.h:51