LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
cluster::EndPointAlg Class Reference

Algorithm to find 2D end points. More...

#include "EndPointAlg.h"

Public Member Functions

 EndPointAlg (fhicl::ParameterSet const &pset)
 
virtual ~EndPointAlg ()
 
void reconfigure (fhicl::ParameterSet const &pset)
 
size_t EndPoint (const art::PtrVector< recob::Cluster > &clusIn, std::vector< recob::EndPoint2D > &vtxcol, std::vector< art::PtrVector< recob::Hit > > &vtxHitsOut, art::Event const &evt, std::string const &label)
 

Private Member Functions

double Gaussian (int x, int y, double sigma)
 
double GaussianDerivativeX (int x, int y)
 
double GaussianDerivativeY (int x, int y)
 
void VSSaveBMPFile (const char *fileName, unsigned char *pix, int dx, int dy)
 

Private Attributes

int fTimeBins
 
int fMaxCorners
 
double fGsigma
 
int fWindow
 
double fThreshold
 
int fSaveVertexMap
 

Detailed Description

Algorithm to find 2D end points.

Definition at line 28 of file EndPointAlg.h.

Constructor & Destructor Documentation

cluster::EndPointAlg::EndPointAlg ( fhicl::ParameterSet const &  pset)
explicit

The algorithm is based on: C. Harris and M. Stephens (1988). "A combined corner and edge detector". Proceedings of the 4th Alvey Vision Conference. pp. 147-151. B. Morgan (2010). "Interest Point Detection for Reconstruction in High Granularity Tracking Detectors". arXiv:1006.3012v1 [physics.ins-det]

Definition at line 51 of file EndPointAlg.cxx.

References reconfigure().

52 {
53  this->reconfigure(pset);
54 }
void reconfigure(fhicl::ParameterSet const &pset)
Definition: EndPointAlg.cxx:62
cluster::EndPointAlg::~EndPointAlg ( )
virtual

Definition at line 57 of file EndPointAlg.cxx.

58 {
59 }

Member Function Documentation

size_t cluster::EndPointAlg::EndPoint ( const art::PtrVector< recob::Cluster > &  clusIn,
std::vector< recob::EndPoint2D > &  vtxcol,
std::vector< art::PtrVector< recob::Hit > > &  vtxHitsOut,
art::Event const &  evt,
std::string const &  label 
)

Definition at line 136 of file EndPointAlg.cxx.

References art::PtrVector< T >::begin(), art::PtrVector< T >::clear(), geo::CryostatID::Cryostat, geo::GeometryCore::Cryostat(), detinfo::DetectorProperties::DriftVelocity(), detinfo::DetectorProperties::Efield(), art::PtrVector< T >::end(), fGsigma, fMaxCorners, fSaveVertexMap, fThreshold, fTimeBins, fWindow, Gaussian(), GaussianDerivativeX(), GaussianDerivativeY(), n, geo::PlaneGeo::Nwires(), geo::TPCGeo::Plane(), geo::PlaneID::Plane, art::PtrVector< T >::push_back(), detinfo::DetectorProperties::ReadOutWindowSize(), detinfo::DetectorProperties::SamplingRate(), art::PtrVector< T >::size(), detinfo::DetectorProperties::Temperature(), geo::CryostatGeo::TPC(), geo::TPCID::TPC, geo::GeometryCore::Views(), VSSaveBMPFile(), w, geo::WireID::WireID(), geo::GeometryCore::WirePitch(), x, and y.

Referenced by cluster::EndPointModule::produce().

