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
7DECLARE_CONDITIONS_PROVIDER_NS(conditions, SimpleCSVTableProvider);
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.getParameter<std::vector<std::string>>("columns");
19 std::string dtype = parameters.getParameter<std::string>("dataType");
20 if (dtype == "int" || dtype == "integer")
21 objectType_ = SimpleCSVTableProvider::OBJ_int;
22 if (dtype == "double" || dtype == "float")
23 objectType_ = SimpleCSVTableProvider::OBJ_double;
24
25 conditions_baseURL_ =
26 parameters.getParameter<std::string>("conditions_baseURL");
27
28 if (parameters.exists("entries")) {
29 std::vector<framework::config::Parameters> plist =
30 parameters.getParameter<std::vector<framework::config::Parameters>>(
31 "entries");
32 if (!plist.empty()) entriesFromPython(plist);
33 }
34
35 entriesURL_ = parameters.getParameter<std::string>("entriesURL");
36 if (!entriesURL_.empty()) entriesFromCSV();
37}
38
39void SimpleCSVTableProvider::entriesFromPython(
40 std::vector<framework::config::Parameters>& plist) {
41 for (auto aprov : plist) {
42 SimpleCSVTableProvider::Entry item;
43 int firstRun = aprov.getParameter<int>("firstRun", -1);
44 int lastRun = aprov.getParameter<int>("lastRun", -1);
45 std::string rtype = aprov.getParameter<std::string>("runType", "any");
46 bool isMC = (rtype == "any" || rtype == "MC");
47 bool isData = (rtype == "any" || rtype == "data");
48 item.iov_ = framework::ConditionsIOV(firstRun, lastRun, isData, isMC);
49 item.url_ = aprov.getParameter<std::string>("URL");
50 if (objectType_ == OBJ_int && aprov.exists("values")) {
51 item.ivalues_ = aprov.getParameter<std::vector<int>>("values");
52 if (item.ivalues_.size() != columns_.size()) {
53 EXCEPTION_RAISE("ConditionsException",
54 "Mismatch in values vector (" +
55 std::to_string(item.ivalues_.size()) +
56 ") and columns vector (" +
57 std::to_string(columns_.size()) + ") in " +
58 getConditionObjectName());
59 }
60 }
61 if (objectType_ == OBJ_double && aprov.exists("values")) {
62 item.dvalues_ = aprov.getParameter<std::vector<double>>("values");
63 if (item.dvalues_.size() != columns_.size()) {
64 EXCEPTION_RAISE("ConditionsException",
65 "Mismatch in values vector (" +
66 std::to_string(item.dvalues_.size()) +
67 ") and columns vector (" +
68 std::to_string(columns_.size()) + ") in " +
69 getConditionObjectName());
70 }
71 }
72 // here we check for overlaps
73
74 for (auto tabledef : entries_) {
75 if (item.iov_.overlaps(tabledef.iov_)) {
76 std::stringstream err;
77 err << "Table '" << getConditionObjectName()
78 << "' has entries with overlapping providers " << tabledef.url_
79 << " and " << item.url_;
80 EXCEPTION_RAISE("ConditionsException", err.str());
81 }
82 }
83 // add to the list
84 entries_.push_back(item);
85 }
86}
87
88void SimpleCSVTableProvider::entriesFromCSV() {
89 std::string csvurl = expandEnv(entriesURL_);
90 std::unique_ptr<std::istream> pstr = urlstream(csvurl);
91
92 StreamCSVLoader loader(*(pstr.get()));
93
94 if (!loader.nextRow()) return; // need to advance to gather column headers
95
96 // check that we have the expected columns
97 const char* column_names[] = {"FIRST_RUN", "LAST_RUN", "RUNTYPE", "URL", 0};
98 std::vector<std::string> cnames = loader.columnNames();
99 for (int i = 0; column_names[i] != 0; i++) {
100 bool found = false;
101 for (auto name : cnames) {
102 if (!strcasecmp(name.c_str(), column_names[i])) found = true;
103 }
104 if (!found) {
105 EXCEPTION_RAISE("CSVNoSuchColumn", "No such column '" +
106 std::string(column_names[i]) +
107 "' reading index CSV");
108 }
109 }
110 // ok, we're good on that...
111 do {
112 bool valid_for_data = strcasecmp("MC", loader.get("RUNTYPE").c_str());
113 bool valid_for_mc = strcasecmp("DATA", loader.get("RUNTYPE").c_str());
114 int firstRun = loader.getInteger("FIRST_RUN");
115 int lastRun = loader.getInteger("LAST_RUN");
116 Entry e;
117 e.iov_ = framework::ConditionsIOV(firstRun, lastRun, valid_for_data,
118 valid_for_mc);
119 e.url_ = loader.get("URL");
120 // std::cout << valid_for_data << " " << valid_for_mc << " " << e.url_ <<
121 // std::endl;
122 entries_.push_back(e);
123 } while (loader.nextRow());
124}
125
126std::string SimpleCSVTableProvider::expandEnv(const std::string& s) const {
127 std::string retval;
128 std::string::size_type j = 0;
129 for (std::string::size_type i = s.find("${", j); i < s.size();
130 i = s.find("${", j)) {
131 if (i != j) retval.append(s, j, i - j); // append
132 j = s.find("}", i); // look for the end of request
133 std::string key = std::string(s, i + 2, j - i - 2);
134 if (key == "LDMX_CONDITION_TAG")
135 retval += getTagName();
136 else if (key == "LDMX_CONDITION_BASEURL")
137 retval += conditions_baseURL_;
138 else {
139 const char* cenv = getenv(key.c_str());
140 if (cenv != 0) {
141 retval += cenv;
142 } else {
143 // ERROR!
144 }
145 }
146 j++;
147 }
148 if (j < s.size()) retval.append(s, j);
149 // prepend base URL if no URL provided
150 if (retval.find("://") == std::string::npos) {
151 retval = conditions_baseURL_ + retval;
152 }
153 // std::cout << s << "=>" << retval << std::endl;
154 return retval;
155}
156
157std::pair<const framework::ConditionsObject*, framework::ConditionsIOV>
158SimpleCSVTableProvider::getCondition(const ldmx::EventHeader& context) {
159 for (auto tabledef : entries_) {
160 // std::cout << condition_name << " " << tabledef.objectName_ << " " <<
161 // tabledef.iov_ << " " << std::endl;
162 if (tabledef.iov_.validForEvent(context)) {
163 std::string expurl = expandEnv(tabledef.url_);
164
165 if (expurl == "python:") {
166 // here we just copy values...
167 if (objectType_ == OBJ_int) {
168 IntegerTableCondition* table =
169 new IntegerTableCondition(getConditionObjectName(), columns_);
170 table->setIdMask(0); // all ids are the same...
171 table->add(0, tabledef.ivalues_);
172 return std::pair<const framework::ConditionsObject*,
173 framework::ConditionsIOV>(table, tabledef.iov_);
174 } else if (objectType_ == OBJ_double) {
176 new conditions::DoubleTableCondition(getConditionObjectName(),
177 columns_);
178 table->setIdMask(0); // all ids are the same...
179 table->add(0, tabledef.dvalues_);
180 return std::pair<const framework::ConditionsObject*,
181 framework::ConditionsIOV>(table, tabledef.iov_);
182 }
183 } else {
184 std::unique_ptr<std::istream> stream = urlstream(expurl);
185
186 if (objectType_ == OBJ_int) {
187 IntegerTableCondition* table =
188 new IntegerTableCondition(getConditionObjectName(), columns_);
190 *(stream.get()));
191 return std::pair<const framework::ConditionsObject*,
192 framework::ConditionsIOV>(table, tabledef.iov_);
193 } else if (objectType_ == OBJ_double) {
195 new conditions::DoubleTableCondition(getConditionObjectName(),
196 columns_);
198 *(stream.get()));
199 return std::pair<const framework::ConditionsObject*,
200 framework::ConditionsIOV>(table, tabledef.iov_);
201 }
202 }
203 }
204 }
205 return std::pair<const framework::ConditionsObject*,
207}
208
209} // namespace conditions
#define DECLARE_CONDITIONS_PROVIDER_NS(NS, 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:27
T getParameter(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:89
bool exists(const std::string &name) const
Check to see if a parameter exists.
Definition Parameters.h:71
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.
Definition PerfDict.cxx:45