Logo ROOT  
Reference Guide
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 "strlcpy.h"
20
25
27
28/** \class TCandle
29\ingroup BasicGraphics
30
31The candle plot painter class.
32
33Instances of this class are generated by the histograms painting
34classes (THistPainter and THStack) when an candle plot (box plot) is drawn.
35TCandle is the "painter class" of the box plots. Therefore it is never used
36directly to draw a candle.
37*/
38
39////////////////////////////////////////////////////////////////////////////////
40/// TCandle default constructor.
41
43{
44 fIsCalculated = false;
45 fIsRaw = false;
46 fPosCandleAxis = 0.;
47 fCandleWidth = 1.0;
48 fHistoWidth = 1.0;
49 fMean = 0.;
50 fMedian = 0.;
51 fMedianErr = 0;
52 fBoxUp = 0.;
53 fBoxDown = 0.;
54 fWhiskerUp = 0.;
55 fWhiskerDown = 0.;
56 fNDatapoints = 0;
57 fDismiss = false;
58 fLogX = 0;
59 fLogY = 0;
60 fLogZ = 0;
61 fNDrawPoints = 0;
62 fNHistoPoints = 0;
63 fAxisMin = 0.;
64 fAxisMax = 0.;
66 fProj = nullptr;
67 fDatapoints = nullptr;
68
69}
70
71////////////////////////////////////////////////////////////////////////////////
72/// TCandle constructor passing a draw-option.
73
74TCandle::TCandle(const char *opt)
75{
76 fIsCalculated = false;
77 fIsRaw = false;
78 fPosCandleAxis = 0.;
79 fCandleWidth = 1.0;
80 fHistoWidth = 1.0;
81 fMean = 0.;
82 fMedian = 0.;
83 fMedianErr = 0;
84 fBoxUp = 0.;
85 fBoxDown = 0.;
86 fWhiskerUp = 0.;
87 fWhiskerDown = 0.;
88 fNDatapoints = 0;
89 fDismiss = false;
90 fLogX = 0;
91 fLogY = 0;
92 fLogZ = 0;
93 fNDrawPoints = 0;
94 fNHistoPoints = 0;
95 fAxisMin = 0.;
96 fAxisMax = 0.;
98 fProj = nullptr;
99 fDatapoints = nullptr;
100
101 // Conversion necessary in order to cast from const char* to char*
102 char myopt[128];
103 strlcpy(myopt,opt,128);
104
105
106 ParseOption(myopt);
107}
108
109
110////////////////////////////////////////////////////////////////////////////////
111/// TCandle constructor for raw-data candles.
112
113TCandle::TCandle(const Double_t candlePos, const Double_t candleWidth, Long64_t n, Double_t * points)
115{
116 //Preliminary values only, need to be calculated before paint
117 fMean = 0;
118 fMedian = 0;
119 fMedianErr = 0;
120 fBoxUp = 0;
121 fBoxDown = 0;
122 fWhiskerUp = 0;
123 fWhiskerDown = 0;
124 fNDatapoints = n;
125 fIsCalculated = 0;
126 fIsRaw = true;
127 fPosCandleAxis = candlePos;
128 fCandleWidth = candleWidth;
129 fHistoWidth = candleWidth;
131 fProj = nullptr;
132 fDismiss = false;
134 fLogX = 0;
135 fLogY = 0;
136 fLogZ = 0;
137 fNDrawPoints = 0;
138 fNHistoPoints = 0;
139 fAxisMin = 0.;
140 fAxisMax = 0.;
141 snprintf(fOptionStr, sizeof(fOptionStr), " ");
142}
143
144////////////////////////////////////////////////////////////////////////////////
145/// TCandle TH1 data constructor.
146
147TCandle::TCandle(const Double_t candlePos, const Double_t candleWidth, TH1D *proj)
149{
150 //Preliminary values only, need to be calculated before paint
151 fMean = 0;
152 fMedian = 0;
153 fMedianErr = 0;
154 fBoxUp = 0;
155 fBoxDown = 0;
156 fWhiskerUp = 0;
157 fWhiskerDown = 0;
158 fNDatapoints = 0;
159 fIsCalculated = false;
160 fIsRaw = false;
161 fPosCandleAxis = candlePos;
162 fCandleWidth = candleWidth;
163 fHistoWidth = candleWidth;
164 fDatapoints = nullptr;
165 fProj = proj;
166 fDismiss = false;
168 fLogX = 0;
169 fLogY = 0;
170 fLogZ = 0;
171 fNDrawPoints = 0;
172 fNHistoPoints = 0;
173 fAxisMin = 0.;
174 fAxisMax = 0.;
175 snprintf(fOptionStr, sizeof(fOptionStr), " ");
176}
177
178////////////////////////////////////////////////////////////////////////////////
179/// TCandle default destructor.
180
182 if (fIsRaw && fProj) delete fProj;
183}
184
186{
187 return fScaledCandle;
188}
189
191{
192 return fScaledViolin;
193}
194
195////////////////////////////////////////////////////////////////////////////////
196/// Static function to set fWhiskerRange, by setting whisker-range, one can force
197/// the whiskers to cover the fraction of the distribution.
198/// Set wRange between 0 and 1. Default is 1
199/// TCandle::SetWhiskerRange(0.95) will set all candle-charts to cover 95% of
200/// the distribution with the whiskers.
201/// Can only be used with the standard-whisker definition
202
204 if (wRange < 0) fWhiskerRange = 0;
205 else if (wRange > 1) fWhiskerRange = 1;
206 else fWhiskerRange = wRange;
207
208}
209
210////////////////////////////////////////////////////////////////////////////////
211/// Static function to set fBoxRange, by setting whisker-range, one can force the
212/// box of the candle-chart to cover that given fraction of the distribution.
213/// Set bRange between 0 and 1. Default is 0.5
214/// TCandle::SetBoxRange(0.68) will set all candle-charts to cover 68% of the
215/// distribution by the box
216
217void TCandle::SetBoxRange(const Double_t bRange) {
218 if (bRange < 0) fBoxRange = 0;
219 else if (bRange > 1) fBoxRange = 1;
220 else fBoxRange = bRange;
221}
222
223////////////////////////////////////////////////////////////////////////////////
224/// Static function to set scaling between candles-withs. A candle containing
225/// 100 entries with be two times wider than a candle containing 50 entries
226
228 fScaledCandle = cScale;
229}
230
231////////////////////////////////////////////////////////////////////////////////
232/// Static function to set scaling between violin-withs. A violin or histo chart
233/// with a maximum bin content to 100 will be two times as high as a violin with
234/// a maximum bin content of 50
235
237 fScaledViolin = 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 snprintf(fOptionStr, sizeof(fOptionStr), "CANDLE%c(%ld)",direction,(long)fOption);
299 } else {
300 fOption = (CandleOption)(fOption + fallbackCandle);
301 }
302 } else {
303 snprintf(fOptionStr, sizeof(fOptionStr), "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 snprintf(fOptionStr, sizeof(fOptionStr), "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 snprintf(fOptionStr, sizeof(fOptionStr), "VIOLIN%c(%ld)",direction,(long)fOption);
356 } else {
357 fOption = (CandleOption)(fOption + fallbackCandle);
358 }
359 } else {
360 snprintf(fOptionStr, sizeof(fOptionStr), "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 snprintf(fOptionStr, sizeof(fOptionStr), "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
396 if (fWhiskerRange >= 1) {
397 prob[0] = 1e-15;
398 prob[4] = 1-1e-15;
399 } else {
400 prob[0] = 0.5 - fWhiskerRange/2.;
401 prob[4] = 0.5 + fWhiskerRange/2.;
402 }
403
404 if (fBoxRange >= 1) {
405 prob[1] = 1E-14;
406 prob[3] = 1-1E-14;
407 } else {
408 prob[1] = 0.5 - fBoxRange/2.;
409 prob[3] = 0.5 + fBoxRange/2.;
410 }
411
412 prob[2] = 0.5;
413
414 Double_t quantiles[5] = { 0., 0., 0., 0., 0. };
415 if (!fIsRaw && fProj) { //Need a calculation for a projected histo
416 if (((IsOption(kHistoLeft)) || (IsOption(kHistoRight)) || (IsOption(kHistoViolin))) && fProj->GetNbinsX() > 500) {
417 // When using the histooption the number of bins of the projection is
418 // limited because of the array space defined by kNMAXPOINTS.
419 // So the histo is rebinned, that it can be displayed at any time.
420 // Finer granularity is not useful anyhow
421 int divideBy = ((fProj->GetNbinsX() - 1)/((kNMAXPOINTS-10)/4))+1;
422 fProj->RebinX(divideBy);
423 }
424 fProj->GetQuantiles(5, quantiles, prob);
425 } else { //Need a calculation for a raw-data candle
427 }
428
429 // Check if the quantiles are valid, seems the under- and overflow is taken
430 // into account as well, we need to ignore this!
431 if (quantiles[0] >= quantiles[4] ||
432 quantiles[1] >= quantiles[3]) {
433 return;
434 }
435
436 // Definition of the candle in the standard case
437 fBoxUp = quantiles[3];
438 fBoxDown = quantiles[1];
439 fWhiskerUp = quantiles[4]; //Standard case
440 fWhiskerDown = quantiles[0]; //Standard case
441 fMedian = quantiles[2];
443 Int_t nOutliers = 0;
444
445 if (IsOption(kWhisker15)) { // Improved whisker definition, with 1.5*iqr
446 if (!fIsRaw && fProj) { //Need a calculation for a projected histo
447 int bin = fProj->FindBin(fBoxDown-1.5*iqr);
448 // extending only to the lowest data value within this range
449 while (fProj->GetBinContent(bin) == 0 && bin <= fProj->GetNbinsX()) bin++;
451
452 bin = fProj->FindBin(fBoxUp+1.5*iqr);
453 while (fProj->GetBinContent(bin) == 0 && bin >= 1) bin--;
455 } else { //Need a calculation for a raw-data candle
458
459 //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
460 for (Long64_t i = 0; i < fNDatapoints; ++i) {
461 Double_t myData = fDatapoints[i];
462 if (myData > fWhiskerUp && myData <= fBoxUp + 1.5*iqr) fWhiskerUp = myData;
463 if (myData < fWhiskerDown && myData >= fBoxDown - 1.5*iqr) fWhiskerDown = myData;
464 }
465 }
466 }
467
468 if (!fIsRaw && fProj) { //Need a calculation for a projected histo
469 fMean = fProj->GetMean();
470 fMedianErr = 1.57*iqr/sqrt(fProj->GetEntries());
473 } else { //Need a calculation for a raw-data candle
474 //Calculate the Mean
475 fMean = 0;
476 for (Long64_t i = 0; i < fNDatapoints; ++i) {
477 fMean += fDatapoints[i];
478 if (fDatapoints[i] < min) min = fDatapoints[i];
479 if (fDatapoints[i] > max) max = fDatapoints[i];
480 if (fDatapoints[i] < fWhiskerDown || fDatapoints[i] > fWhiskerUp) nOutliers++;
481 }
483 fMedianErr = 1.57*iqr/sqrt(fNDatapoints);
484 }
485
486 //Doing the outliers and other single points to show
487 if (GetCandleOption(5) > 0) { //Draw outliers
488 TRandom2 random;
489 const int maxOutliers = kNMAXPOINTS;
490 Double_t myScale = 1.;
491 if (!fIsRaw && fProj) { //Need a calculation for a projected histo
492 if (fProj->GetEntries() > maxOutliers/2) myScale = fProj->GetEntries()/(maxOutliers/2.);
493 fNDrawPoints = 0;
494 for (int bin = 0; bin < fProj->GetNbinsX(); bin++) {
495 // Either show them only outside the whiskers, or all of them
496 if (fProj->GetBinContent(bin) > 0 && (fProj->GetBinCenter(bin) < fWhiskerDown || fProj->GetBinCenter(bin) > fWhiskerUp || (GetCandleOption(5) > 1)) ) {
497 Double_t scaledBinContent = fProj->GetBinContent(bin)/myScale;
498 if (scaledBinContent >0 && scaledBinContent < 1) scaledBinContent = 1; //Outliers have a typical bin content between 0 and 1, when scaling they would disappear
499 for (int j=0; j < (int)scaledBinContent; j++) {
500 if (fNDrawPoints > maxOutliers) break;
501 if (IsOption(kPointsAllScat)) { //Draw outliers and "all" values scattered
504 } else { //Draw them in the "candle line"
506 if ((int)scaledBinContent == 1) //If there is only one datapoint available put it in the middle of the bin
508 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
510 }
511 if (swapXY) {
512 //Swap X and Y
513 Double_t keepCurrently;
514 keepCurrently = fDrawPointsX[fNDrawPoints];
516 fDrawPointsY[fNDrawPoints] = keepCurrently;
517 }
518 // Continue fMeans, that fNDrawPoints is not increased, so that value will not be shown
519 if (doLogX) {
521 }
522 if (doLogY) {
524 }
525 fNDrawPoints++;
526 }
527 }
528 if (fNDrawPoints > maxOutliers) { //Should never happen, due to myScale!!!
529 Error ("PaintCandlePlot","Not possible to draw all outliers.");
530 break;
531 }
532 }
533 } else { //Raw data candle
534 //If only outliers are shown, calculate myScale only based on nOutliers, use fNDatapoints (all) instead
535 if (IsOption(kPointsOutliers) && nOutliers > maxOutliers/2) {
536 myScale = nOutliers/(maxOutliers/2.);
537 } else {
538 if (fNDatapoints > maxOutliers/2) myScale = fNDatapoints/(maxOutliers/2.);
539 }
540 fNDrawPoints = 0;
541 for (int i = 0; i < fNDatapoints; i++ ) {
542 Double_t myData = fDatapoints[i];
543 Double_t maxScatter = (fWhiskerUp-fWhiskerDown)/100;
544 if (!(i % (int) myScale == 0 )) continue; //If the amount of data is too large take only every 2nd or 3rd to reduce the amount
545 // Either show them only outside the whiskers, or all of them
546 if (myData < fWhiskerDown || myData > fWhiskerUp || (GetCandleOption(5) > 1)) {
547 if (IsOption(kPointsAllScat)) { //Draw outliers and "all" values scattered
549 fDrawPointsY[fNDrawPoints] = myData + (random.Rndm() - 0.5)*maxScatter; //random +- 0.5 of candle-height
550 } else { //Draw them in the "candle line"
552 fDrawPointsY[fNDrawPoints] = myData + (random.Rndm() - 0.5)*maxScatter; //random +- 0.5 of candle-height
553 }
554 if (swapXY) {
555 //Swap X and Y
556 Double_t keepCurrently;
557 keepCurrently = fDrawPointsX[fNDrawPoints];
559 fDrawPointsY[fNDrawPoints] = keepCurrently;
560 }
561 // Continue fMeans, that fNDrawPoints is not increased, so that value will not be shown
562 if (doLogX) {
564 else continue;
565 }
566 if (doLogY) {
568 else continue;
569 }
570 fNDrawPoints++;
571 if (fNDrawPoints > maxOutliers) { //Should never happen, due to myScale!!!
572 Error ("PaintCandlePlotRaw","Not possible to draw all outliers.");
573 break;
574 }
575 }
576 }
577 }
578 }
580 //We are starting with kHistoRight, left will be modified from right later
581 if (fIsRaw) { //This is a raw-data candle
582 if (!fProj) {
583 fProj = new TH1D("hpa","hpa",100,min,max+0.0001*(max-min));
584 fProj->SetDirectory(nullptr);
585 for (Long64_t i = 0; i < fNDatapoints; ++i) {
587 }
588 }
589 }
590
591 fNHistoPoints = 0;
592 Double_t maxContent = fProj->GetMaximum();
593 Double_t maxHistoHeight = fHistoWidth;
594 if (IsOption(kHistoViolin)) maxHistoHeight *= 0.5;
595
596 bool isFirst = true;
597 int lastNonZero = 0;
598 for (int bin = 1; bin <= fProj->GetNbinsX(); bin++) {
599 if (isFirst) {
600 if (fProj->GetBinContent(bin) > 0) {
603 if (doLogX) {
605 }
606 if (doLogY) {
608 }
610 isFirst = false;
611 } else {
612 continue;
613 }
614 }
615
616 Double_t myBinValue = fProj->GetBinContent(bin);
617 if (doLogZ) {
618 if (myBinValue > 0) myBinValue = TMath::Log10(myBinValue); else myBinValue = 0;
619 }
620 fHistoPointsX[fNHistoPoints] = fPosCandleAxis + myBinValue/maxContent*maxHistoHeight;
623 fHistoPointsX[fNHistoPoints] = fPosCandleAxis + myBinValue/maxContent*maxHistoHeight;
625 if (doLogX) {
628 }
629 if (doLogY) {
632 }
633
635 if (fProj->GetBinContent(bin) > 0) lastNonZero = fNHistoPoints;
636 }
637
640 fNHistoPoints = lastNonZero+1; //+1 so that the line down to 0 is added as well
641
642 if (IsOption(kHistoLeft)) {
643 for (int i = 0; i < fNHistoPoints; i++) {
645 }
646 }
647 if (IsOption(kHistoViolin)) {
648 for (int i = 0; i < fNHistoPoints; i++) {
651 }
652 fNHistoPoints *= 2;
653 }
654 }
655
656 fIsCalculated = true;
657}
658
659////////////////////////////////////////////////////////////////////////////////
660/// Paint one candle with its current attributes.
661
663{
664 //If something was changed before, we need to recalculate some values
665 if (!fIsCalculated) Calculate();
666
667 // Save the attributes as they were set originally
668 Style_t saveLine = GetLineStyle();
669 Style_t saveMarker = GetMarkerStyle();
670 Style_t saveFillStyle = GetFillStyle();
671 Style_t saveFillColor = GetFillColor();
672 Style_t saveLineColor = GetLineColor();
673
675 Double_t dimRight = fPosCandleAxis+0.5*fCandleWidth;
676
680
681 Bool_t swapXY = IsOption(kHorizontal);
682 Bool_t doLogY = (!(swapXY) && fLogY) || (swapXY && fLogX);
683 Bool_t doLogX = (!(swapXY) && fLogX) || (swapXY && fLogY);
684
685 // From now on this is real painting only, no calculations anymore
686
688 SetLineColor(saveFillColor);
691 SetLineColor(saveLineColor);
693 }
694
695
697 if (IsOption(kHistoZeroIndicator) && (saveFillStyle != 0)) {
698 SetLineColor(saveFillColor);
700 }
701 if (!swapXY) {
704 } else {
707 }
708 if (IsOption(kHistoZeroIndicator) && (saveFillStyle != 0)) {
709 SetLineColor(saveLineColor);
711 }
712 }
713
714 if (IsOption(kBox)) { // Draw a simple box
715 if (IsOption(kMedianNotched)) { // Check if we have to draw a box with notches
716 Double_t x[] = {dimLeft, dimLeft, dimLeft+fCandleWidth/3., dimLeft, dimLeft, dimRight,
717 dimRight, dimRight-fCandleWidth/3., dimRight, dimRight, dimLeft};
720 PaintBox(11, x, y, swapXY);
721 } else { // draw a simple box
722 Double_t x[] = {dimLeft, dimLeft, dimRight, dimRight, dimLeft};
724 PaintBox(5, x, y, swapXY);
725 }
726 }
727
728 if (IsOption(kAnchor)) { // Draw the anchor line
729 PaintLine(dimLeft, fWhiskerUp, dimRight, fWhiskerUp, swapXY);
730 PaintLine(dimLeft, fWhiskerDown, dimRight, fWhiskerDown, swapXY);
731 }
732
733 if (IsOption(kWhiskerAll) && !IsOption(kHistoZeroIndicator)) { // Whiskers are dashed
734 SetLineStyle(2);
738 SetLineStyle(saveLine);
740 } else if ((IsOption(kWhiskerAll) && IsOption(kHistoZeroIndicator)) || IsOption(kWhisker15) ) { // Whiskers without dashing, better whisker definition, or forced when using zero line
743 }
744
745 if (IsOption(kMedianLine)) { // Paint fMedian as a line
746 PaintLine(dimLeft, fMedian, dimRight, fMedian, swapXY);
747 } else if (IsOption(kMedianNotched)) { // Paint fMedian as a line (using notches, fMedian line is shorter)
748 PaintLine(dimLeft+fCandleWidth/3, fMedian, dimRight-fCandleWidth/3., fMedian, swapXY);
749 } else if (IsOption(kMedianCircle)) { // Paint fMedian circle
750 Double_t myMedianX[1], myMedianY[1];
751 if (!swapXY) {
752 myMedianX[0] = fPosCandleAxis;
753 myMedianY[0] = fMedian;
754 } else {
755 myMedianX[0] = fMedian;
756 myMedianY[0] = fPosCandleAxis;
757 }
758
759 Bool_t isValid = true;
760 if (doLogX) {
761 if (myMedianX[0] > 0) myMedianX[0] = TMath::Log10(myMedianX[0]); else isValid = false;
762 }
763 if (doLogY) {
764 if (myMedianY[0] > 0) myMedianY[0] = TMath::Log10(myMedianY[0]); else isValid = false;
765 }
766
767 SetMarkerStyle(24);
769
770 if (isValid) gPad->PaintPolyMarker(1,myMedianX,myMedianY); // A circle for the fMedian
771
772 SetMarkerStyle(saveMarker);
774
775 }
776
777 if (IsOption(kMeanCircle)) { // Paint fMean as a circle
778 Double_t myMeanX[1], myMeanY[1];
779 if (!swapXY) {
780 myMeanX[0] = fPosCandleAxis;
781 myMeanY[0] = fMean;
782 } else {
783 myMeanX[0] = fMean;
784 myMeanY[0] = fPosCandleAxis;
785 }
786
787 Bool_t isValid = true;
788 if (doLogX) {
789 if (myMeanX[0] > 0) myMeanX[0] = TMath::Log10(myMeanX[0]); else isValid = false;
790 }
791 if (doLogY) {
792 if (myMeanY[0] > 0) myMeanY[0] = TMath::Log10(myMeanY[0]); else isValid = false;
793 }
794
795 SetMarkerStyle(24);
797
798 if (isValid) gPad->PaintPolyMarker(1,myMeanX,myMeanY); // A circle for the fMean
799
800 SetMarkerStyle(saveMarker);
802
803 } else if (IsOption(kMeanLine)) { // Paint fMean as a dashed line
804 SetLineStyle(2);
806
807 PaintLine(dimLeft, fMean, dimRight, fMean, swapXY);
808 SetLineStyle(saveLine);
810
811 }
812
813 if (IsOption(kAnchor)) { //Draw standard anchor
814 PaintLine(dimLeft, fWhiskerDown, dimRight, fWhiskerDown, swapXY); // the lower anchor line
815 PaintLine(dimLeft, fWhiskerUp, dimRight, fWhiskerUp, swapXY); // the upper anchor line
816 }
817
818 // This is a bit complex. All values here are handled as outliers. Usually
819 // only the datapoints outside the whiskers are shown.
820 // One can show them in one row as crosses, or scattered randomly. If activated
821 // all datapoint are shown in the same way
822
823 if (GetCandleOption(5) > 0) { //Draw outliers
824 if (IsOption(kPointsAllScat)) { //Draw outliers and "all" values scattered
826 } else {
828 }
830 gPad->PaintPolyMarker(fNDrawPoints,fDrawPointsX, fDrawPointsY);
831 }
832}
833
834////////////////////////////////////////////////////////////////////////////////
835/// Return true is this option is activated in fOption
836
838 long myOpt = 9;
839 int pos = 0;
840 for (pos = 0; pos < 16; pos++) {
841 if (myOpt > opt) break;
842 else myOpt *=10;
843 }
844 myOpt /= 9;
845 int thisOpt = GetCandleOption(pos);
846
847 return ((thisOpt * myOpt) == opt);
848}
849
850////////////////////////////////////////////////////////////////////////////////
851/// Paint a box for candle.
852
854{
855 Bool_t doLogY = (!(swapXY) && fLogY) || (swapXY && fLogX);
856 Bool_t doLogX = (!(swapXY) && fLogX) || (swapXY && fLogY);
857 if (doLogY) {
858 for (int i=0; i<nPoints; i++) {
859 if (y[i] > 0) y[i] = TMath::Log10(y[i]);
860 else return;
861 }
862 }
863 if (doLogX) {
864 for (int i=0; i<nPoints; i++) {
865 if (x[i] > 0) x[i] = TMath::Log10(x[i]);
866 else return;
867 }
868 }
869 if (!swapXY) {
870 gPad->PaintFillArea(nPoints, x, y);
871 gPad->PaintPolyLine(nPoints, x, y);
872 } else {
873 gPad->PaintFillArea(nPoints, y, x);
874 gPad->PaintPolyLine(nPoints, y, x);
875 }
876}
877
878////////////////////////////////////////////////////////////////////////////////
879/// Paint a line for candle.
880
882{
883 Bool_t doLogY = (!(swapXY) && fLogY) || (swapXY && fLogX);
884 Bool_t doLogX = (!(swapXY) && fLogX) || (swapXY && fLogY);
885 if (doLogY) {
886 if (y1 > 0) y1 = TMath::Log10(y1); else return;
887 if (y2 > 0) y2 = TMath::Log10(y2); else return;
888 }
889 if (doLogX) {
890 if (x1 > 0) x1 = TMath::Log10(x1); else return;
891 if (x2 > 0) x2 = TMath::Log10(x2); else return;
892 }
893 if (!swapXY) {
894 gPad->PaintLine(x1, y1, x2, y2);
895 } else {
896 gPad->PaintLine(y1, x1, y2, x2);
897 }
898}
899
900////////////////////////////////////////////////////////////////////////////////
901/// Stream an object of class TCandle.
902
904{
905 if (R__b.IsReading()) {
906 UInt_t R__s, R__c;
907 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
908 if (R__v > 3) {
909 R__b.ReadClassBuffer(TCandle::Class(), this, R__v, R__s, R__c);
910 return;
911 }
912 } else {
913 R__b.WriteClassBuffer(TCandle::Class(),this);
914 }
915}
916
917////////////////////////////////////////////////////////////////////////////////
918/// The coordinates in the TParallelCoordVar-class are in Pad-Coordinates, so we need to convert them
919
920void TCandle::ConvertToPadCoords(Double_t minAxis, Double_t maxAxis, Double_t axisMinCoord, Double_t axisMaxCoord)
921{
922 if (!fIsCalculated) Calculate();
923 Double_t a,b;
924 if (fLogY) {
925 a = TMath::Log10(minAxis);
926 b = TMath::Log10(maxAxis/minAxis);
927 } else {
928 a = minAxis;
929 b = maxAxis-minAxis;
930 }
931
932 fMean = axisMinCoord + ((fMean-a)/b)*(axisMaxCoord-axisMinCoord);
933 fMedian = axisMinCoord + ((fMedian-a)/b)*(axisMaxCoord-axisMinCoord);
934 fMedianErr = axisMinCoord + ((fMedianErr-a)/b)*(axisMaxCoord-axisMinCoord);
935 fBoxUp = axisMinCoord + ((fBoxUp-a)/b)*(axisMaxCoord-axisMinCoord);
936 fBoxDown = axisMinCoord + ((fBoxDown-a)/b)*(axisMaxCoord-axisMinCoord);
937 fWhiskerUp = axisMinCoord + ((fWhiskerUp-a)/b)*(axisMaxCoord-axisMinCoord);
938 fWhiskerDown = axisMinCoord + ((fWhiskerDown-a)/b)*(axisMaxCoord-axisMinCoord);
939
940 for (int i = 0; i < fNDrawPoints; i++) {
941 fDrawPointsY[i] = axisMinCoord + ((fDrawPointsY[i]-a)/b)*(axisMaxCoord-axisMinCoord);
942 }
943 for (int i = 0; i < fNHistoPoints; i++) {
944 fHistoPointsY[i] = axisMinCoord + ((fHistoPointsY[i]-a)/b)*(axisMaxCoord-axisMinCoord);
945 }
946}
#define e(i)
Definition: RSha256.hxx:103
short Style_t
Definition: RtypesCore.h:89
bool Bool_t
Definition: RtypesCore.h:63
short Version_t
Definition: RtypesCore.h:65
const Bool_t kFALSE
Definition: RtypesCore.h:101
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:375
const Int_t kNMAXPOINTS
Definition: TCandle.h:24
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition: TError.cxx:188
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 b
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 GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t points
Option_t Option_t TPoint TPoint const char y1
#define gPad
Definition: TVirtualPad.h:302
#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
virtual void Modify()
Change current fill area attributes if necessary.
Definition: TAttFill.cxx:213
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 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 void Modify()
Change current line attributes if necessary.
Definition: TAttLine.cxx:245
Marker Attributes class.
Definition: TAttMarker.h:19
virtual void Modify()
Change current marker attributes if necessary.
Definition: TAttMarker.cxx:320
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition: TAttMarker.h:32
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition: TAttMarker.h:40
Double_t GetXmax() const
Definition: TAxis.h:135
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition: TAxis.cxx:518
Double_t GetXmin() const
Definition: TAxis.h:134
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:26
Double_t fMedian
Position of the median.
Definition: TCandle.h:63
static Double_t fBoxRange
The fraction which is covered by the box (0 < x < 1), default 0.5.
Definition: TCandle.h:91
CandleOption
Definition: TCandle.h:29
@ kHorizontal
If this bit is not set it is vertical.
Definition: TCandle.h:47
@ kAnchor
Definition: TCandle.h:39
@ kWhiskerAll
Definition: TCandle.h:37
@ kMeanCircle
Definition: TCandle.h:36
@ kHistoZeroIndicator
Definition: TCandle.h:46
@ kPointsAllScat
Definition: TCandle.h:42
@ kNoOption
Definition: TCandle.h:30
@ kHistoRight
Definition: TCandle.h:44
@ kMeanLine
Definition: TCandle.h:35
@ kBox
Definition: TCandle.h:31
@ kWhisker15
Definition: TCandle.h:38
@ kMedianLine
Definition: TCandle.h:32
@ kPointsAll
Definition: TCandle.h:41
@ kPointsOutliers
Definition: TCandle.h:40
@ kMedianNotched
Definition: TCandle.h:33
@ kHistoLeft
Definition: TCandle.h:43
@ kMedianCircle
Definition: TCandle.h:34
@ kHistoViolin
Definition: TCandle.h:45
TH1D * fProj
Definition: TCandle.h:55
static TClass * Class()
void Streamer(TBuffer &) override
Stream an object of class TCandle.
Definition: TCandle.cxx:903
static void SetScaledViolin(const Bool_t vScale=true)
Static function to set scaling between violin-withs.
Definition: TCandle.cxx:236
bool fIsRaw
0: for TH1 projection, 1: using raw data
Definition: TCandle.h:53
static Double_t fWhiskerRange
The fraction which is covered by the whiskers (0 < x < 1), default 1.
Definition: TCandle.h:90
CandleOption fOption
Setting the style of the candle.
Definition: TCandle.h:81
Double_t fAxisMax
The Maximum which is visible by the axis (used by zero indicator)
Definition: TCandle.h:88
int fLogZ
make the candle appear logz-like
Definition: TCandle.h:85
bool IsOption(CandleOption opt)
Return true is this option is activated in fOption.
Definition: TCandle.cxx:837
Double_t fPosCandleAxis
x-pos for a vertical candle
Definition: TCandle.h:58
int fNHistoPoints
Definition: TCandle.h:79
Double_t fMean
Position of the mean.
Definition: TCandle.h:62
Double_t fWhiskerDown
Position of the lower whisker end.
Definition: TCandle.h:68
Long64_t fNDrawPoints
max number of outliers or other point to be shown
Definition: TCandle.h:75
virtual void Paint(Option_t *option="")
Paint one candle with its current attributes.
Definition: TCandle.cxx:662
Double_t fAxisMin
The Minimum which is visible by the axis (used by zero indicator)
Definition: TCandle.h:87
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:920
Double_t fDrawPointsY[kNMAXPOINTS]
y-coord for every outlier, ..
Definition: TCandle.h:74
Bool_t IsViolinScaled()
Definition: TCandle.cxx:190
Long64_t fNDatapoints
Number of Datapoints within this candle.
Definition: TCandle.h:71
Double_t fHistoPointsY[kNMAXPOINTS]
y-coord for the polyline of the histo
Definition: TCandle.h:78
Bool_t IsHorizontal()
Definition: TCandle.h:117
Double_t fHistoPointsX[kNMAXPOINTS]
x-coord for the polyline of the histo
Definition: TCandle.h:77
static void SetScaledCandle(const Bool_t cScale=true)
Static function to set scaling between candles-withs.
Definition: TCandle.cxx:227
Double_t * fDatapoints
position of all Datapoints within this candle
Definition: TCandle.h:70
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:56
Double_t fWhiskerUp
Position of the upper whisker end.
Definition: TCandle.h:67
static void SetBoxRange(const Double_t bRange)
Static function to set fBoxRange, by setting whisker-range, one can force the box of the candle-chart...
Definition: TCandle.cxx:217
static Bool_t fScaledViolin
shall the violin or histos be scaled to each other by the maximum height?
Definition: TCandle.h:94
int fLogY
make the candle appear logy-like
Definition: TCandle.h:84
Double_t fMedianErr
The size of the notch.
Definition: TCandle.h:64
void PaintBox(Int_t nPoints, Double_t *x, Double_t *y, Bool_t swapXY)
Paint a box for candle.
Definition: TCandle.cxx:853
Double_t fBoxUp
Position of the upper box end.
Definition: TCandle.h:65
virtual ~TCandle()
TCandle default destructor.
Definition: TCandle.cxx:181
int fLogX
make the candle appear logx-like
Definition: TCandle.h:83
Double_t fDrawPointsX[kNMAXPOINTS]
x-coord for every outlier, ..
Definition: TCandle.h:73
TCandle()
TCandle default constructor.
Definition: TCandle.cxx:42
Double_t fBoxDown
Position of the lower box end.
Definition: TCandle.h:66
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:881
Bool_t IsCandleScaled()
Definition: TCandle.cxx:185
Double_t fHistoWidth
The histo width (the height of the max bin)
Definition: TCandle.h:60
int GetCandleOption(const int pos)
Definition: TCandle.h:98
bool fIsCalculated
Definition: TCandle.h:54
static void SetWhiskerRange(const Double_t wRange)
Static function to set fWhiskerRange, by setting whisker-range, one can force the whiskers to cover t...
Definition: TCandle.cxx:203
static Bool_t fScaledCandle
shall the box-width be scaled to each other by the integral of a box?
Definition: TCandle.h:93
char fOptionStr[128]
String to draw the candle.
Definition: TCandle.h:82
Double_t fCandleWidth
The candle width.
Definition: TCandle.h:59
1-D histogram with a double per channel (see TH1 documentation)}
Definition: TH1.h:620
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:8803
virtual Double_t GetBinCenter(Int_t bin) const
Return bin center for 1D histogram.
Definition: TH1.cxx:9007
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:7445
TAxis * GetXaxis()
Definition: TH1.h:322
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:8411
virtual Int_t GetNbinsX() const
Definition: TH1.h:295
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition: TH1.cxx:3338
virtual TH1 * RebinX(Int_t ngroup=2, const char *newname="")
Definition: TH1.h:352
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition: TH1.cxx:9018
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:9029
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:56
Double_t y[n]
Definition: legend1.C:17
Double_t x[n]
Definition: legend1.C:17
const Int_t n
Definition: legend1.C:16
VecExpr< UnaryOp< Sqrt< T >, VecExpr< A, T, D >, T >, T, D > sqrt(const VecExpr< A, T, D > &rhs)
constexpr Double_t E()
Base of natural log: .
Definition: TMath.h:93
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:760
TLine l
Definition: textangle.C:4
TArc a
Definition: textangle.C:12