Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DHoughFind.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DHoughFind.cc
4 // Created: Wed Oct 31 05:59:26 EDT 2007
5 // Creator: davidl (on Darwin Amelia.local 8.10.1 i386)
6 //
7 
8 #include <algorithm>
9 #include <iostream>
10 #include <cmath>
11 using namespace std;
12 
13 #include "DHoughFind.h"
14 
15 //---------------------------------
16 // DHoughFind (Constructor)
17 //---------------------------------
19 {
20  hist = NULL;
21  max_bin_valid = false;
22 }
23 
24 //---------------------------------
25 // DHoughFind (Constructor)
26 //---------------------------------
27 DHoughFind::DHoughFind(double xmin, double xmax, double ymin, double ymax, unsigned int Nbinsx, unsigned int Nbinsy)
28 {
29  hist = NULL;
30  SetLimits(xmin, xmax, ymin, ymax, Nbinsx, Nbinsy);
31 }
32 
33 //---------------------------------
34 // ~DHoughFind (Destructor)
35 //---------------------------------
37 {
38  if(hist)delete[] hist;
39 }
40 
41 //---------------------------------
42 // SetLimits
43 //---------------------------------
44 void DHoughFind::SetLimits(double xmin, double xmax, double ymin, double ymax, unsigned int Nbinsx, unsigned int Nbinsy)
45 {
46  // If hist already has memory allocated, check if we need to reallocate
47  if(hist){
48  if(this->Nbinsx*this->Nbinsy != Nbinsx*Nbinsy){
49  delete[] hist;
50  hist = NULL;
51  }
52  }
53 
54  // Allocate memory if necessary
55  if(!hist)hist = new double[Nbinsx*Nbinsy];
56 
57  this->xmin = xmin;
58  this->xmax = xmax;
59  this->ymin = ymin;
60  this->ymax = ymax;
61  this->Nbinsx = Nbinsx;
62  this->Nbinsy = Nbinsy;
63 
64  bin_widthx = (xmax-xmin)/(double)(Nbinsx-1);
65  bin_widthy = (ymax-ymin)/(double)(Nbinsy-1);
66  bin_size = bin_widthx<bin_widthy ? bin_widthx:bin_widthy; // used for characteristic "size" of a bin
67 
68  ResetHist();
69 }
70 
71 //---------------------------------
72 // ResetHist
73 //---------------------------------
75 {
76  for(unsigned int i=0; i<Nbinsx*Nbinsy; i++)hist[i]=0.0;
77  //memset(hist, 0, Nbinsx*Nbinsy*sizeof(double));
78 
79  imax_binx = Nbinsx/2;
80  imax_biny = Nbinsy/2;
81  max_bin_content = 0.0;
82 }
83 
84 //---------------------------------
85 // GetMaxBinLocation
86 //---------------------------------
88 {
89  double x = xmin + (0.5+(double)imax_binx)*bin_widthx;
90  double y = ymin + (0.5+(double)imax_biny)*bin_widthy;
91 
92  DVector2 pos(x,y);
93 
94  return pos;
95 }
96 
97 //---------------------------------
98 // GetMaxBinContent
99 //---------------------------------
101 {
102  return max_bin_content;
103 }
104 
105 //---------------------------------
106 // GetSigmaX
107 //---------------------------------
109 {
110  return bin_widthx/sqrt(12.0);
111 }
112 
113 //---------------------------------
114 // GetSigmaY
115 //---------------------------------
117 {
118  return bin_widthy/sqrt(12.0);
119 }
120 
121 //---------------------------------
122 // Find
123 //---------------------------------
125 {
126  return Find(points);
127 }
128 
129 //---------------------------------
130 // Find
131 //---------------------------------
132 DVector2 DHoughFind::Find(const vector<DVector2> &points)
133 {
134  /// Loop over "points" transforming them into lines and filling the 2-D
135  /// histogram.
136 
137 
138  // When determining the bins we just stepped into and out of,
139  // we add a small step in the g direction to push us just over
140  // the boundary we're currently on. We calculate the size of
141  // that step here so we don't have to over and over inside the loop
142  double small_step = bin_size*1.0E-3;
143 
144  for(unsigned int i=0; i<points.size(); i++){
145  const DVector2 &point = points[i];
146  DVector2 g(point.Y(), -point.X()); // perp. to point
147  g /= g.Mod(); // Make unit vector
148  DVector2 pos = point/2.0; // initialize to a point on the line
149 
150  // Find intersection with an edge of the histogram area that
151  // we can use as a starting point.
152  double beta = FindBeta(xmin, ymin, xmax-xmin, ymax-ymin, pos, g);
153  pos += beta*g;
154 
155  // Find the indexes of the bin we're about to step across.
156  // Note: we must also figure out if we need to step
157  // in the +g or -g direction to go "into" the histogram. Since
158  // we'll keep stepping in this direction, we adjust the sign
159  // of g as needed to always step in the scan direction
160  int ix, iy; // bin indexes
161  FindIndexes(pos + small_step*g, ix, iy);
162  if(ix<0 || ix>=(int)Nbinsx-1 || iy<0 || iy>=(int)Nbinsy-1){
163  g *= -1.0;
164  FindIndexes(pos + small_step*g, ix, iy);
165 
166  // If we're still out of range, then this line doesn't intersect our histo ever
167  if(ix<0 || ix>=(int)Nbinsx-1 || iy<0 || iy>=(int)Nbinsy-1){
168  continue;
169  }
170  }
171 
172  unsigned int Niterations=0;
173  do{
174 
175  // Find distance to boundary of next bin
176  beta = FindBeta(xmin+(double)ix*bin_widthx, ymin+(double)iy*bin_widthy, bin_widthx, bin_widthy, pos, g);
177 
178  // Beta too large indicates problem
179  if(beta*beta > (bin_widthx*bin_widthx + bin_widthy*bin_widthy))break;
180 
181  // increment histo for bin we just stepped across
182  if(ix<0 || ix>=(int)Nbinsx || iy<0 || iy>=(int)Nbinsy)break; // must have left the histo
183  int index = ix + iy*Nbinsx;
184  hist[index] += fabs(beta);
185  if(hist[index]>max_bin_content){
186  max_bin_content = hist[index];
187  imax_binx = ix;
188  imax_biny = iy;
189  }
190 
191  // Step to next boundary and find indexes of next bin
192  pos += beta*g;
193  FindIndexes(pos + small_step*g, ix, iy);
194 
195  }while(++Niterations<2*Nbinsx);
196  }
197 
198  return GetMaxBinLocation();
199 }
200 
201 //---------------------------------
202 // Fill
203 //---------------------------------
204 void DHoughFind::Fill(double x, double sigmax, double y, double sigmay)
205 {
206  /// Increment the histogram bins according to the given location
207  /// and sigmas. This will increment each bin by calculating the
208  /// product of 2 gaussians using the coordinates of the center of
209  /// the bin. Only bins within 4 sigma in each dimension are incremented.
210  ///
211  /// Note that the histogram is NOT reset prior to filling. This is
212  /// to allow accumulation over multiple calls.
213 
214  int ixmin = (int)(((x-xmin) - 4.0*sigmax)/bin_widthx -0.5);
215  int ixmax = (int)(((x-xmin) + 4.0*sigmax)/bin_widthx +0.5);
216  int iymin = (int)(((y-ymin) - 4.0*sigmay)/bin_widthy -0.5);
217  int iymax = (int)(((y-ymin) + 4.0*sigmay)/bin_widthy +0.5);
218  if(ixmin<0)ixmin=0;
219  if(iymin<0)iymin=0;
220  if(ixmax>(int)Nbinsx)ixmax=Nbinsx;
221  if(iymax>(int)Nbinsy)iymax=Nbinsy;
222 
223 //_DBG_<<"x="<<x<<"( sigmax="<<sigmax<<") y="<<y<<" (sigmay="<<sigmay<<") ixmin="<<ixmin<<" ixmax="<<ixmax<<" iymin="<<iymin<<" iymax="<<iymax<<endl;
224 
225  // Loop over bins
226  for(int i=ixmin; i<ixmax; i++){
227  double x_bin = xmin + (0.5+(double)i)*bin_widthx;
228  for(int j=iymin; j<iymax; j++){
229  double y_bin = ymin + (0.5+(double)j)*bin_widthy;
230  double k_x = (x - x_bin)/sigmax;
231  double k_y = (y - y_bin)/sigmay;
232  double gauss_x = exp(-k_x*k_x)/sigmax; // divide by sigma to make constant area
233  double gauss_y = exp(-k_y*k_y)/sigmay; // divide by sigma to make constant area
234 
235  int index = i + j*Nbinsx;
236  hist[index] += gauss_x*gauss_y;
237  }
238  }
239 }
240 
241 //---------------------------------
242 // GetMaxBinLocation (static)
243 //---------------------------------
244 DVector2 DHoughFind::GetMaxBinLocation(vector<const DHoughFind*> &houghs)
245 {
246  /// This routine is designed to be called statically via:
247  ///
248  /// DHoughFind::GetMaxBinLocation(houghs);
249  ///
250  /// It will find the location of the center of the bin with the maximum
251  /// content based on the sum of the input DHough objects. It does this
252  /// dynamically without maintaining a sum histogram.
253  ///
254  /// WARNING: If you call this as a method of an existing object, (e.g.
255  /// like this myhough->GetMacBinLocation(houghs); ) the object is NOT
256  /// used unless it explicitly appears in the "houghs" list!
257  ///
258  /// It is left to the caller to ensure the limits and number of bins for each
259  /// DHough object are the same.
260 
261  if(houghs.size()<1)return DVector2(0.0, 0.0);
262 
263  unsigned int Nbinsx = houghs[0]->Nbinsx;
264  unsigned int Nbinsy = houghs[0]->Nbinsy;
265 
266  unsigned int imax_binx=0, imax_biny=0;
267  double max_bin_content = 0.0;
268  for(unsigned int i=0; i<Nbinsx; i++){
269  for(unsigned int j=0; j<Nbinsy; j++){
270  unsigned int index = i + Nbinsx*j;
271  double tot = 0.0;
272  for(unsigned int k=0; k<houghs.size(); k++){
273  tot += houghs[k]->hist[index];
274  }
275  if(tot>max_bin_content){
276  max_bin_content = tot;
277  imax_binx = i;
278  imax_biny = j;
279  }
280  }
281  }
282 
283  double x = houghs[0]->xmin + (0.5+(double)imax_binx)*houghs[0]->bin_widthx;
284  double y = houghs[0]->ymin + (0.5+(double)imax_biny)*houghs[0]->bin_widthy;
285 
286  return DVector2(x, y);
287 }
288 
289 //---------------------------------
290 // Add
291 //---------------------------------
292 void DHoughFind::Add(const DHoughFind* hough)
293 {
294  bool same_configuration = true;
295  same_configuration &= hough->Nbinsx==Nbinsx;
296  same_configuration &= hough->Nbinsy==Nbinsy;
297  same_configuration &= hough->xmin==xmin;
298  same_configuration &= hough->ymin==ymin;
299  same_configuration &= hough->xmax==xmax;
300  same_configuration &= hough->ymax==ymax;
301 
302  if(!same_configuration){
303  _DBG_<<"WARNING: trying to add 2 DHoughFind objects with different dimensions!"<<endl;
304  _DBG_<<"Nbinsx="<<Nbinsx<<":"<<hough->Nbinsx
305  <<" Nbinsy="<<Nbinsy<<":"<<hough->Nbinsy
306  <<" xmin="<<xmin<<":"<<hough->xmin
307  <<" ymin="<<ymin<<":"<<hough->ymin
308  <<" xmax="<<xmax<<":"<<hough->xmax
309  <<" ymax="<<ymax<<":"<<hough->ymax;
310  return;
311  }
312 
313  for(unsigned int i=0; i<Nbinsx*Nbinsy; i++){
314  hist[i] += hough->hist[i];
315  }
316 }
317 
318 //---------------------------------
319 // AddPoint
320 //---------------------------------
321 void DHoughFind::AddPoint(const DVector2 &point)
322 {
323  points.push_back(point);
324 }
325 
326 //---------------------------------
327 // AddPoint
328 //---------------------------------
329 void DHoughFind::AddPoint(const double &x, const double &y)
330 {
331  DVector2 point(x,y);
332  AddPoint(point);
333 }
334 
335 //---------------------------------
336 // AddPoints
337 //---------------------------------
338 void DHoughFind::AddPoints(const vector<DVector2> &points)
339 {
340  for(unsigned int i=0; i<points.size(); i++)this->points.push_back(points[i]);
341 }
342 
343 //---------------------------------
344 // ClearPoints
345 //---------------------------------
347 {
348  points.clear();
349 }
350 
351 //---------------------------------
352 // PrintHist
353 //---------------------------------
355 {
356  /// Dump an ASCII representation of the normalized histogram
357  /// to the screen. This will dump a table of Nbinsx x Nbinsy
358  /// characters to the screen as a sort of cheap visual of
359  /// the histgram. It is only intended for debugging.
360 
361  // X-axis labels
362  string space(Nbinsx-10, ' ');
363  cout<<xmin<<space<<xmax<<endl;
364 
365 
366  for(unsigned int i=0; i<Nbinsy; i++){
367  string row(Nbinsx,' ');
368  for(unsigned int j=0; j<Nbinsx; j++){
369 
370  int index = j + i*Nbinsx;
371  unsigned int d = (unsigned int)(floor(15.0*hist[index]/max_bin_content));
372  char c[16];
373  sprintf(c, "%x", d);
374  row[j] = c[0] == '0' ? '.':c[0];
375  }
376  cout<<row<<" "<<ymin+(double)i*bin_widthy<<endl;
377  }
378 }
379 
380 //---------------------------------
381 // MakeIntoRootHist
382 //---------------------------------
383 TH2D* DHoughFind::MakeIntoRootHist(string hname)
384 {
385  /// Make a ROOT TH2D histogram out of this contents of this DHoughFind object.
386  /// Note that it is up to the caller to delete the returned TH2D object.
387 
388  TH2D *h = new TH2D(hname.c_str(),"Copied from DHoughFind object",Nbinsx, xmin, xmax, Nbinsy, ymin, ymax);
389  for(unsigned int i=0; i<Nbinsx; i++){
390  for(unsigned int j=0; j<Nbinsy; j++){
391  h->SetBinContent(i, j, hist[i+j*Nbinsx]);
392  }
393  }
394 
395  return h;
396 }
397 
virtual ~DHoughFind()
Definition: DHoughFind.cc:36
void Add(const DHoughFind *hough)
Definition: DHoughFind.cc:292
DVector2 GetMaxBinLocation(void)
Definition: DHoughFind.cc:87
unsigned int Nbinsx
Definition: DHoughFind.h:63
double ymax
Definition: DHoughFind.h:62
TVector2 DVector2
Definition: DVector2.h:9
double xmin
Definition: DHoughFind.h:62
void AddPoints(const vector< DVector2 > &points)
Definition: DHoughFind.cc:338
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
sprintf(text,"Post KinFit Cut")
#define c
double * hist
Definition: DHoughFind.h:69
#define y
DVector2 Find(void)
Definition: DHoughFind.cc:124
void AddPoint(const DVector2 &point)
Definition: DHoughFind.cc:321
static char index(char c)
Definition: base64.cpp:115
double ymin
Definition: DHoughFind.h:62
void ClearPoints(void)
Definition: DHoughFind.cc:346
double xmax
Definition: DHoughFind.h:62
TH2D * MakeIntoRootHist(string hname)
Definition: DHoughFind.cc:383
void SetLimits(double xmin, double xmax, double ymin, double ymax, unsigned int Nbinsx, unsigned int Nbinsy)
Definition: DHoughFind.cc:44
void ResetHist(void)
Definition: DHoughFind.cc:74
#define _DBG_
Definition: HDEVIO.h:12
double sqrt(double)
double GetSigmaX(void)
Definition: DHoughFind.cc:108
double GetMaxBinContent(void)
Definition: DHoughFind.cc:100
Double_t ymin
Definition: bcal_hist_eff.C:89
Double_t ymax
Definition: bcal_hist_eff.C:91
double GetSigmaY(void)
Definition: DHoughFind.cc:116
unsigned int Nbinsy
Definition: DHoughFind.h:63
void PrintHist(void)
Definition: DHoughFind.cc:354
void Fill(double x, double sigmax, double y, double sigmay)
Definition: DHoughFind.cc:204
TH1F * hist[Idx+1]
Definition: readhist.C:10