16 : fPartAlg(pset.get<
fhicl::ParameterSet>(
"MCShowerRecoPart")),
17 fDebugMode(pset.get<bool>(
"DebugMode")),
18 fMinShowerEnergy(pset.get<double>(
"MinShowerEnergy")),
19 fMinNumDaughters(pset.get<unsigned int>(
"MinNumDaughters"))
24 std::unique_ptr<std::vector<sim::MCShower>>
34 auto result = std::make_unique<std::vector<sim::MCShower>>();
35 auto& mcshower = *result;
39 mcshower.reserve(shower_index_v.size());
40 std::vector<size_t> mcs_to_spart_v;
41 mcs_to_spart_v.reserve(shower_index_v.size());
43 bool daughter_stored=
false;
44 for(
size_t shower_index = 0; shower_index < shower_index_v.size(); ++shower_index) {
46 unsigned int shower_candidate = shower_index_v.at(shower_index);
47 auto const& shower_part = part_v.at(shower_candidate);
49 unsigned int mother_track = part_v.
MotherTrackID(shower_candidate);
54 throw cet::exception(__FUNCTION__) <<
"LOGIC ERROR: mother/ancestor track ID is invalid!";
62 if(mother_index !=
kINVALID_UINT) mother_part = part_v[mother_index];
63 else mother_part.
_track_id = mother_track;
65 if(ancestor_index !=
kINVALID_UINT) ancestor_part = part_v[ancestor_index];
66 else ancestor_part.
_track_id = ancestor_track;
68 double shower_g4_energy = shower_part._start_mom[3];
72 std::cout <<
"Found MCShower with mother energy: " << shower_g4_energy <<
" MeV";
77 std::cout <<
" ... below energy threshold: skipping!"<<std::endl;
81 std::cout <<
" ... below # daughter particle count threshold: skipping!"<<std::endl;
84 std::cout <<
" ... condition matched. Storing this MCShower..."<<std::endl;
88 mcs_to_spart_v.push_back(shower_index);
92 std::cout <<
" Storage index " << mcshower.size() <<
" => Shower index " << shower_index
97 shower_prof.
Origin ( shower_part._origin );
98 shower_prof.
PdgCode ( shower_part._pdgcode );
99 shower_prof.
TrackID ( shower_part._track_id );
100 shower_prof.
Process ( shower_part._process );
110 shower_prof.
Start (
MCStep ( shower_part._start_vtx, shower_part._start_mom ) );
111 shower_prof.
End (
MCStep ( shower_part._end_vtx, shower_part._end_mom ) );
118 std::vector<unsigned int> daughter_track_id;
123 daughter_track_id.push_back( part_v.at(index)._track_id );
127 if(!daughter_stored && daughter_track_id.size()>1) daughter_stored=
true;
129 mcshower.push_back(shower_prof);
133 std::cout <<
" Found " << mcshower.size() <<
" MCShowers. Now computing DetProfile position..." << std::endl;
138 std::vector<TLorentzVector> mcs_daughter_vtx_v(mcshower.size(),TLorentzVector(
sim::kINVALID_DOUBLE,
142 std::vector<TLorentzVector> mcs_daughter_mom_v ( mcshower.size(), TLorentzVector() );
144 std::vector< std::vector<double> > plane_charge_v ( mcshower.size(), std::vector<double>(3,0) );
145 std::vector< std::vector<double> > plane_dqdx_v ( mcshower.size(), std::vector<double>(3,0) );
148 std::vector<double> mcs_daughter_dedx_v ( mcshower.size(), 0 );
149 std::vector<double> mcs_daughter_dedxRAD_v ( mcshower.size(), 0 );
150 std::vector<TVector3> mcs_daughter_dir_v ( mcshower.size(), TVector3() );
152 for(
size_t mcs_index=0; mcs_index<mcshower.size(); ++mcs_index) {
154 auto& mcs_daughter_vtx = mcs_daughter_vtx_v[mcs_index];
155 auto& mcs_daughter_mom = mcs_daughter_mom_v[mcs_index];
156 auto& mcs_daughter_dedx = mcs_daughter_dedx_v[mcs_index];
157 auto& mcs_daughter_dedxRAD = mcs_daughter_dedxRAD_v[mcs_index];
158 auto& mcs_daughter_dir = mcs_daughter_dir_v[mcs_index];
159 auto& plane_charge = plane_charge_v[mcs_index];
160 auto& plane_dqdx = plane_dqdx_v[mcs_index];
162 for(
auto const& daughter_trk_id : mcshower[mcs_index].DaughterTrackID()) {
166 auto const& daughter_part = part_v[daughter_part_index];
170 if(daughter_edep_index<0)
continue;
172 auto const& daughter_edep = edep_v.
GetEdepArrayAt(daughter_edep_index);
174 if(!(daughter_edep.size()))
continue;
178 for(
auto const&
edep : daughter_edep) {
180 double dist = sqrt( pow(
edep.pos._x - daughter_part._start_vtx[0],2) +
181 pow(
edep.pos._y - daughter_part._start_vtx[1],2) +
182 pow(
edep.pos._z - daughter_part._start_vtx[2],2) );
184 if(dist < min_dist) {
186 mcs_daughter_vtx[0] =
edep.pos._x;
187 mcs_daughter_vtx[1] =
edep.pos._y;
188 mcs_daughter_vtx[2] =
edep.pos._z;
189 mcs_daughter_vtx[3] = (dist/100. / 2.998e8)*1.e9 + daughter_part._start_vtx[3];
193 if(!daughter_stored) {
195 std::vector<double> shower_dir(3,0);
196 shower_dir[0] = mcshower[mcs_index].Start().Px();
197 shower_dir[1] = mcshower[mcs_index].Start().Py();
198 shower_dir[2] = mcshower[mcs_index].Start().Pz();
199 double magnitude = 0;
200 for(
size_t i=0; i<3; ++i)
201 magnitude += pow(shower_dir[i],2);
203 magnitude = sqrt(magnitude);
205 if(magnitude > 1.
e-10) {
209 for(
auto& v : shower_dir) v /= magnitude;
211 for(
auto const&
edep : daughter_edep) {
212 std::vector<double> shower_dep_dir(3,0);
213 shower_dep_dir[0] =
edep.pos._x - mcshower[mcs_index].Start().X();
214 shower_dep_dir[1] =
edep.pos._y - mcshower[mcs_index].Start().Y();
215 shower_dep_dir[2] =
edep.pos._z - mcshower[mcs_index].Start().Z();
217 double dist = sqrt( pow(shower_dep_dir[0],2) + pow(shower_dep_dir[1],2) + pow(shower_dep_dir[2],2) );
218 for(
auto& v : shower_dep_dir) v /= dist;
220 double angle = acos( shower_dep_dir[0] * shower_dir[0] +
221 shower_dep_dir[1] * shower_dir[1] +
222 shower_dep_dir[2] * shower_dir[2] ) / TMath::Pi() * 180.;
224 if(dist < min_dist && angle < 10) {
227 mcs_daughter_vtx[0] =
edep.pos._x;
228 mcs_daughter_vtx[1] =
edep.pos._y;
229 mcs_daughter_vtx[2] =
edep.pos._z;
230 mcs_daughter_vtx[3] = (dist/100. / 2.998e8)*1.e9 + mcshower[mcs_index].Start().T();
239 std::vector<double> mom(3,0);
240 for(
auto const& daughter_trk_id : mcshower[mcs_index].DaughterTrackID()) {
249 if(daughter_edep_index<0)
continue;
251 auto const& daughter_edep = edep_v.
GetEdepArrayAt(daughter_edep_index);
253 if(!(daughter_edep.size()))
continue;
256 for(
auto const&
edep : daughter_edep) {
259 mom[0] =
edep.pos._x - mcs_daughter_vtx[0];
260 mom[1] =
edep.pos._y - mcs_daughter_vtx[1];
261 mom[2] =
edep.pos._z - mcs_daughter_vtx[2];
264 double magnitude = sqrt(pow(mom.at(0),2) + pow(mom.at(1),2) + pow(mom.at(2),2));
268 for(
auto const& pid_energy :
edep.deps) {
270 energy += pid_energy.energy;
274 if(magnitude>1.
e-10) {
275 mom.at(0) = mom.at(0) * energy / magnitude;
276 mom.at(1) = mom.at(1) * energy / magnitude;
277 mom.at(2) = mom.at(2) * energy / magnitude;
278 mcs_daughter_mom[0] += mom.at(0);
279 mcs_daughter_mom[1] += mom.at(1);
280 mcs_daughter_mom[2] += mom.at(2);
285 if(sqrt( pow(
edep.pos._x - mcs_daughter_vtx[0],2) +
286 pow(
edep.pos._y - mcs_daughter_vtx[1],2) +
287 pow(
edep.pos._z - mcs_daughter_vtx[2],2)) < 2.4 && magnitude>1.e-10){
289 mcs_daughter_dir[0] += mom.at(0);
290 mcs_daughter_dir[1] += mom.at(1);
291 mcs_daughter_dir[2] += mom.at(2);
297 mcs_daughter_dedxRAD +=
E;
299 mcs_daughter_mom[3] +=
energy;
303 auto q_i = pindex.find(
pid);
304 if(q_i != pindex.end())
305 plane_charge[
pid.Plane] += (
double)(
edep.deps[pindex[
pid]].charge);
310 mcs_daughter_dedxRAD /= 2.4;
312 for(
auto const& daughter_trk_id : mcshower[mcs_index].DaughterTrackID()) {
321 if(daughter_edep_index<0)
continue;
323 auto const& daughter_edep = edep_v.
GetEdepArrayAt(daughter_edep_index);
325 if(!(daughter_edep.size()))
continue;
327 for(
auto const&
edep : daughter_edep) {
339 double p_mag = sqrt( pow(mcs_daughter_dir[0],2) + pow(mcs_daughter_dir[1],2) + pow(mcs_daughter_dir[2],2) );
340 double a = 0, b = 0, c = 0,
d = 0;
342 a = mcs_daughter_dir[0]/p_mag;
343 b = mcs_daughter_dir[1]/p_mag;
344 c = mcs_daughter_dir[2]/p_mag;
345 d = -1*(a*mcs_daughter_vtx[0] + b*mcs_daughter_vtx[1] + c*mcs_daughter_vtx[2]);
347 else{mcs_daughter_dedx += 0;
continue;}
349 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 &&
350 (a*
edep.pos._x + b*
edep.pos._y + c*
edep.pos._z +
d)/sqrt( pow(a,2) + pow(b,2) + pow(c,2)) > 0){
355 for(
auto const& pid_energy :
edep.deps) {
357 E += pid_energy.energy;
365 mcs_daughter_dedx +=
E;
369 auto q_i = pindex.find(
pid);
370 if(q_i != pindex.end())
371 plane_dqdx[
pid.Plane] += (
double)(
edep.deps[pindex[
pid]].charge);
375 mcs_daughter_dedx /= 2.4;
376 plane_dqdx.at(0) /= 2.4;
377 plane_dqdx.at(1) /= 2.4;
378 plane_dqdx.at(2) /= 2.4;
384 std::cout <<
" Found " << mcshower.size() <<
" MCShowers. Now storing..." << std::endl;
387 for(
size_t mcs_index=0; mcs_index<mcshower.size(); ++mcs_index) {
389 auto& daughter_vtx = mcs_daughter_vtx_v[mcs_index];
390 auto& daughter_mom = mcs_daughter_mom_v[mcs_index];
391 auto& daughter_dedx = mcs_daughter_dedx_v[mcs_index];
392 auto& daughter_dedxRAD = mcs_daughter_dedxRAD_v[mcs_index];
393 auto& daughter_dir = mcs_daughter_dir_v[mcs_index];
394 auto& plane_charge = plane_charge_v[mcs_index];
395 auto& plane_dqdx = plane_dqdx_v[mcs_index];
397 double magnitude = sqrt(pow(daughter_mom[0],2)+pow(daughter_mom[1],2)+pow(daughter_mom[2],2));
399 if(daughter_mom[3]>1.
e-10) {
400 daughter_mom[0] *= daughter_mom[3]/magnitude;
401 daughter_mom[1] *= daughter_mom[3]/magnitude;
402 daughter_mom[2] *= daughter_mom[3]/magnitude;
404 for(
size_t i=0; i<4; ++i) daughter_mom[i]=0;
406 mcshower.at(mcs_index).DetProfile(
MCStep( daughter_vtx, daughter_mom ) );
407 mcshower.at(mcs_index).Charge(plane_charge);
408 mcshower.at(mcs_index).dQdx(plane_dqdx);
409 mcshower.at(mcs_index).dEdx(daughter_dedx);
410 mcshower.at(mcs_index).dEdxRAD(daughter_dedxRAD);
411 mcshower.at(mcs_index).StartDir(daughter_dir);
417 for(
auto const& prof : mcshower) {
421 << Form(
" Shower particle: PDG=%d : Track ID=%d Start @ (%g,%g,%g,%g) with Momentum (%g,%g,%g,%g)",
422 prof.PdgCode(), prof.TrackID(),
423 prof.Start().X(),prof.Start().Y(),prof.Start().Z(),prof.Start().T(),
424 prof.Start().Px(),prof.Start().Py(),prof.Start().Pz(),prof.Start().E())
426 << Form(
" Mother particle: PDG=%d : Track ID=%d Start @ (%g,%g,%g,%g) with Momentum (%g,%g,%g,%g)",
427 prof.MotherPdgCode(), prof.MotherTrackID(),
428 prof.MotherStart().X(),prof.MotherStart().Y(),prof.MotherStart().Z(),prof.MotherStart().T(),
429 prof.MotherStart().Px(),prof.MotherStart().Py(),prof.MotherStart().Pz(),prof.MotherStart().E())
431 << Form(
" Ancestor particle: PDG=%d : Track ID=%d Start @ (%g,%g,%g,%g) with Momentum (%g,%g,%g,%g)",
432 prof.AncestorPdgCode(), prof.AncestorTrackID(),
433 prof.AncestorStart().X(),prof.AncestorStart().Y(),prof.AncestorStart().Z(),prof.AncestorStart().T(),
434 prof.AncestorStart().Px(),prof.AncestorStart().Py(),prof.AncestorStart().Pz(),prof.AncestorStart().E())
436 << Form(
" ... with %zu daughters: Start @ (%g,%g,%g,%g) with Momentum (%g,%g,%g,%g)",
437 prof.DaughterTrackID().size(),
438 prof.DetProfile().X(),prof.DetProfile().Y(),prof.DetProfile().Z(),prof.DetProfile().T(),
439 prof.DetProfile().Px(),prof.DetProfile().Py(),prof.DetProfile().Pz(),prof.DetProfile().E())
441 <<
" Charge per plane: ";
442 size_t const nPlanes = prof.Charge().size();
443 for(
size_t i=0; i<nPlanes; ++i) {
445 std::cout <<
" | Plane " << i << std::flush;
446 std::cout <<
" ... Q = " << prof.Charge(i) << std::flush;
449 std::cout<<std::endl<<std::endl;
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
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
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
const unsigned int kINVALID_UINT
unsigned int MotherTrackID() const
const std::string & Process() const
const MCStep & MotherStart() const
int AncestorPdgCode() const
Namespace collecting geometry-related classes utilities.
unsigned int TrackToParticleIndex(const unsigned int track_id) const
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...