Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TParallelCoordVar.cxx
Go to the documentation of this file.
1// @(#)root/treeviewer:$Id$
2// Author: Bastien Dalla Piazza 02/08/2007
3
4/*************************************************************************
5 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "TParallelCoordVar.h"
13#include "TParallelCoord.h"
14#include "TParallelCoordRange.h"
15
16#include <iostream>
17
18#include "TLatex.h"
19#include "TLine.h"
20#include "TVirtualPad.h"
21#include "TVirtualX.h"
22#include "TMath.h"
23#include "TH1.h"
24#include "TStyle.h"
25#include "TBox.h"
26#include "TCollection.h"
27#include "TList.h"
28#include "TFrame.h"
29#include "TCanvas.h"
30#include "TMarker.h"
31#include "snprintf.h"
32
34
35/** \class TParallelCoordVar
36
37TParallelCoord axes. Class containing a variable for the TParallelCoord.
38
39Options can be defined each axis separately using the right mouse click. These
40options can be applied to every axes using the editor.
41
42 - Axis width: If set to 0, the axis is simply a line. If higher, a color
43 histogram is drawn on the axis.
44 - Axis histogram height: If not 0, a usual bar histogram is drawn on the plot.
45
46The order in which the variables are drawn is essential to see the clusters. The
47axes can be dragged to change their position. A zoom is also available. The
48logarithm scale is also available by right clicking on the axis.
49*/
50
51////////////////////////////////////////////////////////////////////////////////
52/// Default constructor.
53
56{
57 Init();
58}
59
60////////////////////////////////////////////////////////////////////////////////
61///Destructor.
62
64{
65 if (fHistogram) delete fHistogram;
66 if (fRanges){
67 TIter next(fRanges);
69 while((range = (TParallelCoordRange*)next())) fParallel->CleanUpSelections(range);
70 fRanges->Delete();
71 delete fRanges;
72 }
73 if (fVal) delete [] fVal;
74}
75
76////////////////////////////////////////////////////////////////////////////////
77/// Normal constructor. By default, the title and the name are the expression
78/// given to TTree::Draw. The name can be changed by the user (the label on the
79/// plot) but not the title.
80
82 :TNamed(title,title), TAttLine(1,1,1), TAttFill(kOrange+9,3001)
83{
84 Init();
85 fId = id;
86 fParallel = parallel;
87 fRanges = new TList();
89
91
92 for(Long64_t ui = 0;ui<fParallel->GetNentries();++ui) fVal[ui]=val[ui];
93
97}
98
99////////////////////////////////////////////////////////////////////////////////
100/// Add a range to the current selection on the axis.
101
103{
104 if (!range) {
106 if (select) {
107 range = new TParallelCoordRange(this,0,0,select);
108 fRanges->Add(range);
109 range->GetSelection()->Add(range);
110 } else {
111 Error("AddRange","You must create a selection before adding ranges.");
112 }
113 } else {
114 fRanges->Add(range);
115 range->GetSelection()->Add(range);
116 }
117}
118
119////////////////////////////////////////////////////////////////////////////////
120/// Delete variables.
121
123{
125 delete this;
126}
127
128////////////////////////////////////////////////////////////////////////////////
129/// Computes the distance from the axis.
130
132{
133 if(!gPad) return 9999;
134 Double_t xx = gPad->AbsPixeltoX(px);
135 Double_t yy = gPad->AbsPixeltoY(py);
136 Double_t dist = 9999;
137
138 if (fX1==fX2) {
139 if (yy>fY1+0.01 && yy<fY2-0.01) dist = TMath::Abs(xx - fX1);
140 } else {
141 if (xx>fX1+0.01 && xx<fX2-0.01) dist = TMath::Abs(yy - fY1);
142 }
143 if (dist<=0.005) return 0;
144 else return 9999;
145}
146
147////////////////////////////////////////////////////////////////////////////////
148/// Draw the axis.
149
151{
153}
154
155////////////////////////////////////////////////////////////////////////////////
156/// Check if the entry is within the range(s) of "select". Two ranges on a
157/// single axis are conjugated as a "or": to be selected, the entry must be in
158/// one of the ranges.
159
161{
162 if (fRanges->GetSize() > 0){
163 TIter next(fRanges);
164 bool inarange = false;
165 bool noOwnedRange = true;
166 TParallelCoordRange *range;
167 while ((range = (TParallelCoordRange*)next())){
168 if(select->Contains(range)) {
169 noOwnedRange = false;
170 if(range->IsIn(fVal[evtidx])) inarange = true;
171 }
172 }
173 if (noOwnedRange) return true;
174 else return inarange;
175 }
176 else return true;
177}
178
179////////////////////////////////////////////////////////////////////////////////
180/// Execute the corresponding entry.
181
183{
184 if (!gPad) return;
185 if (!gPad->IsEditable() && entry!=kMouseEnter) return;
186
187 static Int_t pxold, pyold;
188 static Int_t zoom; // -1:nothing zoomed or translated, 0:translating the axis, 1:zooming
189 static Int_t pzoomold;
190 static bool first = true;
191
192 Int_t px1,px2,py1,py2,n=-1;
193 px1 = gPad->XtoAbsPixel(fX1);
194 px2 = gPad->XtoAbsPixel(fX2);
195 py1 = gPad->YtoAbsPixel(fY1);
196 py2 = gPad->YtoAbsPixel(fY2);
197
198 if(fX1 == fX2) {
199 if(gPad->AbsPixeltoX(px)-fX1 > 0) gPad->SetCursor(kArrowVer);
200 else gPad->SetCursor(kArrowHor);
201 } else {
202 if(gPad->AbsPixeltoY(py)-fY1 > 0) gPad->SetCursor(kArrowHor);
203 else gPad->SetCursor(kArrowVer);
204 }
205
206 gVirtualX->SetLineColor(-1);
207 switch (entry) {
208 case kButton1Down:
209 if (fX1==fX2){
210 ((TCanvas*)gPad)->Selected(gPad,fParallel,1);
211 if(gPad->AbsPixeltoX(px)-fX1 > 0){
212 zoom = 1;
213 gVirtualX->DrawLine(gPad->XtoAbsPixel(fX1-0.05),py,gPad->XtoAbsPixel(fX1+0.05),py);
214 first = true;
215 pzoomold = py;
216 } else {
217 zoom = 0;
218 gVirtualX->DrawLine(px,py1,px,py2);
219 }
220 } else {
221 if(gPad->AbsPixeltoY(py)-fY1 > 0){
222 zoom = 1;
223 gVirtualX->DrawLine(px,gPad->YtoAbsPixel(fY1-0.05),px,gPad->YtoAbsPixel(fY1+0.05));
224 first=true;
225 pzoomold = px;
226 } else {
227 zoom = 0;
228 gVirtualX->DrawLine(px1,py,px2,py);
229 }
230 }
231 pxold = px;
232 pyold = py;
233 break;
234 case kButton1Up: {
235 Double_t xx = gPad->AbsPixeltoX(px);
236 Double_t yy = gPad->AbsPixeltoY(py);
237 TFrame *frame = gPad->GetFrame();
238 if (fX1==fX2) {
239 if(zoom == 0){
240 Double_t axisSpace = (frame->GetX2() - frame->GetX1())/(fParallel->GetNvar() - 1);
241 Double_t pos = (xx - frame->GetX1())/axisSpace;
242 if (pos < 0) n = -1;
243 else n = (Int_t)pos;
244 } else {
245 Double_t min = GetValuefromXY(xx,yy);
246 Double_t max = GetValuefromXY(xx,gPad->AbsPixeltoY(pzoomold));
247 if(TMath::Abs(min-max) < 0.00001) return; // Avoid zooming if the axis is just clicked.
249 if (min>max) {
250 Double_t mem = min;
251 min = max; max = mem;
252 }
255 } else {
256 SetCurrentLimits(min,max);
257 }
258 }
259 } else {
260 if(zoom == 0) {
261 Double_t axisSpace = (frame->GetY2() - frame->GetY1())/(fParallel->GetNvar() - 1);
262 Double_t pos = (yy-frame->GetY1())/axisSpace;
263 if (pos < 0) n= -1;
264 else n = (Int_t)pos;
265 } else {
266 Double_t min = GetValuefromXY(xx,yy);
267 Double_t max = GetValuefromXY(gPad->AbsPixeltoX(pzoomold),yy);
268 SetCurrentLimits(min,max);
269 }
270 }
271 if(zoom == 0){
272 if (n>=0 && (UInt_t)n>=fParallel->GetNvar()) --n;
273 else if (n<fParallel->GetVarList()->IndexOf(this)) ++n;
274 fParallel->GetVarList()->Remove(this);
275 fParallel->GetVarList()->AddAt(this,n);
276 }
277 gPad->Modified();
278 break;
279 }
280 case kMouseMotion:
281 pxold=px;
282 pyold=py;
283 break;
284 case kButton1Motion:
285 if(fX1==fX2){
286 if(zoom==0){
287 gPad->SetCursor(kArrowHor);
288 gVirtualX->DrawLine(pxold,py1,pxold,py2);
289 gVirtualX->DrawLine(px,py1,px,py2);
290 } else if(zoom==1) {
291 gPad->SetCursor(kArrowVer);
292 if(!first) gVirtualX->DrawLine(gPad->XtoAbsPixel(fX1-0.05),pyold,gPad->XtoAbsPixel(fX1+0.05),pyold);
293 gVirtualX->DrawLine(gPad->XtoAbsPixel(fX1-0.05),py,gPad->XtoAbsPixel(fX1+0.05),py);
294 first = false;
295 }
296 } else {
297 if(zoom==0){
298 gPad->SetCursor(kArrowVer);
299 gVirtualX->DrawLine(px1,pyold,px2,pyold);
300 gVirtualX->DrawLine(px1,py,px2,py);
301 } else if(zoom==1){
302 gPad->SetCursor(kArrowHor);
303 if(!first) gVirtualX->DrawLine(pxold,gPad->YtoAbsPixel(fY1-0.05),pxold,gPad->YtoAbsPixel(fY1+0.05));
304 gVirtualX->DrawLine(px,gPad->YtoAbsPixel(fY1-0.05),px,gPad->YtoAbsPixel(fY1+0.05));
305 first = false;
306 }
307 }
308 pxold = px;
309 pyold = py;
310 break;
311 }
312}
313
314////////////////////////////////////////////////////////////////////////////////
315/// Get the position of the variable on the graph for the n'th entry.
316
318{
319 if(fX1==fX2){
320 x = fX1;
321 if (fMinCurrent != fMaxCurrent) {
322 if (TestBit(kLogScale)) y = fY1 + (fY2 - fY1) *
324 else y = fY1 + (fY2 - fY1) *
326 } else {
327 y = fY1 + 0.5*(fY2-fY1);
328 }
329 } else {
330 y = fY1;
331 if (fMinCurrent != fMaxCurrent) {
332 if (TestBit(kLogScale)) x = fX1 + (fX2 - fX1) *
334 else x = fX1 + (fX2 - fX1) *
336 } else {
337 x = fX1 + 0.5*(fX2-fX1);
338 }
339 }
340}
341
342////////////////////////////////////////////////////////////////////////////////
343/// Get the entry weight: The weight of an entry for a given variable
344/// is the bin content of the histogram bin the entry is going through.
345
347{
348 Int_t bin = 1 + (Int_t)((fVal[evtidx] - fMinCurrent)/((fMaxCurrent-fMinCurrent)/fNbins));
349 return (Int_t)fHistogram->GetBinContent(bin);
350}
351
352////////////////////////////////////////////////////////////////////////////////
353/// Create or recreate the histogram.
354
356{
357 if (fHistogram) delete fHistogram;
358 fHistogram = nullptr;
359 fHistogram = new TH1F("hpa", "hpa", fNbins, fMinCurrent, fMaxCurrent+0.0001*(fMaxCurrent-fMinCurrent));
360 fHistogram->SetDirectory(nullptr);
363 for(Long64_t li=first; li<first+nentries;++li) {
364 if(fVal[li] >= fMinCurrent && fVal[li] <= fMaxCurrent) fHistogram->Fill(fVal[li]);
365 }
366 return fHistogram;
367}
368
369////////////////////////////////////////////////////////////////////////////////
370/// Get mean, min and max of those variable.
371
373{
374 Double_t min,max,ave = 0;
375 min = DBL_MAX;
376 max = -DBL_MAX;
377 Long64_t first,nentries;
378 first = fParallel->GetCurrentFirst();
380 for(Long64_t li=first; li<first+nentries;++li){
381 if(fVal[li]<min) min = fVal[li];
382 if(fVal[li]>max) max = fVal[li];
383 ave+=fVal[li];
384 }
385
386 fMean = ave/((Double_t)nentries);
387 fMinCurrent = fMinInit = min;
388 fMaxCurrent = fMaxInit = max;
389}
390
391////////////////////////////////////////////////////////////////////////////////
392/// Returns info about this axis.
393
395{
396 static char info[128];
397 info[0] = 0;
398
399 if (!gPad) return info;
400 Double_t xx = gPad->AbsPixeltoX(px);
401 Double_t yy = gPad->AbsPixeltoY(py);
402 if (fX1 == fX2) {
403 if (yy<fY1) {
404 snprintf(info,128,"%s = %f", GetTitle(), fMinCurrent);
405 } else if (yy>fY2) {
406 snprintf(info,128,"%s = %f", GetTitle(), fMaxCurrent);
407 } else {
408 Double_t axislength = fY2-fY1;
409 Double_t pos = (yy-fY1)/axislength;
410 snprintf(info,128,"%s = %f", GetTitle(), fMinCurrent + pos*(fMaxCurrent-fMinCurrent));
411 }
412 } else {
413 if (xx<fX1) {
414 snprintf(info,128,"%s = %f", GetTitle(), fMinCurrent);
415 } else if(xx>fX2) {
416 snprintf(info,128,"%s = %f", GetTitle(), fMaxCurrent);
417 } else {
418 Double_t axislength = fX2-fX1;
419 Double_t pos = (xx-fX1)/axislength;
420 snprintf(info,128,"%s = %f", GetTitle(), pos*(fMaxCurrent-fMinCurrent));
421 }
422 }
423 return info;
424}
425
426////////////////////////////////////////////////////////////////////////////////
427/// Get the box plot values (quantiles).
428
430{
431 Double_t *quantiles = new Double_t[3];
432 quantiles[0]=0.; quantiles[1]=0.; quantiles[2] = 0.;
433 Double_t *prob = new Double_t[3];
434 prob[0]=0.25; prob[1]=0.5; prob[2] = 0.75;
437 if (!TestBit(kLogScale) && first==0 && nentries==fNentries) TMath::Quantiles(fNentries,3,fVal,quantiles,prob,false);
438 else {
439 Double_t* val = new Double_t[nentries];
440 Int_t selected = 0;
441 if(fMinInit<=0) {
442 for (Long64_t n=first;n<first+nentries;++n) {
443 if (fVal[n] >= fMinCurrent) {
444 if (TestBit(kLogScale)) val[selected] = TMath::Log10(fVal[n]);
445 else val[selected] = fVal[n];
446 ++selected;
447 }
448 }
449 } else {
450 for (Long64_t n=first;n<first+nentries;++n) {
451 if (TestBit(kLogScale)) val[selected] = TMath::Log10(fVal[n]);
452 else val[selected] = fVal[n];
453 ++selected;
454 }
455 }
456 TMath::Quantiles(selected,3,val,quantiles,prob,false);
457 delete [] val;
458 }
459 fQua1 = quantiles[0];
460 fMed = quantiles[1];
461 fQua3 = quantiles[2];
462 delete [] quantiles;
463 delete [] prob;
464}
465
466////////////////////////////////////////////////////////////////////////////////
467/// Get the value corresponding to the position.
468
470{
471 Double_t pos;
472 if (fMinCurrent == fMaxCurrent) return fMinCurrent;
473 if (fX1 == fX2) {
474 if (y<=fY1) pos = fMinCurrent;
475 else if (y>=fY2) pos = fMaxCurrent;
476 else pos = fMinCurrent + ((y-fY1)/(fY2-fY1))*(fMaxCurrent-fMinCurrent);
477 } else {
478 if (x<=fX1) pos = fMinCurrent;
479 else if (x>=fX2) pos = fMaxCurrent;
480 else pos = fMinCurrent + ((x-fX1)/(fX2-fX1))*(fMaxCurrent-fMinCurrent);
481 }
482 return pos;
483}
484
485////////////////////////////////////////////////////////////////////////////////
486/// Get a position corresponding to the value on the axis.
487
489{
490 if(value < fMinCurrent || value > fMaxCurrent) return;
491
492 if (fX1==fX2) {
493 x = fX1;
494 if (fMinCurrent != fMaxCurrent) {
495 if (TestBit(kLogScale)) y = fY1 + (fY2 - fY1) *
497 else y = fY1 + (fY2 - fY1) *
499 } else {
500 y = fY1 + 0.5*(fY2-fY1);
501 }
502 } else {
503 y = fY1;
504 if (fMinCurrent != fMaxCurrent) {
505 if (TestBit(kLogScale)) x = fX1 + (fX2 - fX1) *
507 else x = fX1 + (fX2 - fX1) *
509 } else {
510 x = fX1 + 0.5*(fX2-fX1);
511 }
512 }
513}
514
515////////////////////////////////////////////////////////////////////////////////
516/// Initialise the TParallelVar variables.
517
519{
520 fX1 = 0;
521 fX2 = 0;
522 fY1 = 0;
523 fY2 = 0;
524 fId = 0;
525 fVal = nullptr;
526 fMean = 0;
527 fMinInit = 0;
528 fMinCurrent = 0;
529 fMaxInit = 0;
530 fMaxCurrent = 0;
531 fMed = 0;
532 fQua1 = 0;
533 fQua3 = 0;
534 fNentries = 0;
535 fParallel = nullptr;
536 fHistogram = nullptr;
537 fNbins = 100;
538 fHistoLW = 2;
539 fHistoHeight = 0.5;
540 fRanges = nullptr;
541 SetBit(kLogScale,false);
542 SetBit(kShowBox,false);
543 SetBit(kShowBarHisto,true);
544}
545
546////////////////////////////////////////////////////////////////////////////////
547/// Paint the axis.
548
550{
551 TIter next(fRanges);
552 TParallelCoordRange* range;
553 while ((range = (TParallelCoordRange*)next())) range->Paint(option);
554
557 PaintLabels();
558}
559
560////////////////////////////////////////////////////////////////////////////////
561/// Paint the boxes in the case of a candle chart.
562
564{
565 TLine *line = new TLine();
567 line->SetLineWidth(1);
568 TBox *box = new TBox();
569 box->SetLineWidth(1);
570 box->SetLineColor(GetLineColor());
571 box->SetLineStyle(1);
572 box->SetFillStyle(0);
573
574 TFrame* frame = gPad->GetFrame();
575
576 Double_t boxSize;
577 if (fParallel->GetNvar() > 1) {
578 if (fX1==fX2) boxSize = fHistoHeight*((frame->GetY2()-frame->GetY1())/(fParallel->GetNvar()-1));
579 else boxSize = fHistoHeight*((frame->GetX2()-frame->GetX1())/(fParallel->GetNvar()-1));
580 if (boxSize >= 0.03) boxSize = 0.03;
581 }
582 else boxSize = 0.03;
583
584 Double_t qua1,med,qua3,max,min;
585 Double_t a,b,maxinit,mininit;
586 if (TestBit(kLogScale)) {
589 if(fMinInit > 0) mininit = TMath::Log10(fMinInit);
590 else mininit = TMath::Log10(fMinCurrent);
591 maxinit = TMath::Log10(fMaxInit);
592 } else {
593 a = fMinCurrent;
595 mininit = fMinInit;
596 maxinit = fMaxInit;
597 }
598 if(fX1==fX2) {
599 qua1 = fY1 + ((fQua1-a)/b)*(fY2-fY1);
600 qua3 = fY1 + ((fQua3-a)/b)*(fY2-fY1);
601 med = fY1 + ((fMed-a)/b)*(fY2-fY1);
602 max = fY1 + ((maxinit-a)/b)*(fY2-fY1);
603 min = fY1 + ((mininit-a)/b)*(fY2-fY1);
604 } else {
605 qua1 = fX1 + ((fQua1-a)/b)*(fX2-fX1);
606 qua3 = fX1 + ((fQua3-a)/b)*(fX2-fX1);
607 med = fX1 + ((fMed-a)/b)*(fX2-fX1);
608 max = fX1 + ((maxinit-a)/b)*(fX2-fX1);
609 min = fX1 + ((mininit-a)/b)*(fX2-fX1);
610 }
611
612 // min and max lines.
613 if (fX1==fX2) {
614 line->PaintLine(fX1-boxSize,min,fX1+boxSize,min);
615 line->PaintLine(fX2-boxSize,max,fX2+boxSize,max);
616 } else {
617 line->PaintLine(min,fY1-boxSize,min,fY1+boxSize);
618 line->PaintLine(max,fY2-boxSize,max,fY2+boxSize);
619 }
620
621 // lines from min and max to the box.
622 line->SetLineStyle(7);
623 if (fX1==fX2) {
624 if (min<frame->GetY1()) min = frame->GetY1();
625 if (max>frame->GetY2()) max = frame->GetY2();
626 line->PaintLine(fX1,min,fX1,qua1);
627 line->PaintLine(fX1,qua3,fX1,max);
628 } else {
629 if (min<frame->GetX1()) min = frame->GetX1();
630 if (max>frame->GetX2()) max = frame->GetX2();
631 line->PaintLine(min,fY1,qua1,fY2);
632 line->PaintLine(qua3,fY1,max,fY2);
633 }
634
635 // Box
636 if(fX1==fX2) box->PaintBox(fX1-boxSize,qua1,fX1+boxSize,qua3);
637 else box->PaintBox(qua1,fY1-boxSize,qua3,fY1+boxSize);
638
639 // Median line
640 line->SetLineStyle(1);
641 if(fX1==fX2) line->PaintLine(fX1-boxSize,med,fX1+boxSize,med);
642 else line->PaintLine(med,fY1-boxSize,med,fY1+boxSize);
643
644 // Paint average
645 if (!TestBit(kLogScale) || (TestBit(kLogScale) && fMean > 0)) {
646 Double_t mean;
647 if (TestBit(kLogScale)) mean = TMath::Log10(fMean);
648 else mean = fMean;
649 TMarker *mark = nullptr;
650 if(fX1==fX2) mark = new TMarker(fX1,fY1 + ((mean-a)/b)*(fY2-fY1),24);
651 else mark = new TMarker(fX1 + ((mean-a)/b)*(fX2-fX1),fY1,24);
652 mark->Paint();
653 delete mark;
654 }
655
656 delete line;
657 delete box;
658}
659
660////////////////////////////////////////////////////////////////////////////////
661/// Paint the histogram on the axis.
662
664{
665 Int_t i;
666
667 TFrame *frame = gPad->GetFrame();
668
669 if (!fHistogram) GetHistogram();
670
671 // Paint the axis body.
673 // Paint the axis body using bar chart.
674 TBox *b = new TBox();
675 b->SetFillStyle(GetFillStyle());
676 b->SetFillColor(GetFillColor());
677 b->SetLineStyle(1);
678 b->SetLineColor(GetFillColor());
679 b->SetLineWidth(1);
682 if (fX1 == fX2) {
683 // Vertical case.
684 Double_t dy = (fY2-fY1)/fNbins;
687 Double_t y1 = fY1,x2,y2;
688 for (i=1; i<=fNbins; i++) {
690 ((frame->GetX2()-frame->GetX1())/(fParallel->GetNvar()-1));
692 else y2=y1+dy;
693 b->PaintBox(fX1,y1,x2,y2,"l");
694 y1=y2;
695 v += dv;
696 }
697 } else {
698 // Horizontal case.
699 Double_t dx = (fX2-fX1)/fNbins;
702 Double_t x1 = fX1,x2,y2;
703 for (i=1; i<=fNbins; i++) {
704 y2 = fY1+((fHistogram->GetBinContent(i)-hmin)/(hmax-hmin))*fHistoHeight*((frame->GetY2()-frame->GetY1())/(fParallel->GetNvar()-1));
706 else x2=x1+dx;
707 b->PaintBox(x1,fY1,x2,y2,"l");
708 x1=x2;
709 v+=dv;
710 }
711 }
712 delete b;
713 }
714 if (fHistoLW==0 && !TestBit(kShowBox)) {
715 // Paint the axis body as a simple line.
716 TLine* l = new TLine(fX1,fY1,fX2,fY2);
720 l->Paint();
721 delete l;
722 } else if (fHistoLW!=0){
723 // Paint the axis body using the color palette.
724 TLine *lb = new TLine();
728 Int_t theColor;
729 Int_t ncolors = gStyle->GetNumberOfColors();
730 if (fX1 == fX2) {
731 // Vertical case.
732 Double_t dy = (fY2-fY1)/fNbins;
733 Double_t y1 = fY1,y2;
736 for (i=1; i<=fNbins; i++) {
737 theColor = (Int_t)( ((fHistogram->GetBinContent(i)-hmin)/(hmax-hmin))*(ncolors-1) );
739 else y2=y1+dy;
740 lb->SetLineColor(gStyle->GetColorPalette(theColor));
741 lb->PaintLine(fX1,y1,fX1,y2);
742 y1=y2;
743 v+=dv;
744 }
745 } else {
746 // Horizontal case.
747 Double_t dx = (fX2-fX1)/fNbins;
750 Double_t x1 = fX1,x2;
751 for (i=1; i<=fNbins; i++) {
752 theColor = (Int_t)( ((fHistogram->GetBinContent(i)-hmin)/(hmax-hmin))*(ncolors-1) );
753 lb->SetLineColor(gStyle->GetColorPalette(theColor));
755 else x2=x1+dx;
756 lb->PaintLine(x1,fY1,x2,fY1);
757 x1=x2;
758 v+=dv;
759 }
760 }
761 delete lb;
762 }
763}
764
765////////////////////////////////////////////////////////////////////////////////
766/// Paint the axis labels and titles.
767
769{
770 TLatex* t = new TLatex();
771 TFrame *frame = gPad->GetFrame();
772 t->SetTextSize(0.03);
773 if (fX1==fX2) {
774 t->SetText(fX1,frame->GetY1() - 0.04 - t->GetTextSize(),GetName());
775 Double_t tlength = t->GetXsize();
776 if (fX1-0.5*tlength<0.01) {
777 t->SetTextAlign(11);
778 t->SetText(0.01, frame->GetY1() - 0.04 - t->GetTextSize(), GetName());
779 t->Paint();
780 } else if (fX1+0.5*tlength > 0.99) {
781 t->SetTextAlign(31);
782 t->SetText(0.99,frame->GetY1() - 0.04 - t->GetTextSize(),GetName());
783 t->Paint();
784 } else {
785 t->SetTextAlign(21);
786 t->PaintLatex(fX1,frame->GetY1() - 0.04 - t->GetTextSize(),0,0.03,GetName());
787 }
789 t->SetTextAlign(21);
790 t->PaintLatex(fX1,frame->GetY2() + 0.005,0,0.025,Form("%g",fMaxCurrent));
791 t->SetTextAlign(23);
792 t->PaintLatex(fX1,frame->GetY1() - 0.005,0,0.025,Form("%g",fMinCurrent));
793 }
794 } else {
795 t->SetText(fX1-0.04,fY1+0.02,GetName());
796 t->SetTextSize(0.03);
797 Double_t tlength = t->GetXsize();
798 if (fX1-0.04-tlength<0.01) {
799 t->SetTextAlign(12);
800 t->SetText(0.01,fY1+0.02,GetName());
801 t->Paint();
802 } else {
803 t->SetTextAlign(32);
804 t->PaintLatex(fX1-0.04,fY1+0.02,0,0.03,GetName());
805 }
807 t->SetTextAlign(12);
808 t->PaintLatex(0.01,fY1-0.02,0,0.025,Form("%g",fMinCurrent));
809 t->SetTextAlign(32);
810 t->PaintLatex(0.99,fY1-0.02,0,0.025,Form("%g",fMaxCurrent));
811 }
812 }
813 delete t;
814}
815
816////////////////////////////////////////////////////////////////////////////////
817/// Print the axis main data.
818
819void TParallelCoordVar::Print(Option_t* /*option*/) const
820{
821 printf("**************variable #%d**************\n",fParallel->GetVarList()->IndexOf(this));
822 printf("at x1=%f, y1=%f, x2=%f, y2=%f.\n",fX1,fY1,fX2,fY2);
823 printf("min = %f, Q1 = %f, Med = %f, Q3 = %f, Max = %f\n", fMinInit, fQua1, fMed, fQua3, fMaxInit);
824}
825
826////////////////////////////////////////////////////////////////////////////////
827/// Save the TParallelCoordVar as a macro. Can be used only in the context
828/// of TParallelCoord::SavePrimitive (pointer "TParallelCoord* para" is
829/// defined in TParallelCoord::SavePrimitive) with the option "pcalled".
830
831void TParallelCoordVar::SavePrimitive(std::ostream & out, Option_t* options)
832{
833 TString opt = options;
834 if (opt.Contains("pcalled")) {
835 out<<" var->SetBit(TParallelCoordVar::kLogScale,"<<TestBit(kLogScale)<<");"<<std::endl;
836 out<<" var->SetBit(TParallelCoordVar::kShowBox,"<<TestBit(kShowBox)<<");"<<std::endl;
837 out<<" var->SetBit(TParallelCoordVar::kShowBarHisto,"<<TestBit(kShowBarHisto)<<");"<<std::endl;
838 out<<" var->SetHistogramBinning("<<fNbins<<");"<<std::endl;
839 out<<" var->SetHistogramLineWidth("<<fHistoLW<<");"<<std::endl;
840 out<<" var->SetInitMin("<<fMinInit<<");"<<std::endl;
841 out<<" var->SetInitMax("<<fMaxInit<<");"<<std::endl;
842 out<<" var->SetHistogramHeight("<<fHistoHeight<<");"<<std::endl;
843 out<<" var->GetMinMaxMean();"<<std::endl;
844 out<<" var->GetHistogram();"<<std::endl;
845 out<<" var->SetFillStyle("<<GetFillStyle()<<");"<<std::endl;
846 out<<" var->SetFillColor("<<GetFillColor()<<");"<<std::endl;
847 out<<" var->SetLineColor("<<GetLineColor()<<");"<<std::endl;
848 out<<" var->SetLineWidth("<<GetLineWidth()<<");"<<std::endl;
849 out<<" var->SetLineStyle("<<GetLineStyle()<<");"<<std::endl;
850 if (TestBit(kShowBox)) out<<" var->GetQuantiles();"<<std::endl;
851 TIter next(fRanges);
852 TParallelCoordRange* range;
853 Int_t i = 1;
854 while ((range = (TParallelCoordRange*)next())) {
855 out<<" //***************************************"<<std::endl;
856 out<<" // Create the "<<i<<"th range owned by the axis \""<<GetTitle()<<"\"."<<std::endl;
857 out<<" TParallelCoordSelect* sel = para->GetSelection(\""<<range->GetSelection()->GetTitle()<<"\");"<<std::endl;
858 out<<" TParallelCoordRange* newrange = new TParallelCoordRange(var,"<<range->GetMin()<<","<<range->GetMax()<<",sel);"<<std::endl;
859 out<<" var->AddRange(newrange);"<<std::endl;
860 out<<" sel->Add(newrange);"<<std::endl;
861 ++i;
862 }
863 }
864}
865
866////////////////////////////////////////////////////////////////////////////////
867/// Set the axis to display a candle.
868
870{
872 if (box) SetHistogramHeight(0.5);
873 else {
876 }
877}
878
879////////////////////////////////////////////////////////////////////////////////
880/// Set the histogram binning.
881
883{
884 if (n < 0 || n == fNbins) return;
885 fNbins = n;
886 GetHistogram();
887}
888
889////////////////////////////////////////////////////////////////////////////////
890/// Set the height of the bar histogram.
891
893{
894 fHistoHeight = h;
896 if(h!=0) SetBit(kShowBarHisto,true);
897 else SetBit(kShowBarHisto,false);
898 }
899}
900
901////////////////////////////////////////////////////////////////////////////////
902/// Set the current minimum of the axis.
903
905{
906 fMinCurrent = min;
907}
908
909////////////////////////////////////////////////////////////////////////////////
910/// Set the current maximum of the axis.
911
913{
914 fMaxCurrent = max;
915}
916
917////////////////////////////////////////////////////////////////////////////////
918/// Set the limits within which one the entries must be painted.
919
921{
922 if (min>max) {
923 Double_t mem = min;
924 min = max;
925 max = mem;
926 }
927 if(TestBit(kLogScale) && max<=0) return;
928 if(TestBit(kLogScale) && min<=0) min = 0.00001*max;
929 fMinCurrent = min;
930 fMaxCurrent = max;
931
932 delete fHistogram;
933 fHistogram = nullptr;
934 GetHistogram();
935
939 }
940}
941
942////////////////////////////////////////////////////////////////////////////////
943/// If true, the pad is updated while the motion of a dragged range.
944
946{
947 TIter next(fRanges);
948 TParallelCoordRange* range;
949 while ((range = (TParallelCoordRange*)next())) range->SetBit(TParallelCoordRange::kLiveUpdate,on);
950}
951
952////////////////////////////////////////////////////////////////////////////////
953/// Set the axis in log scale.
954
956{
957 if (log == TestBit (kLogScale)) return;
958 if (fMaxInit < 0) SetBit(kLogScale,false);
959 else if (log) {
960 if (fMaxCurrent < 0 ) fMaxCurrent = fMaxInit;
961 if (fMinCurrent < 0 ) fMinCurrent = 0.00001*fMaxCurrent;
962 SetBit(kLogScale,true);
965 } else {
966 SetBit(kLogScale,false);
969 }
970 GetQuantiles();
971 GetHistogram();
972}
973
974////////////////////////////////////////////////////////////////////////////////
975/// Set the variable values.
976
978{
979 if (fVal) delete [] fVal;
980 fVal = new Double_t[length];
982 for (Long64_t li = 0; li < length; ++li) fVal[li] = val[li];
984 GetHistogram();
986}
987
988////////////////////////////////////////////////////////////////////////////////
989/// Set the X position of the axis in the case of a vertical axis.
990/// and rotate the axis if it was horizontal.
991
993{
994 TFrame *frame = gPad->GetFrame();
995 if (!gl) {
996 fY1 = frame->GetY1();
997 fY2 = frame->GetY2();
998 } else {
1001 fY1 = frame->GetY1() + ((fMinCurrent-gmin)/(gmax-gmin))*(frame->GetY2()-frame->GetY1());
1002 fY2 = frame->GetY1() + ((fMaxCurrent-gmin)/(gmax-gmin))*(frame->GetY2()-frame->GetY1());
1003 }
1004 fX1 = fX2 = x;
1005}
1006
1007////////////////////////////////////////////////////////////////////////////////
1008/// Set the Y position of the axis in the case of a horizontal axis.
1009/// and rotate the axis if it was vertical.
1010
1012{
1013 TFrame *frame = gPad->GetFrame();
1014 if (!gl) {
1015 fX1 = frame->GetX1();
1016 fX2 = frame->GetX2();
1017 } else {
1020 fX1 = frame->GetX1() + ((fMinCurrent-gmin)/(gmax-gmin))*(frame->GetX2()-frame->GetX1());
1021 fX2 = frame->GetX1() + ((fMaxCurrent-gmin)/(gmax-gmin))*(frame->GetX2()-frame->GetX1());
1022 }
1023 fY1 = fY2 = y;
1024}
@ kMouseMotion
Definition Buttons.h:23
@ kButton1Motion
Definition Buttons.h:20
@ kButton1Up
Definition Buttons.h:19
@ kButton1Down
Definition Buttons.h:17
@ kMouseEnter
Definition Buttons.h:23
@ kArrowVer
Definition GuiTypes.h:374
@ kArrowHor
Definition GuiTypes.h:374
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
int Int_t
Definition RtypesCore.h:45
double Double_t
Definition RtypesCore.h:59
long long Long64_t
Definition RtypesCore.h:80
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
@ kOrange
Definition Rtypes.h:67
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t hmin
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t hmax
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 winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void on
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char y1
int nentries
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2489
R__EXTERN TStyle * gStyle
Definition TStyle.h:433
#define gPad
#define gVirtualX
Definition TVirtualX.h:337
#define snprintf
Definition civetweb.c:1540
Fill Area Attributes class.
Definition TAttFill.h:19
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:30
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:31
Line Attributes class.
Definition TAttLine.h:18
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:33
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:42
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:35
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:43
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:40
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:34
virtual Float_t GetTextSize() const
Return the text size.
Definition TAttText.h:36
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:42
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:47
Create a Box.
Definition TBox.h:22
Double_t GetX1() const
Definition TBox.h:51
Double_t GetX2() const
Definition TBox.h:52
Double_t GetY1() const
Definition TBox.h:53
Double_t GetY2() const
Definition TBox.h:54
The Canvas class.
Definition TCanvas.h:23
Bool_t Contains(const char *name) const
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Define a Frame.
Definition TFrame.h:19
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:621
virtual void SetDirectory(TDirectory *dir)
By default, when a histogram is created, it is added to the list of histogram objects in the current ...
Definition TH1.cxx:8901
virtual Double_t GetMaximum(Double_t maxval=FLT_MAX) const
Return maximum value smaller than maxval of bins in the range, unless the value has been overridden b...
Definition TH1.cxx:8509
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition TH1.cxx:3340
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5025
virtual Double_t GetMinimum(Double_t minval=-FLT_MAX) const
Return minimum value larger than minval of bins in the range, unless the value has been overridden by...
Definition TH1.cxx:8599
To draw Mathematical Formula.
Definition TLatex.h:18
Double_t GetXsize()
Return size of the formula along X in pad coordinates when the text precision is smaller than 3.
Definition TLatex.cxx:2569
virtual void PaintLatex(Double_t x, Double_t y, Double_t angle, Double_t size, const char *text)
Main drawing function.
Definition TLatex.cxx:2114
void Paint(Option_t *option="") override
Paint.
Definition TLatex.cxx:2092
Use the TLine constructor to create a simple line.
Definition TLine.h:22
virtual void PaintLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Draw this line with new coordinates.
Definition TLine.cxx:399
void Paint(Option_t *option="") override
Paint this line with its current attributes.
Definition TLine.cxx:389
A doubly linked list.
Definition TList.h:38
void AddAt(TObject *obj, Int_t idx) override
Insert object at position idx in the list.
Definition TList.cxx:304
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:820
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:468
Manages Markers.
Definition TMarker.h:22
void Paint(Option_t *option="") override
Paint this marker with its current attributes.
Definition TMarker.cxx:304
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:201
virtual void AppendPad(Option_t *option="")
Append graphics object to current pad.
Definition TObject.cxx:184
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:780
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:976
A TParallelCoordRange is a range used for parallel coordinates plots.
void Paint(Option_t *options) override
Paint a TParallelCoordRange.
virtual Double_t GetMin()
bool IsIn(Double_t evtval)
Evaluate if the given value is within the range or not.
TParallelCoordSelect * GetSelection()
virtual Double_t GetMax()
A TParallelCoordSelect is a specialised TList to hold TParallelCoordRanges used by TParallelCoord.
const char * GetTitle() const override
Returns title of object.
TParallelCoord axes.
void Paint(Option_t *option="") override
Paint the axis.
TH1F * fHistogram
! Histogram holding the variable distribution.
TH1F * GetHistogram()
Create or recreate the histogram.
char * GetObjectInfo(Int_t px, Int_t py) const override
Returns info about this axis.
void GetEntryXY(Long64_t n, Double_t &x, Double_t &y)
Get the position of the variable on the graph for the n'th entry.
Double_t GetValuefromXY(Double_t x, Double_t y)
Get the value corresponding to the position.
void PaintBoxPlot()
Paint the boxes in the case of a candle chart.
void PaintLabels()
Paint the axis labels and titles.
void ExecuteEvent(Int_t entry, Int_t px, Int_t py) override
Execute the corresponding entry.
void SetBoxPlot(bool box)
Set the axis to display a candle.
void PaintHistogram()
Paint the histogram on the axis.
Double_t fY1
y1 coordinate of the axis.
void SetCurrentMin(Double_t min)
Set the current minimum of the axis.
void SetY(Double_t y, bool gl)
Set the Y position of the axis in the case of a horizontal axis.
void SetLiveRangesUpdate(bool on)
If true, the pad is updated while the motion of a dragged range.
void SetX(Double_t x, bool gl)
Set the X position of the axis in the case of a vertical axis.
Double_t fX1
x1 coordinate of the axis.
~TParallelCoordVar() override
Destructor.
void SavePrimitive(std::ostream &out, Option_t *options) override
Save the TParallelCoordVar as a macro.
Double_t fMaxInit
Memory of the maximum when first initialized.
void SetCurrentMax(Double_t max)
Set the current maximum of the axis.
void SetLogScale(bool log)
Set the axis in log scale.
TList * fRanges
List of the TParallelRange owned by TParallelCoordVar.
void GetQuantiles()
Get the box plot values (quantiles).
Double_t fMinCurrent
Current used minimum.
void SetHistogramHeight(Double_t h=0)
Set the height of the bar histogram.
void DeleteVariable()
Delete variables.
TParallelCoordVar()
Default constructor.
Double_t fMinInit
Memory of the minimum when first initialized.
TParallelCoord * fParallel
Pointer to the TParallelCoord which owns the TParallelCoordVar.
Int_t fId
Id identifying the variable for the editor.
Int_t fNbins
Number of bins in fHistogram.
Long64_t fNentries
Number of stored entries values.
Int_t GetEntryWeight(Long64_t evtidx)
Get the entry weight: The weight of an entry for a given variable is the bin content of the histogram...
Double_t * fVal
![fNentries] Entries values for the variable.
Int_t fHistoLW
Line width used to draw the histogram line.
Double_t fMean
Average.
Double_t fY2
y2 coordinate of the axis.
void SetHistogramLineWidth(Int_t lw=2)
Double_t fX2
x2 coordinate of the axis.
void Init()
Initialise the TParallelVar variables.
void GetXYfromValue(Double_t value, Double_t &x, Double_t &y)
Get a position corresponding to the value on the axis.
void Print(Option_t *option="") const override
Print the axis main data.
void GetMinMaxMean()
Get mean, min and max of those variable.
bool Eval(Long64_t evtidx, TParallelCoordSelect *select)
Check if the entry is within the range(s) of "select".
void Draw(Option_t *option="") override
Draw the axis.
Double_t fQua1
First quantile (Q1).
void SetValues(Long64_t length, Double_t *val)
Set the variable values.
Double_t fQua3
Third quantile (Q3).
void SetHistogramBinning(Int_t n=100)
Set the histogram binning.
Double_t fMed
Median value (Q2).
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Computes the distance from the axis.
void SetCurrentLimits(Double_t min, Double_t max)
Set the limits within which one the entries must be painted.
Double_t fHistoHeight
Histogram Height.
Double_t fMaxCurrent
Current used maximum.
Parallel Coordinates class.
TParallelCoordSelect * GetCurrentSelection()
Return the selection currently being edited.
Double_t GetGlobalMin()
return the global minimum.
Long64_t GetNentries()
Long64_t GetCurrentFirst()
Long64_t GetCurrentN()
TList * GetVarList()
Double_t GetGlobalMax()
return the global maximum.
void SetGlobalMax(Double_t max)
Force all variables to adopt the same max.
void SetGlobalMin(Double_t min)
Force all variables to adopt the same min.
void RemoveVariable(TParallelCoordVar *var)
Delete a variable from the graph.
void CleanUpSelections(TParallelCoordRange *range)
Clean up the selections from the ranges which could have been deleted when a variable has been delete...
@ kGlobalScale
Every variable is on the same scale.
@ kCandleChart
To produce a candle chart.
virtual Int_t IndexOf(const TObject *obj) const
Return index of object in collection.
Basic string class.
Definition TString.h:139
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1097
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1171
virtual void SetText(Double_t x, Double_t y, const char *text)
Definition TText.h:74
TLine * line
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
void Quantiles(Int_t n, Int_t nprob, Double_t *x, Double_t *quantiles, Double_t *prob, Bool_t isSorted=kTRUE, Int_t *index=nullptr, Int_t type=7)
Computes sample quantiles, corresponding to the given probabilities.
Definition TMath.cxx:1207
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:762
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:123
TLine l
Definition textangle.C:4