Belle II Software development
CalibrationAlgorithm.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 <set>
9#include <utility>
10#include <filesystem>
11#include <boost/algorithm/string.hpp>
12#include <boost/python.hpp>
13#include <boost/python/list.hpp>
14#include <TChain.h>
15#include <calibration/CalibrationAlgorithm.h>
16#include <framework/logging/Logger.h>
17#include <framework/core/PyObjConvUtils.h>
18#include <framework/io/RootIOUtilities.h>
19
20using namespace Belle2;
21using namespace std;
22using namespace Calibration;
23namespace fs = std::filesystem;
24
25const ExpRun CalibrationAlgorithm::m_allExpRun = make_pair(-1, -1);
26
29{
30 // Is it a sequence?
31 if (PySequence_Check(pyObj)) {
32 Py_ssize_t nObj = PySequence_Length(pyObj);
33 // Does it have 2 objects in it?
34 if (nObj != 2) {
35 B2DEBUG(29, "ExpRun was a Python sequence which didn't have exactly 2 entries!");
36 return false;
37 }
38 PyObject* item1, *item2;
39 item1 = PySequence_GetItem(pyObj, 0);
40 item2 = PySequence_GetItem(pyObj, 1);
41 // Did the GetItem work?
42 if ((item1 == NULL) || (item2 == NULL)) {
43 B2DEBUG(29, "A PyObject pointer was NULL in the sequence");
44 return false;
45 }
46 // Are they longs?
47 if (PyLong_Check(item1) && PyLong_Check(item2)) {
48 long value1, value2;
49 value1 = PyLong_AsLong(item1);
50 value2 = PyLong_AsLong(item2);
51 if (((value1 == -1) || (value2 == -1)) && PyErr_Occurred()) {
52 B2DEBUG(29, "An error occurred while converting the PyLong to long");
53 return false;
54 }
55 } else {
56 B2DEBUG(29, "One or more of the PyObjects in the ExpRun wasn't a long");
57 return false;
58 }
59 // Make sure to kill off the reference GetItem gave us responsibility for
60 Py_DECREF(item1);
61 Py_DECREF(item2);
62 } else {
63 B2DEBUG(29, "ExpRun was not a Python sequence.");
64 return false;
65 }
66 return true;
67}
68
71{
72 ExpRun expRun;
73 PyObject* itemExp, *itemRun;
74 itemExp = PySequence_GetItem(pyObj, 0);
75 itemRun = PySequence_GetItem(pyObj, 1);
76 expRun.first = PyLong_AsLong(itemExp);
77 Py_DECREF(itemExp);
78 expRun.second = PyLong_AsLong(itemRun);
79 Py_DECREF(itemRun);
80 return expRun;
81}
82
84{
85 B2DEBUG(29, "Running execute() using Python Object as input argument");
86 // Reset the execution specific data in case the algorithm was previously called
87 m_data.reset();
88 m_data.setIteration(iteration);
89 vector<ExpRun> vecRuns;
90 // Is it a list?
91 if (PySequence_Check(runs)) {
92 boost::python::handle<> handle(boost::python::borrowed(runs));
93 boost::python::list listRuns(handle);
94
95 int nList = boost::python::len(listRuns);
96 for (int iList = 0; iList < nList; ++iList) {
97 boost::python::object pyExpRun(listRuns[iList]);
98 if (!checkPyExpRun(pyExpRun.ptr())) {
99 B2ERROR("Received Python ExpRuns couldn't be converted to C++");
100 m_data.setResult(c_Failure);
101 return c_Failure;
102 } else {
103 vecRuns.push_back(convertPyExpRun(pyExpRun.ptr()));
104 }
105 }
106 } else {
107 B2ERROR("Tried to set the input runs but we didn't receive a Python sequence object (list,tuple).");
108 m_data.setResult(c_Failure);
109 return c_Failure;
110 }
111 return execute(vecRuns, iteration, iov);
112}
113
114CalibrationAlgorithm::EResult CalibrationAlgorithm::execute(vector<Calibration::ExpRun> runs, int iteration, IntervalOfValidity iov)
115{
116 // Check if we are calling this function directly and need to reset, or through Python where it was already done.
117 if (m_data.getResult() != c_Undefined) {
118 m_data.reset();
119 m_data.setIteration(iteration);
120 }
121
122 if (m_inputFileNames.empty()) {
123 B2ERROR("There aren't any input files set. Please use CalibrationAlgorithm::setInputFiles()");
124 m_data.setResult(c_Failure);
125 return c_Failure;
126 }
127
128 // Did we receive runs to execute over explicitly?
129 if (!(runs.empty())) {
130 for (auto expRun : runs) {
131 B2DEBUG(29, "ExpRun requested = (" << expRun.first << ", " << expRun.second << ")");
132 }
133 // We've asked explicitly for certain runs, but we should check if the data granularity is 'run'
134 if (strcmp(getGranularity().c_str(), "all") == 0) {
135 B2ERROR(("The data is collected with granularity=all (exp=-1,run=-1), but you seem to request calibration for specific runs."
136 " We'll continue but using ALL the input data given instead of the specific runs requested."));
137 }
138 } else {
139 // If no runs are provided, infer the runs from all collected data
140 runs = getRunListFromAllData();
141 // Let's check that we have some now
142 if (runs.empty()) {
143 B2ERROR("No collected data in input files.");
144 m_data.setResult(c_Failure);
145 return c_Failure;
146 }
147 for (auto expRun : runs) {
148 B2DEBUG(29, "ExpRun requested = (" << expRun.first << ", " << expRun.second << ")");
149 }
150 }
151
152 m_data.setRequestedRuns(runs);
153 if (iov.empty()) {
154 // If no user specified IoV we use the IoV from the executed run list
155 iov = IntervalOfValidity(runs[0].first, runs[0].second, runs[runs.size() - 1].first, runs[runs.size() - 1].second);
156 }
157 m_data.setRequestedIov(iov);
158 // After here, the getObject<...>(...) helpers start to work
159
161 m_data.setResult(result);
162 return result;
163}
164
166void CalibrationAlgorithm::setInputFileNames(PyObject* inputFileNames)
167{
168 // The reasoning for this very 'manual' approach to extending the Python interface
169 // (instead of using boost::python) is down to my fear of putting off final users with
170 // complexity on their side.
171 //
172 // I didn't want users that inherit from this class to be forced to use boost and
173 // to have to define a new python module just to use the CAF. A derived class from
174 // from a boost exposed class would need to have its own boost python module definition
175 // to allow access from a steering file and to the base class functions (I think).
176 // I also couldn't be bothered to write a full framework to get around the issue in a similar
177 // way to Module()...maybe there's an easy way.
178 //
179 // But this way we can allow people to continue using their ROOT implemented classes and inherit
180 // easily from this one. But add in a few helper functions that work with Python objects
181 // created in their steering file i.e. instead of being forced to use STL objects as input
182 // to the algorithm.
183 if (PyList_Check(inputFileNames)) {
184 boost::python::handle<> handle(boost::python::borrowed(inputFileNames));
185 boost::python::list listInputFileNames(handle);
186 auto vecInputFileNames = PyObjConvUtils::convertPythonObject(listInputFileNames, vector<string>());
187 setInputFileNames(vecInputFileNames);
188 } else {
189 B2ERROR("Tried to set the input files but we didn't receive a Python list.");
190 }
191}
192
194void CalibrationAlgorithm::setInputFileNames(const vector<string>& inputFileNames)
195{
196 // A lot of code below is tweaked from RootInputModule::initialize,
197 // since we're basically copying the functionality anyway.
198 if (inputFileNames.empty()) {
199 B2WARNING("You have called setInputFileNames() with an empty list. Did you mean to do that?");
200 return;
201 }
202 auto tmpInputFileNames = RootIOUtilities::expandWordExpansions(inputFileNames);
203
204 // We'll use a set to enforce sorted unique file paths as we check them
205 set<string> setInputFileNames;
206 // Check that files exist and convert to absolute paths
207 for (auto path : tmpInputFileNames) {
208 string fullPath = fs::absolute(path).string();
209 if (fs::exists(fullPath)) {
210 setInputFileNames.insert(fs::canonical(fullPath).string());
211 } else {
212 B2WARNING("Couldn't find the file " << path);
213 }
214 }
215
216 if (setInputFileNames.empty()) {
217 B2WARNING("No valid files specified!");
218 return;
219 } else {
220 // Reset the run -> files map as our files are likely different
221 m_runsToInputFiles.clear();
222 }
223
224 // Open TFile to check they can be accessed by ROOT
225 TDirectory* dir = gDirectory;
226 for (const string& fileName : setInputFileNames) {
227 unique_ptr<TFile> f;
228 try {
229 f.reset(TFile::Open(fileName.c_str(), "READ"));
230 } catch (logic_error&) {
231 //this might happen for ~invaliduser/foo.root
232 //actually undefined behaviour per standard, reported as ROOT-8490 in JIRA
233 }
234 if (!f || !f->IsOpen()) {
235 B2FATAL("Couldn't open input file " + fileName);
236 }
237 }
238 dir->cd();
239
240 // Copy the entries of the set to a vector
241 m_inputFileNames = vector<string>(setInputFileNames.begin(), setInputFileNames.end());
243}
244
246{
247 PyObject* objInputFileNames = PyList_New(m_inputFileNames.size());
248 for (size_t i = 0; i < m_inputFileNames.size(); ++i) {
249 PyList_SetItem(objInputFileNames, i, Py_BuildValue("s", m_inputFileNames[i].c_str()));
250 }
251 return objInputFileNames;
252}
253
255{
256 string expRunString;
257 expRunString += to_string(expRun.first);
258 expRunString += ".";
259 expRunString += to_string(expRun.second);
260 return expRunString;
261}
262
263string CalibrationAlgorithm::getFullObjectPath(const string& name, ExpRun expRun) const
264{
265 string dirName = getPrefix() + "/" + name;
266 string objName = name + "_" + getExpRunString(expRun);
267 return dirName + "/" + objName;
268}
269
270void CalibrationAlgorithm::saveCalibration(TObject* data, const string& name, const IntervalOfValidity& iov)
271{
272 B2DEBUG(29, "Saving calibration TObject = '" << name << "' to payloads list.");
273 getPayloads().emplace_back(name, data, iov);
274}
275
276void CalibrationAlgorithm::saveCalibration(TClonesArray* data, const string& name, const IntervalOfValidity& iov)
277{
278 B2DEBUG(29, "Saving calibration TClonesArray '" << name << "' to payloads list.");
279 getPayloads().emplace_back(name, data, iov);
280}
281
283{
284 saveCalibration(data, DataStore::objectName(data->IsA(), ""), iov);
285}
286
288{
289 saveCalibration(data, DataStore::objectName(data->IsA(), ""));
290}
291
292void CalibrationAlgorithm::saveCalibration(TObject* data, const string& name)
293{
294 saveCalibration(data, name, m_data.getRequestedIov());
295}
296
297void CalibrationAlgorithm::saveCalibration(TClonesArray* data, const string& name)
298{
299 saveCalibration(data, name, m_data.getRequestedIov());
300}
301
303{
304 if (getPayloads().empty())
305 return false;
306 list<Database::DBImportQuery> payloads = getPayloads();
307 B2INFO("Committing " << payloads.size() << " payloads to database.");
308 return Database::Instance().storeData(payloads);
309}
310
311// cppcheck-suppress functionStatic
312bool CalibrationAlgorithm::commit(list<Database::DBImportQuery> payloads)
313{
314 if (payloads.empty())
315 return false;
316 return Database::Instance().storeData(payloads);
317}
318
320{
321 RunRange runRange = getRunRangeFromAllData();
322 set<ExpRun> expRunSet = runRange.getExpRunSet();
323 return vector<ExpRun>(expRunSet.begin(), expRunSet.end());
324}
325
330
332{
333 m_runsToInputFiles.clear();
334 // Save TDirectory to change back at the end
335 TDirectory* dir = gDirectory;
336 RunRange* runRange;
337 // Construct the TDirectory name where we expect our objects to be
338 string runRangeObjName(getPrefix() + "/" + RUN_RANGE_OBJ_NAME);
339 for (const auto& fileName : m_inputFileNames) {
340 //Open TFile to get the objects
341 unique_ptr<TFile> f;
342 f.reset(TFile::Open(fileName.c_str(), "READ"));
343 runRange = dynamic_cast<RunRange*>(f->Get(runRangeObjName.c_str()));
344 if (runRange) {
345 // Insert or extend the run -> file mapping for this ExpRun
346 auto expRuns = runRange->getExpRunSet();
347 for (const auto& expRun : expRuns) {
348 auto runFiles = m_runsToInputFiles.find(expRun);
349 if (runFiles != m_runsToInputFiles.end()) {
350 (runFiles->second).push_back(fileName);
351 } else {
352 m_runsToInputFiles.insert(std::make_pair(expRun, std::vector<std::string> {fileName}));
353 }
354 }
355 } else {
356 B2WARNING("Missing a RunRange object for file: " << fileName);
357 }
358 }
359 dir->cd();
360}
361
363{
364 // Save TDirectory to change back at the end
365 TDirectory* dir = gDirectory;
366 RunRange runRange;
367 // Construct the TDirectory name where we expect our objects to be
368 string runRangeObjName(getPrefix() + "/" + RUN_RANGE_OBJ_NAME);
369 for (const auto& fileName : m_inputFileNames) {
370 //Open TFile to get the objects
371 unique_ptr<TFile> f;
372 f.reset(TFile::Open(fileName.c_str(), "READ"));
373 const RunRange* runRangeOther = dynamic_cast<RunRange*>(f->Get(runRangeObjName.c_str()));
374 if (runRangeOther) {
375 runRange.merge(runRangeOther);
376 } else {
377 B2WARNING("Missing a RunRange object for file: " << fileName);
378 }
379 }
380 dir->cd();
381 return runRange;
382}
383
385{
386 // Save TDirectory to change back at the end
387 TDirectory* dir = gDirectory;
388 const RunRange* runRange;
389 string runRangeObjName(getPrefix() + "/" + RUN_RANGE_OBJ_NAME);
390 // We only check the first file
391 string fileName = m_inputFileNames[0];
392 unique_ptr<TFile> f;
393 f.reset(TFile::Open(fileName.c_str(), "READ"));
394 runRange = dynamic_cast<RunRange*>(f->Get(runRangeObjName.c_str()));
395 if (!runRange) {
396 B2FATAL("The input file " << fileName << " does not contain a RunRange object at "
397 << runRangeObjName << ". Please set your input files to exclude it.");
398 return "";
399 }
400 string granularity = runRange->getGranularity();
401 dir->cd();
402 return granularity;
403}
404
405void CalibrationAlgorithm::updateDBObjPtrs(const unsigned int event, const int run, const int experiment)
406{
407 // Construct an EventMetaData object but NOT in the Datastore
408 EventMetaData emd(event, run, experiment);
409 // Explicitly update while avoiding registering a Datastore object
411 // Also update the intra-run objects to the event at the same time (maybe unnecessary...)
413}
414
415// Have to put the explicit template specialization in the enclosing namespace
416namespace Belle2 {
424 template<>
425 shared_ptr<TTree> CalibrationAlgorithm::getObjectPtr<TTree>(const string& name,
426 const vector<ExpRun>& requestedRuns)
427 {
428 // Check if this object already exists
429 RunRange runRangeRequested(requestedRuns);
430 std::shared_ptr<TTree> objOutputPtr = std::dynamic_pointer_cast<TTree>(m_data.getCalibObj(name, runRangeRequested));
431 if (objOutputPtr)
432 return objOutputPtr;
433
434 // If not we best make a new one
435 shared_ptr<TChain> chain = make_shared<TChain>(name.c_str());
436 chain->SetDirectory(0);
437 // Construct the TDirectory names where we expect our objects to be
438 string runRangeObjName(getPrefix() + "/" + RUN_RANGE_OBJ_NAME);
439
440 if (strcmp(getGranularity().c_str(), "run") == 0) {
441 // Loop over our runs requested for the right files
442 for (auto expRunRequested : requestedRuns) {
443 // Find the relevant files for this ExpRun
444 auto searchFiles = m_runsToInputFiles.find(expRunRequested);
445 if (searchFiles == m_runsToInputFiles.end()) {
446 B2WARNING("No input file found with data collected from run "
447 "(" << expRunRequested.first << "," << expRunRequested.second << ")");
448 continue;
449 } else {
450 auto files = searchFiles->second;
451 for (auto fileName : files) {
452 RunRange* runRangeData;
453 //Open TFile to get the objects
454 std::unique_ptr<TFile> f;
455 f.reset(TFile::Open(fileName.c_str(), "READ"));
456 runRangeData = dynamic_cast<RunRange*>(f->Get(runRangeObjName.c_str()));
457 // Check that nothing went wrong in the mapping and that this file definitely contains this run's data
458 auto runSet = runRangeData->getExpRunSet();
459 if (runSet.find(expRunRequested) == runSet.end()) {
460 B2WARNING("Something went wrong with the mapping of ExpRun -> Input Files. "
461 "(" << expRunRequested.first << "," << expRunRequested.second << ") not in " << fileName);
462 }
463 // Get the path/directory of the Exp,Run TDirectory that holds the object(s)
464 std::string objDirName = getFullObjectPath(name, expRunRequested);
465 TDirectory* objDir = f->GetDirectory(objDirName.c_str());
466 if (!objDir) {
467 B2ERROR("Directory for requested object " << name << " not found: " << objDirName);
468 return nullptr;
469 }
470 // Find all the objects inside, there may be more than one
471 for (auto key : * (objDir->GetListOfKeys())) {
472 string keyName = key->GetName();
473 string objectPath = fileName + "/" + objDirName + "/" + keyName;
474 B2DEBUG(29, "Adding TTree " << objectPath);
475 chain->Add(objectPath.c_str());
476 }
477 }
478 }
479 }
480 } else {
481 ExpRun allGranExpRun = getAllGranularityExpRun();
482 string objDirName = getFullObjectPath(name, allGranExpRun);
483 for (const auto& fileName : m_inputFileNames) {
484 string objectPath = fileName + "/" + objDirName + "/" + name + "_1"; // Only one index for this granularity
485 B2DEBUG(29, "Adding TTree " << objectPath);
486 chain->Add(objectPath.c_str());
487 }
488 }
489 if (!chain->GetListOfFiles()->GetEntries()) {
490 B2ERROR("No data found for object " << name);
491 return nullptr;
492 }
493 objOutputPtr = static_pointer_cast<TTree>(chain);
494 // make a TNamed version to input to the map of previous calib objects
495 shared_ptr<TNamed> storedObjPtr = static_pointer_cast<TNamed>(objOutputPtr);
496 m_data.setCalibObj(name, runRangeRequested, storedObjPtr);
497 B2DEBUG(29, "Passing back merged data " << name);
498 return objOutputPtr;
499 }
501}
502
503bool CalibrationAlgorithm::loadInputJson(const std::string& jsonString)
504{
505 try {
506 auto jsonInput = nlohmann::json::parse(jsonString);
507 // Input string has an object (dict) as the top level object?
508 if (jsonInput.is_object()) {
509 m_jsonExecutionInput = jsonInput;
510 return true;
511 } else {
512 B2ERROR("JSON input string isn't an object type i.e. not a '{}' at the top level.");
513 return false;
514 }
515 } catch (nlohmann::json::parse_error&) {
516 B2ERROR("Parsing of JSON input string failed");
517 return false;
518 }
519}
520
521const std::vector<ExpRun> CalibrationAlgorithm::findPayloadBoundaries(std::vector<ExpRun> runs, int iteration)
522{
523 m_boundaries.clear();
524 if (m_inputFileNames.empty()) {
525 B2ERROR("There aren't any input files set. Please use CalibrationAlgorithm::setInputFiles()");
526 return m_boundaries;
527 }
528 // Reset the internal execution data just in case something is hanging around
529 m_data.reset();
530 if (runs.empty()) {
531 // Want to loop over all runs we could possibly know about
532 runs = getRunListFromAllData();
533 }
534 // Let's check that we have some now
535 if (runs.empty()) {
536 B2ERROR("No collected data in input files.");
537 return m_boundaries;
538 }
539 // In order to find run boundaries we must have collected with data granularity == 'run'
540 if (strcmp(getGranularity().c_str(), "all") == 0) {
541 B2ERROR("The data is collected with granularity='all' (exp=-1,run=-1), and we can't use that to find run boundaries.");
542 return m_boundaries;
543 }
544 m_data.setIteration(iteration);
545 // User defined setup function
546 boundaryFindingSetup(runs, iteration);
547 std::vector<ExpRun> runList;
548 // Loop over run list and call derived class "isBoundaryRequired" member function
549 for (auto currentRun : runs) {
550 runList.push_back(currentRun);
551 m_data.setRequestedRuns(runList);
552 // After here, the getObject<...>(...) helpers start to work
553 if (isBoundaryRequired(currentRun)) {
554 m_boundaries.push_back(currentRun);
555 }
556 // Only want run-by-run
557 runList.clear();
558 // Don't want memory hanging around
559 m_data.clearCalibrationData();
560 }
561 m_data.reset();
563 return m_boundaries;
564}
std::shared_ptr< TNamed > getCalibObj(const std::string &name, const RunRange &runRange) const
Get a previously created object in m_mapCalibData if one exists, otherwise return shared_ptr(nullptr)
std::list< Database::DBImportQuery > & getPayloads()
Get constants (in TObjects) for database update from last execution.
std::string getExpRunString(Calibration::ExpRun &expRun) const
Gets the "exp.run" string repr. of (exp,run)
RunRange getRunRangeFromAllData() const
Get the complete RunRange from inspection of collected data.
IntervalOfValidity getIovFromAllData() const
Get the complete IoV from inspection of collected data.
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
static bool checkPyExpRun(PyObject *pyObj)
Checks that a PyObject can be successfully converted to an ExpRun type.
static const Calibration::ExpRun m_allExpRun
allExpRun
static void updateDBObjPtrs(const unsigned int event, const int run, const int experiment)
Updates any DBObjPtrs by calling update(event) for DBStore.
std::vector< Calibration::ExpRun > m_boundaries
When using the boundaries functionality from isBoundaryRequired, this is used to store the boundaries...
const std::string & getPrefix() const
Get the prefix used for getting calibration data.
PyObject * getInputFileNames()
Get the input file names used for this algorithm and pass them out as a Python list of unicode string...
EResult execute(std::vector< Calibration::ExpRun > runs={}, int iteration=0, IntervalOfValidity iov=IntervalOfValidity())
Runs calibration over vector of runs for a given iteration.
std::vector< Calibration::ExpRun > getRunListFromAllData() const
Get the complete list of runs from inspection of collected data.
virtual void boundaryFindingTearDown()
Put your algorithm back into a state ready for normal execution if you need to.
std::string getFullObjectPath(const std::string &name, Calibration::ExpRun expRun) const
constructs the full TDirectory + Key name of an object in a TFile based on its name and exprun
static Calibration::ExpRun getAllGranularityExpRun()
Returns the Exp,Run pair that means 'Everything'. Currently unused.
virtual void boundaryFindingSetup(std::vector< Calibration::ExpRun >, int)
If you need to make some changes to your algorithm class before 'findPayloadBoundaries' is run,...
std::vector< std::string > m_inputFileNames
List of input files to the Algorithm, will initially be user defined but then gets the wildcards expa...
EResult
The result of calibration.
@ c_Undefined
Not yet known (before execution) =4 in Python.
std::string m_granularityOfData
Granularity of input data. This only changes when the input files change so it isn't specific to an e...
nlohmann::json m_jsonExecutionInput
Optional input JSON object used to make decisions about how to execute the algorithm code.
void setInputFileNames(PyObject *inputFileNames)
Set the input file names used for this algorithm from a Python list.
const std::vector< Calibration::ExpRun > findPayloadBoundaries(std::vector< Calibration::ExpRun > runs, int iteration=0)
Used to discover the ExpRun boundaries that you want the Python CAF to execute on....
virtual bool isBoundaryRequired(const Calibration::ExpRun &)
Given the current collector data, make a decision about whether or not this run should be the start o...
std::map< Calibration::ExpRun, std::vector< std::string > > m_runsToInputFiles
Map of Runs to input files. Gets filled when you call getRunRangeFromAllData, gets cleared when setti...
bool loadInputJson(const std::string &jsonString)
Load the m_inputJson variable from a string (useful from Python interface). The return bool indicates...
std::string getGranularityFromData() const
Get the granularity of collected data.
const std::string & getGranularity() const
Get the granularity of collected data.
void fillRunToInputFilesMap()
Fill the mapping of ExpRun -> Files.
bool commit()
Submit constants from last calibration into database.
virtual EResult calibrate()=0
Run algo on data - pure virtual: needs to be implemented.
static Calibration::ExpRun convertPyExpRun(PyObject *pyObj)
Performs the conversion of PyObject to ExpRun.
ExecutionData m_data
Data specific to a SINGLE execution of the algorithm. Gets reset at the beginning of execution.
static std::string objectName(const TClass *t, const std::string &name)
Return the storage name for an object of the given TClass and name.
Definition DataStore.cc:150
Store event, run, and experiment numbers.
A class that describes the interval of experiments/runs for which an object in the database is valid.
Mergeable object holding (unique) set of (exp,run) pairs.
Definition RunRange.h:25
virtual void merge(const RunRange *other)
Implementation of merging - other is added to the set (union)
Definition RunRange.h:52
const std::string & getGranularity() const
Gets the m_granularity.
Definition RunRange.h:110
IntervalOfValidity getIntervalOfValidity()
Make IntervalOfValidity from the set, spanning all runs. Works because sets are sorted by default.
Definition RunRange.h:70
const std::set< Calibration::ExpRun > & getExpRunSet()
Get access to the stored set.
Definition RunRange.h:64
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...
static Database & Instance()
Instance of a singleton Database.
Definition Database.cc:41
static DBStore & Instance()
Instance of a singleton DBStore.
Definition DBStore.cc:26
bool storeData(const std::string &name, TObject *object, const IntervalOfValidity &iov)
Store an object in the database.
Definition Database.cc:140
void updateEvent()
Updates all intra-run dependent objects.
Definition DBStore.cc:140
void update()
Updates all objects that are outside their interval of validity.
Definition DBStore.cc:77
Scalar convertPythonObject(const boost::python::object &pyObject, Scalar)
Convert from Python to given type.
std::vector< std::string > expandWordExpansions(const std::vector< std::string > &filenames)
Performs wildcard expansion using wordexp(), returns matches.
Abstract base class for different kinds of events.
STL namespace.
Struct containing exp number and run number.
Definition Splitter.h:51