1#include <catch2/catch_approx.hpp>
2#include <catch2/catch_test_macros.hpp>
3#include <catch2/matchers/catch_matchers.hpp>
5#include "Framework/EventFile.h"
8#include "Framework/RunHeader.h"
13#include "TTreeReader.h"
61 header.setIntParameter(
"Should Be Run Number", header.getRunNumber());
66 int i_event =
event.getEventNumber();
72 EXCEPTION_RAISE(
"TestKill",
"Pretending to be killed mid-run.");
75 std::vector<ldmx::CalorimeterHit> calo_hits;
76 for (
int i = 0; i < i_event; i++) {
77 calo_hits.emplace_back();
78 calo_hits.back().setID(i_event * 10 + i);
81 REQUIRE_NOTHROW(event.add(
"TestCollection", calo_hits));
84 max_pe_hit.
setID(i_event);
90 REQUIRE_NOTHROW(event.add(
"TestObject", res));
94 std::vector<int> event_indices = {i_event, i_event};
95 REQUIRE_NOTHROW(event.add(
"EventIndex", event_indices));
97 float test_float = i_event * 0.1;
98 REQUIRE_NOTHROW(event.add(
"EventTenth", test_float));
117 std::string test_collection_passname_;
118 std::string test_object_passname_;
119 std::string veto_test_object_passname_;
120 std::string tenth_event_passname_;
121 std::string event_index_passname_;
128 test_collection_passname_ =
129 ps.
get<std::string>(
"test_collection_passname",
"");
130 test_object_passname_ = ps.
get<std::string>(
"test_object_passname",
"");
131 veto_test_object_passname_ =
132 ps.
get<std::string>(
"veto_test_object_passname",
"");
133 tenth_event_passname_ = ps.
get<std::string>(
"tenth_event_passname",
"");
134 event_index_passname_ = ps.
get<std::string>(
"event_index_passname",
"");
139 test_hist_ =
new TH1F(
"test_hist_",
"Test Histogram", 101, -50, 50);
144 int i_event =
event.getEventNumber();
146 REQUIRE(i_event > 0);
148 const std::vector<ldmx::CalorimeterHit>& calo_hits =
150 test_collection_passname_);
152 CHECK(calo_hits.size() == i_event);
153 for (
unsigned int i = 0; i < calo_hits.size(); i++) {
154 CHECK(calo_hits.at(i).getID() == i_event * 10 + i);
160 veto_test_object_passname_);
164 CHECK(max_pe_hit.getID() == i_event);
165 CHECK(veto_res.
passesVeto() == (i_event % 2 == 0));
167 const float& tenth_event =
168 event.getObject<
float>(
"EventTenth", tenth_event_passname_);
169 CHECK(tenth_event == Approx(i_event * 0.1));
171 const std::vector<int>& i_event_from_bus =
172 event.getCollection<
int>(
"EventIndex", event_index_passname_);
174 CHECK(i_event_from_bus.size() == 2);
175 CHECK(i_event_from_bus.at(0) == i_event);
176 CHECK(i_event_from_bus.at(1) == i_event);
221 bool match(
const std::string& filename)
const override {
223 TFile* f = TFile::Open(filename.c_str());
224 if (!f)
return false;
225 TDirectory* d = (TDirectory*)f->Get(
"TestAnalyzer");
226 if (!d)
return false;
227 TH1F* h = (TH1F*)d->Get(
"test_hist_");
228 if (!h)
return false;
240 std::ostringstream ss;
241 ss <<
"has the histogram 'TestAnalyzer/test_hist_' with the number of "
287 bool existColl =
true,
bool existObj =
true)
302 bool match(
const std::string& filename)
const override {
303 TFile* f = TFile::Open(filename.c_str());
304 if (!f)
return false;
306 TTreeReader events(
"LDMX_Events", f);
308 if (events.GetEntries(
true) !=
entries_) {
314 TTreeReaderValue<ldmx::EventHeader> header(events,
"EventHeader");
318 TTreeReaderValue<std::vector<ldmx::CalorimeterHit>> collection(
319 events, (
"TestCollection_" +
pass_).c_str());
320 while (events.Next()) {
321 if (collection->size() != header->getEventNumber()) {
325 for (
unsigned int i = 0; i < collection->size(); i++)
326 if (collection->at(i).getID() != header->getEventNumber() * 10 + i) {
335 auto t{(TTree*)f->Get(
"LDMX_Events")};
336 if (t and t->GetBranch((
"TestCollection_" +
pass_).c_str())) {
344 TTreeReaderValue<ldmx::HcalVetoResult> object(
345 events, (
"TestObject_" +
pass_).c_str());
346 while (events.Next()) {
347 if (object->getMaxPEHit().getID() != header->getEventNumber()) {
354 auto t{(TTree*)f->Get(
"LDMX_Events")};
355 if (t and t->GetBranch((
"TestObject_" +
pass_).c_str())) {
361 TTreeReader runs(
"LDMX_Run", f);
363 if (runs.GetEntries(
true) !=
runs_) {
368 TTreeReaderValue<ldmx::RunHeader> run_header(runs,
"RunHeader");
370 while (runs.Next()) {
371 if (run_header->getRunNumber() !=
372 run_header->getIntParameter(
"Should Be Run Number")) {
387 std::ostringstream ss;
388 ss <<
"can be opened and has the correct number of entries in the event "
389 "tree and the run tree.";
391 ss <<
" TestCollection_" <<
pass_ <<
" was verified to ";
393 ss <<
" be the correct pattern.";
395 ss <<
" not be in the file.";
397 ss <<
" TestObject_" <<
pass_ <<
" was verified to ";
399 ss <<
" be the correct pattern.";
401 ss <<
" not be in the file.";
416static bool removeFile(
const std::string& filepath) {
417 return remove(filepath.c_str()) == 0;
426static void stripRunHeader(
const std::string& source,
427 const std::string& destination) {
428 TFile src(source.c_str());
429 REQUIRE(not src.IsZombie());
430 auto events{
static_cast<TTree*
>(src.Get(
"LDMX_Events"))};
431 REQUIRE(events !=
nullptr);
433 TFile dst(destination.c_str(),
"RECREATE");
434 REQUIRE(dst.IsOpen());
436 auto copy{events->CloneTree(-1,
"fast")};
437 REQUIRE(copy !=
nullptr);
443 TFile check(destination.c_str());
444 REQUIRE(check.Get(
"LDMX_Run") ==
nullptr);
454static bool isCompleted(
const std::string& path) {
455 TFile f(path.c_str());
456 REQUIRE(not f.IsZombie());
457 REQUIRE(f.Get(
"LDMX_Run") !=
nullptr);
458 TTreeReader runs(
"LDMX_Run", &f);
459 TTreeReaderValue<ldmx::RunHeader> run_header(runs,
"RunHeader");
460 REQUIRE(runs.Next());
461 bool completed{run_header->isCompleted()};
472 p = std::make_unique<Process>(parameters);
474 std::cerr <<
"Config Error [" << e.
name() <<
"] : " << e.
message()
476 std::cerr <<
" at " << e.
module() <<
":" << e.
line() <<
" in "
523TEST_CASE(
"Core Framework Functionality",
"[Framework][functionality]") {
526 process.add(
"compression_setting", 9);
527 process.add(
"max_tries_per_event", 1);
528 process.add(
"log_frequency", -1);
529 process.add(
"term_log_level", 4);
530 process.add(
"file_log_level", 4);
531 process.add<std::string>(
"log_file_name",
"");
532 process.add<std::string>(
"tree_name",
"LDMX_Events");
535 producer_parameters.
add<std::string>(
"class_name",
536 "framework::test::TestProducer");
537 producer_parameters.add<std::string>(
"instance_name",
"TestProducer");
540 analyzer_parameters.
add<std::string>(
"class_name",
541 "framework::test::TestAnalyzer");
542 analyzer_parameters.add<std::string>(
"instance_name",
"TestAnalyzer");
545 std::vector<framework::config::Parameters> sequence;
546 std::vector<std::string> input_files, output_files;
548 SECTION(
"Production Mode") {
551 output_files = {
"test_productionmode_events.root"};
552 process.add<std::string>(
"pass_name",
"test");
553 process.add(
"output_files", output_files);
554 process.add(
"max_events", 3);
555 process.add(
"run", 3);
557 producer_parameters.add(
"create_run_header",
true);
559 sequence = {producer_parameters};
561 SECTION(
"only producers") {
562 process.add(
"sequence", sequence);
563 process.add<std::string>(
"histogram_file",
"");
564 SECTION(
"no drop/keep rules") {
566 REQUIRE(framework::test::runProcess(process));
567 CHECK_THAT(output_files.at(0),
571 SECTION(
"drop TestCollection") {
572 std::vector<std::string> keep = {
"drop .*Collection.*"};
573 process.add(
"keep", keep);
574 REQUIRE(framework::test::runProcess(process));
575 CHECK_THAT(output_files.at(0),
579 SECTION(
"skim for even indexed events") {
580 process.add(
"skim_default_is_keep",
false);
581 std::vector<std::string> rules = {
"TestProducer",
""};
582 process.add(
"skim_rules", rules);
583 REQUIRE(framework::test::runProcess(process));
584 CHECK_THAT(output_files.at(0),
589 SECTION(
"with Analyses") {
590 std::string hist_file_path =
591 "test_productionmode_withanalyses_hists.root";
593 process.add(
"histogram_file", hist_file_path);
595 sequence.push_back(analyzer_parameters);
596 process.add(
"sequence", sequence);
598 SECTION(
"no drop/keep rules") {
599 REQUIRE(framework::test::runProcess(process));
600 CHECK_THAT(output_files.at(0),
604 SECTION(
"drop TestCollection") {
605 std::vector<std::string> keep = {
"drop .*Collection.*"};
606 process.add(
"keep", keep);
607 REQUIRE(framework::test::runProcess(process));
608 CHECK_THAT(output_files.at(0),
612 SECTION(
"skim for even indexed events") {
613 process.add(
"skim_default_is_keep",
false);
614 std::vector<std::string> rules = {
"TestProducer",
""};
615 process.add(
"skim_rules", rules);
616 REQUIRE(framework::test::runProcess(process));
617 CHECK_THAT(output_files.at(0),
621 CHECK_THAT(hist_file_path,
623 CHECK(framework::test::removeFile(hist_file_path));
626 CHECK(framework::test::removeFile(output_files.at(0)));
629 SECTION(
"Need Input Files") {
630 input_files = {
"test_needinputfiles_2_events.root",
631 "test_needinputfiles_3_events.root",
632 "test_needinputfiles_4_events.root"};
634 for (
int run{2};
run < 5;
run++) {
635 auto make_inputs = process;
636 make_inputs.add<std::string>(
"pass_name",
"makeInputs");
637 auto producer = producer_parameters;
638 producer.add(
"create_run_header",
true);
639 make_inputs.add<std::vector<framework::config::Parameters>>(
"sequence",
641 output_files = {input_files.at(run - 2)};
642 make_inputs.add(
"output_files", output_files);
643 make_inputs.add(
"max_events", run);
644 make_inputs.add(
"run", run);
645 REQUIRE(framework::test::runProcess(make_inputs));
646 REQUIRE_THAT(input_files.at(run - 2),
649 process.add<std::string>(
"pass_name",
"test");
651 SECTION(
"Analysis Mode") {
654 sequence = {analyzer_parameters};
655 process.add(
"sequence", sequence);
657 std::string hist_file_path =
"test_analysismode_hists.root";
658 process.add(
"histogram_file", hist_file_path);
660 SECTION(
"one input file") {
661 std::vector<std::string> input_file = {input_files.at(0)};
662 process.add(
"input_files", input_file);
663 REQUIRE(framework::test::runProcess(process));
665 CHECK(framework::test::removeFile(hist_file_path));
668 SECTION(
"multiple input files") {
669 process.add(
"input_files", input_files);
670 REQUIRE(framework::test::runProcess(process));
672 1 + 2 + 1 + 2 + 3 + 1 + 2 + 3 + 4));
673 CHECK(framework::test::removeFile(hist_file_path));
678 SECTION(
"Evolve Mode") {
680 std::vector<std::string> input_file = {input_files.at(0)};
681 process.add(
"input_files", input_file);
683 std::string event_file_path =
"test_evolvemode_events.root";
684 output_files = {event_file_path};
685 process.add(
"output_files", output_files);
687 SECTION(
"drop TestCollection") {
688 std::vector<std::string> keep = {
"drop .*Collection.*"};
689 process.add(
"keep", keep);
690 REQUIRE(framework::test::runProcess(process));
691 CHECK_THAT(event_file_path,
696 SECTION(
"Merge Mode") {
699 process.add(
"input_files", input_files);
701 std::string event_file_path =
"test_mergemode_events.root";
702 output_files = {event_file_path};
703 process.add(
"output_files", output_files);
705 SECTION(
"with analyzers") {
706 sequence = {analyzer_parameters};
708 std::string hist_file_path =
"test_mergemode_withanalyzers_hists.root";
710 process.add(
"sequence", sequence);
711 process.add(
"histogram_file", hist_file_path);
713 SECTION(
"no drop/keep rules") {
714 REQUIRE(framework::test::runProcess(process));
716 "makeInputs", 2 + 3 + 4, 3));
719 SECTION(
"drop TestCollection") {
720 std::vector<std::string> keep = {
"drop .*Collection.*"};
721 process.add(
"keep", keep);
722 REQUIRE(framework::test::runProcess(process));
724 "makeInputs", 2 + 3 + 4, 3,
false));
728 1 + 2 + 1 + 2 + 3 + 1 + 2 + 3 + 4));
729 CHECK(framework::test::removeFile(hist_file_path));
732 SECTION(
"with producers") {
733 producer_parameters.add(
"create_run_header",
false);
734 sequence = {producer_parameters};
736 process.add(
"sequence", sequence);
738 SECTION(
"not listening to storage hints") {
739 REQUIRE(framework::test::runProcess(process));
740 CHECK_THAT(event_file_path,
744 SECTION(
"skim for even indexed events") {
745 process.add(
"skim_default_is_keep",
false);
746 std::vector<std::string> rules = {
"TestProducer",
""};
747 process.add(
"skim_rules", rules);
748 REQUIRE(framework::test::runProcess(process));
749 CHECK_THAT(event_file_path,
754 CHECK(framework::test::removeFile(event_file_path));
772TEST_CASE(
"Missing Run Header",
"[Framework][functionality]") {
774 process.add(
"compression_setting", 9);
775 process.add(
"max_tries_per_event", 1);
776 process.add(
"log_frequency", -1);
777 process.add(
"term_log_level", 4);
778 process.add(
"file_log_level", 4);
779 process.add<std::string>(
"log_file_name",
"");
780 process.add<std::string>(
"tree_name",
"LDMX_Events");
783 producer_parameters.
add<std::string>(
"class_name",
784 "framework::test::TestProducer");
785 producer_parameters.add<std::string>(
"instance_name",
"TestProducer");
788 analyzer_parameters.
add<std::string>(
"class_name",
789 "framework::test::TestAnalyzer");
790 analyzer_parameters.add<std::string>(
"instance_name",
"TestAnalyzer");
792 const std::string healthy_file{
"test_missingrh_healthy_events.root"};
793 const std::string headerless_file{
"test_missingrh_headerless_events.root"};
797 auto make_inputs = process;
798 make_inputs.add<std::string>(
"pass_name",
"makeInputs");
799 auto producer = producer_parameters;
800 producer.add(
"create_run_header",
true);
801 make_inputs.add<std::vector<framework::config::Parameters>>(
"sequence",
803 make_inputs.add(
"output_files", std::vector<std::string>{healthy_file});
804 make_inputs.add<std::string>(
"histogram_file",
"");
805 make_inputs.add(
"max_events", 3);
806 make_inputs.add(
"run", 3);
807 REQUIRE(framework::test::runProcess(make_inputs));
808 REQUIRE_THAT(healthy_file,
811 framework::test::stripRunHeader(healthy_file, headerless_file);
813 process.add<std::string>(
"pass_name",
"test");
814 std::string hist_file_path =
"test_missingrh_hists.root";
815 process.add(
"histogram_file", hist_file_path);
816 process.add<std::vector<framework::config::Parameters>>(
817 "sequence", {analyzer_parameters});
818 process.add(
"input_files", std::vector<std::string>{headerless_file});
820 CHECK_THROWS_AS(framework::test::runProcess(process),
823 CHECK(framework::test::removeFile(hist_file_path));
824 CHECK(framework::test::removeFile(headerless_file));
825 CHECK(framework::test::removeFile(healthy_file));
838TEST_CASE(
"Output Completeness",
"[Framework][functionality]") {
840 process.add(
"compression_setting", 9);
841 process.add(
"max_tries_per_event", 1);
842 process.add(
"log_frequency", -1);
843 process.add(
"term_log_level", 4);
844 process.add(
"file_log_level", 4);
845 process.add<std::string>(
"log_file_name",
"");
846 process.add<std::string>(
"tree_name",
"LDMX_Events");
847 process.add<std::string>(
"pass_name",
"test");
848 process.add<std::string>(
"histogram_file",
"");
849 process.add(
"max_events", 5);
850 process.add(
"run", 3);
853 producer_parameters.
add<std::string>(
"class_name",
854 "framework::test::TestProducer");
855 producer_parameters.
add<std::string>(
"instance_name",
"TestProducer");
856 producer_parameters.
add(
"create_run_header",
true);
858 const std::string output_file{
"test_completeness_events.root"};
859 process.add(
"output_files", std::vector<std::string>{output_file});
861 SECTION(
"a clean close is marked completed") {
862 process.add<std::vector<framework::config::Parameters>>(
863 "sequence", {producer_parameters});
864 REQUIRE(framework::test::runProcess(process));
865 CHECK(framework::test::isCompleted(output_file));
869 SECTION(
"an interrupted run is not") {
871 producer_parameters.
add(
"throw_after", 3);
872 process.add<std::vector<framework::config::Parameters>>(
873 "sequence", {producer_parameters});
874 CHECK_THROWS_AS(framework::test::runProcess(process),
877 CHECK_FALSE(framework::test::isCompleted(output_file));
882 CHECK(framework::test::removeFile(output_file));
896TEST_CASE(
"Incomplete Input",
"[Framework][functionality]") {
898 process.add(
"compression_setting", 9);
899 process.add(
"max_tries_per_event", 1);
900 process.add(
"log_frequency", -1);
901 process.add(
"term_log_level", 4);
902 process.add(
"file_log_level", 4);
903 process.add<std::string>(
"log_file_name",
"");
904 process.add<std::string>(
"tree_name",
"LDMX_Events");
907 producer_parameters.
add<std::string>(
"class_name",
908 "framework::test::TestProducer");
909 producer_parameters.add<std::string>(
"instance_name",
"TestProducer");
910 producer_parameters.add(
"create_run_header",
true);
913 analyzer_parameters.
add<std::string>(
"class_name",
914 "framework::test::TestAnalyzer");
915 analyzer_parameters.
add<std::string>(
"instance_name",
"TestAnalyzer");
917 const std::string complete_file{
"test_incompletein_complete_events.root"};
918 const std::string incomplete_file{
"test_incompletein_incomplete_events.root"};
922 auto make_inputs = process;
923 make_inputs.add<std::string>(
"pass_name",
"makeInputs");
924 make_inputs.add<std::vector<framework::config::Parameters>>(
925 "sequence", {producer_parameters});
926 make_inputs.add(
"output_files", std::vector<std::string>{complete_file});
927 make_inputs.add<std::string>(
"histogram_file",
"");
928 make_inputs.add(
"max_events", 3);
929 make_inputs.add(
"run", 3);
930 REQUIRE(framework::test::runProcess(make_inputs));
931 REQUIRE(framework::test::isCompleted(complete_file));
934 auto make_inputs = process;
935 make_inputs.add<std::string>(
"pass_name",
"makeInputs");
936 auto producer = producer_parameters;
937 producer.add(
"throw_after", 3);
938 make_inputs.add<std::vector<framework::config::Parameters>>(
"sequence",
940 make_inputs.add(
"output_files", std::vector<std::string>{incomplete_file});
941 make_inputs.add<std::string>(
"histogram_file",
"");
942 make_inputs.add(
"max_events", 5);
943 make_inputs.add(
"run", 4);
944 REQUIRE_THROWS_AS(framework::test::runProcess(make_inputs),
946 REQUIRE_FALSE(framework::test::isCompleted(incomplete_file));
949 process.add<std::string>(
"pass_name",
"test");
950 std::string hist_file_path =
"test_incompletein_hists.root";
951 process.add(
"histogram_file", hist_file_path);
952 process.add<std::vector<framework::config::Parameters>>(
953 "sequence", {analyzer_parameters});
955 SECTION(
"an unfinished run is refused") {
956 process.add(
"input_files", std::vector<std::string>{incomplete_file});
957 CHECK_THROWS_AS(framework::test::runProcess(process),
961 SECTION(
"an unfinished run is refused even alongside good files") {
962 process.add(
"input_files",
963 std::vector<std::string>{complete_file, incomplete_file});
964 CHECK_THROWS_AS(framework::test::runProcess(process),
968 SECTION(
"experts can ask for it anyway") {
969 process.add(
"input_files", std::vector<std::string>{incomplete_file});
970 process.add(
"allow_incomplete_input_files",
true);
971 CHECK(framework::test::runProcess(process));
975 SECTION(
"a complete run is let through") {
976 process.add(
"input_files", std::vector<std::string>{complete_file});
977 CHECK(framework::test::runProcess(process));
981 CHECK(framework::test::removeFile(hist_file_path));
982 CHECK(framework::test::removeFile(incomplete_file));
983 CHECK(framework::test::removeFile(complete_file));
Class that represents a reconstructed hit in a calorimeter cell within the detector.
Base classes for all user event processing components to extend.
#define DECLARE_ANALYZER(CLASS)
Macro which allows the framework to construct an analyzer given its name during configuration.
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Class that stores Stores reconstructed hit information from the HCAL.
Class used to encapsulate the results obtained from HcalVetoProcessor.
Class which represents the process under execution.
Base class for a module which does not produce a data product.
Analyzer(const std::string &name, Process &process)
Class constructor.
TDirectory * getHistoDirectory()
Access/create a directory in the histogram file for this event processor to create histograms and ana...
void setStorageHint(framework::StorageControl::Hint hint)
Mark the current event as having the given storage control hint from this module_.
Implements an event buffer system for storing event data.
Class which represents the process under execution.
Base class for a module which produces a data product.
Class encapsulating parameters for configuring a processor.
void add(const std::string &name, const T &value)
Add a parameter to the parameter list.
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Standard base exception class with some useful output information.
const std::string & function() const
Get the function name where the exception occurred.
int line() const
Get the source line number where the exception occurred.
const std::string & message() const
Get the message of the exception.
const std::string & name() const
Get the name of the exception.
const std::string & module() const
Get the source filename where the exception occurred.
int entries_
correct number of entries in the event ttree
bool exist_object_
object should exist in file
int runs_
correct number of runs
std::string pass_
pass name to check the collection and/or object for
bool match(const std::string &filename) const override
Actually do the matching.
IsGoodEventFile(const std::string &pass, const int &entries, const int &runs, bool existColl=true, bool existObj=true)
Constructor.
bool exist_collection_
collection should exist in file
virtual std::string describe() const override
Human-readable statement for any match that is true.
bool match(const std::string &filename) const override
Performs the test for this matcher.
int correct_get_entries_
Correct number of entries.
virtual std::string describe() const override
Describe this matcher in a helpful, human-readable way.
IsGoodhistogramFile(int const &n)
Constructor.
Bare analyzer that looks for objects matching what the TestProducer put in.
void configure(framework::config::Parameters &ps) override
Callback for the EventProcessor to configure itself from the given set of parameters.
void analyze(const framework::Event &event) final override
Process the event and make histograms or summaries.
TH1F * test_hist_
test histogram filled with event indices
void onProcessStart() final override
Callback for the EventProcessor to take any necessary action when the processing of events starts,...
Bare producer that creates a collection and an object and puts them on the event bus.
int events_
number of events we've gotten to
bool create_run_header_
should we create the run header?
void configure(framework::config::Parameters &p) final override
Callback for the EventProcessor to configure itself from the given set of parameters.
int throw_after_
throw after this many events (negative to never throw)
void produce(framework::Event &event) final override
Process the event and put new data products into it.
void beforeNewRun(ldmx::RunHeader &header) final override
Callback for Producers to add parameters to the run header before conditions are initialized.
Represents a reconstructed hit in a calorimeter cell within the detector.
void setID(int id)
Set the detector ID.
Stores reconstructed hit information from the HCAL.
void setVetoResult(const bool &passes_veto=true)
Sets whether the Hcal veto was passed or not.
bool passesVeto() const
Checks if the event passes the Hcal veto.
ldmx::HcalHit getMaxPEHit() const
void setMaxPEHit(const ldmx::HcalHit max_PE_hit)
Set the maximum PE hit.
Parameters run(const std::string &root_object, const std::string &pythonScript, char *args[], int nargs)
run the python script and extract the parameters
All classes in the ldmx-sw project use this namespace.
std::unique_ptr< Process > ProcessHandle
A handle to the current process Used to pass a process from ConfigurePython to fire....