TGraphAligned.cc
1 #include "TGraphAligned.h"
2 
3 #include <stdlib.h>
4 #include "TMath.h"
5 #include <stdlib.h>
6 #include "TMutex.h"
7 #include "TH1.h"
8 #include "TList.h"
9 #include "TROOT.h"
10 
11 static int err = 0; // error checking for posix_memalign
12 
13 
14 ClassImp(TGraphAligned);
15 
16 #define ALIGNMENT TGRAPH_ALIGNED_ALIGNMENT
17 
19  :TGraph()
20 {
21  SetEditable(0);
22  //don't think we need to do anything in this case.
23 }
24 
26 {
27  SetTitle("Graph");
28  SetName("Graph");
29  fNpoints =n;
30  if (!CtorAllocate()) return;
31  FillZero(0, fNpoints);
32  SetEditable(0);
33 }
34 
35 
36 void TGraphAligned::adopt(const TGraphAligned *g)
37 {
38  Set(g->GetN());
39  memcpy(fX,g->GetX(),GetN()*sizeof(double));
40  memcpy(fY,g->GetY(),GetN()*sizeof(double));
41 }
42 
43 
44 TGraphAligned& TGraphAligned::operator=(const TGraphAligned &gr)
45 {
46  // Equal operator for this graph
47 
48  if (this != &gr) {
49  TNamed::operator=(gr);
50  TAttLine::operator=(gr);
51  TAttFill::operator=(gr);
52  TAttMarker::operator=(gr);
53 
54  fNpoints = gr.fNpoints;
55  fMaxSize = gr.fMaxSize;
56  {
57  // delete list of functions and their contents before copying it
58  if (fFunctions) {
59  // delete previous lists of functions
60  if (!fFunctions->IsEmpty()) {
61  fFunctions->SetBit(kInvalidObject);
62  // use TList::Remove to take into account the case the same object is
63  // added multiple times in the list
64  TObject *obj;
65  while ((obj = fFunctions->First())) {
66  while (fFunctions->Remove(obj)) { }
67  delete obj;
68  }
69  }
70  delete fFunctions;
71  }
72 
73  if (gr.fFunctions)
74  {
75  fFunctions = (TList*)gr.fFunctions->Clone();
76  }
77  else fFunctions = new TList;
78  }
79 
80  if (fHistogram) delete fHistogram;
81  if (gr.fHistogram) fHistogram = new TH1F(*(gr.fHistogram));
82  else fHistogram = 0;
83 
84  fMinimum = gr.fMinimum;
85  fMaximum = gr.fMaximum;
86  if (fX) free(fX);
87  if (fY) free(fY);
88  if (!fMaxSize) {
89  fX = fY = 0;
90  return *this;
91  }
92  else
93  {
94  err = posix_memalign((void**) &fX, ALIGNMENT, fNpoints * sizeof(Double_t));
95  if(err != 0){
96  fX = NULL;
97  }
98  err = posix_memalign((void**) &fY, ALIGNMENT, fNpoints * sizeof(Double_t));
99  if(err != 0){
100  fX = NULL;
101  }
102  }
103 
104  Int_t n = gr.GetN() * sizeof(Double_t);
105  if (n > 0) {
106  memcpy(fX, gr.fX, n);
107  memcpy(fY, gr.fY, n);
108  }
109  }
110  SetEditable(0);
111  return *this;
112 }
113 
114 TGraphAligned::TGraphAligned(Int_t n, const Double_t * x, const Double_t * y)
115 {
116 
117  SetTitle("Graph");
118  SetName("Graph");
119  if (!x || !y) {
120  fNpoints = 0;
121  } else {
122  fNpoints = n;
123  }
124  if (!CtorAllocate()) return;
125  n = fNpoints * sizeof(Double_t);
126  memcpy(fX, x, n);
127  memcpy(fY, y, n);
128 
129  SetEditable(0);
130 }
131 
132 
133 
134 
135 // I don't think this needs to do everything other than allocate fX and fY since the TGraph constructor should take care of that
136 Bool_t TGraphAligned::CtorAllocate()
137 {
138  if (fNpoints <= 0)
139  {
140  fNpoints = 0;
141  fMaxSize = 0;
142  fX = 0;
143  fY = 0;
144  return kFALSE;
145  }
146  else
147  {
148  fMaxSize = fNpoints;
149  err = posix_memalign((void**) &fX, ALIGNMENT, fNpoints * sizeof(Double_t));
150  if(err != 0){
151  fX = NULL;
152  }
153 
154  err = posix_memalign((void**) &fY, ALIGNMENT, fNpoints * sizeof(Double_t));
155  if(err != 0){
156  fY = NULL;
157  }
158  }
159 
160 
161  if (fX == NULL || fY == NULL)
162  {
163  fprintf(stderr, "Could not allocate aligned memory in TGraphAligned::CtorAllocate()\n");
164  return kFALSE;
165  }
166 
167  return kTRUE;
168 }
169 
170 //same as TGraph except use free instead of delete[]
172 {
173  // Graph default destructor.
174 
175  free(fX);
176  free(fY);
177  fX = 0;
178  fY = 0;
179 }
180 
181 
182 //same as TGraph except use free instead of delete[]
183 void TGraphAligned::CopyAndRelease(Double_t **newarrays, Int_t ibegin, Int_t iend,
184  Int_t obegin)
185 {
186  CopyPoints(newarrays, ibegin, iend, obegin);
187  if (newarrays) {
188  free(fX);
189  fX = newarrays[0];
190  free(fY);
191  fY = newarrays[1];
192  delete[] newarrays;
193  }
194 }
195 
197  : TGraph(gr)
198 {
199  // Copy constructor for this graph
200 
201  // Ok , we'll let the TGraph copy constructor do all the work but then
202  // remake the pointers. If anybody can think of a better way to do this... let me know
203  if (fMaxSize)
204  {
205 
206  Double_t * new_fX = NULL;
207  err = posix_memalign((void**) &new_fX, ALIGNMENT, fMaxSize * sizeof(Double_t));
208  if(err != 0){
209  new_fX = NULL;
210  }
211  Double_t * new_fY = NULL;
212  err = posix_memalign((void**) &new_fY, ALIGNMENT, fMaxSize * sizeof(Double_t));
213  if(err != 0){
214  new_fY = NULL;
215  }
216 
217  memcpy(new_fX, fX, gr.GetN() * sizeof(Double_t));
218  delete [] fX;
219  fX = new_fX;
220 
221 
222  memcpy(new_fY, fY, gr.GetN() * sizeof(Double_t));
223  delete [] fY;
224  fY = new_fY;
225  }
226 }
227 
228 
229 //same as TGraph except use memalign instead of new[]
230 Double_t** TGraphAligned::AllocateAlignedArrays(Int_t Narrays, Int_t arraySize)
231 {
232  if (arraySize < 0)
233  {
234  arraySize = 0;
235  }
236 
237  Double_t **newarrays = new Double_t*[Narrays];
238  if (!arraySize)
239  {
240  for (Int_t i = 0; i < Narrays; ++i)
241  {
242  newarrays[i] = 0;
243  }
244  }
245  else
246  {
247  for (Int_t i = 0; i < Narrays; ++i)
248  {
249  err = posix_memalign((void**) &newarrays[i], ALIGNMENT, arraySize * sizeof(Double_t));
250  if(err != 0)
251  {
252  newarrays[i] = NULL;
253  }
254  }
255  }
256 
257  fMaxSize = arraySize;
258  return newarrays;
259 }
260 
261 
262 void TGraphAligned::undBize()
263 {
264  int n = GetN();
265 
266  for (int i = 0; i < n; i++)
267  {
268  fY[i] = TMath::Power(10,fY[i]/10);
269  }
270 }
271 
272 
273 Double_t TGraphAligned::getSumV2(Int_t istart, Int_t iend) const
274 {
275  aligned_double_v v = GetY();
276  __builtin_prefetch(v); // This is really an academic exercise at this point
277  int N = GetN();
278  int real_start = istart >= 0 ? TMath::Min(istart, N-1) : TMath::Max(0, N + istart) ;
279  int real_end = iend >= 0 ? TMath::Min(iend, N-1) : TMath::Max(0, N + iend) ;
280 
281  double sum2 = 0;
282 
283 
284  for (int i = real_start; i <= real_end; i++)
285  {
286  sum2 += v[i]*v[i];
287  }
288 
289  return sum2;
290 
291 }
292 
293 void TGraphAligned::getMeanAndRMS(Double_t * mean, Double_t * rms, Int_t istart, Int_t iend) const
294 {
295  aligned_double_v v = GetY();
296  __builtin_prefetch(v);
297  int N = GetN();
298  int real_start = istart >= 0 ? TMath::Min(istart, N-1) : TMath::Max(0, N + istart) ;
299  int real_end = iend >= 0 ? TMath::Min(iend, N-1) : TMath::Max(0, N + iend) ;
300 
301  double sum = 0;
302  double sum2 = 0;
303 
304 
305  //weird that this doesn't auto-vectorize
306  //is it because hadd is too slow?
307  for (int i = real_start; i <= real_end; i++)
308  {
309  sum += v[i];
310  sum2 += v[i]*v[i];
311  }
312 
313  double mn = sum/N;
314  if (mean) *mean = mn;
315 
316  if (rms)
317  {
318  double mn2 = mn*mn;
319  *rms = sqrt(sum2/N - mn2);
320  }
321 }
322 
323 
324 //TODO, this can be optimized mostly likely
325 double * TGraphAligned::getMoments(int N, double origin, double * moment) const
326 {
327  if (!moment) moment = new double[N];
328 
329 
330  for (int i = 0; i < N; i++ )
331  {
332  int n = i+1;
333  double sum = 0;
334  for (int j = 0; j < GetN(); j++)
335  {
336  sum += TMath::Power(fX[j] - origin, n) * fY[j];
337  }
338 
339  moment[i] = sum;
340  }
341 
342 
343  return moment;
344 }
345 
346 
347 
348 void TGraphAligned::dBize(double mindB)
349 {
350  int n = GetN();
351 
352  for (int i = 0; i < n; i++)
353  {
354  fY[i] = TMath::Max(mindB, 10 * TMath::Log10(fY[i]));
355  }
356 
357 
358 }
359 
360 Double_t TGraphAligned::pk2pk(Int_t nth_max, Int_t nth_min, Int_t * location_max, Int_t * location_min, Int_t istart, Int_t iend) const
361 {
362 
363  int start = istart < 0 ? GetN() + istart : istart;
364  int end = iend < 0 ? GetN() + iend : iend;
365 
366  int max_index = -1;
367  int min_index = -1;
368  double max = 0;
369  double min = 0 ;
370  const double * y = GetY();
371 
372 
373  //the easy case
374  if (nth_max == 0 && nth_min == 0)
375  {
376  for (int i = start; i <= end; i++)
377  {
378  double val =y[i];
379  if (max_index < 0 || val > max)
380  {
381  max = val;
382  max_index = i;
383  }
384 
385  if (min_index < 0 || val < min)
386  {
387  min = val;
388  min_index = i;
389  }
390  }
391 
392  if (location_max) *location_max = max_index;
393  if (location_min) *location_min = min_index;
394 
395  }
396 
397  else //probably not the optimal algorithm here.
398  {
399  int N = end-start+1;
400  double ycopy[N];
401  memcpy(ycopy, y+start, N *sizeof(double));
402 
403  std::nth_element(ycopy, ycopy + N-1-nth_max, ycopy + N);
404  std::nth_element(ycopy, ycopy + nth_min, ycopy + N);
405 
406  max = ycopy[N-1-nth_max];
407  min = ycopy[nth_min];
408 
409 
410  if (location_max || location_min)
411  {
412  bool need_max = location_max;
413  bool need_min = location_min;
414  for (int i =start; i <=end; i++)
415  {
416  if (location_max && y[i] == max)
417  {
418  *location_max = i;
419  need_max = false;
420  }
421 
422  if (location_min && y[i] == min)
423  {
424  *location_min = i;
425  need_min = false;
426  }
427 
428  if (!need_min && !need_max) break;
429  }
430  }
431  }
432 
433  return max-min;
434 }
435 
436 Double_t TGraphAligned::peakVal(Int_t * location, Int_t istart, Int_t iend, bool abs) const
437 {
438 
439  int start = istart < 0 ? GetN() + istart : istart;
440  int end = iend < 0 ? GetN() + iend : iend;
441 
442  int max_index = -1;
443  double max = 0;
444  const double * y = GetY();
445 
446  for (int i = start; i <= end; i++)
447  {
448  double val = abs ? fabs(y[i]) : y[i];
449  if (max_index < 0 || val > max)
450  {
451  max = val;
452  max_index = i;
453  }
454  }
455 
456  if (location) *location = max_index;
457  return max;
458 }
459 
460 
461 
462 TH1 * TGraphAligned::valueHist(int nbins, const double * w, TH1 * out) const
463 {
464  if (!out)
465  {
466  out = new TH1I(TString::Format("%s_value_hist", GetName()), TString::Format("Values for %s", GetTitle()), nbins, GetMinimum(), GetMaximum());
467  }
468  else
469  {
470  out->Reset();
471  out->SetBins(nbins, GetMinimum(), GetMaximum());
472  }
473 
474  double sumw2 = 0;
475  if (w)
476  {
477  for (int i = 0; i < GetN(); i++)
478  {
479  sumw2 += w[i]*w[i];
480  }
481  sumw2 = sqrt(sumw2);
482  }
483  for (int i = 0; i < GetN(); i++)
484  {
485  out->Fill(GetY()[i], w? w[i]/sumw2 : 1./GetN());
486  }
487 
488  return out;
489 }
490 
491 
492 
493 void TGraphAligned::zeroMean()
494 {
495  double mean = 0;
496  for (int i = 0; i < GetN(); i++) mean+= GetY()[i];
497  mean /= GetN();
498  for (int i = 0; i < GetN(); i++) GetY()[i]-=mean;
499 }
500 
501 void TGraphAligned::shift(int nsamp, bool zero)
502 {
503 
504  //this does the rotation
505  std::rotate(GetY(), GetY()+((GetN() + nsamp) % GetN()), GetY() + GetN());
506 
507 
508  //now do some zeroing
509  if (zero)
510  {
511  if (nsamp > 0)
512  {
513  for (int i = GetN()-nsamp; i < GetN(); i++) GetY()[i] = 0;
514  }
515  else
516  {
517  for (int i = 0; i < nsamp; i++) GetY()[i] = 0;
518  }
519  }
520 }
521 
522 
523 void TGraphAligned::setPlottingLimits(double mult, bool sym, double dt)
524 {
525 
526  int imax, imin;
527  pk2pk(0,0,&imax,&imin);
528 
529  double val_max = GetY()[imax];
530  double val_min = GetY()[imin];
531 
532  double abs_max = TMath::Max(val_max,-val_min);
533 
534 
535  GetHistogram()->SetMaximum(mult * ( sym ? abs_max : val_max));
536  GetHistogram()->SetMinimum(mult * ( sym ? -abs_max : val_min));
537 
538  if (dt > 0 )
539  {
540  double x0 = val_max > -val_min ? GetX()[imax] : GetX()[imin];
541  GetXaxis()->SetLimits(x0-dt, x0+dt);
542  }
543  else
544  {
545  GetXaxis()->SetLimits(GetX()[0], GetX()[GetN()-1]);
546  }
547 }
548 
549 void TGraphAligned::setBelow(double val, bool abso, double to)
550 {
551  for (int i = 0; i < GetN(); i++)
552  {
553  if (GetY()[i] < val && (!abso || GetY()[i] > -val))
554  {
555  GetY()[i] = to;
556  }
557  }
558 }
virtual ~TGraphAligned()
TH1 * valueHist(int nbins=100, const double *weights=0, TH1 *out=0) const