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"
58 header.setIntParameter(
"Should Be Run Number", header.getRunNumber());
63 int i_event =
event.getEventNumber();
67 std::vector<ldmx::CalorimeterHit> caloHits;
68 for (
int i = 0; i < i_event; i++) {
69 caloHits.emplace_back();
70 caloHits.back().setID(i_event * 10 + i);
73 REQUIRE_NOTHROW(event.add(
"TestCollection", caloHits));
76 maxPEHit.
setID(i_event);
82 REQUIRE_NOTHROW(event.add(
"TestObject", res));
86 std::vector<int> event_indices = {i_event, i_event};
87 REQUIRE_NOTHROW(event.add(
"EventIndex", event_indices));
89 float test_float = i_event * 0.1;
90 REQUIRE_NOTHROW(event.add(
"EventTenth", test_float));
114 test_hist_ =
new TH1F(
"test_hist_",
"Test Histogram", 101, -50, 50);
119 int i_event =
event.getEventNumber();
121 REQUIRE(i_event > 0);
123 const std::vector<ldmx::CalorimeterHit>& caloHits =
126 CHECK(caloHits.size() == i_event);
127 for (
unsigned int i = 0; i < caloHits.size(); i++) {
128 CHECK(caloHits.at(i).getID() == i_event * 10 + i);
137 CHECK(maxPEHit.getID() == i_event);
138 CHECK(vetoRes.
passesVeto() == (i_event % 2 == 0));
140 const float& tenth_event =
event.getObject<
float>(
"EventTenth");
141 CHECK(tenth_event == Approx(i_event * 0.1));
143 const std::vector<int>& i_event_from_bus =
144 event.getCollection<
int>(
"EventIndex");
146 CHECK(i_event_from_bus.size() == 2);
147 CHECK(i_event_from_bus.at(0) == i_event);
148 CHECK(i_event_from_bus.at(1) == i_event);
193 bool match(
const std::string& filename)
const override {
195 TFile* f = TFile::Open(filename.c_str());
196 if (!f)
return false;
197 TDirectory* d = (TDirectory*)f->Get(
"TestAnalyzer");
198 if (!d)
return false;
199 TH1F* h = (TH1F*)d->Get(
"test_hist_");
200 if (!h)
return false;
193 bool match(
const std::string& filename)
const override {
…}
212 std::ostringstream ss;
213 ss <<
"has the histogram 'TestAnalyzer/test_hist_' with the number of "
259 bool existColl =
true,
bool existObj =
true)
274 bool match(
const std::string& filename)
const override {
275 TFile* f = TFile::Open(filename.c_str());
276 if (!f)
return false;
278 TTreeReader events(
"LDMX_Events", f);
280 if (events.GetEntries(
true) !=
entries_) {
286 TTreeReaderValue<ldmx::EventHeader> header(events,
"EventHeader");
290 TTreeReaderValue<std::vector<ldmx::CalorimeterHit>> collection(
291 events, (
"TestCollection_" +
pass_).c_str());
292 while (events.Next()) {
293 if (collection->size() != header->getEventNumber()) {
297 for (
unsigned int i = 0; i < collection->size(); i++)
298 if (collection->at(i).getID() != header->getEventNumber() * 10 + i) {
307 auto t{(TTree*)f->Get(
"LDMX_Events")};
308 if (t and t->GetBranch((
"TestCollection_" +
pass_).c_str())) {
316 TTreeReaderValue<ldmx::HcalVetoResult> object(
317 events, (
"TestObject_" +
pass_).c_str());
318 while (events.Next()) {
319 if (object->getMaxPEHit().getID() != header->getEventNumber()) {
326 auto t{(TTree*)f->Get(
"LDMX_Events")};
327 if (t and t->GetBranch((
"TestObject_" +
pass_).c_str())) {
333 TTreeReader runs(
"LDMX_Run", f);
335 if (runs.GetEntries(
true) !=
runs_) {
340 TTreeReaderValue<ldmx::RunHeader> runHeader(runs,
"RunHeader");
342 while (runs.Next()) {
343 if (runHeader->getRunNumber() !=
344 runHeader->getIntParameter(
"Should Be Run Number")) {
274 bool match(
const std::string& filename)
const override {
…}
359 std::ostringstream ss;
360 ss <<
"can be opened and has the correct number of entries in the event "
361 "tree and the run tree.";
363 ss <<
" TestCollection_" <<
pass_ <<
" was verified to ";
365 ss <<
" be the correct pattern.";
367 ss <<
" not be in the file.";
369 ss <<
" TestObject_" <<
pass_ <<
" was verified to ";
371 ss <<
" be the correct pattern.";
373 ss <<
" not be in the file.";
388static bool removeFile(
const std::string& filepath) {
389 return remove(filepath.c_str()) == 0;
398 p = std::make_unique<Process>(parameters);
400 std::cerr <<
"Config Error [" << e.
name() <<
"] : " << e.
message()
402 std::cerr <<
" at " << e.
module() <<
":" << e.
line() <<
" in "
449TEST_CASE(
"Core Framework Functionality",
"[Framework][functionality]") {
452 process.add(
"compressionSetting", 9);
453 process.add(
"maxTriesPerEvent", 1);
454 process.add(
"logFrequency", -1);
455 process.add(
"termLogLevel", 4);
456 process.add(
"fileLogLevel", 4);
457 process.add<std::string>(
"logFileName",
"");
458 process.add<std::string>(
"tree_name",
"LDMX_Events");
461 producerParameters.
add<std::string>(
"className",
462 "framework::test::TestProducer");
463 producerParameters.add<std::string>(
"instanceName",
"TestProducer");
466 analyzerParameters.
add<std::string>(
"className",
467 "framework::test::TestAnalyzer");
468 analyzerParameters.add<std::string>(
"instanceName",
"TestAnalyzer");
471 std::vector<framework::config::Parameters> sequence;
472 std::vector<std::string> inputFiles, outputFiles;
474 SECTION(
"Production Mode") {
477 outputFiles = {
"test_productionmode_events.root"};
478 process.add<std::string>(
"passName",
"test");
479 process.add(
"outputFiles", outputFiles);
480 process.add(
"maxEvents", 3);
481 process.add(
"run", 3);
483 producerParameters.add(
"createRunHeader",
true);
485 sequence = {producerParameters};
487 SECTION(
"only producers") {
488 process.add(
"sequence", sequence);
489 process.add<std::string>(
"histogramFile",
"");
490 SECTION(
"no drop/keep rules") {
492 REQUIRE(framework::test::runProcess(process));
493 CHECK_THAT(outputFiles.at(0),
497 SECTION(
"drop TestCollection") {
498 std::vector<std::string> keep = {
"drop .*Collection.*"};
499 process.add(
"keep", keep);
500 REQUIRE(framework::test::runProcess(process));
501 CHECK_THAT(outputFiles.at(0),
505 SECTION(
"skim for even indexed events") {
506 process.add(
"skimDefaultIsKeep",
false);
507 std::vector<std::string> rules = {
"TestProducer",
""};
508 process.add(
"skimRules", rules);
509 REQUIRE(framework::test::runProcess(process));
510 CHECK_THAT(outputFiles.at(0),
515 SECTION(
"with Analyses") {
516 std::string hist_file_path =
517 "test_productionmode_withanalyses_hists.root";
519 process.add(
"histogramFile", hist_file_path);
521 sequence.push_back(analyzerParameters);
522 process.add(
"sequence", sequence);
524 SECTION(
"no drop/keep rules") {
525 REQUIRE(framework::test::runProcess(process));
526 CHECK_THAT(outputFiles.at(0),
530 SECTION(
"drop TestCollection") {
531 std::vector<std::string> keep = {
"drop .*Collection.*"};
532 process.add(
"keep", keep);
533 REQUIRE(framework::test::runProcess(process));
534 CHECK_THAT(outputFiles.at(0),
538 SECTION(
"skim for even indexed events") {
539 process.add(
"skimDefaultIsKeep",
false);
540 std::vector<std::string> rules = {
"TestProducer",
""};
541 process.add(
"skimRules", rules);
542 REQUIRE(framework::test::runProcess(process));
543 CHECK_THAT(outputFiles.at(0),
547 CHECK_THAT(hist_file_path,
549 CHECK(framework::test::removeFile(hist_file_path));
552 CHECK(framework::test::removeFile(outputFiles.at(0)));
555 SECTION(
"Need Input Files") {
556 inputFiles = {
"test_needinputfiles_2_events.root",
557 "test_needinputfiles_3_events.root",
558 "test_needinputfiles_4_events.root"};
560 for (
int run{2};
run < 5;
run++) {
561 auto makeInputs = process;
562 makeInputs.add<std::string>(
"passName",
"makeInputs");
563 auto producer = producerParameters;
564 producer.add(
"createRunHeader",
true);
565 makeInputs.add<std::vector<framework::config::Parameters>>(
"sequence",
567 outputFiles = {inputFiles.at(run - 2)};
568 makeInputs.add(
"outputFiles", outputFiles);
569 makeInputs.add(
"maxEvents", run);
570 makeInputs.add(
"run", run);
571 REQUIRE(framework::test::runProcess(makeInputs));
572 REQUIRE_THAT(inputFiles.at(run - 2),
575 process.add<std::string>(
"passName",
"test");
577 SECTION(
"Analysis Mode") {
580 sequence = {analyzerParameters};
581 process.add(
"sequence", sequence);
583 std::string hist_file_path =
"test_analysismode_hists.root";
584 process.add(
"histogramFile", hist_file_path);
586 SECTION(
"one input file") {
587 std::vector<std::string> inputFile = {inputFiles.at(0)};
588 process.add(
"inputFiles", inputFile);
589 REQUIRE(framework::test::runProcess(process));
591 CHECK(framework::test::removeFile(hist_file_path));
594 SECTION(
"multiple input files") {
595 process.add(
"inputFiles", inputFiles);
596 REQUIRE(framework::test::runProcess(process));
598 1 + 2 + 1 + 2 + 3 + 1 + 2 + 3 + 4));
599 CHECK(framework::test::removeFile(hist_file_path));
604 SECTION(
"Merge Mode") {
607 process.add(
"inputFiles", inputFiles);
609 std::string event_file_path =
"test_mergemode_events.root";
610 outputFiles = {event_file_path};
611 process.add(
"outputFiles", outputFiles);
613 SECTION(
"with analyzers") {
614 sequence = {analyzerParameters};
616 std::string hist_file_path =
"test_mergemode_withanalyzers_hists.root";
618 process.add(
"sequence", sequence);
619 process.add(
"histogramFile", hist_file_path);
621 SECTION(
"no drop/keep rules") {
622 REQUIRE(framework::test::runProcess(process));
624 "makeInputs", 2 + 3 + 4, 3));
627 SECTION(
"drop TestCollection") {
628 std::vector<std::string> keep = {
"drop .*Collection.*"};
629 process.add(
"keep", keep);
630 REQUIRE(framework::test::runProcess(process));
632 "makeInputs", 2 + 3 + 4, 3,
false));
636 1 + 2 + 1 + 2 + 3 + 1 + 2 + 3 + 4));
637 CHECK(framework::test::removeFile(hist_file_path));
640 SECTION(
"with producers") {
641 producerParameters.add(
"createRunHeader",
false);
642 sequence = {producerParameters};
644 process.add(
"sequence", sequence);
646 SECTION(
"not listening to storage hints") {
647 REQUIRE(framework::test::runProcess(process));
648 CHECK_THAT(event_file_path,
652 SECTION(
"skim for even indexed events") {
653 process.add(
"skimDefaultIsKeep",
false);
654 std::vector<std::string> rules = {
"TestProducer",
""};
655 process.add(
"skimRules", rules);
656 REQUIRE(framework::test::runProcess(process));
657 CHECK_THAT(event_file_path,
662 CHECK(framework::test::removeFile(event_file_path));
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_NS(NS, CLASS)
Macro which allows the framework to construct an analyzer given its name during configuration.
#define DECLARE_PRODUCER_NS(NS, 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.
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.
Bare analyzer that looks for objects matching what the TestProducer put in.
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
void configure(framework::config::Parameters &p) final override
Callback for the EventProcessor to configure itself from the given set of parameters.
void produce(framework::Event &event) final override
Process the event and put new data products into it.
void beforeNewRun(ldmx::RunHeader &header) final override
Handle allowing producers to modify run headers before the run begins.
bool createRunHeader_
should we create the run header?
virtual std::string describe() const override
Human-readable statement for any match that is true.
int runs_
correct number of runs
isGoodEventFile(const std::string &pass, const int &entries, const int &runs, bool existColl=true, bool existObj=true)
Constructor.
bool existCollection_
collection should exist in file
bool existObject_
object should exist in file
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.
int entries_
correct number of entries in the event ttree
Runs a variety of checks to make sure the histogram in the input filename is what we expect it to be.
virtual std::string describe() const override
Describe this matcher in a helpful, human-readable way.
int correctGetEntries_
Correct number of entries.
bool match(const std::string &filename) const override
Performs the test for this matcher.
isGoodHistogramFile(int const &n)
Constructor.
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....