10#include <ecl/modules/eclDQM/eclDQM.h>
13#include <ecl/dataobjects/ECLCalDigit.h>
14#include <ecl/dataobjects/ECLDigit.h>
15#include <ecl/dataobjects/ECLDsp.h>
16#include <ecl/dataobjects/ECLElementNumbers.h>
17#include <ecl/dataobjects/ECLTrig.h>
18#include <ecl/geometry/ECLGeometryPar.h>
19#include <ecl/mapper/ECLChannelMapper.h>
22#include <analysis/dataobjects/ParticleList.h>
23#include <analysis/VariableManager/Manager.h>
24#include <analysis/variables/ECLVariables.h>
25#include <framework/core/HistoModule.h>
26#include <framework/dataobjects/EventMetaData.h>
27#include <framework/gearbox/Unit.h>
28#include <framework/logging/Logger.h>
29#include <mdst/dataobjects/TRGSummary.h>
32#include <boost/format.hpp>
33#include <boost/range/combine.hpp>
34#include <boost/range/adaptor/indexed.hpp>
37#include <TDirectory.h>
52using namespace boost::adaptors;
58 m_calibrationThrApsd(
"ECL_FPGA_StoreWaveform")
62 "Primary module for ECL Data Quality Monitor.\n"
63 "This module provides a large set of low-level histograms: occupancy, time distribution, number of saved waveforms, etc.");
69 "histogram directory in ROOT file", std::string(
"ECL"));
72 "Thresholds to display hit occupancy, MeV. Note that it has to be consistent with m_HitNumberUpperLimits", std::vector<double> {0, 5, 10, 20, 50});
76 "Upper limit (# of hits) to display hit multiplicity. Note that it has to be consistent with m_HitThresholds", std::vector<double> {10000, 1000, 700, 400, 200});
80 "Flag to control trigger of delayed bhabha events; 0 - select events by 'bha_delay' trigger bit, 1 - select by TTYP_DPHY",
false);
91 TDirectory* oldDir = gDirectory;
100 h_evtot =
new TH1F(
"event",
"Total event bank", 1, 0, 1);
102 h_quality =
new TH1F(
"quality",
"Fit quality flag. 0-good, 1-integer overflow, 2-low amplitude, 3-bad chi2", 4, 0, 4);
103 h_quality->GetXaxis()->SetTitle(
"Quality flag");
104 h_quality->GetYaxis()->SetTitle(
"ECL hits count");
107 h_quality_other =
new TH1F(
"quality_other",
"Fit quality flag for unexpectedly saved waveforms", 4, 0, 4);
108 h_quality_other->GetXaxis()->SetTitle(
"Quality flag. 0-good,1-int overflow,2-low amplitude,3-bad chi2");
111 h_bad_quality =
new TH1F(
"bad_quality",
"Fraction of hits with bad chi2 (qual=3) and E > 1 GeV vs Cell ID",
116 h_trigtag1 =
new TH1F(
"trigtag1",
"Consistency b/w global event number and trigger tag. 0-good, 1-DQM error", 2, 0, 2);
117 h_trigtag1->GetXaxis()->SetTitle(
"Flag value");
118 h_trigtag1->GetYaxis()->SetTitle(
"Events count");
122 h_adc_hits =
new TH1F(
"adc_hits",
"Fraction of high-energy hits (E > 50 MeV)", 1001, 0, 1.001);
124 h_adc_hits->GetYaxis()->SetTitle(
"Events count");
127 "Number of hits with timing outside #pm 100 ns per Crate ID (E > 1 GeV)",
133 std::string h_name, h_title;
134 h_name = str(boost::format(
"cid_Thr%1%MeV") %
id);
135 h_title = str(boost::format(
"Occupancy per Cell ID (E > %1% MeV)") %
id);
136 TH1F* h =
new TH1F(h_name.c_str(), h_title.c_str(),
138 h->GetXaxis()->SetTitle(
"Cell ID");
139 h->GetYaxis()->SetTitle(
"Occupancy (hits / events_count)");
144 std::string h_name, h_title;
145 h_name = str(boost::format(
"edep_Thr%1%MeV") %
id);
146 h_title = str(boost::format(
"Total energy (thr = %1% MeV)") %
id);
148 h->GetXaxis()->SetTitle(
"Energy, [GeV]");
153 std::string h_bar_name, h_bar_title;
154 std::string h_end_name, h_end_title;
155 h_bar_name = str(boost::format(
"time_barrel_Thr%1%MeV") %
id);
156 h_bar_title = str(boost::format(
"Reconstructed time for ECL barrel (E > %1% MeV)") %
id);
157 h_end_name = str(boost::format(
"time_endcaps_Thr%1%MeV") %
id);
158 h_end_title = str(boost::format(
"Reconstructed time for ECL endcaps (E > %1% MeV)") %
id);
159 TH1F* h_time_barrel =
new TH1F(h_bar_name.c_str(), h_bar_title.c_str(), 206, -1030, 1030);
160 TH1F* h_time_endcap =
new TH1F(h_end_name.c_str(), h_end_title.c_str(), 206, -1030, 1030);
161 h_time_barrel->GetXaxis()->SetTitle(
"Time, [ns]");
162 h_time_endcap->GetXaxis()->SetTitle(
"Time, [ns]");
168 B2FATAL(
"m_HitThresholds[] and m_HitNumberUpperLimits[] have different sizes");
171 double id1 = 0, id2 = 0;
172 boost::tie(id1, id2) = id;
173 std::string h_name, h_title;
174 h_name = str(boost::format(
"ncev_Thr%1%MeV") % id1);
175 h_title = str(boost::format(
"Number of hits in event (E > %1% MeV)") % id1);
176 TH1F* h =
new TH1F(h_name.c_str(), h_title.c_str(), id2, 0, id2);
177 h->GetXaxis()->SetTitle(
"Number of hits");
181 for (
int i = 0; i < ECL_CRATES; i++) {
183 std::string h_name, h_title;
184 h_name = str(boost::format(
"time_crate_%1%_Thr1GeV") % (crate));
185 h_title = str(boost::format(
"Reconstructed time for ECL crate #%1% with E > 1 GeV") % (crate));
186 TH1F* h =
new TH1F(h_name.c_str(), h_title.c_str(), 400, -100, 100);
187 h->GetXaxis()->SetTitle(
"Time [ns]");
192 if (
id !=
"all" &&
id !=
"psd" &&
id !=
"logic" &&
id !=
"rand" &&
id !=
"dphy" &&
id !=
"other")
193 B2WARNING(
"Waveform Options are not correctly assigned. They must be 'all', 'psd', 'logic', 'rand', 'dphy', 'other'!");
195 std::string h_cell_name;
196 if (
id ==
"other") h_title =
"Unexpectedly saved waveforms";
197 if (
id ==
"psd") h_title =
"#frac{Saved}{Expected} waveforms for high-energy hits (E > 50 MeV)";
198 if (
id ==
"logic") h_title =
"#frac{Saved}{Expected} waveforms for every 1000th event";
199 if (
id ==
"rand") h_title =
"#frac{Saved}{Expected} waveforms for random trigger events";
200 if (
id ==
"dphy") h_title =
"#frac{Saved}{Expected} waveforms for delayed bhabha (DPHY) events";
201 if (
id ==
"all") h_title =
"#frac{Saved}{Expected} waveforms for all events";
202 h_cell_name = str(boost::format(
"wf_cid_%1%") % (
id));
203 TH1F* h_cell =
new TH1F(h_cell_name.c_str(), h_title.c_str(),
205 h_cell->GetXaxis()->SetTitle(
"Cell ID");
207 h_cell_psd_norm =
new TH1F(
"psd_cid",
"Normalization to psd hits for cid",
211 h_evtot_logic =
new TH1F(
"event_logic",
"Event bank for logic", 1, 0, 1);
214 h_evtot_rand =
new TH1F(
"event_rand",
"Event bank for rand", 1, 0, 1);
217 h_evtot_dphy =
new TH1F(
"event_dphy",
"Event bank for dphy", 1, 0, 1);
224 h_trigtag2_trigid =
new TH2F(
"trigtag2_trigid",
"Internal data consistency vs crate. 0-good, 1-data corruption",
225 52, 1, 53, 11, -1, 10);
232 h_pedmean_cellid->GetYaxis()->SetTitle(
"Ped. average (ADC units, #approx 0.05 MeV)");
234 h_pedrms_cellid =
new TProfile(
"pedrms_cellid",
"Pedestal stddev vs Cell ID",
237 h_pedrms_cellid->GetYaxis()->SetTitle(
"Ped. stddev (ADC units, #approx 0.05 MeV)");
239 h_pedrms_thetaid =
new TProfile(
"pedrms_thetaid",
"Pedestal stddev vs #theta ID",
241 h_pedrms_thetaid->GetXaxis()->SetTitle(
"#theta ID (0-12=FWD, 59-67=BWD endcap)");
242 h_pedrms_thetaid->GetYaxis()->SetTitle(
"Ped. stddev (ADC units, #approx 0.05 MeV)");
244 h_trigtime_trigid =
new TH2F(
"trigtime_trigid",
"Trigger time vs Crate ID", 52, 1, 53, 145, 0, 145);
248 h_pi0_mass =
new TH1F(
"ecl_pi0_mass",
"ecl_pi0_mass", 120, 0.08, 0.20);
264 if (!
mapper.
initFromDB()) B2FATAL(
"ECL DQM: Can't initialize eclChannelMapper");
288 std::for_each(
h_cids.begin(),
h_cids.end(), [](
auto & it) {it->Reset();});
289 std::for_each(
h_edeps.begin(),
h_edeps.end(), [](
auto & it) {it->Reset();});
292 std::for_each(
h_ncevs.begin(),
h_ncevs.end(), [](
auto & it) {it->Reset();});
293 std::for_each(
h_cells.begin(),
h_cells.end(), [](
auto & it) {it->Reset();});
307 for (
auto& value :
ecltot) value = 0;
308 for (
auto& value :
nhits) value = 0;
309 bool bhatrig =
false;
313 try { bhatrig =
m_l1Trigger->testInput(
"bha_delay"); }
314 catch (
const std::exception&) { bhatrig =
false; }
331 int i = aECLDigit.getCellId() - 1;
333 if (aECLDigit.getAmp() > 2.e04 && aECLDigit.getQuality() == 3)
h_bad_quality->Fill(aECLDigit.getCellId());
334 if (aECLDigit.getAmp() >= (
v_totalthrApsd[i] / 4 * 4)) NDigits ++;
336 if (
id !=
"psd")
continue;
337 else if (
id ==
"psd" && (
m_iEvent % 1000 == 999 ||
346 double itrg = aECLTrig.getTimeTrig();
349 int tg = (int)itrg - 2 * ((
int)itrg / 8);
351 trigtag1 += aECLTrig.getTrigTag();
359 if (compar == trigtag1) flagtag = 0;
364 int cid = aECLCalDigit.getCellId();
365 double energy = aECLCalDigit.getEnergy();
366 double timing = aECLCalDigit.getTime();
370 if (energy > thrGeV) {
377 auto thrGeV = thr.value() / 1000.;
378 if (energy > thrGeV)
ecltot[thr.index()] += energy;
382 auto thrGeV = thr.value() / 1000.;
383 if (energy > thrGeV) {
384 if (cid > ECL_FWD_CHANNELS && cid <= ECL_FWD_CHANNELS + ECL_BARREL_CHANNELS)
h_time_barrels[thr.index()]->Fill(timing);
393 for (
const auto& h :
h_edeps | indexed(0)) {
394 h.value()->Fill(
ecltot[h.index()]);
397 for (
const auto& h :
h_ncevs | indexed(0)) {
398 h.value()->Fill(
nhits[h.index()]);
402 int i = aECLDsp.getCellId() - 1;
420 const auto& index = iter.index();
421 const auto& wf_opt = iter.value();
422 if (wf_opt !=
"all" && wf_opt !=
"psd" && wf_opt !=
"logic" && wf_opt !=
"rand" && wf_opt !=
"dphy" && wf_opt !=
"other")
continue;
425 else if (wf_opt ==
"logic" &&
m_iEvent % 1000 != 999)
continue;
427 else if (wf_opt ==
"dphy" && (
m_iEvent % 1000 == 999 || !bhatrig))
continue;
430 h_cells[index]->Fill(aECLDsp.getCellId());
458 const std::string trg_identifier =
"software_trigger_cut&skim&accept_hadron";
460 if (!result.isValid())
return false;
463 const std::map<std::string, int>& results = result->getResults();
464 if (results.find(trg_identifier) == results.end())
return false;
467 if (!accepted)
return false;
470 if (!particles.isValid())
return false;
472 for (
unsigned int i = 0; i < particles->getListSize(); i++) {
473 const Particle* part = particles->getParticle(i);
474 auto inv_mass = Variable::eclClusterOnlyInvariantMass(part);
double m_PedestalMean[ECLElementNumbers::c_NCrystals]
Pedestal average values.
TH1F * h_trigtag1
Histogram: Trigger tag flag #1.
std::vector< double > nhits
Container for channel multiplicity.
bool fillInvMassHistogram()
Fill entries for pi0 invariant mass distribution.
TH1F * h_bad_quality
Histogram: Cell IDs w/ bad fit quality flag.
double m_PedestalRms[ECLElementNumbers::c_NCrystals]
Pedestal rms error values.
bool m_DPHYTTYP
Flag to select events triggered by delayed bhabha.
std::vector< double > m_TimingThresholds
Parameters for timing histograms.
TH1F * h_adc_hits
Histogram: Fraction of digits above ADC threshold.
StoreArray< ECLDsp > m_ECLDsps
StoreArray ECLDsp.
virtual void initialize() override
Initialize the module.
virtual ~ECLDQMModule()
Destructor.
StoreArray< ECLCalDigit > m_ECLCalDigits
StoreArray ECLCalDigit.
StoreObjPtr< TRGSummary > m_l1Trigger
StoreObjPtr TRGSummary
TH1F * h_cell_psd_norm
Histogram: Normalize to psd hits for CellID.
virtual void event() override
Event processor.
TH2F * h_trigtime_trigid
Histogram: Trigger time vs.
ECLDQMModule()
< derived from HistoModule class.
std::vector< TH1F * > h_edeps
Histogram vector: Total energy.
virtual void endRun() override
Call when a run ends.
std::vector< TH1F * > h_ncevs
Histogram vector: Channel multiplicity.
virtual void terminate() override
Terminate.
TH1F * h_evtot
Histogram: Total event no (auxiliary) to normalize hit map .
int m_iEvent
Global event number.
ECL::ECLGeometryPar * m_geom
Geometry.
StoreArray< ECLDigit > m_ECLDigits
StoreArray ECLDigit.
std::vector< double > ecltot
Container for energy.
std::vector< TH1F * > h_time_barrels
Histogram vector: Reconstructed time for barrel.
double m_EnergyUpperThr
Upper threshold of energy deposition in event, [GeV].
TProfile * h_pedmean_cellid
Histogram: Pedestal Average vs.
TH1F * h_evtot_rand
Histogram: Event no for rand (auxiliary) to normalize rand waveform flow.
std::vector< TH1F * > h_time_crate_Thr1GeV
Histogram vector: Reconstructed signal time for all ECL crates above the threshold = 1 GeV.
TH1F * h_time_crate_Thr1GeV_large
Histogram: Entries with crate time offsets > 100 ns (E > 1 GeV).
virtual void beginRun() override
Call when a run begins.
std::string m_histogramDirectoryName
Histogram directory in ROOT file.
ECL::ECLChannelMapper mapper
ECL channel mapper.
TH1F * h_evtot_logic
Histogram: Event no for logic (auxiliary) to normalize logic waveform flow.
std::vector< double > m_HitNumberUpperLimits
Parameters for number of hits histograms.
std::vector< double > m_TotalEnergyThresholds
Parameters for histograms w/ total energy.
TProfile * h_pedrms_thetaid
Histogram: Pedestal rms error vs.
std::vector< std::string > m_WaveformOption
Parameters for waveform histograms.
int m_DspArray[ECLElementNumbers::c_NCrystals][31]
WF sampling points for digit array.
TH1F * h_evtot_dphy
Histogram: Event no for dphy (auxiliary) to normalize dphy waveform flow.
std::vector< double > m_HitThresholds
Parameters for hit occ.
TH1F * h_quality
Histogram: Fit quality flag (0 - good, 1 - large amplitude, 3 - bad chi2).
StoreArray< ECLTrig > m_ECLTrigs
StoreArray ECLTrig.
StoreObjPtr< EventMetaData > m_eventmetadata
StoreObjPtr EventMetaData.
TH2F * h_trigtag2_trigid
Histogram: Trigger tag flag #2 vs.
std::vector< int > v_totalthrApsd
Vector to store psd wf amplitude threshold.
TH1F * h_pi0_mass
Histogram: pi0 mass.
TH1F * h_quality_other
Histogram: Fit quality flag for waveform type 'other'.
std::vector< TH1F * > h_cids
Histogram vector: Hit map.
TProfile * h_pedrms_cellid
Histogram: Pedestal rms error vs.
std::string m_pi0PListName
Name of the pi0 particle list.
DBObjPtr< ECLCrystalCalib > m_calibrationThrApsd
PSD waveform amplitude threshold.
std::vector< TH1F * > h_cells
Histogram vector: Waveforms vs CellID.
virtual void defineHisto() override
Function to define histograms.
std::vector< TH1F * > h_time_endcaps
Histogram vector: Reconstructed time for endcaps.
Class to store ECL digitized hits (output of ECLDigi) relation to ECLHit filled in ecl/modules/eclDig...
int getAmp() const
Get Fitting Amplitude.
int getQuality() const
Get Fitting Quality.
static ECLDigit * getByCellID(int cid)
Find ECLDigit by Cell ID using linear search.
bool initFromDB()
Initialize channel mapper from the conditions database.
int getCrateID(int iCOPPERNode, int iFINESSE, bool pcie40=false)
Get crate number by given COPPER node number and FINESSE number.
static ECLGeometryPar * Instance()
Static method to get a reference to the ECLGeometryPar instance.
void Mapping(int cid)
Mapping theta, phi Id.
int GetThetaID()
Get Theta Id.
HistoModule.h is supposed to be used instead of Module.h for the modules with histogram definitions t...
void setDescription(const std::string &description)
Sets the description of the module.
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Class to store reconstructed particles.
Type-safe access to single objects in the data store.
@ TTYP_DPHY
delayed physics events for background
@ TTYP_POIS
poisson random trigger
@ TTYP_RAND
random trigger events
static const double GeV
Standard of [energy, momentum, mass].
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
double sqrt(double a)
sqrt for double
@ c_accept
Accept this event.
const int c_NCrystals
Number of crystals.
Abstract base class for different kinds of events.