141 {
142 
144  const detinfo::DetectorProperties* detp = lar::providerFrom<detinfo::DetectorPropertiesService>();
145 
146  //Point to a collection of vertices to output.
147  std::vector< art::Ptr<recob::Hit> > hit;
148 
149  art::FindManyP<recob::Hit> fmh(clusIn, evt, label);
150 
151  int flag = 0;
152  int windex = 0;//the wire index to make sure the end point finder does not fall off the edge of the hit map
153  int tindex = 0;//the time index to make sure the end point finder does not fall off the edge of the hit map
154  int n = 0; //index of window cell. There are 49 cells in the 7X7 Gaussian and Gaussian derivative windows
155  unsigned int numberwires = 0;
156  const unsigned int numbertimesamples = detp->ReadOutWindowSize();
157  const float TicksPerBin = numbertimesamples / fTimeBins;
158 
159  double MatrixAAsum = 0.;
160  double MatrixBBsum = 0.;
161  double MatrixCCsum = 0.;
162  std::vector<double> Cornerness2;
163  //gaussian window definitions. The cell weights are calculated here to help the algorithm's speed
164  double w[49] = {0.};
165  double wx[49] = {0.};
166  double wy[49] = {0.};
167  int ctr = 0;
168  for(int i = -3; i < 4; ++i){
169  for(int j = 3; j > -4; --j){
170  w[ctr] = Gaussian(i, j, fGsigma);
171  wx[ctr] = GaussianDerivativeX(i,j);
172  wy[ctr] = GaussianDerivativeY(i,j);
173  ++ctr;
174  }
175  }
176 
177  unsigned int wire = 0;
178  unsigned int wire2 = 0;
179  for(auto view : geom->Views()){
182  hit.clear();
183  size_t cinctr = 0;
184  while(clusterIter!= clusIn.end() ) {
185  if((*clusterIter)->View() == view){
186  hit = fmh.at(cinctr);
187  }//end if cluster is in the correct view
188  clusterIter++;
189  ++cinctr;
190  }
191 
192  if(hit.size() == 0) continue;
193 
194  geo::WireID wid = hit[0]->WireID();
195  numberwires = geom->Cryostat(wid.Cryostat).TPC(wid.TPC).Plane(wid.Plane).Nwires();
196  mf::LogInfo("EndPointAlg") << " --- endpoints check "
197  << numberwires << " "
198  << numbertimesamples << " "
199  << fTimeBins;
200 
201  std::vector < std::vector < double > > MatrixAsum(numberwires);
202  std::vector < std::vector < double > > MatrixBsum(numberwires);
203  std::vector < std::vector < double > > hit_map(numberwires); //the map of hits
204 
205  //the index of the hit that corresponds to the potential corner
206  std::vector < std::vector < int > > hit_loc(numberwires);
207 
208  std::vector < std::vector < double > > Cornerness(numberwires); //the "weight" of a corner
209 
210  for(unsigned int wi = 0; wi < numberwires; ++wi){
211  hit_map[wi].resize(fTimeBins,0);
212  hit_loc[wi].resize(fTimeBins,-1);
213  Cornerness[wi].resize(fTimeBins,0);
214  MatrixAsum[wi].resize(fTimeBins,0);
215  MatrixBsum[wi].resize(fTimeBins,0);
216  }
217  for(unsigned int i = 0; i < hit.size(); ++i){
218  wire = hit[i]->WireID().Wire;
219  //pixelization using a Gaussian
220  // for(int j = 0; j <= (int)(hit[i]->EndTime()-hit[i]->StartTime()+.5); ++j)
221  // hit_map[wire][(int)((hit[i]->StartTime()+j)*(fTimeBins/numbertimesamples)+.5)] += Gaussian((int)(j-((hit[i]->EndTime()-hit[i]->StartTime())/2.)+.5),0,hit[i]->EndTime()-hit[i]->StartTime());
222  const float center = hit[i]->PeakTime(), sigma = hit[i]->RMS();
223  const int iFirstBin = int((center - 3*sigma) / TicksPerBin),
224  iLastBin = int((center + 3*sigma) / TicksPerBin);
225  for (int iBin = iFirstBin; iBin <= iLastBin; ++iBin) {
226  const float bin_center = iBin * TicksPerBin;
227  hit_map[wire][iBin] += Gaussian(bin_center, center, sigma);
228  }
229  }
230 
231  // Gaussian derivative convolution
232  for(unsigned int wire = 1; wire < numberwires-1; ++wire){
233 
234  for(int timebin = 1; timebin < fTimeBins-1; ++timebin){
235  MatrixAsum[wire][timebin] = 0.;
236  MatrixBsum[wire][timebin] = 0.;
237  n = 0;
238  for(int i = -3; i <= 3; ++i) {
239  windex = wire+i;
240  if(windex < 0 ) windex = 0;
241  // this is ok, because the line before makes sure it's not negative
242  else if ((unsigned int)windex >= numberwires) windex = numberwires-1;
243 
244  for(int j = -3; j <= 3; ++j){
245  tindex = timebin+j;
246  if(tindex < 0) tindex=0;
247  else if(tindex >= fTimeBins) tindex = fTimeBins-1;
248 
249  MatrixAsum[wire][timebin] += wx[n]*hit_map[windex][tindex];
250  MatrixBsum[wire][timebin] += wy[n]*hit_map[windex][tindex];
251  ++n;
252  } // end loop over j
253  } // end loop over i
254  } // end loop over time bins
255  }// end loop over wires
256 
257  //calculate the cornerness of each pixel while making sure not to fall off the hit map.
258  for(unsigned int wire = 1; wire < numberwires-1; ++wire){
259 
260  for(int timebin = 1; timebin < fTimeBins-1; ++timebin){
261  MatrixAAsum = 0.;
262  MatrixBBsum = 0.;
263  MatrixCCsum = 0.;
264  //Gaussian smoothing convolution
265  n = 0;
266  for(int i = -3; i <= 3; ++i){
267  windex = wire+i;
268  if(windex<0) windex = 0;
269  // this is ok, because the line before makes sure it's not negative
270  else if((unsigned int)windex >= numberwires) windex = numberwires-1;
271 
272  for(int j = -3; j <= 3; ++j){
273  tindex = timebin+j;
274  if(tindex < 0) tindex = 0;
275  else if(tindex >= fTimeBins) tindex = fTimeBins-1;
276 
277  MatrixAAsum += w[n]*pow(MatrixAsum[windex][tindex],2);
278  MatrixBBsum += w[n]*pow(MatrixBsum[windex][tindex],2);
279  MatrixCCsum += w[n]*MatrixAsum[windex][tindex]*MatrixBsum[windex][tindex];
280  ++n;
281  }// end loop over j
282  }// end loop over i
283 
284  if((MatrixAAsum + MatrixBBsum) > 0)
285  Cornerness[wire][timebin] = (MatrixAAsum*MatrixBBsum-pow(MatrixCCsum,2))/(MatrixAAsum+MatrixBBsum);
286  else
287  Cornerness[wire][timebin] = 0;
288 
289  if(Cornerness[wire][timebin] > 0){
290  for(unsigned int i = 0;i < hit.size(); ++i){
291  wire2 = hit[i]->WireID().Wire;
292  //make sure the end point candidate coincides with an actual hit.
293  if(wire == wire2
294  && std::abs(hit[i]->TimeDistanceAsRMS(timebin*(numbertimesamples/fTimeBins))) < 1.){
295  //this index keeps track of the hit number
296  hit_loc[wire][timebin] = i;
297  Cornerness2.push_back(Cornerness[wire][timebin]);
298  break;
299  }
300  }// end loop over hits
301  }// end if cornerness > 0
302  } // end loop over time bins
303  } // end wire loop
304 
305  std::sort(Cornerness2.rbegin(), Cornerness2.rend());
306 
307  for(int vertexnum = 0; vertexnum < fMaxCorners; ++vertexnum){
308  flag = 0;
309  for(unsigned int wire = 0; wire < numberwires && flag == 0; ++wire){
310  for(int timebin = 0; timebin < fTimeBins && flag == 0; ++timebin){
311  if(Cornerness2.size() > (unsigned int)vertexnum)
312  if(Cornerness[wire][timebin] == Cornerness2[vertexnum]
313  && Cornerness[wire][timebin] > 0.
314  && hit_loc[wire][timebin] > -1){
315  ++flag;
316 
317  //thresholding
318  if(Cornerness2.size())
319  if(Cornerness[wire][timebin] < (fThreshold*Cornerness2[0]))
320  vertexnum = fMaxCorners;
321  vHits.push_back(hit[hit_loc[wire][timebin]]);
322 
323  // get the total charge from the associated hits
324  double totalQ = 0.;
325  for(size_t vh = 0; vh < vHits.size(); ++vh) totalQ += vHits[vh]->Integral();
326 
327  recob::EndPoint2D endpoint(hit[hit_loc[wire][timebin]]->PeakTime(),
328  hit[hit_loc[wire][timebin]]->WireID(),
329  Cornerness[wire][timebin],
330  vtxcol.size(),
331  view,
332  totalQ);
333  vtxcol.push_back(endpoint);
334  vtxHitsOut.push_back(vHits);
335  vHits.clear();
336 
337  // non-maximal suppression on a square window. The wire coordinate units are
338  // converted to time ticks so that the window is truly square.
339  // Note that there are 1/0.0743=13.46 time samples per 4.0 mm (wire pitch in ArgoNeuT),
340  // assuming a 1.5 mm/us drift velocity for a 500 V/cm E-field
341 
342  double drifttick = detp->DriftVelocity(detp->Efield(),detp->Temperature());
343  drifttick *= detp->SamplingRate()*1.e-3;
344  double wirepitch = geom->WirePitch();
345  double corrfactor = drifttick/wirepitch;
346 
347  for(int wireout=(int)wire-(int)((fWindow*(numbertimesamples/fTimeBins)*corrfactor)+.5);
348  wireout <= (int)wire+(int)((fWindow*(numbertimesamples/fTimeBins)*corrfactor)+.5); ++wireout){
349  for(int timebinout=timebin-fWindow;timebinout <= timebin+fWindow; timebinout++){
350  if(std::sqrt(pow(wire-wireout,2)+pow(timebin-timebinout,2))<fWindow)//circular window
351  Cornerness[wireout][timebinout]=0;
352  }
353  }
354  }
355  }
356  }
357  }
358  Cornerness2.clear();
359  hit.clear();
360  if(clusterIter != clusIn.end()) clusterIter++;
361 
362  if((int)wid.Plane == fSaveVertexMap){
363  unsigned char *outPix = new unsigned char [fTimeBins*numberwires];
364  //finds the maximum cell in the map for image scaling
365  int cell = 0;
366  int pix = 0;
367  int maxCell = 0;
368  //int xmaxx, ymaxx;
369  for (int y = 0; y < fTimeBins; ++y){
370  for (unsigned int x = 0; x < numberwires; ++x){
371  cell = (int)(hit_map[x][y]*1000);
372  if (cell > maxCell){
373  maxCell = cell;
374  // xmaxx=x;
375  // ymaxx=y;
376  }
377  }
378  }
379  for (int y = 0; y < fTimeBins; ++y){
380  for (unsigned int x = 0; x<numberwires; ++x){
381  //scales the pixel weights based on the maximum cell value
382  if(maxCell>0)
383  pix = (int)((1500000*hit_map[x][y])/maxCell);
384  outPix[y*numberwires + x] = pix;
385  }
386  }
387 
388  // add 3x3 pixel squares to with the harris vertex finders to the .bmp file
389 
390  for(unsigned int ii = 0; ii < vtxcol.size(); ++ii){
391  if(vtxcol[ii].View() == (unsigned int)view){
392  pix = (int)(255);
393  outPix[(int)(vtxcol[ii].DriftTime()*(fTimeBins/numbertimesamples))*numberwires + vtxcol[ii].WireID().Wire] = pix;
394  outPix[(int)(vtxcol[ii].DriftTime()*(fTimeBins/numbertimesamples))*numberwires + vtxcol[ii].WireID().Wire-1] = pix;
395  outPix[(int)(vtxcol[ii].DriftTime()*(fTimeBins/numbertimesamples))*numberwires + vtxcol[ii].WireID().Wire+1] = pix;
396  outPix[(int)((vtxcol[ii].DriftTime()*(fTimeBins/numbertimesamples))-1)*numberwires + vtxcol[ii].WireID().Wire] = pix;
397  outPix[(int)((vtxcol[ii].DriftTime()*(fTimeBins/numbertimesamples))+1)*numberwires + vtxcol[ii].WireID().Wire] = pix;
398  outPix[(int)((vtxcol[ii].DriftTime()*(fTimeBins/numbertimesamples))-1)*numberwires + vtxcol[ii].WireID().Wire-1] = pix;
399  outPix[(int)((vtxcol[ii].DriftTime()*(fTimeBins/numbertimesamples))-1)*numberwires + vtxcol[ii].WireID().Wire-2] = pix;
400  outPix[(int)((vtxcol[ii].DriftTime()*(fTimeBins/numbertimesamples))+1)*numberwires + vtxcol[ii].WireID().Wire+1] = pix;
401  outPix[(int)((vtxcol[ii].DriftTime()*(fTimeBins/numbertimesamples))+1)*numberwires + vtxcol[ii].WireID().Wire+2] = pix;
402  }
403  }
404 
405  VSSaveBMPFile(Form("harrisvertexmap_%d_%d.bmp",(*clusIn.begin())->ID(),wid.Plane), outPix, numberwires, fTimeBins);
406  delete [] outPix;
407  }
408  } // end loop over views
409 
410  return vtxcol.size();
411 }
Float_t x
Definition: compare.C:6
virtual unsigned int ReadOutWindowSize() const =0
double GaussianDerivativeX(int x, int y)
Definition: EndPointAlg.cxx:81
const std::string label
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
iterator begin()
Definition: PtrVector.h:223
Float_t y
Definition: compare.C:6
std::set< geo::View_t > const & Views() const
Returns a list of possible views in the detector.
virtual double SamplingRate() const =0
Returns the period of the TPC readout electronics clock.
CryostatID_t Cryostat
Index of cryostat.
Definition: geo_types.h:130
double Gaussian(int x, int y, double sigma)
Definition: EndPointAlg.cxx:73
geo::Length_t WirePitch(geo::PlaneID const &planeid) const
Returns the distance between two consecutive wires.
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:441
virtual double Temperature() const =0
iterator end()
Definition: PtrVector.h:237
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
double GaussianDerivativeY(int x, int y)
Definition: EndPointAlg.cxx:89
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:258
size_type size() const
Definition: PtrVector.h:308
Detector simulation of raw signals on wires.
data_t::const_iterator const_iterator
Definition: PtrVector.h:61
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc&#39;th TPC in the cryostat.
virtual double DriftVelocity(double efield=0., double temperature=0.) const =0
unsigned int Nwires() const
Number of wires in this plane.
Definition: PlaneGeo.h:250
Char_t n[5]
PlaneGeo const & Plane(geo::View_t view) const
Return the plane in the tpc with View_t view.
Definition: TPCGeo.cxx:298
virtual double Efield(unsigned int planegap=0) const =0
Returns the nominal electric field in the specified volume.
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:203
WireID()=default
Default constructor: an invalid TPC ID.
void clear()
Definition: PtrVector.h:537
Float_t w
Definition: plot.C:23
void VSSaveBMPFile(const char *fileName, unsigned char *pix, int dx, int dy)
Definition: EndPointAlg.cxx:99
double cluster::EndPointAlg::Gaussian ( int  x,
int  y,
double  sigma 
)
private

