AirSlicer_module.cc
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////
2 // \file AirSlicer_module.cc
3 // \brief Modified version of slicer4D for reconstructing high energy
4 // cosmic ray air showers.
5 // \version $Id: AirSlicer_module.cc,v 1.0 2015-04-23 09:30:00 dwwhitti Exp $
6 // \authors grohmc@fnal.gov, dwwhitti@indiana.edu
7 ///////////////////////////////////////////////////////////////////////////
8 
15 
16 #include "Calibrator/Calibrator.h"
17 #include "Geometry/Geometry.h"
20 #include "NovaDAQConventions/DAQConventions.h"
21 #include "RecoBase/CellHit.h"
22 #include "RecoBase/Cluster.h"
23 #include "RecoBase/HitList.h"
24 #include "RecoBase/HoughResult.h"
25 
26 #include "RawData/RawTrigger.h"
27 
28 #include <cmath>
29 #include <string>
30 #include <vector>
31 
32 #include <TH1D.h>
33 #include <TH2D.h>
34 #include <TSpectrum.h>
35 #include <TFitResult.h>
36 #include <TFile.h>
37 #include "TTree.h"
38 #include "TGraph.h"
39 
40 // AirSlicer header
41 namespace airshower {
42 
43  class AirSlicer : public art::EDProducer {
44  public:
45  explicit AirSlicer(fhicl::ParameterSet const &pset);
46  virtual ~AirSlicer();
47 
48  void produce(art::Event& evt);
49  void beginJob();
50 
51  protected:
52  // internal methods
53  bool GenerateCluster(unsigned int point, int ClID);
54  int CountActiveDCM(const std::vector<rb::CellHit>& hitlist);
55  std::vector<rb::Cluster> TemporalClusters( std::vector<art::Ptr<rb::CellHit > > hitList );
56  void HoughRhoTheta(double x1, double y1, double x2, double y2, double* rho, double* theta, double* sigmaRho, double* sigmaTheta);
57  TH2D* GetHoughMap(rb::HitList hitList);
58  TH1D* GetHoughAngles(rb::HitList hitList);
59  TH1D* GetHoughRhos(rb::HitList hitList, double angle, double angleSig);
60  std::pair<double,double> GetHitPos( art::Ptr<rb::CellHit> hit );
61  void FindNeighbors(rb::Cluster clusterList, geo::View_t view);
62  std::vector<rb::Cluster> MakeTrackSlices( rb::Cluster timeSlice, rb::Cluster& noiseCluster, geo::View_t view, bool& mapItrForward );
63 
64  // configuration settings
65  std::string fCellHitInput; ///< Read CellHits from this input
66  unsigned int fMinPts; ///< minimum number of neighbors for a hit to be in a cluster
67  int fMaxSlices; ///< maximum number of time slices to create
68  int fMaxPeaks; ///< maximum number of rho peaks to count
69  bool fWriteTimeSlices; ///< save time slices to output file
70  std::string fTimeSliceInstance; ///< instance name of time slices
71  std::string fTrackSliceInstance; ///< instance name of track slices
72  int fTimeRangeLow; ///< low edge of time range for temporal slicing (integer microseconds)
73  int fTimeRangeHigh; ///< high edge of time range for temporal slicing (integer microseconds)
74  double fTimePeakCut; ///< cut for temporal slicing
75  double fTimePeakSig; ///< significance for temporal slice peak search
76  double fTimePeakThresh; ///< threshold for temporal slice peak search
77  double fRhoPeakSig; ///< significance for rho peak search
78  double fRhoPeakThresh; ///< threshold for rho peak search
79  double fSigCellSepX; ///< scale for X separation between cells in X-view to include in non-noise slice
80  double fSigCellSepY; ///< scale for Y separation between cells in Y-view to include in non-noise slice
81  double fSigCellSepZ; ///< scale for Z separation between cells to include in non-noise slice
82  double fMaxNeighborScore; ///< neighbor score cutoff
83  double fMaxHitSepX; ///< maximum X separation between hits along track slice in X-view
84  double fMaxHitSepY; ///< maximum Y separation between hits along track slice in Y-view
85  double fMaxHitSepZ; ///< maximum Z separation between hits along track slice
86  double fMinHoughPairs; ///< minimum number of hit pairs in maximum Hough angle or rho histogram to proceed
87  double fMinHoughHitSep; ///< minimum separation of hit pairs for Hough map
88  double fHoughRhoPeakThresh; ///< threshold for Hough map rho peak search
89  double fHoughExtrapPlanes; ///< number of planes required for Hough extrapolation
90  double fMaxHoughMatchVal; ///< maximum match value for Hough extrapolation
91  unsigned int fMinTrackHits; ///< minimum number of hits for a track slice
92  unsigned int fMinTracks; ///< minimum number of tracks in each time slice
93  double fChi2NdofCut; ///< cut on Chi2/Ndof for track fit
94  double fMinTrackLen; ///< minimum track length for good tracks
95  int fMaxSliceHits; ///< maximum number of hits to perform slicing
96  bool fSaveHists; ///< save intermediate histograms
97  std::string fRawDataLabel; ///< Data label for trigger prescale
98 
99  // internal objects
100  std::vector< std::vector<unsigned int> > fNeighborList;
101  std::vector< int > fClusterIDs;
102 
103  TSpectrum *fSpecAna;
104  TSpectrum *fRhoSpecAna;
105 
106  // Global Variables for creating a ROOT tree
107  TTree *tree;
108  int run; // Event run number
109  int subrun; // Event subrun number
110  int evtNum; // Event number
111  int evtTime; // Event time in unix time (s)
112  int prescale; // Trigger prescale
113  int ndcm; // Number of active dcms in the event
114  int houghMultY; // Y-View multiplicity from hough transform
115  int trackMultY; // Y-View multiplicity from slicing
116  int houghMultX; // X-View multiplicity from hough transform
117  int trackMultX; // X-View multiplicity from slicing
118  double houghAngleY; // Y-View peak hough angle
119  double houghStDevY; // Y-View stdev in peak hough angle
120  double houghAngleX; // X-View peak hough angle
121  double houghStDevX; // X-View stdev in peak hough angle
122  int totalHits; // total hits in time slice
123  int totalADC; // total ADC in time slice
124  };
125 
126 }
127 
128 namespace airshower
129 {
130  //----------------------------------------------------------------------
132  fCellHitInput (pset.get<std::string >("CellHitInput") ),
133  fMinPts (pset.get<unsigned int>("MinPts") ),
134  fMaxSlices (pset.get<int >("MaxSlices") ),
135  fMaxPeaks (pset.get<int >("MaxPeaks") ),
136  fWriteTimeSlices (pset.get<bool >("WriteTimeSlices") ),
137  fTimeSliceInstance (pset.get<std::string >("TimeSliceInstance") ),
138  fTrackSliceInstance(pset.get<std::string >("TrackSliceInstance")),
139  fTimeRangeLow (pset.get<int >("TimeRangeLow") ),
140  fTimeRangeHigh (pset.get<int >("TimeRangeHigh") ),
141  fTimePeakCut (pset.get<double >("TimePeakCut") ),
142  fTimePeakSig (pset.get<double >("TimePeakSig") ),
143  fTimePeakThresh (pset.get<double >("TimePeakThresh") ),
144  fRhoPeakSig (pset.get<double >("RhoPeakSig") ),
145  fRhoPeakThresh (pset.get<double >("RhoPeakThresh") ),
146  fSigCellSepX (pset.get<double >("SigCellSepX") ),
147  fSigCellSepY (pset.get<double >("SigCellSepY") ),
148  fSigCellSepZ (pset.get<double >("SigCellSepZ") ),
149  fMaxNeighborScore (pset.get<double >("MaxNeighborScore") ),
150  fMaxHitSepX (pset.get<double >("MaxHitSepX") ),
151  fMaxHitSepY (pset.get<double >("MaxHitSepY") ),
152  fMaxHitSepZ (pset.get<double >("MaxHitSepZ") ),
153  fMinHoughPairs (pset.get<int >("MinHoughPairs") ),
154  fMinHoughHitSep (pset.get<double >("MinHoughHitSep") ),
155  fHoughExtrapPlanes (pset.get<int >("HoughExtrapPlanes") ),
156  fMaxHoughMatchVal (pset.get<double >("MaxHoughMatchVal") ),
157  fMinTrackHits (pset.get<unsigned int>("MinTrackHits") ),
158  fMinTracks (pset.get<unsigned int>("MinTracks") ),
159  fChi2NdofCut (pset.get<double >("Chi2NdofCut") ),
160  fMinTrackLen (pset.get<double >("MinTrackLen") ),
161  fMaxSliceHits (pset.get<int >("MaxSliceHits") ),
162  fSaveHists (pset.get<bool >("SaveHists") ),
163  fRawDataLabel (pset.get<std::string >("RawDataLabel") )
164  {
165  produces< std::vector<rb::Cluster> >(fTimeSliceInstance);
166  produces< std::vector<rb::Cluster> >(fTrackSliceInstance);
167 
168  //Spectrums for peak counting
169  fSpecAna = new TSpectrum(fMaxSlices,fTimePeakSig);
170  fRhoSpecAna = new TSpectrum(fMaxPeaks,fRhoPeakSig);
171  }
172 
173  //----------------------------------------------------------------------
175  { }
176 
177  //----------------------------------------------------------------------
179  {
181 
182  // Create the tree branches
183  tree = tfs->make<TTree>("Tree","Tree of info");
184 
185  tree->Branch("run", &run, "run/I" );
186  tree->Branch("subrun", &subrun, "subrun/I" );
187  tree->Branch("evtNum", &evtNum, "evtNum/I" );
188  tree->Branch("eventTime", &evtTime, "eventTime/I" );
189  tree->Branch("ndcm", &ndcm, "ndcm/I" );
190  tree->Branch("prescale", &prescale, "prescale/I" );
191 
192  tree->Branch("houghMultY", &houghMultY, "houghMultY/I" );
193  tree->Branch("trackMultY", &trackMultY, "trackMultY/I" );
194 
195  tree->Branch("houghMultX", &houghMultX, "houghMultX/I" );
196  tree->Branch("trackMultX", &trackMultX, "trackMultX/I" );
197 
198  tree->Branch("houghAngleY",&houghAngleY,"houghAngleY/D");
199  tree->Branch("houghStDevY",&houghStDevY,"houghStDevY/D");
200  tree->Branch("houghAngleX",&houghAngleX,"houghAngleX/D");
201  tree->Branch("houghStDevX",&houghStDevX,"houghStDevX/D");
202 
203  tree->Branch("totalHits", &totalHits, "totalHits/I" );
204  tree->Branch("totalADC" , &totalADC , "totalADC/I" );
205  }
206 
207  //----------------------------------------------------------------------
208  std::vector<rb::Cluster> AirSlicer::TemporalClusters(std::vector<art::Ptr<rb::CellHit > > hitlist)
209  {
210  std::map<int,rb::Cluster> clusterMap;
211  clusterMap[0] = rb::Cluster(); // noise hits (unassociated to peaks)
212  std::vector<art::Ptr<rb::CellHit > > cleanHitlist;
213 
214  // Microsecond-level binning
215  TH1D *fTimeHist = new TH1D("fTimeHist",";time [#mus];hits in view",fTimeRangeHigh-fTimeRangeLow,fTimeRangeLow,fTimeRangeHigh);
216  for ( unsigned int i = 0; i < hitlist.size(); ++i ) {
217  double minCellDistXY(1000.);
218  double minCellDistZ(1000.);
219  std::pair<double,double> hitPosI = GetHitPos( hitlist[i] );
220  double maxHitSepXY(0.);
221  if ( hitlist[i]->View() == geo::kY ) maxHitSepXY = fMaxHitSepY;
222  if ( hitlist[i]->View() == geo::kX ) maxHitSepXY = fMaxHitSepX;
223  for ( unsigned int j = 0; j < hitlist.size(); ++j ) {
224  if ( j == i ) continue;
225  double timeDiff = fabs( hitlist[i]->TNS()*1e-3 - hitlist[j]->TNS()*1e-3 );
226  if ( timeDiff > fTimePeakCut ) continue;
227  // Check whether it's isolated in it's own view
228  if ( hitlist[j]->View() == hitlist[i]->View() ) {
229  std::pair<double,double> hitPosJ = GetHitPos( hitlist[j] );
230  double cellDistXY = fabs(hitPosI.first-hitPosJ.first);
231  if ( cellDistXY < minCellDistXY ) minCellDistXY = cellDistXY;
232  double cellDistZ = fabs(hitPosI.second-hitPosJ.second);
233  if ( cellDistZ < minCellDistZ ) minCellDistZ = cellDistZ;
234  }
235  }
236 
237  if ( minCellDistXY > maxHitSepXY || minCellDistZ > fMaxHitSepZ ) {
238  clusterMap[0].Add(hitlist[i]);
239  continue;
240  }
241  cleanHitlist.push_back(hitlist[i]);
242  fTimeHist->Fill( hitlist[i]->TNS()*1e-3 );
243  }
244 
245  int nPeaks = fSpecAna->Search( fTimeHist, fTimePeakSig, "goff nodraw", fTimePeakThresh );
246  double *peaks = fSpecAna->GetPositionX();
247 
248  // Loop through hits and associate to clusters
249  for ( unsigned int i = 0; i < cleanHitlist.size(); ++i ) {
250  int matchPeak(0);
251  // Find matching time peak
252  for ( int p = 0; p < nPeaks; ++p ) {
253  if ( fabs( cleanHitlist[i]->TNS()*1e-3 - peaks[p] ) < fTimePeakCut ) {
254  matchPeak = p+1;
255  break;
256  }
257  }
258  // Add in this hit
259  if ( clusterMap.find(matchPeak) == clusterMap.end() ) clusterMap[matchPeak] = rb::Cluster();
260  clusterMap[matchPeak].Add(cleanHitlist[i]);
261  }
262 
263  // Transfer to output cluster vector
264  std::vector<rb::Cluster> clusterList;
265  for ( auto itr = clusterMap.begin(); itr != clusterMap.end(); ++itr ) {
266  if ( itr->first == 0 ) itr->second.SetNoise(true);
267  clusterList.push_back(itr->second);
268  }
269 
270  delete fTimeHist;
271  return clusterList;
272  }
273 
274  //----------------------------------------------------------------------
275  void AirSlicer::HoughRhoTheta(double x1, double y1,
276  double x2, double y2,
277  double* rho, double* theta,
278  double* sigmarho, double* sigmatheta)
279  {
280  // Modified from MultiHough/MultiHough2P.cxx
281  *theta = atan2(x1-x2,y2-y1); // angle w.r.t. vertical
282  *rho = 0.5*(cos(*theta)*(x1+x2)+sin(*theta)*(y1+y2));
283  //
284  // Keep rho and theta within range [-pi/2,pi/2) (-R,+R)
285  //
286  while (*theta < -M_PI/2.) {
287  *theta += M_PI;
288  *rho = -(*rho);
289  }
290  while (*theta >= M_PI/2.) {
291  *theta -= M_PI;
292  *rho = -(*rho);
293  }
294 
295  // Compute the error estimates
296  double d = sqrt(pow(x2-x1,2)+pow(y2-y1,2));
297  *sigmarho = 3.0/sqrt(12.);
298  *sigmatheta = M_SQRT2*(3.0/sqrt(12.))/d;
299  }
300 
301  //----------------------------------------------------------------------
303  {
305  TH2D *mapHist = new TH2D("HoughMap",";Rho [cm];Angle [rad]",geoSvc->NPlanes()*4,-1.5*geoSvc->DetLength(),2.5*geoSvc->DetLength(),100,-M_PI/2.,M_PI/2.);
306  for ( unsigned int i = 0; i < hitList.size(); ++i ) {
307  for ( unsigned int j = i+1; j < hitList.size(); ++j ) {
308  if ( hitList[j].fView != hitList[i].fView ) continue;
309  double hitSep = sqrt( pow(hitList[i].fZ-hitList[j].fZ,2) + pow(hitList[i].fXY-hitList[j].fXY,2) );
310  if ( hitSep > geoSvc->DetHalfWidth() ) continue;
311  if ( hitSep < fMinHoughHitSep ) continue;
312  double rho, theta, sigmaRho, sigmaTheta;
313  HoughRhoTheta( hitList[i].fZ, hitList[i].fXY,
314  hitList[j].fZ, hitList[j].fXY,
315  &rho, &theta,
316  &sigmaRho, &sigmaTheta );
317  mapHist->Fill(rho,theta);
318  }
319  }
320  return mapHist;
321  }
322 
323  //----------------------------------------------------------------------
325  {
327  TH1D *angleHist = new TH1D("HoughAngleHist",";Angle [rad];Hit Pairs",200,-M_PI/2.,M_PI/2.);
328 
329  for ( unsigned int i = 0; i < hitList.size(); ++i ) {
330  for ( unsigned int j = i+1; j < hitList.size(); ++j ) {
331  if ( hitList[j].fView != hitList[i].fView ) continue;
332  double hitSep = sqrt( pow(hitList[i].fZ-hitList[j].fZ,2) + pow(hitList[i].fXY-hitList[j].fXY,2) );
333  if ( hitSep > geoSvc->DetHalfWidth() ) continue;
334  if ( hitSep < fMinHoughHitSep ) continue;
335  double rho, theta, sigmaRho, sigmaTheta;
336  HoughRhoTheta( hitList[i].fZ, hitList[i].fXY,
337  hitList[j].fZ, hitList[j].fXY,
338  &rho, &theta,
339  &sigmaRho, &sigmaTheta );
340  angleHist->Fill(theta);
341  }
342  }
343  return angleHist;
344  }
345 
346  //----------------------------------------------------------------------
347  TH1D* AirSlicer::GetHoughRhos(rb::HitList hitList, double angle, double angleSig)
348  {
350  TH1D *rhoHist = new TH1D("HoughRhoHist",";Rho [cm];Hit Pairs",geoSvc->NPlanes()*3,-0.25*geoSvc->DetLength(),1.25*geoSvc->DetLength());
351  for ( unsigned int i = 0; i < hitList.size(); ++i ) {
352  for ( unsigned int j = i+1; j < hitList.size(); ++j ) {
353  if ( hitList[j].fView != hitList[i].fView ) continue;
354  double hitSep = sqrt( pow(hitList[i].fZ-hitList[j].fZ,2) + pow(hitList[i].fXY-hitList[j].fXY,2) );
355  if ( hitSep > geoSvc->DetHalfWidth() ) continue;
356  if ( hitSep < fMinHoughHitSep ) continue;
357  double rho, theta, sigmaRho, sigmaTheta;
358  HoughRhoTheta( hitList[i].fZ, hitList[i].fXY,
359  hitList[j].fZ, hitList[j].fXY,
360  &rho, &theta,
361  &sigmaRho, &sigmaTheta );
362  if ( fabs( theta - angle ) / angleSig > 2. ) continue;
363  rhoHist->Fill(rho);
364  }
365  }
366  return rhoHist;
367  }
368 
369  //----------------------------------------------------------------------
370  std::pair<double,double> AirSlicer::GetHitPos( art::Ptr<rb::CellHit> hit )
371  {
373 
374  unsigned int plane = hit->Plane();
375  unsigned int cell = hit->Cell();
376  const geo::PlaneGeo* thePlane = geoSvc->Plane(plane);
377  const geo::CellGeo* theCell = thePlane->Cell(cell);
378 
379  double xyz[3];
380  theCell->GetCenter(xyz);
381  double xy(0.);
382  if ( thePlane->View() == geo::kX ) xy = xyz[0];
383  if ( thePlane->View() == geo::kY ) xy = xyz[1];
384  double z = xyz[2];
385 
386  return std::make_pair(xy,z);
387  }
388 
389  //----------------------------------------------------------------------
391  {
392  fClusterIDs.clear();
393  fNeighborList.clear();
394  fNeighborList.resize( slice.NCell() );
395 
396  double sigCellSepXY(0.);
397  if ( view == geo::kY ) sigCellSepXY = fSigCellSepY;
398  if ( view == geo::kX ) sigCellSepXY = fSigCellSepX;
399 
400  // First add each point to its own list (the DBSCAN algorithm needs this to work correctly.)
401  for ( unsigned int i = 0; i < slice.NCell(); ++i ) {
402  fClusterIDs.push_back(-1);
403  fNeighborList[i].push_back(i);
404  }
405 
406  // Use i+1 < NCell to protect against the case where NCell = 0
407  for ( unsigned int i = 0; i+1 < slice.NCell(); ++i ) {
408  art::Ptr<rb::CellHit> hitI = slice.Cell(i);
409 
410  std::pair<double,double> hitPosI = GetHitPos( hitI );
411  double XYI = hitPosI.first;
412  double ZI = hitPosI.second;
413 
414  for ( unsigned int j = i+1; j < slice.NCell(); ++j ) {
415  art::Ptr<rb::CellHit> hitJ = slice.Cell(j);
416  if ( hitI->View() != hitJ->View() ) continue;
417 
418  std::pair<double,double> hitPosJ = GetHitPos( hitJ );
419  double XYJ = hitPosJ.first;
420  double ZJ = hitPosJ.second;
421 
422  // use physical distance for neighbor score
423  double deltaR = sqrt( pow(XYI-XYJ,2)/pow(sigCellSepXY,2) + pow(ZI-ZJ,2)/pow(fSigCellSepZ,2) );
424 
425  double score = deltaR;
426 
427  if ( score <= fMaxNeighborScore ) {
428  // i and j are neighbors, so they go into each others' lists
429  fNeighborList[i].push_back(j);
430  fNeighborList[j].push_back(i);
431  }
432  }
433  }
434  }
435 
436  //----------------------------------------------------------------------
437  int AirSlicer::CountActiveDCM(const std::vector<rb::CellHit>& hitlist)
438  {
439  unsigned int ndeaddcms = 0;
440  unsigned int ndcmhits[14][12] = {{0}};
442 
443  for(const rb::CellHit& chit: hitlist){
444  const unsigned int db = cmap->getDiBlock(chit.DaqChannel());
445  const unsigned int dcm = cmap->getDCM(chit.DaqChannel());
446 
447  ndcmhits[db-1][dcm-1]++;
448  }
449 
450  for(unsigned int i = 0; i < 14; ++i)
451  for(unsigned int j = 0; j < 12; ++j)
452  if(ndcmhits[i][j]==0) ndeaddcms++;
453 
454  return 168-ndeaddcms;
455  }
456 
457 
458 
459  //----------------------------------------------------------------------
461  {
462  // Reset tree
463  run = evt.run();
464  subrun = evt.subRun();
465  evtNum = evt.event();
466  evtTime = evt.time().timeHigh();
467  prescale = -999;
468  houghMultY = -999;
469  trackMultY = -999;
470  houghMultX = -999;
471  trackMultX = -999;
472  houghAngleY = -999;
473  houghStDevY = -999;
474  houghAngleX = -999;
475  houghStDevX = -999;
476  totalHits = -999;
477  totalADC = -999;
478 
479  // Modified from DDTPrescaleOffline Package
480  // use rawdata::RawTrigger method to get prescale number
482  evt.getByLabel(fRawDataLabel, rawtrigger);
483  const rawdata::RawTrigger& pre = (*rawtrigger)[0];
485 
489 
490  // Get the cell hits
492  evt.getByLabel(fCellHitInput, hitcol);
493 
494  ndcm = CountActiveDCM(*hitcol);
495 
496  // Load the cell hits into a vector for easy use
497  std::vector<art::Ptr<rb::CellHit > > hitlist;
498  for(unsigned int i = 0; i < hitcol->size(); ++i){
499  art::Ptr<rb::CellHit> hit(hitcol, i);
500  hitlist.push_back(hit);
501  }
502 
503  std::unique_ptr< std::vector<rb::Cluster> > clustercoltime(new std::vector<rb::Cluster>);
504  std::unique_ptr< std::vector<rb::Cluster> > clustercoltracks(new std::vector<rb::Cluster>);
505  rb::Cluster noiseCluster;
506  noiseCluster.SetNoise(true);
507 
508  // Avoid slicing on extremely large events
509  if((int)hitlist.size() > fMaxSliceHits){
510  if ( fWriteTimeSlices ) {
511  clustercoltime->push_back(noiseCluster);
512  evt.put(std::move(clustercoltime),fTimeSliceInstance);
513  }
514 
515  trackMultY=1000;
516  houghMultY=1000;
517  trackMultX=1000;
518  houghMultX=1000;
519 
520  tree->Fill();
521  houghMultY=-999;
522  trackMultY=-999;
523  houghMultX=-999;
524  trackMultX=-999;
525  houghAngleY=-999;
526  houghStDevY=-999;
527  houghAngleX=-999;
528  houghStDevX=-999;
529  totalHits=-999;
530  totalADC=-999;
531  }
532  else{
533  // Sort the hits by time to improve the speed.
534  // WARNING: The rest of the code assumes that the hits are time sorted!
535  rb::SortByTime(hitlist);
536 
537  // Slice hits by time (with minimal spatial proximity in each view)
538  std::vector<rb::Cluster> timeSlices = TemporalClusters(hitlist);
539 
540  // Split time-sliced clusters into separate views
541  std::vector<rb::Cluster> timeSlicesY;
542  std::vector<rb::Cluster> timeSlicesX;
543 
544  for ( unsigned int i = 0; i < timeSlices.size(); ++i ) {
545  if ( timeSlices[i].IsNoise() ) {
546  for ( unsigned int j = 0; j < timeSlices[i].NCell(); ++j ) noiseCluster.Add(timeSlices[i].AllCells()[j]);
547  }
548  rb::Cluster hitsY(geo::kY);
549  rb::Cluster hitsX(geo::kX);
550  for ( unsigned int j = 0; j < timeSlices[i].NCell(); ++j ) {
551  if ( timeSlices[i].AllCells()[j]->View() == geo::kY ) hitsY.Add( timeSlices[i].AllCells()[j] );
552  if ( timeSlices[i].AllCells()[j]->View() == geo::kX ) hitsX.Add( timeSlices[i].AllCells()[j] );
553  }
554  hitsY.SetNoise( timeSlices[i].IsNoise() );
555  hitsX.SetNoise( timeSlices[i].IsNoise() );
556  timeSlicesY.push_back(hitsY);
557  timeSlicesX.push_back(hitsX);
558  }
559  noiseCluster.SetNoise(true);
560 
561  if ( fWriteTimeSlices ) {
562  clustercoltime->push_back(noiseCluster);
563  for ( unsigned int i = 0; i < timeSlices.size(); ++i ) if ( !timeSlices[i].IsNoise() && timeSlices[i].NCell() > 0 ) clustercoltime->push_back(timeSlices[i]);
564  evt.put(std::move(clustercoltime),fTimeSliceInstance);
565  }
566 
567  // Do track slicing on time slices by view
568  for ( unsigned int i = 0; i < timeSlices.size(); ++i ) {
569  if ( timeSlices[i].IsNoise() ) continue;
570  totalHits = timeSlices[i].NCell();
571  totalADC = timeSlices[i].TotalADC();
572  std::vector<rb::Cluster> trackSlicesY;
573  std::vector<rb::Cluster> trackSlicesX;
574 
575  bool mapItrForward(true); // pick direction based on Y-view Hough angle
576 
577  trackSlicesY = MakeTrackSlices( timeSlicesY[i], noiseCluster, geo::kY, mapItrForward );
578  trackSlicesX = MakeTrackSlices( timeSlicesX[i], noiseCluster, geo::kX, mapItrForward );
579 
580  // Add all of our slices to the event store.
581  for ( unsigned int j = 0; j < trackSlicesY.size(); ++j )
582  if ( trackSlicesY[j].NCell() > 0 ) clustercoltracks->push_back(trackSlicesY[j]);
583  for ( unsigned int j = 0; j < trackSlicesX.size(); ++j )
584  if ( trackSlicesX[j].NCell() > 0 ) clustercoltracks->push_back(trackSlicesX[j]);
585 
586  // Fill the ROOT tree and reset the tree variables
587  tree->Fill();
588  houghMultY=-999;
589  trackMultY=-999;
590  houghMultX=-999;
591  trackMultX=-999;
592  houghAngleY=-999;
593  houghStDevY=-999;
594  houghAngleX=-999;
595  houghStDevX=-999;
596  totalHits=-999;
597  totalADC=-999;
598  } // end for
599  }
600 
601  clustercoltracks->push_back(noiseCluster);
602  evt.put(std::move(clustercoltracks),fTrackSliceInstance);
603  }
604 
605  //----------------------------------------------------------------------
606  std::vector<rb::Cluster> AirSlicer::MakeTrackSlices( rb::Cluster timeSlice, rb::Cluster& noiseCluster, geo::View_t view, bool& mapItrForward )
607  {
608  std::vector<rb::Cluster> trackSlices;
609  std::vector<rb::Cluster> finalTrackSlices;
610  if ( timeSlice.IsNoise() ) return trackSlices;
611 
613 
615 
616  double maxHitSepXY(0.);
617  if ( view == geo::kY ) maxHitSepXY = fMaxHitSepY;
618  if ( view == geo::kX ) maxHitSepXY = fMaxHitSepX;
619 
620  rb::HitList thisHitList( timeSlice );
621 
622  // Generate angular Hough map for entire slice
623  std::string viewName("XY");
624  if ( view == geo::kY ) viewName = std::string("Y");
625  if ( view == geo::kX ) viewName = std::string("X");
626 
627  if ( fSaveHists ) {
628  TH2D *mapHist = GetHoughMap( thisHitList );
629  mapHist->SetName(TString::Format("HoughMap_%s_%i_%i_%i",viewName.c_str(),run,subrun,evtNum));
630  tfs->make<TH2D>(*mapHist);
631  delete mapHist;
632  }
633  TH1D *angleHist = GetHoughAngles( thisHitList );
634 
635  angleHist->SetName(TString::Format("HoughAngleHist_%s_%i_%i_%i",viewName.c_str(),run,subrun,evtNum));
636  if ( fSaveHists ) tfs->make<TH1D>(*angleHist);
637  int maxBin = angleHist->GetMaximumBin();
638  if ( angleHist->GetBinContent(maxBin) < fMinHoughPairs ){
639  delete angleHist;
640  return trackSlices; // require minimum number of contributing cell pairs
641  }
642 
643  TF1 *agaus=new TF1("agaus","gaus",angleHist->GetBinCenter(maxBin-5),angleHist->GetBinCenter(maxBin+5));
644  agaus->SetParameter(0,angleHist->GetBinContent(maxBin));
645  agaus->SetParameter(1,angleHist->GetBinCenter(maxBin));
646  agaus->SetParameter(2,.01);
647  agaus->SetParLimits(1,angleHist->GetBinCenter(maxBin-1),angleHist->GetBinCenter(maxBin+1));
648  TFitResultPtr fitResult = angleHist->Fit("agaus","QSNB","",angleHist->GetBinCenter(maxBin-10),angleHist->GetBinCenter(maxBin+10));
649  int fitStatus = fitResult;
650 
651  if ( fitStatus != 0 ){
652  delete agaus;
653  delete angleHist;
654  return trackSlices; // Failed to find maximum Hough angle! Do something?
655  }
656 
657  double maxAngle = fitResult->Parameter(1);
658  double sigAngle = fitResult->Parameter(2);
659  sigAngle=sqrt(sigAngle*sigAngle);
660  delete agaus;
661  delete angleHist;
662 
663  // Generate rho Hough map for entire slice
664  TH1D *rhoHist = GetHoughRhos( thisHitList, maxAngle, sigAngle );
665  rhoHist->SetName(TString::Format("HoughRhoHist_%s_%i_%i_%i",viewName.c_str(),run,subrun,evtNum));
666  if ( fSaveHists ) tfs->make<TH1D>(*rhoHist);
667  int mult=fRhoSpecAna->Search( rhoHist, fRhoPeakSig, "goff nodraw", fRhoPeakThresh );
668 
669  // fill the tree variables for the appropriate view
670  if(view==geo::kY){
671  houghMultY=mult;
672  houghAngleY=maxAngle;
673  houghStDevY=sigAngle;
674  }
675  if(view==geo::kX){
676  houghMultX=mult;
677  houghAngleX=maxAngle;
678  houghStDevX=sigAngle;
679  }
680  delete rhoHist;
681 
682  // Group hits by plane
683  std::map< int, rb::Cluster > hitsByPlane;
684  for ( unsigned int hitItr = 0; hitItr < timeSlice.NCell(); ++hitItr ) {
685  if ( timeSlice.AllCells()[hitItr]->View() != view ) continue; // just to check
686  int plane = timeSlice.AllCells()[hitItr]->Plane();
687  if ( hitsByPlane.find(plane) == hitsByPlane.end() ) hitsByPlane[plane] = rb::Cluster(view);
688  hitsByPlane[plane].Add( timeSlice.AllCells()[hitItr] );
689  }
690 
691  // Loop through plane groupings
692  std::map< int, std::vector<rb::Cluster> > inPlaneClusters;
693  for ( auto planeItr = hitsByPlane.begin(); planeItr != hitsByPlane.end(); ++planeItr ) {
694  int thePlane = planeItr->first;
695  // Cluster hits in this plane
696  int CurrentClusterID = 1;
697  FindNeighbors( planeItr->second, view );
698  for ( unsigned int j = 0; j < planeItr->second.NCell(); ++j ) {
699  // if this cell isn't classified, attempt to expand the cluster
700  if ( fClusterIDs[j] == -1 ) {
701  if ( GenerateCluster( j, CurrentClusterID ) ) CurrentClusterID++;
702  }
703  }
704  // Group hits by cluster in this plane
705  inPlaneClusters[thePlane].resize(CurrentClusterID,rb::Cluster(view));
706  for ( unsigned int j = 0; j < planeItr->second.NCell(); ++j ) {
707  if ( fClusterIDs[j] == 0 ) {
708  noiseCluster.Add( planeItr->second.AllCells()[j] );
709  continue;
710  }
711  inPlaneClusters[thePlane][fClusterIDs[j]].Add( planeItr->second.AllCells()[j] );
712  }
713  } // Now inPlaneClusters contains clusters within each plane.
714 
715  // Loop through planes in this temporal slice
716  if ( view == geo::kY ) mapItrForward = (maxAngle > 0.);
717  // pick the direction for the X- and Y-views from this slice's Y-view, then pass it back for the X-view call
718  auto mapItrStart = inPlaneClusters.begin();
719  auto mapItrEnd = inPlaneClusters.end();
720  if ( !mapItrForward ) {
721  mapItrStart = --(inPlaneClusters.rbegin().base());
722  mapItrEnd = --(inPlaneClusters.rend().base());
723  }
724 
725  // Create first clusters from first plane
726  for ( unsigned int clusItr = 0; clusItr < mapItrStart->second.size(); ++clusItr ) {
727  trackSlices.push_back( mapItrStart->second[clusItr] );
728  }
729 
730  // Loop through remaining planes
731  auto mapItr = mapItrStart;
732  if ( mapItrForward ) ++mapItr;
733  else --mapItr;
734  while ( mapItr != mapItrEnd ) {
735  if ( mapItr->second.size() == 0 ) { // continue
736  if ( mapItrForward ) ++mapItr;
737  else --mapItr;
738  continue;
739  }
740  int thisPlane = mapItr->first;
741 
742  // Match each cluster in this plane with the best seed cluster
743  std::vector<int> bestMatchInt(inPlaneClusters[thisPlane].size(),-1);
744  std::vector<double> bestMatchVal(inPlaneClusters[thisPlane].size(),100000.);
745  for ( unsigned int j = 1; j < mapItr->second.size(); ++j ) { // cluster 0 is noise
746  if ( mapItr->second[j].NCell() == 0 ) continue;
747  // Find mean position of this cluster in this plane
748  double meanXY(0.);
749  double meanZ(0.);
750  for ( unsigned int c = 0; c < mapItr->second[j].NCell(); ++c ) {
751  art::Ptr<rb::CellHit> hit = mapItr->second[j].Cell(c);
752  std::pair<double,double> hitPos = GetHitPos( hit );
753  meanXY += hitPos.first;
754  meanZ += hitPos.second;
755  }
756  meanXY = meanXY / double(mapItr->second[j].NCell());
757  meanZ = meanZ / double(mapItr->second[j].NCell());
758 
759  // Loop through track clusters
760  for ( unsigned int i = 0; i < trackSlices.size(); ++i ) {
761  // Loop through hits in this track slice that are within the last few planes
762  std::map< int, std::pair<double,double> > trackSliceClusterPositions;
763  std::map< int, int > trackSliceClusterCounts;
764  double meanXYC(0.), meanZC(0.);
765  int nCells(0), maxPlane(0), minPlane(9999);
766  for ( unsigned int c = 0; c < trackSlices[i].NCell(); ++c ) {
767  if ( abs( int(trackSlices[i].Cell(c)->Plane()) - int(thisPlane) ) > 10 ) continue;
768  if ( trackSlices[i].Cell(c)->Plane() > maxPlane ) maxPlane = trackSlices[i].Cell(c)->Plane();
769  if ( trackSlices[i].Cell(c)->Plane() < minPlane ) minPlane = trackSlices[i].Cell(c)->Plane();
770  std::pair<double,double> hitPosC = GetHitPos( trackSlices[i].Cell(c) );
771  trackSliceClusterPositions[int(trackSlices[i].Cell(c)->Plane())].first += hitPosC.first;
772  trackSliceClusterPositions[int(trackSlices[i].Cell(c)->Plane())].second += hitPosC.second;
773  trackSliceClusterCounts[int(trackSlices[i].Cell(c)->Plane())]++;
774  meanXYC += hitPosC.first;
775  meanZC += hitPosC.second;
776  nCells++;
777  }
778  auto posItr = trackSliceClusterPositions.begin();
779  auto countItr = trackSliceClusterCounts.begin();
780  for ( unsigned int c = 0; c < trackSliceClusterPositions.size(); ++c ) {
781  posItr->second.first = posItr->second.first / countItr->second;
782  posItr->second.second = posItr->second.second / countItr->second;
783  posItr++;
784  countItr++;
785  }
786  if ( nCells == 0 ) {
787  continue;
788  }
789  meanXYC = meanXYC / double( nCells );
790  meanZC = meanZC / double( nCells );
791  int nPlanes = maxPlane-minPlane+1;
792  double closestClusterDistXY(1000000.);
793  double closestClusterDistZ(1000000.);
794  double meanHoughAngle(0.), meanHoughAngleSig(0.);
795  double meanHoughRho(0.), meanHoughRhoSig(0.);
796  int nMeanEntries(0);
797  for ( auto c = trackSliceClusterPositions.begin(); c != trackSliceClusterPositions.end(); ++c ) {
798  double deltaXY = fabs(c->second.first-meanXY);
799  double deltaZ = fabs(c->second.second-meanZ);
800  if ( deltaXY < closestClusterDistXY ) closestClusterDistXY = deltaXY;
801  if ( deltaZ < closestClusterDistZ ) closestClusterDistZ = deltaZ;
802  double houghRho, houghAngle, houghRhoSig, houghAngleSig;
803  HoughRhoTheta( c->second.second, c->second.first,
804  meanZ, meanXY,
805  &houghRho, &houghAngle, &houghRhoSig, &houghAngleSig );
806  meanHoughAngle += houghAngle;
807  meanHoughRho += houghRho;
808  meanHoughAngleSig += houghAngleSig*houghAngleSig;
809  meanHoughRhoSig += houghAngleSig*houghRhoSig;
810  nMeanEntries++;
811  }
812  if ( closestClusterDistXY > maxHitSepXY || closestClusterDistZ > fMaxHitSepZ ) {
813  continue;
814  }
815  meanHoughAngle = meanHoughAngle / double(nMeanEntries); // should already have excluded nMeanEntries == 0
816  meanHoughRho = meanHoughRho / double(nMeanEntries);
817  meanHoughAngleSig = sqrt(meanHoughAngleSig) / double(nMeanEntries);
818  meanHoughRhoSig = sqrt(meanHoughRhoSig) / double(nMeanEntries);
819  double matchVal;
820  if ( nPlanes <= 2*fHoughExtrapPlanes ) {
821  // Compare Hough angle between mean track slice cluster position and this cluster's position
822  // to the Hough angle of the time slice
823  double houghRho, houghAngle, houghRhoSig, houghAngleSig;
824  HoughRhoTheta( meanZ, meanXY, meanZC, meanXYC, &houghRho, &houghAngle, &houghRhoSig, &houghAngleSig );
825  matchVal = std::min(fabs(houghAngle-maxAngle),M_PI-fabs(houghAngle-maxAngle))/sigAngle;
826  } else {
827  // Compare mean Hough angle between all clusters in the track slice and this cluster's position
828  // to the Hough angle of the time slice
829  matchVal = std::min(fabs(meanHoughAngle-maxAngle),M_PI-fabs(meanHoughAngle-maxAngle))/sigAngle;
830  }
831  if ( matchVal > fMaxHoughMatchVal ) continue;
832  if ( matchVal < bestMatchVal[j] ) {
833  bestMatchInt[j] = i;
834  bestMatchVal[j] = matchVal;
835  }
836  }
837  }
838  for ( unsigned int j = 1; j < mapItr->second.size(); ++j ) { // cluster 0 is noise
839  // If no match found, add this cluster as a new seed
840  if ( bestMatchInt[j] < 0 ) {
841  trackSlices.push_back( mapItr->second[j] );
842  continue;
843  }
844  // Otherwise add the hits from this cluster to the best-matched track cluster
845  for ( unsigned int k = 0; k < mapItr->second[j].NCell(); ++k ) {
846  trackSlices[bestMatchInt[j]].Add( mapItr->second[j].AllCells()[k] );
847  }
848  }
849  if ( mapItrForward ) ++mapItr;
850  else --mapItr;
851  }
852 
853  for ( unsigned int i = 0; i < trackSlices.size(); ++i ) {
854  if ( trackSlices[i].NCell() < fMinTrackHits ) {
855  for ( unsigned int j = 0; j < trackSlices[i].NCell(); ++j ) {
856  noiseCluster.Add( trackSlices[i].AllCells()[j] );
857  }
858  } else {
859  finalTrackSlices.push_back( trackSlices[i] );
860  }
861  }
862  if ( finalTrackSlices.size() < fMinTracks ) finalTrackSlices.clear();
863  if(view==geo::kY) trackMultY=finalTrackSlices.size();
864  if(view==geo::kX) trackMultX=finalTrackSlices.size();
865  return finalTrackSlices;
866  }
867 
868  //----------------------------------------------------------------------
869  bool AirSlicer::GenerateCluster(unsigned int point, int ClID)
870  {
871  // In the original DBSCAN paper, this is the function they called
872  // "ExpandCluster." How this function works is most easily understood
873  // by reading that paper (don't worry, it is pretty short...)
874 
875  // Get the list of neighbors for 'point.'
876  std::vector<unsigned int> seeds = fNeighborList[point];
877 
878  // If 'point' is not a core point, label it as noise and return.
879  if(seeds.size() < fMinPts) {
880  fClusterIDs[point] = 0;
881  return false;
882  }
883  else {
884  // Assign 'point' and the neighbors of 'point' to the cluster ClID.
885  for(unsigned int seedi = 0; seedi < seeds.size(); ++seedi)
886  fClusterIDs[point] = ClID;
887  seeds.erase(seeds.begin());
888 
889  // Loop over the neighbors of 'point' to see if they are also core
890  // points.
891  while(seeds.size() > 0) {
892  // Get the list of neighbors for the first seed point.
893  std::vector<unsigned int> result = fNeighborList[seeds[0]];
894 
895  // If the first seed point is also a core point, add its neighbors
896  // to the list of seeds and assigne them to the cluster ClID.
897  if(result.size() >= fMinPts) {
898  for(unsigned int resulti = 0; resulti < result.size(); ++resulti) {
899  // If the point is unassigned (-1) or previously labeled as
900  // noise (0), asign it ClID.
901  if(fClusterIDs[result[resulti]] == -1 ||
902  fClusterIDs[result[resulti]] == 0) {
903  // Only add this point to the list of seeds if it was
904  // previously unassigned.
905  if(fClusterIDs[result[resulti]] == -1)
906  seeds.push_back(result[resulti]);
907  fClusterIDs[result[resulti]] = ClID;
908  } // end if(resulti is -1 or 0)
909 
910  } // end for resulti
911 
912  } // end if result.size() >= fMinPts
913  seeds.erase(seeds.begin());
914 
915  } // end while
916  return true;
917  } // end else
918 
919  } // end GenerateCluster function
920 
921 } // end namespace airshower
922 /////////////////////////////////////////////////////////////////////////
923 
924 namespace airshower
925 {
927 }
double fMaxHoughMatchVal
maximum match value for Hough extrapolation
SubRunNumber_t subRun() const
Definition: Event.h:72
double fMinHoughHitSep
minimum separation of hit pairs for Hough map
uint32_t fTriggerMask_Prescale
Definition: RawTrigger.h:44
Double_t angle
Definition: plot.C:86
unsigned int NCell(geo::View_t view) const
Number of cells in view view.
Definition: Cluster.cxx:134
double fTimePeakThresh
threshold for temporal slice peak search
void GetCenter(double *xyz, double localz=0.0) const
Definition: CellGeo.cxx:159
int fTimeRangeHigh
high edge of time range for temporal slicing (integer microseconds)
unsigned int fMinPts
minimum number of neighbors for a hit to be in a cluster
fvar< T > fabs(const fvar< T > &x)
Definition: fabs.hpp:15
Float_t y1[n_points_granero]
Definition: compare.C:5
void SetNoise(bool noise)
Declare the cluster to consist of noise hits or not.
Definition: Cluster.h:161
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
unsigned short Plane() const
Definition: CellHit.h:39
Float_t x1[n_points_granero]
Definition: compare.C:5
double fSigCellSepX
scale for X separation between cells in X-view to include in non-noise slice
geo::View_t View() const
Definition: CellHit.h:41
const CellGeo * Cell(int icell) const
Definition: PlaneGeo.h:48
const char * p
Definition: xmltok.h:285
T sqrt(T number)
Definition: d0nt_math.hpp:156
constexpr std::uint32_t timeHigh() const
Definition: Timestamp.h:35
constexpr T pow(T x)
Definition: pow.h:75
Vertical planes which measure X.
Definition: PlaneGeo.h:28
std::pair< double, double > GetHitPos(art::Ptr< rb::CellHit > hit)
A collection of associated CellHits.
Definition: Cluster.h:47
double DetLength() const
double fTimePeakSig
significance for temporal slice peak search
void abs(TH1 *hist)
std::pair< Spectrum *, CheatDecomp * > make_pair(SpectrumLoaderBase &loader_data, SpectrumLoaderBase &loader_mc, HistAxis *axis, Cut *cut, const SystShifts &shift, const Var &wei)
Definition: DataMCLoad.C:336
void SortByTime(std::vector< art::Ptr< rb::CellHit > > &c)
Sort c in time order (earliest to latest).
Definition: CellHit.cxx:134
const PlaneGeo * Plane(unsigned int i) const
double fMinTrackLen
minimum track length for good tracks
DEFINE_ART_MODULE(TestTMapFile)
std::vector< rb::Cluster > MakeTrackSlices(rb::Cluster timeSlice, rb::Cluster &noiseCluster, geo::View_t view, bool &mapItrForward)
#define M_PI
Definition: SbMath.h:34
Horizontal planes which measure Y.
Definition: PlaneGeo.h:29
art::PtrVector< rb::CellHit > AllCells() const
Get all cells from both views.
Definition: Cluster.cxx:180
double fSigCellSepZ
scale for Z separation between cells to include in non-noise slice
int fTimeRangeLow
low edge of time range for temporal slicing (integer microseconds)
virtual void Add(const art::Ptr< rb::CellHit > &cell, double weight=1)
Definition: Cluster.cxx:84
ProductID put(std::unique_ptr< PROD > &&product)
Definition: Event.h:102
unsigned short Cell() const
Definition: CellHit.h:40
std::string fRawDataLabel
Data label for trigger prescale.
View_t View() const
Which coordinate does this plane measure.
Definition: PlaneGeo.h:53
Just the essential information required for track fitting.
Definition: HitList.h:40
double fRhoPeakSig
significance for rho peak search
TH1D * GetHoughAngles(rb::HitList hitList)
double fTimePeakCut
cut for temporal slicing
Geometry information for a single readout plane.
Definition: PlaneGeo.h:36
Float_t d
Definition: plot.C:236
void HoughRhoTheta(double x1, double y1, double x2, double y2, double *rho, double *theta, double *sigmaRho, double *sigmaTheta)
const double j
Definition: BetheBloch.cxx:29
double fMinHoughPairs
minimum number of hit pairs in maximum Hough angle or rho histogram to proceed
EventNumber_t event() const
Definition: Event.h:67
std::vector< int > fClusterIDs
std::string fCellHitInput
Read CellHits from this input.
double fChi2NdofCut
cut on Chi2/Ndof for track fit
double fHoughExtrapPlanes
number of planes required for Hough extrapolation
Definition: View.py:1
std::vector< std::vector< unsigned int > > fNeighborList
z
Definition: test.py:28
std::string fTrackSliceInstance
instance name of track slices
int CountActiveDCM(const std::vector< rb::CellHit > &hitlist)
Definition: run.py:1
double fHoughRhoPeakThresh
threshold for Hough map rho peak search
bool fSaveHists
save intermediate histograms
std::vector< rb::Cluster > TemporalClusters(std::vector< art::Ptr< rb::CellHit > > hitList)
art::Ptr< rb::CellHit > Cell(geo::View_t view, unsigned int viewIdx) const
Get the ith cell from view view.
Definition: Cluster.cxx:145
::xsd::cxx::tree::string< char, simple_type > string
Definition: Database.h:154
A rawdata::RawDigit with channel information decoded.
Definition: CellHit.h:27
int fMaxSlices
maximum number of time slices to create
T * make(ARGS...args) const
T sin(T number)
Definition: d0nt_math.hpp:132
double DetHalfWidth() const
Data resulting from a Hough transform on the cell hit positions.
void produce(art::Event &evt)
double fMaxNeighborScore
neighbor score cutoff
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
std::string fTimeSliceInstance
instance name of time slices
Definition: event.h:1
unsigned int fMinTrackHits
minimum number of hits for a track slice
bool GenerateCluster(unsigned int point, int ClID)
unsigned int fMinTracks
minimum number of tracks in each time slice
double fMaxHitSepX
maximum X separation between hits along track slice in X-view
void FindNeighbors(rb::Cluster clusterList, geo::View_t view)
T cos(T number)
Definition: d0nt_math.hpp:78
Timestamp time() const
Definition: Event.h:61
double fSigCellSepY
scale for Y separation between cells in Y-view to include in non-noise slice
double fRhoPeakThresh
threshold for rho peak search
cmap::CMap class source code
Definition: CMap.cxx:17
double fMaxHitSepZ
maximum Z separation between hits along track slice
bool fWriteTimeSlices
save time slices to output file
dcm_id_t getDCM(dchan daqchan) const
Decode the dcm ID from a dchan.
void Format(TGraph *gr, int lcol, int lsty, int lwid, int mcol, int msty, double msiz)
Definition: Style.cxx:154
unsigned int NPlanes() const
T min(const caf::Proxy< T > &a, T b)
bool IsNoise() const
Is the noise flag set?
Definition: Cluster.h:163
Float_t e
Definition: plot.C:35
RunNumber_t run() const
Definition: Event.h:77
double fMaxHitSepY
maximum Y separation between hits along track slice in Y-view
Encapsulate the cell geometry.
Definition: CellGeo.h:25
AirSlicer(fhicl::ParameterSet const &pset)
int fMaxPeaks
maximum number of rho peaks to count
TH1D * GetHoughRhos(rb::HitList hitList, double angle, double angleSig)
diblock_t getDiBlock(dchan daqchan) const
Decode the diblock ID from a dchan.
TH2D * GetHoughMap(rb::HitList hitList)
Encapsulate the geometry of one entire detector (near, far, ndos)
int fMaxSliceHits
maximum number of hits to perform slicing
T atan2(T number)
Definition: d0nt_math.hpp:72