10 #include "RtypesCore.h"
11 #include "TLorentzVector.h"
16 #include "art/Framework/Services/Registry/ServiceHandle.h"
17 #include "canvas/Utilities/Exception.h"
18 #include "fhiclcpp/ParameterSet.h"
36 : fPartAlg(pset.
get<fhicl::ParameterSet>(
"MCShowerRecoPart")),
37 fDebugMode(pset.
get<
bool>(
"DebugMode")),
38 fMinShowerEnergy(pset.
get<double>(
"MinShowerEnergy")),
39 fMinNumDaughters(pset.
get<unsigned int>(
"MinNumDaughters"))
44 std::unique_ptr<std::vector<sim::MCShower>>
49 art::ServiceHandle<geo::Geometry const> geo;
54 auto result = std::make_unique<std::vector<sim::MCShower>>();
55 auto& mcshower = *result;
59 mcshower.reserve(shower_index_v.size());
60 std::vector<size_t> mcs_to_spart_v;
61 mcs_to_spart_v.reserve(shower_index_v.size());
63 bool daughter_stored=
false;
64 for(
size_t shower_index = 0; shower_index < shower_index_v.size(); ++shower_index) {
66 unsigned int shower_candidate = shower_index_v.at(shower_index);
67 auto const& shower_part = part_v.at(shower_candidate);
69 unsigned int mother_track = part_v.
MotherTrackID(shower_candidate);
74 throw cet::exception(__FUNCTION__) <<
"LOGIC ERROR: mother/ancestor track ID is invalid!";
82 if(mother_index !=
kINVALID_UINT) mother_part = part_v[mother_index];
83 else mother_part.
_track_id = mother_track;
85 if(ancestor_index !=
kINVALID_UINT) ancestor_part = part_v[ancestor_index];
86 else ancestor_part.
_track_id = ancestor_track;
88 double shower_g4_energy = shower_part._start_mom[3];
92 std::cout <<
"Found MCShower with mother energy: " << shower_g4_energy <<
" MeV";
97 std::cout <<
" ... below energy threshold: skipping!"<<std::endl;
102 std::cout <<
" ... below # daughter particle count threshold: skipping!"<<std::endl;
106 std::cout <<
" ... condition matched. Storing this MCShower..."<<std::endl;
110 mcs_to_spart_v.push_back(shower_index);
114 std::cout <<
" Storage index " << mcshower.size() <<
" => Shower index " << shower_index
119 shower_prof.
Origin ( shower_part._origin );
120 shower_prof.
PdgCode ( shower_part._pdgcode );
121 shower_prof.
TrackID ( shower_part._track_id );
122 shower_prof.
Process ( shower_part._process );
132 shower_prof.
Start (
MCStep ( shower_part._start_vtx, shower_part._start_mom ) );
133 shower_prof.
End (
MCStep ( shower_part._end_vtx, shower_part._end_mom ) );
140 std::vector<unsigned int> daughter_track_id;
145 daughter_track_id.push_back( part_v.at(index)._track_id );
149 if(!daughter_stored && daughter_track_id.size()>1) daughter_stored=
true;
151 mcshower.push_back(shower_prof);
155 std::cout <<
" Found " << mcshower.size() <<
" MCShowers. Now computing DetProfile position..." << std::endl;
161 std::vector<TLorentzVector> mcs_daughter_vtx_v(mcshower.size(),TLorentzVector(
sim::kINVALID_DOUBLE,
165 std::vector<TLorentzVector> mcs_daughter_mom_v ( mcshower.size(), TLorentzVector() );
167 std::vector< std::vector<double> > plane_charge_v ( mcshower.size(), std::vector<double>(3,0) );
168 std::vector< std::vector<double> > plane_dqdx_v ( mcshower.size(), std::vector<double>(3,0) );
171 std::vector<double> mcs_daughter_dedx_v ( mcshower.size(), 0 );
172 std::vector<double> mcs_daughter_dedxRAD_v ( mcshower.size(), 0 );
173 std::vector<TVector3> mcs_daughter_dir_v ( mcshower.size(), TVector3() );
175 for(
size_t mcs_index=0; mcs_index<mcshower.size(); ++mcs_index) {
177 auto& mcs_daughter_vtx = mcs_daughter_vtx_v[mcs_index];
178 auto& mcs_daughter_mom = mcs_daughter_mom_v[mcs_index];
179 auto& mcs_daughter_dedx = mcs_daughter_dedx_v[mcs_index];
180 auto& mcs_daughter_dedxRAD = mcs_daughter_dedxRAD_v[mcs_index];
181 auto& mcs_daughter_dir = mcs_daughter_dir_v[mcs_index];
182 auto& plane_charge = plane_charge_v[mcs_index];
183 auto& plane_dqdx = plane_dqdx_v[mcs_index];
185 for(
auto const& daughter_trk_id : mcshower[mcs_index].DaughterTrackID()) {
189 auto const& daughter_part = part_v[daughter_part_index];
193 if(daughter_edep_index<0)
continue;
195 auto const& daughter_edep = edep_v.
GetEdepArrayAt(daughter_edep_index);
197 if(!(daughter_edep.size()))
continue;
201 for(
auto const& edep : daughter_edep) {
203 double dist = sqrt( pow(edep.pos._x - daughter_part._start_vtx[0],2) +
204 pow(edep.pos._y - daughter_part._start_vtx[1],2) +
205 pow(edep.pos._z - daughter_part._start_vtx[2],2) );
207 if(dist < min_dist) {
209 mcs_daughter_vtx[0] = edep.pos._x;
210 mcs_daughter_vtx[1] = edep.pos._y;
211 mcs_daughter_vtx[2] = edep.pos._z;
212 mcs_daughter_vtx[3] = (dist/100. / 2.998e8)*1.e9 + daughter_part._start_vtx[3];
216 if(!daughter_stored) {
218 std::vector<double> shower_dir(3,0);
219 shower_dir[0] = mcshower[mcs_index].Start().Px();
220 shower_dir[1] = mcshower[mcs_index].Start().Py();
221 shower_dir[2] = mcshower[mcs_index].Start().Pz();
222 double magnitude = 0;
223 for(
size_t i=0; i<3; ++i)
224 magnitude += pow(shower_dir[i],2);
226 magnitude = sqrt(magnitude);
228 if(magnitude > 1.
e-10) {
232 for(
auto& v : shower_dir) v /= magnitude;
234 for(
auto const& edep : daughter_edep) {
235 std::vector<double> shower_dep_dir(3,0);
236 shower_dep_dir[0] = edep.pos._x - mcshower[mcs_index].Start().X();
237 shower_dep_dir[1] = edep.pos._y - mcshower[mcs_index].Start().Y();
238 shower_dep_dir[2] = edep.pos._z - mcshower[mcs_index].Start().Z();
240 double dist = sqrt( pow(shower_dep_dir[0],2) + pow(shower_dep_dir[1],2) + pow(shower_dep_dir[2],2) );
241 for(
auto& v : shower_dep_dir) v /=
dist;
243 double angle = acos( shower_dep_dir[0] * shower_dir[0] +
244 shower_dep_dir[1] * shower_dir[1] +
245 shower_dep_dir[2] * shower_dir[2] ) / TMath::Pi() * 180.;
247 if(dist < min_dist && angle < 10) {
250 mcs_daughter_vtx[0] = edep.pos._x;
251 mcs_daughter_vtx[1] = edep.pos._y;
252 mcs_daughter_vtx[2] = edep.pos._z;
253 mcs_daughter_vtx[3] = (dist/100. / 2.998e8)*1.e9 + mcshower[mcs_index].Start().T();
262 std::vector<double> mom(3,0);
263 for(
auto const& daughter_trk_id : mcshower[mcs_index].DaughterTrackID()) {
272 if(daughter_edep_index<0)
continue;
274 auto const& daughter_edep = edep_v.
GetEdepArrayAt(daughter_edep_index);
276 if(!(daughter_edep.size()))
continue;
279 for(
auto const& edep : daughter_edep) {
282 mom[0] = edep.pos._x - mcs_daughter_vtx[0];
283 mom[1] = edep.pos._y - mcs_daughter_vtx[1];
284 mom[2] = edep.pos._z - mcs_daughter_vtx[2];
287 double magnitude = sqrt(pow(mom.at(0),2) + pow(mom.at(1),2) + pow(mom.at(2),2));
291 for(
auto const& pid_energy : edep.deps) {
293 energy += pid_energy.energy;
297 if(magnitude>1.
e-10) {
298 mom.at(0) = mom.at(0) * energy / magnitude;
299 mom.at(1) = mom.at(1) * energy / magnitude;
300 mom.at(2) = mom.at(2) * energy / magnitude;
301 mcs_daughter_mom[0] += mom.at(0);
302 mcs_daughter_mom[1] += mom.at(1);
303 mcs_daughter_mom[2] += mom.at(2);
308 if(sqrt( pow( edep.pos._x - mcs_daughter_vtx[0],2) +
309 pow( edep.pos._y - mcs_daughter_vtx[1],2) +
310 pow( edep.pos._z - mcs_daughter_vtx[2],2)) < 2.4 && magnitude>1.e-10){
312 mcs_daughter_dir[0] += mom.at(0);
313 mcs_daughter_dir[1] += mom.at(1);
314 mcs_daughter_dir[2] += mom.at(2);
320 mcs_daughter_dedxRAD +=
E;
322 mcs_daughter_mom[3] += energy;
325 auto const pid = edep.pid;
326 auto q_i = pindex.find(pid);
327 if(q_i != pindex.end())
328 plane_charge[pid.Plane] += (
double)(edep.deps[pindex[pid]].charge);
333 mcs_daughter_dedxRAD /= 2.4;
335 for(
auto const& daughter_trk_id : mcshower[mcs_index].DaughterTrackID()) {
344 if(daughter_edep_index<0)
continue;
346 auto const& daughter_edep = edep_v.
GetEdepArrayAt(daughter_edep_index);
348 if(!(daughter_edep.size()))
continue;
350 for(
auto const& edep : daughter_edep) {
362 double p_mag = sqrt( pow(mcs_daughter_dir[0],2) + pow(mcs_daughter_dir[1],2) + pow(mcs_daughter_dir[2],2) );
363 double a = 0, b = 0, c = 0, d = 0;
365 a = mcs_daughter_dir[0]/p_mag;
366 b = mcs_daughter_dir[1]/p_mag;
367 c = mcs_daughter_dir[2]/p_mag;
368 d = -1*(a*mcs_daughter_vtx[0] + b*mcs_daughter_vtx[1] + c*mcs_daughter_vtx[2]);
370 else{mcs_daughter_dedx += 0;
continue;}
372 if( (a*edep.pos._x + b*edep.pos._y + c*edep.pos._z + d)/sqrt( pow(a,2) + pow(b,2) + pow(c,2)) < 2.4 &&
373 (a*edep.pos._x + b*edep.pos._y + c*edep.pos._z + d)/sqrt( pow(a,2) + pow(b,2) + pow(c,2)) > 0){
378 for(
auto const& pid_energy : edep.deps) {
380 E += pid_energy.energy;
388 mcs_daughter_dedx +=
E;
391 auto const pid = edep.pid;
392 auto q_i = pindex.find(pid);
393 if(q_i != pindex.end())
394 plane_dqdx[pid.Plane] += (
double)(edep.deps[pindex[pid]].charge);
398 mcs_daughter_dedx /= 2.4;
399 plane_dqdx.at(0) /= 2.4;
400 plane_dqdx.at(1) /= 2.4;
401 plane_dqdx.at(2) /= 2.4;
407 std::cout <<
" Found " << mcshower.size() <<
" MCShowers. Now storing..." << std::endl;
410 for(
size_t mcs_index=0; mcs_index<mcshower.size(); ++mcs_index) {
412 auto& daughter_vtx = mcs_daughter_vtx_v[mcs_index];
413 auto& daughter_mom = mcs_daughter_mom_v[mcs_index];
414 auto& daughter_dedx = mcs_daughter_dedx_v[mcs_index];
415 auto& daughter_dedxRAD = mcs_daughter_dedxRAD_v[mcs_index];
416 auto& daughter_dir = mcs_daughter_dir_v[mcs_index];
417 auto& plane_charge = plane_charge_v[mcs_index];
418 auto& plane_dqdx = plane_dqdx_v[mcs_index];
420 double magnitude = sqrt(pow(daughter_mom[0],2)+pow(daughter_mom[1],2)+pow(daughter_mom[2],2));
422 if(daughter_mom[3]>1.
e-10) {
423 daughter_mom[0] *= daughter_mom[3]/magnitude;
424 daughter_mom[1] *= daughter_mom[3]/magnitude;
425 daughter_mom[2] *= daughter_mom[3]/magnitude;
427 for(
size_t i=0; i<4; ++i) daughter_mom[i]=0;
429 mcshower.at(mcs_index).DetProfile(
MCStep( daughter_vtx, daughter_mom ) );
430 mcshower.at(mcs_index).Charge(plane_charge);
431 mcshower.at(mcs_index).dQdx(plane_dqdx);
432 mcshower.at(mcs_index).dEdx(daughter_dedx);
433 mcshower.at(mcs_index).dEdxRAD(daughter_dedxRAD);
434 mcshower.at(mcs_index).StartDir(daughter_dir);
440 for(
auto const&
prof : mcshower) {
444 << Form(
" Shower particle: PDG=%d : Track ID=%d Start @ (%g,%g,%g,%g) with Momentum (%g,%g,%g,%g)",
449 << Form(
" Mother particle: PDG=%d : Track ID=%d Start @ (%g,%g,%g,%g) with Momentum (%g,%g,%g,%g)",
450 prof.MotherPdgCode(),
prof.MotherTrackID(),
451 prof.MotherStart().X(),
prof.MotherStart().Y(),
prof.MotherStart().Z(),
prof.MotherStart().T(),
452 prof.MotherStart().Px(),
prof.MotherStart().Py(),
prof.MotherStart().Pz(),
prof.MotherStart().E())
454 << Form(
" Ancestor particle: PDG=%d : Track ID=%d Start @ (%g,%g,%g,%g) with Momentum (%g,%g,%g,%g)",
455 prof.AncestorPdgCode(),
prof.AncestorTrackID(),
456 prof.AncestorStart().X(),
prof.AncestorStart().Y(),
prof.AncestorStart().Z(),
prof.AncestorStart().T(),
457 prof.AncestorStart().Px(),
prof.AncestorStart().Py(),
prof.AncestorStart().Pz(),
prof.AncestorStart().E())
459 << Form(
" ... with %zu daughters: Start @ (%g,%g,%g,%g) with Momentum (%g,%g,%g,%g)",
460 prof.DaughterTrackID().size(),
461 prof.DetProfile().X(),
prof.DetProfile().Y(),
prof.DetProfile().Z(),
prof.DetProfile().T(),
462 prof.DetProfile().Px(),
prof.DetProfile().Py(),
prof.DetProfile().Pz(),
prof.DetProfile().E())
464 <<
" Charge per plane: ";
465 size_t const nPlanes =
prof.Charge().size();
466 for(
size_t i=0; i<nPlanes; ++i) {
468 std::cout <<
" | Plane " << i << std::flush;
const double kINVALID_DOUBLE
const MCStep & End() const
unsigned int TrackID() const
MCShowerRecoAlg(fhicl::ParameterSet const &pset)
Default constructor with fhicl parameters.
const std::vector< unsigned int > ShowerMothers() const
MCShowerRecoPart fPartAlg
std::unique_ptr< std::vector< sim::MCShower > > Reconstruct(MCRecoPart &part_v, MCRecoEdep &edep_v)
std::map< geo::PlaneID, size_t > createPlaneIndexMap()
unsigned int MotherTrackID(const unsigned int part_index) const
const std::vector< sim::MCEdep > & GetEdepArrayAt(size_t edep_index) const
Returns a vector of MCEdep object at the given index.
TLorentzVector _start_vtx
Class def header for mcstep data container.
unsigned int fMinNumDaughters
TLorentzVector _start_mom
const std::vector< unsigned int > & DaughterTrackID() const
unsigned int AncestorTrackID(const unsigned int part_index)
simb::Origin_t Origin() const
int TrackToEdepIndex(unsigned int track_id) const
Converts a track ID to MCEdep array index. Returns -1 if no corresponding array found ...
int MotherPdgCode() const
const std::string & AncestorProcess() const
const MCStep & AncestorStart() const
const std::string & MotherProcess() const
Definition of data types for geometry description.
const std::vector< unsigned int > & ShowerDaughters(const unsigned int shower_id) const
unsigned int AncestorTrackID() const
const MCStep & AncestorEnd() const
const MCStep & Start() const
const MCStep & MotherEnd() const
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
process_name largeant stream1 can override from command line with o or output physics producers generator N
Class def header for MCShower data container.
const unsigned int kINVALID_UINT
unsigned int MotherTrackID() const
const std::string & Process() const
const MCStep & MotherStart() const
finds tracks best matching by angle
int AncestorPdgCode() const
unsigned int TrackToParticleIndex(const unsigned int track_id) const
art framework interface to geometry description
BEGIN_PROLOG could also be cout
void ConstructShower(const MCRecoPart &part_v)
Main function to read-in data and fill variables in this algorithm to reconstruct MC shower...