1#include <catch2/catch_approx.hpp>
2#include <catch2/catch_test_macros.hpp>
3#include <catch2/matchers/catch_matchers.hpp>
6#include "Framework/EventFile.h"
9#include "Framework/RunHeader.h"
15#include "TTreeReader.h"
63 header.setIntParameter(
"Should Be Run Number", header.getRunNumber());
68 int i_event =
event.getEventNumber();
74 EXCEPTION_RAISE(
"TestKill",
"Pretending to be killed mid-run.");
77 std::vector<ldmx::CalorimeterHit> calo_hits;
78 for (
int i = 0; i < i_event; i++) {
79 calo_hits.emplace_back();
80 calo_hits.back().setID(i_event * 10 + i);
83 REQUIRE_NOTHROW(event.add(
"TestCollection", calo_hits));
86 max_pe_hit.
setID(i_event);
92 REQUIRE_NOTHROW(event.add(
"TestObject", res));
96 std::vector<int> event_indices = {i_event, i_event};
97 REQUIRE_NOTHROW(event.add(
"EventIndex", event_indices));
99 float test_float = i_event * 0.1;
100 REQUIRE_NOTHROW(event.add(
"EventTenth", test_float));
119 std::string test_collection_passname_;
120 std::string test_object_passname_;
121 std::string veto_test_object_passname_;
122 std::string tenth_event_passname_;
123 std::string event_index_passname_;
130 test_collection_passname_ =
131 ps.
get<std::string>(
"test_collection_passname",
"");
132 test_object_passname_ = ps.
get<std::string>(
"test_object_passname",
"");
133 veto_test_object_passname_ =
134 ps.
get<std::string>(
"veto_test_object_passname",
"");
135 tenth_event_passname_ = ps.
get<std::string>(
"tenth_event_passname",
"");
136 event_index_passname_ = ps.
get<std::string>(
"event_index_passname",
"");
141 test_hist_ =
new TH1F(
"test_hist_",
"Test Histogram", 101, -50, 50);
146 int i_event =
event.getEventNumber();
148 REQUIRE(i_event > 0);
150 const std::vector<ldmx::CalorimeterHit>& calo_hits =
152 test_collection_passname_);
154 CHECK(calo_hits.size() == i_event);
155 for (
unsigned int i = 0; i < calo_hits.size(); i++) {
156 CHECK(calo_hits.at(i).getID() == i_event * 10 + i);
162 veto_test_object_passname_);
166 CHECK(max_pe_hit.getID() == i_event);
167 CHECK(veto_res.
passesVeto() == (i_event % 2 == 0));
169 const float& tenth_event =
170 event.getObject<
float>(
"EventTenth", tenth_event_passname_);
171 CHECK(tenth_event == Approx(i_event * 0.1));
173 const std::vector<int>& i_event_from_bus =
174 event.getCollection<
int>(
"EventIndex", event_index_passname_);
176 CHECK(i_event_from_bus.size() == 2);
177 CHECK(i_event_from_bus.at(0) == i_event);
178 CHECK(i_event_from_bus.at(1) == i_event);
223 bool match(
const std::string& filename)
const override {
225 TFile* f = TFile::Open(filename.c_str());
226 if (!f)
return false;
227 TDirectory* d = (TDirectory*)f->Get(
"TestAnalyzer");
228 if (!d)
return false;
229 TH1F* h = (TH1F*)d->Get(
"test_hist_");
230 if (!h)
return false;
242 std::ostringstream ss;
243 ss <<
"has the histogram 'TestAnalyzer/test_hist_' with the number of "
289 bool existColl =
true,
bool existObj =
true)
304 bool match(
const std::string& filename)
const override {
305 TFile* f = TFile::Open(filename.c_str());
306 if (!f)
return false;
308 TTreeReader events(
"LDMX_Events", f);
310 if (events.GetEntries(
true) !=
entries_) {
316 TTreeReaderValue<ldmx::EventHeader> header(events,
"EventHeader");
320 TTreeReaderValue<std::vector<ldmx::CalorimeterHit>> collection(
321 events, (
"TestCollection_" +
pass_).c_str());
322 while (events.Next()) {
323 if (collection->size() != header->getEventNumber()) {
327 for (
unsigned int i = 0; i < collection->size(); i++)
328 if (collection->at(i).getID() != header->getEventNumber() * 10 + i) {
337 auto t{(TTree*)f->Get(
"LDMX_Events")};
338 if (t and t->GetBranch((
"TestCollection_" +
pass_).c_str())) {
346 TTreeReaderValue<ldmx::HcalVetoResult> object(
347 events, (
"TestObject_" +
pass_).c_str());
348 while (events.Next()) {
349 if (object->getMaxPEHit().getID() != header->getEventNumber()) {
356 auto t{(TTree*)f->Get(
"LDMX_Events")};
357 if (t and t->GetBranch((
"TestObject_" +
pass_).c_str())) {
363 TTreeReader runs(
"LDMX_Run", f);
365 if (runs.GetEntries(
true) !=
runs_) {
370 TTreeReaderValue<ldmx::RunHeader> run_header(runs,
"RunHeader");
372 while (runs.Next()) {
373 if (run_header->getRunNumber() !=
374 run_header->getIntParameter(
"Should Be Run Number")) {
389 std::ostringstream ss;
390 ss <<
"can be opened and has the correct number of entries in the event "
391 "tree and the run tree.";
393 ss <<
" TestCollection_" <<
pass_ <<
" was verified to ";
395 ss <<
" be the correct pattern.";
397 ss <<
" not be in the file.";
399 ss <<
" TestObject_" <<
pass_ <<
" was verified to ";
401 ss <<
" be the correct pattern.";
403 ss <<
" not be in the file.";
418static bool removeFile(
const std::string& filepath) {
419 return remove(filepath.c_str()) == 0;
428static void stripRunHeader(
const std::string& source,
429 const std::string& destination) {
430 TFile src(source.c_str());
431 REQUIRE(not src.IsZombie());
432 auto events{
static_cast<TTree*
>(src.Get(
"LDMX_Events"))};
433 REQUIRE(events !=
nullptr);
435 TFile dst(destination.c_str(),
"RECREATE");
436 REQUIRE(dst.IsOpen());
438 auto copy{events->CloneTree(-1,
"fast")};
439 REQUIRE(copy !=
nullptr);
445 TFile check(destination.c_str());
446 REQUIRE(check.Get(
"LDMX_Run") ==
nullptr);
456static bool isCompleted(
const std::string& path) {
457 TFile f(path.c_str());
458 REQUIRE(not f.IsZombie());
459 REQUIRE(f.Get(
"LDMX_Run") !=
nullptr);
460 TTreeReader runs(
"LDMX_Run", &f);
461 TTreeReaderValue<ldmx::RunHeader> run_header(runs,
"RunHeader");
462 REQUIRE(runs.Next());
463 bool completed{run_header->isCompleted()};
474 p = std::make_unique<Process>(parameters);
476 std::cerr <<
"Config Error [" << e.
name() <<
"] : " << e.
message()
478 std::cerr <<
" at " << e.
module() <<
":" << e.
line() <<
" in "
525TEST_CASE(
"Core Framework Functionality",
"[Framework][functionality]") {
528 process.add(
"compression_setting", 9);
529 process.add(
"max_tries_per_event", 1);
530 process.add(
"log_frequency", -1);
531 process.add(
"term_log_level", 4);
532 process.add(
"file_log_level", 4);
533 process.add<std::string>(
"log_file_name",
"");
534 process.add<std::string>(
"tree_name",
"LDMX_Events");
537 producer_parameters.
add<std::string>(
"class_name",
538 "framework::test::TestProducer");
539 producer_parameters.add<std::string>(
"instance_name",
"TestProducer");
542 analyzer_parameters.
add<std::string>(
"class_name",
543 "framework::test::TestAnalyzer");
544 analyzer_parameters.add<std::string>(
"instance_name",
"TestAnalyzer");
547 std::vector<framework::config::Parameters> sequence;
548 std::vector<std::string> input_files, output_files;
550 SECTION(
"Production Mode") {
553 output_files = {
"test_productionmode_events.root"};
554 process.add<std::string>(
"pass_name",
"test");
555 process.add(
"output_files", output_files);
556 process.add(
"max_events", 3);
557 process.add(
"run", 3);
559 producer_parameters.add(
"create_run_header",
true);
561 sequence = {producer_parameters};
563 SECTION(
"only producers") {
564 process.add(
"sequence", sequence);
565 process.add<std::string>(
"histogram_file",
"");
566 SECTION(
"no drop/keep rules") {
568 REQUIRE(framework::test::runProcess(process));
569 CHECK_THAT(output_files.at(0),
573 SECTION(
"drop TestCollection") {
574 std::vector<std::string> keep = {
"drop .*Collection.*"};
575 process.add(
"keep", keep);
576 REQUIRE(framework::test::runProcess(process));
577 CHECK_THAT(output_files.at(0),
581 SECTION(
"skim for even indexed events") {
582 process.add(
"skim_default_is_keep",
false);
583 std::vector<std::string> rules = {
"TestProducer",
""};
584 process.add(
"skim_rules", rules);
585 REQUIRE(framework::test::runProcess(process));
586 CHECK_THAT(output_files.at(0),
591 SECTION(
"with Analyses") {
592 std::string hist_file_path =
593 "test_productionmode_withanalyses_hists.root";
595 process.add(
"histogram_file", hist_file_path);
597 sequence.push_back(analyzer_parameters);
598 process.add(
"sequence", sequence);
600 SECTION(
"no drop/keep rules") {
601 REQUIRE(framework::test::runProcess(process));
602 CHECK_THAT(output_files.at(0),
606 SECTION(
"drop TestCollection") {
607 std::vector<std::string> keep = {
"drop .*Collection.*"};
608 process.add(
"keep", keep);
609 REQUIRE(framework::test::runProcess(process));
610 CHECK_THAT(output_files.at(0),
614 SECTION(
"skim for even indexed events") {
615 process.add(
"skim_default_is_keep",
false);
616 std::vector<std::string> rules = {
"TestProducer",
""};
617 process.add(
"skim_rules", rules);
618 REQUIRE(framework::test::runProcess(process));
619 CHECK_THAT(output_files.at(0),
623 CHECK_THAT(hist_file_path,
625 CHECK(framework::test::removeFile(hist_file_path));
628 CHECK(framework::test::removeFile(output_files.at(0)));
631 SECTION(
"Need Input Files") {
632 input_files = {
"test_needinputfiles_2_events.root",
633 "test_needinputfiles_3_events.root",
634 "test_needinputfiles_4_events.root"};
636 for (
int run{2};
run < 5;
run++) {
637 auto make_inputs = process;
638 make_inputs.add<std::string>(
"pass_name",
"makeInputs");
639 auto producer = producer_parameters;
640 producer.add(
"create_run_header",
true);
641 make_inputs.add<std::vector<framework::config::Parameters>>(
"sequence",
643 output_files = {input_files.at(run - 2)};
644 make_inputs.add(
"output_files", output_files);
645 make_inputs.add(
"max_events", run);
646 make_inputs.add(
"run", run);
647 REQUIRE(framework::test::runProcess(make_inputs));
648 REQUIRE_THAT(input_files.at(run - 2),
651 process.add<std::string>(
"pass_name",
"test");
653 SECTION(
"Analysis Mode") {
656 sequence = {analyzer_parameters};
657 process.add(
"sequence", sequence);
659 std::string hist_file_path =
"test_analysismode_hists.root";
660 process.add(
"histogram_file", hist_file_path);
662 SECTION(
"one input file") {
663 std::vector<std::string> input_file = {input_files.at(0)};
664 process.add(
"input_files", input_file);
665 REQUIRE(framework::test::runProcess(process));
667 CHECK(framework::test::removeFile(hist_file_path));
670 SECTION(
"multiple input files") {
671 process.add(
"input_files", input_files);
672 REQUIRE(framework::test::runProcess(process));
674 1 + 2 + 1 + 2 + 3 + 1 + 2 + 3 + 4));
675 CHECK(framework::test::removeFile(hist_file_path));
680 SECTION(
"Evolve Mode") {
682 std::vector<std::string> input_file = {input_files.at(0)};
683 process.add(
"input_files", input_file);
685 std::string event_file_path =
"test_evolvemode_events.root";
686 output_files = {event_file_path};
687 process.add(
"output_files", output_files);
689 SECTION(
"drop TestCollection") {
690 std::vector<std::string> keep = {
"drop .*Collection.*"};
691 process.add(
"keep", keep);
692 REQUIRE(framework::test::runProcess(process));
693 CHECK_THAT(event_file_path,
698 SECTION(
"Merge Mode") {
701 process.add(
"input_files", input_files);
703 std::string event_file_path =
"test_mergemode_events.root";
704 output_files = {event_file_path};
705 process.add(
"output_files", output_files);
707 SECTION(
"with analyzers") {
708 sequence = {analyzer_parameters};
710 std::string hist_file_path =
"test_mergemode_withanalyzers_hists.root";
712 process.add(
"sequence", sequence);
713 process.add(
"histogram_file", hist_file_path);
715 SECTION(
"no drop/keep rules") {
716 REQUIRE(framework::test::runProcess(process));
718 "makeInputs", 2 + 3 + 4, 3));
721 SECTION(
"drop TestCollection") {
722 std::vector<std::string> keep = {
"drop .*Collection.*"};
723 process.add(
"keep", keep);
724 REQUIRE(framework::test::runProcess(process));
726 "makeInputs", 2 + 3 + 4, 3,
false));
730 1 + 2 + 1 + 2 + 3 + 1 + 2 + 3 + 4));
731 CHECK(framework::test::removeFile(hist_file_path));
734 SECTION(
"with producers") {
735 producer_parameters.add(
"create_run_header",
false);
736 sequence = {producer_parameters};
738 process.add(
"sequence", sequence);
740 SECTION(
"not listening to storage hints") {
741 REQUIRE(framework::test::runProcess(process));
742 CHECK_THAT(event_file_path,
746 SECTION(
"skim for even indexed events") {
747 process.add(
"skim_default_is_keep",
false);
748 std::vector<std::string> rules = {
"TestProducer",
""};
749 process.add(
"skim_rules", rules);
750 REQUIRE(framework::test::runProcess(process));
751 CHECK_THAT(event_file_path,
756 CHECK(framework::test::removeFile(event_file_path));
774TEST_CASE(
"Missing Run Header",
"[Framework][functionality]") {
776 process.add(
"compression_setting", 9);
777 process.add(
"max_tries_per_event", 1);
778 process.add(
"log_frequency", -1);
779 process.add(
"term_log_level", 4);
780 process.add(
"file_log_level", 4);
781 process.add<std::string>(
"log_file_name",
"");
782 process.add<std::string>(
"tree_name",
"LDMX_Events");
785 producer_parameters.
add<std::string>(
"class_name",
786 "framework::test::TestProducer");
787 producer_parameters.add<std::string>(
"instance_name",
"TestProducer");
790 analyzer_parameters.
add<std::string>(
"class_name",
791 "framework::test::TestAnalyzer");
792 analyzer_parameters.add<std::string>(
"instance_name",
"TestAnalyzer");
794 const std::string healthy_file{
"test_missingrh_healthy_events.root"};
795 const std::string headerless_file{
"test_missingrh_headerless_events.root"};
799 auto make_inputs = process;
800 make_inputs.add<std::string>(
"pass_name",
"makeInputs");
801 auto producer = producer_parameters;
802 producer.add(
"create_run_header",
true);
803 make_inputs.add<std::vector<framework::config::Parameters>>(
"sequence",
805 make_inputs.add(
"output_files", std::vector<std::string>{healthy_file});
806 make_inputs.add<std::string>(
"histogram_file",
"");
807 make_inputs.add(
"max_events", 3);
808 make_inputs.add(
"run", 3);
809 REQUIRE(framework::test::runProcess(make_inputs));
810 REQUIRE_THAT(healthy_file,
813 framework::test::stripRunHeader(healthy_file, headerless_file);
815 process.add<std::string>(
"pass_name",
"test");
816 std::string hist_file_path =
"test_missingrh_hists.root";
817 process.add(
"histogram_file", hist_file_path);
818 process.add<std::vector<framework::config::Parameters>>(
819 "sequence", {analyzer_parameters});
820 process.add(
"input_files", std::vector<std::string>{headerless_file});
822 CHECK_THROWS_AS(framework::test::runProcess(process),
825 CHECK(framework::test::removeFile(hist_file_path));
826 CHECK(framework::test::removeFile(headerless_file));
827 CHECK(framework::test::removeFile(healthy_file));
840TEST_CASE(
"Output Completeness",
"[Framework][functionality]") {
842 process.add(
"compression_setting", 9);
843 process.add(
"max_tries_per_event", 1);
844 process.add(
"log_frequency", -1);
845 process.add(
"term_log_level", 4);
846 process.add(
"file_log_level", 4);
847 process.add<std::string>(
"log_file_name",
"");
848 process.add<std::string>(
"tree_name",
"LDMX_Events");
849 process.add<std::string>(
"pass_name",
"test");
850 process.add<std::string>(
"histogram_file",
"");
851 process.add(
"max_events", 5);
852 process.add(
"run", 3);
855 producer_parameters.
add<std::string>(
"class_name",
856 "framework::test::TestProducer");
857 producer_parameters.
add<std::string>(
"instance_name",
"TestProducer");
858 producer_parameters.
add(
"create_run_header",
true);
860 const std::string output_file{
"test_completeness_events.root"};
861 process.add(
"output_files", std::vector<std::string>{output_file});
863 SECTION(
"a clean close is marked completed") {
864 process.add<std::vector<framework::config::Parameters>>(
865 "sequence", {producer_parameters});
866 REQUIRE(framework::test::runProcess(process));
867 CHECK(framework::test::isCompleted(output_file));
871 SECTION(
"an interrupted run is not") {
873 producer_parameters.
add(
"throw_after", 3);
874 process.add<std::vector<framework::config::Parameters>>(
875 "sequence", {producer_parameters});
876 CHECK_THROWS_AS(framework::test::runProcess(process),
879 CHECK_FALSE(framework::test::isCompleted(output_file));
884 CHECK(framework::test::removeFile(output_file));
898TEST_CASE(
"Incomplete Input",
"[Framework][functionality]") {
900 process.add(
"compression_setting", 9);
901 process.add(
"max_tries_per_event", 1);
902 process.add(
"log_frequency", -1);
903 process.add(
"term_log_level", 4);
904 process.add(
"file_log_level", 4);
905 process.add<std::string>(
"log_file_name",
"");
906 process.add<std::string>(
"tree_name",
"LDMX_Events");
909 producer_parameters.
add<std::string>(
"class_name",
910 "framework::test::TestProducer");
911 producer_parameters.add<std::string>(
"instance_name",
"TestProducer");
912 producer_parameters.add(
"create_run_header",
true);
915 analyzer_parameters.
add<std::string>(
"class_name",
916 "framework::test::TestAnalyzer");
917 analyzer_parameters.
add<std::string>(
"instance_name",
"TestAnalyzer");
919 const std::string complete_file{
"test_incompletein_complete_events.root"};
920 const std::string incomplete_file{
"test_incompletein_incomplete_events.root"};
924 auto make_inputs = process;
925 make_inputs.add<std::string>(
"pass_name",
"makeInputs");
926 make_inputs.add<std::vector<framework::config::Parameters>>(
927 "sequence", {producer_parameters});
928 make_inputs.add(
"output_files", std::vector<std::string>{complete_file});
929 make_inputs.add<std::string>(
"histogram_file",
"");
930 make_inputs.add(
"max_events", 3);
931 make_inputs.add(
"run", 3);
932 REQUIRE(framework::test::runProcess(make_inputs));
933 REQUIRE(framework::test::isCompleted(complete_file));
936 auto make_inputs = process;
937 make_inputs.add<std::string>(
"pass_name",
"makeInputs");
938 auto producer = producer_parameters;
939 producer.add(
"throw_after", 3);
940 make_inputs.add<std::vector<framework::config::Parameters>>(
"sequence",
942 make_inputs.add(
"output_files", std::vector<std::string>{incomplete_file});
943 make_inputs.add<std::string>(
"histogram_file",
"");
944 make_inputs.add(
"max_events", 5);
945 make_inputs.add(
"run", 4);
946 REQUIRE_THROWS_AS(framework::test::runProcess(make_inputs),
948 REQUIRE_FALSE(framework::test::isCompleted(incomplete_file));
951 process.add<std::string>(
"pass_name",
"test");
952 std::string hist_file_path =
"test_incompletein_hists.root";
953 process.add(
"histogram_file", hist_file_path);
954 process.add<std::vector<framework::config::Parameters>>(
955 "sequence", {analyzer_parameters});
957 SECTION(
"an unfinished run is refused") {
958 process.add(
"input_files", std::vector<std::string>{incomplete_file});
959 CHECK_THROWS_AS(framework::test::runProcess(process),
963 SECTION(
"an unfinished run is refused even alongside good files") {
964 process.add(
"input_files",
965 std::vector<std::string>{complete_file, incomplete_file});
966 CHECK_THROWS_AS(framework::test::runProcess(process),
970 SECTION(
"experts can ask for it anyway") {
971 process.add(
"input_files", std::vector<std::string>{incomplete_file});
972 process.add(
"allow_incomplete_input_files",
true);
973 CHECK(framework::test::runProcess(process));
977 SECTION(
"a complete run is let through") {
978 process.add(
"input_files", std::vector<std::string>{complete_file});
979 CHECK(framework::test::runProcess(process));
983 CHECK(framework::test::removeFile(hist_file_path));
984 CHECK(framework::test::removeFile(incomplete_file));
985 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....