Logo ROOT   6.16/01
Reference Guide
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 "Riostream.h"
17#include "TROOT.h"
18#include "TLatex.h"
19#include "TLine.h"
20#include "TVirtualPad.h"
21#include "TMath.h"
22#include "TH1.h"
23#include "TStyle.h"
24#include "TBox.h"
25#include "TCollection.h"
26#include "TList.h"
27#include "TFrame.h"
28#include "TCanvas.h"
29#include "TMarker.h"
30
32
33/** \class TParallelCoordVar
34
35TParallelCoord axes. Class containing a variable for the TParallelCoord.
36
37Options can be defined each axis separately using the right mouse click. These
38options can be applied to every axes using the editor.
39
40 - Axis width: If set to 0, the axis is simply a line. If higher, a color
41 histogram is drawn on the axis.
42 - Axis histogram height: If not 0, a usual bar histogram is drawn on the plot.
43
44The order in which the variables are drawn is essential to see the clusters. The
45axes can be dragged to change their position. A zoom is also available. The
46logarithm scale is also available by right clicking on the axis.
47*/
48
49////////////////////////////////////////////////////////////////////////////////
50/// Default constructor.
51
54{
55 Init();
56}
57
58////////////////////////////////////////////////////////////////////////////////
59///Destructor.
60
62{
63 if (fHistogram) delete fHistogram;
64 if (fRanges){
65 TIter next(fRanges);
67 while((range = (TParallelCoordRange*)next())) fParallel->CleanUpSelections(range);
68 fRanges->Delete();
69 delete fRanges;
70 }
71 if (fVal) delete [] fVal;
72}
73
74////////////////////////////////////////////////////////////////////////////////
75/// Normal constructor. By default, the title and the name are the expression
76/// given to TTree::Draw. The name can be changed by the user (the label on the
77/// plot) but not the title.
78
80 :TNamed(title,title), TAttLine(1,1,1), TAttFill(kOrange+9,3001)
81{
82 Init();
83 fId = id;
84 fParallel = parallel;
85 fRanges = new TList();
87
89
90 for(Long64_t ui = 0;ui<fParallel->GetNentries();++ui) fVal[ui]=val[ui];
91
95}
96
97////////////////////////////////////////////////////////////////////////////////
98/// Add a range to the current selection on the axis.
99
101{
102 if (!range) {
104 if (select) {
105 range = new TParallelCoordRange(this,0,0,select);
106 fRanges->Add(range);
107 range->GetSelection()->Add(range);
108 } else {
109 Error("AddRange","You must create a selection before adding ranges.");
110 }
111 } else {
112 fRanges->Add(range);
113 range->GetSelection()->Add(range);
114 }
115}
116
117////////////////////////////////////////////////////////////////////////////////
118/// Delete variables.
119
121{
123 delete this;
124}
125
126////////////////////////////////////////////////////////////////////////////////
127/// Computes the distance from the axis.
128
130{
131 if(!gPad) return 9999;
132 Double_t xx = gPad->AbsPixeltoX(px);
133 Double_t yy = gPad->AbsPixeltoY(py);
134 Double_t dist = 9999;
135
136 if (fX1==fX2) {
137 if (yy>fY1+0.01 && yy<fY2-0.01) dist = TMath::Abs(xx - fX1);
138 } else {
139 if (xx>fX1+0.01 && xx<fX2-0.01) dist = TMath::Abs(yy - fY1);
140 }
141 if (dist<=0.005) return 0;
142 else return 9999;
143}
144
145////////////////////////////////////////////////////////////////////////////////
146/// Draw the axis.
147
149{
150 AppendPad(option);
151}
152
153////////////////////////////////////////////////////////////////////////////////
154/// Check if the entry is within the range(s) of "select". Two ranges on a
155/// single axis are conjugated as a "or": to be selected, the entry must be in
156/// one of the ranges.
157
159{
160 if (fRanges->GetSize() > 0){
161 TIter next(fRanges);
162 Bool_t inarange = kFALSE;
163 Bool_t noOwnedRange = kTRUE;
164 TParallelCoordRange *range;
165 while ((range = (TParallelCoordRange*)next())){
166 if(select->Contains(range)) {
167 noOwnedRange = kFALSE;
168 if(range->IsIn(fVal[evtidx])) inarange = kTRUE;
169 }
170 }
171 if (noOwnedRange) return kTRUE;
172 else return inarange;
173 }
174 else return kTRUE;
175}
176
177////////////////////////////////////////////////////////////////////////////////
178/// Execute the corresponding entry.
179
181{
182 if (!gPad) return;
183 if (!gPad->IsEditable() && entry!=kMouseEnter) return;
184
185 static Int_t pxold, pyold;
186 static Int_t zoom; // -1:nothing zoomed or translated, 0:translating the axis, 1:zooming
187 static Int_t pzoomold;
188 static Bool_t first = kTRUE;
189
190 Int_t px1,px2,py1,py2,n=-1;
191 px1 = gPad->XtoAbsPixel(fX1);
192 px2 = gPad->XtoAbsPixel(fX2);
193 py1 = gPad->YtoAbsPixel(fY1);
194 py2 = gPad->YtoAbsPixel(fY2);
195
196 if(fX1 == fX2) {
197 if(gPad->AbsPixeltoX(px)-fX1 > 0) gPad->SetCursor(kArrowVer);
198 else gPad->SetCursor(kArrowHor);
199 } else {
200 if(gPad->AbsPixeltoY(py)-fY1 > 0) gPad->SetCursor(kArrowHor);
201 else gPad->SetCursor(kArrowVer);
202 }
203
204 gVirtualX->SetLineColor(-1);
205 switch (entry) {
206 case kButton1Down:
207 if (fX1==fX2){
208 ((TCanvas*)gPad)->Selected(gPad,fParallel,1);
209 if(gPad->AbsPixeltoX(px)-fX1 > 0){
210 zoom = 1;
211 gVirtualX->DrawLine(gPad->XtoAbsPixel(fX1-0.05),py,gPad->XtoAbsPixel(fX1+0.05),py);
212 first = kTRUE;
213 pzoomold = py;
214 } else {
215 zoom = 0;
216 gVirtualX->DrawLine(px,py1,px,py2);
217 }
218 } else {
219 if(gPad->AbsPixeltoY(py)-fY1 > 0){
220 zoom = 1;
221 gVirtualX->DrawLine(px,gPad->YtoAbsPixel(fY1-0.05),px,gPad->YtoAbsPixel(fY1+0.05));
222 first=kTRUE;
223 pzoomold = px;
224 } else {
225 zoom = 0;
226 gVirtualX->DrawLine(px1,py,px2,py);
227 }
228 }
229 pxold = px;
230 pyold = py;
231 break;
232 case kButton1Up: {
233 Double_t xx = gPad->AbsPixeltoX(px);
234 Double_t yy = gPad->AbsPixeltoY(py);
235 TFrame *frame = gPad->GetFrame();
236 if (fX1==fX2) {
237 if(zoom == 0){
238 Double_t axisSpace = (frame->GetX2() - frame->GetX1())/(fParallel->GetNvar() - 1);
239 Double_t pos = (xx - frame->GetX1())/axisSpace;
240 if (pos < 0) n = -1;
241 else n = (Int_t)pos;
242 } else {
243 Double_t min = GetValuefromXY(xx,yy);
244 Double_t max = GetValuefromXY(xx,gPad->AbsPixeltoY(pzoomold));
245 if(TMath::Abs(min-max) < 0.00001) return; // Avoid zooming if the axis is just clicked.
247 if (min>max) {
248 Double_t mem = min;
249 min = max; max = mem;
250 }
253 } else {
254 SetCurrentLimits(min,max);
255 }
256 }
257 } else {
258 if(zoom == 0) {
259 Double_t axisSpace = (frame->GetY2() - frame->GetY1())/(fParallel->GetNvar() - 1);
260 Double_t pos = (yy-frame->GetY1())/axisSpace;
261 if (pos < 0) n= -1;
262 else n = (Int_t)pos;
263 } else {
264 Double_t min = GetValuefromXY(xx,yy);
265 Double_t max = GetValuefromXY(gPad->AbsPixeltoX(pzoomold),yy);
266 SetCurrentLimits(min,max);
267 }
268 }
269 if(zoom == 0){
270 if (n>=0 && (UInt_t)n>=fParallel->GetNvar()) --n;
271 else if (n<fParallel->GetVarList()->IndexOf(this)) ++n;
272 fParallel->GetVarList()->Remove(this);
273 fParallel->GetVarList()->AddAt(this,n);
274 }
275 gPad->Modified();
276 break;
277 }
278 case kMouseMotion:
279 pxold=px;
280 pyold=py;
281 break;
282 case kButton1Motion:
283 if(fX1==fX2){
284 if(zoom==0){
285 gPad->SetCursor(kArrowHor);
286 gVirtualX->DrawLine(pxold,py1,pxold,py2);
287 gVirtualX->DrawLine(px,py1,px,py2);
288 } else if(zoom==1) {
289 gPad->SetCursor(kArrowVer);
290 if(!first) gVirtualX->DrawLine(gPad->XtoAbsPixel(fX1-0.05),pyold,gPad->XtoAbsPixel(fX1+0.05),pyold);
291 gVirtualX->DrawLine(gPad->XtoAbsPixel(fX1-0.05),py,gPad->XtoAbsPixel(fX1+0.05),py);
292 first = kFALSE;
293 }
294 } else {
295 if(zoom==0){
296 gPad->SetCursor(kArrowVer);
297 gVirtualX->DrawLine(px1,pyold,px2,pyold);
298 gVirtualX->DrawLine(px1,py,px2,py);
299 } else if(zoom==1){
300 gPad->SetCursor(kArrowHor);
301 if(!first) gVirtualX->DrawLine(pxold,gPad->YtoAbsPixel(fY1-0.05),pxold,gPad->YtoAbsPixel(fY1+0.05));
302 gVirtualX->DrawLine(px,gPad->YtoAbsPixel(fY1-0.05),px,gPad->YtoAbsPixel(fY1+0.05));
303 first = kFALSE;
304 }
305 }
306 pxold = px;
307 pyold = py;
308 break;
309 }
310}
311
312////////////////////////////////////////////////////////////////////////////////
313/// Get the position of the variable on the graph for the n'th entry.
314
316{
317 if(fX1==fX2){
318 x = fX1;
319 if (fMinCurrent != fMaxCurrent) {
320 if (TestBit(kLogScale)) y = fY1 + (fY2 - fY1) *
322 else y = fY1 + (fY2 - fY1) *
324 } else {
325 y = fY1 + 0.5*(fY2-fY1);
326 }
327 } else {
328 y = fY1;
329 if (fMinCurrent != fMaxCurrent) {
330 if (TestBit(kLogScale)) x = fX1 + (fX2 - fX1) *
332 else x = fX1 + (fX2 - fX1) *
334 } else {
335 x = fX1 + 0.5*(fX2-fX1);
336 }
337 }
338}
339
340////////////////////////////////////////////////////////////////////////////////
341/// Get the entry weight: The weight of an entry for a given variable
342/// is the bin content of the histogram bin the entry is going through.
343
345{
346 Int_t bin = 1 + (Int_t)((fVal[evtidx] - fMinCurrent)/((fMaxCurrent-fMinCurrent)/fNbins));
347 return (Int_t)fHistogram->GetBinContent(bin);
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// Create or recreate the histogram.
352
354{
355 if (fHistogram) delete fHistogram;
356 fHistogram = NULL;
357 fHistogram = new TH1F("hpa", "hpa", fNbins, fMinCurrent, fMaxCurrent+0.0001*(fMaxCurrent-fMinCurrent));
361 for(Long64_t li=first; li<first+nentries;++li) {
362 if(fVal[li] >= fMinCurrent && fVal[li] <= fMaxCurrent) fHistogram->Fill(fVal[li]);
363 }
364 return fHistogram;
365}
366
367////////////////////////////////////////////////////////////////////////////////
368/// Get mean, min and max of those variable.
369
371{
372 Double_t min,max,ave = 0;
373 min = DBL_MAX;
374 max = -DBL_MAX;
378 for(Long64_t li=first; li<first+nentries;++li){
379 if(fVal[li]<min) min = fVal[li];
380 if(fVal[li]>max) max = fVal[li];
381 ave+=fVal[li];
382 }
383
384 fMean = ave/((Double_t)nentries);
385 fMinCurrent = fMinInit = min;
386 fMaxCurrent = fMaxInit = max;
387}
388
389////////////////////////////////////////////////////////////////////////////////
390/// Returns info about this axis.
391
393{
394 static char info[128];
395 info[0] = 0;
396
397 if (!gPad) return info;
398 Double_t xx = gPad->AbsPixeltoX(px);
399 Double_t yy = gPad->AbsPixeltoY(py);
400 if (fX1 == fX2) {
401 if (yy<fY1) {
402 snprintf(info,128,"%s = %f", GetTitle(), fMinCurrent);
403 } else if (yy>fY2) {
404 snprintf(info,128,"%s = %f", GetTitle(), fMaxCurrent);
405 } else {
406 Double_t axislength = fY2-fY1;
407 Double_t pos = (yy-fY1)/axislength;
408 snprintf(info,128,"%s = %f", GetTitle(), fMinCurrent + pos*(fMaxCurrent-fMinCurrent));
409 }
410 } else {
411 if (xx<fX1) {
412 snprintf(info,128,"%s = %f", GetTitle(), fMinCurrent);
413 } else if(xx>fX2) {
414 snprintf(info,128,"%s = %f", GetTitle(), fMaxCurrent);
415 } else {
416 Double_t axislength = fX2-fX1;
417 Double_t pos = (xx-fX1)/axislength;
418 snprintf(info,128,"%s = %f", GetTitle(), pos*(fMaxCurrent-fMinCurrent));
419 }
420 }
421 return info;
422}
423
424////////////////////////////////////////////////////////////////////////////////
425/// Get the box plot values (quantiles).
426
428{
429 Double_t *quantiles = new Double_t[3];
430 quantiles[0]=0.; quantiles[1]=0.; quantiles[2] = 0.;
431 Double_t *prob = new Double_t[3];
432 prob[0]=0.25; prob[1]=0.5; prob[2] = 0.75;
435 if (!TestBit(kLogScale) && first==0 && nentries==fNentries) TMath::Quantiles(fNentries,3,fVal,quantiles,prob,kFALSE);
436 else {
437 Double_t* val = new Double_t[nentries];
438 Int_t selected = 0;
439 if(fMinInit<=0) {
440 for (Long64_t n=first;n<first+nentries;++n) {
441 if (fVal[n] >= fMinCurrent) {
442 if (TestBit(kLogScale)) val[selected] = TMath::Log10(fVal[n]);
443 else val[selected] = fVal[n];
444 ++selected;
445 }
446 }
447 } else {
448 for (Long64_t n=first;n<first+nentries;++n) {
449 if (TestBit(kLogScale)) val[selected] = TMath::Log10(fVal[n]);
450 else val[selected] = fVal[n];
451 ++selected;
452 }
453 }
454 TMath::Quantiles(selected,3,val,quantiles,prob,kFALSE);
455 delete [] val;
456 }
457 fQua1 = quantiles[0];
458 fMed = quantiles[1];
459 fQua3 = quantiles[2];
460 delete [] quantiles;
461 delete [] prob;
462}
463
464////////////////////////////////////////////////////////////////////////////////
465/// Get the value corresponding to the position.
466
468{
469 Double_t pos;
470 if (fMinCurrent == fMaxCurrent) return fMinCurrent;
471 if (fX1 == fX2) {
472 if (y<=fY1) pos = fMinCurrent;
473 else if (y>=fY2) pos = fMaxCurrent;
474 else pos = fMinCurrent + ((y-fY1)/(fY2-fY1))*(fMaxCurrent-fMinCurrent);
475 } else {
476 if (x<=fX1) pos = fMinCurrent;
477 else if (x>=fX2) pos = fMaxCurrent;
478 else pos = fMinCurrent + ((x-fX1)/(fX2-fX1))*(fMaxCurrent-fMinCurrent);
479 }
480 return pos;
481}
482
483////////////////////////////////////////////////////////////////////////////////
484/// Get a position corresponding to the value on the axis.
485
487{
488 if(value < fMinCurrent || value > fMaxCurrent) return;
489
490 if (fX1==fX2) {
491 x = fX1;
492 if (fMinCurrent != fMaxCurrent) {
493 if (TestBit(kLogScale)) y = fY1 + (fY2 - fY1) *
495 else y = fY1 + (fY2 - fY1) *
496 (value - fMinCurrent) / (fMaxCurrent - fMinCurrent);
497 } else {
498 y = fY1 + 0.5*(fY2-fY1);
499 }
500 } else {
501 y = fY1;
502 if (fMinCurrent != fMaxCurrent) {
503 if (TestBit(kLogScale)) x = fX1 + (fX2 - fX1) *
505 else x = fX1 + (fX2 - fX1) *
506 (value - fMinCurrent) / (fMaxCurrent - fMinCurrent);
507 } else {
508 x = fX1 + 0.5*(fX2-fX1);
509 }
510 }
511}
512
513////////////////////////////////////////////////////////////////////////////////
514/// Initialise the TParallelVar variables.
515
517{
518 fX1 = 0;
519 fX2 = 0;
520 fY1 = 0;
521 fY2 = 0;
522 fId = 0;
523 fVal = NULL;
524 fMean = 0;
525 fMinInit = 0;
526 fMinCurrent = 0;
527 fMaxInit = 0;
528 fMaxCurrent = 0;
529 fMed = 0;
530 fQua1 = 0;
531 fQua3 = 0;
532 fNentries = 0;
533 fParallel = NULL;
534 fHistogram = NULL;
535 fNbins = 100;
536 fHistoLW = 2;
537 fHistoHeight = 0.5;
538 fRanges = NULL;
542}
543
544////////////////////////////////////////////////////////////////////////////////
545/// Paint the axis.
546
548{
549 TIter next(fRanges);
550 TParallelCoordRange* range;
551 while ((range = (TParallelCoordRange*)next())) range->Paint(option);
552
555 PaintLabels();
556}
557
558////////////////////////////////////////////////////////////////////////////////
559/// Paint the boxes in the case of a candle chart.
560
562{
563 TLine *line = new TLine();
565 line->SetLineWidth(1);
566 TBox *box = new TBox();
567 box->SetLineWidth(1);
568 box->SetLineColor(GetLineColor());
569 box->SetLineStyle(1);
570 box->SetFillStyle(0);
571
572 TFrame* frame = gPad->GetFrame();
573
574 Double_t boxSize;
575 if (fParallel->GetNvar() > 1) {
576 if (fX1==fX2) boxSize = fHistoHeight*((frame->GetY2()-frame->GetY1())/(fParallel->GetNvar()-1));
577 else boxSize = fHistoHeight*((frame->GetX2()-frame->GetX1())/(fParallel->GetNvar()-1));
578 if (boxSize >= 0.03) boxSize = 0.03;
579 }
580 else boxSize = 0.03;
581
582 Double_t qua1,med,qua3,max,min;
583 Double_t a,b,maxinit,mininit;
584 if (TestBit(kLogScale)) {
587 if(fMinInit > 0) mininit = TMath::Log10(fMinInit);
588 else mininit = TMath::Log10(fMinCurrent);
589 maxinit = TMath::Log10(fMaxInit);
590 } else {
591 a = fMinCurrent;
593 mininit = fMinInit;
594 maxinit = fMaxInit;
595 }
596 if(fX1==fX2) {
597 qua1 = fY1 + ((fQua1-a)/b)*(fY2-fY1);
598 qua3 = fY1 + ((fQua3-a)/b)*(fY2-fY1);
599 med = fY1 + ((fMed-a)/b)*(fY2-fY1);
600 max = fY1 + ((maxinit-a)/b)*(fY2-fY1);
601 min = fY1 + ((mininit-a)/b)*(fY2-fY1);
602 } else {
603 qua1 = fX1 + ((fQua1-a)/b)*(fX2-fX1);
604 qua3 = fX1 + ((fQua3-a)/b)*(fX2-fX1);
605 med = fX1 + ((fMed-a)/b)*(fX2-fX1);
606 max = fX1 + ((maxinit-a)/b)*(fX2-fX1);
607 min = fX1 + ((mininit-a)/b)*(fX2-fX1);
608 }
609
610 // min and max lines.
611 if (fX1==fX2) {
612 line->PaintLine(fX1-boxSize,min,fX1+boxSize,min);
613 line->PaintLine(fX2-boxSize,max,fX2+boxSize,max);
614 } else {
615 line->PaintLine(min,fY1-boxSize,min,fY1+boxSize);
616 line->PaintLine(max,fY2-boxSize,max,fY2+boxSize);
617 }
618
619 // lines from min and max to the box.
620 line->SetLineStyle(7);
621 if (fX1==fX2) {
622 if (min<frame->GetY1()) min = frame->GetY1();
623 if (max>frame->GetY2()) max = frame->GetY2();
624 line->PaintLine(fX1,min,fX1,qua1);
625 line->PaintLine(fX1,qua3,fX1,max);
626 } else {
627 if (min<frame->GetX1()) min = frame->GetX1();
628 if (max>frame->GetX2()) max = frame->GetX2();
629 line->PaintLine(min,fY1,qua1,fY2);
630 line->PaintLine(qua3,fY1,max,fY2);
631 }
632
633 // Box
634 if(fX1==fX2) box->PaintBox(fX1-boxSize,qua1,fX1+boxSize,qua3);
635 else box->PaintBox(qua1,fY1-boxSize,qua3,fY1+boxSize);
636
637 // Median line
638 line->SetLineStyle(1);
639 if(fX1==fX2) line->PaintLine(fX1-boxSize,med,fX1+boxSize,med);
640 else line->PaintLine(med,fY1-boxSize,med,fY1+boxSize);
641
642 // Paint average
643 if (!TestBit(kLogScale) || (TestBit(kLogScale) && fMean > 0)) {
644 Double_t mean;
645 if (TestBit(kLogScale)) mean = TMath::Log10(fMean);
646 else mean = fMean;
647 TMarker *mark = NULL;
648 if(fX1==fX2) mark = new TMarker(fX1,fY1 + ((mean-a)/b)*(fY2-fY1),24);
649 else mark = new TMarker(fX1 + ((mean-a)/b)*(fX2-fX1),fY1,24);
650 mark->Paint();
651 delete mark;
652 }
653
654 delete line;
655 delete box;
656}
657
658////////////////////////////////////////////////////////////////////////////////
659/// Paint the histogram on the axis.
660
662{
663 Int_t i;
664
665 TFrame *frame = gPad->GetFrame();
666
667 if (!fHistogram) GetHistogram();
668
669 // Paint the axis body.
671 // Paint the axis body using bar chart.
672 TBox *b = new TBox();
673 b->SetFillStyle(GetFillStyle());
674 b->SetFillColor(GetFillColor());
675 b->SetLineStyle(1);
676 b->SetLineColor(GetFillColor());
677 b->SetLineWidth(1);
680 if (fX1 == fX2) {
681 // Vertical case.
682 Double_t dy = (fY2-fY1)/fNbins;
685 Double_t y1 = fY1,x2,y2;
686 for (i=1; i<=fNbins; i++) {
687 x2 = fX1+((fHistogram->GetBinContent(i)-hmin)/(hmax-hmin))*fHistoHeight*
688 ((frame->GetX2()-frame->GetX1())/(fParallel->GetNvar()-1));
690 else y2=y1+dy;
691 b->PaintBox(fX1,y1,x2,y2,"l");
692 y1=y2;
693 v += dv;
694 }
695 } else {
696 // Horizontal case.
697 Double_t dx = (fX2-fX1)/fNbins;
700 Double_t x1 = fX1,x2,y2;
701 for (i=1; i<=fNbins; i++) {
702 y2 = fY1+((fHistogram->GetBinContent(i)-hmin)/(hmax-hmin))*fHistoHeight*((frame->GetY2()-frame->GetY1())/(fParallel->GetNvar()-1));
704 else x2=x1+dx;
705 b->PaintBox(x1,fY1,x2,y2,"l");
706 x1=x2;
707 v+=dv;
708 }
709 }
710 delete b;
711 }
712 if (fHistoLW==0 && !TestBit(kShowBox)) {
713 // Paint the axis body as a simple line.
714 TLine* l = new TLine(fX1,fY1,fX2,fY2);
715 l->SetLineWidth(GetLineWidth());
716 l->SetLineColor(GetLineColor());
717 l->SetLineStyle(GetLineColor());
718 l->Paint();
719 delete l;
720 } else if (fHistoLW!=0){
721 // Paint the axis body using the color palette.
722 TLine *lb = new TLine();
726 Int_t theColor;
727 Int_t ncolors = gStyle->GetNumberOfColors();
728 if (fX1 == fX2) {
729 // Vertical case.
730 Double_t dy = (fY2-fY1)/fNbins;
731 Double_t y1 = fY1,y2;
734 for (i=1; i<=fNbins; i++) {
735 theColor = (Int_t)( ((fHistogram->GetBinContent(i)-hmin)/(hmax-hmin))*(ncolors-1) );
737 else y2=y1+dy;
738 lb->SetLineColor(gStyle->GetColorPalette(theColor));
739 lb->PaintLine(fX1,y1,fX1,y2);
740 y1=y2;
741 v+=dv;
742 }
743 } else {
744 // Horizontal case.
745 Double_t dx = (fX2-fX1)/fNbins;
748 Double_t x1 = fX1,x2;
749 for (i=1; i<=fNbins; i++) {
750 theColor = (Int_t)( ((fHistogram->GetBinContent(i)-hmin)/(hmax-hmin))*(ncolors-1) );
751 lb->SetLineColor(gStyle->GetColorPalette(theColor));
753 else x2=x1+dx;
754 lb->PaintLine(x1,fY1,x2,fY1);
755 x1=x2;
756 v+=dv;
757 }
758 }
759 delete lb;
760 }
761}
762
763////////////////////////////////////////////////////////////////////////////////
764/// Paint the axis labels and titles.
765
767{
768 TLatex* t = new TLatex();
769 TFrame *frame = gPad->GetFrame();
770 t->SetTextSize(0.03);
771 if (fX1==fX2) {
772 t->SetText(fX1,frame->GetY1() - 0.04 - t->GetTextSize(),GetName());
773 Double_t tlength = t->GetXsize();
774 if (fX1-0.5*tlength<0.01) {
775 t->SetTextAlign(11);
776 t->SetText(0.01, frame->GetY1() - 0.04 - t->GetTextSize(), GetName());
777 t->Paint();
778 } else if (fX1+0.5*tlength > 0.99) {
779 t->SetTextAlign(31);
780 t->SetText(0.99,frame->GetY1() - 0.04 - t->GetTextSize(),GetName());
781 t->Paint();
782 } else {
783 t->SetTextAlign(21);
784 t->PaintLatex(fX1,frame->GetY1() - 0.04 - t->GetTextSize(),0,0.03,GetName());
785 }
787 t->SetTextAlign(21);
788 t->PaintLatex(fX1,frame->GetY2() + 0.005,0,0.025,Form("%g",fMaxCurrent));
789 t->SetTextAlign(23);
790 t->PaintLatex(fX1,frame->GetY1() - 0.005,0,0.025,Form("%g",fMinCurrent));
791 }
792 } else {
793 t->SetText(fX1-0.04,fY1+0.02,GetName());
794 t->SetTextSize(0.03);
795 Double_t tlength = t->GetXsize();
796 if (fX1-0.04-tlength<0.01) {
797 t->SetTextAlign(12);
798 t->SetText(0.01,fY1+0.02,GetName());
799 t->Paint();
800 } else {
801 t->SetTextAlign(32);
802 t->PaintLatex(fX1-0.04,fY1+0.02,0,0.03,GetName());
803 }
805 t->SetTextAlign(12);
806 t->PaintLatex(0.01,fY1-0.02,0,0.025,Form("%g",fMinCurrent));
807 t->SetTextAlign(32);
808 t->PaintLatex(0.99,fY1-0.02,0,0.025,Form("%g",fMaxCurrent));
809 }
810 }
811 delete t;
812}
813
814////////////////////////////////////////////////////////////////////////////////
815/// Print the axis main data.
816
817void TParallelCoordVar::Print(Option_t* /*option*/) const
818{
819 printf("**************variable #%d**************\n",fParallel->GetVarList()->IndexOf(this));
820 printf("at x1=%f, y1=%f, x2=%f, y2=%f.\n",fX1,fY1,fX2,fY2);
821 printf("min = %f, Q1 = %f, Med = %f, Q3 = %f, Max = %f\n", fMinInit, fQua1, fMed, fQua3, fMaxInit);
822}
823
824////////////////////////////////////////////////////////////////////////////////
825/// Save the TParallelCoordVar as a macro. Can be used only in the context
826/// of TParallelCoord::SavePrimitive (pointer "TParallelCoord* para" is
827/// defined in TParallelCoord::SavePrimitive) with the option "pcalled".
828
829void TParallelCoordVar::SavePrimitive(std::ostream & out, Option_t* options)
830{
831 TString opt = options;
832 if (opt.Contains("pcalled")) {
833 out<<" var->SetBit(TParallelCoordVar::kLogScale,"<<TestBit(kLogScale)<<");"<<std::endl;
834 out<<" var->SetBit(TParallelCoordVar::kShowBox,"<<TestBit(kShowBox)<<");"<<std::endl;
835 out<<" var->SetBit(TParallelCoordVar::kShowBarHisto,"<<TestBit(kShowBarHisto)<<");"<<std::endl;
836 out<<" var->SetHistogramBinning("<<fNbins<<");"<<std::endl;
837 out<<" var->SetHistogramLineWidth("<<fHistoLW<<");"<<std::endl;
838 out<<" var->SetInitMin("<<fMinInit<<");"<<std::endl;
839 out<<" var->SetInitMax("<<fMaxInit<<");"<<std::endl;
840 out<<" var->SetHistogramHeight("<<fHistoHeight<<");"<<std::endl;
841 out<<" var->GetMinMaxMean();"<<std::endl;
842 out<<" var->GetHistogram();"<<std::endl;
843 out<<" var->SetFillStyle("<<GetFillStyle()<<");"<<std::endl;
844 out<<" var->SetFillColor("<<GetFillColor()<<");"<<std::endl;
845 out<<" var->SetLineColor("<<GetLineColor()<<");"<<std::endl;
846 out<<" var->SetLineWidth("<<GetLineWidth()<<");"<<std::endl;
847 out<<" var->SetLineStyle("<<GetLineStyle()<<");"<<std::endl;
848 if (TestBit(kShowBox)) out<<" var->GetQuantiles();"<<std::endl;
849 TIter next(fRanges);
850 TParallelCoordRange* range;
851 Int_t i = 1;
852 while ((range = (TParallelCoordRange*)next())) {
853 out<<" //***************************************"<<std::endl;
854 out<<" // Create the "<<i<<"th range owned by the axis \""<<GetTitle()<<"\"."<<std::endl;
855 out<<" TParallelCoordSelect* sel = para->GetSelection(\""<<range->GetSelection()->GetTitle()<<"\");"<<std::endl;
856 out<<" TParallelCoordRange* newrange = new TParallelCoordRange(var,"<<range->GetMin()<<","<<range->GetMax()<<",sel);"<<std::endl;
857 out<<" var->AddRange(newrange);"<<std::endl;
858 out<<" sel->Add(newrange);"<<std::endl;
859 ++i;
860 }
861 }
862}
863
864////////////////////////////////////////////////////////////////////////////////
865/// Set the axis to display a candle.
866
868{
870 if (box) SetHistogramHeight(0.5);
871 else {
874 }
875}
876
877////////////////////////////////////////////////////////////////////////////////
878/// Set the histogram binning.
879
881{
882 if (n < 0 || n == fNbins) return;
883 fNbins = n;
884 GetHistogram();
885}
886
887////////////////////////////////////////////////////////////////////////////////
888/// Set the height of the bar histogram.
889
891{
892 fHistoHeight = h;
894 if(h!=0) SetBit(kShowBarHisto,kTRUE);
896 }
897}
898
899////////////////////////////////////////////////////////////////////////////////
900/// Set the current minimum of the axis.
901
903{
904 fMinCurrent = min;
905}
906
907////////////////////////////////////////////////////////////////////////////////
908/// Set the current maximum of the axis.
909
911{
912 fMaxCurrent = max;
913}
914
915////////////////////////////////////////////////////////////////////////////////
916/// Set the limits within which one the entries must be painted.
917
919{
920 if (min>max) {
921 Double_t mem = min;
922 min = max;
923 max = mem;
924 }
925 if(TestBit(kLogScale) && max<=0) return;
926 if(TestBit(kLogScale) && min<=0) min = 0.00001*max;
927 fMinCurrent = min;
928 fMaxCurrent = max;
929
930 delete fHistogram;
931 fHistogram = NULL;
932 GetHistogram();
933
937 }
938}
939
940////////////////////////////////////////////////////////////////////////////////
941/// If true, the pad is updated while the motion of a dragged range.
942
944{
945 TIter next(fRanges);
946 TParallelCoordRange* range;
947 while ((range = (TParallelCoordRange*)next())) range->SetBit(TParallelCoordRange::kLiveUpdate,on);
948}
949
950////////////////////////////////////////////////////////////////////////////////
951/// Set the axis in log scale.
952
954{
955 if (log == TestBit (kLogScale)) return;
957 else if (log) {
958 if (fMaxCurrent < 0 ) fMaxCurrent = fMaxInit;
959 if (fMinCurrent < 0 ) fMinCurrent = 0.00001*fMaxCurrent;
963 } else {
967 }
968 GetQuantiles();
969 GetHistogram();
970}
971
972////////////////////////////////////////////////////////////////////////////////
973/// Set the variable values.
974
976{
977 if (fVal) delete [] fVal;
978 fVal = new Double_t[length];
979 fNentries = length;
980 for (Long64_t li = 0; li < length; ++li) fVal[li] = val[li];
982 GetHistogram();
984}
985
986////////////////////////////////////////////////////////////////////////////////
987/// Set the X position of the axis in the case of a vertical axis.
988/// and rotate the axis if it was horizontal.
989
991{
992 TFrame *frame = gPad->GetFrame();
993 if (!gl) {
994 fY1 = frame->GetY1();
995 fY2 = frame->GetY2();
996 } else {
999 fY1 = frame->GetY1() + ((fMinCurrent-gmin)/(gmax-gmin))*(frame->GetY2()-frame->GetY1());
1000 fY2 = frame->GetY1() + ((fMaxCurrent-gmin)/(gmax-gmin))*(frame->GetY2()-frame->GetY1());
1001 }
1002 fX1 = fX2 = x;
1003}
1004
1005////////////////////////////////////////////////////////////////////////////////
1006/// Set the Y position of the axis in the case of a horizontal axis.
1007/// and rotate the axis if it was vertical.
1008
1010{
1011 TFrame *frame = gPad->GetFrame();
1012 if (!gl) {
1013 fX1 = frame->GetX1();
1014 fX2 = frame->GetX2();
1015 } else {
1018 fX1 = frame->GetX1() + ((fMinCurrent-gmin)/(gmax-gmin))*(frame->GetX2()-frame->GetX1());
1019 fX2 = frame->GetX1() + ((fMaxCurrent-gmin)/(gmax-gmin))*(frame->GetX2()-frame->GetX1());
1020 }
1021 fY1 = fY2 = y;
1022}
@ 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
SVector< double, 2 > v
Definition: Dict.h:5
#define b(i)
Definition: RSha256.hxx:100
#define h(i)
Definition: RSha256.hxx:106
static const double x2[5]
static const double x1[5]
int Int_t
Definition: RtypesCore.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
long long Long64_t
Definition: RtypesCore.h:69
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:363
@ kOrange
Definition: Rtypes.h:64
int nentries
Definition: THbookFile.cxx:89
double log(double)
char * Form(const char *fmt,...)
R__EXTERN TStyle * gStyle
Definition: TStyle.h:406
#define gPad
Definition: TVirtualPad.h:286
#define gVirtualX
Definition: TVirtualX.h:345
@ kArrowVer
Definition: TVirtualX.h:46
@ kArrowHor
Definition: TVirtualX.h:46
#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:41
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition: TAttText.h:46
Create a Box.
Definition: TBox.h:24
Double_t GetX1() const
Definition: TBox.h:52
Double_t GetX2() const
Definition: TBox.h:53
Double_t GetY1() const
Definition: TBox.h:54
Double_t GetY2() const
Definition: TBox.h:55
The Canvas class.
Definition: TCanvas.h:31
Bool_t Contains(const char *name) const
Definition: TCollection.h:169
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
Define a Frame.
Definition: TFrame.h:19
1-D histogram with a float per channel (see TH1 documentation)}
Definition: TH1.h:571
virtual void SetDirectory(TDirectory *dir)
By default when an histogram is created, it is added to the list of histogram objects in the current ...
Definition: TH1.cxx:8259
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:7872
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition: TH1.cxx:3251
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4790
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:7957
To draw Mathematical Formula.
Definition: TLatex.h:18
Double_t GetXsize()
Return size of the formula along X in pad coordinates.
Definition: TLatex.cxx:2510
virtual void PaintLatex(Double_t x, Double_t y, Double_t angle, Double_t size, const char *text)
Main drawing function.
Definition: TLatex.cxx:2038
virtual void Paint(Option_t *option="")
Paint.
Definition: TLatex.cxx:2017
A simple line.
Definition: TLine.h:23
virtual void PaintLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Draw this line with new coordinates.
Definition: TLine.cxx:380
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:818
virtual void AddAt(TObject *obj, Int_t idx)
Insert object at position idx in the list.
Definition: TList.cxx:303
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
Manages Markers.
Definition: TMarker.h:23
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
virtual void AppendPad(Option_t *option="")
Append graphics object to current pad.
Definition: TObject.cxx:105
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
A TParallelCoordRange is a range used for parallel coordinates plots.
Bool_t IsIn(Double_t evtval)
Evaluate if the given value is within the range or not.
virtual void Paint(Option_t *options)
Paint a TParallelCoordRange.
virtual Double_t GetMin()
TParallelCoordSelect * GetSelection()
virtual Double_t GetMax()
A TParallelCoordSelect is a specialised TList to hold TParallelCoordRanges used by TParallelCoord.
const char * GetTitle() const
Returns title of object.
TParallelCoord axes.
TH1F * GetHistogram()
Create or recreate the histogram.
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 SetLogScale(Bool_t log)
Set the axis in log scale.
void PaintBoxPlot()
Paint the boxes in the case of a candle chart.
void PaintLabels()
Paint the axis labels and titles.
void PaintHistogram()
Paint the histogram on the axis.
void SetCurrentMin(Double_t min)
Set the current minimum of the axis.
void SavePrimitive(std::ostream &out, Option_t *options)
Save the TParallelCoordVar as a macro.
virtual void Print(Option_t *option="") const
Print the axis main data.
void SetLiveRangesUpdate(Bool_t on)
If true, the pad is updated while the motion of a dragged range.
void SetX(Double_t x, Bool_t gl)
Set the X position of the axis in the case of a vertical axis.
void SetY(Double_t y, Bool_t gl)
Set the Y position of the axis in the case of a horizontal axis.
void SetBoxPlot(Bool_t box)
Set the axis to display a candle.
void SetCurrentMax(Double_t max)
Set the current maximum of the axis.
TList * fRanges
[fNentries] Entries values for the variable.
void GetQuantiles()
Get the box plot values (quantiles).
void SetHistogramHeight(Double_t h=0)
Set the height of the bar histogram.
void DeleteVariable()
Delete variables.
TParallelCoordVar()
Histogram holding the variable distribution.
virtual void Draw(Option_t *option="")
Draw the axis.
TParallelCoord * fParallel
Bool_t Eval(Long64_t evtidx, TParallelCoordSelect *select)
Check if the entry is within the range(s) of "select".
virtual void Paint(Option_t *option="")
Paint the axis.
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...
~TParallelCoordVar()
Destructor.
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Computes the distance from the axis.
void SetHistogramLineWidth(Int_t lw=2)
virtual char * GetObjectInfo(Int_t px, Int_t py) const
Returns info about this axis.
void Init()
Initialise the TParallelVar variables.
virtual void ExecuteEvent(Int_t entry, Int_t px, Int_t py)
Execute the corresponding entry.
void GetXYfromValue(Double_t value, Double_t &x, Double_t &y)
Get a position corresponding to the value on the axis.
void GetMinMaxMean()
Get mean, min and max of those variable.
void SetValues(Long64_t length, Double_t *val)
Set the variable values.
void SetHistogramBinning(Int_t n=100)
Set the histogram binning.
void SetCurrentLimits(Double_t min, Double_t max)
Set the limits within which one the entries must be painted.
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.
UInt_t GetNvar()
void CleanUpSelections(TParallelCoordRange *range)
Clean up the selections from the ranges which could have been deleted when a variable has been delete...
virtual Int_t IndexOf(const TObject *obj) const
Return index of object in collection.
Basic string class.
Definition: TString.h:131
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition: TStyle.cxx:913
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition: TStyle.cxx:979
virtual void SetText(Double_t x, Double_t y, const char *text)
Definition: TText.h:72
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
double dist(Rotation3D const &r1, Rotation3D const &r2)
Definition: 3DDistances.cxx:48
void Quantiles(Int_t n, Int_t nprob, Double_t *x, Double_t *quantiles, Double_t *prob, Bool_t isSorted=kTRUE, Int_t *index=0, Int_t type=7)
Computes sample quantiles, corresponding to the given probabilities.
Definition: TMath.cxx:1190
Double_t Log10(Double_t x)
Definition: TMath.h:752
Short_t Abs(Short_t d)
Definition: TMathBase.h:120
Definition: first.py:1
auto * l
Definition: textangle.C:4
auto * a
Definition: textangle.C:12
#define mark(osub)
Definition: triangle.c:1206