hpstr
The Heavy Photon Search Toolkit for Reconstruction (hpstr) provides an interface to physics data from the HPS experiment saved in the LCIO format and converts it into an ROOT based format.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ConfigurePython.cxx
Go to the documentation of this file.
1
8#include "ConfigurePython.h"
9
10static std::string stringMember(PyObject* owner, const std::string& name) {
11
12 std::string retval;
13 PyObject* temp = PyObject_GetAttrString(owner, name.c_str());
14 if (temp != 0) {
15#if PY_MAJOR_VERSION >= 3
16 PyObject* pyStr = PyUnicode_AsEncodedString(temp, "utf-8","Error ~");
17 retval = PyBytes_AS_STRING(pyStr);
18 Py_XDECREF(pyStr);
19#else
20 retval = PyString_AsString(temp);
21#endif
22 Py_DECREF(temp);
23 }
24 return retval;
25}
26
27
28static long intMember(PyObject* owner, const std::string& name) {
29
30 long retval;
31 PyObject* temp = PyObject_GetAttrString(owner, name.c_str());
32 if (temp != 0) {
33 retval = PyLong_AsLong(temp);
34 Py_DECREF(temp);
35 }
36 return retval;
37}
38
39
40ConfigurePython::ConfigurePython(const std::string& python_script, char* args[], int nargs) {
41
42 std::string path(".");
43 std::string cmd = python_script;
44
45 // if a path was specified, extract it and the command
46 if (python_script.rfind("/") != std::string::npos) {
47 path = python_script.substr(0, python_script.rfind("/"));
48 cmd = python_script.substr(python_script.rfind("/") + 1);
49 }
50 cmd = cmd.substr(0, cmd.find(".py"));
51
52 // Initialize the python interpreter.
53 Py_Initialize();
54
55 // Set the command line arguments passed to the python script to be
56 // executed. Note that the first parameter in the list or arguments
57 // should refer to the script to be executed.
58#if PY_MAJOR_VERSION >= 3
59 wchar_t** targs = new wchar_t*[nargs + 1];
60
61#if PY_MINOR_VERSION >=5 // Python 3.4 is missing the Py_DecodeLocale() method.
62 targs[0] = Py_DecodeLocale(python_script.c_str(),NULL);
63 for (int i = 0; i < nargs; i++)
64 targs[i + 1] = Py_DecodeLocale(args[i],NULL);
65#else // Code for Python 3.4, where Py_DecodeLocale is missing.
66 PyObject *tmpstr = PyUnicode_FromString(python_script.c_str());
67 targs[0] = PyUnicode_AsWideCharString(tmpstr,NULL);
68 Py_DECREF(tmpstr);
69 for (int i = 0; i < nargs; i++){
70 tmpstr = PyUnicode_FromString(args[i]);
71 targs[i + 1] = PyUnicode_AsWideCharString(tmpstr,NULL);
72 Py_DECREF(tmpstr);
73 }
74
75
76#endif
77 PySys_SetArgvEx(nargs+1, targs,1);
78 for(int i=0;i<nargs+1; i++) PyMem_RawFree(targs[i]);
79 delete[] targs;
80#else
81 char** targs = new char*[nargs + 1];
82 targs[0] = (char*) python_script.c_str();
83 for (int i = 0; i < nargs; i++)
84 targs[i + 1] = args[i];
85
86 PySys_SetArgvEx(nargs+1, targs, 1);
87 delete[] targs;
88#endif
89
90 PyObject* script = nullptr;
91 PyObject* process = nullptr;
92 PyObject* p_main = nullptr;
93 PyObject* py_list = nullptr;
94 PyObject* p_process = nullptr;
95
96 try {
97 // Load the python script.
98 script = PyImport_ImportModule(cmd.c_str());
99
100 // If a reference to the python script couldn't be created, raise
101 // an exception.
102 if (script == 0) {
103 PyErr_Print();
104 throw std::runtime_error("[ ConfigurePython ]: Problem loading python script.");
105 }
106
107 Py_DECREF(script);
108
109 // Load the script that is used create a processor
110 PyObject* pCMod = PyObject_GetAttrString(script, "HpstrConf");
111 if (pCMod == 0) {
112 PyErr_Print();
113 throw std::runtime_error("[ ConfigurePython ]: Problem loading configuration");
114 }
115
116 PyObject* p_process_class = PyObject_GetAttrString(pCMod, "Process");
117 Py_DECREF(pCMod);
118 if (p_process_class == 0) {
119 PyErr_Print();
120 throw std::runtime_error("[ ConfigurePython ]: Problem loading Process class");
121 }
122
123 p_process = PyObject_GetAttrString(p_process_class, "lastProcess");
124 Py_DECREF(p_process_class);
125 if (p_process == 0) {
126 PyErr_Print();
127 throw std::runtime_error("[ ConfigurePython ]: Problem loading Process class");
128 }
129
130 event_limit_ = intMember(p_process, "max_events");
131 run_mode_ = intMember(p_process, "run_mode");
132 skip_events_ = intMember(p_process, "skip_events");
133
134 PyObject* p_sequence = PyObject_GetAttrString(p_process, "sequence");
135 if (!PyList_Check(p_sequence)) {
136 throw std::runtime_error("[ ConfigurePython ]: Sequence is not a python list as expected.");
137 }
138
139 for (Py_ssize_t i = 0; i < PyList_Size(p_sequence); i++) {
140 PyObject* processor = PyList_GetItem(p_sequence, i);
141 ProcessorInfo pi;
142 pi.classname_ = stringMember(processor, "class_name");
143 pi.instancename_ = stringMember(processor, "instance_name");
144 std::cout << pi.classname_ << std::endl;
145
146 PyObject* params = PyObject_GetAttrString(processor, "parameters");
147 if (params != 0 && PyDict_Check(params)) {
148 PyObject *key(0), *value(0);
149 Py_ssize_t pos = 0;
150
151 while (PyDict_Next(params, &pos, &key, &value)) {
152#if PY_MAJOR_VERSION >= 3
153 PyObject* pyStr = PyUnicode_AsEncodedString(key, "utf-8","Error ~");
154 std::string skey = PyBytes_AS_STRING(pyStr);
155
156 if (PyLong_Check(value)) {
157 pi.params_.insert(skey, int(PyLong_AsLong(value)));
158 //printf("Int Key: %s\n",skey.c_str());
159 } else if (PyFloat_Check(value)) {
160 pi.params_.insert(skey, PyFloat_AsDouble(value));
161 //printf("Double Key: %s\n",skey.c_str());
162 } else if (PyUnicode_Check(value)) {
163 PyObject* pyStr = PyUnicode_AsEncodedString(value, "utf-8","Error ~");
164 pi.params_.insert(skey, PyBytes_AS_STRING(pyStr));
165 Py_XDECREF(pyStr);
166 //printf("String Key: %s\n",skey.c_str());
167 } else if (PyList_Check(value)) { // assume everything is same value as first value
168 if (PyList_Size(value) > 0) {
169 PyObject* vec0 = PyList_GetItem(value, 0);
170 if (PyLong_Check(vec0)) {
171 std::vector<int> vals;
172 for (Py_ssize_t j = 0; j < PyList_Size(value); j++)
173 vals.push_back(PyLong_AsLong(PyList_GetItem(value, j)));
174 pi.params_.insert(skey, vals);
175 //printf("VInt Key: %s\n",skey.c_str());
176 } else if (PyFloat_Check(vec0)) {
177 std::vector<double> vals;
178 for (Py_ssize_t j = 0; j < PyList_Size(value); j++)
179 vals.push_back(PyFloat_AsDouble(PyList_GetItem(value, j)));
180 pi.params_.insert(skey, vals);
181 //printf("VDouble Key: %s\n",skey.c_str());
182 } else if (PyUnicode_Check(vec0)) {
183 std::vector<std::string> vals;
184 for (Py_ssize_t j = 0; j < PyList_Size(value); j++){
185 PyObject* pyStr = PyUnicode_AsEncodedString(PyList_GetItem(value, j), "utf-8","Error ~");
186 vals.push_back( PyBytes_AS_STRING(pyStr));
187 Py_XDECREF(pyStr);
188 }
189 pi.params_.insert(skey, vals);
190 //printf("VString Key: %s\n",skey.c_str());
191 }
192 }
193 }
194
195#else
196 std::string skey = PyString_AsString(key);
197 if (PyInt_Check(value)) {
198 pi.params_.insert(skey, int(PyInt_AsLong(value)));
199 //printf("Int Key: %s\n",skey.c_str());
200 } else if (PyFloat_Check(value)) {
201 pi.params_.insert(skey, PyFloat_AsDouble(value));
202 //printf("Double Key: %s\n",skey.c_str());
203 } else if (PyString_Check(value)) {
204 pi.params_.insert(skey, PyString_AsString(value));
205 //printf("String Key: %s\n",skey.c_str());
206 } else if (PyList_Check(value)) { // assume everything is same value as first value
207 if (PyList_Size(value) > 0) {
208 PyObject* vec0 = PyList_GetItem(value, 0);
209 if (PyInt_Check(vec0)) {
210 std::vector<int> vals;
211 for (Py_ssize_t j = 0; j < PyList_Size(value); j++)
212 vals.push_back(PyInt_AsLong(PyList_GetItem(value, j)));
213 pi.params_.insert(skey, vals);
214 //printf("VInt Key: %s\n",skey.c_str());
215 } else if (PyFloat_Check(vec0)) {
216 std::vector<double> vals;
217 for (Py_ssize_t j = 0; j < PyList_Size(value); j++)
218 vals.push_back(PyFloat_AsDouble(PyList_GetItem(value, j)));
219 pi.params_.insert(skey, vals);
220 //printf("VDouble Key: %s\n",skey.c_str());
221 } else if (PyString_Check(vec0)) {
222 std::vector<std::string> vals;
223 for (Py_ssize_t j = 0; j < PyList_Size(value); j++)
224 vals.push_back(PyString_AsString(PyList_GetItem(value, j)));
225 pi.params_.insert(skey, vals);
226 //printf("VString Key: %s\n",skey.c_str());
227 }
228 }
229 }
230#endif
231 }
232 }
233
234 sequence_.push_back(pi);
235 }
236 Py_DECREF(p_sequence);
237
238 py_list = PyObject_GetAttrString(p_process, "input_files");
239 if (!PyList_Check(py_list)) {
240 throw std::runtime_error("[ ConfigurePython ]: Input files is not a python list as expected.");
241 return;
242 }
243 for (Py_ssize_t i = 0; i < PyList_Size(py_list); i++) {
244 PyObject* elem = PyList_GetItem(py_list, i);
245#if PY_MAJOR_VERSION >= 3
246 PyObject* pyStr = PyUnicode_AsEncodedString(elem, "utf-8","Error ~");
247 input_files_.push_back(PyBytes_AS_STRING(pyStr));
248 Py_XDECREF(pyStr);
249#else
250 input_files_.push_back(PyString_AsString(elem));
251#endif
252 }
253
254 Py_DECREF(py_list);
255
256 py_list = PyObject_GetAttrString(p_process, "output_files");
257 if (!PyList_Check(py_list)) {
258 throw std::runtime_error("[ ConfigurePython ]: Output files is not a python list as expected.");
259 return;
260 }
261 for (Py_ssize_t i = 0; i < PyList_Size(py_list); i++) {
262 PyObject* elem = PyList_GetItem(py_list, i);
263#if PY_MAJOR_VERSION >= 3
264 PyObject* pyStr = PyUnicode_AsEncodedString(elem, "utf-8","Error ~");
265 output_files_.push_back(PyBytes_AS_STRING(pyStr));
266 Py_XDECREF(pyStr);
267#else
268 output_files_.push_back(PyString_AsString(elem));
269#endif
270 }
271 Py_DECREF(py_list);
272
273 py_list = PyObject_GetAttrString(p_process, "libraries");
274 if (!PyList_Check(py_list)) {
275 throw std::runtime_error("[ ConfigurePython ]: libraries is not a python list as expected.");
276 return;
277 }
278 for (Py_ssize_t i = 0; i < PyList_Size(py_list); i++) {
279 PyObject* elem = PyList_GetItem(py_list, i);
280#if PY_MAJOR_VERSION >= 3
281 PyObject* pyStr = PyUnicode_AsEncodedString(elem, "utf-8","Error ~");
282 libraries_.push_back(PyBytes_AS_STRING(pyStr));
283 Py_XDECREF(pyStr);
284#else
285 libraries_.push_back(PyString_AsString(elem));
286#endif
287 }
288 Py_DECREF(py_list);
289
290 } catch (std::exception& e) {
291 std::cout << e.what() << std::endl;
292 }
293
294}
295
297 Py_Finalize();
298}
299
301 Process* p = new Process();
302
303 for (auto lib : libraries_) {
305 }
306
307 for (auto proc : sequence_) {
308 Processor* ep = ProcessorFactory::instance().createProcessor(proc.classname_, proc.instancename_, *p);
309 if (ep == 0) {
310 throw std::runtime_error("[ ConfigurePython ]: Unable to create instance of " + proc.instancename_);
311 }
312 ep->configure(proc.params_);
313 p->addToSequence(ep);
314 }
315
316 for (auto file : input_files_) {
317 p->addFileToProcess(file);
318 }
319
320 for (auto file : output_files_) {
321 p->addOutputFileName(file);
322 }
323
324 p->setEventLimit(event_limit_);
325 p->setRunMode(run_mode_);
326 p->setSkipEvents(skip_events_);
327
328 return p;
329}
static long intMember(PyObject *owner, const std::string &name)
static std::string stringMember(PyObject *owner, const std::string &name)
Utility class that reads/executes a python script and creates a Process object based on the input.
ConfigurePython(const std::string &pythonScript, char *args[], int nargs)
Class constructor.
std::vector< std::string > output_files_
std::vector< std::string > libraries_
std::vector< ProcessorInfo > sequence_
Process * makeProcess()
std::vector< std::string > input_files_
void insert(const std::string &name, int value)
Add an integer to the ParameterSet.
void loadLibrary(const std::string &libname)
Load a library.
static ProcessorFactory & instance()
Get the factory instance.
Processor * createProcessor(const std::string &classname, const std::string &module_instance_name, Process &process)
Make an event processor.
Base class for all event processing components.
Definition Processor.h:34
virtual void configure(const ParameterSet &parameters)
Callback for the Processor to configure itself from the given set of parameters.
Definition Processor.h:61
Represents the configuration of an EventProcessor in the job.