1#include <catch2/catch_approx.hpp>
2#include <catch2/catch_test_macros.hpp>
3#include <catch2/matchers/catch_matchers.hpp>
6#include "Ecal/Event/EcalHit.h"
7#include "Framework/ConfigurePython.h"
11#include "Recon/Event/HgcrocTrigDigi.h"
23static const double MIP_SI_ENERGY = 0.130;
32static const double MeV_per_fC = MIP_SI_ENERGY / (37 * 0.1602);
43static const double MAX_ENERGY_PERCENT_ERROR_DAQ = 0.025;
54static const double MAX_ENERGY_PERCENT_ERROR_TP = 0.15;
65static const double MAX_ENERGY_ERROR_DAQ = MIP_SI_ENERGY / 2;
76static const double MAX_ENERGY_ERROR_TP = 2 * MIP_SI_ENERGY;
88static const int NUM_TEST_SIM_HITS = 2000;
113 double const &rel_diff)
125 bool match(
const double &daq_energy)
const override {
134 std::ostringstream ss;
183 header.setDetectorName(
"ldmx-det-v14-8gev");
188 std::vector<ldmx::SimCalorimeterHit> pretendSimHits(1);
191 pretendSimHits[0].setID(
id.raw());
194 pretendSimHits[0].addContrib(-1, -1, 0,
currEnergy_, 1.);
196 pretendSimHits[0].setPosition(0., 0., 299.);
199 REQUIRE_NOTHROW(event.add(
"EcalSimHits", pretendSimHits));
243 REQUIRE(simHits.size() == 1);
245 float truth_energy = simHits.at(0).getEdep();
251 CHECK(daqDigis.getNumDigis() == 1);
252 auto daqDigi = daqDigis.getDigi(0);
254 bool is_in_adc_mode = daqDigi.isADC();
259 const auto recHits =
event.getCollection<
ldmx::EcalHit>(
"EcalRecHits");
260 CHECK(recHits.size() == 1);
262 auto hit = recHits.at(0);
264 CHECK_FALSE(hit.isNoise());
265 CHECK(
id.raw() == simHits.at(0).getID());
267 double daq_energy{hit.getAmplitude()};
268 CHECK_THAT(daq_energy,
isCloseEnough(truth_energy, MAX_ENERGY_ERROR_DAQ,
269 MAX_ENERGY_PERCENT_ERROR_DAQ));
272 const auto trigDigis{
273 event.getObject<ldmx::HgcrocTrigDigiCollection>(
"ecalTrigDigis")};
274 CHECK(trigDigis.size() == 1);
276 auto trigDigi = trigDigis.at(0);
277 float tp_energy = 8 * trigDigi.linearPrimitive() * 320. / 1024 * MeV_per_fC;
279 CHECK_THAT(tp_energy,
isCloseEnough(truth_energy, MAX_ENERGY_ERROR_TP,
280 MAX_ENERGY_PERCENT_ERROR_TP));
282 ntuple_.
setVar<
int>(
"TrigPrimDigiEncoded", trigDigi.getPrimitive());
283 ntuple_.
setVar<
int>(
"TrigPrimDigiLinear", trigDigi.linearPrimitive());
308TEST_CASE(
"Ecal Digi Pipeline test",
"[Ecal][functionality]") {
309 const std::string config_file{
"ecal_digi_pipeline_test_config.py"};
311 char **args{
nullptr};
315 REQUIRE_NOTHROW(p = cfg.makeProcess());
Class that defines an ECal detector ID with a cell number.
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 represents a digitized hit in a calorimeter cell readout by an HGCROC.
Class which represents the process under execution.
Class which stores simulated calorimeter hit information.
void onProcessStart() final override
Callback for the EventProcessor to take any necessary action when the processing of events starts,...
void analyze(const framework::Event &event) final override
Process the event and make histograms or summaries.
const double energyStep_
The step between energies is calculated depending on the min, max energy and the total number of sim ...
const double minEnergy_
Minimum energy to make a sim hit for [MeV] Needs to be above readout threshold (after internal EcalDi...
const double maxEnergy_
Maximum energy to make a simulated hit for [MeV].
void beforeNewRun(ldmx::RunHeader &header) final override
Handle allowing producers to modify run headers before the run begins.
void produce(framework::Event &event) final override
Process the event and put new data products into it.
double currEnergy_
current energy of the sim hit we are on
Our custom energy checker which makes sure that the input energy is "close enough" to the truth energ...
isCloseEnough(double const &truth, double const &abs_diff, double const &rel_diff)
Constructor.
const double max_relative_diff_
maximum relative energy difference
double truth_
correct (sim-level) energy [MeV]
const double max_absolute_diff_
maximum absolute energy difference [MeV]
bool match(const double &daq_energy) const override
Performs the test for this matcher.
virtual std::string describe() const override
Describes matcher for printing to terminal.
Base class for a module which does not produce a data product.
NtupleManager & ntuple_
Manager for any ntuples.
TDirectory * getHistoDirectory()
Access/create a directory in the histogram file for this event processor to create histograms and ana...
Implements an event buffer system for storing event data.
void addVar(const std::string &tname, const std::string &vname)
Add a variable of type VarType to the ROOT tree with name 'tname'.
void create(const std::string &tname)
Create a ROOT tree to hold the ntuple variables (ROOT leaves).
void setVar(const std::string &vname, const T &value)
Set the value of the variable named 'vname'.
Class which represents the process under execution.
Base class for a module which produces a data product.
Producer(const std::string &name, Process &process)
Class constructor.
Stores reconstructed hit information from the ECAL.
Extension of DetectorID providing access to ECal layers and cell numbers in a hex grid.
Represents a collection of the digi hits readout by an HGCROC.
Stores simulated calorimeter hit information.
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....