KaliVeda  1.13/01
Heavy-Ion Analysis Toolkit
KVIDLine.cpp
Go to the documentation of this file.
1 /***************************************************************************
2 $Id: KVIDLine.cpp,v 1.22 2009/05/05 15:57:52 franklan Exp $
3  KVIDLine.cpp - description
4  -------------------
5  begin : Nov 10 2004
6  copyright : (C) 2004 by J.D. Frankland
7  email : frankland@ganil.fr
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 #include "KVIDLine.h"
20 #include "Riostream.h"
21 #include "TF1.h"
22 #include "TProfile.h"
23 #include "TH2.h"
24 #include "TCutG.h"
25 #include "TPad.h"
26 #include "TList.h"
27 #include "TROOT.h"
28 #include "TVirtualX.h"
29 
30 using namespace std;
31 
33 
34 
35 
39 {
40  //Default ctor
41 }
42 
43 
44 
47 
48 KVIDLine::~KVIDLine()
49 {
50  //Default dtor
51 }
52 
53 
54 
57 
59  : KVIDentifier(obj)
60 {
61  // copy constructor
62 }
63 
64 
65 
68 
70 {
71  //initialize KVIDLine using TGraph copy ctor
72 }
73 
74 
75 
76 
87 
89 {
90  // create an IDLine from different objects (Inherited from TProfile, TGraph, TF1)
91  // - "xdeb" and "xfin" stand for the delimitation of the line - dafault values are -1
92  // in this case range is the one of the considered object
93  // if the choosen range is greater than the object one, one point for each limit is added with the value
94  // corresponding to the first and/or last of the object
95  // - "np" is in the TF1 case the number point (default value 20), in the TProfile case is the minimum threshold
96  // for the bin entries (default value is one); for the TGraph case it has no effect;
97  // In the TProfile and TGraph cases the number of points are determined by the object considering the interval
98  // - "save" allow to save the TF1 or TProfile object which can be recall with the GetListofFunction() method
99  Double_t xdeb_bis = xdeb, xfin_bis = xfin, np_bis = np;
100  if (obj) {
101  KVIDLine* line = new KVIDLine();
102  if (obj->InheritsFrom("TF1")) {
103  Double_t xmin, xmax;
104  dynamic_cast<TF1*>(obj)->GetRange(xmin, xmax);
105  if (xdeb_bis == -1) xdeb_bis = xmin;
106  if (xfin_bis == -1) xfin_bis = xmax;
107  if (np_bis == 1) np_bis = Double_t(dynamic_cast<TF1*>(obj)->GetNpx());
108  Double_t inter = (xfin_bis - xdeb_bis) / (np_bis);
109  Int_t pp = 0;
110  for (Double_t xx = xdeb_bis; xx <= xfin_bis; xx += inter) {
111  line->SetPoint(pp++, xx, dynamic_cast<TF1*>(obj)->Eval(xx));
112  }
113  if (save) line->Fit(dynamic_cast<TF1*>(obj), "0+", "", xdeb_bis, xfin_bis);
114  }
115  else if (obj->InheritsFrom("TGraph")) { // np has no effect in this case
116  Int_t nx = dynamic_cast<TGraph*>(obj)->GetN(), np2 = 0;
117  Double_t* xtab = dynamic_cast<TGraph*>(obj)->GetX();
118  Double_t* ytab = dynamic_cast<TGraph*>(obj)->GetY();
119  if (xdeb_bis == -1) xdeb_bis = xtab[0];
120  if (xfin_bis == -1) xfin_bis = xtab[nx - 1];
121  if (xdeb_bis < xtab[0]) line->SetPoint(np2++, xdeb_bis, ytab[0]);
122  for (Int_t pp = 0; pp < nx; pp += 1) if (xdeb_bis <= xtab[pp] && xtab[pp] <= xfin_bis) line->SetPoint(np2++, xtab[pp], ytab[pp]);
123  if (xfin_bis > xtab[nx - 1]) line->SetPoint(np2, xfin_bis, ytab[nx - 1]);
124  }
125  else if (obj->InheritsFrom("TProfile")) {
126  TProfile* pf = dynamic_cast<TProfile*>(obj);
127  Int_t nx = pf->GetNbinsX(), np2 = 0;
128  Int_t pp = 1;
129  while (pf->GetBinEntries(pp) < np && pp < nx) pp += 1;
130  Int_t xmin = pp;
131  pp = nx;
132  while (pf->GetBinEntries(pp) < np && pp > xmin) pp -= 1;
133  Int_t xmax = pp;
134  if (xdeb_bis == -1) xdeb_bis = pf->GetBinCenter(xmin);
135  if (xfin_bis == -1) xfin_bis = pf->GetBinCenter(xmax);
136  if (xdeb_bis < pf->GetBinCenter(xmin)) line->SetPoint(np2++, xdeb_bis, pf->GetBinContent(xmin));
137  for (pp = xmin; pp <= xmax; pp += 1) {
138  Double_t xx = pf->GetBinCenter(pp);
139  if (xdeb_bis <= xx && xx <= xfin_bis && pf->GetBinEntries(pp) >= np) line->SetPoint(np2++, xx, pf->GetBinContent(pp));
140  }
141  if (xfin_bis > pf->GetBinCenter(xmax)) line->SetPoint(np2, xfin_bis, pf->GetBinContent(xmax));
142  if (save) line->GetListOfFunctions()->Add(pf);
143  }
144  else cout << "le type ne correspond pas " << endl;
145  line->SetName(Form("from_%s", obj->GetName()));
146  return line;
147  }
148  else return NULL;
149 }
150 
151 
152 
153 /*
154 KVIDLine *KVIDLine::MakeIDLine(TH2 *hh,TCutG *cut,Double_t xdeb,Double_t xfin,Double_t np,Bool_t save)
155 {
156  if (hh){
157  TProfile *gg = NULL;
158  if (cut){
159  if (cut->InheritsFrom("TCutG")){
160  Double_t xmin=1e6,xmax=-1e6;
161  Double_t ymin=1e6,ymax=-1e6;
162  for (Int_t pp=0;pp<cut->GetN();pp+=1){
163  Double_t xx,yy; cut->GetPoint(pp,xx,yy);
164  if (xx<xmin) xmin=xx; if (xx>xmax) xmax=xx;
165  if (yy<ymin) ymin=yy; if (yy>ymax) ymax=yy;
166  }
167 
168  Int_t bxmin = hh->GetXaxis()->FindBin(xmin); xmin = hh->GetXaxis()->GetBinLowEdge(bxmin);
169  Int_t bxmax = hh->GetXaxis()->FindBin(xmax); xmax = hh->GetXaxis()->GetBinUpEdge(bxmax);
170  Int_t bymin = hh->GetYaxis()->FindBin(ymin); ymin = hh->GetYaxis()->GetBinLowEdge(bymin);
171  Int_t bymax = hh->GetYaxis()->FindBin(ymax); ymax = hh->GetYaxis()->GetBinUpEdge(bymax);
172 
173  Int_t dx = bxmax - bxmin +1;
174  gg = new TProfile(Form("%s_%s",hh->GetName(),cut->GetName()),"prof",dx,xmin,xmax,ymin,ymax);
175  for (Int_t xx=bxmin;xx<=bxmax;xx+=1)
176  for (Int_t yy=bymin;yy<=bymax;yy+=1)
177  if ( cut->IsInside(hh->GetXaxis()->GetBinCenter(xx),hh->GetYaxis()->GetBinCenter(yy)) )
178  gg->Fill(hh->GetXaxis()->GetBinCenter(xx),hh->GetYaxis()->GetBinCenter(yy),hh->GetBinContent(xx,yy));
179  }
180  }
181  else { gg = hh->ProfileX(); }
182  return KVIDLine::MakeIDLine(gg,xdeb,xfin,np,save);
183  }
184  else return NULL;
185 }
186 */
187 
188 
189 
193 
195 {
196  // Method used to draw a new identifier in the active pad
197  // Override in child classes so that gPad->WaitPrimitive has correct arguments
198 
199  if (!gPad) return;
200  TGraph* gr = (TGraph*) gPad->WaitPrimitive("Graph", "PolyLine");
201  //copy coordinates of user's line
202  CopyGraph(gr);
203  //remove TGraph and draw the KVIDLine in its place
204  gPad->GetListOfPrimitives()->Remove(gr);
205  delete gr;
206  Draw("PL");
207 }
208 
209 
210 
225 
227 {
228  // We override the TGraph::ExecuteEvent which contains a TCutG-specific part
229  // making sure that the first and last point are the same. This is a copy
230  // of that method with the "if(InheritsFrom("TCutG"))" part commented out.
231  //
232  // Execute action corresponding to one event.
233  //
234  // This member function is called when a graph is clicked with the locator
235  //
236  // If Left button clicked on one of the line end points, this point
237  // follows the cursor until button is released.
238  //
239  // if Middle button clicked, the line is moved parallel to itself
240  // until the button is released.
241 
242  Int_t i, d;
243  Double_t xmin, xmax, ymin, ymax, dx, dy, dxr, dyr;
244  const Int_t kMaxDiff = 10;
245  static Bool_t middle, badcase;
246  static Int_t ipoint, pxp, pyp;
247  static Int_t px1, px2, py1, py2;
248  static Int_t pxold, pyold, px1old, py1old, px2old, py2old;
249  static Int_t dpx, dpy;
250  static Int_t* x = 0, *y = 0;
251 
252  if (!IsEditable()) {
253  gPad->SetCursor(kHand);
254  return;
255  }
256  if (!gPad->IsEditable()) return;
257 
258  switch (event) {
259 
260  case kButton1Down:
261  badcase = kFALSE;
262  gVirtualX->SetLineColor(-1);
263  TAttLine::Modify(); //Change line attributes only if necessary
264  px1 = gPad->XtoAbsPixel(gPad->GetX1());
265  py1 = gPad->YtoAbsPixel(gPad->GetY1());
266  px2 = gPad->XtoAbsPixel(gPad->GetX2());
267  py2 = gPad->YtoAbsPixel(gPad->GetY2());
268  ipoint = -1;
269 
270 
271  if (x || y) break;
272  x = new Int_t[fNpoints + 1];
273  y = new Int_t[fNpoints + 1];
274  for (i = 0; i < fNpoints; i++) {
275  pxp = gPad->XtoAbsPixel(gPad->XtoPad(fX[i]));
276  pyp = gPad->YtoAbsPixel(gPad->YtoPad(fY[i]));
277  if (pxp < -kMaxPixel || pxp >= kMaxPixel ||
278  pyp < -kMaxPixel || pyp >= kMaxPixel) {
279  badcase = kTRUE;
280  continue;
281  }
282  gVirtualX->DrawLine(pxp - 4, pyp - 4, pxp + 4, pyp - 4);
283  gVirtualX->DrawLine(pxp + 4, pyp - 4, pxp + 4, pyp + 4);
284  gVirtualX->DrawLine(pxp + 4, pyp + 4, pxp - 4, pyp + 4);
285  gVirtualX->DrawLine(pxp - 4, pyp + 4, pxp - 4, pyp - 4);
286  x[i] = pxp;
287  y[i] = pyp;
288  d = TMath::Abs(pxp - px) + TMath::Abs(pyp - py);
289  if (d < kMaxDiff) ipoint = i;
290  }
291  dpx = 0;
292  dpy = 0;
293  pxold = px;
294  pyold = py;
295  if (ipoint < 0) return;
296  if (ipoint == 0) {
297  px1old = 0;
298  py1old = 0;
299  px2old = gPad->XtoAbsPixel(fX[1]);
300  py2old = gPad->YtoAbsPixel(fY[1]);
301  }
302  else if (ipoint == fNpoints - 1) {
303  px1old = gPad->XtoAbsPixel(gPad->XtoPad(fX[fNpoints - 2]));
304  py1old = gPad->YtoAbsPixel(gPad->YtoPad(fY[fNpoints - 2]));
305  px2old = 0;
306  py2old = 0;
307  }
308  else {
309  px1old = gPad->XtoAbsPixel(gPad->XtoPad(fX[ipoint - 1]));
310  py1old = gPad->YtoAbsPixel(gPad->YtoPad(fY[ipoint - 1]));
311  px2old = gPad->XtoAbsPixel(gPad->XtoPad(fX[ipoint + 1]));
312  py2old = gPad->YtoAbsPixel(gPad->YtoPad(fY[ipoint + 1]));
313  }
314  pxold = gPad->XtoAbsPixel(gPad->XtoPad(fX[ipoint]));
315  pyold = gPad->YtoAbsPixel(gPad->YtoPad(fY[ipoint]));
316 
317  break;
318 
319 
320  case kMouseMotion:
321 
322  middle = kTRUE;
323  for (i = 0; i < fNpoints; i++) {
324  pxp = gPad->XtoAbsPixel(gPad->XtoPad(fX[i]));
325  pyp = gPad->YtoAbsPixel(gPad->YtoPad(fY[i]));
326  d = TMath::Abs(pxp - px) + TMath::Abs(pyp - py);
327  if (d < kMaxDiff) middle = kFALSE;
328  }
329 
330 
331  // check if point is close to an axis
332  if (middle) gPad->SetCursor(kMove);
333  else gPad->SetCursor(kHand);
334  break;
335 
336  case kButton1Motion:
337  if (middle) {
338  for (i = 0; i < fNpoints - 1; i++) {
339  gVirtualX->DrawLine(x[i] + dpx, y[i] + dpy, x[i + 1] + dpx, y[i + 1] + dpy);
340  pxp = x[i] + dpx;
341  pyp = y[i] + dpy;
342  if (pxp < -kMaxPixel || pxp >= kMaxPixel ||
343  pyp < -kMaxPixel || pyp >= kMaxPixel) continue;
344  gVirtualX->DrawLine(pxp - 4, pyp - 4, pxp + 4, pyp - 4);
345  gVirtualX->DrawLine(pxp + 4, pyp - 4, pxp + 4, pyp + 4);
346  gVirtualX->DrawLine(pxp + 4, pyp + 4, pxp - 4, pyp + 4);
347  gVirtualX->DrawLine(pxp - 4, pyp + 4, pxp - 4, pyp - 4);
348  }
349  pxp = x[fNpoints - 1] + dpx;
350  pyp = y[fNpoints - 1] + dpy;
351  gVirtualX->DrawLine(pxp - 4, pyp - 4, pxp + 4, pyp - 4);
352  gVirtualX->DrawLine(pxp + 4, pyp - 4, pxp + 4, pyp + 4);
353  gVirtualX->DrawLine(pxp + 4, pyp + 4, pxp - 4, pyp + 4);
354  gVirtualX->DrawLine(pxp - 4, pyp + 4, pxp - 4, pyp - 4);
355  dpx += px - pxold;
356  dpy += py - pyold;
357  pxold = px;
358  pyold = py;
359  for (i = 0; i < fNpoints - 1; i++) {
360  gVirtualX->DrawLine(x[i] + dpx, y[i] + dpy, x[i + 1] + dpx, y[i + 1] + dpy);
361  pxp = x[i] + dpx;
362  pyp = y[i] + dpy;
363  if (pxp < -kMaxPixel || pxp >= kMaxPixel ||
364  pyp < -kMaxPixel || pyp >= kMaxPixel) continue;
365  gVirtualX->DrawLine(pxp - 4, pyp - 4, pxp + 4, pyp - 4);
366  gVirtualX->DrawLine(pxp + 4, pyp - 4, pxp + 4, pyp + 4);
367  gVirtualX->DrawLine(pxp + 4, pyp + 4, pxp - 4, pyp + 4);
368  gVirtualX->DrawLine(pxp - 4, pyp + 4, pxp - 4, pyp - 4);
369  }
370  pxp = x[fNpoints - 1] + dpx;
371  pyp = y[fNpoints - 1] + dpy;
372  gVirtualX->DrawLine(pxp - 4, pyp - 4, pxp + 4, pyp - 4);
373  gVirtualX->DrawLine(pxp + 4, pyp - 4, pxp + 4, pyp + 4);
374  gVirtualX->DrawLine(pxp + 4, pyp + 4, pxp - 4, pyp + 4);
375  gVirtualX->DrawLine(pxp - 4, pyp + 4, pxp - 4, pyp - 4);
376  }
377  else {
378  if (px1old) gVirtualX->DrawLine(px1old, py1old, pxold, pyold);
379  if (px2old) gVirtualX->DrawLine(pxold, pyold, px2old, py2old);
380  gVirtualX->DrawLine(pxold - 4, pyold - 4, pxold + 4, pyold - 4);
381  gVirtualX->DrawLine(pxold + 4, pyold - 4, pxold + 4, pyold + 4);
382  gVirtualX->DrawLine(pxold + 4, pyold + 4, pxold - 4, pyold + 4);
383  gVirtualX->DrawLine(pxold - 4, pyold + 4, pxold - 4, pyold - 4);
384  pxold = px;
385  pxold = TMath::Max(pxold, px1);
386  pxold = TMath::Min(pxold, px2);
387  pyold = py;
388  pyold = TMath::Max(pyold, py2);
389  pyold = TMath::Min(pyold, py1);
390  if (px1old) gVirtualX->DrawLine(px1old, py1old, pxold, pyold);
391  if (px2old) gVirtualX->DrawLine(pxold, pyold, px2old, py2old);
392  gVirtualX->DrawLine(pxold - 4, pyold - 4, pxold + 4, pyold - 4);
393  gVirtualX->DrawLine(pxold + 4, pyold - 4, pxold + 4, pyold + 4);
394  gVirtualX->DrawLine(pxold + 4, pyold + 4, pxold - 4, pyold + 4);
395  gVirtualX->DrawLine(pxold - 4, pyold + 4, pxold - 4, pyold - 4);
396  }
397  break;
398 
399  case kButton1Up:
400 
401  if (gROOT->IsEscaped()) {
402  gROOT->SetEscape(kFALSE);
403  delete [] x;
404  x = 0;
405  delete [] y;
406  y = 0;
407  break;
408  }
409 
410  // Compute x,y range
411  xmin = gPad->GetUxmin();
412  xmax = gPad->GetUxmax();
413  ymin = gPad->GetUymin();
414  ymax = gPad->GetUymax();
415  dx = xmax - xmin;
416  dy = ymax - ymin;
417  dxr = dx / (1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
418  dyr = dy / (1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
419 
420  if (fHistogram) {
421  // Range() could change the size of the pad pixmap and therefore should
422  // be called before the other paint routines
423  gPad->Range(xmin - dxr * gPad->GetLeftMargin(),
424  ymin - dyr * gPad->GetBottomMargin(),
425  xmax + dxr * gPad->GetRightMargin(),
426  ymax + dyr * gPad->GetTopMargin());
427  gPad->RangeAxis(xmin, ymin, xmax, ymax);
428  }
429  if (middle) {
430  for (i = 0; i < fNpoints; i++) {
431  if (badcase) continue; //do not update if big zoom and points moved
432  if (x) fX[i] = gPad->PadtoX(gPad->AbsPixeltoX(x[i] + dpx));
433  if (y) fY[i] = gPad->PadtoY(gPad->AbsPixeltoY(y[i] + dpy));
434  }
435  }
436  else {
437  fX[ipoint] = gPad->PadtoX(gPad->AbsPixeltoX(pxold));
438  fY[ipoint] = gPad->PadtoY(gPad->AbsPixeltoY(pyold));
439 // if (InheritsFrom("TCutG")) {
440 // //make sure first and last point are the same
441 // if (ipoint == 0) {
442 // fX[fNpoints-1] = fX[0];
443 // fY[fNpoints-1] = fY[0];
444 // }
445 // if (ipoint == fNpoints-1) {
446 // fX[0] = fX[fNpoints-1];
447 // fY[0] = fY[fNpoints-1];
448 // }
449 // }
450  }
451  badcase = kFALSE;
452  delete [] x;
453  x = 0;
454  delete [] y;
455  y = 0;
456  gPad->Modified(kTRUE);
457  gVirtualX->SetLineColor(-1);
458 
459  }
460 
461 }
462 
463 
464 
465 
468 
469 void KVIDLine::Streamer(TBuffer& R__b)
470 {
471  // Stream an object of class KVIDLine
472 
473  UInt_t R__s, R__c;
474  if (R__b.IsReading()) {
475  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
476  if (R__v < 2) {
477  TGraph::Streamer(R__b);
478  }
479  else {
480  R__b.ReadClassBuffer(KVIDLine::Class(), this, R__v, R__s, R__c);
481  }
482  }
483  else {
484  R__b.WriteClassBuffer(KVIDLine::Class(), this);
485  }
486 }
487 
488 
kMouseMotion
kButton1Motion
kButton1Up
kButton1Down
int Int_t
unsigned int UInt_t
const Int_t kMaxPixel
kMove
kHand
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
#define d(i)
short Version_t
const Bool_t kFALSE
bool Bool_t
double Double_t
const Bool_t kTRUE
float xmin
float ymin
float xmax
float ymax
#define gROOT
char * Form(const char *fmt,...)
#define gPad
#define gVirtualX
Base class for lines/cuts used for particle identification in 2D data maps.
Definition: KVIDLine.h:142
static KVIDLine * MakeIDLine(TObject *obj, Double_t xdeb=-1., Double_t xfin=-1., Double_t np=1., Bool_t save=kFALSE)
Definition: KVIDLine.cpp:88
virtual void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Definition: KVIDLine.cpp:226
KVIDLine()
Default ctor.
Definition: KVIDLine.cpp:38
virtual void WaitForPrimitive()
Definition: KVIDLine.cpp:194
Base class for graphical cuts used in particle identification.
Definition: KVIDentifier.h:27
void CopyGraph(TGraph *)
Copy coordinates of points from the TGraph.
virtual void Modify()
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
Bool_t IsReading() const
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Int_t fNpoints
virtual Bool_t IsEditable() const
TH1F * fHistogram
Int_t GetN() const
Double_t * fY
Double_t * GetX() const
virtual void Draw(Option_t *chopt="")
Double_t * fX
Double_t * GetY() const
virtual Double_t GetBinCenter(Int_t bin) const
virtual Int_t GetNbinsX() const
virtual const char * GetName() const
virtual Bool_t InheritsFrom(const char *classname) const
virtual Double_t GetBinEntries(Int_t bin) const
virtual Double_t GetBinContent(Int_t bin) const
TLine * line
Double_t y[n]
Double_t x[n]
TGraphErrors * gr
Double_t Min(Double_t a, Double_t b)
Double_t Abs(Double_t d)
Double_t Max(Double_t a, Double_t b)