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 "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 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
bool Bool_t
Definition RtypesCore.h:63
short Version_t
Definition RtypesCore.h:65
constexpr 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:377
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:197
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
#define gPad
#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 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.
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:32
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
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