SNSlicer_module.cc
Go to the documentation of this file.
1 
2 // Tutorial module example
3 
4 #ifndef SNSlicer_H
5 #define SNSlicer_H 1
6 
7 // Framework includes
8 
14 #include "art_root_io/TFileService.h"
15 #include "art_root_io/TFileDirectory.h"
16 #include "fhiclcpp/ParameterSet.h"
17 
18 // LArSoft includes
19 
21 #include "lardataobj/RawData/raw.h"
24 //#include "larsim/MCCheater/BackTrackerService.h"
25 //#include "larsim/MCCheater/ParticleInventoryService.h"
26 //#include "larsim/MCCheater/PhotonBackTrackerService.h"
27 #include "nug4/ParticleNavigation/EmEveIdCalculator.h"
28 
30 
32 
33 // ROOT includes
34 
35 #include "TGraph.h"
36 #include "TH2.h"
37 #include "TTree.h"
38 #include "TPad.h"
39 
40 // C++ includes
41 
42 #include <vector>
43 #include <string>
44 #include <iostream>
45 
51 
52 
54 
55 namespace
56 {
57  struct Pt2D
58  {
59  Pt2D(){}
60  Pt2D(double _x, double _y, double _q, bool _isSig, int _idx) : x(_x), y(_y), q(_q), isSig(_isSig), idx(_idx) {}
61  double x, y;
62  double q;
63  bool isSig;
64  int idx; // index into original hits array
65  };
66 
67  class SNSlicer: public art::EDProducer
68  {
69  public:
70  SNSlicer(const fhicl::ParameterSet&);
71 
72  void produce(art::Event&) override;
73 
74  protected:
75  std::vector<int> regionQuery(const std::vector<Pt2D>& D, const Pt2D& p) const;
76 
77  void expandCluster(const std::vector<Pt2D>& D,
78  int ip,
79  std::vector<int> neiPts, int C,
80  std::vector<bool>& visited,
81  std::vector<int>& inClust) const;
82 
83  std::vector<std::vector<Pt2D>> DBSCAN(const std::vector<Pt2D>& D) const;
84 
85  // std::string fDetSimProducerLabel;
86 
87 // art::ServiceHandle<cheat::BackTrackerService> bt_serv;
88 // art::ServiceHandle<cheat::ParticleInventoryService> pi_serv;
89 // art::ServiceHandle<cheat::PhotonBackTrackerService> pbt;
90 
91  const geo::GeometryCore& geom;
93 
94  // DBScan params
95  double fEps;
96  int fMinPts;
97  };
98 
99 }
100 
101 #endif
102 
103 namespace {
104 
105  DEFINE_ART_MODULE(SNSlicer)
106 
107 }
108 
109 namespace {
110 
111  //---------------------------------------------------------------------------
112  // Constructor
113  SNSlicer::SNSlicer(const fhicl::ParameterSet& pset)
114  : EDProducer(),//pset),
115  geom(*lar::providerFrom<geo::Geometry>()),
116  {
117  produces<std::vector<sn::SNSlice>>();
118 
119  // Read the fcl-file
120  // fDetSimProducerLabel = pset.get< std::string >("DetSimLabel");
121 
122  fEps = pset.get<double>("Eps");
123  fMinPts = pset.get<int>("MinPts");
124  }
125 
126  //---------------------------------------------------------------------------
127  std::vector<int> SNSlicer::regionQuery(const std::vector<Pt2D>& D, const Pt2D& p) const
128  {
129  std::vector<int> ret;
130  for(unsigned int i = 0; i < D.size(); ++i){
131  if((D[i].x-p.x)*(D[i].x-p.x) + (D[i].y-p.y)*(D[i].y-p.y) < fEps*fEps)
132  ret.push_back(i);
133  }
134  return ret;
135  }
136 
137  //---------------------------------------------------------------------------
138  std::vector<int> Join(const std::vector<int> a, const std::vector<int> b)
139  {
140  std::set<int> s(a.begin(), a.end());
141  s.insert(b.begin(), b.end());
142 
143  return std::vector<int>(s.begin(), s.end());
144  }
145 
146  //---------------------------------------------------------------------------
147  void SNSlicer::expandCluster(const std::vector<Pt2D>& D,
148  int ip,
149  std::vector<int> neiPts, int C,
150  std::vector<bool>& visited,
151  std::vector<int>& inClust) const
152  {
153  inClust[ip] = C;
154 
155  bool any = true;
156  while(any){
157  any = false;
158  for(unsigned int iNP = 0; iNP < neiPts.size(); ++iNP){ // P'
159  if(inClust[neiPts[iNP]] == -1){
160  inClust[neiPts[iNP]] = C;
161  }
162 
163  if(!visited[neiPts[iNP]]){
164  visited[neiPts[iNP]] = true;
165  std::vector<int> neiPts2 = regionQuery(D, D[neiPts[iNP]]);
166  // double Q = 0;
167  // for(int i: neiPts2) Q += D[i].q;
168  const int Q = neiPts2.size();
169  if(Q >= fMinPts){
170  neiPts = Join(neiPts, neiPts2);
171  any = true;
172  break; // restart the while loop
173  }
174  }
175  }
176  }
177  }
178 
179  //---------------------------------------------------------------------------
180  std::vector<std::vector<Pt2D>> SNSlicer::DBSCAN(const std::vector<Pt2D>& D) const
181  {
182  std::vector<bool> visited(D.size(), false);
183  // std::vector<bool> noise(D.size(), false);
184  std::vector<int> inclust(D.size(), -1);
185 
186  int C = 0; // TODO, should this be -1 since we ++ below?
187  for(unsigned int iD = 0; iD < D.size(); ++iD){
188  if(visited[iD]) continue;
189  visited[iD] = true;
190 
191  std::vector<int> neiPts = regionQuery(D, D[iD]);
192  // double Q = 0;
193  // for(int i: neiPts) Q += /D[i].q;
194  const int Q = neiPts.size();
195  if(Q < fMinPts){
196  // noise[iD] = true;
197  }
198  else {
199  ++C;
200  expandCluster(D, iD, neiPts, C, visited, inclust);
201  }
202  }
203 
204  std::vector<std::vector<Pt2D>> ret(C+1);
205  for(unsigned int i = 0; i < D.size(); ++i){
206  if(inclust[i] >= 0) ret[inclust[i]].push_back(D[i]);
207  }
208  return ret;
209  }
210 
211  //---------------------------------------------------------------------------
212  void SNSlicer::produce(art::Event& evt)
213  {
214  std::unique_ptr<std::vector<sn::SNSlice>> slicecol(new std::vector<sn::SNSlice>);
215 
216  // sim::EveIdCalculator eve;
217  // eve.Init(&bt->ParticleList());
218 
219  auto hits = evt.getHandle<std::vector<recob::Hit>>("gaushit");
220  // std::cout << "nhits: " << hits->size() << std::endl;
221 
222  // auto simchans = evt.getHandle<std::vector<sim::SimChannel>>("largeant");
223  // std::cout << "nsimchans: " << simchans->size() << std::endl;
224 
225  // auto ophits = evt.getHandle<std::vector<recob::OpHit>>("ophit");
226 
227  // std::set<raw::ChannelID_t> hitChans;
228 
229  // for(unsigned int hitIdx = 0; hitIdx < hits->size(); ++hitIdx){
230  // const recob::Hit& hit = (*hits)[hitIdx];
231 
232  // if(hit.View() != geo::kZ) continue; // vertical ie collection
233 
234  // std::vector<sim::IDE> ides;
235  // bt->HitToSimIDEs(hit, ides);
236  // for(const sim::IDE& ide: ides){
237  // const art::Ptr<simb::MCTruth>& mct = bt->TrackIDToMCTruth(eve.CalculateEveId(ide.trackID));
238  // if(mct->GetNeutrino().Nu().PdgCode() == 12){
239  // hitChans.insert(hit.Channel());
240  // break;
241  // }
242  // }
243  // }
244 
245  // gTrueDepositE = 0;
246  // gTrueVisE = 0;
247  // for(const sim::SimChannel& simchan: *simchans){
248  // // Only count truth on the collection plane
249  // if(geom.View(simchan.Channel()) != geo::kZ) continue;
250 
251  // for(const auto& it: simchan.TDCIDEMap()){
252  // for(const sim::IDE& ide: it.second){
253  // const art::Ptr<simb::MCTruth>& mct = bt->TrackIDToMCTruth(eve.CalculateEveId(ide.trackID));
254 
255  // if(mct->GetNeutrino().Nu().PdgCode() == 12){
256  // gTrueDepositE += ide.energy;
257  // if(hitChans.count(simchan.Channel())) gTrueVisE += ide.energy;
258  // }
259  // }
260  // }
261  // }
262 
263 
264 
265  std::vector<Pt2D> pts;
266 
267  // cm / tick
268  const double driftVel = dp.DriftVelocity() * dp.SamplingRate() / 1000;
269 
270  // const double driftLen = geom.Cryostat(0).TPC(0).DriftDistance();
271  // const double driftT = driftLen / dp.DriftVelocity();
272 
273  double totTrueQ = 0;
274  double totHitQ = 0;
275 
276  for(unsigned int hitIdx = 0; hitIdx < hits->size(); ++hitIdx){
277  const recob::Hit& hit = (*hits)[hitIdx];
278 
279  if(hit.View() != geo::kZ) continue; // vertical ie collection
280 
281  // std::vector<sim::TrackIDE> eveIDs = bt->HitToEveID(art::Ptr<recob::Hit>(hits, hitIdx));
282 
283  bool isSig = false;
284  // std::vector<sim::IDE> ides;
285  // bt->HitToSimIDEs(hit, ides);
286  // for(const sim::IDE& ide: ides){
287  // const art::Ptr<simb::MCTruth>& mct = bt->TrackIDToMCTruth(eve.CalculateEveId(ide.trackID));
288 
289  // if(mct->GetNeutrino().Nu().PdgCode() == 12){
290  // isSig = true;
291  // }
292  // }
293 
294  const geo::WireGeo* wiregeo = geom.WirePtr(hit.WireID());
295  double xyz[3];
296  wiregeo->GetCenter(xyz);
297 
298  // Apparently this is in ticks. We want it in time units.
299  const double t = hit.PeakTime() * dp.SamplingRate() / 1000;
300 
301  const double q = hit.Integral();
302  totHitQ += q;
303 
304  pts.push_back(Pt2D(xyz[2], t*driftVel, q, isSig, hitIdx));
305  if(isSig) totTrueQ += q;
306  }
307 
308  std::vector<std::vector<Pt2D>> slices = DBSCAN(pts);
309 
310  for(const std::vector<Pt2D>& slice: slices){
311  if(slice.empty()) continue; // TODO - how does this happen?
312 
313  sn::SNSlice prod;
314 
315  prod.meanT = 0;
316  prod.meanZ = 0;
317  prod.totQ = 0;
318 
319  for(const Pt2D& p: slice){
320  prod.meanT += p.q * p.y / driftVel;
321  prod.meanZ += p.q * p.x;
322  prod.totQ += p.q;
323 
324  prod.hits.push_back(art::Ptr<recob::Hit>(hits, p.idx));
325  }
326 
327  prod.meanT /= prod.totQ;
328  prod.meanZ /= prod.totQ;
329 
330  slicecol->push_back(prod);
331  }
332 
333 
334  // gEfficiency = 0;
335  // gPurity = 0;
336 
337  // for(unsigned int i = 0; i < slices.size(); ++i){
338  // double sliceQ = 0;
339  // double pur = 0;
340  // double eff = 0;
341  // for(unsigned int j = 0; j < slices[i].size(); ++j){
342  // sliceQ += slices[i][j].q;
343  // if(slices[i][j].isSig){
344  // pur += slices[i][j].q;
345  // eff += slices[i][j].q;
346  // }
347  // }
348  // }
349 
350  evt.put(std::move(slicecol));
351  }
352 
353  } // namespace
Geometry description of a TPC wireThe wire is a single straight segment on a wire plane...
Definition: WireGeo.h:65
Handle< PROD > getHandle(SelectorBase const &) const
Definition: DataViewImpl.h:382
geo::WireID WireID() const
Definition: Hit.h:233
Planes which measure Z direction.
Definition: geo_types.h:132
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
Definition: Hit.h:224
geo::View_t View() const
View for the plane of the hit.
Definition: Hit.h:232
float totQ
Definition: SNSlice.h:14
float meanZ
Definition: SNSlice.h:13
art framework interface to geometry description
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
const double a
def move(depos, offset)
Definition: depos.py:107
T get(std::string const &key) const
Definition: ParameterSet.h:271
p
Definition: test.py:223
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
Description of geometry of one entire detector.
QCString & insert(uint index, const char *s)
Definition: qcstring.cpp:355
std::vector< TCSlice > slices
Definition: DataStructs.cxx:12
Detector simulation of raw signals on wires.
float meanT
Definition: SNSlice.h:12
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:218
Declaration of signal hit object.
std::vector< art::Ptr< recob::Hit > > hits
Definition: SNSlice.h:16
static bool * b
Definition: config.cpp:1043
Access the description of detector geometry.
Declaration of basic channel signal object.
list x
Definition: train.py:276
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:48
void GetCenter(double *xyz, double localz=0.0) const
Fills the world coordinate of a point on the wire.
Definition: WireGeo.cxx:73
TCEvent evt
Definition: DataStructs.cxx:7
static QCString * s
Definition: config.cpp:1042