Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TCandle.cxx
Go to the documentation of this file.
1// @(#)root/graf:$Id$
2// Author: Georg Troska 19/05/16
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, 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 <cstdlib>
13
14#include "TBuffer.h"
15#include "TCandle.h"
16#include "TVirtualPad.h"
17#include "TH2D.h"
18#include "TRandom2.h"
19#include "TStyle.h"
20#include "strlcpy.h"
21
23
24/** \class TCandle
25\ingroup BasicGraphics
26
27The candle plot painter class.
28
29Instances of this class are generated by the histograms painting
30classes (THistPainter and THStack) when an candle plot (box plot) is drawn.
31TCandle is the "painter class" of the box plots. Therefore it is never used
32directly to draw a candle.
33*/
34
35////////////////////////////////////////////////////////////////////////////////
36/// TCandle default constructor.
37
39{
40 fIsCalculated = false;
41 fIsRaw = false;
42 fPosCandleAxis = 0.;
43 fCandleWidth = 1.0;
44 fHistoWidth = 1.0;
45 fMean = 0.;
46 fMedian = 0.;
47 fMedianErr = 0;
48 fBoxUp = 0.;
49 fBoxDown = 0.;
50 fWhiskerUp = 0.;
51 fWhiskerDown = 0.;
52 fNDatapoints = 0;
53 fDismiss = false;
54 fLogX = 0;
55 fLogY = 0;
56 fLogZ = 0;
57 fNDrawPoints = 0;
58 fNHistoPoints = 0;
59 fAxisMin = 0.;
60 fAxisMax = 0.;
62 fProj = nullptr;
63 fDatapoints = nullptr;
64
65}
66
67////////////////////////////////////////////////////////////////////////////////
68/// TCandle constructor passing a draw-option.
69
70TCandle::TCandle(const char *opt)
71{
72 fIsCalculated = false;
73 fIsRaw = false;
74 fPosCandleAxis = 0.;
75 fCandleWidth = 1.0;
76 fHistoWidth = 1.0;
77 fMean = 0.;
78 fMedian = 0.;
79 fMedianErr = 0;
80 fBoxUp = 0.;
81 fBoxDown = 0.;
82 fWhiskerUp = 0.;
83 fWhiskerDown = 0.;
84 fNDatapoints = 0;
85 fDismiss = false;
86 fLogX = 0;
87 fLogY = 0;
88 fLogZ = 0;
89 fNDrawPoints = 0;
90 fNHistoPoints = 0;
91 fAxisMin = 0.;
92 fAxisMax = 0.;
94 fProj = nullptr;
95 fDatapoints = nullptr;
96
97 // Conversion necessary in order to cast from const char* to char*
98 char myopt[128];
99 strlcpy(myopt,opt,128);
100
101
102 ParseOption(myopt);
103}
104
105
106////////////////////////////////////////////////////////////////////////////////
107/// TCandle constructor for raw-data candles.
108
109TCandle::TCandle(const Double_t candlePos, const Double_t candleWidth, Long64_t n, Double_t * points)
111{
112 //Preliminary values only, need to be calculated before paint
113 fMean = 0;
114 fMedian = 0;
115 fMedianErr = 0;
116 fBoxUp = 0;
117 fBoxDown = 0;
118 fWhiskerUp = 0;
119 fWhiskerDown = 0;
120 fNDatapoints = n;
121 fIsCalculated = false;
122 fIsRaw = true;
123 fPosCandleAxis = candlePos;
124 fCandleWidth = candleWidth;
125 fHistoWidth = candleWidth;
127 fProj = nullptr;
128 fDismiss = false;
130 fLogX = 0;
131 fLogY = 0;
132 fLogZ = 0;
133 fNDrawPoints = 0;
134 fNHistoPoints = 0;
135 fAxisMin = 0.;
136 fAxisMax = 0.;
137}
138
139////////////////////////////////////////////////////////////////////////////////
140/// TCandle TH1 data constructor.
141
142TCandle::TCandle(const Double_t candlePos, const Double_t candleWidth, TH1D *proj)
144{
145 //Preliminary values only, need to be calculated before paint
146 fMean = 0;
147 fMedian = 0;
148 fMedianErr = 0;
149 fBoxUp = 0;
150 fBoxDown = 0;
151 fWhiskerUp = 0;
152 fWhiskerDown = 0;
153 fNDatapoints = 0;
154 fIsCalculated = false;
155 fIsRaw = false;
156 fPosCandleAxis = candlePos;
157 fCandleWidth = candleWidth;
158 fHistoWidth = candleWidth;
159 fDatapoints = nullptr;
160 fProj = proj;
161 fDismiss = false;
163 fLogX = 0;
164 fLogY = 0;
165 fLogZ = 0;
166 fNDrawPoints = 0;
167 fNHistoPoints = 0;
168 fAxisMin = 0.;
169 fAxisMax = 0.;
170}
171
172////////////////////////////////////////////////////////////////////////////////
173/// TCandle default destructor.
174
176{
177 if (fIsRaw && fProj) delete fProj;
178}
179
180////////////////////////////////////////////////////////////////////////////////
181/// Returns true if candle plot should be scaled
182
184{
185 return gStyle->GetCandleScaled();
186}
187
188////////////////////////////////////////////////////////////////////////////////
189/// Returns true if violin plot should be scaled
190
192{
193 return gStyle->GetViolinScaled();
194}
195
196////////////////////////////////////////////////////////////////////////////////
197/// Static function to set WhiskerRange, by setting whisker-range, one can force
198/// the whiskers to cover the fraction of the distribution.
199/// Set wRange between 0 and 1. Default is 1
200/// TCandle::SetWhiskerRange(0.95) will set all candle-charts to cover 95% of
201/// the distribution with the whiskers.
202/// Can only be used with the standard-whisker definition
203
205{
207}
208
209////////////////////////////////////////////////////////////////////////////////
210/// Static function to set BoxRange, by setting box-range, one can force the
211/// box of the candle-chart to cover that given fraction of the distribution.
212/// Set bRange between 0 and 1. Default is 0.5
213/// TCandle::SetBoxRange(0.68) will set all candle-charts to cover 68% of the
214/// distribution by the box
215
217{
218 gStyle->SetCandleBoxRange(bRange);
219}
220
221////////////////////////////////////////////////////////////////////////////////
222/// Static function to set scaling between candles-withs. A candle containing
223/// 100 entries will be two times wider than a candle containing 50 entries
224
226{
227 gStyle->SetCandleScaled(cScale);
228}
229
230////////////////////////////////////////////////////////////////////////////////
231/// Static function to set scaling between violin-withs. A violin or histo chart
232/// with a maximum bin content to 100 will be two times as high as a violin with
233/// a maximum bin content of 50
234
236{
237 gStyle->SetViolinScaled(vScale);
238}
239
240////////////////////////////////////////////////////////////////////////////////
241/// Parsing of the option-string.
242/// The option-string will be empty at the end (by-reference).
243
244int TCandle::ParseOption(char * opt) {
246 char *l = strstr(opt,"CANDLE");
247
248 if (l) {
249 const CandleOption fallbackCandle = (CandleOption)(kBox + kMedianLine + kMeanCircle + kWhiskerAll + kAnchor);
250
251 char direction = ' ';
252 char preset = ' ';
253
254 if (l[6] >= 'A' && l[6] <= 'Z') direction = l[6];
255 if (l[6] >= '1' && l[6] <= '9') preset = l[6];
256 if (l[7] >= 'A' && l[7] <= 'Z' && preset != ' ') direction = l[7];
257 if (l[7] >= '1' && l[7] <= '9' && direction != ' ') preset = l[7];
258
259 if (direction == 'X' || direction == 'V') { /* nothing */ }
260 if (direction == 'Y' || direction == 'H') { fOption = (CandleOption)(fOption + kHorizontal); }
261 if (preset == '1') //Standard candle using old candle-definition
262 fOption = (CandleOption)(fOption + fallbackCandle);
263 else if (preset == '2') //New standard candle with better whisker definition + outlier
265 else if (preset == '3') //Like candle2 but with a fMean as a circle
267 else if (preset == '4') //Like candle3 but showing the uncertainty of the fMedian as well
269 else if (preset == '5') //Like candle2 but showing all datapoints
271 else if (preset == '6') //Like candle2 but showing all datapoints scattered
273 else if (preset != ' ') //For all other presets not implemented yet used fallback candle
274 fOption = (CandleOption)(fOption + fallbackCandle);
275
276 if (preset != ' ' && direction != ' ')
277 memcpy(l," ",8);
278 else if (preset != ' ' || direction != ' ')
279 memcpy(l," ",7);
280 else
281 memcpy(l," ",6);
282
283 Bool_t useIndivOption = false;
284
285 if (direction == ' ') direction = 'X';
286 if (preset == ' ') { // Check if the user wants to set the properties individually
287 char *brOpen = strstr(opt,"(");
288 char *brClose = strstr(opt,")");
289 char indivOption[32];
290 if (brOpen && brClose) {
291 useIndivOption = true;
292 bool wasHorizontal = IsHorizontal();
293 strlcpy(indivOption, brOpen, brClose-brOpen+2); //Now the string "(....)" including brackets is in this array
294 sscanf(indivOption,"(%d)", (int*) &fOption);
295 if (wasHorizontal && !IsHorizontal()) {fOption = (CandleOption)(fOption + kHorizontal);}
296 memcpy(brOpen," ",brClose-brOpen+1); //Cleanup
297
298 fOptionStr.Form("CANDLE%c(%ld)", direction, (long)fOption);
299 } else {
300 fOption = (CandleOption)(fOption + fallbackCandle);
301 }
302 } else {
303 fOptionStr.Form("CANDLE%c%c",direction,preset);
304 }
305 //Handle option "CANDLE" ,"CANDLEX" or "CANDLEY" to behave like "CANDLEX1" or "CANDLEY1"
306 if (!useIndivOption && !fOption ) {
307 fOption = fallbackCandle;
308 fOptionStr.Form("CANDLE%c2",direction);
309 }
310 }
311
312 l = strstr(opt,"VIOLIN");
313 if (l) {
315
316 char direction = ' ';
317 char preset = ' ';
318
319 if (l[6] >= 'A' && l[6] <= 'Z') direction = l[6];
320 if (l[6] >= '1' && l[6] <= '9') preset = l[6];
321 if (l[7] >= 'A' && l[7] <= 'Z' && preset != ' ') direction = l[7];
322 if (l[7] >= '1' && l[7] <= '9' && direction != ' ') preset = l[7];
323
324 if (direction == 'X' || direction == 'V') { /* nothing */ }
325 if (direction == 'Y' || direction == 'H') { fOption = (CandleOption)(fOption + kHorizontal); }
326 if (preset == '1') //Standard candle using old candle-definition
327 fOption = (CandleOption)(fOption + fallbackCandle);
328 else if (preset == '2') //New standard candle with better whisker definition + outlier
330 else if (preset != ' ') //For all other presets not implemented yet used fallback candle
331 fOption = (CandleOption)(fOption + fallbackCandle);
332
333 if (preset != ' ' && direction != ' ')
334 memcpy(l," ",8);
335 else if (preset != ' ' || direction != ' ')
336 memcpy(l," ",7);
337 else
338 memcpy(l," ",6);
339
340 Bool_t useIndivOption = false;
341
342 if (direction == ' ') direction = 'X';
343 if (preset == ' ') { // Check if the user wants to set the properties individually
344 char *brOpen = strstr(opt,"(");
345 char *brClose = strstr(opt,")");
346 char indivOption[32];
347 if (brOpen && brClose) {
348 useIndivOption = true;
349 bool wasHorizontal = IsHorizontal();
350 strlcpy(indivOption, brOpen, brClose-brOpen +2); //Now the string "(....)" including brackets is in this array
351 sscanf(indivOption,"(%d)", (int*) &fOption);
352 if (wasHorizontal && !IsHorizontal()) {fOption = (CandleOption)(fOption + kHorizontal);}
353 memcpy(brOpen," ",brClose-brOpen+1); //Cleanup
354
355 fOptionStr.Form("VIOLIN%c(%ld)", direction, (long)fOption);
356 } else {
357 fOption = (CandleOption)(fOption + fallbackCandle);
358 }
359 } else {
360 fOptionStr.Form("VIOLIN%c%c", direction, preset);
361 }
362 //Handle option "VIOLIN" ,"VIOLINX" or "VIOLINY" to behave like "VIOLINX1" or "VIOLINY1"
363 if (!useIndivOption && !fOption ) {
364 fOption = fallbackCandle;
365 fOptionStr.Form("VIOLIN%c1", direction);
366 }
367 }
368
369 fIsCalculated = false;
370
371 return fOption;
372
373}
374
375////////////////////////////////////////////////////////////////////////////////
376/// Calculates all values needed by the candle definition depending on the
377/// candle options.
378
380 //Reset everything
381 fNDrawPoints = 0;
382 fNHistoPoints = 0;
383
384 Bool_t swapXY = IsOption(kHorizontal);
385 Bool_t doLogY = (!(swapXY) && fLogY) || (swapXY && fLogX);
386 Bool_t doLogX = (!(swapXY) && fLogX) || (swapXY && fLogY);
387 Bool_t doLogZ = fLogZ;
388
389 //Will be min and max values of raw-data
390 Double_t min = 1e15;
391 Double_t max = -1e15;
392
393 // Determining the quantiles
394 Double_t prob[5];
395
398
399
400 if (wRange >= 1) {
401 prob[0] = 1e-15;
402 prob[4] = 1-1e-15;
403 } else {
404 prob[0] = 0.5 - wRange/2.;
405 prob[4] = 0.5 + wRange/2.;
406 }
407
408 if (bRange >= 1) {
409 prob[1] = 1E-14;
410 prob[3] = 1-1E-14;
411 } else {
412 prob[1] = 0.5 - bRange/2.;
413 prob[3] = 0.5 + bRange/2.;
414 }
415
416 prob[2] = 0.5;
417
418 Double_t quantiles[5] = { 0., 0., 0., 0., 0. };
419 if (!fIsRaw && fProj) { //Need a calculation for a projected histo
420 if (((IsOption(kHistoLeft)) || (IsOption(kHistoRight)) || (IsOption(kHistoViolin))) && fProj->GetNbinsX() > 500) {
421 // When using the histooption the number of bins of the projection is
422 // limited because of the array space defined by kNMAXPOINTS.
423 // So the histo is rebinned, that it can be displayed at any time.
424 // Finer granularity is not useful anyhow
425 int divideBy = ((fProj->GetNbinsX() - 1)/((kNMAXPOINTS-10)/4))+1;
426 fProj->RebinX(divideBy);
427 }
428 fProj->GetQuantiles(5, quantiles, prob);
429 } else { //Need a calculation for a raw-data candle
431 }
432
433 // Check if the quantiles are valid, seems the under- and overflow is taken
434 // into account as well, we need to ignore this!
435 if (quantiles[0] >= quantiles[4] ||
436 quantiles[1] >= quantiles[3]) {
437 return;
438 }
439
440 // Definition of the candle in the standard case
441 fBoxUp = quantiles[3];
442 fBoxDown = quantiles[1];
443 fWhiskerUp = quantiles[4]; //Standard case
444 fWhiskerDown = quantiles[0]; //Standard case
445 fMedian = quantiles[2];
447 Int_t nOutliers = 0;
448
449 if (IsOption(kWhisker15)) { // Improved whisker definition, with 1.5*iqr
450 if (!fIsRaw && fProj) { //Need a calculation for a projected histo
451 int bin = fProj->FindBin(fBoxDown-1.5*iqr);
452 // extending only to the lowest data value within this range
453 while (fProj->GetBinContent(bin) == 0 && bin <= fProj->GetNbinsX()) bin++;
455
456 bin = fProj->FindBin(fBoxUp+1.5*iqr);
457 while (fProj->GetBinContent(bin) == 0 && bin >= 1) bin--;
459 } else { //Need a calculation for a raw-data candle
462
463 //Need to find highest value up to 1.5*iqr from the BoxUp-pos, and the lowest value up to -1.5*iqr from the boxLow-pos
464 for (Long64_t i = 0; i < fNDatapoints; ++i) {
465 Double_t myData = fDatapoints[i];
466 if (myData > fWhiskerUp && myData <= fBoxUp + 1.5*iqr) fWhiskerUp = myData;
467 if (myData < fWhiskerDown && myData >= fBoxDown - 1.5*iqr) fWhiskerDown = myData;
468 }
469 }
470 }
471
472 if (!fIsRaw && fProj) { //Need a calculation for a projected histo
473 fMean = fProj->GetMean();
474 fMedianErr = 1.57*iqr/sqrt(fProj->GetEntries());
477 } else { //Need a calculation for a raw-data candle
478 //Calculate the Mean
479 fMean = 0;
480 for (Long64_t i = 0; i < fNDatapoints; ++i) {
481 fMean += fDatapoints[i];
482 if (fDatapoints[i] < min) min = fDatapoints[i];
483 if (fDatapoints[i] > max) max = fDatapoints[i];
484 if (fDatapoints[i] < fWhiskerDown || fDatapoints[i] > fWhiskerUp) nOutliers++;
485 }
487 fMedianErr = 1.57*iqr/sqrt(fNDatapoints);
488 }
489
490 //Doing the outliers and other single points to show
491 if (GetCandleOption(5) > 0) { //Draw outliers
492 TRandom2 random;
493 const int maxOutliers = kNMAXPOINTS;
494 Double_t myScale = 1.;
495 if (!fIsRaw && fProj) { //Need a calculation for a projected histo
496 if (fProj->GetEntries() > maxOutliers/2) myScale = fProj->GetEntries()/(maxOutliers/2.);
497 fNDrawPoints = 0;
498 for (int bin = 0; bin < fProj->GetNbinsX(); bin++) {
499 // Either show them only outside the whiskers, or all of them
500 if (fProj->GetBinContent(bin) > 0 && (fProj->GetBinCenter(bin) < fWhiskerDown || fProj->GetBinCenter(bin) > fWhiskerUp || (GetCandleOption(5) > 1)) ) {
501 Double_t scaledBinContent = fProj->GetBinContent(bin)/myScale;
502 if (scaledBinContent >0 && scaledBinContent < 1) scaledBinContent = 1; //Outliers have a typical bin content between 0 and 1, when scaling they would disappear
503 for (int j=0; j < (int)scaledBinContent; j++) {
504 if (fNDrawPoints > maxOutliers) break;
505 if (IsOption(kPointsAllScat)) { //Draw outliers and "all" values scattered
508 } else { //Draw them in the "candle line"
510 if ((int)scaledBinContent == 1) //If there is only one datapoint available put it in the middle of the bin
512 else //If there is more than one datapoint scatter it along the bin, otherwise all marker would be (invisibly) stacked on top of each other
514 }
515 if (swapXY) {
516 //Swap X and Y
517 Double_t keepCurrently;
518 keepCurrently = fDrawPointsX[fNDrawPoints];
520 fDrawPointsY[fNDrawPoints] = keepCurrently;
521 }
522 // Continue fMeans, that fNDrawPoints is not increased, so that value will not be shown
523 if (doLogX) {
525 }
526 if (doLogY) {
528 }
529 fNDrawPoints++;
530 }
531 }
532 if (fNDrawPoints > maxOutliers) { //Should never happen, due to myScale!!!
533 Error ("PaintCandlePlot","Not possible to draw all outliers.");
534 break;
535 }
536 }
537 } else { //Raw data candle
538 //If only outliers are shown, calculate myScale only based on nOutliers, use fNDatapoints (all) instead
539 if (IsOption(kPointsOutliers) && nOutliers > maxOutliers/2) {
540 myScale = nOutliers/(maxOutliers/2.);
541 } else {
542 if (fNDatapoints > maxOutliers/2) myScale = fNDatapoints/(maxOutliers/2.);
543 }
544 fNDrawPoints = 0;
545 for (int i = 0; i < fNDatapoints; i++ ) {
546 Double_t myData = fDatapoints[i];
547 Double_t maxScatter = (fWhiskerUp-fWhiskerDown)/100;
548 if (!(i % (int) myScale == 0 )) continue; //If the amount of data is too large take only every 2nd or 3rd to reduce the amount
549 // Either show them only outside the whiskers, or all of them
550 if (myData < fWhiskerDown || myData > fWhiskerUp || (GetCandleOption(5) > 1)) {
551 if (IsOption(kPointsAllScat)) { //Draw outliers and "all" values scattered
553 fDrawPointsY[fNDrawPoints] = myData + (random.Rndm() - 0.5)*maxScatter; //random +- 0.5 of candle-height
554 } else { //Draw them in the "candle line"
556 fDrawPointsY[fNDrawPoints] = myData + (random.Rndm() - 0.5)*maxScatter; //random +- 0.5 of candle-height
557 }
558 if (swapXY) {
559 //Swap X and Y
560 Double_t keepCurrently;
561 keepCurrently = fDrawPointsX[fNDrawPoints];
563 fDrawPointsY[fNDrawPoints] = keepCurrently;
564 }
565 // Continue fMeans, that fNDrawPoints is not increased, so that value will not be shown
566 if (doLogX) {
568 else continue;
569 }
570 if (doLogY) {
572 else continue;
573 }
574 fNDrawPoints++;
575 if (fNDrawPoints > maxOutliers) { //Should never happen, due to myScale!!!
576 Error ("PaintCandlePlotRaw","Not possible to draw all outliers.");
577 break;
578 }
579 }
580 }
581 }
582 }
584 //We are starting with kHistoRight, left will be modified from right later
585 if (fIsRaw) { //This is a raw-data candle
586 if (!fProj) {
587 fProj = new TH1D("hpa","hpa",100,min,max+0.0001*(max-min));
588 fProj->SetDirectory(nullptr);
589 for (Long64_t i = 0; i < fNDatapoints; ++i) {
591 }
592 }
593 }
594
595 fNHistoPoints = 0;
596 Double_t maxContent = fProj->GetMaximum();
597 Double_t maxHistoHeight = fHistoWidth;
598 if (IsOption(kHistoViolin)) maxHistoHeight *= 0.5;
599
600 bool isFirst = true;
601 int lastNonZero = 0;
602 for (int bin = 1; bin <= fProj->GetNbinsX(); bin++) {
603 if (isFirst) {
604 if (fProj->GetBinContent(bin) > 0) {
607 if (doLogX) {
609 }
610 if (doLogY) {
612 }
614 isFirst = false;
615 } else {
616 continue;
617 }
618 }
619
620 Double_t myBinValue = fProj->GetBinContent(bin);
621 if (doLogZ) {
622 if (myBinValue > 0) myBinValue = TMath::Log10(myBinValue); else myBinValue = 0;
623 }
624 fHistoPointsX[fNHistoPoints] = fPosCandleAxis + myBinValue/maxContent*maxHistoHeight;
627 fHistoPointsX[fNHistoPoints] = fPosCandleAxis + myBinValue/maxContent*maxHistoHeight;
629 if (doLogX) {
632 }
633 if (doLogY) {
636 }
637
639 if (fProj->GetBinContent(bin) > 0) lastNonZero = fNHistoPoints;
640 }
641
644 fNHistoPoints = lastNonZero+1; //+1 so that the line down to 0 is added as well
645
646 if (IsOption(kHistoLeft)) {
647 for (int i = 0; i < fNHistoPoints; i++) {
649 }
650 }
651 if (IsOption(kHistoViolin)) {
652 for (int i = 0; i < fNHistoPoints; i++) {
655 }
656 fNHistoPoints *= 2;
657 }
658 }
659
660 fIsCalculated = true;
661}
662
663////////////////////////////////////////////////////////////////////////////////
664/// Paint one candle with its current attributes.
665
667{
668 if (!gPad) return;
669
670 //If something was changed before, we need to recalculate some values
671 if (!fIsCalculated) Calculate();
672
673 // Save the attributes as they were set originally
674 Style_t saveLine = GetLineStyle();
675 Style_t saveMarker = GetMarkerStyle();
676 Style_t saveFillStyle = GetFillStyle();
677 Style_t saveFillColor = GetFillColor();
678 Style_t saveLineColor = GetLineColor();
679
681 Double_t dimRight = fPosCandleAxis+0.5*fCandleWidth;
682
686
687 Bool_t swapXY = IsOption(kHorizontal);
688 Bool_t doLogY = (!(swapXY) && fLogY) || (swapXY && fLogX);
689 Bool_t doLogX = (!(swapXY) && fLogX) || (swapXY && fLogY);
690
691 // From now on this is real painting only, no calculations anymore
692
694 SetLineColor(saveFillColor);
697 SetLineColor(saveLineColor);
699 }
700
701
703 if (IsOption(kHistoZeroIndicator) && (saveFillStyle != 0)) {
704 SetLineColor(saveFillColor);
706 }
707 if (!swapXY) {
710 } else {
713 }
714 if (IsOption(kHistoZeroIndicator) && (saveFillStyle != 0)) {
715 SetLineColor(saveLineColor);
717 }
718 }
719
720 if (IsOption(kBox)) { // Draw a simple box
721 if (IsOption(kMedianNotched)) { // Check if we have to draw a box with notches
722 Double_t x[] = {dimLeft, dimLeft, dimLeft+fCandleWidth/3., dimLeft, dimLeft, dimRight,
723 dimRight, dimRight-fCandleWidth/3., dimRight, dimRight, dimLeft};
726 PaintBox(11, x, y, swapXY);
727 } else { // draw a simple box
728 Double_t x[] = {dimLeft, dimLeft, dimRight, dimRight, dimLeft};
730 PaintBox(5, x, y, swapXY);
731 }
732 }
733
734 if (IsOption(kAnchor)) { // Draw the anchor line
735 PaintLine(dimLeft, fWhiskerUp, dimRight, fWhiskerUp, swapXY);
736 PaintLine(dimLeft, fWhiskerDown, dimRight, fWhiskerDown, swapXY);
737 }
738
739 if (IsOption(kWhiskerAll) && !IsOption(kHistoZeroIndicator)) { // Whiskers are dashed
740 SetLineStyle(2);
744 SetLineStyle(saveLine);
746 } else if ((IsOption(kWhiskerAll) && IsOption(kHistoZeroIndicator)) || IsOption(kWhisker15) ) { // Whiskers without dashing, better whisker definition, or forced when using zero line
749 }
750
751 if (IsOption(kMedianLine)) { // Paint fMedian as a line
752 PaintLine(dimLeft, fMedian, dimRight, fMedian, swapXY);
753 } else if (IsOption(kMedianNotched)) { // Paint fMedian as a line (using notches, fMedian line is shorter)
754 PaintLine(dimLeft+fCandleWidth/3, fMedian, dimRight-fCandleWidth/3., fMedian, swapXY);
755 } else if (IsOption(kMedianCircle)) { // Paint fMedian circle
756 Double_t myMedianX[1], myMedianY[1];
757 if (!swapXY) {
758 myMedianX[0] = fPosCandleAxis;
759 myMedianY[0] = fMedian;
760 } else {
761 myMedianX[0] = fMedian;
762 myMedianY[0] = fPosCandleAxis;
763 }
764
765 Bool_t isValid = true;
766 if (doLogX) {
767 if (myMedianX[0] > 0) myMedianX[0] = TMath::Log10(myMedianX[0]); else isValid = false;
768 }
769 if (doLogY) {
770 if (myMedianY[0] > 0) myMedianY[0] = TMath::Log10(myMedianY[0]); else isValid = false;
771 }
772
773 SetMarkerStyle(24);
775
776 if (isValid) gPad->PaintPolyMarker(1,myMedianX,myMedianY); // A circle for the fMedian
777
778 SetMarkerStyle(saveMarker);
780
781 }
782
783 if (IsOption(kMeanCircle)) { // Paint fMean as a circle
784 Double_t myMeanX[1], myMeanY[1];
785 if (!swapXY) {
786 myMeanX[0] = fPosCandleAxis;
787 myMeanY[0] = fMean;
788 } else {
789 myMeanX[0] = fMean;
790 myMeanY[0] = fPosCandleAxis;
791 }
792
793 Bool_t isValid = true;
794 if (doLogX) {
795 if (myMeanX[0] > 0) myMeanX[0] = TMath::Log10(myMeanX[0]); else isValid = false;
796 }
797 if (doLogY) {
798 if (myMeanY[0] > 0) myMeanY[0] = TMath::Log10(myMeanY[0]); else isValid = false;
799 }
800
801 SetMarkerStyle(24);
803
804 if (isValid) gPad->PaintPolyMarker(1,myMeanX,myMeanY); // A circle for the fMean
805
806 SetMarkerStyle(saveMarker);
808
809 } else if (IsOption(kMeanLine)) { // Paint fMean as a dashed line
810 SetLineStyle(2);
812
813 PaintLine(dimLeft, fMean, dimRight, fMean, swapXY);
814 SetLineStyle(saveLine);
816
817 }
818
819 if (IsOption(kAnchor)) { //Draw standard anchor
820 PaintLine(dimLeft, fWhiskerDown, dimRight, fWhiskerDown, swapXY); // the lower anchor line
821 PaintLine(dimLeft, fWhiskerUp, dimRight, fWhiskerUp, swapXY); // the upper anchor line
822 }
823
824 // This is a bit complex. All values here are handled as outliers. Usually
825 // only the datapoints outside the whiskers are shown.
826 // One can show them in one row as crosses, or scattered randomly. If activated
827 // all datapoint are shown in the same way
828
829 if (GetCandleOption(5) > 0) { //Draw outliers
830 if (IsOption(kPointsAllScat)) { //Draw outliers and "all" values scattered
832 } else {
834 }
836 gPad->PaintPolyMarker(fNDrawPoints,fDrawPointsX, fDrawPointsY);
837 }
838}
839
840////////////////////////////////////////////////////////////////////////////////
841/// Return true is this option is activated in fOption
842
844 long myOpt = 9;
845 int pos = 0;
846 for (pos = 0; pos < 16; pos++) {
847 if (myOpt > opt) break;
848 else myOpt *=10;
849 }
850 myOpt /= 9;
851 int thisOpt = GetCandleOption(pos);
852
853 return (thisOpt * myOpt) == opt;
854}
855
856////////////////////////////////////////////////////////////////////////////////
857/// Paint a box for candle.
858
860{
861 if (!gPad) return;
862
863 Bool_t doLogY = (!(swapXY) && fLogY) || (swapXY && fLogX);
864 Bool_t doLogX = (!(swapXY) && fLogX) || (swapXY && fLogY);
865 if (doLogY) {
866 for (int i=0; i<nPoints; i++) {
867 if (y[i] > 0) y[i] = TMath::Log10(y[i]);
868 else return;
869 }
870 }
871 if (doLogX) {
872 for (int i=0; i<nPoints; i++) {
873 if (x[i] > 0) x[i] = TMath::Log10(x[i]);
874 else return;
875 }
876 }
877 if (!swapXY) {
878 gPad->PaintFillArea(nPoints, x, y);
879 gPad->PaintPolyLine(nPoints, x, y);
880 } else {
881 gPad->PaintFillArea(nPoints, y, x);
882 gPad->PaintPolyLine(nPoints, y, x);
883 }
884}
885
886////////////////////////////////////////////////////////////////////////////////
887/// Paint a line for candle.
888
890{
891 if (!gPad) return;
892
893 Bool_t doLogY = (!(swapXY) && fLogY) || (swapXY && fLogX);
894 Bool_t doLogX = (!(swapXY) && fLogX) || (swapXY && fLogY);
895 if (doLogY) {
896 if (y1 > 0) y1 = TMath::Log10(y1); else return;
897 if (y2 > 0) y2 = TMath::Log10(y2); else return;
898 }
899 if (doLogX) {
900 if (x1 > 0) x1 = TMath::Log10(x1); else return;
901 if (x2 > 0) x2 = TMath::Log10(x2); else return;
902 }
903 if (!swapXY) {
904 gPad->PaintLine(x1, y1, x2, y2);
905 } else {
906 gPad->PaintLine(y1, x1, y2, x2);
907 }
908}
909
910////////////////////////////////////////////////////////////////////////////////
911/// Stream an object of class TCandle.
912
914{
915 if (R__b.IsReading()) {
916 UInt_t R__s, R__c;
917 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
918 if (R__v > 3) {
919 R__b.ReadClassBuffer(TCandle::Class(), this, R__v, R__s, R__c);
920 return;
921 }
922 } else {
923 R__b.WriteClassBuffer(TCandle::Class(),this);
924 }
925}
926
927////////////////////////////////////////////////////////////////////////////////
928/// The coordinates in the TParallelCoordVar-class are in Pad-Coordinates, so we need to convert them
929
930void TCandle::ConvertToPadCoords(Double_t minAxis, Double_t maxAxis, Double_t axisMinCoord, Double_t axisMaxCoord)
931{
932 if (!fIsCalculated) Calculate();
933 Double_t a,b;
934 if (fLogY) {
935 a = TMath::Log10(minAxis);
936 b = TMath::Log10(maxAxis/minAxis);
937 } else {
938 a = minAxis;
939 b = maxAxis-minAxis;
940 }
941
942 fMean = axisMinCoord + ((fMean-a)/b)*(axisMaxCoord-axisMinCoord);
943 fMedian = axisMinCoord + ((fMedian-a)/b)*(axisMaxCoord-axisMinCoord);
944 fMedianErr = axisMinCoord + ((fMedianErr-a)/b)*(axisMaxCoord-axisMinCoord);
945 fBoxUp = axisMinCoord + ((fBoxUp-a)/b)*(axisMaxCoord-axisMinCoord);
946 fBoxDown = axisMinCoord + ((fBoxDown-a)/b)*(axisMaxCoord-axisMinCoord);
947 fWhiskerUp = axisMinCoord + ((fWhiskerUp-a)/b)*(axisMaxCoord-axisMinCoord);
948 fWhiskerDown = axisMinCoord + ((fWhiskerDown-a)/b)*(axisMaxCoord-axisMinCoord);
949
950 for (int i = 0; i < fNDrawPoints; i++) {
951 fDrawPointsY[i] = axisMinCoord + ((fDrawPointsY[i]-a)/b)*(axisMaxCoord-axisMinCoord);
952 }
953 for (int i = 0; i < fNHistoPoints; i++) {
954 fHistoPointsY[i] = axisMinCoord + ((fHistoPointsY[i]-a)/b)*(axisMaxCoord-axisMinCoord);
955 }
956}
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
#define e(i)
Definition RSha256.hxx:103
short Style_t
Definition RtypesCore.h:89
short Version_t
Definition RtypesCore.h:65
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
long long Long64_t
Definition RtypesCore.h:80
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
const Int_t kNMAXPOINTS
Definition TCandle.h:25
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
Option_t Option_t SetLineColor
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 SetMarkerStyle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t points
Option_t Option_t TPoint TPoint const char y1
R__EXTERN TStyle * gStyle
Definition TStyle.h:433
#define gPad
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
virtual void Modify()
Change current fill area attributes if necessary.
Definition TAttFill.cxx:216
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 Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:34
virtual void Modify()
Change current line attributes if necessary.
Definition TAttLine.cxx:247
Marker Attributes class.
Definition TAttMarker.h:19
virtual void Modify()
Change current marker attributes if necessary.
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:32
Double_t GetXmax() const
Definition TAxis.h:140
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:518
Double_t GetXmin() const
Definition TAxis.h:139
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:528
Buffer base class used for serializing objects.
Definition TBuffer.h:43
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
Definition TBuffer.h:86
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
The candle plot painter class.
Definition TCandle.h:27
Double_t fMedian
Position of the median.
Definition TCandle.h:64
CandleOption
Definition TCandle.h:30
@ kHorizontal
If this bit is not set it is vertical.
Definition TCandle.h:48
@ kAnchor
Definition TCandle.h:40
@ kWhiskerAll
Definition TCandle.h:38
@ kMeanCircle
Definition TCandle.h:37
@ kHistoZeroIndicator
Definition TCandle.h:47
@ kPointsAllScat
Definition TCandle.h:43
@ kNoOption
Definition TCandle.h:31
@ kHistoRight
Definition TCandle.h:45
@ kMeanLine
Definition TCandle.h:36
@ kBox
Definition TCandle.h:32
@ kWhisker15
Definition TCandle.h:39
@ kMedianLine
Definition TCandle.h:33
@ kPointsAll
Definition TCandle.h:42
@ kPointsOutliers
Definition TCandle.h:41
@ kMedianNotched
Definition TCandle.h:34
@ kHistoLeft
Definition TCandle.h:44
@ kMedianCircle
Definition TCandle.h:35
@ kHistoViolin
Definition TCandle.h:46
TH1D * fProj
Definition TCandle.h:56
static TClass * Class()
void Streamer(TBuffer &) override
Stream an object of class TCandle.
Definition TCandle.cxx:913
static void SetScaledViolin(const Bool_t vScale=true)
Static function to set scaling between violin-withs.
Definition TCandle.cxx:235
bool fIsRaw
0: for TH1 projection, 1: using raw data
Definition TCandle.h:54
CandleOption fOption
Setting the style of the candle.
Definition TCandle.h:82
TString fOptionStr
String to draw the candle.
Definition TCandle.h:83
Double_t fAxisMax
The Maximum which is visible by the axis (used by zero indicator)
Definition TCandle.h:89
~TCandle() override
TCandle default destructor.
Definition TCandle.cxx:175
int fLogZ
make the candle appear logz-like
Definition TCandle.h:86
Double_t fPosCandleAxis
x-pos for a vertical candle
Definition TCandle.h:59
int GetCandleOption(const int pos) const
Definition TCandle.h:93
int fNHistoPoints
Definition TCandle.h:80
Double_t fMean
Position of the mean.
Definition TCandle.h:63
Double_t fWhiskerDown
Position of the lower whisker end.
Definition TCandle.h:69
Long64_t fNDrawPoints
max number of outliers or other point to be shown
Definition TCandle.h:76
virtual void Paint(Option_t *option="")
Paint one candle with its current attributes.
Definition TCandle.cxx:666
Double_t fAxisMin
The Minimum which is visible by the axis (used by zero indicator)
Definition TCandle.h:88
void ConvertToPadCoords(Double_t minAxis, Double_t maxAxis, Double_t axisMinCoord, Double_t axisMaxCoord)
The coordinates in the TParallelCoordVar-class are in Pad-Coordinates, so we need to convert them.
Definition TCandle.cxx:930
Double_t fDrawPointsY[kNMAXPOINTS]
y-coord for every outlier, ..
Definition TCandle.h:75
Long64_t fNDatapoints
Number of Datapoints within this candle.
Definition TCandle.h:72
Bool_t IsViolinScaled() const
Returns true if violin plot should be scaled.
Definition TCandle.cxx:191
Double_t fHistoPointsY[kNMAXPOINTS]
y-coord for the polyline of the histo
Definition TCandle.h:79
Bool_t IsHorizontal() const
Definition TCandle.h:112
Double_t fHistoPointsX[kNMAXPOINTS]
x-coord for the polyline of the histo
Definition TCandle.h:78
static void SetScaledCandle(const Bool_t cScale=true)
Static function to set scaling between candles-withs.
Definition TCandle.cxx:225
Double_t * fDatapoints
position of all Datapoints within this candle
Definition TCandle.h:71
int ParseOption(char *optin)
Parsing of the option-string.
Definition TCandle.cxx:244
bool fDismiss
True if the candle cannot be painted.
Definition TCandle.h:57
Double_t fWhiskerUp
Position of the upper whisker end.
Definition TCandle.h:68
static void SetBoxRange(const Double_t bRange)
Static function to set BoxRange, by setting box-range, one can force the box of the candle-chart to c...
Definition TCandle.cxx:216
bool IsOption(CandleOption opt) const
Return true is this option is activated in fOption.
Definition TCandle.cxx:843
int fLogY
make the candle appear logy-like
Definition TCandle.h:85
Double_t fMedianErr
The size of the notch.
Definition TCandle.h:65
void PaintBox(Int_t nPoints, Double_t *x, Double_t *y, Bool_t swapXY)
Paint a box for candle.
Definition TCandle.cxx:859
Double_t fBoxUp
Position of the upper box end.
Definition TCandle.h:66
int fLogX
make the candle appear logx-like
Definition TCandle.h:84
Double_t fDrawPointsX[kNMAXPOINTS]
x-coord for every outlier, ..
Definition TCandle.h:74
TCandle()
TCandle default constructor.
Definition TCandle.cxx:38
Double_t fBoxDown
Position of the lower box end.
Definition TCandle.h:67
void Calculate()
Calculates all values needed by the candle definition depending on the candle options.
Definition TCandle.cxx:379
void PaintLine(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Bool_t swapXY)
Paint a line for candle.
Definition TCandle.cxx:889
Double_t fHistoWidth
The histo width (the height of the max bin)
Definition TCandle.h:61
Bool_t IsCandleScaled() const
Returns true if candle plot should be scaled.
Definition TCandle.cxx:183
bool fIsCalculated
Definition TCandle.h:55
static void SetWhiskerRange(const Double_t wRange)
Static function to set WhiskerRange, by setting whisker-range, one can force the whiskers to cover th...
Definition TCandle.cxx:204
Double_t fCandleWidth
The candle width.
Definition TCandle.h:60
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:664
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 GetBinCenter(Int_t bin) const
Return bin center for 1D histogram.
Definition TH1.cxx:9105
virtual Double_t GetMean(Int_t axis=1) const
For axis = 1,2 or 3 returns the mean value of the histogram along X,Y or Z axis.
Definition TH1.cxx:7499
TAxis * GetXaxis()
Definition TH1.h:324
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 GetNbinsX() const
Definition TH1.h:297
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition TH1.cxx:3340
virtual TH1 * RebinX(Int_t ngroup=2, const char *newname="")
Definition TH1.h:354
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9116
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4419
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5025
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9127
virtual Int_t GetQuantiles(Int_t nprobSum, Double_t *q, const Double_t *probSum=nullptr)
Compute Quantiles for this histogram Quantile x_q of a probability distribution Function F is defined...
Definition TH1.cxx:4575
virtual Int_t FindBin(Double_t x, Double_t y=0, Double_t z=0)
Return Global bin number corresponding to x,y,z.
Definition TH1.cxx:3668
Random number generator class based on the maximally quidistributed combined Tausworthe generator by ...
Definition TRandom2.h:27
Double_t Rndm() override
TausWorth generator from L'Ecuyer, uses as seed 3x32bits integers Use a mask of 0xffffffffUL to make ...
Definition TRandom2.cxx:55
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
Bool_t GetViolinScaled() const
Definition TStyle.h:291
Bool_t GetCandleScaled() const
Definition TStyle.h:290
Double_t GetCandleWhiskerRange() const
Definition TStyle.h:288
void SetCandleScaled(Bool_t on=kFALSE)
Definition TStyle.h:422
Double_t GetCandleBoxRange() const
Definition TStyle.h:289
void SetViolinScaled(Bool_t on=kTRUE)
Definition TStyle.h:423
void SetCandleWhiskerRange(Double_t wRange=1.0)
By setting whisker-range for candle plot, one can force the whiskers to cover the fraction of the dis...
Definition TStyle.cxx:1935
void SetCandleBoxRange(Double_t bRange=0.5)
By setting box-range for candle plot, one can force the box of the candle-chart to cover that given f...
Definition TStyle.cxx:1952
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
TLine l
Definition textangle.C:4