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...