Definition at line 73 of file EndPointAlg.cxx.

References fhicl::detail::atom::value().

Referenced by EndPoint().

74 {
75  double Norm=1./std::sqrt(2*TMath::Pi()*pow(sigma,2));
76  double value=Norm*exp(-(pow(x,2)+pow(y,2))/(2*pow(sigma,2)));
77  return value;
78 }
Float_t x
Definition: compare.C:6
Float_t y
Definition: compare.C:6
std::string value(boost::any const &)
double cluster::EndPointAlg::GaussianDerivativeX ( int  x,
int  y 
)
private

Definition at line 81 of file EndPointAlg.cxx.

References fGsigma, fhicl::detail::atom::value(), and x.

Referenced by EndPoint().

82 {
83  double Norm=1./(std::sqrt(2*TMath::Pi())*pow(fGsigma,3));
84  double value=Norm*(-x)*exp(-(pow(x,2)+pow(y,2))/(2*pow(fGsigma,2)));
85  return value;
86 }
Float_t x
Definition: compare.C:6
Float_t y
Definition: compare.C:6
std::string value(boost::any const &)
double cluster::EndPointAlg::GaussianDerivativeY ( int  x,
int  y 
)
private

Definition at line 89 of file EndPointAlg.cxx.

References fGsigma, fhicl::detail::atom::value(), and y.

