-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathlumi.h
More file actions
97 lines (89 loc) · 4.42 KB
/
lumi.h
File metadata and controls
97 lines (89 loc) · 4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#pragma once
#include <set>
#include <map>
#include <boost/json.hpp>
#include "corrections.h"
class LumiFilter : public correction::CorrectionsBase<LumiFilter> {
public:
using RunType = unsigned int;
using LumiType = unsigned int;
using LumiRange = std::pair<LumiType, LumiType>;
using LumiRangeList = std::vector<LumiRange>;
using LumiMap = std::map<RunType, LumiRangeList>;
static boost::json::value ParseFile(const std::string& jsonFile) {
std::ifstream f(jsonFile);
const std::string input((std::istreambuf_iterator<char>(f)), {});
boost::system::error_code ec;
const auto lumiJson = boost::json::parse(input, ec);
if (ec)
throw std::invalid_argument("LumiFilter: Invalid lumi json file = '" + jsonFile +
"'. Error while parsing: " + ec.message());
return lumiJson;
}
template <typename FieldType>
FieldType Parse(const std::string& fieldStr, const std::string& fieldName) {
std::istringstream ss(fieldStr);
FieldType field;
ss >> field;
if (ss.fail())
throw std::invalid_argument("LumiFilter: Invalid " + fieldName + " = '" + fieldStr + "'.");
return field;
}
LumiFilter(const std::string& lumiJsonFile) {
const auto lumiJson = ParseFile(lumiJsonFile);
if (!lumiJson.is_object())
throw std::invalid_argument("LumiFilter: Invalid lumi json file = '" + lumiJsonFile +
"'. Root element is not an object.");
for (const auto& [runStrRaw, lumiList] : lumiJson.as_object()) {
const std::string runStr(runStrRaw.begin(), runStrRaw.end());
const auto run = Parse<RunType>(runStr, "run");
if (!lumiList.is_array())
throw std::invalid_argument("LumiFilter: Invalid lumi json file = '" + lumiJsonFile +
"'. Lumi list for run = " + runStr + " is not an array.");
for (const auto& lumiRangeValue : lumiList.as_array()) {
if (!lumiRangeValue.is_array())
throw std::invalid_argument("LumiFilter: Invalid lumi json file = '" + lumiJsonFile +
"'. Lumi range for run = " + runStr + " is not an array.");
const auto& lumiRangeArray = lumiRangeValue.as_array();
if (lumiRangeArray.size() != 2)
throw std::invalid_argument("LumiFilter: Invalid lumi json file = '" + lumiJsonFile +
"'. Lumi range for run = " + runStr + " has size != 2.");
if (!lumiRangeArray[0].is_int64() || !lumiRangeArray[1].is_int64())
throw std::invalid_argument("LumiFilter: Invalid lumi json file = '" + lumiJsonFile +
"'. Lumi range for run = " + runStr + " has non-integer elements.");
LumiRange lumiRange;
lumiRange.first = lumiRangeArray.at(0).as_int64();
lumiRange.second = lumiRangeArray.at(1).as_int64();
lumiMap_[run].push_back(lumiRange);
}
}
for (auto& [run, lumiRangeList] : lumiMap_) {
if (lumiRangeList.size() > 0) {
std::sort(lumiRangeList.begin(), lumiRangeList.end());
for (size_t n = 0; n < lumiRangeList.size() - 1; ++n) {
if (lumiRangeList[n + 1].first <= lumiRangeList[n].second) {
std::ostringstream os;
os << "LumiFilter: overlaping ranges for run = " << run << ". lumiRange1 = ["
<< lumiRangeList[n].first << ", " << lumiRangeList[n].second << "]. lumiRange2 = ["
<< lumiRangeList[n + 1].first << ", " << lumiRangeList[n + 1].second << "].";
throw std::invalid_argument(os.str());
}
}
}
}
}
bool Pass(RunType run, LumiType luminosityBlock) const {
const auto iter = lumiMap_.find(run);
if (iter == lumiMap_.end())
return false;
for (const LumiRange& range : iter->second) {
if (luminosityBlock < range.first)
return false;
if (luminosityBlock <= range.second)
return true;
}
return false;
}
private:
LumiMap lumiMap_;
};