14 #include "art/Framework/Core/EDAnalyzer.h"
15 #include "art/Framework/Core/ModuleMacros.h"
16 #include "art/Framework/Principal/Event.h"
17 #include "art/Framework/Principal/Handle.h"
18 #include "art/Framework/Principal/Run.h"
19 #include "art/Framework/Principal/SubRun.h"
20 #include "canvas/Utilities/InputTag.h"
21 #include "fhiclcpp/ParameterSet.h"
22 #include "fhiclcpp/types/Atom.h"
23 #include "fhiclcpp/types/Sequence.h"
25 #include "art_root_io/TFileService.h"
27 #include "messagefacility/MessageLogger/MessageLogger.h"
29 #include "canvas/Persistency/Common/FindMany.h"
30 #include "canvas/Persistency/Common/FindOne.h"
31 #include "canvas/Persistency/Common/FindManyP.h"
32 #include "canvas/Persistency/Common/FindOneP.h"
33 #include "canvas/Persistency/Common/Assns.h"
68 Comment(
"Label for the Trigger fragment label")
72 Name(
"DumpWaveformsInfo"),
73 Comment(
"Set the option to save some aggregated waveform information")
77 Name(
"OpDetWaveformLabels"),
78 Comment(
"Tags for the raw::OpDetWaveform data products")
83 Comment(
"Tags for the recob::OpHit data products")
88 Comment(
"Tags for the recob::Flashe data products")
92 Name(
"PEOpHitThreshold"),
93 Comment(
"Threshold in PE for an OpHit to be considered in the information calculated for a flash")
113 void analyze(art::Event
const&
e)
override;
118 template<
typename T> T
Median( std::vector<T> data )
const;
127 int &multiplicity_left,
int &multiplicity_right,
128 float &sum_pe_left,
float &sum_pe_right,
129 float *xyz, TTree *ophittree );
131 static std::string_view
firstLine(std::string
const&
s,
const char* endl =
"\r");
202 , fTriggerLabel( config().TriggerLabel() )
203 , fSaveWaveformInfo( config().DumpWaveformsInfo() )
204 , fOpDetWaveformLabels( config().OpDetWaveformLabels() )
205 , fOpHitLabels( config().OpHitLabels() )
206 , fFlashLabels( config().FlashLabels() )
207 , fPEOpHitThreshold( config().PEOpHitThreshold() )
208 , fDebug( config().Debug() )
215 art::ServiceHandle<art::TFileService const>
tfs;
217 TTree* fGeoTree = tfs->make<TTree>(
"geotree",
"geometry information" );
218 fGeoTree->Branch(
"pmt_x",&m_pmt_x);
219 fGeoTree->Branch(
"pmt_y",&m_pmt_y);
220 fGeoTree->Branch(
"pmt_z",&m_pmt_z);
223 for(
size_t opch=0; opch<
fGeom->NOpChannels(); ++opch) {
225 fGeom->OpDetGeoFromOpChannel(opch).GetCenter(PMTxyz);
229 m_pmt_x.push_back(PMTxyz[0]);
230 m_pmt_y.push_back(PMTxyz[1]);
231 m_pmt_z.push_back(PMTxyz[2]);
237 fEventTree = tfs->make<TTree>(
"eventstree",
"higher level information on the event" );
238 fEventTree->Branch(
"run", &m_run,
"run/I");
239 fEventTree->Branch(
"event", &m_event,
"event/I");
240 fEventTree->Branch(
"timestamp", &m_timestamp,
"timestamp/I");
243 fEventTree->Branch(
"beam_gate_start", &m_beam_gate_start,
"beam_gate_start/F");
244 fEventTree->Branch(
"beam_gate_width", &m_beam_gate_width,
"beam_gate_width/F");
245 fEventTree->Branch(
"beam_type", &m_beam_type,
"beam_type/I");
246 fEventTree->Branch(
"gate_type", &m_gate_type,
"gate_type/b");
247 fEventTree->Branch(
"gate_name", &m_gate_name);
248 fEventTree->Branch(
"trigger_timestamp", &m_trigger_timestamp,
"trigger_timestamp/l");
249 fEventTree->Branch(
"gate_start_timestamp", &m_gate_start_timestamp,
"gate_start_timestamp/l");
250 fEventTree->Branch(
"trigger_gate_diff", &m_trigger_gate_diff,
"trigger_gate_diff/l");
254 if( !fOpDetWaveformLabels.empty() && fSaveWaveformInfo ) {
256 for(
auto const & label : fOpDetWaveformLabels ) {
258 std::string
name = label.label()+
"wfttree";
259 std::string
info =
"TTree with aggregated optical waveform information with label: " + label.label();
261 TTree* ttree = tfs->make<TTree>(name.c_str(), info.c_str());
262 ttree->Branch(
"run", &m_run,
"run/I");
263 ttree->Branch(
"event", &m_event,
"event/I");
264 ttree->Branch(
"timestamp", &m_timestamp,
"timestamp/I");
265 ttree->Branch(
"channel_id", &m_channel_id,
"channel_id/I");
266 ttree->Branch(
"baseline", &m_baseline,
"baseline/s");
267 ttree->Branch(
"chargesum", &m_chargesum,
"chargesum/s");
268 ttree->Branch(
"nticks", &m_nticks,
"nticks/I");
270 fOpDetWaveformTrees.push_back(ttree);
280 for(
auto const & label : fOpHitLabels ) {
282 std::string
name = label.label()+
"_ttree";
283 std::string
info =
"TTree for the recob::OpHit objects with label " + label.label() +
" in events without flashes.";
285 TTree* ttree = tfs->make<TTree>(name.c_str(), info.c_str());
286 ttree->Branch(
"run", &m_run,
"run/I");
287 ttree->Branch(
"event", &m_event,
"event/I");
288 ttree->Branch(
"timestamp", &m_timestamp,
"timestamp/I");
289 ttree->Branch(
"channel_id", &m_channel_id,
"channel_id/I");
290 ttree->Branch(
"integral", &m_integral,
"integral/F");
291 ttree->Branch(
"amplitude", &m_amplitude,
"amplitude/F");
292 ttree->Branch(
"start_time", &m_start_time,
"start_time/F");
293 ttree->Branch(
"abs_start_time", &m_abs_start_time,
"abs_start_time/F");
294 ttree->Branch(
"pe", &m_pe,
"pe/F");
295 ttree->Branch(
"width", &m_width,
"width/F");
296 ttree->Branch(
"fast_to_total", &m_fast_to_total,
"fast_to_total/F");
298 fOpHitTrees.push_back(ttree);
303 if ( !fFlashLabels.empty() ) {
305 for(
auto const & label : fFlashLabels ) {
308 std::string
name = label.label()+
"_flashtree";
309 std::string
info =
"TTree for the recob::Flashes with label "+label.label();
311 TTree* ttree = tfs->make<TTree>(name.c_str(), info.c_str() );
312 ttree->Branch(
"run", &m_run,
"run/I");
313 ttree->Branch(
"event", &m_event,
"event/I");
314 ttree->Branch(
"timestamp", &m_timestamp,
"timestamp/I");
315 ttree->Branch(
"flash_id", &m_flash_id,
"flash_id/I");
316 ttree->Branch(
"multiplicity", &m_multiplicity,
"multiplicity/I");
317 ttree->Branch(
"multiplicity_right", &m_multiplicity_right,
"multiplicity_right/I" );
318 ttree->Branch(
"multiplicity_left", &m_multiplicity_left,
"multiplicity_left/I" );
319 ttree->Branch(
"sum_pe", &m_sum_pe,
"sum_pe/F");
320 ttree->Branch(
"sum_pe_right", &m_sum_pe_right,
"sum_pe_right/F");
321 ttree->Branch(
"sum_pe_left", &m_sum_pe_left,
"sum_pe_left/F");
322 ttree->Branch(
"flash_time", &m_flash_time,
"flash_time/F");
325 ttree->Branch(
"flash_y", &m_flash_y,
"flash_y/F");
326 ttree->Branch(
"flash_width_y", &m_flash_width_y,
"flash_width_y/F");
327 ttree->Branch(
"flash_z", &m_flash_z,
"flash_z/F");
328 ttree->Branch(
"flash_width_z", &m_flash_width_z,
"flash_width_z/F");
330 fOpFlashTrees.push_back( ttree );
333 name = label.label()+
"_ophittree";
334 info =
"Three for the recob::OpHit associated with an OpHitFlash"+label.label();
336 TTree* ophittree = tfs->make<TTree>(name.c_str(), info.c_str() );
337 ophittree->Branch(
"run", &m_run,
"run/I");
338 ophittree->Branch(
"event", &m_event,
"event/I");
339 ophittree->Branch(
"timestamp", &m_timestamp,
"timestamp/I");
340 ophittree->Branch(
"flash_id", &m_flash_id,
"flash_id/I");
341 ophittree->Branch(
"channel_id", &m_channel_id,
"channel_id/I");
342 ophittree->Branch(
"integral", &m_integral,
"integral/F");
343 ophittree->Branch(
"amplitude", &m_amplitude,
"amplitude/F");
344 ophittree->Branch(
"start_time", &m_start_time,
"start_time/F");
345 ophittree->Branch(
"abs_start_time", &m_abs_start_time,
"abs_start_time/F");
346 ophittree->Branch(
"pe", &m_pe,
"pe/F");
347 ophittree->Branch(
"width", &m_width,
"width/F");
348 ophittree->Branch(
"fast_to_total", &m_fast_to_total,
"fast_to_total/F");
350 fOpHitFlashTrees.push_back( ophittree );
362 std::nth_element( data.begin(), data.begin() + data.size()/2, data.end() );
364 return data[ data.size()/2 ];
398 int side = channel / 90;
407 if( fOpHitLabels.empty() ){
409 mf::LogError(
"ICARUSFlashAssAna") <<
"No recob::OpHit labels selected.";
414 for(
size_t iOpHitLabel=0; iOpHitLabel<fOpHitLabels.size(); iOpHitLabel++ ) {
416 auto const label = fOpHitLabels[iOpHitLabel];
418 art::Handle<std::vector<recob::OpHit>> ophit_handle;
419 e.getByLabel( label, ophit_handle );
423 if( !ophit_handle.isValid() || ophit_handle->empty() ) {
424 mf::LogError(
"ICARUSFlashAssAna")
425 <<
"Invalid recob::OpHit with label '" << label.encode() <<
"'";
430 for(
auto const &
ophit : *ophit_handle ) {
434 const int channel_id =
ophit.OpChannel();
436 if( getCryostatByChannel(channel_id) != cryo ){
continue; }
438 m_channel_id = channel_id;
439 m_integral =
ophit.Area();
440 m_amplitude =
ophit.Amplitude();
441 m_start_time =
ophit.PeakTime();
442 m_width =
ophit.Width();
443 m_abs_start_time =
ophit.PeakTimeAbs();
445 m_fast_to_total =
ophit.FastToTotal();
447 fOpHitTrees[iOpHitLabel]->Fill();
458 int &multiplicity_left,
int &multiplicity_right,
459 float &sum_pe_left,
float &sum_pe_right,
460 float *xyz, TTree *ophittree ) {
463 std::unordered_map<int, float > sumpe_map;
466 for(
auto const ophit : ophits ) {
468 if (
ophit->PE() < fPEOpHitThreshold ) {
continue; }
470 const int channel_id =
ophit->OpChannel();
472 sumpe_map[ channel_id ]+=
ophit->PE() ;
478 m_channel_id = channel_id;
479 m_integral =
ophit->Area();
480 m_amplitude =
ophit->Amplitude();
481 m_start_time =
ophit->PeakTime();
482 m_width =
ophit->Width();
483 m_abs_start_time =
ophit->PeakTimeAbs();
485 m_fast_to_total =
ophit->FastToTotal();
491 m_multiplicity_left = std::accumulate( sumpe_map.begin(), sumpe_map.end(), 0,
492 [&](
int value,
const std::map<int, float>::value_type&
p) {
493 return getSideByChannel(
p.first)==0 ? ++value :
value ;
496 m_multiplicity_right =std::accumulate( sumpe_map.begin(), sumpe_map.end(), 0,
497 [&](
int value,
const std::map<int, float>::value_type&
p) {
498 return getSideByChannel(
p.first)==1 ? ++value :
value ;
501 m_sum_pe_left = std::accumulate( sumpe_map.begin(), sumpe_map.end(), 0.0,
502 [&](
float value,
const std::map<int, float>::value_type&
p) {
503 return getSideByChannel(
p.first)==0 ? value+
p.second :
value ;
506 m_sum_pe_right = std::accumulate( sumpe_map.begin(), sumpe_map.end(), 0.0,
507 [&](
float value,
const std::map<int, float>::value_type&
p) {
508 return getSideByChannel(
p.first)==1 ? value+
p.second :
value ;
524 m_run = e.id().run();
525 m_event = e.id().event();
526 m_timestamp = e.time().timeHigh();
535 if( !fTriggerLabel.empty() ) {
538 art::Handle<std::vector<sim::BeamGateInfo>> beamgate_handle;
539 e.getByLabel( fTriggerLabel, beamgate_handle );
541 if( beamgate_handle.isValid() ) {
543 for(
auto const & beamgate : *beamgate_handle ) {
545 m_beam_gate_start = beamgate.Start();
546 m_beam_gate_width = beamgate.Width();
547 m_beam_type = beamgate.BeamType() ;
554 mf::LogError(
"ICARUSFlashAssAna") <<
"No sim::BeamGateInfo associated to label: " << fTriggerLabel.label() <<
"\n" ;
558 art::Handle<sbn::ExtraTriggerInfo> trigger_handle;
559 e.getByLabel( fTriggerLabel, trigger_handle );
561 if( trigger_handle.isValid() ) {
565 m_gate_type = (
unsigned int)bit;
567 m_trigger_timestamp = trigger_handle->triggerTimestamp;
568 m_gate_start_timestamp = trigger_handle->beamGateTimestamp;
569 m_trigger_gate_diff = trigger_handle->triggerTimestamp - trigger_handle->beamGateTimestamp;
573 mf::LogError(
"ICARUSFlashAssAna") <<
"No raw::Trigger associated to label: " << fTriggerLabel.label() <<
"\n" ;
579 mf::LogError(
"ICARUSFlashAssAna") <<
"Trigger Data product " << fTriggerLabel.label() <<
" not found!\n" ;
587 if( !fOpDetWaveformLabels.empty() && fSaveWaveformInfo ) {
589 for(
size_t i=0; i<fOpDetWaveformLabels.size(); i++ ) {
591 auto const label = fOpDetWaveformLabels[i];
593 art::Handle<std::vector<raw::OpDetWaveform>> wfm_handle;
594 e.getByLabel( label, wfm_handle );
596 if( wfm_handle.isValid() && !wfm_handle->empty() ) {
598 for(
auto const & wave : *wfm_handle ){
600 m_channel_id = wave.ChannelNumber();
601 m_nticks = wave.Waveform().size();
602 m_baseline = Median( wave.Waveform() );
603 m_chargesum = std::accumulate( wave.Waveform().begin(), wave.Waveform().end(), 0,
604 [ & ](
short x,
short y){
return ((m_baseline-x) + (m_baseline-
y)) ; } );
606 fOpDetWaveformTrees[i]->Fill();
618 if ( !fFlashLabels.empty() ) {
621 std::vector<unsigned int> cids;
624 for (
size_t iFlashLabel=0; iFlashLabel<fFlashLabels.size(); iFlashLabel++ ) {
626 auto const label = fFlashLabels[iFlashLabel];
628 art::Handle<std::vector<recob::OpFlash>> flash_handle;
629 e.getByLabel( label, flash_handle );
632 if( !flash_handle.isValid() ) {
633 mf::LogError(
"ICARUSFlashAssAna")
634 <<
"Not found a recob::OpFlash with label '" << label.encode() <<
"'";
635 }
else if ( flash_handle->empty() ) {
636 mf::LogWarning(
"ICARUSFlashAssAna")
637 <<
"No recob::OpFlash in collection with label '" << label.encode() <<
"'";
641 art::FindManyP<recob::OpHit> ophitsPtr( flash_handle, e, label );
644 for (
size_t idx=0; idx<flash_handle->size(); idx++ ) {
647 auto const & flash = (*flash_handle)[idx];
649 m_flash_time = flash.Time();
650 m_sum_pe = flash.TotalPE();
652 auto const & ophits = ophitsPtr.at(idx);
657 auto const found = std::find(cids.begin(), cids.end(), cid);
658 if( found != cids.end() ){
659 cids.push_back( cid );
663 float xyz[3] = {0.0, 0.0, 0.0};
664 processOpHitsFlash( ophits,
665 m_multiplicity_left, m_multiplicity_right,
666 m_sum_pe_left, m_sum_pe_right, xyz, fOpHitFlashTrees[iFlashLabel] );
678 m_multiplicity = m_multiplicity_left+m_multiplicity_right;
682 m_flash_y = flash.YCenter();
683 m_flash_width_y = flash.YWidth();
684 m_flash_z = flash.ZCenter();
685 m_flash_width_z = flash.ZWidth();
687 fOpFlashTrees[iFlashLabel]->Fill();
694 for(
unsigned int cid=0; cid<
fGeom->Ncryostats(); cid++ ){
696 auto const found = std::find( cids.begin(), cids.end(), cid );
697 if( found == cids.end() ){
698 processOpHits(e, cid);
705 mf::LogError(
"ICARUSFlashAssAna")
706 <<
"No recob::OpFlash labels selected\n";
709 for(
unsigned int cid=0; cid<
fGeom->Ncryostats(); cid++ ){
710 processOpHits(e, cid);
std::vector< TTree * > fOpFlashTrees
static std::string_view firstLine(std::string const &s, const char *endl="\r")
Utilities related to art service access.
ICARUSFlashAssAna & operator=(ICARUSFlashAssAna const &)=delete
process_name opflash particleana ie x
std::vector< TTree * > fOpDetWaveformTrees
T::provider_type const * providerFrom()
Returns a constant pointer to the provider of specified service.
void processOpHitsFlash(std::vector< art::Ptr< recob::OpHit >> const &ophits, int &multiplicity_left, int &multiplicity_right, float &sum_pe_left, float &sum_pe_right, float *xyz, TTree *ophittree)
std::vector< art::InputTag > fOpDetWaveformLabels
ICARUSFlashAssAna(Parameters const &config)
fhicl::Atom< float > PEOpHitThreshold
CryostatID_t Cryostat
Index of cryostat.
uint64_t m_gate_start_timestamp
fhicl::Atom< art::InputTag > TriggerLabel
geo::CryostatID::CryostatID_t getCryostatByChannel(int channel)
int getSideByChannel(const int channel)
std::vector< float > m_pmt_x
std::string bitName(triggerSource bit)
Returns a mnemonic short name of the beam type.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
process_name opflash particleana ie ie y
fhicl::Sequence< art::InputTag > OpDetWaveformLabels
fhicl::Sequence< art::InputTag > FlashLabels
BEGIN_PROLOG vertical distance to the surface Name
Description of geometry of one entire detector.
art::InputTag fTriggerLabel
T Median(std::vector< T > data) const
geo::GeometryCore const * fGeom
art::EDAnalyzer::Table< Config > Parameters
unsigned int CryostatID_t
Type for the ID number.
std::vector< TTree * > fOpHitFlashTrees
BEGIN_PROLOG opflashCryoW opflashCryoW triggerfilterBNB triggerfilterNuMI triggerfilterOffbeamBNB triggerfilterOffbeamNuMI triggerfilterUnknown roifinder roifinder2d gaushitTPCEE gaushitTPCWE purityana1 ophit
fhicl::Sequence< art::InputTag > OpHitLabels
void analyze(art::Event const &e) override
uint64_t m_trigger_gate_diff
then echo File list $list not found else cat $list while read file do echo $file sed s
std::vector< TTree * > fOpHitTrees
uint64_t m_trigger_timestamp
fhicl::Atom< bool > Debug
std::vector< float > m_pmt_z
triggerSource
Type of beam or beam gate or other trigger source.
geo::OpDetID const & ID() const
Returns the geometry ID of this optical detector.
std::vector< art::InputTag > fFlashLabels
art::ServiceHandle< art::TFileService > tfs
fhicl::Atom< bool > DumpWaveformsInfo
std::vector< float > m_pmt_y
std::vector< art::InputTag > fOpHitLabels
art framework interface to geometry description
void processOpHits(art::Event const &e, unsigned int cryo)