KaliVeda
Toolkit for HIC analysis
Loading...
Searching...
No Matches
KVIDLine.cpp
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
30using namespace std;
31
33
34
35
37
39{
40 //Default ctor
41}
42
43
44
47
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")) {
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/*
154KVIDLine *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
469void 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
kMove
kHand
const Int_t kMaxPixel
#define d(i)
bool Bool_t
short Version_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
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:143
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
virtual ~KVIDLine()
Default dtor.
Definition KVIDLine.cpp:48
KVIDLine()
Default ctor.
Definition KVIDLine.cpp:38
virtual void WaitForPrimitive()
Definition KVIDLine.cpp:194
Base class for graphical cuts used in particle identification.
void CopyGraph(TGraph *)
Copy coordinates of points from the TGraph.
virtual void Streamer(TBuffer &)
static TClass * Class()
virtual void Modify()
virtual Version_t ReadVersion(UInt_t *start=nullptr, UInt_t *bcnt=nullptr, const TClass *cl=nullptr)=0
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=nullptr)=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
Double_t * GetY() const
virtual Bool_t IsEditable() const
TH1F * fHistogram
Int_t GetN() const
Double_t * fY
void Streamer(TBuffer &) override
Double_t * GetX() const
void Draw(Option_t *chopt="") override
Double_t * fX
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
Double_t GetBinContent(Int_t bin) const override
virtual Double_t GetBinEntries(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)
ClassImp(TPyArg)