Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:18

0001 
0002 // Copyright 2020, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 
0006 #include <JANA/JEventProcessor.h>
0007 #include <JANA/JObject.h>
0008 
0009 #include <vector>
0010 #include <fstream>
0011 
0012 class CsvWriter : public JEventProcessor {
0013 private:
0014 
0015     // Define the parameters that our processor is going to request
0016 
0017     Parameter<std::vector<std::string>> m_collection_names {this, "csv:collection_names", {}, 
0018         "Comma-separated list of collection names (Type:Tag) to write to CSV"};
0019 
0020     Parameter<std::string> m_dest_path{this, "csv:dest_file", "./output.csv", 
0021         "Location where CSV files get written"};
0022 
0023     // Other internal member variables that our EventProcessor needs
0024 
0025     std::vector<std::pair<std::string, std::string>> m_collection_types_and_tags;
0026 
0027     std::fstream m_dest_file;
0028 
0029 public:
0030 
0031     CsvWriter() {
0032         SetTypeName(NAME_OF_THIS);
0033         SetCallbackStyle(CallbackStyle::ExpertMode);
0034     };
0035 
0036     void Init() override {
0037 
0038         m_dest_file.open(*m_dest_path, std::fstream::out);
0039 
0040         // For historical reasons, our JEvent interface requires types and tags to be separated
0041         // for non-Podio types. Ideally we could deprecate this in favor of a unified concept of
0042         // collection name that includes both type and tag information. However this takes some finesse.
0043         // So for now, we do the separation here in order to minimize runtime costs.
0044         for (auto collection_name : *m_collection_names) {
0045             auto pos = collection_name.find(":");
0046             std::string type_name = collection_name.substr(0, pos);
0047             std::string tag = (pos==std::string::npos ? "":collection_name.substr(pos+1));
0048             // Note that we do this exact same thing in JControlEventProcessor.cc:158. This should be refactored in both
0049             // places once the JStorage mechanism is fully implemented and merged.
0050 
0051             m_collection_types_and_tags.push_back({type_name, tag});
0052             LOG_INFO(GetLogger()) << "Requesting collection with type=" << type_name << ", tag=" << tag << LOG_END;
0053         }
0054     }
0055 
0056     void ProcessParallel(const JEvent& event) override {
0057 
0058         // In parallel, trigger construction of the collections we need.
0059         for (const auto& [type_name, tag] : m_collection_types_and_tags) {
0060             auto fac = event.GetFactorySet()->GetFactory(type_name, tag);
0061             if (fac == nullptr) {
0062                 // If the factory is not found, throw an exception immediately and exit
0063                 throw JException("Factory not found! typename=%s, tag=%s", type_name.c_str(), tag.c_str());
0064             }
0065             fac->Create(event.shared_from_this());
0066         }
0067     }
0068 
0069     void Process(const JEvent& event) override {
0070 
0071         // Sequentially, read the collections we requested earlier, and write them to file.
0072         // Everything inside this callback happens inside a lock; unlike earlier versions
0073         // of JANA, users do not need to manipulate locks at all. To get this behavior,
0074         // set the callback style to "ExpertMode" in the constructor.
0075 
0076         m_dest_file
0077             << "########################################" << std::endl
0078             << "event_number,run_number" << std::endl
0079             << event.GetEventNumber() << "," << event.GetRunNumber() << std::endl;
0080 
0081         for (const auto& [type_name, tag] : m_collection_types_and_tags) {
0082 
0083             // Retrieve the collections we triggered earlier
0084             auto fac = event.GetFactorySet()->GetFactory(type_name, tag);
0085             std::vector<JObject*> objects = fac->GetAs<JObject>();
0086             size_t obj_count = objects.size();
0087             if (obj_count != fac->GetNumObjects()) {
0088                 throw JException("Collection does not appear to contain JObjects!");
0089                 // Right now, there's no foolproof way to distinguish between 
0090                 // JFactory::GetAs() returning empty because the collection is simply empty,
0091                 // or because the objects don't inherit from JObject. This is another thing
0092                 // to address once JStorage is in place.
0093             }
0094 
0095             // Print collection information
0096             m_dest_file
0097                 << "========================================" << std::endl
0098                 << "type_name,tag,object_count" << std::endl
0099                 << type_name << "," << tag << "," << obj_count << std::endl
0100                 << "----------------------------------------" << std::endl;
0101 
0102             JObjectSummary summary;
0103 
0104             // Print header
0105             if (obj_count > 0) {
0106                 objects[0]->Summarize(summary);
0107                 for (auto& field : summary.get_fields()) {
0108                     m_dest_file << field.name << ",";
0109                 }
0110                 m_dest_file << std::endl;
0111             }
0112 
0113             // Print each row in the table
0114             for (auto obj : objects) {
0115                 obj->Summarize(summary);
0116                 for (auto& field : summary.get_fields()) {
0117                     m_dest_file << field.value << ",";
0118                 }
0119                 m_dest_file << std::endl;
0120             }
0121         }
0122     }
0123 
0124     void Finish() override {
0125         //m_dest_file.close();
0126     }
0127 
0128 };
0129 
0130 extern "C" {
0131 void InitPlugin(JApplication* app) {
0132     InitJANAPlugin(app);
0133     app->Add(new CsvWriter);
0134 }
0135 }
0136 
0137 
0138 
0139