Logo ROOT   6.10/09
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 <stdlib.h>
13 #include <iostream>
14 #include "TROOT.h"
15 #include "TCandle.h"
16 #include "TClass.h"
17 #include "TPad.h"
18 #include "TRandom2.h"
19 
21 
22 /** \class TCandle
23 \ingroup BasicGraphics
24 
25 The candle plot painter class.
26 
27 Instances of this class are generated by the histograms painting
28 classes (THistPainter and THStack) when an candle plot (box plot) is drawn.
29 TCandle is the "painter class" of the box plots. Therefore it is never used
30 directly to draw a candle.
31 */
32 
33 ////////////////////////////////////////////////////////////////////////////////
34 /// TCandle default constructor.
35 
37 {
38  fIsCalculated = 0;
39  fIsRaw = 0;
40  fPosCandleAxis = 0.;
41  fCandleWidth = 1.0;
42  fMean = 0.;
43  fMedian = 0.;
44  fMedianErr = 0;
45  fBoxUp = 0.;
46  fBoxDown = 0.;
47  fWhiskerUp = 0.;
48  fWhiskerDown = 0.;
49  fNDatapoints = 0;
50  fDismiss = 0;
51  fLogX = 0;
52  fLogY = 0;
53  fNDrawPoints = 0;
54  fNHistoPoints = 0;
55  fAxisMin = 0.;
56  fAxisMax = 0.;
57  fOption = kNoOption;
58  fProj = NULL;
59  fDatapoints = 0;
60 }
61 
62 ////////////////////////////////////////////////////////////////////////////////
63 /// TCandle constructor for raw-data candles.
64 
65 TCandle::TCandle(const Double_t candlePos, const Double_t candleWidth, Long64_t n, Double_t * points)
66  : TAttLine(), TAttFill(), TAttMarker()
67 {
68  //Preliminary values only, need to be calculated before paint
69  fMean = 0;
70  fMedian = 0;
71  fMedianErr = 0;
72  fBoxUp = 0;
73  fBoxDown = 0;
74  fWhiskerUp = 0;
75  fWhiskerDown = 0;
76  fNDatapoints = n;
77  fIsCalculated = 0;
78  fIsRaw = true;
79  fPosCandleAxis = candlePos;
80  fCandleWidth = candleWidth;
82  fProj = NULL;
83  fDismiss = 0;
85  fLogX = 0;
86  fLogY = 0;
87  fNDrawPoints = 0;
88  fNHistoPoints = 0;
89  fAxisMin = 0.;
90  fAxisMax = 0.;
91 }
92 
93 ////////////////////////////////////////////////////////////////////////////////
94 /// TCandle TH1 data constructor.
95 
96 TCandle::TCandle(const Double_t candlePos, const Double_t candleWidth, TH1D *proj)
97  : TAttLine(), TAttFill(), TAttMarker()
98 {
99  //Preliminary values only, need to be calculated before paint
100  fMean = 0;
101  fMedian = 0;
102  fMedianErr = 0;
103  fBoxUp = 0;
104  fBoxDown = 0;
105  fWhiskerUp = 0;
106  fWhiskerDown = 0;
107  fNDatapoints = 0;
108  fIsCalculated = 0;
109  fIsRaw = 0;
110  fPosCandleAxis = candlePos;
111  fCandleWidth = candleWidth;
112  fDatapoints = 0;
113  fProj = proj;
114  fDismiss = 0;
115  fOption = kNoOption;
116  fLogX = 0;
117  fLogY = 0;
118  fNDrawPoints = 0;
119  fNHistoPoints = 0;
120  fAxisMin = 0.;
121  fAxisMax = 0.;
122 }
123 
124 ////////////////////////////////////////////////////////////////////////////////
125 /// TCandle default destructor.
126 
128  if (fIsRaw && fProj) delete fProj;
129 }
130 
131 ////////////////////////////////////////////////////////////////////////////////
132 /// Parsing of the option-string.
133 /// The option-string will be empty at the end (by-reference).
134 
135 int TCandle::ParseOption(char * opt) {
136  fOption = kNoOption;
137  char *l;
138 
139  l = strstr(opt,"CANDLE");
140  if (l) {
141  const CandleOption fallbackCandle = (CandleOption)(kBox + kMedianLine + kMeanCircle + kWhiskerAll + kAnchor);
142 
143  char direction = ' ';
144  char preset = ' ';
145 
146  if (l[6] >= 'A' && l[6] <= 'Z') direction = l[6];
147  if (l[6] >= '1' && l[6] <= '9') preset = l[6];
148  if (l[7] >= 'A' && l[7] <= 'Z' && preset != ' ') direction = l[7];
149  if (l[7] >= '1' && l[7] <= '9' && direction != ' ') preset = l[7];
150 
151  if (direction == 'X' || direction == 'V') { /* nothing */ }
152  if (direction == 'Y' || direction == 'H') { fOption = (CandleOption)(fOption + kHorizontal); }
153  if (preset == '1') //Standard candle using old candle-definition
154  fOption = (CandleOption)(fOption + fallbackCandle);
155  else if (preset == '2') //New standard candle with better whisker definition + outlier
157  else if (preset == '3') //Like candle2 but with a fMean as a circle
159  else if (preset == '4') //Like candle3 but showing the uncertainty of the fMedian as well
161  else if (preset == '5') //Like candle2 but showing all datapoints
163  else if (preset == '6') //Like candle2 but showing all datapoints scattered
165  else if (preset != ' ') //For all other presets not implemented yet used fallback candle
166  fOption = (CandleOption)(fOption + fallbackCandle);
167 
168  if (preset != ' ' && direction != ' ')
169  strncpy(l," ",8);
170  else if (preset != ' ' || direction != ' ')
171  strncpy(l," ",7);
172  else
173  strncpy(l," ",6);
174 
175  Bool_t useIndivOption = false;
176 
177  if (preset == ' ') { // Check if the user wants to set the properties individually
178  char *brOpen = strstr(opt,"(");
179  char *brClose = strstr(opt,")");
180  char indivOption[32];
181  if (brOpen && brClose) {
182  useIndivOption = true;
183  bool isHorizontal = IsHorizontal();
184  strlcpy(indivOption, brOpen, brClose-brOpen+2); //Now the string "(....)" including brackets is in this array
185  sscanf(indivOption,"(%d)", (int*) &fOption);
186  if (isHorizontal) {fOption = (CandleOption)(fOption + kHorizontal);}
187  strncpy(brOpen," ",brClose-brOpen+1); //Cleanup
188 
189  }
190  }
191  //Handle option "CANDLE" ,"CANDLEX" or "CANDLEY" to behave like "CANDLEX1" or "CANDLEY1"
192  if (!useIndivOption && !fOption ) {
193  fOption = fallbackCandle;
194  }
195  }
196 
197  l = strstr(opt,"VIOLIN");
198  if (l) {
200 
201  char direction = ' ';
202  char preset = ' ';
203 
204  if (l[6] >= 'A' && l[6] <= 'Z') direction = l[6];
205  if (l[6] >= '1' && l[6] <= '9') preset = l[6];
206  if (l[7] >= 'A' && l[7] <= 'Z' && preset != ' ') direction = l[7];
207  if (l[7] >= '1' && l[7] <= '9' && direction != ' ') preset = l[7];
208 
209  if (direction == 'X' || direction == 'V') { /* nothing */ }
210  if (direction == 'Y' || direction == 'H') { fOption = (CandleOption)(fOption + kHorizontal); }
211  if (preset == '1') //Standard candle using old candle-definition
212  fOption = (CandleOption)(fOption + fallbackCandle);
213  else if (preset == '2') //New standard candle with better whisker definition + outlier
215  else if (preset != ' ') //For all other presets not implemented yet used fallback candle
216  fOption = (CandleOption)(fOption + fallbackCandle);
217 
218  if (preset != ' ' && direction != ' ')
219  strncpy(l," ",8);
220  else if (preset != ' ' || direction != ' ')
221  strncpy(l," ",7);
222  else
223  strncpy(l," ",6);
224 
225  Bool_t useIndivOption = false;
226 
227  if (preset == ' ') { // Check if the user wants to set the properties individually
228  char *brOpen = strstr(opt,"(");
229  char *brClose = strstr(opt,")");
230  char indivOption[32];
231  if (brOpen && brClose) {
232  useIndivOption = true;
233  bool isHorizontal = IsHorizontal();
234  strlcpy(indivOption, brOpen, brClose-brOpen +2); //Now the string "(....)" including brackets is in this array
235  sscanf(indivOption,"(%d)", (int*) &fOption);
236  if (isHorizontal) {fOption = (CandleOption)(fOption + kHorizontal);}
237  strncpy(brOpen," ",brClose-brOpen+1); //Cleanup
238 
239  }
240  }
241  //Handle option "VIOLIN" ,"VIOLINX" or "VIOLINY" to behave like "VIOLINX1" or "VIOLINY1"
242  if (!useIndivOption && !fOption ) {
243  fOption = fallbackCandle;
244  }
245  }
246 
247  fIsCalculated = false;
248  return fOption;
249 
250 }
251 
252 ////////////////////////////////////////////////////////////////////////////////
253 /// Calculates all values needed by the candle definition depending on the
254 /// candle options.
255 
257  //Reset everything
258  fNDrawPoints = 0;
259  fNHistoPoints = 0;
260 
261  Bool_t swapXY = IsOption(kHorizontal);
262  Bool_t doLogY = (!(swapXY) && fLogY) || (swapXY && fLogX);
263  Bool_t doLogX = (!(swapXY) && fLogX) || (swapXY && fLogY);
264 
265  //Will be min and max values of raw-data
266  Double_t min = 1e15;
267  Double_t max = -1e15;
268 
269  // Determining the quantiles
270  Double_t *prob = new Double_t[5];
271  prob[0]=1E-15; prob[1]=0.25; prob[2]=0.5; prob[3]=0.75; prob[4]=1-1E-15;
272  Double_t *quantiles = new Double_t[5];
273  quantiles[0]=0.; quantiles[1]=0.; quantiles[2] = 0.; quantiles[3] = 0.; quantiles[4] = 0.;
274  if (!fIsRaw && fProj) { //Need a calculation for a projected histo
275  if (((IsOption(kHistoLeft)) || (IsOption(kHistoRight)) || (IsOption(kHistoViolin))) && fProj->GetNbinsX() > 500) {
276  // When using the histooption the number of bins of the projection is
277  // limited because of the array space defined by kNMAXPOINTS.
278  // So the histo is rebinned, that it can be displayed at any time.
279  // Finer granularity is not useful anyhow
280  int divideBy = ((fProj->GetNbinsX() - 1)/((kNMAXPOINTS-10)/4))+1;
281  fProj->RebinX(divideBy);
282  }
283  fProj->GetQuantiles(5, quantiles, prob);
284  } else { //Need a calculation for a raw-data candle
286  }
287 
288  // Check if the quantiles are valid, seems the under- and overflow is taken
289  // into account as well, we need to ignore this!
290  if (quantiles[0] >= quantiles[4] ||
291  quantiles[1] >= quantiles[3]) {
292  delete [] prob;
293  delete [] quantiles;
294  return;
295  }
296 
297  // Definition of the candle in the standard case
298  fBoxUp = quantiles[3];
299  fBoxDown = quantiles[1];
300  fWhiskerUp = quantiles[4]; //Standard case
301  fWhiskerDown = quantiles[0]; //Standard case
302  fMedian = quantiles[2];
303  Double_t iqr = fBoxUp-fBoxDown;
304  Int_t nOutliers = 0;
305 
306  if (IsOption(kWhisker15)) { // Improved whisker definition, with 1.5*iqr
307  if (!fIsRaw && fProj) { //Need a calculation for a projected histo
308  int bin = fProj->FindBin(fBoxDown-1.5*iqr);
309  // extending only to the lowest data value within this range
310  while (fProj->GetBinContent(bin) == 0 && bin <= fProj->GetNbinsX()) bin++;
312 
313  bin = fProj->FindBin(fBoxUp+1.5*iqr);
314  while (fProj->GetBinContent(bin) == 0 && bin >= 1) bin--;
315  fWhiskerUp = fProj->GetBinCenter(bin);
316  } else { //Need a calculation for a raw-data candle
319 
320  //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
321  for (Long64_t i = 0; i < fNDatapoints; ++i) {
322  Double_t myData = fDatapoints[i];
323  if (myData > fWhiskerUp && myData <= fBoxUp + 1.5*iqr) fWhiskerUp = myData;
324  if (myData < fWhiskerDown && myData >= fBoxDown - 1.5*iqr) fWhiskerDown = myData;
325  }
326  }
327  }
328 
329  if (!fIsRaw && fProj) { //Need a calculation for a projected histo
330  fMean = fProj->GetMean();
331  fMedianErr = 1.57*iqr/sqrt(fProj->GetEntries());
332  fAxisMin = fProj->GetXaxis()->GetXmin();
333  fAxisMax = fProj->GetXaxis()->GetXmax();
334  } else { //Need a calculation for a raw-data candle
335  //Calculate the Mean
336  fMean = 0;
337  for (Long64_t i = 0; i < fNDatapoints; ++i) {
338  fMean += fDatapoints[i];
339  if (fDatapoints[i] < min) min = fDatapoints[i];
340  if (fDatapoints[i] > max) max = fDatapoints[i];
341  if (fDatapoints[i] < fWhiskerDown || fDatapoints[i] > fWhiskerUp) nOutliers++;
342  }
343  fMean /= fNDatapoints;
344  fMedianErr = 1.57*iqr/sqrt(fNDatapoints);
345  }
346 
347  delete [] prob;
348  delete [] quantiles;
349 
350  //Doing the outliers and other single points to show
351  if (GetCandleOption(5) > 0) { //Draw outliers
352  TRandom2 random;
353  const int maxOutliers = kNMAXPOINTS;
354  Double_t myScale = 1.;
355  if (!fIsRaw && fProj) { //Need a calculation for a projected histo
356  if (fProj->GetEntries() > maxOutliers/2) myScale = fProj->GetEntries()/(maxOutliers/2.);
357  fNDrawPoints = 0;
358  for (int bin = 0; bin < fProj->GetNbinsX(); bin++) {
359  // Either show them only outside the whiskers, or all of them
360  if (fProj->GetBinContent(bin) > 0 && (fProj->GetBinCenter(bin) < fWhiskerDown || fProj->GetBinCenter(bin) > fWhiskerUp || (GetCandleOption(5) > 1)) ) {
361  Double_t scaledBinContent = fProj->GetBinContent(bin)/myScale;
362  if (scaledBinContent >0 && scaledBinContent < 1) scaledBinContent = 1; //Outliers have a typical bin content between 0 and 1, when scaling they would disappear
363  for (int j=0; j < (int)scaledBinContent; j++) {
364  if (fNDrawPoints > maxOutliers) break;
365  if (IsOption(kPointsAllScat)) { //Draw outliers and "all" values scattered
368  } else { //Draw them in the "candle line"
370  if ((int)scaledBinContent == 1) //If there is only one datapoint available put it in the middle of the bin
372  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
374  }
375  if (swapXY) {
376  //Swap X and Y
377  Double_t keepCurrently;
378  keepCurrently = fDrawPointsX[fNDrawPoints];
380  fDrawPointsY[fNDrawPoints] = keepCurrently;
381  }
382  // Continue fMeans, that fNDrawPoints is not increased, so that value will not be shown
383  if (doLogX) {
385  }
386  if (doLogY) {
388  }
389  fNDrawPoints++;
390  }
391  }
392  if (fNDrawPoints > maxOutliers) { //Should never happen, due to myScale!!!
393  Error ("PaintCandlePlot","Not possible to draw all outliers.");
394  break;
395  }
396  }
397  } else { //Raw data candle
398  //If only outliers are shown, calculate myScale only based on nOutliers, use fNDatapoints (all) instead
399  if (IsOption(kPointsOutliers) && nOutliers > maxOutliers/2) {
400  myScale = nOutliers/(maxOutliers/2.);
401  } else {
402  if (fNDatapoints > maxOutliers/2) myScale = fNDatapoints/(maxOutliers/2.);
403  }
404  fNDrawPoints = 0;
405  for (int i = 0; i < fNDatapoints; i++ ) {
406  Double_t myData = fDatapoints[i];
407  Double_t maxScatter = (fWhiskerUp-fWhiskerDown)/100;
408  if (!(i % (int) myScale == 0 )) continue; //If the amount of data is too large take only every 2nd or 3rd to reduce the amount
409  // Either show them only outside the whiskers, or all of them
410  if (myData < fWhiskerDown || myData > fWhiskerUp || (GetCandleOption(5) > 1)) {
411  if (IsOption(kPointsAllScat)) { //Draw outliers and "all" values scattered
413  fDrawPointsY[fNDrawPoints] = myData + (random.Rndm() - 0.5)*maxScatter; //random +- 0.5 of candle-height
414  } else { //Draw them in the "candle line"
416  fDrawPointsY[fNDrawPoints] = myData + (random.Rndm() - 0.5)*maxScatter; //random +- 0.5 of candle-height
417  }
418  if (swapXY) {
419  //Swap X and Y
420  Double_t keepCurrently;
421  keepCurrently = fDrawPointsX[fNDrawPoints];
423  fDrawPointsY[fNDrawPoints] = keepCurrently;
424  }
425  // Continue fMeans, that fNDrawPoints is not increased, so that value will not be shown
426  if (doLogX) {
428  else continue;
429  }
430  if (doLogY) {
432  else continue;
433  }
434  fNDrawPoints++;
435  if (fNDrawPoints > maxOutliers) { //Should never happen, due to myScale!!!
436  Error ("PaintCandlePlotRaw","Not possible to draw all outliers.");
437  break;
438  }
439  }
440  }
441  }
442  }
443 
445  //We are starting with kHistoRight, left will be modified from right later
446  if (fIsRaw) { //This is a raw-data candle
447  if (!fProj) {
448  fProj = new TH1D("hpa","hpa",100,min,max+0.0001*(max-min));
449  for (Long64_t i = 0; i < fNDatapoints; ++i) {
450  fProj->Fill(fDatapoints[i]);
451  }
452  }
453  }
454 
455  fNHistoPoints = 0;
456  Double_t maxContent = fProj->GetMaximum();
457  Double_t maxHistoHeight = fCandleWidth*0.8;
458  if (IsOption(kHistoViolin)) maxHistoHeight *= 0.5;
459 
460  bool isFirst = true;
461  int lastNonZero = 0;
462  for (int bin = 1; bin <= fProj->GetNbinsX(); bin++) {
463  if (isFirst) {
464  if (fProj->GetBinContent(bin) > 0) {
467  if (doLogX) {
469  }
470  if (doLogY) {
472  }
473  fNHistoPoints++;
474  isFirst = false;
475  } else {
476  continue;
477  }
478  }
479  Double_t myBinValue = fProj->GetBinContent(bin);
480  fHistoPointsX[fNHistoPoints] = fPosCandleAxis + myBinValue/maxContent*maxHistoHeight;
482  fNHistoPoints++;
483  fHistoPointsX[fNHistoPoints] = fPosCandleAxis + myBinValue/maxContent*maxHistoHeight;
485  if (doLogX) {
488  }
489  if (doLogY) {
492  }
493 
494  fNHistoPoints++;
495  if (fProj->GetBinContent(bin) > 0) lastNonZero = fNHistoPoints;
496  }
497 
500  fNHistoPoints = lastNonZero+1; //+1 so that the line down to 0 is added as well
501 
502  if (IsOption(kHistoLeft)) {
503  for (int i = 0; i < fNHistoPoints; i++) {
505  }
506  }
507  if (IsOption(kHistoViolin)) {
508  for (int i = 0; i < fNHistoPoints; i++) {
509  fHistoPointsX[fNHistoPoints + i] = 2*fPosCandleAxis - fHistoPointsX[fNHistoPoints -i-1];
510  fHistoPointsY[fNHistoPoints + i] = fHistoPointsY[fNHistoPoints -i-1];
511  }
512  fNHistoPoints *= 2;
513  }
514  }
515 
516 
517  fIsCalculated = true;
518 }
519 
520 ////////////////////////////////////////////////////////////////////////////////
521 /// Paint one candle with its current attributes.
522 
524 {
525  //If something was changed before, we need to recalculate some values
526  if (!fIsCalculated) Calculate();
527 
528  // Save the attributes as they were set originally
529  Style_t saveLine = GetLineStyle();
530  Style_t saveMarker = GetMarkerStyle();
531  Style_t saveFillStyle = GetFillStyle();
532  Style_t saveFillColor = GetFillColor();
533  Style_t saveLineColor = GetLineColor();
534 
535  Double_t dimLeft = fPosCandleAxis-0.5*fCandleWidth;
536  Double_t dimRight = fPosCandleAxis+0.5*fCandleWidth;
537 
541 
542  Bool_t swapXY = IsOption(kHorizontal);
543  Bool_t doLogY = (!(swapXY) && fLogY) || (swapXY && fLogX);
544  Bool_t doLogX = (!(swapXY) && fLogX) || (swapXY && fLogY);
545 
546  // From now on this is real painting only, no calculations anymore
547 
549  SetLineColor(saveFillColor);
552  SetLineColor(saveLineColor);
554  }
555 
556 
558  if (IsOption(kHistoZeroIndicator) && (saveFillStyle != 0)) {
559  SetLineColor(saveFillColor);
561  }
562  if (!swapXY) {
563  gPad->PaintFillArea(fNHistoPoints, fHistoPointsX, fHistoPointsY);
564  gPad->PaintPolyLine(fNHistoPoints, fHistoPointsX, fHistoPointsY);
565  } else {
566  gPad->PaintFillArea(fNHistoPoints, fHistoPointsY, fHistoPointsX);
567  gPad->PaintPolyLine(fNHistoPoints, fHistoPointsY, fHistoPointsX);
568  }
569  if (IsOption(kHistoZeroIndicator) && (saveFillStyle != 0)) {
570  SetLineColor(saveLineColor);
572  }
573  }
574 
575  if (IsOption(kBox)) { // Draw a simple box
576  if (IsOption(kMedianNotched)) { // Check if we have to draw a box with notches
577  Double_t x[] = {dimLeft, dimLeft, dimLeft+fCandleWidth/3., dimLeft, dimLeft, dimRight,
578  dimRight, dimRight-fCandleWidth/3., dimRight, dimRight, dimLeft};
580  fMedian+fMedianErr, fMedian, fMedian-fMedianErr, fBoxDown, fBoxDown};
581  PaintBox(11, x, y, swapXY);
582  } else { // draw a simple box
583  Double_t x[] = {dimLeft, dimLeft, dimRight, dimRight, dimLeft};
584  Double_t y[] = {fBoxDown, fBoxUp, fBoxUp, fBoxDown, fBoxDown};
585  PaintBox(5, x, y, swapXY);
586  }
587  }
588 
589  if (IsOption(kAnchor)) { // Draw the anchor line
590  PaintLine(dimLeft, fWhiskerUp, dimRight, fWhiskerUp, swapXY);
591  PaintLine(dimLeft, fWhiskerDown, dimRight, fWhiskerDown, swapXY);
592  }
593 
594  if (IsOption(kWhiskerAll) && !IsOption(kHistoZeroIndicator)) { // Whiskers are dashed
595  SetLineStyle(2);
599  SetLineStyle(saveLine);
601  } else if ((IsOption(kWhiskerAll) && IsOption(kHistoZeroIndicator)) || IsOption(kWhisker15) ) { // Whiskers without dashing, better whisker definition, or forced when using zero line
604  }
605 
606  if (IsOption(kMedianLine)) { // Paint fMedian as a line
607  PaintLine(dimLeft, fMedian, dimRight, fMedian, swapXY);
608  } else if (IsOption(kMedianNotched)) { // Paint fMedian as a line (using notches, fMedian line is shorter)
609  PaintLine(dimLeft+fCandleWidth/3, fMedian, dimRight-fCandleWidth/3., fMedian, swapXY);
610  } else if (IsOption(kMedianCircle)) { // Paint fMedian circle
611  Double_t myMedianX[1], myMedianY[1];
612  if (!swapXY) {
613  myMedianX[0] = fPosCandleAxis;
614  myMedianY[0] = fMedian;
615  } else {
616  myMedianX[0] = fMedian;
617  myMedianY[0] = fPosCandleAxis;
618  }
619 
620  Bool_t isValid = true;
621  if (doLogX) {
622  if (myMedianX[0] > 0) myMedianX[0] = TMath::Log10(myMedianX[0]); else isValid = false;
623  }
624  if (doLogY) {
625  if (myMedianY[0] > 0) myMedianY[0] = TMath::Log10(myMedianY[0]); else isValid = false;
626  }
627 
628  SetMarkerStyle(24);
630 
631  if (isValid) gPad->PaintPolyMarker(1,myMedianX,myMedianY); // A circle for the fMedian
632 
633  SetMarkerStyle(saveMarker);
635 
636  }
637 
638  if (IsOption(kMeanCircle)) { // Paint fMean as a circle
639  Double_t myMeanX[1], myMeanY[1];
640  if (!swapXY) {
641  myMeanX[0] = fPosCandleAxis;
642  myMeanY[0] = fMean;
643  } else {
644  myMeanX[0] = fMean;
645  myMeanY[0] = fPosCandleAxis;
646  }
647 
648  Bool_t isValid = true;
649  if (doLogX) {
650  if (myMeanX[0] > 0) myMeanX[0] = TMath::Log10(myMeanX[0]); else isValid = false;
651  }
652  if (doLogY) {
653  if (myMeanY[0] > 0) myMeanY[0] = TMath::Log10(myMeanY[0]); else isValid = false;
654  }
655 
656  SetMarkerStyle(24);
658 
659  if (isValid) gPad->PaintPolyMarker(1,myMeanX,myMeanY); // A circle for the fMean
660 
661  SetMarkerStyle(saveMarker);
663 
664  } else if (IsOption(kMeanLine)) { // Paint fMean as a dashed line
665  SetLineStyle(2);
667 
668  PaintLine(dimLeft, fMean, dimRight, fMean, swapXY);
669  SetLineStyle(saveLine);
671 
672  }
673 
674  if (IsOption(kAnchor)) { //Draw standard anchor
675  PaintLine(dimLeft, fWhiskerDown, dimRight, fWhiskerDown, swapXY); // the lower anchor line
676  PaintLine(dimLeft, fWhiskerUp, dimRight, fWhiskerUp, swapXY); // the upper anchor line
677  }
678 
679  // This is a bit complex. All values here are handled as outliers. Usually
680  // only the datapoints outside the whiskers are shown.
681  // One can show them in one row as crosses, or scattered randomly. If activated
682  // all datapoint are shown in the same way
683 
684  if (GetCandleOption(5) > 0) { //Draw outliers
685  if (IsOption(kPointsAllScat)) { //Draw outliers and "all" values scattered
686  SetMarkerStyle(0);
687  } else {
688  SetMarkerStyle(5);
689  }
691  gPad->PaintPolyMarker(fNDrawPoints,fDrawPointsX, fDrawPointsY);
692  }
693 }
694 
695 ////////////////////////////////////////////////////////////////////////////////
696 /// Return true is this option is activated in fOption
697 
699  long myOpt = 9;
700  int pos = 0;
701  for (pos = 0; pos < 16; pos++) {
702  if (myOpt > opt) break;
703  else myOpt *=10;
704  }
705  myOpt /= 9;
706  int thisOpt = GetCandleOption(pos);
707 
708  return ((thisOpt * myOpt) == opt);
709 }
710 
711 ////////////////////////////////////////////////////////////////////////////////
712 /// Paint a box for candle.
713 
714 void TCandle::PaintBox(Int_t nPoints, Double_t *x, Double_t *y, Bool_t swapXY)
715 {
716  Bool_t doLogY = (!(swapXY) && fLogY) || (swapXY && fLogX);
717  Bool_t doLogX = (!(swapXY) && fLogX) || (swapXY && fLogY);
718  if (doLogY) {
719  for (int i=0; i<nPoints; i++) {
720  if (y[i] > 0) y[i] = TMath::Log10(y[i]);
721  else return;
722  }
723  }
724  if (doLogX) {
725  for (int i=0; i<nPoints; i++) {
726  if (x[i] > 0) x[i] = TMath::Log10(x[i]);
727  else return;
728  }
729  }
730  if (!swapXY) {
731  gPad->PaintFillArea(nPoints, x, y);
732  gPad->PaintPolyLine(nPoints, x, y);
733  } else {
734  gPad->PaintFillArea(nPoints, y, x);
735  gPad->PaintPolyLine(nPoints, y, x);
736  }
737 }
738 
739 ////////////////////////////////////////////////////////////////////////////////
740 /// Paint a line for candle.
741 
743 {
744  Bool_t doLogY = (!(swapXY) && fLogY) || (swapXY && fLogX);
745  Bool_t doLogX = (!(swapXY) && fLogX) || (swapXY && fLogY);
746  if (doLogY) {
747  if (y1 > 0) y1 = TMath::Log10(y1); else return;
748  if (y2 > 0) y2 = TMath::Log10(y2); else return;
749  }
750  if (doLogX) {
751  if (x1 > 0) x1 = TMath::Log10(x1); else return;
752  if (x2 > 0) x2 = TMath::Log10(x2); else return;
753  }
754  if (!swapXY) {
755  gPad->PaintLine(x1, y1, x2, y2);
756  } else {
757  gPad->PaintLine(y1, x1, y2, x2);
758  }
759 }
760 
761 ////////////////////////////////////////////////////////////////////////////////
762 /// Stream an object of class TCandle.
763 
764 void TCandle::Streamer(TBuffer &R__b)
765 {
766  if (R__b.IsReading()) {
767  UInt_t R__s, R__c;
768  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
769  if (R__v > 3) {
770  R__b.ReadClassBuffer(TCandle::Class(), this, R__v, R__s, R__c);
771  return;
772  }
773  } else {
774  R__b.WriteClassBuffer(TCandle::Class(),this);
775  }
776 }
777 
778 ////////////////////////////////////////////////////////////////////////////////
779 /// The coordinates in the TParallelCoordVar-class are in Pad-Coordinates, so we need to convert them
780 
781 void TCandle::ConvertToPadCoords(Double_t minAxis, Double_t maxAxis, Double_t axisMinCoord, Double_t axisMaxCoord)
782 {
783  if (!fIsCalculated) Calculate();
784  Double_t a,b;
785  if (fLogY) {
786  a = TMath::Log10(minAxis);
787  b = TMath::Log10(maxAxis/minAxis);
788  } else {
789  a = minAxis;
790  b = maxAxis-minAxis;
791  }
792 
793  fMean = axisMinCoord + ((fMean-a)/b)*(axisMaxCoord-axisMinCoord);
794  fMedian = axisMinCoord + ((fMedian-a)/b)*(axisMaxCoord-axisMinCoord);
795  fMedianErr = axisMinCoord + ((fMedianErr-a)/b)*(axisMaxCoord-axisMinCoord);
796  fBoxUp = axisMinCoord + ((fBoxUp-a)/b)*(axisMaxCoord-axisMinCoord);
797  fBoxDown = axisMinCoord + ((fBoxDown-a)/b)*(axisMaxCoord-axisMinCoord);
798  fWhiskerUp = axisMinCoord + ((fWhiskerUp-a)/b)*(axisMaxCoord-axisMinCoord);
799  fWhiskerDown = axisMinCoord + ((fWhiskerDown-a)/b)*(axisMaxCoord-axisMinCoord);
800 
801  for (int i = 0; i < fNDrawPoints; i++) {
802  fDrawPointsY[i] = axisMinCoord + ((fDrawPointsY[i]-a)/b)*(axisMaxCoord-axisMinCoord);
803  }
804  for (int i = 0; i < fNHistoPoints; i++) {
805  fHistoPointsY[i] = axisMinCoord + ((fHistoPointsY[i]-a)/b)*(axisMaxCoord-axisMinCoord);
806  }
807 }
Bool_t IsReading() const
Definition: TBuffer.h:81
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:3441
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition: TH1.cxx:3126
TCandle()
TCandle default constructor.
Definition: TCandle.cxx:36
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:7666
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
virtual Double_t GetBinCenter(Int_t bin) const
Return bin center for 1D histogram.
Definition: TH1.cxx:8253
Double_t fMedian
Position of the median.
Definition: TCandle.h:60
long long Long64_t
Definition: RtypesCore.h:69
short Style_t
Definition: RtypesCore.h:76
Bool_t IsHorizontal()
Definition: TCandle.h:105
short Version_t
Definition: RtypesCore.h:61
If this bit is not set it is vertical.
Definition: TCandle.h:46
Double_t fWhiskerUp
Position of the upper whisker end.
Definition: TCandle.h:64
bool IsOption(CandleOption opt)
Return true is this option is activated in fOption.
Definition: TCandle.cxx:698
const char Option_t
Definition: RtypesCore.h:62
Random number generator class based on the maximally quidistributed combined Tausworthe generator by ...
Definition: TRandom2.h:27
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4639
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:4191
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
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:6763
int ParseOption(char *optin)
Parsing of the option-string.
Definition: TCandle.cxx:135
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TArc * a
Definition: textangle.C:12
Double_t fAxisMin
The Minimum which is visible by the axis (used by zero indicator)
Definition: TCandle.h:82
Double_t * fDatapoints
position of all Datapoints within this candle
Definition: TCandle.h:67
Double_t fDrawPointsX[kNMAXPOINTS]
x-coord for every outlier, ..
Definition: TCandle.h:70
#define NULL
Definition: RtypesCore.h:88
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition: TH1.cxx:8264
virtual void Modify()
Change current line attributes if necessary.
Definition: TAttLine.cxx:232
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:742
Double_t fMean
Position of the mean.
Definition: TCandle.h:59
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition: TAttMarker.h:32
Marker Attributes class.
Definition: TAttMarker.h:19
virtual Style_t GetLineStyle() const
Return the line style.
Definition: TAttLine.h:34
double sqrt(double)
CandleOption
Definition: TCandle.h:28
Double_t GetXmin() const
Definition: TAxis.h:133
static const double x2[5]
Fill Area Attributes class.
Definition: TAttFill.h:19
bool fIsCalculated
Definition: TCandle.h:52
Double_t x[n]
Definition: legend1.C:17
void Class()
Definition: Class.C:29
Double_t fCandleWidth
The candle width.
Definition: TCandle.h:57
int fLogX
make the candle appear logx-like
Definition: TCandle.h:79
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 Parameters: x -the data sample n ...
Definition: TMath.cxx:1177
virtual void Modify()
Change current fill area attributes if necessary.
Definition: TAttFill.cxx:209
void PaintBox(Int_t nPoints, Double_t *x, Double_t *y, Bool_t swapXY)
Paint a box for candle.
Definition: TCandle.cxx:714
Double_t Log10(Double_t x)
Definition: TMath.h:652
Double_t fDrawPointsY[kNMAXPOINTS]
y-coord for every outlier, ..
Definition: TCandle.h:71
void Error(const char *location, const char *msgfmt,...)
Double_t fHistoPointsX[kNMAXPOINTS]
x-coord for the polyline of the histo
Definition: TCandle.h:74
Double_t fBoxDown
Position of the lower box end.
Definition: TCandle.h:63
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:781
point * points
Definition: X3DBuffer.c:20
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition: TAttLine.h:40
virtual void Modify()
Change current marker attributes if necessary.
Definition: TAttMarker.cxx:219
Double_t fBoxUp
Position of the upper box end.
Definition: TCandle.h:62
int fLogY
make the candle appear logy-like
Definition: TCandle.h:80
The candle plot painter class.
Definition: TCandle.h:25
unsigned int UInt_t
Definition: RtypesCore.h:42
void Calculate()
Calculates all values needed by the candle definition depending on the candle options.
Definition: TCandle.cxx:256
Double_t fAxisMax
The Maximum which is visible by the axis (used by zero indicator)
Definition: TCandle.h:83
TLine * l
Definition: textangle.C:4
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition: TAttMarker.h:40
tomato 1-D histogram with a double per channel (see TH1 documentation)}
Definition: TH1.h:594
constexpr Double_t E()
Definition: TMath.h:74
virtual void Paint(Option_t *option="")
Paint one candle with its current attributes.
Definition: TCandle.cxx:523
const Bool_t kFALSE
Definition: RtypesCore.h:92
virtual Color_t GetLineColor() const
Return the line color.
Definition: TAttLine.h:33
bool fDismiss
True if the candle cannot be painted.
Definition: TCandle.h:54
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition: TH1.cxx:8275
virtual Double_t Rndm()
TausWorth generator from L&#39;Ecuyer, uses as seed 3x32bits integers Use a mask of 0xffffffffUL to make ...
Definition: TRandom2.cxx:58
static const double x1[5]
#define ClassImp(name)
Definition: Rtypes.h:336
virtual TH1 * RebinX(Int_t ngroup=2, const char *newname="")
Definition: TH1.h:328
TH1D * fProj
Definition: TCandle.h:53
double Double_t
Definition: RtypesCore.h:55
CandleOption fOption
Setting the style of the candle.
Definition: TCandle.h:78
Double_t fMedianErr
The size of the notch.
Definition: TCandle.h:61
Double_t y[n]
Definition: legend1.C:17
Double_t fHistoPointsY[kNMAXPOINTS]
y-coord for the polyline of the histo
Definition: TCandle.h:75
virtual Color_t GetFillColor() const
Return the fill area color.
Definition: TAttFill.h:30
virtual Double_t GetEntries() const
Return the current number of entries.
Definition: TH1.cxx:4054
int GetCandleOption(const int pos)
Definition: TCandle.h:87
Long64_t fNDrawPoints
max number of outliers or other point to be shown
Definition: TCandle.h:72
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition: TAttLine.h:42
Double_t fWhiskerDown
Position of the lower whisker end.
Definition: TCandle.h:65
Double_t fPosCandleAxis
x-pos for a vertical candle
Definition: TCandle.h:56
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
const Int_t kNMAXPOINTS
Definition: TCandle.h:23
THist< 1, double, THistStatContent, THistStatUncertainty > TH1D
Definition: THist.hxx:310
#define gPad
Definition: TVirtualPad.h:284
virtual ~TCandle()
TCandle default destructor.
Definition: TCandle.cxx:127
bool fIsRaw
0: for TH1 projection, 1: using raw data
Definition: TCandle.h:51
virtual Int_t GetNbinsX() const
Definition: TH1.h:277
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition: TAttFill.h:31
int fNHistoPoints
Definition: TCandle.h:76
Double_t GetXmax() const
Definition: TAxis.h:134
const Int_t n
Definition: legend1.C:16
Line Attributes class.
Definition: TAttLine.h:18
TAxis * GetXaxis()
Definition: TH1.h:300
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
Long64_t fNDatapoints
Number of Datapoints within this candle.
Definition: TCandle.h:68