Referenced by EndPoint().

90 {
91  double Norm=1./(std::sqrt(2*TMath::Pi())*pow(fGsigma,3));
92  double value=Norm*(-y)*exp(-(pow(x,2)+pow(y,2))/(2*pow(fGsigma,2)));
93  return value;
94 }
Float_t x
Definition: compare.C:6
Float_t y
Definition: compare.C:6
std::string value(boost::any const &)
void cluster::EndPointAlg::reconfigure ( fhicl::ParameterSet const &  pset)

Definition at line 62 of file EndPointAlg.cxx.

References fGsigma, fMaxCorners, fSaveVertexMap, fThreshold, fTimeBins, fWindow, and fhicl::ParameterSet::get().

Referenced by EndPointAlg(), and cluster::EndPointModule::reconfigure().

63 {
64  fTimeBins = p.get< int >("TimeBins");
65  fMaxCorners = p.get< int >("MaxCorners");
66  fGsigma = p.get< double >("Gsigma");
67  fWindow = p.get< int >("Window");
68  fThreshold = p.get< double >("Threshold");
69  fSaveVertexMap = p.get< int >("SaveVertexMap");
70 }
void cluster::EndPointAlg::VSSaveBMPFile ( const char *  fileName,
unsigned char *  pix,
int  dx,
int  dy 
)
private

