LDMX Software
SimpleCSVTableProvider.cxx
1#include "Conditions/SimpleCSVTableProvider.h"
2
3#include "Conditions/GeneralCSVLoader.h"
4#include "Conditions/SimpleTableStreamers.h"
5#include "Conditions/URLStreamer.h"
6
8
9namespace conditions {
10
11SimpleCSVTableProvider::~SimpleCSVTableProvider() {}
12
13SimpleCSVTableProvider::SimpleCSVTableProvider(
14 const std::string& name, const std::string& tagname,
15 const framework::config::Parameters& parameters,
16 framework::Process& process)
17 : framework::ConditionsObjectProvider(name, tagname, parameters, process) {
18 columns_ = parameters.get<std::vector<std::string>>("columns");
19 std::string dtype = parameters.get<std::string>("dataType");
20 if (dtype == "int" || dtype == "integer")
21 object_type_ = SimpleCSVTableProvider::OBJ_int;
22 if (dtype == "double" || dtype == "float")
23 object_type_ = SimpleCSVTableProvider::OBJ_double;
24
25 conditions_base_url_ = parameters.get<std::string>("conditions_baseURL");
26
27 if (parameters.exists("entries")) {
28 std::vector<framework::config::Parameters> plist =
29 parameters.get<std::vector<framework::config::Parameters>>("entries");
30 if (!plist.empty()) entriesFromPython(plist);
31 }
32
33 entries_url_ = parameters.get<std::string>("entriesURL");
34 if (!entries_url_.empty()) entriesFromCSV();
35}
36
37void SimpleCSVTableProvider::entriesFromPython(
38 std::vector<framework::config::Parameters>& plist) {
39 for (auto aprov : plist) {
40 SimpleCSVTableProvider::Entry item;
41 int first_run = aprov.get<int>("firstRun", -1);
42 int last_run = aprov.get<int>("lastRun", -1);
43 std::string rtype = aprov.get<std::string>("runType", "any");
44 bool is_mc = (rtype == "any" || rtype == "MC");
45 bool is_data = (rtype == "any" || rtype == "data");
46 item.iov_ = framework::ConditionsIOV(first_run, last_run, is_data, is_mc);
47 item.url_ = aprov.get<std::string>("URL");
48 if (object_type_ == OBJ_int && aprov.exists("values")) {
49 item.ivalues_ = aprov.get<std::vector<int>>("values");
50 if (item.ivalues_.size() != columns_.size()) {
51 EXCEPTION_RAISE("ConditionsException",
52 "Mismatch in values vector (" +
53 std::to_string(item.ivalues_.size()) +
54 ") and columns vector (" +
55 std::to_string(columns_.size()) + ") in " +
56 getConditionObjectName());
57 }
58 }
59 if (object_type_ == OBJ_double && aprov.exists("values")) {
60 item.dvalues_ = aprov.get<std::vector<double>>("values");
61 if (item.dvalues_.size() != columns_.size()) {
62 EXCEPTION_RAISE("ConditionsException",
63 "Mismatch in values vector (" +
64 std::to_string(item.dvalues_.size()) +
65 ") and columns vector (" +
66 std::to_string(columns_.size()) + ") in " +
67 getConditionObjectName());
68 }
69 }
70 // here we check for overlaps
71
72 for (auto tabledef : entries_) {
73 if (item.iov_.overlaps(tabledef.iov_)) {
74 std::stringstream err;
75 err << "Table '" << getConditionObjectName()
76 << "' has entries with overlapping providers " << tabledef.url_
77 << " and " << item.url_;
78 EXCEPTION_RAISE("ConditionsException", err.str());
79 }
80 }
81 // add to the list
82 entries_.push_back(item);
83 }
84}
85
86void SimpleCSVTableProvider::entriesFromCSV() {
87 std::string csvurl = expandEnv(entries_url_);
88 std::unique_ptr<std::istream> pstr = urlstream(csvurl);
89
90 StreamCSVLoader loader(*(pstr.get()));
91
92 if (!loader.nextRow()) return; // need to advance to gather column headers
93
94 // check that we have the expected columns
95 const char* column_names[] = {"FIRST_RUN", "LAST_RUN", "RUNTYPE", "URL", 0};
96 std::vector<std::string> cnames = loader.columnNames();
97 for (int i = 0; column_names[i] != 0; i++) {
98 bool found = false;
99 for (auto name : cnames) {
100 if (!strcasecmp(name.c_str(), column_names[i])) found = true;
101 }
102 if (!found) {
103 EXCEPTION_RAISE("CSVNoSuchColumn", "No such column '" +
104 std::string(column_names[i]) +
105 "' reading index CSV");
106 }
107 }
108 // ok, we're good on that...
109 do {
110 bool valid_for_data = strcasecmp("MC", loader.get("RUNTYPE").c_str());
111 bool valid_for_mc = strcasecmp("DATA", loader.get("RUNTYPE").c_str());
112 int first_run = loader.getInteger("FIRST_RUN");
113 int last_run = loader.getInteger("LAST_RUN");
114 Entry e;
115 e.iov_ = framework::ConditionsIOV(first_run, last_run, valid_for_data,
116 valid_for_mc);
117 e.url_ = loader.get("URL");
118 // std::cout << valid_for_data << " " << valid_for_mc << " " << e.url_ <<
119 // std::endl;
120 entries_.push_back(e);
121 } while (loader.nextRow());
122}
123
124std::string SimpleCSVTableProvider::expandEnv(const std::string& s) const {
125 std::string retval;
126 std::string::size_type j = 0;
127 for (std::string::size_type i = s.find("${", j); i < s.size();
128 i = s.find("${", j)) {
129 if (i != j) retval.append(s, j, i - j); // append
130 j = s.find("}", i); // look for the end of request
131 std::string key = std::string(s, i + 2, j - i - 2);
132 if (key == "LDMX_CONDITION_TAG")
133 retval += getTagName();
134 else if (key == "LDMX_CONDITION_BASEURL")
135 retval += conditions_base_url_;
136 else {
137 const char* cenv = getenv(key.c_str());
138 if (cenv != 0) {
139 retval += cenv;
140 } else {
141 // ERROR!
142 }
143 }
144 j++;
145 }
146 if (j < s.size()) retval.append(s, j);
147 // prepend base URL if no URL provided
148 if (retval.find("://") == std::string::npos) {
149 retval = conditions_base_url_ + retval;
150 }
151 // std::cout << s << "=>" << retval << std::endl;
152 return retval;
153}
154
155std::pair<const framework::ConditionsObject*, framework::ConditionsIOV>
156SimpleCSVTableProvider::getCondition(const ldmx::EventHeader& context) {
157 for (auto tabledef : entries_) {
158 // std::cout << condition_name << " " << tabledef.object_name_ << " "
159 //<<
160 // tabledef.iov_ << " " << std::endl;
161 if (tabledef.iov_.validForEvent(context)) {
162 std::string expurl = expandEnv(tabledef.url_);
163
164 if (expurl == "python:") {
165 // here we just copy values...
166 if (object_type_ == OBJ_int) {
167 IntegerTableCondition* table =
168 new IntegerTableCondition(getConditionObjectName(), columns_);
169 table->setIdMask(0); // all ids are the same...
170 table->add(0, tabledef.ivalues_);
171 return std::pair<const framework::ConditionsObject*,
172 framework::ConditionsIOV>(table, tabledef.iov_);
173 } else if (object_type_ == OBJ_double) {
175 new conditions::DoubleTableCondition(getConditionObjectName(),
176 columns_);
177 table->setIdMask(0); // all ids are the same...
178 table->add(0, tabledef.dvalues_);
179 return std::pair<const framework::ConditionsObject*,
180 framework::ConditionsIOV>(table, tabledef.iov_);
181 }
182 } else {
183 std::unique_ptr<std::istream> stream = urlstream(expurl);
184
185 if (object_type_ == OBJ_int) {
186 IntegerTableCondition* table =
187 new IntegerTableCondition(getConditionObjectName(), columns_);
189 *(stream.get()));
190 return std::pair<const framework::ConditionsObject*,
191 framework::ConditionsIOV>(table, tabledef.iov_);
192 } else if (object_type_ == OBJ_double) {
194 new conditions::DoubleTableCondition(getConditionObjectName(),
195 columns_);
197 *(stream.get()));
198 return std::pair<const framework::ConditionsObject*,
199 framework::ConditionsIOV>(table, tabledef.iov_);
200 }
201 }
202 }
203 }
204 return std::pair<const framework::ConditionsObject*,
206}
207
208} // namespace conditions
#define DECLARE_CONDITIONS_PROVIDER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
be configured to load conditions objects from CSV files.
void setIdMask(unsigned int mask)
Set an AND mask to be applied to the id.
void add(unsigned int id, const std::vector< T > &values)
Add an entry to the table.
static void load(IntegerTableCondition &, std::istream &)
Load the table from a stream Columns must be defined by the user.
Class which defines the run/event/type range for which a given condition is valid,...
Base class for all conditions objects, very simple.
Class which represents the process under execution.
Definition Process.h:36
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:29
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:78
bool exists(const std::string &name) const
Check to see if a parameter exists.
Definition Parameters.h:63
Provides header information an event such as event number and timestamp.
Definition EventHeader.h:44
All classes in the ldmx-sw project use this namespace.