20 #include "art_root_io/TFileService.h" 78 size_t FlashMatch (
const double reco_time, std::vector<double> op_times_v);
222 fAnode = fcl.
get<
bool> (
"AnodePiercers" );
240 auto const* geom = lar::providerFrom<geo::Geometry>();
247 for (
geo::TPCID const& tID: geom->IterateTPCIDs()) {
256 double tpc_top = center[1] + TPC.
HalfHeight();
257 double tpc_bottom = center[1] - TPC.
HalfHeight();
258 double tpc_front = center[2] - TPC.
HalfLength();
259 double tpc_back = center[2] + TPC.
HalfLength();
261 if (tpc_top > det_top) det_top = tpc_top;
271 double efield = detp.Efield();
272 std::cout <<
"Nominal electric field is: " << efield*1000 <<
" V/cm" <<
std::endl;
274 double temp = detp.Temperature();
275 std::cout <<
"LAr temperature is: " << temp <<
" K" <<
std::endl;
291 track_tree = tfs->make<TTree>(
"track_tree",
"SCE calibrations variables");
344 flash_tree = tfs->make<TTree>(
"flash_tree",
"Flash properties and reco time differences");
357 ev_tree = tfs->make<TTree>(
"ev_tree",
"Event information");
371 int track_number = 0;
377 double TPC_trigger_offset = 0.0;
379 std::vector<std::vector<TLorentzVector>> mcpart_list;
382 if(
fDebug) std::cout <<
"Set event number: " <<
event <<
"\nTop: " <<
det_top 401 std::cerr<<
"\033[93m[ERROR]\033[00m ... could not locate Flash!"<<
std::endl;
414 if( !trigger_h || trigger_h->empty()) {
419 if(
fDebug) std::cout <<
"Loading trigger time from producer " 422 trigger_time = trigger_h->at(0).Time();
429 if(!reco_particles_h.isValid()) {
430 std::cerr<<
"\033[93m[ERROR]\033[00m ... could not locate PFParticles!"<<
std::endl;
441 auto mcpart_h = evt.
getHandle<std::vector<simb::MCParticle> >(
"largeant");
446 if(!mcpart_h.isValid()) {
447 std::cerr<<
"\033[93m[ERROR]\033[00m ... could not locate MCParticle!"<<
std::endl;
455 TPC_trigger_offset = clockData.TriggerOffsetTPC();
456 if(
fDebug) std::cout <<
"TPC time offset from trigger: " 457 << TPC_trigger_offset <<
" us" <<
std::endl;
462 size_t flash_ctr = 0;
463 for (
auto const& flash : *
flash_h){
464 if (flash.TotalPE() >
fMinPE){
466 if(
fUseMC) op_flash_time = op_flash_time - TPC_trigger_offset;
478 if (
fDebug) std::cout <<
"Output all flashes - closest flash to trigger time is: " 486 for (
auto const& op_hit : *
op_hit_h){
487 int op_hit_channel = op_hit.OpChannel();
501 size_t ev_particle_ctr = 0;
503 for(
unsigned int p = 0;
p < reco_particles_h->size(); ++
p){
515 if(
fDebug) std::cout <<
"\tPFParticle " << ev_particle_ctr <<
" is not track like" <<
std::endl;
518 if (
fDebug) std::cout <<
"\tLooping through reco PFParticle " << ev_particle_ctr <<
std::endl;
558 std::vector<TVector3> sorted_trk;
561 TVector3 track_start = sorted_trk.at(0);
562 TVector3 track_end = sorted_trk.at(sorted_trk.size() - 1);
564 if(
fDebug) std::cout <<
"\t\tTrack goes from (" << track_start.X() <<
", " 565 << track_start.Y() <<
", " << track_start.Z() <<
") --> (" <<
566 track_end.X() <<
", " << track_end.Y() <<
", " << track_end.Z() <<
569 if(sqrt(
pow(track_start.X() - track_end.X(),2.0)
570 +
pow(track_start.Y() - track_end.Y(),2.0)
572 if(
fDebug) std::cout <<
"\t\t\tParticle track too short. Skipping." <<
std::endl;
577 auto const* geom = lar::providerFrom<geo::Geometry>();
578 auto const*
hit = hit_v.at(0);
580 const auto TPCGeoObject = geom->TPC(wireID.
TPC,wireID.
Cryostat);
581 short int driftDir_start = TPCGeoObject.DetectDriftDirection();
582 short int driftDir_end = 0;
584 for (
size_t ii = 1; ii < hit_v.size(); ii++) {
585 const geo::WireID wireID2 = hit_v.at(ii)->WireID();
586 const auto TPCGeoObject2 = geom->TPC(wireID2.
TPC,wireID2.
Cryostat);
587 driftDir_end = TPCGeoObject2.DetectDriftDirection();
589 if(driftDir_end + driftDir_start == 0){
596 int last_mc_point = 0;
603 if(mc_particle==0x0) {
604 if(
fDebug) std::cout <<
"\t\t\tNo MC particle matched to PFParticle " 618 " us is significantly different from start time: " <<
mc_time <<
630 if(t0_v.size() == 0)
continue;
631 auto t0 = t0_v.at(0);
634 if (
fDebug) std::cout <<
"\t\tTrack crossers cathode - PFParticle has t0: " 639 std::vector<TVector3> split_trk = sorted_trk;
642 std::vector<TVector3> top_trk = {split_trk.at(0), split_trk.at(1)};
643 std::vector<TVector3> bottom_trk = {split_trk.at(2), split_trk.at(3)};
645 if(
fDebug) std::cout <<
"\t\tCathode-crossing point: (" 646 << top_trk.at(1).X() <<
", " << top_trk.at(1).Y() <<
", " 647 << top_trk.at(1).Z() <<
") --> (" << bottom_trk.at(0).X()
648 <<
", " << bottom_trk.at(0).Y() <<
", " << bottom_trk.at(0).Z()
655 TVector3 top_track_start = top_trk.at(0);
656 TVector3 top_track_end = top_trk.at(1);
658 rc_xs = top_track_start.X();
660 rc_ys = top_track_start.Y();
661 rc_zs = top_track_start.Z();
662 rc_xe = top_track_end.X();
664 rc_ye = top_track_end.Y();
665 rc_ze = top_track_end.Z();
677 TVector3 bottom_track_start = bottom_trk.at(0);
678 TVector3 bottom_track_end = bottom_trk.at(1);
680 rc_xs = bottom_track_start.X();
682 rc_ys = bottom_track_start.Y();
683 rc_zs = bottom_track_start.Z();
684 rc_xe = bottom_track_end.X();
686 rc_ye = bottom_track_end.Y();
687 rc_ze = bottom_track_end.Z();
696 else if(
fDebug) std::cout <<
"\t\tTrack does not cross cathode."<<
std::endl;
707 rc_xs = track_start.X();
708 rc_ys = track_start.Y();
709 rc_zs = track_start.Z();
710 rc_xe = track_end.X();
711 rc_ye = track_end.Y();
712 rc_ze = track_end.Z();
725 for (
auto& hits : hit_v) {
726 auto hit_tick = hits->PeakTime();
727 double hit_time = clockData.TPCTick2TrigTime(hit_tick);
734 if(
fDebug) std::cout <<
"\tTrack hits edge of readout window. " 755 if(
fDebug) std::cout <<
"\t\tTrack may enter TPC through " 768 if(
fDebug) std::cout <<
"\t\tTrack may exit TPC through " 778 if(
fDebug) std::cout <<
"\t\tTrack does not pierce anode." <<
std::endl;
783 if(
fDebug) std::cout <<
"\t\tTrack neither enters nor exits" 784 " through non-anode TPC face. No useful end point for SCE" 795 if(op_match_result==99999) {
796 if(
fDebug) std::cout <<
"Unable to match flash to track." <<
std::endl;
816 unsigned int max_pe_channel = 9999;
819 for(pd_ch = 0; pd_ch <= geom->MaxOpChannel(); pd_ch++) {
820 double channel_i_pe = flash_ptr->
PE(pd_ch);
821 if(channel_i_pe > max_pe) {
822 max_pe = channel_i_pe;
823 max_pe_channel = pd_ch;
827 if(max_pe_channel==9999||max_pe==0)
continue;
829 if(max_pe_channel<9999) {
843 if(
fDebug) std::cout <<
"\t\tOpChannel " << max_pe_channel <<
844 " has maximum PE, and is located at: (" <<
850 if(
fDebug) std::cout <<
"\t\t Matched to flash w/ index " << op_match_result <<
" w/ PE " 852 " us vs corrected reco time " << anode_rc_time <<
" us" <<
std::endl;
863 if(
fDebug) std::cout <<
"\t\t Matched to op hit w/ index " << op_match_result <<
881 for(
int mc_hit_i=0; mc_hit_i<last_mc_point; mc_hit_i++) {
883 double mc_particle_xi = mc_particle->
Position(mc_hit_i).X();
884 double mc_particle_yi = mc_particle->
Position(mc_hit_i).Y();
885 double mc_particle_zi = mc_particle->
Position(mc_hit_i).Z();
902 std::cout <<
"\t\tMC Particle matched to track has t0: " 903 <<
mc_time <<
" us against reconstructed t0: " 915 unsigned int pIndex = particle.
Self();
917 std::vector<anab::T0> t0_apt_v;
919 const art::FindManyP<anab::T0> findParticleT0s(reco_particles_h,evt,
fAnodeT0Producer);
921 for(
unsigned int p = 0;
p < findParticleT0s.at(pIndex).size(); ++
p){
922 t0_apt_v.push_back((*(findParticleT0s.at(pIndex)[
p])));
925 if(t0_apt_v.size() != 0) HasT0 =
true;
928 auto t0_apt = t0_apt_v.at(0);
930 std::cout <<
"PFParticle has T0: " << (t0_apt.Time()/1000) <<
932 " us with dt_flash_reco " <<
dt_flash_reco <<
" us." << std::endl;
940 if(anode_rc_time < fReadoutWindow && cathode_rc_time > -
fReadoutWindow)
957 TVector3 track_start, track_end;
964 if ((trk_loc.X() < -998.)||(trk_loc.Y() < -998.)||(trk_loc.Z() < -998))
continue;
966 if (trk_loc.Y() < end_y){
968 track_end = {trk_loc.X(), trk_loc.Y(), trk_loc.Z()};
970 if (trk_loc.Y() > start_y){
971 start_y = trk_loc.Y();
972 track_start = {trk_loc.X(), trk_loc.Y(), trk_loc.Z()};
976 sorted_trk.push_back(track_start);
977 sorted_trk.push_back(track_end);
984 TVector3 track_neg, track_neg_c, track_pos_c,track_pos;
993 if ((trk_loc.X() < -998.)||(trk_loc.Y() < -998.)||(trk_loc.Z() < -998))
continue;
995 if (trk_loc.X() < neg_x){
997 track_neg = {trk_loc.X(), trk_loc.Y(), trk_loc.Z()};
999 if (trk_loc.X() > pos_x){
1000 pos_x = trk_loc.X();
1001 track_pos = {trk_loc.X(), trk_loc.Y(), trk_loc.Z()};
1003 if ((trk_loc.X() < 0.0) && (trk_loc.X() > neg_c)){
1004 neg_c = trk_loc.X();
1005 track_neg_c = {trk_loc.X(), trk_loc.Y(), trk_loc.Z()};
1007 if ((trk_loc.X() > 0.0) && (trk_loc.X() < pos_c)){
1008 pos_c = trk_loc.X();
1009 track_pos_c = {trk_loc.X(), trk_loc.Y(), trk_loc.Z()};
1013 if( track_neg.Y() > track_pos.Y()){
1014 split_trk.push_back(track_neg);
1015 split_trk.push_back(track_neg_c);
1016 split_trk.push_back(track_pos_c);
1017 split_trk.push_back(track_pos);
1019 split_trk.push_back(track_pos);
1020 split_trk.push_back(track_pos_c);
1021 split_trk.push_back(track_neg_c);
1022 split_trk.push_back(track_neg);
1031 double dt_min = 9999999.;
1032 size_t matched_op_id = 99999;
1044 for (
size_t i=0; i < op_times_v.size(); i++){
1045 double op_time_i = op_times_v[i];
1067 return matched_op_id;
code to link reconstructed objects back to the MC truth information
double matched_flash_max_pe_det_y
unsigned int NumberTrajectoryPoints() const
const TLorentzVector & Position(const int i=0) const
EventNumber_t event() const
bool TPC_entering_candidate
std::vector< anab::T0 > GetPFParticleT0(const recob::PFParticle &particle, art::Event const &evt, std::string particleLabel) const
Get the T0(s) from a given PFParticle.
double matched_flash_width_y
size_t Self() const
Returns the index of this particle.
double matched_flash_max_pe_det_x
Handle< PROD > getHandle(SelectorBase const &) const
std::vector< size_t > op_id_v
double matched_flash_max_pe_det_z
art::Handle< std::vector< recob::OpHit > > op_hit_h
double corrected_flash_time
double mc_particle_z_anode
Point_t const & LocationAtPoint(size_t i) const
Geometry information for a single TPC.
size_t NumberTrajectoryPoints() const
Various functions related to the presence and the number of (valid) points.
unsigned int fReadoutWindow
void SortTrackPoints(const recob::Track &track, std::vector< TVector3 > &sorted_trk)
CryostatID_t Cryostat
Index of cryostat.
double matched_flash_time_width
std::string fAnodeT0Producer
double PE(unsigned int i) const
double HalfLength() const
Length is associated with z coordinate [cm].
EDAnalyzer(fhicl::ParameterSet const &pset)
bool cathode_crossing_track
std::vector< size_t > flash_id_v
std::vector< double > op_times
art framework interface to geometry description
std::string fTriggerProducer
timescale_traits< TriggerTimeCategory >::time_point_t trigger_time
A point in time on the trigger time scale.
void analyze(art::Event const &evt) override
double Length(size_t p=0) const
Access to various track properties.
#define DEFINE_ART_MODULE(klass)
double flash_reco_time_diff
T get(std::string const &key) const
const recob::Track * GetPFParticleTrack(const recob::PFParticle &particle, art::Event const &evt, const std::string particleLabel, const std::string trackLabel) const
Get the track associated to this particle. Returns a null pointer if not found.
double T(const int i=0) const
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
double mc_particle_x_anode
T0RecoSCE & operator=(T0RecoSCE const &)=delete
const simb::MCParticle * GetMCParticleFromRecoTrack(detinfo::DetectorClocksData const &clockData, const recob::Track &track, art::Event const &evt, std::string trackModule) const
bool IsPrimary() const
Returns whether the particle is the root of the flow.
The data type to uniquely identify a TPC.
Class def header for mctrack data container.
bool anode_piercing_candidate
bool TPC_exiting_candidate
double matched_flash_centre_y
double corrected_matched_flash_time
std::string fFlashProducer
Detector simulation of raw signals on wires.
double mc_particle_y_anode
double HalfHeight() const
Height is associated with y coordinate [cm].
const std::vector< const recob::Hit * > GetRecoTrackHits(const recob::Track &track, art::Event const &evt, const std::string trackModule) const
Get the hits from a given reco track.
Declaration of signal hit object.
double DriftDistance() const
Hierarchical representation of particle flow.
art::Handle< std::vector< recob::OpFlash > > flash_h
std::string fTrackProducer
T0RecoSCE(fhicl::ParameterSet const &p)
std::string fOpHitProducer
Provides recob::Track data product.
size_t FlashMatch(const double reco_time, std::vector< double > op_times_v)
double matched_flash_width_z
constexpr WireID()=default
Default constructor: an invalid TPC ID.
TPCID_t TPC
Index of the TPC within its cryostat.
double matched_flash_time
double matched_flash_centre_z
void LocalToWorld(const double *tpc, double *world) const
Transform point from local TPC frame to world frame.
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
constexpr Point origin()
Returns a origin position with a point of the specified type.
cet::coded_exception< error, detail::translate > exception
void SplitTrack(const recob::Track &track, std::vector< TVector3 > &sorted_trk)
QTextStream & endl(QTextStream &s)
Event finding and building.