Definition at line 99 of file EndPointAlg.cxx.

Referenced by EndPoint().

100 {
101  std::ofstream bmpFile(fileName, std::ios::binary);
102  bmpFile.write("B", 1);
103  bmpFile.write("M", 1);
104  int bitsOffset = 54 +256*4;
105  int size = bitsOffset + dx*dy; //header plus 256 entry LUT plus pixels
106  bmpFile.write((const char *)&size, 4);
107  int reserved = 0;
108  bmpFile.write((const char *)&reserved, 4);
109  bmpFile.write((const char *)&bitsOffset, 4);
110  int bmiSize = 40;
111  bmpFile.write((const char *)&bmiSize, 4);
112  bmpFile.write((const char *)&dx, 4);
113  bmpFile.write((const char *)&dy, 4);
114  short planes = 1;
115  bmpFile.write((const char *)&planes, 2);
116  short bitCount = 8;
117  bmpFile.write((const char *)&bitCount, 2);
118  int i, temp = 0;
119  for (i=0; i<6; i++)
120  bmpFile.write((const char *)&temp, 4); // zero out optional color info
121  // write a linear LUT
122  char lutEntry[4]; // blue,green,red
123  lutEntry[3] = 0; // reserved part
124  for (i=0; i<256; i++)
125  {
126  lutEntry[0] =i;
127  lutEntry[1] =i+1;
128  lutEntry[2] = i+2;
129  bmpFile.write(lutEntry, sizeof lutEntry);
130  }
131  // write the actual pixels
132  bmpFile.write((const char *)pix, dx*dy);
133 }

Member Data Documentation

double cluster::EndPointAlg::fGsigma
private

Definition at line 53 of file EndPointAlg.h.

Referenced by EndPoint(), GaussianDerivativeX(), GaussianDerivativeY(), and reconfigure().

int cluster::EndPointAlg::fMaxCorners
private

Definition at line 52 of file EndPointAlg.h.

Referenced by EndPoint(), and reconfigure().

int cluster::EndPointAlg::fSaveVertexMap
private

Definition at line 56 of file EndPointAlg.h.

Referenced by EndPoint(), and reconfigure().

double cluster::EndPointAlg::fThreshold
private

Definition at line 55 of file EndPointAlg.h.

Referenced by EndPoint(), and reconfigure().

int cluster::EndPointAlg::fTimeBins
private

Definition at line 51 of file EndPointAlg.h.

Referenced by EndPoint(), and reconfigure().

int cluster::EndPointAlg::fWindow
private

Definition at line 54 of file EndPointAlg.h.

Referenced by EndPoint(), and reconfigure().


The documentation for this class was generated from the following files: