3 #include <boost/algorithm/string.hpp>
4 #include <boost/python.hpp>
5 #include <boost/python/list.hpp>
6 #include <boost/filesystem.hpp>
8 #include <calibration/CalibrationAlgorithm.h>
9 #include <framework/logging/Logger.h>
10 #include <framework/core/PyObjConvUtils.h>
11 #include <framework/io/RootIOUtilities.h>
15 using namespace Calibration;
16 namespace fs = boost::filesystem;
18 const ExpRun CalibrationAlgorithm::m_allExpRun = make_pair(-1, -1);
24 if (PySequence_Check(pyObj)) {
25 Py_ssize_t nObj = PySequence_Length(pyObj);
28 B2DEBUG(29,
"ExpRun was a Python sequence which didn't have exactly 2 entries!");
31 PyObject* item1, *item2;
32 item1 = PySequence_GetItem(pyObj, 0);
33 item2 = PySequence_GetItem(pyObj, 1);
35 if ((item1 == NULL) || (item2 == NULL)) {
36 B2DEBUG(29,
"A PyObject pointer was NULL in the sequence");
40 if (PyLong_Check(item1) && PyLong_Check(item2)) {
42 value1 = PyLong_AsLong(item1);
43 value2 = PyLong_AsLong(item2);
44 if (((value1 == -1) || (value2 == -1)) && PyErr_Occurred()) {
45 B2DEBUG(29,
"An error occurred while converting the PyLong to long");
49 B2DEBUG(29,
"One or more of the PyObjects in the ExpRun wasn't a long");
56 B2DEBUG(29,
"ExpRun was not a Python sequence.");
66 PyObject* itemExp, *itemRun;
67 itemExp = PySequence_GetItem(pyObj, 0);
68 itemRun = PySequence_GetItem(pyObj, 1);
69 expRun.first = PyLong_AsLong(itemExp);
71 expRun.second = PyLong_AsLong(itemRun);
78 B2DEBUG(29,
"Running execute() using Python Object as input argument");
81 m_data.setIteration(iteration);
82 vector<ExpRun> vecRuns;
84 if (PySequence_Check(runs)) {
85 boost::python::handle<> handle(boost::python::borrowed(runs));
86 boost::python::list listRuns(handle);
88 int nList = boost::python::len(listRuns);
89 for (
int iList = 0; iList < nList; ++iList) {
90 boost::python::object pyExpRun(listRuns[iList]);
91 if (!checkPyExpRun(pyExpRun.ptr())) {
92 B2ERROR(
"Received Python ExpRuns couldn't be converted to C++");
93 m_data.setResult(c_Failure);
96 vecRuns.push_back(convertPyExpRun(pyExpRun.ptr()));
100 B2ERROR(
"Tried to set the input runs but we didn't receive a Python sequence object (list,tuple).");
101 m_data.setResult(c_Failure);
104 return execute(vecRuns, iteration, iov);
110 if (m_data.getResult() != c_Undefined) {
112 m_data.setIteration(iteration);
115 if (m_inputFileNames.empty()) {
116 B2ERROR(
"There aren't any input files set. Please use CalibrationAlgorithm::setInputFiles()");
117 m_data.setResult(c_Failure);
122 if (!(runs.empty())) {
123 for (
auto expRun : runs) {
124 B2DEBUG(29,
"ExpRun requested = (" << expRun.first <<
", " << expRun.second <<
")");
127 if (strcmp(getGranularity().c_str(),
"all") == 0) {
128 B2ERROR((
"The data is collected with granularity=all (exp=-1,run=-1), but you seem to request calibration for specific runs."
129 " We'll continue but using ALL the input data given instead of the specific runs requested."));
133 runs = getRunListFromAllData();
136 B2ERROR(
"No collected data in input files.");
137 m_data.setResult(c_Failure);
140 for (
auto expRun : runs) {
141 B2DEBUG(29,
"ExpRun requested = (" << expRun.first <<
", " << expRun.second <<
")");
145 m_data.setRequestedRuns(runs);
148 iov =
IntervalOfValidity(runs[0].first, runs[0].second, runs[runs.size() - 1].first, runs[runs.size() - 1].second);
150 m_data.setRequestedIov(iov);
154 m_data.setResult(result);
176 if (PyList_Check(inputFileNames)) {
177 boost::python::handle<> handle(boost::python::borrowed(inputFileNames));
178 boost::python::list listInputFileNames(handle);
182 B2ERROR(
"Tried to set the input files but we didn't receive a Python list.");
191 if (inputFileNames.empty()) {
192 B2WARNING(
"You have called setInputFileNames() with an empty list. Did you mean to do that?");
198 set<string> setInputFileNames;
200 for (
auto path : tmpInputFileNames) {
201 string fullPath = fs::absolute(path).string();
202 if (fs::exists(fullPath)) {
203 setInputFileNames.insert(fs::canonical(fullPath).
string());
205 B2WARNING(
"Couldn't find the file " << path);
209 if (setInputFileNames.empty()) {
210 B2WARNING(
"No valid files specified!");
214 m_runsToInputFiles.clear();
218 TDirectory* dir = gDirectory;
219 for (
const string& fileName : setInputFileNames) {
222 f.reset(TFile::Open(fileName.c_str(),
"READ"));
223 }
catch (logic_error&) {
227 if (!f || !f->IsOpen()) {
228 B2FATAL(
"Couldn't open input file " + fileName);
234 m_inputFileNames = vector<string>(setInputFileNames.begin(), setInputFileNames.end());
235 m_granularityOfData = getGranularityFromData();
240 PyObject* objInputFileNames = PyList_New(m_inputFileNames.size());
241 for (
size_t i = 0; i < m_inputFileNames.size(); ++i) {
242 PyList_SetItem(objInputFileNames, i, Py_BuildValue(
"s", m_inputFileNames[i].c_str()));
244 return objInputFileNames;
250 expRunString += to_string(expRun.first);
252 expRunString += to_string(expRun.second);
258 string dirName = getPrefix() +
"/" + name;
259 string objName = name +
"_" + getExpRunString(expRun);
260 return dirName +
"/" + objName;
265 B2DEBUG(29,
"Saving calibration TObject = '" << name <<
"' to payloads list.");
266 getPayloads().emplace_back(name, data, iov);
271 B2DEBUG(29,
"Saving calibration TClonesArray '" << name <<
"' to payloads list.");
272 getPayloads().emplace_back(name, data, iov);
287 saveCalibration(data, name, m_data.getRequestedIov());
292 saveCalibration(data, name, m_data.getRequestedIov());
297 if (getPayloads().empty())
299 list<Database::DBImportQuery> payloads = getPayloads();
300 B2INFO(
"Committing " << payloads.size() <<
" payloads to database.");
306 if (payloads.empty())
313 RunRange runRange = getRunRangeFromAllData();
315 return vector<ExpRun>(expRunSet.begin(), expRunSet.end());
320 return getRunRangeFromAllData().getIntervalOfValidity();
325 m_runsToInputFiles.clear();
327 TDirectory* dir = gDirectory;
330 string runRangeObjName(getPrefix() +
"/" + RUN_RANGE_OBJ_NAME);
331 for (
const auto& fileName : m_inputFileNames) {
334 f.reset(TFile::Open(fileName.c_str(),
"READ"));
335 runRange =
dynamic_cast<RunRange*
>(f->Get(runRangeObjName.c_str()));
339 for (
const auto& expRun : expRuns) {
340 auto runFiles = m_runsToInputFiles.find(expRun);
341 if (runFiles != m_runsToInputFiles.end()) {
342 (runFiles->second).push_back(fileName);
344 m_runsToInputFiles.insert(std::make_pair(expRun, std::vector<std::string> {fileName}));
348 B2WARNING(
"Missing a RunRange object for file: " << fileName);
357 TDirectory* dir = gDirectory;
361 string runRangeObjName(getPrefix() +
"/" + RUN_RANGE_OBJ_NAME);
362 for (
const auto& fileName : m_inputFileNames) {
365 f.reset(TFile::Open(fileName.c_str(),
"READ"));
366 runRangeOther =
dynamic_cast<RunRange*
>(f->Get(runRangeObjName.c_str()));
368 runRange.
merge(runRangeOther);
370 B2WARNING(
"Missing a RunRange object for file: " << fileName);
380 TDirectory* dir = gDirectory;
382 string runRangeObjName(getPrefix() +
"/" + RUN_RANGE_OBJ_NAME);
384 string fileName = m_inputFileNames[0];
386 f.reset(TFile::Open(fileName.c_str(),
"READ"));
387 runRange =
dynamic_cast<RunRange*
>(f->Get(runRangeObjName.c_str()));
389 B2FATAL(
"The input file " << fileName <<
" does not contain a RunRange object at "
390 << runRangeObjName <<
". Please set your input files to exclude it.");
418 shared_ptr<TTree> CalibrationAlgorithm::getObjectPtr<TTree>(
const string& name,
419 const vector<ExpRun>& requestedRuns)
422 RunRange runRangeRequested(requestedRuns);
423 std::shared_ptr<TTree> objOutputPtr = std::dynamic_pointer_cast<TTree>(m_data.getCalibObj(name, runRangeRequested));
428 shared_ptr<TChain> chain = make_shared<TChain>(name.c_str());
429 chain->SetDirectory(0);
431 string runRangeObjName(getPrefix() +
"/" + RUN_RANGE_OBJ_NAME);
433 if (strcmp(getGranularity().c_str(),
"run") == 0) {
435 for (
auto expRunRequested : requestedRuns) {
437 auto searchFiles = m_runsToInputFiles.find(expRunRequested);
438 if (searchFiles == m_runsToInputFiles.end()) {
439 B2WARNING(
"No input file found with data collected from run "
440 "(" << expRunRequested.first <<
"," << expRunRequested.second <<
")");
443 auto files = searchFiles->second;
444 for (
auto fileName : files) {
447 std::unique_ptr<TFile> f;
448 f.reset(TFile::Open(fileName.c_str(),
"READ"));
449 runRangeData =
dynamic_cast<RunRange*
>(f->Get(runRangeObjName.c_str()));
452 if (runSet.find(expRunRequested) == runSet.end()) {
453 B2WARNING(
"Something went wrong with the mapping of ExpRun -> Input Files. "
454 "(" << expRunRequested.first <<
"," << expRunRequested.second <<
") not in " << fileName);
457 std::string objDirName = getFullObjectPath(name, expRunRequested);
458 TDirectory* objDir = f->GetDirectory(objDirName.c_str());
460 B2ERROR(
"Directory for requested object " << name <<
" not found: " << objDirName);
464 for (
auto key : * (objDir->GetListOfKeys())) {
465 string keyName = key->GetName();
466 string objectPath = fileName +
"/" + objDirName +
"/" + keyName;
467 B2DEBUG(29,
"Adding TTree " << objectPath);
468 chain->Add(objectPath.c_str());
474 ExpRun allGranExpRun = getAllGranularityExpRun();
475 string objDirName = getFullObjectPath(name, allGranExpRun);
476 for (
const auto& fileName : m_inputFileNames) {
477 string objectPath = fileName +
"/" + objDirName +
"/" + name +
"_1";
478 B2DEBUG(29,
"Adding TTree " << objectPath);
479 chain->Add(objectPath.c_str());
482 if (!chain->GetListOfFiles()->GetEntries()) {
483 B2ERROR(
"No data found for object " << name);
486 objOutputPtr = static_pointer_cast<TTree>(chain);
488 shared_ptr<TNamed> storedObjPtr = static_pointer_cast<TNamed>(objOutputPtr);
489 m_data.setCalibObj(name, runRangeRequested, storedObjPtr);
490 B2DEBUG(29,
"Passing back merged data " << name);
499 auto jsonInput = nlohmann::json::parse(jsonString);
501 if (jsonInput.is_object()) {
502 m_jsonExecutionInput = jsonInput;
505 B2ERROR(
"JSON input string isn't an object type i.e. not a '{}' at the top level.");
508 }
catch (nlohmann::json::parse_error&) {
509 B2ERROR(
"Parsing of JSON input string failed");
516 m_boundaries.clear();
517 if (m_inputFileNames.empty()) {
518 B2ERROR(
"There aren't any input files set. Please use CalibrationAlgorithm::setInputFiles()");
525 runs = getRunListFromAllData();
529 B2ERROR(
"No collected data in input files.");
533 if (strcmp(getGranularity().c_str(),
"all") == 0) {
534 B2ERROR(
"The data is collected with granularity='all' (exp=-1,run=-1), and we can't use that to find run boundaries.");
537 m_data.setIteration(iteration);
539 boundaryFindingSetup(runs, iteration);
540 std::vector<ExpRun> runList;
542 for (
auto currentRun : runs) {
543 runList.push_back(currentRun);
544 m_data.setRequestedRuns(runList);
546 if (isBoundaryRequired(currentRun)) {
547 m_boundaries.push_back(currentRun);
552 m_data.clearCalibrationData();
555 boundaryFindingTearDown();