File indexing completed on 2025-01-30 10:30:04
0001
0002 #ifndef _JEVEVENTPROCESSOR_PY_H_
0003 #define _JEVEVENTPROCESSOR_PY_H_
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include <JANA/JVersion.h>
0024
0025 #include <mutex>
0026 #include <iostream>
0027 using std::cout;
0028 using std::endl;
0029
0030 #include <pybind11/pybind11.h>
0031 namespace py = pybind11;
0032
0033
0034 #if JANA2_HAVE_ROOT
0035 #include <TObject.h>
0036 #include <TClass.h>
0037 #include <TDataMember.h>
0038 #include <TMethodCall.h>
0039 #include <TList.h>
0040 #endif
0041
0042 #include <JANA/JEventProcessor.h>
0043 #include <JANA/JEvent.h>
0044 #include <JANA/Utils/JStringification.h>
0045
0046 std::mutex pymutex;
0047 extern bool PY_INITIALIZED;
0048
0049
0050
0051 class JEventProcessorPY {
0052
0053 public:
0054
0055
0056
0057 JEventProcessorPY(py::object &py_obj):pyobj(py_obj),jstringification(new JStringification){
0058
0059 cout << "JEventProcessorPY constructor called with py:object : " << this << endl;
0060
0061
0062
0063 auto name_obj = py_obj.get_type().attr("__name__");
0064 class_name = py::cast<std::string>(name_obj);
0065
0066 try { pymInit = pyobj.attr("Init" ); has_pymInit = true; }catch(...){}
0067 try { pymProcess = pyobj.attr("Process"); has_pymProcess = true; }catch(...){}
0068 try { pymFinish = pyobj.attr("Finish" ); has_pymFinish = true; }catch(...){}
0069
0070 }
0071
0072
0073
0074 ~JEventProcessorPY() {
0075 cout << "JEventProcessorPY destructor called : " << this << endl;
0076 }
0077
0078
0079
0080
0081
0082
0083
0084
0085 void SetJApplication(JApplication *japp) {
0086 mApplication = japp;
0087 }
0088
0089
0090
0091 void Init(void){
0092
0093 if( has_pymInit && PY_INITIALIZED ) {
0094 lock_guard<mutex> lck(pymutex);
0095 pymInit();
0096 }
0097
0098 }
0099
0100
0101
0102 void Process(const std::shared_ptr<const JEvent>& aEvent){
0103
0104
0105
0106
0107
0108
0109
0110
0111 for( auto p : prefetch_factories ){
0112
0113 auto fac = aEvent->GetFactory( p.first, p.second);
0114 if( fac == nullptr ){
0115 LOG_ERROR(default_cout_logger) << "Unable to find factory specified for prefetching: factory=" << p.first << " tag=" << p.second << LOG_END;
0116 }else {
0117 auto v = fac->GetAs<JObject>();
0118 #if JANA2_HAVE_ROOT
0119 if( v.empty() )fac->GetAs<TObject>();
0120 #endif
0121
0122 _DBG_<<"Prefetching from factory: " << p.first <<":" << p.second << " - " << v.size() << " objects" <<std::endl;
0123 }
0124 }
0125
0126 if( has_pymProcess && PY_INITIALIZED ) {
0127
0128
0129
0130
0131
0132
0133 lock_guard<mutex> lck(pymutex);
0134
0135
0136
0137
0138
0139
0140 std::shared_ptr<int> mEvent_free(nullptr, [=](int *){ mEvent = nullptr;});
0141 mEvent = aEvent;
0142
0143 pymProcess();
0144 }
0145 }
0146
0147
0148
0149 void Finish(void){
0150
0151 if( has_pymFinish && PY_INITIALIZED ) {
0152 lock_guard<mutex> lck(pymutex);
0153 pymFinish();
0154 }
0155
0156 }
0157
0158
0159
0160 void Prefetch(py::object &fac_name, py::object tag = py::none()){
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183 if( py::isinstance<py::dict>(fac_name) ){
0184
0185 for(auto p : fac_name.cast<py::dict>()){
0186 auto &fac_obj = p.first;
0187 auto &tag_obj = p.second;
0188 std::string fac_name_str = py::str(fac_obj);
0189 std::string tag_str = tag_obj.is(py::none()) ? "":py::str(tag_obj);
0190 prefetch_factories[fac_name_str] = tag_str;
0191 }
0192 }else if( py::isinstance<py::list>(fac_name) ){
0193
0194 for(auto &fac_obj : fac_name.cast<py::list>()){
0195 std::string fac_name_str = py::str(fac_obj);
0196 prefetch_factories[fac_name_str] = "";
0197 }
0198 }else if( py::isinstance<py::str>(fac_name) ){
0199
0200 std::string fac_name_str = py::str(fac_name);
0201 std::string tag_str = tag.is(py::none()) ? "":py::str(tag);
0202 prefetch_factories[fac_name_str] = tag_str;
0203 }else{
0204 LOG_ERROR(default_cout_logger) << "Unknown type passed to Prefetch: " << std::string(py::str(fac_name)) << LOG_END;
0205 }
0206 }
0207
0208
0209
0210 py::object Get(py::object &fac_name, py::object tag = py::none()) {
0211 std::string fac_name_str = py::str(fac_name);
0212 std::string tag_str = tag.is(py::none()) ? "":py::str(tag);
0213
0214 std::vector<std::string> json_vec;
0215 jstringification->GetObjectSummariesAsJSON(json_vec, mEvent, fac_name_str, tag_str);
0216
0217 py::list list;
0218 for(auto obj_json : json_vec){
0219
0220 try {
0221 auto json_loads = pymodule_json->attr("loads" );
0222 auto dict = json_loads( py::str(obj_json) );
0223 list.append( dict );
0224 }catch(...){
0225 LOG_ERROR(default_cout_logger) << "Python json loads function not available!" << LOG_END;
0226 }
0227 }
0228
0229 return list;
0230 }
0231
0232
0233 py::module_ *pymodule = nullptr;
0234 py::module_ *pymodule_json = nullptr;
0235 std::string class_name = "JEventProcssorPY";
0236 py::object &pyobj;
0237 py::object pymInit;
0238 py::object pymProcess;
0239 py::object pymFinish;
0240 bool has_pymInit = false;
0241 bool has_pymProcess = false;
0242 bool has_pymFinish = false;
0243
0244 JApplication *mApplication = nullptr;
0245 std::shared_ptr<const JEvent> mEvent;
0246 std::map<std::string, std::string> prefetch_factories;
0247 std::shared_ptr<const JStringification> jstringification;
0248 };
0249
0250 class JEventProcessorPYTrampoline: public JEventProcessor {
0251
0252 public:
0253 JEventProcessorPYTrampoline(JApplication *japp, JEventProcessorPY *jevent_proc):JEventProcessor(japp),jevent_proc_py(jevent_proc){
0254 SetTypeName(jevent_proc->class_name);
0255 jevent_proc_py->SetJApplication(japp);
0256 }
0257
0258 void Init(void){ jevent_proc_py->Init(); }
0259 void Process(const std::shared_ptr<const JEvent>& aEvent){ jevent_proc_py->Process(aEvent); }
0260 void Finish(void){ jevent_proc_py->Finish(); }
0261
0262 private:
0263 JEventProcessorPY *jevent_proc_py = nullptr;
0264 };
0265 #endif