50 auto result = std::make_unique<std::vector<sim::MCShower>>();
55 mcshower.reserve(shower_index_v.size());
56 std::vector<size_t> mcs_to_spart_v;
57 mcs_to_spart_v.reserve(shower_index_v.size());
59 bool daughter_stored=
false;
60 for(
size_t shower_index = 0; shower_index < shower_index_v.size(); ++shower_index) {
62 unsigned int shower_candidate = shower_index_v.at(shower_index);
63 auto const& shower_part = part_v.at(shower_candidate);
65 unsigned int mother_track = part_v.MotherTrackID(shower_candidate);
66 unsigned int ancestor_track = part_v.AncestorTrackID(shower_candidate);
70 throw cet::exception(__FUNCTION__) <<
"LOGIC ERROR: mother/ancestor track ID is invalid!";
72 MCMiniPart mother_part;
73 MCMiniPart ancestor_part;
75 unsigned int mother_index = part_v.TrackToParticleIndex(mother_track);
76 unsigned int ancestor_index = part_v.TrackToParticleIndex(ancestor_track);
78 if(mother_index !=
kINVALID_UINT) mother_part = part_v[mother_index];
79 else mother_part._track_id = mother_track;
81 if(ancestor_index !=
kINVALID_UINT) ancestor_part = part_v[ancestor_index];
82 else ancestor_part._track_id = ancestor_track;
84 double shower_g4_energy = shower_part._start_mom[3];
88 std::cout <<
"Found MCShower with mother energy: " << shower_g4_energy <<
" MeV";
93 std::cout <<
" ... below energy threshold: skipping!"<<
std::endl;
97 std::cout <<
" ... below # daughter particle count threshold: skipping!"<<
std::endl;
100 std::cout <<
" ... condition matched. Storing this MCShower..."<<
std::endl;
104 mcs_to_spart_v.push_back(shower_index);
108 std::cout <<
" Storage index " << mcshower.size() <<
" => Shower index " << shower_index
113 shower_prof.
Origin ( shower_part._origin );
114 shower_prof.
PdgCode ( shower_part._pdgcode );
115 shower_prof.
TrackID ( shower_part._track_id );
116 shower_prof.
Process ( shower_part._process );
126 shower_prof.
Start ( MCStep ( shower_part._start_vtx, shower_part._start_mom ) );
127 shower_prof.
End ( MCStep ( shower_part._end_vtx, shower_part._end_mom ) );
128 shower_prof.
MotherStart ( MCStep ( mother_part._start_vtx, mother_part._start_mom ) );
129 shower_prof.
MotherEnd ( MCStep ( mother_part._end_vtx, mother_part._end_mom ) );
130 shower_prof.
AncestorStart ( MCStep ( ancestor_part._start_vtx, ancestor_part._start_mom ) );
131 shower_prof.
AncestorEnd ( MCStep ( ancestor_part._end_vtx, ancestor_part._end_mom ) );
134 std::vector<unsigned int> daughter_track_id;
139 daughter_track_id.push_back( part_v.at(
index)._track_id );
143 if(!daughter_stored && daughter_track_id.size()>1) daughter_stored=
true;
145 mcshower.push_back(shower_prof);
149 std::cout <<
" Found " << mcshower.size() <<
" MCShowers. Now computing DetProfile position..." <<
std::endl;
154 std::vector<TLorentzVector> mcs_daughter_vtx_v(mcshower.size(),TLorentzVector(
sim::kINVALID_DOUBLE,
158 std::vector<TLorentzVector> mcs_daughter_mom_v ( mcshower.size(), TLorentzVector() );
160 std::vector< std::vector<double> > plane_charge_v ( mcshower.size(), std::vector<double>(3,0) );
161 std::vector< std::vector<double> > plane_dqdx_v ( mcshower.size(), std::vector<double>(3,0) );
164 std::vector<double> mcs_daughter_dedx_v ( mcshower.size(), 0 );
165 std::vector<double> mcs_daughter_dedxRAD_v ( mcshower.size(), 0 );
166 std::vector<TVector3> mcs_daughter_dir_v ( mcshower.size(), TVector3() );
168 for(
size_t mcs_index=0; mcs_index<mcshower.size(); ++mcs_index) {
170 auto& mcs_daughter_vtx = mcs_daughter_vtx_v[mcs_index];
171 auto& mcs_daughter_mom = mcs_daughter_mom_v[mcs_index];
172 auto& mcs_daughter_dedx = mcs_daughter_dedx_v[mcs_index];
173 auto& mcs_daughter_dedxRAD = mcs_daughter_dedxRAD_v[mcs_index];
174 auto& mcs_daughter_dir = mcs_daughter_dir_v[mcs_index];
175 auto& plane_charge = plane_charge_v[mcs_index];
176 auto& plane_dqdx = plane_dqdx_v[mcs_index];
178 for(
auto const& daughter_trk_id : mcshower[mcs_index].DaughterTrackID()) {
180 auto const daughter_part_index = part_v.TrackToParticleIndex(daughter_trk_id);
182 auto const& daughter_part = part_v[daughter_part_index];
184 auto const daughter_edep_index = edep_v.TrackToEdepIndex(daughter_trk_id);
186 if(daughter_edep_index<0)
continue;
188 auto const& daughter_edep = edep_v.GetEdepArrayAt(daughter_edep_index);
190 if(!(daughter_edep.size()))
continue;
194 for(
auto const& edep : daughter_edep) {
196 double dist = sqrt(
pow(edep.pos._x - daughter_part._start_vtx[0],2) +
197 pow(edep.pos._y - daughter_part._start_vtx[1],2) +
198 pow(edep.pos._z - daughter_part._start_vtx[2],2) );
200 if(dist < min_dist) {
202 mcs_daughter_vtx[0] = edep.pos._x;
203 mcs_daughter_vtx[1] = edep.pos._y;
204 mcs_daughter_vtx[2] = edep.pos._z;
205 mcs_daughter_vtx[3] = (dist/100. / 2.998e8)*1.e9 + daughter_part._start_vtx[3];
209 if(!daughter_stored) {
211 std::vector<double> shower_dir(3,0);
212 shower_dir[0] = mcshower[mcs_index].Start().Px();
213 shower_dir[1] = mcshower[mcs_index].Start().Py();
214 shower_dir[2] = mcshower[mcs_index].Start().Pz();
215 double magnitude = 0;
216 for(
size_t i=0; i<3; ++i)
217 magnitude +=
pow(shower_dir[i],2);
219 magnitude = sqrt(magnitude);
221 if(magnitude > 1.
e-10) {
225 for(
auto& v : shower_dir) v /= magnitude;
227 for(
auto const& edep : daughter_edep) {
228 std::vector<double> shower_dep_dir(3,0);
229 shower_dep_dir[0] = edep.pos._x - mcshower[mcs_index].Start().X();
230 shower_dep_dir[1] = edep.pos._y - mcshower[mcs_index].Start().Y();
231 shower_dep_dir[2] = edep.pos._z - mcshower[mcs_index].Start().Z();
233 double dist = sqrt(
pow(shower_dep_dir[0],2) +
pow(shower_dep_dir[1],2) +
pow(shower_dep_dir[2],2) );
234 for(
auto& v : shower_dep_dir) v /=
dist;
236 double angle = acos( shower_dep_dir[0] * shower_dir[0] +
237 shower_dep_dir[1] * shower_dir[1] +
238 shower_dep_dir[2] * shower_dir[2] ) / TMath::Pi() * 180.;
240 if(dist < min_dist && angle < 10) {
243 mcs_daughter_vtx[0] = edep.pos._x;
244 mcs_daughter_vtx[1] = edep.pos._y;
245 mcs_daughter_vtx[2] = edep.pos._z;
246 mcs_daughter_vtx[3] = (dist/100. / 2.998e8)*1.e9 + mcshower[mcs_index].
Start().T();
255 std::vector<double> mom(3,0);
256 for(
auto const& daughter_trk_id : mcshower[mcs_index].DaughterTrackID()) {
263 auto const daughter_edep_index = edep_v.TrackToEdepIndex(daughter_trk_id);
265 if(daughter_edep_index<0)
continue;
267 auto const& daughter_edep = edep_v.GetEdepArrayAt(daughter_edep_index);
269 if(!(daughter_edep.size()))
continue;
272 for(
auto const& edep : daughter_edep) {
275 mom[0] = edep.pos._x - mcs_daughter_vtx[0];
276 mom[1] = edep.pos._y - mcs_daughter_vtx[1];
277 mom[2] = edep.pos._z - mcs_daughter_vtx[2];
280 double magnitude = sqrt(
pow(mom.at(0),2) +
pow(mom.at(1),2) +
pow(mom.at(2),2));
284 for(
auto const& pid_energy : edep.deps) {
286 energy += pid_energy.energy;
290 if(magnitude>1.
e-10) {
291 mom.at(0) = mom.at(0) * energy / magnitude;
292 mom.at(1) = mom.at(1) * energy / magnitude;
293 mom.at(2) = mom.at(2) * energy / magnitude;
294 mcs_daughter_mom[0] += mom.at(0);
295 mcs_daughter_mom[1] += mom.at(1);
296 mcs_daughter_mom[2] += mom.at(2);
301 if(sqrt(
pow( edep.pos._x - mcs_daughter_vtx[0],2) +
302 pow( edep.pos._y - mcs_daughter_vtx[1],2) +
303 pow( edep.pos._z - mcs_daughter_vtx[2],2)) < 2.4 && magnitude>1.e-10){
305 mcs_daughter_dir[0] += mom.at(0);
306 mcs_daughter_dir[1] += mom.at(1);
307 mcs_daughter_dir[2] += mom.at(2);
313 mcs_daughter_dedxRAD +=
E;
315 mcs_daughter_mom[3] +=
energy;
318 auto const pid = edep.pid;
319 auto q_i = pindex.find(
pid);
320 if(q_i != pindex.end())
321 plane_charge[
pid.Plane] += (
double)(edep.deps[pindex[
pid]].charge);
326 mcs_daughter_dedxRAD /= 2.4;
328 for(
auto const& daughter_trk_id : mcshower[mcs_index].DaughterTrackID()) {
335 auto const daughter_edep_index = edep_v.TrackToEdepIndex(daughter_trk_id);
337 if(daughter_edep_index<0)
continue;
339 auto const& daughter_edep = edep_v.GetEdepArrayAt(daughter_edep_index);
341 if(!(daughter_edep.size()))
continue;
343 for(
auto const& edep : daughter_edep) {
355 double p_mag = sqrt(
pow(mcs_daughter_dir[0],2) +
pow(mcs_daughter_dir[1],2) +
pow(mcs_daughter_dir[2],2) );
356 double a = 0,
b = 0,
c = 0,
d = 0;
358 a = mcs_daughter_dir[0]/p_mag;
359 b = mcs_daughter_dir[1]/p_mag;
360 c = mcs_daughter_dir[2]/p_mag;
361 d = -1*(a*mcs_daughter_vtx[0] +
b*mcs_daughter_vtx[1] +
c*mcs_daughter_vtx[2]);
363 else{mcs_daughter_dedx += 0;
continue;}
365 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 &&
366 (a*edep.pos._x +
b*edep.pos._y +
c*edep.pos._z +
d)/sqrt(
pow(a,2) +
pow(
b,2) +
pow(
c,2)) > 0){
371 for(
auto const& pid_energy : edep.deps) {
373 E += pid_energy.energy;
381 mcs_daughter_dedx +=
E;
384 auto const pid = edep.pid;
385 auto q_i = pindex.find(
pid);
386 if(q_i != pindex.end())
387 plane_dqdx[
pid.Plane] += (
double)(edep.deps[pindex[
pid]].charge);
391 mcs_daughter_dedx /= 2.4;
392 plane_dqdx.at(0) /= 2.4;
393 plane_dqdx.at(1) /= 2.4;
394 plane_dqdx.at(2) /= 2.4;
400 std::cout <<
" Found " << mcshower.size() <<
" MCShowers. Now storing..." <<
std::endl;
403 for(
size_t mcs_index=0; mcs_index<mcshower.size(); ++mcs_index) {
405 auto& daughter_vtx = mcs_daughter_vtx_v[mcs_index];
406 auto& daughter_mom = mcs_daughter_mom_v[mcs_index];
407 auto& daughter_dedx = mcs_daughter_dedx_v[mcs_index];
408 auto& daughter_dedxRAD = mcs_daughter_dedxRAD_v[mcs_index];
409 auto& daughter_dir = mcs_daughter_dir_v[mcs_index];
410 auto& plane_charge = plane_charge_v[mcs_index];
411 auto& plane_dqdx = plane_dqdx_v[mcs_index];
413 double magnitude = sqrt(
pow(daughter_mom[0],2)+
pow(daughter_mom[1],2)+
pow(daughter_mom[2],2));
415 if(daughter_mom[3]>1.
e-10) {
416 daughter_mom[0] *= daughter_mom[3]/magnitude;
417 daughter_mom[1] *= daughter_mom[3]/magnitude;
418 daughter_mom[2] *= daughter_mom[3]/magnitude;
420 for(
size_t i=0; i<4; ++i) daughter_mom[i]=0;
422 mcshower.at(mcs_index).DetProfile( MCStep( daughter_vtx, daughter_mom ) );
423 mcshower.at(mcs_index).Charge(plane_charge);
424 mcshower.at(mcs_index).dQdx(plane_dqdx);
425 mcshower.at(mcs_index).dEdx(daughter_dedx);
426 mcshower.at(mcs_index).dEdxRAD(daughter_dedxRAD);
427 mcshower.at(mcs_index).StartDir(daughter_dir);
433 for(
auto const&
prof : mcshower) {
437 << Form(
" Shower particle: PDG=%d : Track ID=%d Start @ (%g,%g,%g,%g) with Momentum (%g,%g,%g,%g)",
442 << Form(
" Mother particle: PDG=%d : Track ID=%d Start @ (%g,%g,%g,%g) with Momentum (%g,%g,%g,%g)",
443 prof.MotherPdgCode(),
prof.MotherTrackID(),
444 prof.MotherStart().X(),
prof.MotherStart().Y(),
prof.MotherStart().Z(),
prof.MotherStart().T(),
445 prof.MotherStart().Px(),
prof.MotherStart().Py(),
prof.MotherStart().Pz(),
prof.MotherStart().E())
447 << Form(
" Ancestor particle: PDG=%d : Track ID=%d Start @ (%g,%g,%g,%g) with Momentum (%g,%g,%g,%g)",
448 prof.AncestorPdgCode(),
prof.AncestorTrackID(),
449 prof.AncestorStart().X(),
prof.AncestorStart().Y(),
prof.AncestorStart().Z(),
prof.AncestorStart().T(),
450 prof.AncestorStart().Px(),
prof.AncestorStart().Py(),
prof.AncestorStart().Pz(),
prof.AncestorStart().E())
452 << Form(
" ... with %zu daughters: Start @ (%g,%g,%g,%g) with Momentum (%g,%g,%g,%g)",
453 prof.DaughterTrackID().size(),
454 prof.DetProfile().X(),
prof.DetProfile().Y(),
prof.DetProfile().Z(),
prof.DetProfile().T(),
455 prof.DetProfile().Px(),
prof.DetProfile().Py(),
prof.DetProfile().Pz(),
prof.DetProfile().E())
457 <<
" Charge per plane: ";
458 size_t const nPlanes =
prof.Charge().size();
459 for(
size_t i=0; i<nPlanes; ++i) {
const double kINVALID_DOUBLE
const MCStep & End() const
unsigned int TrackID() const
const std::vector< unsigned int > ShowerMothers() const
MCShowerRecoPart fPartAlg
std::map< geo::PlaneID, size_t > createPlaneIndexMap()
unsigned int fMinNumDaughters
const std::vector< unsigned int > & DaughterTrackID() const
simb::Origin_t Origin() const
int MotherPdgCode() const
const std::string & AncestorProcess() const
QTextStream & flush(QTextStream &s)
const MCStep & AncestorStart() const
const std::string & MotherProcess() const
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)
const unsigned int kINVALID_UINT
unsigned int MotherTrackID() const
const std::string & Process() const
const MCStep & MotherStart() const
int AncestorPdgCode() const
LArSoft geometry interface.
cet::coded_exception< error, detail::translate > exception
void ConstructShower(const MCRecoPart &part_v)
Main function to read-in data and fill variables in this algorithm to reconstruct MC shower...
QTextStream & endl(QTextStream &s)