| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /// @begin_doc_example{cpp} | ||
| 2 | /// @file iguana_ex_cpp_dataframes.cc | ||
| 3 | /// @brief Example using HIPO data frames with Iguana. Requires ROOT. | ||
| 4 | /// @par Usage | ||
| 5 | /// ```bash | ||
| 6 | /// iguana_ex_cpp_dataframes [HIPO_FILE] [NUM_EVENTS] [INTERACTIVE_MODE] | ||
| 7 | /// | ||
| 8 | /// HIPO_FILE the HIPO file to analyze | ||
| 9 | /// | ||
| 10 | /// NUM_EVENTS the number of events to analyze; | ||
| 11 | /// set to zero to analyze all events | ||
| 12 | /// | ||
| 13 | /// INTERACTIVE_MODE if 'true', plot will be drawn interactively, | ||
| 14 | /// otherwise it will be saved to a PNG file | ||
| 15 | /// (default = false) | ||
| 16 | /// ``` | ||
| 17 | /// @end_doc_example | ||
| 18 | |||
| 19 | #include <hipo4/RHipoDS.hxx> | ||
| 20 | #include <iguana/algorithms/clas12/EventBuilderFilter/Algorithm.h> | ||
| 21 | |||
| 22 | #include <TApplication.h> | ||
| 23 | #include <TCanvas.h> | ||
| 24 | |||
| 25 | /// main function | ||
| 26 | ✗ | int main(int argc, char** argv) | |
| 27 | { | ||
| 28 | |||
| 29 | // parse arguments | ||
| 30 | ✗ | char const* in_file = argc > 1 ? argv[1] : "data.hipo"; | |
| 31 | ✗ | int const num_events = argc > 2 ? std::stoi(argv[2]) : 100; | |
| 32 | ✗ | bool const interactive_mode = argc > 3 ? std::string(argv[3]) == "true" : false; | |
| 33 | |||
| 34 | // iguana algorithms | ||
| 35 | ✗ | iguana::clas12::EventBuilderFilter algo_eventbuilder_filter; | |
| 36 | ✗ | algo_eventbuilder_filter.SetOption<std::vector<int>>("pids", {11, 211, -211}); | |
| 37 | ✗ | algo_eventbuilder_filter.Start(); | |
| 38 | |||
| 39 | // enable interactive mode | ||
| 40 | ✗ | auto app = interactive_mode ? new TApplication("app", &argc, argv) : nullptr; | |
| 41 | |||
| 42 | // enable multi-threading | ||
| 43 | // ROOT::EnableImplicitMT(); | ||
| 44 | |||
| 45 | // open the HIPO file | ||
| 46 | ✗ | auto frame_init = MakeHipoDataFrame(in_file).Range(0, num_events); | |
| 47 | |||
| 48 | // print the column names | ||
| 49 | ✗ | fmt::print("DATAFRAME COLUMNS:\n"); | |
| 50 | ✗ | for(auto const& column_name : frame_init.GetColumnNames()) | |
| 51 | ✗ | fmt::print(" - {}\n", column_name); | |
| 52 | |||
| 53 | // run algorithms | ||
| 54 | // FIXME: we want to be able to apply an Iguana Filter as an RDataFrame Filter to a set of columns; | ||
| 55 | // this example chain filters only `REC::Particle::pid`, whereas ideally we want all of `REC::Particle`'s columns | ||
| 56 | // to be filtered | ||
| 57 | auto frame_filtered = frame_init | ||
| 58 | ✗ | .Define( // define a filter column, type std::deque<bool> (to avoid std::vector<bool>) | |
| 59 | "REC_Particle_EventBuilderFilter", | ||
| 60 | ✗ | [&](std::vector<int> const& pids) { return algo_eventbuilder_filter.Filter(pids); }, | |
| 61 | {"REC_Particle_pid"}) | ||
| 62 | ✗ | .Define( // apply the filtering column to `REC_Particle_pid` | |
| 63 | "REC_Particle_pid_good", | ||
| 64 | ✗ | [](std::vector<int> const& pids, std::deque<bool>& filter) { | |
| 65 | std::vector<int> result; | ||
| 66 | ✗ | for(std::deque<bool>::size_type i = 0; i < filter.size(); i++) { | |
| 67 | ✗ | if(filter.at(i)) | |
| 68 | ✗ | result.push_back(pids.at(i)); | |
| 69 | } | ||
| 70 | ✗ | return result; | |
| 71 | }, | ||
| 72 | ✗ | {"REC_Particle_pid", "REC_Particle_EventBuilderFilter"}); | |
| 73 | |||
| 74 | // draw | ||
| 75 | ✗ | auto hist = frame_filtered.Histo1D({"pid_filter", "PDG", 6000, -3000, 3000}, "REC_Particle_pid_good"); | |
| 76 | |||
| 77 | // write or hold open | ||
| 78 | ✗ | auto canv = new TCanvas("canv", "canv", 1600, 1200); | |
| 79 | ✗ | canv->SetGrid(1, 1); | |
| 80 | ✗ | hist->Draw(); | |
| 81 | ✗ | if(interactive_mode) { | |
| 82 | ✗ | fmt::print("\n\nShowing plots interactively;\npress ^C to exit.\n\n"); | |
| 83 | ✗ | app->Run(); | |
| 84 | } | ||
| 85 | else { | ||
| 86 | ✗ | canv->SaveAs("out-iguana-dataframe-example.png"); | |
| 87 | } | ||
| 88 | |||
| 89 | return 0; | ||
| 90 | ✗ | } | |
| 91 |