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 = 0;
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 = 0;
100
101
102 // Conversion necessary in order to cast from const char* to char*
103 char myopt[128];
104 strlcpy(myopt,opt,128);
105
106
107 ParseOption(myopt);
108}
109
110
111////////////////////////////////////////////////////////////////////////////////
112/// TCandle constructor for raw-data candles.
113
114TCandle::TCandle(const Double_t candlePos, const Double_t candleWidth, Long64_t n, Double_t * points)
116{
117 //Preliminary values only, need to be calculated before paint
118 fMean = 0;
119 fMedian = 0;
120 fMedianErr = 0;
121 fBoxUp = 0;
122 fBoxDown = 0;
123 fWhiskerUp = 0;
124 fWhiskerDown = 0;
125 fNDatapoints = n;
126 fIsCalculated = 0;
127 fIsRaw = true;
128 fPosCandleAxis = candlePos;
129 fCandleWidth = candleWidth;
130 fHistoWidth = candleWidth;
132 fProj = nullptr;
133 fDismiss = false;
135 fLogX = 0;
136 fLogY = 0;
137 fLogZ = 0;
138 fNDrawPoints = 0;
139 fNHistoPoints = 0;
140 fAxisMin = 0.;
141 fAxisMax = 0.;
142 sprintf(fOptionStr," ");
143}
144
145////////////////////////////////////////////////////////////////////////////////
146/// TCandle TH1 data constructor.
147
148TCandle::TCandle(const Double_t candlePos, const Double_t candleWidth, TH1D *proj)
150{
151 //Preliminary values only, need to be calculated before paint
152 fMean = 0;
153 fMedian = 0;
154 fMedianErr = 0;
155 fBoxUp = 0;
156 fBoxDown = 0;
157 fWhiskerUp = 0;
158 fWhiskerDown = 0;
159 fNDatapoints = 0;
160 fIsCalculated = false;
161 fIsRaw = false;
162 fPosCandleAxis = candlePos;
163 fCandleWidth = candleWidth;
164 fHistoWidth = candleWidth;
165 fDatapoints = 0;
166 fProj = proj;
167 fDismiss = false;
169 fLogX = 0;
170 fLogY = 0;
171 fLogZ = 0;
172 fNDrawPoints = 0;
173 fNHistoPoints = 0;
174 fAxisMin = 0.;
175 fAxisMax = 0.;
176 sprintf(fOptionStr," ");
177}
178
179////////////////////////////////////////////////////////////////////////////////
180/// TCandle default destructor.
181
183 if (fIsRaw && fProj) delete fProj;
184}
185
187{
188 return fScaledCandle;
189}
190
192{
193 return fScaledViolin;
194}
195
196////////////////////////////////////////////////////////////////////////////////
197/// Static function to set fWhiskerRange, 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 if (wRange < 0) fWhiskerRange = 0;
206 else if (wRange > 1) fWhiskerRange = 1;
207 else fWhiskerRange = wRange;
208
209}
210
211////////////////////////////////////////////////////////////////////////////////
212/// Static function to set fBoxRange, by setting whisker-range, one can force the
213/// box of the candle-chart to cover that given fraction of the distribution.
214/// Set bRange between 0 and 1. Default is 0.5
215/// TCandle::SetBoxRange(0.68) will set all candle-charts to cover 68% of the
216/// distribution by the box
217
218void TCandle::SetBoxRange(const Double_t bRange) {
219 if (bRange < 0) fBoxRange = 0;
220 else if (bRange > 1) fBoxRange = 1;
221 else fBoxRange = bRange;
222}
223
224////////////////////////////////////////////////////////////////////////////////
225/// Static function to set scaling between candles-withs. A candle containing
226/// 100 entries with be two times wider than a candle containing 50 entries
227
229 fScaledCandle = cScale;
230}
231
232////////////////////////////////////////////////////////////////////////////////
233/// Static function to set scaling between violin-withs. A violin or histo chart
234/// with a maximum bin content to 100 will be two times as high as a violin with
235/// a maximum bin content of 50
236
238 fScaledViolin = vScale;
239}
240
241////////////////////////////////////////////////////////////////////////////////
242/// Parsing of the option-string.
243/// The option-string will be empty at the end (by-reference).
244
245int TCandle::ParseOption(char * opt) {
247 char *l = strstr(opt,"CANDLE");
248
249 if (l) {
250 const CandleOption fallbackCandle = (CandleOption)(kBox + kMedianLine + kMeanCircle + kWhiskerAll + kAnchor);
251
252 char direction = ' ';
253 char preset = ' ';
254
255 if (l[6] >= 'A' && l[6] <= 'Z') direction = l[6];
256 if (l[6] >= '1' && l[6] <= '9') preset = l[6];
257 if (l[7] >= 'A' && l[7] <= 'Z' && preset != ' ') direction = l[7];
258 if (l[7] >= '1' && l[7] <= '9' && direction != ' ') preset = l[7];
259
260 if (direction == 'X' || direction == 'V') { /* nothing */ }
261 if (direction == 'Y' || direction == 'H') { fOption = (CandleOption)(fOption + kHorizontal); }
262 if (preset == '1') //Standard candle using old candle-definition
263 fOption = (CandleOption)(fOption + fallbackCandle);
264 else if (preset == '2') //New standard candle with better whisker definition + outlier
266 else if (preset == '3') //Like candle2 but with a fMean as a circle
268 else if (preset == '4') //Like candle3 but showing the uncertainty of the fMedian as well
270 else if (preset == '5') //Like candle2 but showing all datapoints
272 else if (preset == '6') //Like candle2 but showing all datapoints scattered
274 else if (preset != ' ') //For all other presets not implemented yet used fallback candle
275 fOption = (CandleOption)(fOption + fallbackCandle);
276
277 if (preset != ' ' && direction != ' ')
278 memcpy(l," ",8);
279 else if (preset != ' ' || direction != ' ')
280 memcpy(l," ",7);
281 else
282 memcpy(l," ",6);
283
284 Bool_t useIndivOption = false;
285
286 if (direction == ' ') direction = 'X';
287 if (preset == ' ') { // Check if the user wants to set the properties individually
288 char *brOpen = strstr(opt,"(");
289 char *brClose = strstr(opt,")");
290 char indivOption[32];
291 if (brOpen && brClose) {
292 useIndivOption = true;
293 bool wasHorizontal = IsHorizontal();
294 strlcpy(indivOption, brOpen, brClose-brOpen+2); //Now the string "(....)" including brackets is in this array
295 sscanf(indivOption,"(%d)", (int*) &fOption);
296 if (wasHorizontal && !IsHorizontal()) {fOption = (CandleOption)(fOption + kHorizontal);}
297 memcpy(brOpen," ",brClose-brOpen+1); //Cleanup
298
299 snprintf(fOptionStr, sizeof(fOptionStr), "CANDLE%c(%ld)",direction,(long)fOption);
300 } else {
301 fOption = (CandleOption)(fOption + fallbackCandle);
302 }
303 } else {
304 snprintf(fOptionStr, sizeof(fOptionStr), "CANDLE%c%c",direction,preset);
305 }
306 //Handle option "CANDLE" ,"CANDLEX" or "CANDLEY" to behave like "CANDLEX1" or "CANDLEY1"
307 if (!useIndivOption && !fOption ) {
308 fOption = fallbackCandle;
309 snprintf(fOptionStr, sizeof(fOptionStr), "CANDLE%c2",direction);
310 }
311 }
312
313 l = strstr(opt,"VIOLIN");
314 if (l) {
316
317 char direction = ' ';
318 char preset = ' ';
319
320 if (l[6] >= 'A' && l[6] <= 'Z') direction = l[6];
321 if (l[6] >= '1' && l[6] <= '9') preset = l[6];
322 if (l[7] >= 'A' && l[7] <= 'Z' && preset != ' ') direction = l[7];
323 if (l[7] >= '1' && l[7] <= '9' && direction != ' ') preset = l[7];
324
325 if (direction == 'X' || direction == 'V') { /* nothing */ }
326 if (direction == 'Y' || direction == 'H') { fOption = (CandleOption)(fOption + kHorizontal); }
327 if (preset == '1') //Standard candle using old candle-definition
328 fOption = (CandleOption)(fOption + fallbackCandle);
329 else if (preset == '2') //New standard candle with better whisker definition + outlier
331 else if (preset != ' ') //For all other presets not implemented yet used fallback candle
332 fOption = (CandleOption)(fOption + fallbackCandle);
333
334 if (preset != ' ' && direction != ' ')
335 memcpy(l," ",8);
336 else if (preset != ' ' || direction != ' ')
337 memcpy(l," ",7);
338 else
339 memcpy(l," ",6);
340
341 Bool_t useIndivOption = false;
342
343 if (direction == ' ') direction = 'X';
344 if (preset == ' ') { // Check if the user wants to set the properties individually
345 char *brOpen = strstr(opt,"(");
346 char *brClose = strstr(opt,")");
347 char indivOption[32];
348 if (brOpen && brClose) {
349 useIndivOption = true;
350 bool wasHorizontal = IsHorizontal();
351 strlcpy(indivOption, brOpen, brClose-brOpen +2); //Now the string "(....)" including brackets is in this array
352 sscanf(indivOption,"(%d)", (int*) &fOption);
353 if (wasHorizontal && !IsHorizontal()) {fOption = (CandleOption)(fOption + kHorizontal);}
354 memcpy(brOpen," ",brClose-brOpen+1); //Cleanup
355
356 snprintf(fOptionStr, sizeof(fOptionStr), "VIOLIN%c(%ld)",direction,(long)fOption);
357 } else {
358 fOption = (CandleOption)(fOption + fallbackCandle);
359 }
360 } else {
361 snprintf(fOptionStr, sizeof(fOptionStr), "VIOLIN%c%c",direction,preset);
362 }
363 //Handle option "VIOLIN" ,"VIOLINX" or "VIOLINY" to behave like "VIOLINX1" or "VIOLINY1"
364 if (!useIndivOption && !fOption ) {
365 fOption = fallbackCandle;
366 snprintf(fOptionStr, sizeof(fOptionStr), "VIOLIN%c1",direction);
367 }
368 }
369
370 fIsCalculated = false;
371
372 return fOption;
373
374}
375
376////////////////////////////////////////////////////////////////////////////////
377/// Calculates all values needed by the candle definition depending on the
378/// candle options.
379
381 //Reset everything
382 fNDrawPoints = 0;
383 fNHistoPoints = 0;
384
385 Bool_t swapXY = IsOption(kHorizontal);
386 Bool_t doLogY = (!(swapXY) && fLogY) || (swapXY && fLogX);
387 Bool_t doLogX = (!(swapXY) && fLogX) || (swapXY && fLogY);
388 Bool_t doLogZ = fLogZ;
389
390 //Will be min and max values of raw-data
391 Double_t min = 1e15;
392 Double_t max = -1e15;
393
394 // Determining the quantiles
395 Double_t *prob = new Double_t[5];
396
397 if (fWhiskerRange >= 1) {
398 prob[0] = 1e-15;
399 prob[4] = 1-1e-15;
400 } else {
401 prob[0] = 0.5 - fWhiskerRange/2.;
402 prob[4] = 0.5 + fWhiskerRange/2.;
403 }
404
405
406 if (fBoxRange >= 1) {
407 prob[1] = 1E-14;
408 prob[3] = 1-1E-14;
409 } else {
410 prob[1] = 0.5 - fBoxRange/2.;
411 prob[3] = 0.5 + fBoxRange/2.;
412 }
413
414 prob[2]=0.5;
415 Double_t *quantiles = new Double_t[5];
416 quantiles[0]=0.; quantiles[1]=0.; quantiles[2] = 0.; quantiles[3] = 0.; quantiles[4] = 0.;
417 if (!fIsRaw && fProj) { //Need a calculation for a projected histo
418 if (((IsOption(kHistoLeft)) || (IsOption(kHistoRight)) || (IsOption(kHistoViolin))) && fProj->GetNbinsX() > 500) {
419 // When using the histooption the number of bins of the projection is
420 // limited because of the array space defined by kNMAXPOINTS.
421 // So the histo is rebinned, that it can be displayed at any time.
422 // Finer granularity is not useful anyhow
423 int divideBy = ((fProj->GetNbinsX() - 1)/((kNMAXPOINTS-10)/4))+1;
424 fProj->RebinX(divideBy);
425 }
426 fProj->GetQuantiles(5, quantiles, prob);
427 } else { //Need a calculation for a raw-data candle
429 }
430
431 // Check if the quantiles are valid, seems the under- and overflow is taken
432 // into account as well, we need to ignore this!
433 if (quantiles[0] >= quantiles[4] ||
434 quantiles[1] >= quantiles[3]) {
435 delete [] prob;
436 delete [] quantiles;
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 delete [] prob;
491 delete [] quantiles;
492
493 //Doing the outliers and other single points to show
494 if (GetCandleOption(5) > 0) { //Draw outliers
495 TRandom2 random;
496 const int maxOutliers = kNMAXPOINTS;
497 Double_t myScale = 1.;
498 if (!fIsRaw && fProj) { //Need a calculation for a projected histo
499 if (fProj->GetEntries() > maxOutliers/2) myScale = fProj->GetEntries()/(maxOutliers/2.);
500 fNDrawPoints = 0;
501 for (int bin = 0; bin < fProj->GetNbinsX(); bin++) {
502 // Either show them only outside the whiskers, or all of them
503 if (fProj->GetBinContent(bin) > 0 && (fProj->GetBinCenter(bin) < fWhiskerDown || fProj->GetBinCenter(bin) > fWhiskerUp || (GetCandleOption(5) > 1)) ) {
504 Double_t scaledBinContent = fProj->GetBinContent(bin)/myScale;
505 if (scaledBinContent >0 && scaledBinContent < 1) scaledBinContent = 1; //Outliers have a typical bin content between 0 and 1, when scaling they would disappear
506 for (int j=0; j < (int)scaledBinContent; j++) {
507 if (fNDrawPoints > maxOutliers) break;
508 if (IsOption(kPointsAllScat)) { //Draw outliers and "all" values scattered
511 } else { //Draw them in the "candle line"
513 if ((int)scaledBinContent == 1) //If there is only one datapoint available put it in the middle of the bin
515 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
517 }
518 if (swapXY) {
519 //Swap X and Y
520 Double_t keepCurrently;
521 keepCurrently = fDrawPointsX[fNDrawPoints];
523 fDrawPointsY[fNDrawPoints] = keepCurrently;
524 }
525 // Continue fMeans, that fNDrawPoints is not increased, so that value will not be shown
526 if (doLogX) {
528 }
529 if (doLogY) {
531 }
532 fNDrawPoints++;
533 }
534 }
535 if (fNDrawPoints > maxOutliers) { //Should never happen, due to myScale!!!
536 Error ("PaintCandlePlot","Not possible to draw all outliers.");
537 break;
538 }
539 }
540 } else { //Raw data candle
541 //If only outliers are shown, calculate myScale only based on nOutliers, use fNDatapoints (all) instead
542 if (IsOption(kPointsOutliers) && nOutliers > maxOutliers/2) {
543 myScale = nOutliers/(maxOutliers/2.);
544 } else {
545 if (fNDatapoints > maxOutliers/2) myScale = fNDatapoints/(maxOutliers/2.);
546 }
547 fNDrawPoints = 0;
548 for (int i = 0; i < fNDatapoints; i++ ) {
549 Double_t myData = fDatapoints[i];
550 Double_t maxScatter = (fWhiskerUp-fWhiskerDown)/100;
551 if (!(i % (int) myScale == 0 )) continue; //If the amount of data is too large take only every 2nd or 3rd to reduce the amount
552 // Either show them only outside the whiskers, or all of them
553 if (myData < fWhiskerDown || myData > fWhiskerUp || (GetCandleOption(5) > 1)) {
554 if (IsOption(kPointsAllScat)) { //Draw outliers and "all" values scattered
556 fDrawPointsY[fNDrawPoints] = myData + (random.Rndm() - 0.5)*maxScatter; //random +- 0.5 of candle-height
557 } else { //Draw them in the "candle line"
559 fDrawPointsY[fNDrawPoints] = myData + (random.Rndm() - 0.5)*maxScatter; //random +- 0.5 of candle-height
560 }
561 if (swapXY) {
562 //Swap X and Y
563 Double_t keepCurrently;
564 keepCurrently = fDrawPointsX[fNDrawPoints];
566 fDrawPointsY[fNDrawPoints] = keepCurrently;
567 }
568 // Continue fMeans, that fNDrawPoints is not increased, so that value will not be shown
569 if (doLogX) {
571 else continue;
572 }
573 if (doLogY) {
575 else continue;
576 }
577 fNDrawPoints++;
578 if (fNDrawPoints > maxOutliers) { //Should never happen, due to myScale!!!
579 Error ("PaintCandlePlotRaw","Not possible to draw all outliers.");
580 break;
581 }
582 }
583 }
584 }
585 }
587 //We are starting with kHistoRight, left will be modified from right later
588 if (fIsRaw) { //This is a raw-data candle
589 if (!fProj) {
590 fProj = new TH1D("hpa","hpa",100,min,max+0.0001*(max-min));
591 fProj->SetDirectory(nullptr);
592 for (Long64_t i = 0; i < fNDatapoints; ++i) {
594 }
595 }
596 }
597
598 fNHistoPoints = 0;
599 Double_t maxContent = fProj->GetMaximum();
600 Double_t maxHistoHeight = fHistoWidth;
601 if (IsOption(kHistoViolin)) maxHistoHeight *= 0.5;
602
603 bool isFirst = true;
604 int lastNonZero = 0;
605 for (int bin = 1; bin <= fProj->GetNbinsX(); bin++) {
606 if (isFirst) {
607 if (fProj->GetBinContent(bin) > 0) {
610 if (doLogX) {
612 }
613 if (doLogY) {
615 }
617 isFirst = false;
618 } else {
619 continue;
620 }
621 }
622
623 Double_t myBinValue = fProj->GetBinContent(bin);
624 if (doLogZ) {
625 if (myBinValue > 0) myBinValue = TMath::Log10(myBinValue); else myBinValue = 0;
626 }
627 fHistoPointsX[fNHistoPoints] = fPosCandleAxis + myBinValue/maxContent*maxHistoHeight;
630 fHistoPointsX[fNHistoPoints] = fPosCandleAxis + myBinValue/maxContent*maxHistoHeight;
632 if (doLogX) {
635 }
636 if (doLogY) {
639 }
640
642 if (fProj->GetBinContent(bin) > 0) lastNonZero = fNHistoPoints;
643 }
644
647 fNHistoPoints = lastNonZero+1; //+1 so that the line down to 0 is added as well
648
649 if (IsOption(kHistoLeft)) {
650 for (int i = 0; i < fNHistoPoints; i++) {
652 }
653 }
654 if (IsOption(kHistoViolin)) {
655 for (int i = 0; i < fNHistoPoints; i++) {
658 }
659 fNHistoPoints *= 2;
660 }
661 }
662
663
664 fIsCalculated = true;
665}
666
667////////////////////////////////////////////////////////////////////////////////
668/// Paint one candle with its current attributes.
669
671{
672 //If something was changed before, we need to recalculate some values
673 if (!fIsCalculated) Calculate();
674
675 // Save the attributes as they were set originally
676 Style_t saveLine = GetLineStyle();
677 Style_t saveMarker = GetMarkerStyle();
678 Style_t saveFillStyle = GetFillStyle();
679 Style_t saveFillColor = GetFillColor();
680 Style_t saveLineColor = GetLineColor();
681
683 Double_t dimRight = fPosCandleAxis+0.5*fCandleWidth;
684
688
689 Bool_t swapXY = IsOption(kHorizontal);
690 Bool_t doLogY = (!(swapXY) && fLogY) || (swapXY && fLogX);
691 Bool_t doLogX = (!(swapXY) && fLogX) || (swapXY && fLogY);
692
693 // From now on this is real painting only, no calculations anymore
694
696 SetLineColor(saveFillColor);
699 SetLineColor(saveLineColor);
701 }
702
703
705 if (IsOption(kHistoZeroIndicator) && (saveFillStyle != 0)) {
706 SetLineColor(saveFillColor);
708 }
709 if (!swapXY) {
712 } else {
715 }
716 if (IsOption(kHistoZeroIndicator) && (saveFillStyle != 0)) {
717 SetLineColor(saveLineColor);
719 }
720 }
721
722 if (IsOption(kBox)) { // Draw a simple box
723 if (IsOption(kMedianNotched)) { // Check if we have to draw a box with notches
724 Double_t x[] = {dimLeft, dimLeft, dimLeft+fCandleWidth/3., dimLeft, dimLeft, dimRight,
725 dimRight, dimRight-fCandleWidth/3., dimRight, dimRight, dimLeft};
728 PaintBox(11, x, y, swapXY);
729 } else { // draw a simple box
730 Double_t x[] = {dimLeft, dimLeft, dimRight, dimRight, dimLeft};
732 PaintBox(5, x, y, swapXY);
733 }
734 }
735
736 if (IsOption(kAnchor)) { // Draw the anchor line
737 PaintLine(dimLeft, fWhiskerUp, dimRight, fWhiskerUp, swapXY);
738 PaintLine(dimLeft, fWhiskerDown, dimRight, fWhiskerDown, swapXY);
739 }
740
741 if (IsOption(kWhiskerAll) && !IsOption(kHistoZeroIndicator)) { // Whiskers are dashed
742 SetLineStyle(2);
746 SetLineStyle(saveLine);
748 } else if ((IsOption(kWhiskerAll) && IsOption(kHistoZeroIndicator)) || IsOption(kWhisker15) ) { // Whiskers without dashing, better whisker definition, or forced when using zero line
751 }
752
753 if (IsOption(kMedianLine)) { // Paint fMedian as a line
754 PaintLine(dimLeft, fMedian, dimRight, fMedian, swapXY);
755 } else if (IsOption(kMedianNotched)) { // Paint fMedian as a line (using notches, fMedian line is shorter)
756 PaintLine(dimLeft+fCandleWidth/3, fMedian, dimRight-fCandleWidth/3., fMedian, swapXY);
757 } else if (IsOption(kMedianCircle)) { // Paint fMedian circle
758 Double_t myMedianX[1], myMedianY[1];
759 if (!swapXY) {
760 myMedianX[0] = fPosCandleAxis;
761 myMedianY[0] = fMedian;
762 } else {
763 myMedianX[0] = fMedian;
764 myMedianY[0] = fPosCandleAxis;
765 }
766
767 Bool_t isValid = true;
768 if (doLogX) {
769 if (myMedianX[0] > 0) myMedianX[0] = TMath::Log10(myMedianX[0]); else isValid = false;
770 }
771 if (doLogY) {
772 if (myMedianY[0] > 0) myMedianY[0] = TMath::Log10(myMedianY[0]); else isValid = false;
773 }
774
775 SetMarkerStyle(24);
777
778 if (isValid) gPad->PaintPolyMarker(1,myMedianX,myMedianY); // A circle for the fMedian
779
780 SetMarkerStyle(saveMarker);
782
783 }
784
785 if (IsOption(kMeanCircle)) { // Paint fMean as a circle
786 Double_t myMeanX[1], myMeanY[1];
787 if (!swapXY) {
788 myMeanX[0] = fPosCandleAxis;
789 myMeanY[0] = fMean;
790 } else {
791 myMeanX[0] = fMean;
792 myMeanY[0] = fPosCandleAxis;
793 }
794
795 Bool_t isValid = true;
796 if (doLogX) {
797 if (myMeanX[0] > 0) myMeanX[0] = TMath::Log10(myMeanX[0]); else isValid = false;
798 }
799 if (doLogY) {
800 if (myMeanY[0] > 0) myMeanY[0] = TMath::Log10(myMeanY[0]); else isValid = false;
801 }
802
803 SetMarkerStyle(24);
805
806 if (isValid) gPad->PaintPolyMarker(1,myMeanX,myMeanY); // A circle for the fMean
807
808 SetMarkerStyle(saveMarker);
810
811 } else if (IsOption(kMeanLine)) { // Paint fMean as a dashed line
812 SetLineStyle(2);
814
815 PaintLine(dimLeft, fMean, dimRight, fMean, swapXY);
816 SetLineStyle(saveLine);
818
819 }
820
821 if (IsOption(kAnchor)) { //Draw standard anchor
822 PaintLine(dimLeft, fWhiskerDown, dimRight, fWhiskerDown, swapXY); // the lower anchor line
823 PaintLine(dimLeft, fWhiskerUp, dimRight, fWhiskerUp, swapXY); // the upper anchor line
824 }
825
826 // This is a bit complex. All values here are handled as outliers. Usually
827 // only the datapoints outside the whiskers are shown.
828 // One can show them in one row as crosses, or scattered randomly. If activated
829 // all datapoint are shown in the same way
830
831 if (GetCandleOption(5) > 0) { //Draw outliers
832 if (IsOption(kPointsAllScat)) { //Draw outliers and "all" values scattered
834 } else {
836 }
838 gPad->PaintPolyMarker(fNDrawPoints,fDrawPointsX, fDrawPointsY);
839 }
840}
841
842////////////////////////////////////////////////////////////////////////////////
843/// Return true is this option is activated in fOption
844
846 long myOpt = 9;
847 int pos = 0;
848 for (pos = 0; pos < 16; pos++) {
849 if (myOpt > opt) break;
850 else myOpt *=10;
851 }
852 myOpt /= 9;
853 int thisOpt = GetCandleOption(pos);
854
855 return ((thisOpt * myOpt) == opt);
856}
857
858////////////////////////////////////////////////////////////////////////////////
859/// Paint a box for candle.
860
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 Bool_t doLogY = (!(swapXY) && fLogY) || (swapXY && fLogX);
892 Bool_t doLogX = (!(swapXY) && fLogX) || (swapXY && fLogY);
893 if (doLogY) {
894 if (y1 > 0) y1 = TMath::Log10(y1); else return;
895 if (y2 > 0) y2 = TMath::Log10(y2); else return;
896 }
897 if (doLogX) {
898 if (x1 > 0) x1 = TMath::Log10(x1); else return;
899 if (x2 > 0) x2 = TMath::Log10(x2); else return;
900 }
901 if (!swapXY) {
902 gPad->PaintLine(x1, y1, x2, y2);
903 } else {
904 gPad->PaintLine(y1, x1, y2, x2);
905 }
906}
907
908////////////////////////////////////////////////////////////////////////////////
909/// Stream an object of class TCandle.
910
912{
913 if (R__b.IsReading()) {
914 UInt_t R__s, R__c;
915 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
916 if (R__v > 3) {
917 R__b.ReadClassBuffer(TCandle::Class(), this, R__v, R__s, R__c);
918 return;
919 }
920 } else {
921 R__b.WriteClassBuffer(TCandle::Class(),this);
922 }
923}
924
925////////////////////////////////////////////////////////////////////////////////
926/// The coordinates in the TParallelCoordVar-class are in Pad-Coordinates, so we need to convert them
927
928void TCandle::ConvertToPadCoords(Double_t minAxis, Double_t maxAxis, Double_t axisMinCoord, Double_t axisMaxCoord)
929{
930 if (!fIsCalculated) Calculate();
931 Double_t a,b;
932 if (fLogY) {
933 a = TMath::Log10(minAxis);
934 b = TMath::Log10(maxAxis/minAxis);
935 } else {
936 a = minAxis;
937 b = maxAxis-minAxis;
938 }
939
940 fMean = axisMinCoord + ((fMean-a)/b)*(axisMaxCoord-axisMinCoord);
941 fMedian = axisMinCoord + ((fMedian-a)/b)*(axisMaxCoord-axisMinCoord);
942 fMedianErr = axisMinCoord + ((fMedianErr-a)/b)*(axisMaxCoord-axisMinCoord);
943 fBoxUp = axisMinCoord + ((fBoxUp-a)/b)*(axisMaxCoord-axisMinCoord);
944 fBoxDown = axisMinCoord + ((fBoxDown-a)/b)*(axisMaxCoord-axisMinCoord);
945 fWhiskerUp = axisMinCoord + ((fWhiskerUp-a)/b)*(axisMaxCoord-axisMinCoord);
946 fWhiskerDown = axisMinCoord + ((fWhiskerDown-a)/b)*(axisMaxCoord-axisMinCoord);
947
948 for (int i = 0; i < fNDrawPoints; i++) {
949 fDrawPointsY[i] = axisMinCoord + ((fDrawPointsY[i]-a)/b)*(axisMaxCoord-axisMinCoord);
950 }
951 for (int i = 0; i < fNHistoPoints; i++) {
952 fHistoPointsY[i] = axisMinCoord + ((fHistoPointsY[i]-a)/b)*(axisMaxCoord-axisMinCoord);
953 }
954}
#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:187
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:288
#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:519
Double_t GetXmin() const
Definition: TAxis.h:134
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition: TAxis.cxx:529
Buffer base class used for serializing objects.
Definition: TBuffer.h:43
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=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:911
static void SetScaledViolin(const Bool_t vScale=true)
Static function to set scaling between violin-withs.
Definition: TCandle.cxx:237
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:845
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:670
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:928
Double_t fDrawPointsY[kNMAXPOINTS]
y-coord for every outlier, ..
Definition: TCandle.h:74
Bool_t IsViolinScaled()
Definition: TCandle.cxx:191
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:228
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:245
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:218
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:861
Double_t fBoxUp
Position of the upper box end.
Definition: TCandle.h:65
virtual ~TCandle()
TCandle default destructor.
Definition: TCandle.cxx:182
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:380
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
Bool_t IsCandleScaled()
Definition: TCandle.cxx:186
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:204
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:617
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:8812
virtual Double_t GetBinCenter(Int_t bin) const
Return bin center for 1D histogram.
Definition: TH1.cxx:9016
virtual Int_t GetQuantiles(Int_t nprobSum, Double_t *q, const Double_t *probSum=0)
Compute Quantiles for this histogram Quantile x_q of a probability distribution Function F is defined...
Definition: TH1.cxx:4585
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:7454
TAxis * GetXaxis()
Get the behaviour adopted by the object about the statoverflows. See EStatOverflows for more informat...
Definition: TH1.h:319
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:8420
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:3348
virtual TH1 * RebinX(Int_t ngroup=2, const char *newname="")
Definition: TH1.h:349
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition: TH1.cxx:9027
virtual Double_t GetEntries() const
Return the current number of entries.
Definition: TH1.cxx:4429
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:5035
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition: TH1.cxx:9038
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:3678
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:96
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:1184
Double_t Log10(Double_t x)
Definition: TMath.h:714
auto * l
Definition: textangle.C:4
auto * a
Definition: textangle.C:12