NucleonDecayFilter_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: NucleonDecayFilter
3 // Module Type: analyzer
4 // File: NucleonDecayFilter_module.cc
5 //
6 // Generated at Sun Mar 24 09:05:02 2013 by Tingjun Yang using artmod
7 // from art v1_02_06.
8 //
9 // Making a filter module to reduce the number of events which nucleon
10 // decay analyses have to look at.
11 // For example, if there are no Kaon energy deposits, then shouldn't
12 // reconstruct a Kaon in the event!
13 //
14 // Thomas Karl Warburton
15 // k.warburton@sheffield.ac.uk
16 //
17 ////////////////////////////////////////////////////////////////////////
18 
19 // Framework includes
24 #include "fhiclcpp/ParameterSet.h"
25 #include "art_root_io/TFileService.h"
27 
32 
33 // ROOT includes
34 #include "TTree.h"
35 
36 //standard library includes
37 #include <map>
38 #include <iostream>
39 #include <iomanip>
40 #include <sstream>
41 #include <cmath>
42 #include <memory>
43 #include <limits> // std::numeric_limits<>
44 
45 #define MaxPart 100
46 #define MaxParent 100
47 #define HolderVal 9999
48 
49 namespace filt{
51  public:
52  explicit NucleonDecayFilter(fhicl::ParameterSet const & pset);
53  virtual ~NucleonDecayFilter() {};
54  virtual bool filter(art::Event& e);
55  void reconfigure(fhicl::ParameterSet const& pset);
56  void beginJob() ;
57 
58  private:
59  // My functions
60  void FillVars( std::vector<int> &TrackIDVec, int &numParts, int ThisID );
61 
62  // Global variables
63  double ActiveBounds[6]; // Cryostat boundaries ( neg x, pos x, neg y, pos y, neg z, pos z )
64  std::map<int, const simb::MCParticle*> truthmap; // A map of the truth particles.
65 
66  // Handles
68 
69  // FHiCL parameters
70  bool fWantMuon;
71  bool fWantPion;
72  bool fWantPi0;
73  bool fWantKaon;
74  bool fWantElec;
75 
76  // Tree variables
77  TTree *MyOutTree;
78  int Run;
79  int SubRun;
80  int Event;
82 
83  };
84  // *************************************************************************************
85  NucleonDecayFilter::NucleonDecayFilter::NucleonDecayFilter(fhicl::ParameterSet const & pset) : EDFilter{pset} {
86  this->reconfigure(pset);
87  }
88  // ************************************ Reconfigure ************************************
90  fWantMuon = pset.get<bool>("WantMuon");
91  fWantPion = pset.get<bool>("WantPion");
92  fWantPi0 = pset.get<bool>("WantPi0" );
93  fWantKaon = pset.get<bool>("WantKaon");
94  fWantElec = pset.get<bool>("WantElec");
95  std::cout << "Your filter is selecting only events with: "
96  << "Muons " << fWantMuon << ", "
97  << "Pions " << fWantPion << ", "
98  << "Pi0s " << fWantPi0 << ", "
99  << "Kaons " << fWantKaon << ", "
100  << "Elecs " << fWantElec << "."
101  << std::endl;
102  }
103  // ************************************ Filter Func ************************************
105  Run = e.run();
106  SubRun = e.subRun();
107  Event = e.event();
108  nMuon = nPion = nPi0 = nKaon = nElec = 0;
109 
110  // Any providers I need.
111  auto const* geo = lar::providerFrom<geo::Geometry>();
112 
113  // Make a map of MCParticles which I can access later.
114  auto truth = e.getHandle<std::vector<simb::MCParticle> >("largeant");
115  truthmap.clear();
116  for (size_t i=0; i<truth->size(); i++)
117  truthmap[truth->at(i).TrackId()]=&((*truth)[i]);
118  //std::cout << "The primary muon in this event had an energy of " << truthmap[1]->E() << std::endl;
119 
120  // Get a vector of sim channels.
121  auto simchannels = e.getHandle<std::vector<sim::SimChannel> >("largeant");
122 
123  // Make vectors to hold all of my particle TrackIDs
124  std::vector<int> MuonVec, PionVec, Pi0Vec, KaonVec, ElecVec;
125 
126  // ------ Now loop through all of my hits ------
127  for (auto const& simchannel:*simchannels) {
128  // ------ Only want to look at collection plane hits ------
129  if (geo->SignalType(simchannel.Channel()) != geo::kCollection) continue;
130  // ------ Loop through all the IDEs for this channel ------
131  for (auto const& tdcide:simchannel.TDCIDEMap()) {
132  auto const& idevec=tdcide.second;
133  // ------ Look at each individual IDE ------
134  for (auto const& ide:idevec) {
135  int ideTrackID = ide.trackID;
136  double idePos[3];
137  idePos[0] = ide.x;
138  idePos[1] = ide.y;
139  idePos[2] = ide.z;
140  // ------ Is the hit in a TPC? ------
141  geo::TPCID tpcid=geo->FindTPCAtPosition(idePos);
142  if (!(geo->HasTPC(tpcid)) ) {
143  //std::cout << "Outside the Active volume I found at the top!" << std::endl;
144  continue;
145  }
146  // ------ Now to work out which particles in particular I want to save more information about... ------
147  // ----------------- I want to write out the IDE to the relevant parent particle type -----------------
148  // ------- This means looping back through the IDE's parents until I find an interesting TrackID ------
149  bool WrittenOut = false;
150  while ( ideTrackID != 0 && !WrittenOut ) {
151  const simb::MCParticle& part=*( truthmap[ abs(ideTrackID) ] );
152  int PdgCode=part.PdgCode();
153  WrittenOut = true; // If one of my particles don't want to go further back.
154  // ========== Muons ==========
155  if ( (PdgCode == -13 || PdgCode == 13) )
156  FillVars( MuonVec, nMuon, ideTrackID );
157  // ========== Pions ==========
158  else if ( (PdgCode == -211 || PdgCode == 211) && part.Process() != "pi+Inelastic" && part.Process() != "pi-Inelastic" )
159  FillVars( PionVec, nPion, ideTrackID );
160  // ========== Pi0s ==========
161  else if ( PdgCode == 111 )
162  FillVars( Pi0Vec , nPi0 , ideTrackID );
163  // ========== Kaons ===========
164  else if ( (PdgCode == 321 || PdgCode == -321) && part.Process() != "kaon+Inelastic" && part.Process() != "kaon-Inelastic" )
165  FillVars( KaonVec, nKaon, ideTrackID );
166  // ========== Elecs ===========
167  else if ( (PdgCode == -11 || PdgCode == 11) )
168  FillVars( ElecVec, nElec, ideTrackID );
169  // ========== If still not one of my intersting particles I need to find this particles parent ==========
170  else {
171  ideTrackID = part.Mother();
172  PdgCode = truthmap[ abs(ideTrackID) ]->PdgCode();
173  WrittenOut = false; // If not one of my particles change back to false.
174  } // If not one of chosen particles.
175  } // While loop
176  } // Each IDE ( ide:idevec )
177  } // IDE vector for SimChannel ( tdcide:simcahnnel.TPCIDEMap() )
178  } // Loop through simchannels
179  /*
180  std::cout << "Looking at Run " << Run << " SubRun " << SubRun << " Event " << Event
181  << ". There were " << nMuon << " muons, " << nPion << " pions, " << nPi0 << " pi0s, " << nKaon << " Kaons, " << nElec << " Electrons."
182  << std::endl;
183  */
184  // Fill Tree and decide whether to keep this event...
185  MyOutTree->Fill();
186  bool EventPasses = true;
187  if ( (fWantMuon && nMuon == 0) || nMuon > MaxPart) EventPasses = false;
188  if ( (fWantPion && nPion == 0) || nPi0 > MaxPart) EventPasses = false;
189  if ( (fWantPi0 && nPi0 == 0) || nPion > MaxPart) EventPasses = false;
190  if ( (fWantKaon && nKaon == 0) || nKaon > MaxPart) EventPasses = false;
191  if ( (fWantElec && nElec == 0) || nElec > MaxPart) EventPasses = false;
192  return EventPasses;
193  }
194  // ************************************* Begin Job *************************************
196  ActiveBounds[0] = ActiveBounds[2] = ActiveBounds[4] = DBL_MAX;
197  ActiveBounds[1] = ActiveBounds[3] = ActiveBounds[5] = -DBL_MAX;
198  // ----- FixMe: Assume single cryostats ------
199  auto const* geom = lar::providerFrom<geo::Geometry>();
200  for (geo::TPCGeo const& TPC: geom->IterateTPCs()) {
201  // get center in world coordinates
202  const double origin[3] = {0.};
203  double center[3] = {0.};
204  TPC.LocalToWorld(origin, center);
205  double tpcDim[3] = {TPC.HalfWidth(), TPC.HalfHeight(), 0.5*TPC.Length() };
206  if( center[0] - tpcDim[0] < ActiveBounds[0] ) ActiveBounds[0] = center[0] - tpcDim[0];
207  if( center[0] + tpcDim[0] > ActiveBounds[1] ) ActiveBounds[1] = center[0] + tpcDim[0];
208  if( center[1] - tpcDim[1] < ActiveBounds[2] ) ActiveBounds[2] = center[1] - tpcDim[1];
209  if( center[1] + tpcDim[1] > ActiveBounds[3] ) ActiveBounds[3] = center[1] + tpcDim[1];
210  if( center[2] - tpcDim[2] < ActiveBounds[4] ) ActiveBounds[4] = center[2] - tpcDim[2];
211  if( center[2] + tpcDim[2] > ActiveBounds[5] ) ActiveBounds[5] = center[2] + tpcDim[2];
212  } // for all TPC
213  std::cout << "Active Boundaries: "
214  << "\n\tx: " << ActiveBounds[0] << " to " << ActiveBounds[1]
215  << "\n\ty: " << ActiveBounds[2] << " to " << ActiveBounds[3]
216  << "\n\tz: " << ActiveBounds[4] << " to " << ActiveBounds[5]
217  << std::endl;
218 
220  MyOutTree = tfs->make<TTree>("FilterTree","FilterTree");
221  MyOutTree->Branch( "Run", &Run , "Run/I" );
222  MyOutTree->Branch( "SubRun",&SubRun, "SubRun/I" );
223  MyOutTree->Branch( "Event", &Event , "Event/I" );
224  MyOutTree->Branch( "nMuon", &nMuon , "nMuon/I" );
225  MyOutTree->Branch( "nPion", &nPion , "nPion/I" );
226  MyOutTree->Branch( "nPi0" , &nPi0 , "nPi0/I" );
227  MyOutTree->Branch( "nKaon", &nKaon , "nKaon/I" );
228  MyOutTree->Branch( "nElec", &nElec , "nElec/I" );
229  }
230  // *********************************** Fill Variable ***********************************
231  void NucleonDecayFilter::FillVars( std::vector<int> &TrackIDVec, int &numParts, int ThisID ) {
232  std::vector<int>::iterator it=std::find( TrackIDVec.begin(), TrackIDVec.end(), abs(ThisID) );
233  if ( it==TrackIDVec.end() ) {
234  TrackIDVec.push_back ( abs(ThisID) ); // Push back this particle type IDVec
235  ++numParts;
236  }
237  }
238  // *********************************** Define Module ***********************************
240 }
intermediate_table::iterator iterator
int PdgCode() const
Definition: MCParticle.h:212
EventNumber_t event() const
Definition: DataViewImpl.cc:85
std::map< int, const simb::MCParticle * > truthmap
Handle< PROD > getHandle(SelectorBase const &) const
Definition: DataViewImpl.h:382
int Mother() const
Definition: MCParticle.h:213
Geometry information for a single TPC.
Definition: TPCGeo.h:38
std::string Process() const
Definition: MCParticle.h:215
Particle class.
art::ServiceHandle< geo::Geometry > geom
art framework interface to geometry description
void reconfigure(fhicl::ParameterSet const &pset)
T abs(T value)
const double e
int PdgCode(Resonance_t res, int Q)
(resonance id, charge) -> PDG code
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
IteratorBox< TPC_iterator,&GeometryCore::begin_TPC,&GeometryCore::end_TPC > IterateTPCs() const
Enables ranged-for loops on all TPCs of the detector.
NucleonDecayFilter(fhicl::ParameterSet const &pset)
T get(std::string const &key) const
Definition: ParameterSet.h:271
#define MaxPart
SubRunNumber_t subRun() const
Definition: DataViewImpl.cc:78
RunNumber_t run() const
Definition: DataViewImpl.cc:71
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
def center(depos, point)
Definition: depos.py:117
EDFilter(fhicl::ParameterSet const &pset)
Definition: EDFilter.h:21
void FillVars(std::vector< int > &TrackIDVec, int &numParts, int ThisID)
virtual bool filter(art::Event &e)
LArSoft geometry interface.
Definition: ChannelGeo.h:16
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:227
QTextStream & endl(QTextStream &s)
Signal from collection planes.
Definition: geo_types.h:146