FilterGenInTime_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file FilterGenInTime_module.cc
3 /// \brief EDFilter to require projected generator trajectories in volumes within a particular time window.
4 ///
5 /// \author Matthew.Bass@physics.ox.ac.uk
6 ////////////////////////////////////////////////////////////////////////
7 
8 /// Framework includes
11 
12 // Framework includes
14 #include "fhiclcpp/ParameterSet.h"
19 #include "cetlib_except/exception.h"
20 #include "canvas/Persistency/Common/FindManyP.h"
21 #include "canvas/Persistency/Common/FindOneP.h"
22 
23 // LArSoft Includes
24 #include "nug4/ParticleNavigation/ParticleList.h"
28 
29 // C++ Includes
30 #include <cstring>
31 #include <sys/stat.h>
32 
33 // Root includes
34 #include <TMath.h>
35 
36 namespace simfilter {
37 
39  {
40  public:
41 
42  explicit FilterGenInTime(fhicl::ParameterSet const &pset);
43 
44  bool filter(art::Event&) ;
45 
46  virtual void beginJob();
47 
48 
49  private:
50  bool KeepParticle(simb::MCParticle const& part) const;
51 
52  std::vector<std::array<double, 6>> fCryostatBoundaries; //!< boundaries of each cryostat
53  double fMinKE; //<only keep based on particles with greater than this energy
54  bool fKeepOnlyMuons; //keep based only on muons if enabled
55  double fMinT,fMaxT; //<time range in which to keep particles
56  bool fSortParticles; //create new MCTruth collections with particles sorted by their timing
57  bool fAlwaysPass; // flag to have filter always pass (to be used with sorting...)
58  };
59 
60 } // namespace simfilter
61 
62 namespace simfilter {
63 
65  EDFilter{pset},
66  fMinKE (pset.get< double > ("MinEnergy" , 0.0) )
67  , fKeepOnlyMuons (pset.get< bool > ("KeepOnlyMuons", false) )
68  , fMinT (pset.get< double > ("MinT",0.0) )
69  , fMaxT (pset.get< double > ("MaxT") )
70  , fSortParticles ( pset.get< bool > ("SortParticles",false) )
71  , fAlwaysPass (pset.get<bool>("AlwaysPass",false))
72  {
73  if(fSortParticles) {
74  produces< std::vector<simb::MCTruth> >("intime");
75  produces< std::vector<simb::MCTruth> >("outtime");
76  }
77  std::cout << "New Filter!\n";
78 
79  }
80 
82  auto const& geom = *art::ServiceHandle<geo::Geometry const>();
83  for (auto const &cryo: geom.IterateCryostats()) {
84  std::array<double, 6> this_cryo_boundaries {};
85  cryo.Boundaries(&this_cryo_boundaries[0]);
86  fCryostatBoundaries.push_back(this_cryo_boundaries);
87  }
88  }
89 
90 
92  const TLorentzVector& v4 = part.Position();
93  const TLorentzVector& p4 = part.Momentum();
94  // origin of particle
95  double x0[3] = {v4.X(), v4.Y(), v4.Z() };
96  // normalized direction of particle
97  double dx[3] = {p4.Px() / p4.Vect().Mag(), p4.Py() / p4.Vect().Mag(), p4.Pz() / p4.Vect().Mag()};
98 
99  // tolernace for treating number as "zero"
100  double eps = 1e-5;
101 
102  //check to see if particle crosses boundary of any cryostat within appropriate time window
103  std::vector<bool> intersects_cryo(fCryostatBoundaries.size(), false);
104  std::vector<bool> inside_cryo(fCryostatBoundaries.size(), false);
105  std::vector<double> distance_to_cryo(fCryostatBoundaries.size(), 0.);
106 
107  // Check to see if particle intersects any cryostat
108  //
109  // Algorithmically, this is looking for ray-box intersection. This is a common problem in
110  // computer graphics. The algorithm below is taken from "Graphics Gems", Academic Press, 1990
111  for (size_t i_cryo = 0; i_cryo < fCryostatBoundaries.size(); i_cryo++) {
112  auto const &bound = fCryostatBoundaries[i_cryo];
113  std::array<int, 3> quadrant {}; // 0 == RIGHT, 1 == LEFT, 2 == MIDDLE
114  std::array<double, 3> candidatePlane {};
115  std::array<double, 3> coord {};
116 
117  std::array<double, 3> bound_lo = {{bound[0], bound[2], bound[4]}};
118  std::array<double, 3> bound_hi = {{bound[1], bound[3], bound[5]}};
119 
120  // First check if origin is inside box
121  // Also check which of the two planes in each dimmension is the
122  // "candidate" for the ray to hit
123  bool inside = true;
124  for (int i = 0; i < 3; i++) {
125  if (x0[i] < bound_lo[i]) {
126  quadrant[i] = 1; // LEFT
127  candidatePlane[i] = bound_lo[i];
128  inside = false;
129  }
130  else if (x0[i] > bound_hi[i]) {
131  quadrant[i] = 0; // RIGHT
132  candidatePlane[i] = bound_hi[i];
133  inside = false;
134  }
135  else {
136  quadrant[i] = 2; // MIDDLE
137  }
138  }
139 
140  if (inside) {
141  inside_cryo[i_cryo] = true;
142  // if we're inside the cryostat, then we do intersect it
143  intersects_cryo[i_cryo] = true;
144  continue;
145  }
146 
147  // ray origin is outside the box -- calculate the distance to the cryostat and see if it intersects
148 
149  // calculate distances to candidate planes
150  std::array<double, 3> maxT {};
151  for (int i = 0; i < 3; i++) {
152  if (quadrant[i] != 2 /* MIDDLE */ && abs(dx[i]) > eps) {
153  maxT[i] = (candidatePlane[i] - x0[i]) / dx[i];
154  }
155  // if a ray origin is between two the two planes in a dimmension, it would never hit that plane first
156  else {
157  maxT[i] = -1;
158  }
159  }
160 
161  // The plane on the box that the ray hits is the one with the largest distance
162  int whichPlane = 0;
163  for (int i = 1; i < 3; i++) {
164  if (maxT[whichPlane] < maxT[i]) whichPlane = i;
165  }
166 
167  // check if the candidate intersection point is inside the box
168 
169  // no intersection
170  if (maxT[whichPlane] < 0.) {
171  intersects_cryo[i_cryo] = false;
172  continue;
173  }
174 
175  for (int i = 0; i < 3; i++) {
176  if (whichPlane != i) {
177  coord[i] = x0[i] + maxT[whichPlane] * dx[i];
178  }
179  else {
180  coord[i] = candidatePlane[i];
181  }
182  }
183 
184 
185  // check if intersection is in box
186  intersects_cryo[i_cryo] = true;
187  for (int i = 0; i < 3; i++) {
188  if (coord[i] < bound_lo[i] || coord[i] > bound_hi[i]) {
189  intersects_cryo[i_cryo] = false;
190  }
191  }
192 
193  if (intersects_cryo[i_cryo]) {
194  distance_to_cryo[i_cryo] = maxT[whichPlane];
195  }
196  }
197 
198  // check if any cryostats are intersected in-time
199  for (size_t i_cryo = 0; i_cryo < fCryostatBoundaries.size(); i_cryo++) {
200 
201  // If the particle originates inside the cryostat, then
202  // we can't really say when it will leave. Thus, accept
203  // the particle
204  if (inside_cryo[i_cryo]) {
205  return true;
206  }
207  // otherwise check arrival time at boundary of cryostat
208  if (intersects_cryo[i_cryo]){
209  double ptime = (distance_to_cryo[i_cryo] * 1e-2 /* cm -> m */) / (TMath::C()*sqrt(1-pow(part.Mass()/part.E(),2))) /* velocity */;
210  double totT=part.T()+ptime*1e9 /* s -> ns */;
211  if(totT>fMinT && totT<fMaxT){
212  return true;
213  }
214  }
215  }
216 
217 
218 
219  return false;
220  }
221 
223 
224  std::unique_ptr< std::vector<simb::MCTruth> > truthInTimePtr(new std::vector<simb::MCTruth>(1));
225  std::unique_ptr< std::vector<simb::MCTruth> > truthOutOfTimePtr(new std::vector<simb::MCTruth>(1));
226 
227  simb::MCTruth & truthInTime = truthInTimePtr->at(0);
228  simb::MCTruth & truthOutOfTime = truthOutOfTimePtr->at(0);
229 
230 
231  //get the list of particles from this event
233 
234  //std::vector< art::Handle< std::vector<simb::MCTruth> > > allmclists;
235  //evt.getManyByType(allmclists);
236  auto allmclists = evt.getMany< std::vector<simb::MCTruth> >();
237  bool keepEvent=false;
238  for(size_t mcl = 0; mcl < allmclists.size(); ++mcl){
239  art::Handle< std::vector<simb::MCTruth> > mclistHandle = allmclists[mcl];
240  for(size_t m = 0; m < mclistHandle->size(); ++m){
241  art::Ptr<simb::MCTruth> mct(mclistHandle, m);
242 
243  for(int ipart=0;ipart<mct->NParticles();ipart++){
244  bool kp=KeepParticle(mct->GetParticle(ipart));
245 
246  if(kp
247  && (!fKeepOnlyMuons || abs(mct->GetParticle(ipart).PdgCode())==13 )
248  && mct->GetParticle(ipart).E()-mct->GetParticle(ipart).Mass()>fMinKE){
249  keepEvent = true;
250  if(!fSortParticles) break;
251  }
252 
253  if(fSortParticles){
254  simb::MCParticle particle = mct->GetParticle(ipart);
255  if(kp) truthInTime.Add(particle);
256  if(!kp) truthOutOfTime.Add(particle);
257  }
258 
259  }//end loop over particles
260 
261  if(!fSortParticles && keepEvent) break;
262 
263  }//end loop over mctruth col
264 
265  if(!fSortParticles && keepEvent) break;
266 
267  }//end loop over all mctruth lists
268 
269  if(fSortParticles){
270  evt.put(std::move(truthInTimePtr),"intime");
271  evt.put(std::move(truthOutOfTimePtr),"outtime");
272  }
273 
274  return (keepEvent || fAlwaysPass);
275  }
276 
277 } // namespace simfilter
278 
279 namespace simfilter {
280 
282 
283 } // namespace simfilter
double E(const int i=0) const
Definition: MCParticle.h:233
const TLorentzVector & Position(const int i=0) const
Definition: MCParticle.h:219
int PdgCode() const
Definition: MCParticle.h:212
auto coord(Vector &v, unsigned int n) noexcept
Returns an object to manage the coordinate n of a vector.
double Mass() const
Definition: MCParticle.h:239
constexpr T pow(T x)
Definition: pow.h:72
std::vector< std::array< double, 6 > > fCryostatBoundaries
boundaries of each cryostat
int NParticles() const
Definition: MCTruth.h:75
art framework interface to geometry description
T abs(T value)
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
std::vector< Handle< PROD > > getMany(SelectorBase const &selector=MatchAllSelector{}) const
Definition: DataViewImpl.h:479
def move(depos, offset)
Definition: depos.py:107
double T(const int i=0) const
Definition: MCParticle.h:224
FilterGenInTime(fhicl::ParameterSet const &pset)
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
const simb::MCParticle & GetParticle(int i) const
Definition: MCTruth.h:76
void Add(simb::MCParticle const &part)
Definition: MCTruth.h:80
const TLorentzVector & Momentum(const int i=0) const
Definition: MCParticle.h:220
EDFilter(fhicl::ParameterSet const &pset)
Definition: EDFilter.h:21
bool KeepParticle(simb::MCParticle const &part) const
Tools and modules for checking out the basics of the Monte Carlo.
TCEvent evt
Definition: DataStructs.cxx:7
Event generator information.
Definition: MCTruth.h:32
Framework includes.