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;
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 for (TH1F* histogram :
h_cids)
290 for (TH1F* histogram :
h_edeps)
296 for (TH1F* histogram :
h_ncevs)
298 for (TH1F* histogram :
h_cells)
314 for (
auto& value :
ecltot) value = 0;
315 for (
auto& value :
nhits) value = 0;
316 bool bhatrig =
false;
320 try { bhatrig =
m_l1Trigger->testInput(
"bha_delay"); }
321 catch (
const std::exception&) { bhatrig =
false; }
338 int i = aECLDigit.getCellId() - 1;
340 if (aECLDigit.getAmp() > 2.e04 && aECLDigit.getQuality() == 3)
h_bad_quality->Fill(aECLDigit.getCellId());
341 if (aECLDigit.getAmp() >= (
v_totalthrApsd[i] / 4 * 4)) NDigits ++;
343 if (
id !=
"psd")
continue;
344 else if (
id ==
"psd" && (
m_iEvent % 1000 == 999 ||
353 double itrg = aECLTrig.getTimeTrig();
356 int tg = (int)itrg - 2 * ((
int)itrg / 8);
358 trigtag1 += aECLTrig.getTrigTag();
366 if (compar == trigtag1) flagtag = 0;
371 int cid = aECLCalDigit.getCellId();
372 double energy = aECLCalDigit.getEnergy();
373 double timing = aECLCalDigit.getTime();
377 if (energy > thrGeV) {
384 auto thrGeV = thr.value() / 1000.;
385 if (energy > thrGeV)
ecltot[thr.index()] += energy;
389 auto thrGeV = thr.value() / 1000.;
390 if (energy > thrGeV) {
391 if (cid > ECL_FWD_CHANNELS && cid <= ECL_FWD_CHANNELS + ECL_BARREL_CHANNELS)
h_time_barrels[thr.index()]->Fill(timing);
400 for (
const auto& h :
h_edeps | indexed(0)) {
401 h.value()->Fill(
ecltot[h.index()]);
404 for (
const auto& h :
h_ncevs | indexed(0)) {
405 h.value()->Fill(
nhits[h.index()]);
409 int i = aECLDsp.getCellId() - 1;
427 const auto& index = iter.index();
428 const auto& wf_opt = iter.value();
429 if (wf_opt !=
"all" && wf_opt !=
"psd" && wf_opt !=
"logic" && wf_opt !=
"rand" && wf_opt !=
"dphy" && wf_opt !=
"other")
continue;
432 else if (wf_opt ==
"logic" &&
m_iEvent % 1000 != 999)
continue;
434 else if (wf_opt ==
"dphy" && (
m_iEvent % 1000 == 999 || !bhatrig))
continue;
437 h_cells[index]->Fill(aECLDsp.getCellId());
465 const std::string trg_identifier =
"software_trigger_cut&skim&accept_hadron";
467 if (!result.isValid())
return false;
470 const std::map<std::string, int>& results = result->getResults();
471 if (results.find(trg_identifier) == results.end())
return false;
474 if (!accepted)
return false;
477 if (!particles.isValid())
return false;
479 for (
unsigned int i = 0; i < particles->getListSize(); i++) {
480 const Particle* part = particles->getParticle(i);
481 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.
static ECLGeometryPar * Instance()
Static method to get a reference to the ECLGeometryPar instance.
HistoModule()
Constructor.
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.