GenExtCounterFilter_module.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <utility>
3 #include <complex>
4 #include <algorithm>
5 
6 
13 #include "lardataobj/RawData/raw.h"
15 
16 namespace filt{
17 
18  class GenFilter : public art::EDFilter {
19  public:
20  explicit GenFilter(fhicl::ParameterSet const & pset);
21  virtual ~GenFilter() {};
22  virtual bool filter(art::Event& e);
23  void reconfigure(fhicl::ParameterSet const& pset);
24  void beginJob() ;
25 
26  private:
27 
30  std::vector<geo::AuxDetGeo const*> setA;
31  std::vector<geo::AuxDetGeo const*> setB;
32  double normalVec[3];
33 
34  };
35  std::vector<CounterSetPair> fCounterSetPairs;
36 
37  //Adjustable parameters
38  bool fUseEWCounterPair; //Use the EW counter pair
39  bool fUseNupSdownCounterPair; //Use North (up) South (down) counter pair
40  bool fUseNdownSupCounterPair; //Use the North (down) South (up) counter pair
41  std::vector<int> fInterestingPDGs; //A vector of particle PDGs which want to be filtered on
42  double fParticleMinEnergy; //The minimum energy of a particle to be filtered
43  double fParticleMaxEnergy; //The maximum energy of a particle to be filtered
44  double fCounterSizeScaleFactor; //The scaling factor to increase/decrease thedimensions of the counter
45 
46 
47  bool IsInterestingParticle(const simb::MCParticle &particle);
48  bool ParticleHitsCounterSetPairs(const simb::MCParticle &particle, const CounterSetPair &CSP);
49  bool ParticleHitsCounterSet(const simb::MCParticle &particle, const std::vector<geo::AuxDetGeo const*> &counters, const TVector3 &counter_norm);
50 
51  };
52 
53 
54  GenFilter::GenFilter::GenFilter(fhicl::ParameterSet const & pset) : EDFilter{pset}
55  {
56  this->reconfigure(pset);
57  }
58 
60  fUseEWCounterPair = pset.get<bool>("UseEWCounterPair",1);
61  std::cout<<"Use EW counter pair: " << fUseEWCounterPair<<std::endl;
62  fUseNupSdownCounterPair = pset.get<bool>("UseNupSdownCounterPair",1);
63  std::cout<<"Use N (up) S (down) counter pair: " << fUseNupSdownCounterPair << std::endl;
64  fUseNdownSupCounterPair = pset.get<bool>("UseNdownSupCounterPair",1);
65  std::cout<<"Use N (down) S (up) counter pair: " << fUseNdownSupCounterPair << std::endl;
66  fInterestingPDGs = pset.get<std::vector<int> >("InterestingPDGs");
67  std::cout<<"NInteresting PDGs: " << fInterestingPDGs.size() << std::endl;
68  for (unsigned int i = 0; i < fInterestingPDGs.size(); i++){
69  std::cout<<"-- PDG: " << fInterestingPDGs[i] << std::endl;
70  }
71  fParticleMinEnergy = pset.get<double>("ParticleMinEnergy",0);
72  std::cout<<"Particle min energy: " << fParticleMinEnergy << std::endl;
73  fParticleMaxEnergy = pset.get<double>("ParticleMaxEnergy",999999999);
74  std::cout<<"Particle max energy: " << fParticleMaxEnergy << std::endl;
75 
76  fCounterSizeScaleFactor = pset.get<double>("CounterSizeScaleFactor",1.);
77  std::cout<<"Counter size scale factor: " << fCounterSizeScaleFactor << std::endl;
78  }
79 
80 
82 
83  auto const mclists = e.getMany<std::vector<simb::MCTruth>>();
84  for (unsigned int i = 0; i < mclists.size() ; i++){
85  for (unsigned int j = 0; j < mclists[i]->size(); j++){
86  //Should have the truth record for the event now
87  const art::Ptr<simb::MCTruth> mc_truth(mclists[i],j);
88  for (int part = 0; part < mc_truth->NParticles(); part++){
89  const simb::MCParticle particle = mc_truth->GetParticle(part);
90  if (!IsInterestingParticle(particle)) continue;
91  TVector3 particle_pos = particle.Position().Vect();
92  TVector3 particle_dir = particle.Momentum().Vect().Unit();
93  for (unsigned CSP_i = 0; CSP_i < fCounterSetPairs.size(); CSP_i++){
94  if (!fCounterSetPairs[CSP_i].isRequested) continue;
96  std::cout<<"HIT COUNTER SET"<<std::endl;
97  return true;
98  }
99  /*
100  TVector3 counter_norm(fCounterSetPairs[i].normalVec[0],fCounterSetPairs[i].normalVec[1],fCounterSetPairs[i].normalVec[2]);
101  double counter_pos_array[3];
102  fCounterSetPairs[CSP_i].setA.front()->GetCenter(counter_pos_array);
103  TVector3 counter_pos(counter_pos_array[0], counter_pos_array[1], counter_pos_array[2]);
104  double scale_factor = counter_norm.Dot(counter_pos - particle_pos)/(counter_norm.Dot(particle_dir));
105  TVector3 particle_pos_in_plane = particle_pos + scale_factor * particle_dir;
106  std::cout<<"Particle pos: " << "("<<particle_pos_in_plane.X()<<","<<particle_pos_in_plane.Y()<<","<<particle_pos_in_plane.Z()<<")"<<std::endl;
107  std::cout<<"Counter pos: " << "("<<counter_pos.X()<<","<<counter_pos.Y()<<","<<counter_pos.Z()<<")"<<std::endl;
108  */
109 
110  }
111  /*
112  geo::AuxDetGeo const*counter = fCounterSetPairs.front().setA.front();
113  std::cout<<"Length: " << counter->Length() << std::endl;
114  std::cout<<"HalfWidth1: " << counter->HalfWidth1() << std::endl;
115  std::cout<<"HalfWidth2: " << counter->HalfWidth2() << std::endl;
116 
117  std::cout<<"HalfHeight: " << counter->HalfHeight() << std::endl;
118  */
119  }
120  }
121  }
122 
123  return false;
124  }
125 
128 
129  CounterSetPair EWCounterSetPair;
130  CounterSetPair NupSdownCounterSetPair;
131  CounterSetPair NdownSupCounterSetPair;
132 
133  for (unsigned int i = 0; i < geom->NAuxDets(); i++){
134  //The WE counter pairs
135  geo::AuxDetGeo const* counter = &(geom->AuxDet(i));
136  if (i >=6 && i <= 15) EWCounterSetPair.setA.push_back(counter);
137  else if (i >= 28 && i <=37) EWCounterSetPair.setB.push_back(counter);
138  //The N (up) S (down) counter pairs
139  else if (i >= 22 && i <= 27) NupSdownCounterSetPair.setA.push_back(counter);
140  else if (i <= 5) NupSdownCounterSetPair.setB.push_back(counter);
141  //The N (down) S (up) counter pairs
142  else if (i >= 16 && i <= 21) NdownSupCounterSetPair.setA.push_back(counter);
143  else if (i >= 38 && i <= 43) NdownSupCounterSetPair.setB.push_back(counter);
144  }
145 
146  EWCounterSetPair.normalVec[0] = 0.;
147  EWCounterSetPair.normalVec[1] = 0.;
148  EWCounterSetPair.normalVec[2] = 1.;
149  EWCounterSetPair.isRequested = fUseEWCounterPair;
150  fCounterSetPairs.push_back(EWCounterSetPair);
151 
152  NupSdownCounterSetPair.normalVec[0] = 1.;
153  NupSdownCounterSetPair.normalVec[1] = 0.;
154  NupSdownCounterSetPair.normalVec[2] = 0.;
155  NupSdownCounterSetPair.isRequested = fUseNupSdownCounterPair;
156  fCounterSetPairs.push_back(NupSdownCounterSetPair);
157 
158  NdownSupCounterSetPair.normalVec[0] = 1.;
159  NdownSupCounterSetPair.normalVec[1] = 0.;
160  NdownSupCounterSetPair.normalVec[2] = 0.;
161  NdownSupCounterSetPair.isRequested = fUseNdownSupCounterPair;
162  fCounterSetPairs.push_back(NdownSupCounterSetPair);
163 
164  for (unsigned int i = 0; i < fCounterSetPairs.size(); i++){
165  std::cout<<"Counter set pair: "<<i<<std::endl;
166  std::cout<<"--setA size: " << fCounterSetPairs[i].setA.size() << std::endl;
167  std::cout<<"--setB size: " << fCounterSetPairs[i].setB.size() << std::endl;
168 
169  }
170 
171 
172  }
173 
175 
176  for (unsigned int i = 0; i < fInterestingPDGs.size(); i++){
177  //Check if the particle under consideration has a requested PDG
178  if (particle.PdgCode() == fInterestingPDGs[i]){
179  //Got a requested PDG, now check that the energy matches the requested range
180  TLorentzVector mom4 = particle.Momentum();
181  if (mom4.T() > fParticleMinEnergy && mom4.T() < fParticleMaxEnergy){
182  //std::cout<<"FOUND INTERESTING PARTICLE"<<std::endl;
183  return true;
184  }
185  }
186  }
187 
188  return false;
189  }
190 
192  //Need the normal to the counters
193  TVector3 counter_norm(CSP.normalVec[0],CSP.normalVec[1],CSP.normalVec[2]);
194 
195  //Loop through one of the counter sets
196  if (ParticleHitsCounterSet(particle, CSP.setA, counter_norm)){
197  if (ParticleHitsCounterSet(particle, CSP.setB, counter_norm)){
198  return true;
199  }
200  }
201  return false;
202  }
203 
204  bool GenFilter::ParticleHitsCounterSet(const simb::MCParticle &particle, const std::vector<geo::AuxDetGeo const*> &counters, const TVector3 &counter_norm){
205 
206  //Loop through the counters
207  for (unsigned int i = 0; i < counters.size(); i++){
208  //First step is to push the particle to the counter plane
209  geo::AuxDetGeo const*counter = counters[i];
210 
211  double counter_pos_array[3];
212  //fCounterSetPairs[CSP_i].setA.front()->GetCenter(counter_pos_array);
213  counter->GetCenter(counter_pos_array);
214  TVector3 counter_pos(counter_pos_array[0], counter_pos_array[1], counter_pos_array[2]);
215  TVector3 particle_pos = particle.Position().Vect();
216  TVector3 particle_dir = particle.Momentum().Vect().Unit();
217 
218  /*
219  Length: 62.992
220  HalfWidth1: 16.2814
221  HalfWidth2: 13.5255
222  HalfHeight: 0.475
223  */
224 
225  double scale_factor = counter_norm.Dot(counter_pos - particle_pos)/(counter_norm.Dot(particle_dir));
226 
227  TVector3 particle_pos_in_plane = particle_pos + scale_factor * particle_dir;
228 
229  //We now have the particle position in the plane of the counter. We now just need to calculate whether it sits inside the box
230  //Create two TVector3s, each will hold the coordinates of opposing corners of the counter in question
231  //We need to use the normals associated with the counter. We already have two, one is a member of the C++ object and the other was passed to this function
232  //Create the two TVector3s
233  TVector3 pos_corner, neg_corner;
234  //Lets start with the one passed to this function
235  //The thin dimension of the counter is the one associated with normal passed to this function
236  pos_corner += counter->HalfHeight()*counter_norm*fCounterSizeScaleFactor;
237  neg_corner += -1.*counter->HalfHeight()*counter_norm*fCounterSizeScaleFactor;
238 
239  //Now lets to the same for the normal stored in the C++ object (this "normal" actually points out the top of a counter)
240  double counter_top_norm_array[3];
241  counter->GetNormalVector(counter_top_norm_array);
242  //Now package this up a TVector
243  TVector3 counter_top_norm;
244  counter_top_norm.SetX(counter_top_norm_array[0]);
245  counter_top_norm.SetY(counter_top_norm_array[1]);
246  counter_top_norm.SetZ(counter_top_norm_array[2]);
247  //OK now we can add the dimension to the corner vectors. The relevant dimension this time is Length/2
248  pos_corner += counter->Length()*counter_top_norm*0.5*fCounterSizeScaleFactor;
249  neg_corner += -1.*counter->Length()*counter_top_norm*0.5*fCounterSizeScaleFactor;
250  //Now we need to the same for the vector pointing along the counter.
251  //The relevant dimension in this case in HalfWidth1 (going to assume the counter is a square and take the bigger width)
252  //Because we have the other two vectors already, we can very easily get the final one by taking the cross product of them
253  TVector3 counter_side_norm = counter_norm.Cross(counter_top_norm);
254  //now add the dimenions onto the corner vectors
255  pos_corner += counter->HalfWidth1()*counter_side_norm*fCounterSizeScaleFactor;
256  neg_corner += -1.*counter->HalfWidth1()*counter_side_norm*fCounterSizeScaleFactor;
257 
258  //Almost ready
259  //We have calculated the corners assuming the centre of the counter is the origin. Two choices, either translate the corners OR translate the propagated particle position
260  //The latter is less lines of code so lets to that
261  particle_pos_in_plane += -1.*counter_pos;
262 
263  //We are now ready to check if the particle sits in the counter
264  //We don't know by default which way round the corners are oriented, but that doesn't matter as we can take abs, max and min
265  //We are going to take abs of the particle position, the pos corner and the neg corner first
266  /*
267  pos_corner.SetXYZ(std::abs(pos_corner.X()),std::abs(pos_corner.Y()),std::abs(pos_corner.Z()));
268  neg_corner.SetXYZ(std::abs(neg_corner.X()),std::abs(neg_corner.Y()),std::abs(neg_corner.Z()));
269  particle_pos_in_plane.SetXYZ(std::abs(particle_pos_in_plane.X()),std::abs(particle_pos_in_plane.Y()),std::abs(particle_pos_in_plane.Z()));
270  */
271 
272  /*
273  //Dump the corners and particle pos
274  std::cout<<"pos_corner: " << pos_corner.X()<<","<<pos_corner.Y()<<","<<pos_corner.Z()<<std::endl;
275  std::cout<<"neg_corner: " << neg_corner.X()<<","<<neg_corner.Y()<<","<<neg_corner.Z()<<std::endl;
276  std::cout<<"particle_pos_in_plane: " << particle_pos_in_plane.X()<<","<<particle_pos_in_plane.Y()<<","<<particle_pos_in_plane.Z()<<std::endl;
277  */
278 
279 
280 
281  //Now we can check
282  //This is going to be one huge if statement...
283  if (particle_pos_in_plane.X() > std::min(pos_corner.X(), neg_corner.X()) && particle_pos_in_plane.X() < std::max(pos_corner.X(),neg_corner.X()) && particle_pos_in_plane.Y() > std::min(pos_corner.Y(), neg_corner.Y()) && particle_pos_in_plane.Y() < std::max(pos_corner.Y(),neg_corner.Y()) && particle_pos_in_plane.Z() > std::min(pos_corner.Z(), neg_corner.Z()) && particle_pos_in_plane.Z() < std::max(pos_corner.Z(),neg_corner.Z())){
284  std::cout<<"Particle uses counter in set"<<std::endl;
285  return true;
286  }
287 
288  }
289 
290  return false;
291  }
292 
293 
295 
296 }
bool IsInterestingParticle(const simb::MCParticle &particle)
const TLorentzVector & Position(const int i=0) const
Definition: MCParticle.h:219
int PdgCode() const
Definition: MCParticle.h:212
int NParticles() const
Definition: MCTruth.h:75
art framework interface to geometry description
std::vector< geo::AuxDetGeo const * > setB
GenFilter(fhicl::ParameterSet const &pset)
const double e
bool ParticleHitsCounterSetPairs(const simb::MCParticle &particle, const CounterSetPair &CSP)
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
double HalfHeight() const
Definition: AuxDetGeo.h:105
bool ParticleHitsCounterSet(const simb::MCParticle &particle, const std::vector< geo::AuxDetGeo const * > &counters, const TVector3 &counter_norm)
std::vector< Handle< PROD > > getMany(SelectorBase const &selector=MatchAllSelector{}) const
Definition: DataViewImpl.h:479
T get(std::string const &key) const
Definition: ParameterSet.h:271
std::vector< int > fInterestingPDGs
geo::Vector_t GetNormalVector() const
Returns the unit normal vector to the detector.
Definition: AuxDetGeo.cxx:72
static int max(int a, int b)
AuxDetGeo const & AuxDet(unsigned int const ad=0) const
Returns the specified auxiliary detector.
const simb::MCParticle & GetParticle(int i) const
Definition: MCTruth.h:76
virtual bool filter(art::Event &e)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
double Length() const
Definition: AuxDetGeo.h:102
std::vector< CounterSetPair > fCounterSetPairs
const TLorentzVector & Momentum(const int i=0) const
Definition: MCParticle.h:220
EDFilter(fhicl::ParameterSet const &pset)
Definition: EDFilter.h:21
Declaration of basic channel signal object.
std::vector< geo::AuxDetGeo const * > setA
double HalfWidth1() const
Definition: AuxDetGeo.h:103
void reconfigure(fhicl::ParameterSet const &pset)
QTextStream & endl(QTextStream &s)
unsigned int NAuxDets() const
Returns the number of auxiliary detectors.
void GetCenter(double *xyz, double localz=0.0) const
Return the center position of an AuxDet.
Definition: AuxDetGeo.cxx:62