Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGaxis.cxx
Go to the documentation of this file.
1// @(#)root/graf:$Id$
2// Author: Rene Brun, Olivier Couet 12/12/94
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#include <cstring>
14#include <ctime>
15#include <cmath>
16#include <iostream>
17
18#include "TROOT.h"
19#include "TBuffer.h"
20#include "TGaxis.h"
21#include "TAxisModLab.h"
22#include "TVirtualPad.h"
23#include "TLine.h"
24#include "TArrow.h"
25#include "TLatex.h"
26#include "TStyle.h"
27#include "TF1.h"
28#include "TAxis.h"
29#include "THashList.h"
30#include "TObject.h"
31#include "TMath.h"
32#include "THLimitsFinder.h"
33#include "TColor.h"
34#include "TTimeStamp.h"
35#include "strlcpy.h"
36#include "snprintf.h"
37
38const Int_t kHori = BIT(9);
39
40
41/** \class TGaxis
42\ingroup BasicGraphics
43
44The axis painter class.
45
46Instances of this class are generated by the histograms and graphs painting
47classes when `TAxis` are drawn. `TGaxis` is the "painter class" of
48`TAxis`. Therefore it is mainly used via `TAxis`, even if is some
49occasion it can be used directly to draw an axis which is not part of a graph
50or an instance. For instance to draw an extra scale on a plot.
51
52- [Basic definition](\ref GA00)
53- [Definition with a function](\ref GA01)
54- [Logarithmic axis](\ref GA02)
55- [Blank axis](\ref GA03)
56- [Arrow on axis](\ref GA03a)
57- [Tick marks' orientation](\ref GA04)
58- [Tick marks' size](\ref GA05)
59- [Labels' positioning](\ref GA06)
60- [Labels' orientation](\ref GA07)
61- [Labels' position on tick marks](\ref GA08)
62- [Labels' format](\ref GA09)
63- [Alphanumeric labels](\ref GA10)
64- [Changing axis labels](\ref GA10a)
65- [Number of divisions optimisation](\ref GA11)
66- [Maximum Number of Digits for the axis labels](\ref GA12)
67- [Optional grid](\ref GA13)
68- [Time axis](\ref GA14)
69
70\anchor GA00
71## Basic definition
72A `TGaxis` is defined the following way:
73~~~ {.cpp}
74 TGaxis::TGaxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax,
75 Double_t wmin, Double_t wmax, Int_t ndiv, Option_t *chopt,
76 Double_t gridlength)
77~~~
78Where:
79
80- xmin : X origin coordinate in user's coordinates space.
81- xmax : X end axis coordinate in user's coordinates space.
82- ymin : Y origin coordinate in user's coordinates space.
83- ymax : Y end axis coordinate in user's coordinates space.
84- wmin : Lowest value for the tick mark labels written on the axis.
85- wmax : Highest value for the tick mark labels written on the axis.
86- ndiv : Number of divisions.
87 - ndiv=N1 + 100*N2 + 10000*N3
88 - N1=number of 1st divisions.
89 - N2=number of 2nd divisions.
90 - N3=number of 3rd divisions. e.g.:
91 - ndiv=0 --> no tick marks.
92 - ndiv=2 --> 2 divisions, one tick mark in the middle of the axis.
93- chopt : Drawing options (see below).
94- gridlength: grid length on main tick marks.
95
96The example below generates various kind of axis.
97
98Begin_Macro(source)
99../../../tutorials/visualisation/graphics/gaxis.C
100End_Macro
101
102\anchor GA01
103## Definition with a function
104
105Instead of the wmin,wmax arguments of the normal definition, the
106name of a `TF1` function can be specified. This function will be used to
107map the user coordinates to the axis values and ticks.
108
109A `TGaxis` is defined the following way:
110~~~ {.cpp}
111 TGaxis::TGaxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax,
112 const char *func, Int_t ndiv, Option_t *chopt,
113 Double_t gridlength)
114~~~
115Where:
116
117- xmin : X origin coordinate in user's coordinates space.
118- xmax : X end axis coordinate in user's coordinates space.
119- ymin : Y origin coordinate in user's coordinates space.
120- ymax : Y end axis coordinate in user's coordinates space.
121- func : function defining axis labels and tick marks.
122- ndiv : Number of divisions.
123 - ndiv=N1 + 100*N2 + 10000*N3
124 - N1=number of 1st divisions.
125 - N2=number of 2nd divisions.
126 - N3=number of 3rd divisions. e.g.:
127 - ndiv=0 --> no tick marks.
128 - ndiv=2 --> 2 divisions, one tick mark in the middle of the axis.
129- chopt : Drawing options (see below).
130- gridlength: grid length on main tick marks.
131
132It should be noted that `func` is not defined in the user's coordinate space,
133but in the new TGaxis space. If `x` is the original axis, `w` the new axis,
134and `w = f(x)` (for example, `f` is a calibration function converting ADC
135channels `x` to energy `w`), then `func` must be supplied as `f^{-1}(w)`.
136
137Examples:
138
139Begin_Macro(source)
140{
141 TCanvas *c2 = new TCanvas("c2","c2",10,10,700,500);
142
143 gPad->DrawFrame(0.,-2.,10.,2);
144
145 TF1 *f1=new TF1("f1","-x",-10,10);
146 TGaxis *A1 = new TGaxis(0,2,10,2,"f1",510,"-");
147 A1->SetTitle("axis with decreasing values");
148 A1->Draw();
149
150 TF1 *f2=new TF1("f2","exp(x)",0,2);
151 TGaxis *A2 = new TGaxis(1,1,9,1,"f2");
152 A2->SetTitle("exponential axis");
153 A2->SetLabelSize(0.03);
154 A2->SetTitleSize(0.03);
155 A2->SetTitleOffset(1.2);
156 A2->Draw();
157
158 TF1 *f3=new TF1("f3","log10(x)",1,1000);
159 TGaxis *A3 = new TGaxis(2,-2,2,0,"f3",505,"");
160 A3->SetTitle("logarithmic axis");
161 A3->SetLabelSize(0.02);
162 A3->SetTitleSize(0.03);
163 A3->SetTitleOffset(0.); // Axis title automatically placed
164 A3->Draw();
165}
166End_Macro
167
168Note that this functionality has some limitations and does not follow all the TGaxis setting.
169In particular the number of divisions or the maximum number digits do not apply.
170
171\anchor GA02
172## Logarithmic axis
173
174By default axis are linear. To define a `TGaxis` as logarithmic, it is
175enough to create it with the option `"G"`.
176
177When plotting an histogram or a graph the logarithmic scale can be set using:
178
179 - `gPad->SetLogx(1);` set the logarithmic scale on the X axis
180 - `gPad->SetLogy(1);` set the logarithmic scale on the Y axis
181
182When the `SetMoreLogLabels()` method is called more labels are drawn
183when in logarithmic scale and there is a small number of decades (less than 3).
184
185\anchor GA03
186## Blank axis
187To draw only the axis tick marks without the axis body, it is enough to specify
188the option `"B"`. It useful to superpose axis.
189
190\anchor GA03a
191## Arrow on axis
192\since **ROOT version 6.27/01:**
193
194To draw an arrow at the end of the axis use the option `">"`. To draw it at the beginning
195of the axis use the option `"<"`. To draw it on both ends use `"<>"`.
196
197Begin_Macro(source)
198{
199 auto c = new TCanvas("c","c",0,0,500,500);
200 c->Range(-11,-11,11,11);
201
202 auto f2 = new TF1("x2","x*x",-10,10);
203 f2->SetLineColor(kRed);
204 f2->Draw("same");
205
206 auto f3 = new TF1("x3","x*x*x",-10,10);
207 f3->SetLineColor(kBlue);
208 f3->Draw("same");
209
210 // Draw the axis with arrows
211 auto ox = new TGaxis(-10,0,10,0,-10.,10.,510,"+-S>");
212 ox->SetTickSize(0.009);
213 ox->SetLabelFont(42);
214 ox->SetLabelSize(0.025);
215 ox->Draw();
216 auto oy = new TGaxis(0,-10,0,10,-10,10,510,"+-S>");
217 oy->SetTickSize(0.009);
218 oy->SetLabelFont(42);
219 oy->SetLabelSize(0.025);
220 oy->Draw();
221}
222End_Macro
223
224\anchor GA04
225## Tick marks' orientation
226
227By default tick marks are drawn on the positive side of the axis, except for
228vertical axis for which the default is negative. The `chop` parameter
229allows to control the tick marks orientation:
230
231 - `chopt = "+"`: tick marks are drawn on Positive side. (default)
232 - `chopt ="-"`: tick mark are drawn on the negative side.
233 - `chopt = "+-"`: tick marks are drawn on both sides of the axis.
234 - `chopt = "U"`: Unlabelled axis, default is labeled.
235
236\anchor GA05
237## Tick marks' size
238
239By default, tick marks have a length equal to 3 per cent of the axis length.
240When the option "S" is specified, the length of the tick marks is equal to
241`fTickSize*axis_length`, where `fTickSize` may be set via
242`TGaxis::SetTickSize`.
243
244When plotting an histogram `h` the tick marks size can be changed using:
245
246 - `h->GetXaxis()->SetTickLength(0.02);` set the tick length for the X axis
247 - `gStyle->SetTickLength(0.02,"x");` set the tick length for the X axis
248 of all histograms drawn after this instruction.
249
250A good way to remove tick marks on an axis is to set the tick length to 0:
251`h->GetXaxis()->SetTickLength(0.);`
252
253\anchor GA06
254## Labels' positioning
255
256Labels are normally drawn on side opposite to tick marks. However the option
257`"="` allows to draw them on the same side. The distance between the labels and
258the axis body can be changed with `SetLabelOffset`.
259
260\anchor GA07
261## Labels' orientation
262
263By default axis labels are drawn parallel to the axis. However if the axis is vertical
264then are drawn perpendicular to the axis.
265
266\anchor GA08
267## Labels' position on tick marks
268
269By default axis labels are centered on tick marks. However, for vertical axis,
270they are right adjusted. The `chop` parameter allows to control the labels'
271position on tick marks:
272
273 - `chopt = "R"`: labels are Right adjusted on tick mark.(default is centered)
274 - `chopt = "L"`: labels are Left adjusted on tick mark.
275 - `chopt = "C"`: labels are Centered on tick mark.
276 - `chopt = "M"`: In the Middle of the divisions.
277
278\anchor GA09
279## Labels' format
280
281Blank characters are stripped, and then the label is correctly aligned. the dot,
282if last character of the string, is also stripped, unless the option `"."`
283(a dot, or period) is specified. if `SetDecimals(kTRUE)` has been called
284all labels have the same number of decimals after the `"."`
285The same is true if `gStyle->SetStripDecimals(kFALSE)` has been called.
286
287In the following, we have some parameters, like tick marks length and characters
288height (in percentage of the length of the axis (user's coordinates))
289The default values are as follows:
290
291 - Primary tick marks: 3.0 %
292 - Secondary tick marks: 1.5 %
293 - Third order tick marks: .75 %
294 - Characters height for labels: 4%
295 - Labels offset: 1.0 %
296
297By default, an exponent of the form 10^N is used when the label values are either
298all very small or very large. One can disable the exponent by calling
299`axis.SetNoExponent(kTRUE)`.
300
301`TGaxis::SetExponentOffset(Float_t xoff, Float_t yoff, Option_t *axis)` is
302static function to set X and Y offset of the axis 10^n notation. It is in % of
303the pad size. It can be negative. `axis` specifies which axis
304(`"x"` or/and `"y"`), default is `"x"` if `axis = "xz"`
305set the two axes
306
307\anchor GA10
308## Alphanumeric labels
309
310Axis labels can be any alphanumeric character strings. Such axis can be produced
311only with histograms because the labels'definition is stored in `TAxis`.
312The following example demonstrates how to create such labels.
313
314Begin_Macro(source)
315../../../tutorials/hist/hist036_TH2_labels.C
316End_Macro
317
318Because the alphanumeric labels are usually longer that the numeric labels, their
319size is by default equal to `0.66666 * the_numeric_labels_size`.
320
321\anchor GA10a
322## Changing axis labels
323\since **ROOT version 6.07/07:**
324
325After an axis has been created, TGaxis::ChangeLabel allows to define new text
326attributes for a given label. A fine tuning of the labels can be done. All the
327attributes can be changed as well as the text label itself.
328
329When plotting an histogram or a graph the labels can be changed like in the
330following example which shows a way to produce \f$\pi\f$-axis :
331
332Begin_Macro(source)
333{
334 Double_t pi = TMath::Pi();
335 TF1* f = new TF1("f","TMath::Cos(x/TMath::Pi())", -pi, pi);
336 TAxis* a = f->GetXaxis();
337 a->SetNdivisions(-502);
338 a->ChangeLabel(1,-1,-1,-1,-1,-1,"-#pi");
339 a->ChangeLabel(-1,-1,-1,-1,-1,-1,"#pi");
340 f->Draw();
341}
342End_Macro
343
344\anchor GA11
345## Number of divisions optimisation
346
347By default the number of divisions on axis is optimised to show a coherent
348labelling of the main tick marks. The number of division (`ndiv`) is a
349composite integer given by:
350
351` ndiv = N1 + 100*N2 + 10000*N3`
352
353 - `N1` = number of 1st divisions.
354 - `N2` = number of 2nd divisions.
355 - `N3` = number of 3rd divisions.
356
357by default the value of `N1`, `N2` and `N3` are maximum
358values. After optimisation the real number of divisions will be smaller or
359equal to these value. If one wants to bypass the optimisation, the option `"N"`
360should be given when the `TGaxis` is created. The option `"I"`
361also act on the number of division as it will force an integer labelling of
362the axis.
363
364On an histogram pointer `h` the number of divisions can be set in different ways:.
365
366- Directly on the histogram. The following will set the number of division
367 to 510 on the X axis of `h`. To avoid optimization the number of divisions
368 should be negative (ie: -510);
369~~~ {.cpp}
370 h->SetNdivisions(510, "X");
371~~~
372- On the axis itself:
373~~~ {.cpp}
374 h->GetXaxis()->SetNdivisions(510, kTRUE);
375~~~
376
377The first parameter is the number of division. If it is negative of if the
378second parameter is kFALSE then the number of divisions is not optimised.
379And other signature is also allowed:
380~~~ {.cpp}
381 h->GetXaxis()->SetNdivisions(10, 5, 0, kTRUE);
382~~~
383\anchor GA12
384## Maximum Number of Digits for the axis labels
385
386The static method `TGaxis::SetMaxDigits` sets the maximum number of
387digits permitted for the axis labels above which the notation with 10^N is used.
388For example, to accept 6 digits number like 900000 on an axis call
389`TGaxis::SetMaxDigits(6)`. The default value is 5.
390`fgMaxDigits` must be greater than 0.
391Warning: even when called on a particular TGaxis* instance, this static function
392changes globally the number of digits for all axes (X, Y, ...) in the canvas.
393If you want to change the maximum number of digits N only of the current TGaxis*,
394and not all the others, use axis->SetNdivisions(N*1000000 + (axis->GetNdiv()%1000000))
395instead of axis->SetMaxDigits(N).
396
397\anchor GA13
398## Optional grid
399
400The option `"W"` allows to draw a grid on the primary tick marks. In case
401of a log axis, the grid is only drawn for the primary tick marks if the number
402of secondary and tertiary divisions is 0. `SetGridLength()` allows to define
403the length of the grid.
404
405When plotting an histogram or a graph the grid can be set ON or OFF using:
406
407 - `gPad->SetGridy(1);` set the grid on the X axis
408 - `gPad->SetGridx(1);` set the grid on the Y axis
409 - `gPad->SetGrid(1,1);` set the grid on both axis.
410
411\anchor GA14
412## Time axis
413
414Histograms' axis can be defined as "time axis". To do that it is enough to activate
415the TAxis::SetTimeDisplay attribute on a given axis. If `h` is an histogram, it is
416done the following way:
417
418~~~ {.cpp}
419 h->GetXaxis()->SetTimeDisplay(1); // The X axis is a time axis
420~~~
421
422Two parameters can be adjusted in order to define time axis:
423
424### The time format:
425
426Defines the format of the labels along the time axis. It can be changed using the TAxis
427TAxis::SetTimeFormat. The time format is the one used by the C function **strftime()**.
428It's a string containing the following formatting characters:
429
430 - for date :
431 - **%a** abbreviated weekday name
432 - **%b** abbreviated month name
433 - **%d** day of the month (01-31)
434 - **%m** month (01-12)
435 - **%y** year without century
436 - **%Y** year with century
437 - for time :
438 - **%H** hour (24-hour clock)
439 - **%I** hour (12-hour clock)
440 - **%p** local equivalent of AM or PM
441 - **%M** minute (00-59)
442 - **%S** seconds (00-61)
443 - **%%** %
444
445 The other characters are output as is. For example to have a format like
446 `dd/mm/yyyy` one should do:
447
448~~~ {.cpp}
449 h->GetXaxis()->SetTimeFormat("%d\/%m\/%Y");
450~~~
451
452### The time offset:
453
454This is a time in seconds in the UNIX standard UTC format (this is an universal
455time, not the local time), defining the starting date of an histogram axis.
456This date should be greater than 01/01/95 and is given in seconds. There are
457three ways to define the time offset:
458
459#### By setting the global default time offset:
460
461~~~ {.cpp}
462 TDatime da(2003,02,28,12,00,00);
463 gStyle->SetTimeOffset(da.Convert());
464~~~
465
466 If no time offset is defined for a particular axis, the default time offset
467 will be used. In the example above, notice the usage of TDateTime to translate
468 an explicit date into the time in seconds required by TAxis::SetTimeFormat.
469
470#### By setting a time offset to a particular axis:
471
472~~~ {.cpp}
473 TDatime dh(2001,09,23,15,00,00);
474 h->GetXaxis()->SetTimeOffset(dh.Convert());
475~~~
476
477#### Together with the time format using TAxis::SetTimeFormat:
478
479The time offset can be specified using the control character `%F` after
480the normal time format. **%F** is followed by the date in the format:
481`yyyy-mm-dd hh:mm:ss`.
482
483Example:
484
485~~~ {.cpp}
486 h->GetXaxis()->SetTimeFormat("%d\/%m\/%y%F2000-02-28 13:00:01");
487~~~
488
489
490
491Notice that this date format is the same used by the TDateString function
492`AsSQLString`. If needed, this function can be used to translate a time in
493seconds into a character string which can be appended after `%F`. If the time
494format is not specified (before `%F), the automatic one will be used.
495
496If a time axis has no specified time offset, the global time offset will be
497stored in the axis data structure.
498
499The following example illustrates the various possibilities.
500
501Begin_Macro(source)
502{
503 gStyle->SetTitleH(0.08);
504
505 TDatime da(2003,2,28,12,00,00);
506 gStyle->SetTimeOffset(da.Convert());
507
508 auto ct = new TCanvas("ct","Time on axis",0,0,600,600);
509 ct->Divide(1,3);
510
511 auto ht1 = new TH1F("ht1","ht1",30000,0.,200000.);
512 auto ht2 = new TH1F("ht2","ht2",30000,0.,200000.);
513 auto ht3 = new TH1F("ht3","ht3",30000,0.,200000.);
514 for (Int_t i=1;i<30000;i++) {
515 auto noise = gRandom->Gaus(0,120);
516 ht1->SetBinContent(i,noise);
517 ht2->SetBinContent(i,noise*noise);
518 ht3->SetBinContent(i,noise*noise*noise);
519 }
520
521 ct->cd(1);
522 ht1->GetXaxis()->SetLabelSize(0.06);
523 ht1->GetXaxis()->SetTimeDisplay(1);
524 ht1->GetXaxis()->SetTimeFormat("%d/%m/%y%F2000-02-28 13:00:01");
525 ht1->Draw();
526
527 ct->cd(2);
528 ht2->GetXaxis()->SetLabelSize(0.06);
529 ht2->GetXaxis()->SetTimeDisplay(1);
530 ht2->GetXaxis()->SetTimeFormat("%d/%m/%y");
531 ht2->Draw();
532
533 ct->cd(3);
534 ht3->GetXaxis()->SetLabelSize(0.06);
535 TDatime dh(2001,9,23,15,00,00);
536 ht3->GetXaxis()->SetTimeDisplay(1);
537 ht3->GetXaxis()->SetTimeOffset(dh.Convert());
538 ht3->Draw();
539}
540End_Macro
541
542The histogram limits times in seconds. If `wmin` and `wmax` are the histogram
543limits, the time axis will spread around the time offset value from `TimeOffset+wmin`
544to `TimeOffset+wmax`. Until now all the examples had a lowest value equal to 0.
545The following example demonstrates how to define the histogram limits relatively
546to the time offset value.
547
548Begin_Macro(source)
549{
550 // Define the time offset as 2003, January 1st
551 TDatime T0(2003,1,1,0,0,0);
552 auto X0 = T0.Convert();
553 gStyle->SetTimeOffset(X0);
554
555 // Define the lowest histogram limit as 2002, September 23rd
556 TDatime T1(2002,9,23,0,0,0);
557 auto X1 = T1.Convert()-X0;
558
559 // Define the highest histogram limit as 2003, March 7th
560 TDatime T2(2003,3,7,0,0,0);
561 auto X2 = T2.Convert(1)-X0;
562
563 auto h1 = new TH1F("h1","test",100,X1,X2);
564
565 TRandom r;
566 for (Int_t i=0;i<30000;i++) {
567 Double_t noise = r.Gaus(0.5*(X1+X2),0.1*(X2-X1));
568 h1->Fill(noise);
569 }
570
571 h1->GetXaxis()->SetTimeDisplay(1);
572 h1->GetXaxis()->SetLabelSize(0.03);
573 h1->GetXaxis()->SetTimeFormat("%Y/%m/%d");
574 h1->Draw();
575}
576End_Macro
577
578
579Usually time axis are created automatically via histograms, but one may also want
580to draw a time axis outside an "histogram context". Therefore it is useful to
581understand how TGaxis works for such axis.
582
583The time offset can be defined using one of the three methods described before.
584The time axis will spread around the time offset value. Actually it will go from
585`TimeOffset+wmin` to `TimeOffset+wmax` where `wmin` and `wmax` are the minimum
586and maximum values (in seconds) of the axis. Let's take again an example. Having
587defined "2003, February 28 at 12h" we would like to see the axis a day before and
588a day after. A TGaxis can be created the following way (a day has 86400 seconds):
589
590~~~ {.cpp}
591 TGaxis *axis = new TGaxis(x1,y1,x2,y2,-100000,150000,2405,"t");
592~~~
593
594the `t` option (in lower case) means it is a "time axis". The axis goes form
595100000 seconds before `TimeOffset` and 150000 seconds after.
596
597So the complete macro is:
598
599Begin_Macro(source)
600{
601 auto c1 = new TCanvas("c1","Examples of TGaxis",10,10,700,100);
602 c1->Range(-10,-1,10,1);
603
604 TGaxis *axis = new TGaxis(-8,0.,8,0.,-100000,150000,2405,"tS");
605 axis->SetLabelSize(0.2);
606 axis->SetTickSize(0.2);
607
608 TDatime da(2003,02,28,12,00,00);
609 axis->SetTimeOffset(da.Convert());
610 axis->SetTimeFormat("%d-%m-%Y");
611 axis->Draw();
612 return c1;
613}
614End_Macro
615
616
617Thanks to the TLatex directive `#splitline` it is possible to write the time
618labels on two lines. In the previous example changing the `SetTimeFormat` line by
619
620~~~ {.cpp}
621 axis->SetLabelOffset(0.15);
622 axis->SetTimeFormat("#splitline{%Y}{%d\/%m}");
623~~~
624
625will produce the following axis:
626
627Begin_Macro
628{
629 auto c1 = new TCanvas("c1","Examples of TGaxis",10,10,700,100);
630 c1->Range(-10,-1,10,1);
631
632 TGaxis *axis = new TGaxis(-8,0.,8,0.,-100000,150000,2405,"tS");
633 axis->SetLabelSize(0.2);
634 axis->SetTickSize(0.2);
635
636 TDatime da(2003,02,28,12,00,00);
637 axis->SetTimeOffset(da.Convert());
638 axis->SetLabelOffset(0.15);
639 axis->SetTimeFormat("#splitline{%Y}{%d/%m}");
640 axis->Draw();
641 return c1;
642}
643End_Macro
644
645
646The following example shows time axis on a TGraph:
647
648Begin_Macro(source)
649{
650 TDatime da1(2008,02,28,15,52,00);
651 TDatime da2(2008,02,28,15,53,00);
652
653 double x[2],y[2];
654
655 y[0] = 1.;
656 y[1] = 2.;
657 x[0] = da1.Convert();
658 x[1] = da2.Convert();
659
660 TGraph mgr(2,x,y);
661 mgr.SetMarkerStyle(20);
662
663 mgr.Draw("apl");
664 mgr.GetXaxis()->SetTimeDisplay(1);
665 mgr.GetXaxis()->SetNdivisions(-503);
666 mgr.GetXaxis()->SetTimeFormat("%Y-%m-%d %H:%M");
667 mgr.GetXaxis()->SetTimeOffset(0,"gmt");
668}
669End_Macro
670
671The following example compares what the system time function `gmtime`
672and `localtime` give with what gives `TGaxis`. It can be used
673as referenced test to check if the time option of `TGaxis` is working properly.
674
675Begin_Macro(source)
676../../../tutorials/visualisation/graphics/timeonaxis3.C
677End_Macro
678
679
680The following macro illustrates the use, with histograms axis, of the time mode on the axis
681with different time intervals and time formats.
682
683Begin_Macro(source)
684../../../tutorials/hist/hist061_TH1_timeonaxis.C
685End_Macro
686
687*/
688
689////////////////////////////////////////////////////////////////////////////////
690/// TGaxis default constructor.
691
692TGaxis::TGaxis(): TLine(), TAttText(11,0,1,62,0.040)
693{
694
695 fGridLength = 0.;
696 fLabelOffset = 0.005;
697 fLabelSize = 0.040;
698 fLabelFont = 62;
699 fLabelColor = 1;
700 fTickSize = 0.030;
701 fTitleOffset = 1;
703 fChopt = "";
704 fName = "";
705 fTitle = "";
706 fTimeFormat = "";
707 fFunctionName= "";
708 fFunction = nullptr;
709 fAxis = nullptr;
710 fNdiv = 0;
711 fNModLabs = 0;
712 fModLabs = nullptr;
713 fWmin = 0.;
714 fWmax = 0.;
715}
716
717////////////////////////////////////////////////////////////////////////////////
718/// TGaxis normal constructor.
719
723 : TLine(xmin,ymin,xmax,ymax), TAttText(11,0,1,62,0.040)
724{
725
726 fWmin = wmin;
727 fWmax = wmax;
728 fNdiv = ndiv;
729 fNModLabs = 0;
730 fModLabs = nullptr;
732 fLabelOffset = 0.005;
733 fLabelSize = 0.040;
734 fLabelFont = 62;
735 fLabelColor = 1;
736 fTickSize = 0.030;
737 fTitleOffset = 1;
739 fChopt = chopt;
740 fName = "";
741 fTitle = "";
742 fTimeFormat = "";
743 fFunctionName= "";
744 fFunction = nullptr;
745 fAxis = nullptr;
746}
747
748////////////////////////////////////////////////////////////////////////////////
749/// Constructor with a `TF1` to map axis values.
750///
751/// \note The function `func` (with name `funcname`) is not defined in the user's
752/// coordinate space, but in the new TGaxis space. If `x` is the original axis,
753/// `w` the new axis, and `w = f(x)` (for example, `f` is a calibration function
754/// converting ADC channels `x` to energy `w`), then `func` must be supplied as
755/// `f^{-1}(w)`.
756
758 const char *funcname, Int_t ndiv, Option_t *chopt,
760 : TLine(xmin,ymin,xmax,ymax), TAttText(11,0,1,62,0.040)
761{
762
763 fFunction = (TF1*)gROOT->GetFunction(funcname);
764 if (!fFunction) {
765 Error("TGaxis", "calling constructor with an unknown function: %s", funcname);
766 fWmin = 0;
767 fWmax = 1;
768 } else {
771 }
773 fNdiv = ndiv;
774 fNModLabs = 0;
775 fModLabs = nullptr;
777 fLabelOffset = 0.005;
778 fLabelSize = 0.040;
779 fLabelFont = 62;
780 fLabelColor = 1;
781 fTickSize = 0.030;
782 fTitleOffset = 1;
784 fChopt = chopt;
785 fName = "";
786 fTitle = "";
787 fTimeFormat = "";
788 fAxis = nullptr;
789}
790
791////////////////////////////////////////////////////////////////////////////////
792/// Copy constructor.
793
795 TLine(ax),
796 TAttText(ax),
797 fWmin(ax.fWmin),
798 fWmax(ax.fWmax),
799 fGridLength(ax.fGridLength),
800 fTickSize(ax.fTickSize),
801 fLabelOffset(ax.fLabelOffset),
802 fLabelSize(ax.fLabelSize),
803 fTitleOffset(ax.fTitleOffset),
804 fTitleSize(ax.fTitleSize),
805 fNdiv(ax.fNdiv),
806 fLabelColor(ax.fLabelColor),
807 fLabelFont(ax.fLabelFont),
808 fNModLabs(ax.fNModLabs),
809 fChopt(ax.fChopt),
810 fName(ax.fName),
811 fTitle(ax.fTitle),
812 fTimeFormat(ax.fTimeFormat),
813 fFunctionName(ax.fFunctionName),
814 fFunction(ax.fFunction),
815 fAxis(ax.fAxis)
816{
817 if (ax.IsOwnedModLabs())
818 fModLabs = (TList *) ax.fModLabs->Clone();
819 else
820 fModLabs = ax.fModLabs;
821}
822
823////////////////////////////////////////////////////////////////////////////////
824/// Assignment operator.
825
827{
828
829 if(this!=&ax) {
831 TAttText::operator=(ax);
832 fWmin=ax.fWmin;
833 fWmax=ax.fWmax;
834 fGridLength=ax.fGridLength;
835 fTickSize=ax.fTickSize;
836 fLabelOffset=ax.fLabelOffset;
837 fLabelSize=ax.fLabelSize;
838 fTitleOffset=ax.fTitleOffset;
839 fTitleSize=ax.fTitleSize;
840 fNdiv=ax.fNdiv;
841 fLabelColor=ax.fLabelColor;
842 fLabelFont=ax.fLabelFont;
843 fChopt=ax.fChopt;
844 fName=ax.fName;
845 fTitle=ax.fTitle;
846 fTimeFormat=ax.fTimeFormat;
847 fFunctionName=ax.fFunctionName;
848 fFunction=ax.fFunction;
849 fAxis=ax.fAxis;
850 fNModLabs=ax.fNModLabs;
851 fModLabs = ax.IsOwnedModLabs() ? (TList *) ax.fModLabs->Clone() : ax.fModLabs;
852 }
853 return *this;
854}
855
856////////////////////////////////////////////////////////////////////////////////
857/// TGaxis default destructor.
858
863
864////////////////////////////////////////////////////////////////////////////////
865/// Returns kTRUE when fModLabs owned by TGaxis and should be cleaned up
866
868{
869 if (!fModLabs) return kFALSE;
870 if (fAxis && (fAxis->GetModifiedLabels() == fModLabs)) return kFALSE;
871 // TList created by TGaxis configured with owner flag
872 // If TGaxis object from old ROOT file will be read, memory will be leaked
873 return fModLabs->IsOwner();
874}
875
876////////////////////////////////////////////////////////////////////////////////
877/// Correctly cleanup fModLabs - delete content when owned by TGaxis
878
880{
881 if (IsOwnedModLabs()) {
882 fModLabs->Delete();
883 delete fModLabs;
884 }
885 fModLabs = nullptr;
886 fNModLabs = 0;
887}
888
889////////////////////////////////////////////////////////////////////////////////
890/// If center = kTRUE axis labels are centered in the center of the bin.
891/// The default is to center on the primary tick marks.
892/// This option does not make sense if there are more bins than tick marks.
893
895{
896
897 if (center) SetBit(TAxis::kCenterLabels);
899}
900
901////////////////////////////////////////////////////////////////////////////////
902/// If center = kTRUE axis title will be centered. The default is right adjusted.
903
905{
906
907 if (center) SetBit(TAxis::kCenterTitle);
909}
910
911////////////////////////////////////////////////////////////////////////////////
912/// Draw this axis with new attributes.
913
917{
918
920 newaxis->SetLineColor(fLineColor);
921 newaxis->SetLineWidth(fLineWidth);
922 newaxis->SetLineStyle(fLineStyle);
923 newaxis->SetTextAlign(fTextAlign);
924 newaxis->SetTextAngle(fTextAngle);
925 newaxis->SetTextColor(fTextColor);
926 newaxis->SetTextFont(fTextFont);
927 newaxis->SetTextSize(fTextSize);
928 newaxis->SetTitleSize(fTitleSize);
929 newaxis->SetTitleOffset(fTitleOffset);
930 newaxis->SetLabelFont(fLabelFont);
931 newaxis->SetLabelColor(fLabelColor);
932 newaxis->SetLabelSize(fLabelSize);
933 newaxis->SetLabelOffset(fLabelOffset);
934 newaxis->SetTickSize(fTickSize);
935 newaxis->SetBit(kCanDelete);
936 newaxis->SetTitle(GetTitle());
938 newaxis->AppendPad();
939 return newaxis;
940}
941
942////////////////////////////////////////////////////////////////////////////////
943/// Static function returning `gStyle->GetAxisMaxDigits()`.
944
949
950////////////////////////////////////////////////////////////////////////////////
951/// Internal method to import TAxis attributes to this TGaxis.
952
980
981////////////////////////////////////////////////////////////////////////////////
982/// Draw this axis with its current attributes.
983
985{
986 if (!gPad) return;
987
990 Int_t ndiv = fNdiv;
991
992 // following code required to support toggle of lin/log scales
993 Double_t x1 = gPad->XtoPad(fX1);
994 Double_t y1 = gPad->YtoPad(fY1);
995 Double_t x2 = gPad->XtoPad(fX2);
996 Double_t y2 = gPad->YtoPad(fY2);
997
999}
1000
1001////////////////////////////////////////////////////////////////////////////////
1002/// Control function to draw an axis.
1003/// Original authors: O.Couet C.E.Vandoni N.Cremel-Somon.
1004/// Modified and converted to C++ class by Rene Brun.
1005
1009{
1010 if (!gPad) return;
1011
1012 const char *where = "PaintAxis";
1013
1019 Double_t atick[3];
1022 Double_t phil, phi, sinphi, cosphi;
1023 Double_t binLow = 0., binLow2 = 0., binLow3 = 0.;
1024 Double_t binHigh = 0., binHigh2 = 0., binHigh3 = 0.;
1025 Double_t binWidth = 0., binWidth2 = 0., binWidth3 = 0.;
1027 Double_t dxtick=0;
1032 Double_t rlab;
1033 Double_t x0, x1, y0, y1, xx0, xx1, yy0, yy1;
1034 xx0 = xx1 = yy0 = yy1 = 0;
1036 xxmin = xxmax = yymin = yymax = 0;
1038 Double_t ww, af, rne;
1039 Double_t xx, yy;
1040 Double_t xmnlog, x00, x11, h2, h2sav, axmul, y;
1042 Int_t nlabels, nticks, nticks0 = 0, nticks1 = 0;
1043 Int_t i, j, k, l, decade;
1044 Int_t mside, lside;
1045 Int_t nexe = 0;
1046 Int_t lnlen = 0;
1047 Int_t iexe, if1, if2, na, nf, ih1, ih2, nbinin, nch, kmod;
1052 Int_t first=0,last=0,labelnumber;
1054 Int_t nn1, nn2, nn3, n1a, n2a, n3a, nb2, nb3;
1055 Int_t nbins=10, n1aold, nn1old;
1057 n1aold = nn1old = 0;
1058 Int_t ndyn;
1059 Int_t nhilab = 0;
1060 Int_t idn;
1061 Bool_t flexe = false;
1063 char *label;
1064 char *chtemp;
1065 char chlabel[256];
1066 char kchtemp[256];
1067 char chcoded[64];
1071 time_t timelabel;
1073 struct tm* utctis;
1075
1076 Double_t epsilon = 1e-5;
1077 const Double_t kPI = TMath::Pi();
1078
1079 Double_t rwmi = wmin;
1080 Double_t rwma = wmax;
1081 chtemp = &kchtemp[0];
1082 label = &chlabel[0];
1083
1084 fFunction = (TF1*)gROOT->GetFunction(fFunctionName.Data());
1085
1087
1088// If moreLogLabels = kTRUE more Log Intermediate Labels are drawn.
1090
1091// the following parameters correspond to the pad range in NDC
1092// and the user's coordinates in the pad
1093
1094 Double_t padh = gPad->GetWh()*gPad->GetAbsHNDC();
1095 Double_t padw = gPad->GetWw()*gPad->GetAbsWNDC();
1096 Double_t rwxmin = gPad->GetX1();
1097 Double_t rwxmax = gPad->GetX2();
1098 Double_t rwymin = gPad->GetY1();
1099 Double_t rwymax = gPad->GetY2();
1100
1101 if(strchr(chopt,'G')) optionLog = 1; else optionLog = 0;
1102 if(strchr(chopt,'B')) optionBlank= 1; else optionBlank= 0;
1103 if(strchr(chopt,'V')) optionVert = 1; else optionVert = 0;
1104 if(strchr(chopt,'+')) optionPlus = 1; else optionPlus = 0;
1105 if(strchr(chopt,'-')) optionMinus= 1; else optionMinus= 0;
1106 if(strchr(chopt,'U')) optionUnlab= 1; else optionUnlab= 0;
1107 if(strchr(chopt,'P')) optionPara = 1; else optionPara = 0;
1108 if(strchr(chopt,'O')) optionDown = 1; else optionDown = 0;
1109 if(strchr(chopt,'R')) optionRight= 1; else optionRight= 0;
1110 if(strchr(chopt,'L')) optionLeft = 1; else optionLeft = 0;
1111 if(strchr(chopt,'C')) optionCent = 1; else optionCent = 0;
1112 if(strchr(chopt,'=')) optionEqual= 1; else optionEqual= 0;
1113 if(strchr(chopt,'Y')) optionY = 1; else optionY = 0;
1114 if(strchr(chopt,'T')) optionText = 1; else optionText = 0;
1115 if(strchr(chopt,'W')) optionGrid = 1; else optionGrid = 0;
1116 if(strchr(chopt,'S')) optionSize = 1; else optionSize = 0;
1117 if(strchr(chopt,'N')) optionNoopt= 1; else optionNoopt= 0;
1118 if(strchr(chopt,'I')) optionInt = 1; else optionInt = 0;
1119 if(strchr(chopt,'M')) optionM = 1; else optionM = 0;
1120 if(strchr(chopt,'0')) optionUp = 1; else optionUp = 0;
1121 if(strchr(chopt,'X')) optionX = 1; else optionX = 0;
1122 if(strchr(chopt,'t')) optionTime = 1; else optionTime = 0;
1123 if(strchr(chopt,'.')) optionDot = 1; else optionDot = 0;
1129 optionArrow= 0;
1130 if(strchr(chopt,'>')) optionArrow = 1;
1131 if(strchr(chopt,'<')) optionArrow = optionArrow+2;
1132 if (fAxis) {
1133 if (fAxis->GetLabels()) {
1134 optionM = 1;
1135 optionText = 1;
1136 optionNoopt = 1;
1137 ndiv = fAxis->GetLast()-fAxis->GetFirst()+1;
1138 }
1140 if (ml) {
1141 fModLabs = ml;
1143 } else {
1144 fModLabs = nullptr;
1145 fNModLabs = 0;
1146 }
1147 }
1148 if (ndiv < 0) {
1149 Error(where, "Invalid number of divisions: %d",ndiv);
1150 return;
1151 }
1152
1153// Set the grid length
1154
1155 if (optionGrid) {
1156 if (gridlength == 0) gridlength = 0.8;
1157 linegrid.SetLineColor(gStyle->GetGridColor());
1158 if (linegrid.GetLineColor() == 0) linegrid.SetLineColor(GetLineColor());
1159 linegrid.SetLineStyle(gStyle->GetGridStyle());
1160 linegrid.SetLineWidth(gStyle->GetGridWidth());
1161 }
1162
1163// No labels if the axis label offset is big.
1164// In that case the labels are not visible anyway.
1165
1166 if (GetLabelOffset() > 1.1 ) optionUnlab = 1;
1167
1168// Determine time format
1169
1170 Int_t idF = fTimeFormat.Index("%F");
1171 if (idF>=0) {
1173 } else {
1175 }
1176
1177 //GMT option
1178 if (fTimeFormat.Index("GMT")>=0) optionTime =2;
1179
1180 // Determine the time offset and correct for time offset not being integer.
1182 if (optionTime) {
1183 if (idF>=0) {
1186 Int_t year, mm, dd, hh, mi, ss;
1187 if (sscanf(stringtimeoffset.Data(), "%d-%d-%d %d:%d:%d", &year, &mm, &dd, &hh, &mi, &ss) == 6) {
1188 //Get time offset in seconds since EPOCH:
1189 struct tm tp;
1190 tp.tm_year = year-1900;
1191 tp.tm_mon = mm-1;
1192 tp.tm_mday = dd;
1193 tp.tm_hour = hh;
1194 tp.tm_min = mi;
1195 tp.tm_sec = ss;
1196 tp.tm_isdst = 0; //no DST for UTC (and forced to 0 in MktimeFromUTC function)
1198
1199 // Add the time offset's decimal part if it is there
1200 Int_t ids = stringtimeoffset.Index("s");
1201 if (ids >= 0) {
1202 Float_t dp;
1203 Int_t lns = stringtimeoffset.Length();
1205 sscanf(sdp.Data(),"%g",&dp);
1206 timeoffset += dp;
1207 }
1208 } else {
1209 Error(where, "Time offset has not the right format");
1210 }
1211 } else {
1213 }
1214 wmin += timeoffset - (int)(timeoffset);
1215 wmax += timeoffset - (int)(timeoffset);
1216
1217 // correct for time offset at a good limit (min, hour, day, month, year)
1218 struct tm* tp0;
1219 time_t timetp = (time_t)((Long_t)(timeoffset));
1220 Double_t range = wmax - wmin;
1221 Long_t rangeBase = 60;
1222 if (range>60) rangeBase = 60*20; // minutes
1223 if (range>3600) rangeBase = 3600*20; // hours
1224 if (range>86400) rangeBase = 86400*20; // days
1225 if (range>2419200) rangeBase = 31556736; // months (average # days)
1227 if (range>31536000) {
1228 tp0 = gmtime(&timetp);
1229 tp0->tm_mon = 0;
1230 tp0->tm_mday = 1;
1231 tp0->tm_hour = 0;
1232 tp0->tm_min = 0;
1233 tp0->tm_sec = 0;
1234 tp0->tm_isdst = 1; // daylight saving time is on.
1235 rangeBase = (timetp-mktime(tp0)); // years
1237 }
1238 wmax += rangeOffset;
1239 wmin += rangeOffset;
1240 }
1241
1242// Determine number of divisions 1, 2 and 3 and the maximum digits for this axis
1243 n1a = (ndiv%100);
1244 n2a = (ndiv%10000 - n1a)/100;
1245 n3a = (ndiv%1000000 - n2a -n1a)/10000;
1246 nn3 = TMath::Max(n3a,1);
1247 nn2 = TMath::Max(n2a,1)*nn3;
1248 nn1 = TMath::Max(n1a,1)*nn2+1;
1249 nticks = nn1;
1250 maxDigits = (ndiv/1000000);
1252
1253// Axis bining optimisation is ignored if:
1254// - the first and the last label are equal
1255// - the number of divisions is 0
1256// - less than 1 primary division is requested
1257// - logarithmic scale is requested
1258
1259 if (wmin == wmax || ndiv == 0 || n1a <= 1 || optionLog) {
1260 optionNoopt = 1;
1261 optionInt = 0;
1262 }
1263
1264// Axis bining optimisation
1265 if ( (wmax-wmin) < 1 && optionInt) {
1266 Error(where, "option I not available");
1267 optionInt = 0;
1268 }
1269 if (!optionNoopt || optionInt ) {
1270
1271// Primary divisions optimisation
1272// When integer labelling is required, Optimize is invoked first
1273// and only if the result is not an integer labelling, AdjustBinSize is invoked.
1274
1275 THLimitsFinder::Optimize(wmin,wmax,n1a,binLow,binHigh,nbins,binWidth,fChopt.Data());
1276 if (optionInt) {
1277 if (binLow != Double_t(int(binLow)) || binWidth != Double_t(int(binWidth))) {
1278 AdjustBinSize(wmin,wmax,n1a,binLow,binHigh,nbins,binWidth);
1279 }
1280 }
1281 if ((wmin-binLow) > epsilon) { binLow += binWidth; nbins--; }
1282 if ((binHigh-wmax) > epsilon) { binHigh -= binWidth; nbins--; }
1283 if (xmax == xmin) {
1284 rtyw = (ymax-ymin)/(wmax-wmin);
1285 xxmin = xmin;
1286 xxmax = xmax;
1287 yymin = rtyw*(binLow-wmin) + ymin;
1288 yymax = rtyw*(binHigh-wmin) + ymin;
1289 }
1290 else {
1291 rtxw = (xmax-xmin)/(wmax-wmin);
1292 xxmin = rtxw*(binLow-wmin) + xmin;
1293 xxmax = rtxw*(binHigh-wmin) + xmin;
1294 if (ymax == ymin) {
1295 yymin = ymin;
1296 yymax = ymax;
1297 }
1298 else {
1299 alfa = (ymax-ymin)/(xmax-xmin);
1300 beta = (ymin*xmax-ymax*xmin)/(xmax-xmin);
1301 yymin = alfa*xxmin + beta;
1302 yymax = alfa*xxmax + beta;
1303 }
1304 }
1305 if (fFunction) {
1306 yymin = ymin;
1307 yymax = ymax;
1308 xxmin = xmin;
1309 xxmax = xmax;
1310 } else {
1311 wmin = binLow;
1312 wmax = binHigh;
1313 }
1314
1315// Secondary divisions optimisation
1316 nb2 = n2a;
1317 if (!optionNoopt && n2a > 1 && binWidth > 0) {
1319 }
1320
1321// Tertiary divisions optimisation
1322 nb3 = n3a;
1323 if (!optionNoopt && n3a > 1 && binWidth2 > 0) {
1325 }
1326 n1aold = n1a;
1327 nn1old = nn1;
1328 n1a = nbins;
1329 nn3 = TMath::Max(nb3,1);
1330 nn2 = TMath::Max(nb2,1)*nn3;
1331 nn1 = TMath::Max(n1a,1)*nn2+1;
1332 nticks = nn1;
1333 }
1334
1335// Coordinates are normalized
1336
1337 ratio1 = 1/(rwxmax-rwxmin);
1338 ratio2 = 1/(rwymax-rwymin);
1339 x0 = ratio1*(xmin-rwxmin);
1340 x1 = ratio1*(xmax-rwxmin);
1341 y0 = ratio2*(ymin-rwymin);
1342 y1 = ratio2*(ymax-rwymin);
1343 if (!optionNoopt || optionInt ) {
1344 xx0 = ratio1*(xxmin-rwxmin);
1345 xx1 = ratio1*(xxmax-rwxmin);
1346 yy0 = ratio2*(yymin-rwymin);
1347 yy1 = ratio2*(yymax-rwymin);
1348 }
1349
1350 if ((x0 == x1) && (y0 == y1)) {
1351 Error(where, "length of axis is 0");
1352 return;
1353 }
1354
1355// Title offset. If 0 it is automatically computed
1358 if (toffset==0 && x1 == x0) autotoff = kTRUE;
1359
1360// Return wmin, wmax and the number of primary divisions
1361 if (optionX) {
1362 ndiv = n1a;
1363 return;
1364 }
1365
1367 SetLineStyle(1); // axis line style
1370
1371// Compute length of axis
1372 axis_length = TMath::Sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0));
1373 if (axis_length == 0) {
1374 Error(where, "length of axis is 0");
1375 return;
1376 }
1377 if (!optionNoopt || optionInt) {
1379 axis_length0 = TMath::Sqrt((xx0-x0)*(xx0-x0)+(yy0-y0)*(yy0-y0));
1381 if (axis_lengthN < epsilon) {
1382 optionNoopt = 1;
1383 optionInt = 0;
1384 wmin = rwmi;
1385 wmax = rwma;
1386 n1a = n1aold;
1387 nn1 = nn1old;
1388 nticks = nn1;
1389 if (optionTime) {
1392 }
1393 }
1394 }
1395
1396 if (x0 == x1) {
1397 if (y1>=y0) phi = 0.5*kPI;
1398 else phi = 1.5*kPI;
1399 phil = phi;
1400 } else {
1401 phi = TMath::ATan2((y1-y0),(x1-x0));
1402 Int_t px0 = gPad->UtoPixel(x0);
1403 Int_t py0 = gPad->VtoPixel(y0);
1404 Int_t px1 = gPad->UtoPixel(x1);
1405 Int_t py1 = gPad->VtoPixel(y1);
1406 if (x0 < x1) phil = TMath::ATan2(Double_t(py0-py1), Double_t(px1-px0));
1407 else phil = TMath::ATan2(Double_t(py1-py0), Double_t(px0-px1));
1408 }
1409 cosphi = TMath::Cos(phi);
1410 sinphi = TMath::Sin(phi);
1411 if (TMath::Abs(cosphi) <= epsilon)
1412 cosphi = 0;
1413 if (TMath::Abs(sinphi) <= epsilon)
1414 sinphi = 0;
1415
1416// mside positive, tick marks on positive side
1417// mside negative, tick marks on negative side
1418// mside zero, tick marks on both sides
1419// Default is positive except for vertical axis
1420
1421 mside=1;
1422 if (x0 == x1 && y1 > y0) mside = -1;
1423 if (optionPlus) mside = 1;
1424 if (optionMinus) mside = -1;
1425 if (optionPlus && optionMinus) mside = 0;
1426 xmside = mside;
1427 lside = -mside;
1428 if (optionEqual) lside = mside;
1429 if (optionPlus && optionMinus) {
1430 lside = -1;
1431 if (optionEqual) lside=1;
1432 }
1433 xlside = lside;
1434
1435// Tick marks size
1436 if(xmside >= 0) tick_side = 1;
1437 else tick_side = -1;
1439 else atick[0] = tick_side*axis_length*0.03;
1440
1441 atick[1] = 0.5*atick[0];
1442 atick[2] = 0.5*atick[1];
1443
1444// Set the side of the grid
1445 if ((x0 == x1) && (y1 > y0)) grid_side =-1;
1446 else grid_side = 1;
1447
1448// Compute Values if Function is given
1449 if(fFunction) {
1450 rwmi = fFunction->Eval(wmin);
1451 rwma = fFunction->Eval(wmax);
1452 if(rwmi > rwma) {
1453 Double_t t = rwma;
1454 rwma = rwmi;
1455 rwmi = t;
1456 }
1457 }
1458
1459// Draw the axis if needed...
1460 if (!optionBlank) {
1461 xpl1 = x0;
1462 xpl2 = x1;
1463 ypl1 = y0;
1464 ypl2 = y1;
1465 if (optionArrow) {
1466 TArrow a;
1468 a.SetFillColor(GetLineColor());
1469 a.SetLineWidth(GetLineWidth());
1470 a.SetAngle(30);
1471 Double_t as = 0.04*axis_length;
1472 if (optionArrow==1) a.PaintArrowNDC(xpl1, ypl1, xpl2, ypl2, as,"|>");
1473 if (optionArrow==2) a.PaintArrowNDC(xpl1, ypl1, xpl2, ypl2, as,"<|");
1474 if (optionArrow==3) a.PaintArrowNDC(xpl1, ypl1, xpl2, ypl2, as,"<|>");
1475 } else {
1477 }
1478 }
1479
1480// No bining
1481
1482 if (ndiv == 0) return;
1483 if (wmin == wmax) {
1484 Error(where, "wmin (%f) == wmax (%f)", wmin, wmax);
1485 return;
1486 }
1487
1488// Labels preparation:
1489// Get character height
1490// Compute the labels orientation in case of overlaps
1491// (with alphanumeric labels for horizontal axis).
1492
1494 if (optionText && GetLabelFont()%10 != 3) charheight *= 0.66666;
1495 textaxis.SetTextFont(GetLabelFont());
1496 if ((GetLabelFont()%10 < 2) && optionLog) // force TLatex mode in PaintLatex
1497 textaxis.SetTextFont((Int_t)(GetLabelFont()/10)*10+2);
1498 textaxis.SetTextColor(GetLabelColor());
1499 textaxis.SetTextSize (charheight);
1500 textaxis.SetTextAngle(GetTextAngle());
1501 if (GetLabelFont()%10 > 2) {
1502 charheight /= padh;
1503 }
1504 if (!optionUp && !optionDown && !optionY && !optionUnlab) {
1505 if (!drawGridOnly && optionText && ((ymin == ymax) || (xmin == xmax))) {
1506 textaxis.SetTextAlign(32);
1507 optionText = 2;
1508 Int_t nl = fAxis->GetLast()-fAxis->GetFirst()+1;
1509 Double_t angle = 0;
1510 for (i=fAxis->GetFirst(); i<=fAxis->GetLast(); i++) {
1511 textaxis.SetText(0,0,fAxis->GetBinLabel(i));
1512 if (textaxis.GetXsize() < (xmax-xmin)/nl) continue;
1513 angle = -20;
1514 break;
1515 }
1516 for (i=fAxis->GetFirst(); i<=fAxis->GetLast(); i++) {
1517 if ((!strcmp(fAxis->GetName(),"xaxis") && !gPad->TestBit(kHori))
1518 ||(!strcmp(fAxis->GetName(),"yaxis") && gPad->TestBit(kHori))) {
1519 if (nl > 50) angle = 90;
1522 if (fAxis->TestBit(TAxis::kLabelsUp)) angle = 20;
1524 if (angle == 0) textaxis.SetTextAlign(23);
1525 if (angle == -20) textaxis.SetTextAlign(12);
1526 textaxis.SetTextAngle(angle);
1527 Double_t s = -3;
1528 if (ymin == gPad->GetUymax()) {
1529 if (angle == 0) textaxis.SetTextAlign(21);
1530 s = 3;
1531 }
1532 strlcpy(chtemp, fAxis->GetBinLabel(i), 255);
1534 textaxis.PaintLatex(fAxis->GetBinCenter(i),
1535 ymin + s*fAxis->GetLabelOffset()*(gPad->GetUymax()-gPad->GetUymin()),
1536 textaxis.GetTextAngle(),
1537 textaxis.GetTextSize(),
1538 chtemp);
1540 } else if ((!strcmp(fAxis->GetName(),"yaxis") && !gPad->TestBit(kHori))
1541 || (!strcmp(fAxis->GetName(),"xaxis") && gPad->TestBit(kHori))) {
1542 Double_t s = -3;
1543 if (xmin == gPad->GetUxmax()) {
1544 textaxis.SetTextAlign(12);
1545 s = 3;
1546 }
1547 if (autotoff) {
1548 UInt_t w,h;
1549 textaxis.SetText(0.,0., fAxis->GetBinLabel(i));
1550 textaxis.GetBoundingBox(w,h);
1551 double scale=gPad->GetWw()*gPad->GetWNDC();
1552 if (scale>0.0) toffset = TMath::Max(toffset,(double)w/scale);
1553 }
1554 strlcpy(chtemp, fAxis->GetBinLabel(i), 255);
1556 textaxis.PaintLatex(xmin + s*fAxis->GetLabelOffset()*(gPad->GetUxmax()-gPad->GetUxmin()),
1557 fAxis->GetBinCenter(i),
1558 0,
1559 textaxis.GetTextSize(),
1560 chtemp);
1562 } else {
1563 strlcpy(chtemp, fAxis->GetBinLabel(i), 255);
1565 textaxis.PaintLatex(xmin - 3*fAxis->GetLabelOffset()*(gPad->GetUxmax()-gPad->GetUxmin()),
1566 ymin +(i-0.5)*(ymax-ymin)/nl,
1567 0,
1568 textaxis.GetTextSize(),
1569 chtemp);
1571 }
1572 }
1573 }
1574 }
1575
1576// Now determine text alignment
1577 xalign = 2;
1578 yalign = 1;
1579 if (x0 == x1) xalign = 3;
1580 if (y0 != y1) yalign = 2;
1581 if (optionCent) xalign = 2;
1582 if (optionRight) xalign = 3;
1583 if (optionLeft) xalign = 1;
1584 if (TMath::Abs(cosphi) > 0.9) {
1585 xalign = 2;
1586 } else {
1587 if (cosphi*sinphi > 0) xalign = 1;
1588 if (cosphi*sinphi < 0) xalign = 3;
1589 }
1590 textaxis.SetTextAlign(10*xalign+yalign);
1591
1592// Position of labels in Y
1593 if (x0 == x1) {
1594 if (optionPlus && !optionMinus) {
1595 if (optionEqual) ylabel = fLabelOffset/2 + atick[0];
1596 else ylabel = -fLabelOffset;
1597 } else {
1599 if (lside < 0) ylabel += atick[0];
1600 }
1601 } else if (y0 == y1) {
1602 if (optionMinus && !optionPlus) {
1603 if ((GetLabelFont() % 10) == 3 ) {
1604 ylabel = fLabelOffset+0.5*
1605 ((gPad->AbsPixeltoY(0)-gPad->AbsPixeltoY((Int_t)fLabelSize))/
1606 (gPad->GetY2() - gPad->GetY1()));
1607 } else {
1609 }
1610 ylabel += TMath::Abs(atick[0]);
1611 } else {
1613 if (mside <= 0) ylabel -= TMath::Abs(atick[0]);
1614 }
1615 if (optionLog) ylabel -= 0.5*charheight;
1616 } else {
1617 if (mside+lside >= 0) ylabel = fLabelOffset;
1618 else ylabel = -fLabelOffset;
1619 }
1620 if (optionText) ylabel /= 2;
1621
1622// Draw the linear tick marks if needed...
1623 if (!optionLog && ndiv) {
1624 if (fFunction) {
1625 dxtick = (binHigh-binLow)/Double_t(nticks-1);
1626 axis_length0 = binLow-wmin;
1627 axis_length1 = wmax-binHigh;
1628 } else {
1631 }
1632 if (!optionNoopt || optionInt) {
1633 if (axis_length0)
1634 nticks0 = TMath::Min(Int_t(axis_length0/dxtick + epsilon), 1000);
1635 if (axis_length1)
1636 nticks1 = TMath::Min(Int_t(axis_length1/dxtick + epsilon), 1000);
1637 }
1638
1639 std::vector<Double_t> ticksx, ticksy, gridx, gridy;
1640 if (!drawGridOnly) {
1641 ticksx.reserve(nticks + nticks0 + nticks1);
1642 ticksy.reserve(nticks + nticks0 + nticks1);
1643 }
1644 if (optionGrid) {
1645 gridx.reserve((nticks + nticks0 + nticks1) / nn2 + 2);
1646 gridy.reserve((nticks + nticks0 + nticks1) / nn2 + 2);
1647 }
1648
1649 auto draw_tick = [&](int indx, double xtick, double xf) {
1650 int ltick;
1651 if (indx % nn2 == 0)
1652 ltick = 0;
1653 else if (indx % nn3 == 0)
1654 ltick = 1;
1655 else
1656 ltick = 2;
1657
1658 if (fFunction) {
1661 }
1662
1663 Double_t ytick = mside ? 0. : -atick[ltick];
1664 if (optionNoopt && !optionInt) {
1667 } else {
1670 }
1671 if (optionVert) {
1672 if ((x0 != x1) && (y0 != y1)) {
1673 if (mside) {
1674 xpl1 = xpl2;
1675 if (cosphi > 0) ypl1 = ypl2 + atick[ltick];
1676 else ypl1 = ypl2 - atick[ltick];
1677 } else {
1678 xpl1 = 0.5*(xpl1 + xpl2);
1679 xpl2 = xpl1;
1680 ypl1 = 0.5*(ypl1 + ypl2) + atick[ltick];
1681 ypl2 = 0.5*(ypl1 + ypl2) - atick[ltick];
1682 }
1683 }
1684 }
1685 if (!drawGridOnly) {
1687 if (optionArrow == 1)
1688 paint_tick = (x1 != x0) ? (xpl2 < x1) : (ypl2 < y1);
1689 else if (optionArrow == 2)
1690 paint_tick = (x1 != x0) ? (xpl1 > x0) : (ypl1 > y0);
1691 else if (optionArrow == 3)
1692 paint_tick = (x1 != x0) ? (xpl1 > x0 && xpl2 < x1) : (ypl1 > y0 && ypl2 < y1);
1693 if (paint_tick) {
1694 ticksx.push_back(xpl1);
1695 ticksx.push_back(xpl2);
1696 ticksy.push_back(ypl1);
1697 ticksy.push_back(ypl2);
1698 }
1699 }
1700
1701 if (optionGrid && (ltick == 0)) {
1702 if (optionNoopt && !optionInt) {
1705 } else {
1708 }
1709 gridx.push_back(xpl1);
1710 gridx.push_back(xpl2);
1711 gridy.push_back(ypl1);
1712 gridy.push_back(ypl2);
1713 }
1714 };
1715
1716 for (k = 0; k < nticks; k++)
1717 draw_tick(k, Double_t(k) * dxtick, binLow + Double_t(k)*dxtick);
1718
1719 for (k = 1; k <= nticks0; k++)
1720 draw_tick(k, -1. * Double_t(k) * dxtick, binLow - Double_t(k)*dxtick);
1721
1722 for (k = 1; k <= nticks1; k++)
1723 draw_tick(k, Double_t(nticks-1 + k) * dxtick, binHigh + Double_t(k)*dxtick);
1724
1725 // paint ticks all together with one command
1726 if (ticksx.size() > 0) {
1728 gPad->PaintSegmentsNDC(ticksx.size() / 2, ticksx.data(), ticksy.data());
1729 }
1730
1731 // paint grid lines all together after ticks
1732 if (gridx.size() > 0) {
1733 linegrid.TAttLine::Modify();
1734 gPad->PaintSegmentsNDC(gridx.size() / 2, gridx.data(), gridy.data());
1735 }
1736 }
1737
1738// Draw the numeric labels if needed...
1739 if (!drawGridOnly && !optionUnlab) {
1740 if (!optionLog) {
1741 if (n1a) {
1742// Spacing of labels
1743 if ((wmin == wmax) || (ndiv == 0)) {
1744 Error(where, "wmin (%f) == wmax (%f), or ndiv == 0", wmin, wmax);
1745 return;
1746 }
1747 wlabel = wmin;
1751
1752 if (!optionText && !optionTime) {
1753
1754// We have to decide what format to generate
1755// (for numeric labels only)
1756// Test the magnitude, decide format
1757 flexe = kFALSE;
1758 nexe = 0;
1759 flexpo = kFALSE;
1760 flexne = kFALSE;
1762
1763// First case : (wmax-wmin)/n1a less than 0.001
1764// (0.001 fgMaxDigits of 5 (fgMaxDigits) characters). Then we use x 10 n
1765// format. If af >=0 x10 n cannot be used
1766 Double_t xmicros = 0.00099;
1769 af = TMath::Log10(ww) + epsilon;
1770 if (af < 0) {
1771 flexe = kTRUE;
1772 nexe = int(af);
1773 iexe = TMath::Abs(nexe);
1774 if (iexe%3 == 1) iexe += 2;
1775 else if(iexe%3 == 2) iexe += 1;
1776 if (nexe < 0) nexe = -iexe;
1777 else nexe = iexe;
1780 if1 = maxDigits;
1781 if2 = maxDigits-2;
1782 goto L110;
1783 }
1784 }
1785 if (ww >= 1) af = TMath::Log10(ww);
1786 else af = TMath::Log10(ww*0.0001);
1787 af += epsilon;
1788 nf = Int_t(af)+1;
1789 if (!noExponent && nf > maxDigits) flexpo = kTRUE;
1790 if (!noExponent && nf < -maxDigits) flexne = kTRUE;
1791
1792// Use x 10 n format. (only powers of 3 allowed)
1793
1794 if (flexpo) {
1795 flexe = kTRUE;
1796 while (true) {
1797 nexe++;
1798 ww /= 10;
1799 wlabel /= 10;
1800 dwlabel /= 10;
1801 if (nexe%3 == 0 && ww <= TMath::Power(10,maxDigits-1)) break;
1802 }
1803 }
1804
1805 if (flexne) {
1806 flexe = kTRUE;
1807 rne = 1/TMath::Power(10,maxDigits-2);
1808 while (true) {
1809 nexe--;
1810 ww *= 10;
1811 wlabel *= 10;
1812 dwlabel *= 10;
1813 if (nexe%3 == 0 && ww >= rne) break;
1814 }
1815 }
1816
1817 na = 0;
1818 for (i=maxDigits-1; i>0; i--) {
1819 if (TMath::Abs(ww) < TMath::Power(10,i)) na = maxDigits-i;
1820 }
1821 ndyn = n1a;
1822 while (ndyn) {
1824 if (wdyn <= 0.999 && na < maxDigits-2) {
1825 na++;
1826 ndyn /= 10;
1827 }
1828 else break;
1829 }
1830// if1 and if2 are the two digits defining the format used to produce the
1831// labels. The format used will be %[if1].[if2]f .
1832// if1 and if2 are positive (small) integers.
1833 if2 = na;
1835L110:
1836 if (TMath::Min(wmin,wmax) < 0)if1 = if1+1;
1837 if1 = TMath::Min(if1,32);
1838
1839// In some cases, if1 and if2 are too small....
1840 while (dwlabel < TMath::Power(10,-if2)) {
1841 if1++;
1842 if2++;
1843 }
1844 if (if1 > 14) if1 = 14;
1845 if (if2 > 14) if2 = 14;
1846 if (if1 < 0) if1 = 0;
1847 int len = 0;
1848 if (if2 > 0) {
1849 len = snprintf(chcoded,sizeof(chcoded),"%%%d.%df",if1,if2);
1850 } else {
1851 len = snprintf(chcoded,sizeof(chcoded),"%%%d.%df",if1+1,1);
1852 }
1853 // check improbable error condition, suppress gcc9 warnings
1854 if ((len < 0) || (len >= (int) sizeof(chcoded)))
1855 strcpy(chcoded,"%7.3f");
1856 }
1857
1858// We draw labels
1859
1860 snprintf(chtemp,256,"%g",dwlabel);
1861 Int_t ndecimals = 0;
1862 if (optionDecimals) {
1863 char *dot = strchr(chtemp,'.');
1864 if (dot) {
1865 ndecimals = chtemp + strlen(chtemp) -dot;
1866 } else {
1867 char *exp;
1868 exp = strstr(chtemp,"e-");
1869 if (exp) {
1870 sscanf(&exp[2],"%d",&ndecimals);
1871 ndecimals++;
1872 }
1873 }
1874 }
1875 if (optionM) nlabels = n1a-1;
1876 else nlabels = n1a;
1877 wTimeIni = wlabel;
1878 for ( k=0; k<=nlabels; k++) {
1879 if (fFunction) {
1880 Double_t xf = binLow+Double_t(k*nn2)*dxtick;
1882 wlabel = xf;
1884 } else {
1885 xlabel = dxlabel*k;
1886 }
1887 if (optionM) xlabel += 0.5*dxlabel;
1888
1890
1891 if (!optionText && !optionTime) {
1892 snprintf(label,256,chcoded,wlabel);
1893
1894 label[28] = 0;
1895 wlabel += dwlabel;
1896
1897 LabelsLimits(label,first,last); //Eliminate blanks
1898
1899 if (label[first] == '.') { //check if '.' is preceded by a digit
1900 strncpy(chtemp, "0", 256);
1901 strlcat(chtemp, &label[first],256);
1902 strlcpy(label, chtemp, 256);
1903 first = 1; last = strlen(label);
1904 }
1905 if (label[first] == '-' && label[first+1] == '.') {
1906 strncpy(chtemp, "-0",256);
1907 strlcat(chtemp, &label[first+1],256);
1908 strlcpy(label, chtemp, 256);
1909 first = 1; last = strlen(label);
1910 }
1911
1912// We eliminate the non significant 0 after '.'
1913 if (ndecimals) {
1914 char *adot = strchr(label,'.');
1915 if (adot) adot[ndecimals] = 0;
1916 } else {
1917 while (label[last] == '0') { label[last] = 0; last--;}
1918 }
1919
1920// We eliminate the dot, unless dot is forced.
1921 if (label[last] == '.') {
1922 if (!optionDot) { label[last] = 0; last--;}
1923 }
1924
1925// Make sure the label is not "-0"
1926 if (last-first == 1 && label[first] == '-'
1927 && label[last] == '0') {
1928 strncpy(label, "0", 256);
1929 label[last] = 0;
1930 }
1931 }
1932
1933// Generate the time labels
1934
1935 if (optionTime) {
1937 timelabel = (time_t)((Long_t)(timed));
1938 if (optionTime == 1) {
1940 } else {
1942 }
1944 if (timeformat.Length() < 220) timeformattmp = timeformat;
1945 else timeformattmp = "#splitline{Format}{too long}";
1946
1947// Appends fractional part if seconds displayed
1948 if (dwlabel<0.9) {
1949 double tmpdb;
1950 int tmplast;
1951 snprintf(label, 256, "%%S%7.5f", modf(timed,&tmpdb));
1952 tmplast = strlen(label)-1;
1953
1954// We eliminate the non significant 0 after '.'
1955 while (label[tmplast] == '0') {
1956 label[tmplast] = 0; tmplast--;
1957 }
1958
1959 timeformattmp.ReplaceAll("%S",label);
1960// replace the "0." at the beginning by "s"
1961 timeformattmp.ReplaceAll("%S0.","%Ss");
1962
1963 }
1964
1965 if (utctis != nullptr) {
1966 strftime(label, 256, timeformattmp.Data(), utctis);
1967 } else {
1968 strncpy(label, "invalid", 256);
1969 }
1970 strlcpy(chtemp, &label[0], 256);
1971 first = 0; last=strlen(label)-1;
1972 wlabel = wTimeIni + (k+1)*dwlabel;
1973 }
1974
1975// We generate labels (numeric or alphanumeric).
1976
1977 if (optionNoopt && !optionInt)
1980 if (y0 == y1 && !optionDown && !optionUp) {
1981 yy -= 0.80*charheight;
1982 }
1983 if (optionVert) {
1984 if (x0 != x1 && y0 != y1) {
1985 if (optionNoopt && !optionInt)
1986 Rotate (xlabel,0,cosphi,sinphi,x0,y0,xx,yy);
1987 else Rotate (xlabel,0,cosphi,sinphi,xx0,yy0,xx,yy);
1988 if (cosphi > 0 ) yy += ylabel;
1989 if (cosphi < 0 ) yy -= ylabel;
1990 }
1991 }
1992 if (!optionY || (x0 == x1)) {
1993 if (!optionText) {
1994 if (first > last) strncpy(chtemp, " ", 256);
1995 else strlcpy(chtemp, &label[first], 255);
1997 typolabel = chtemp;
1998 if (!optionTime) typolabel.ReplaceAll("-", "#minus");
1999 if (autotoff) {
2000 UInt_t w,h;
2001 textaxis.SetText(0.,0., typolabel.Data());
2002 textaxis.GetBoundingBox(w,h);
2003 double scale=gPad->GetWw()*gPad->GetWNDC();
2004 if (scale>0.0) toffset = TMath::Max(toffset,(double)w/scale);
2005 }
2006 textaxis.PaintLatex(gPad->GetX1() + xx*(gPad->GetX2() - gPad->GetX1()),
2007 gPad->GetY1() + yy*(gPad->GetY2() - gPad->GetY1()),
2008 textaxis.GetTextAngle(),
2009 textaxis.GetTextSize(),
2010 typolabel.Data());
2012 } else {
2015 if (optionText == 1) textaxis.PaintLatex(gPad->GetX1() + xx*(gPad->GetX2() - gPad->GetX1()),
2016 gPad->GetY1() + yy*(gPad->GetY2() - gPad->GetY1()),
2017 0,
2018 textaxis.GetTextSize(),
2019 chtemp);
2021 }
2022 } else {
2023
2024// Text alignment is down
2025 if (!optionText) lnlen = last-first+1;
2026 else {
2027 if (k+1 > nhilab) lnlen = 0;
2028 }
2029 for ( l=1; l<=lnlen; l++) {
2030 if (!optionText) *chtemp = label[first+l-2];
2031 else {
2032 if (lnlen == 0) strncpy(chtemp, " ", 256);
2033 else strncpy(chtemp, "1", 256);
2034 }
2035 typolabel = chtemp;
2036 typolabel.ReplaceAll("-", "#minus");
2037 textaxis.PaintLatex(gPad->GetX1() + xx*(gPad->GetX2() - gPad->GetX1()),
2038 gPad->GetY1() + yy*(gPad->GetY2() - gPad->GetY1()),
2039 0,
2040 textaxis.GetTextSize(),
2041 typolabel.Data());
2042 yy -= charheight*1.3;
2043 }
2044 }
2045 }
2046
2047// We use the format x 10 ** n
2048
2049 if (flexe && !optionText && nexe) {
2050 snprintf(label,256,"#times10^{%d}", nexe);
2051 if (x0 != x1) { xfactor = axis_length+0.1*charheight; yfactor = 0; }
2052 else { xfactor = y1-y0+0.1*charheight; yfactor = 0; }
2054 textaxis.SetTextAlign(11);
2055 if (GetLabelFont()%10 < 2) // force TLatex mode in PaintLatex
2056 textaxis.SetTextFont((Int_t)(GetLabelFont()/10)*10+2);
2057 if (fAxis && !strcmp(fAxis->GetName(),"xaxis")) {
2058 Float_t xoff = 0., yoff = 0.;
2060 xx += xoff;
2061 yy += yoff;
2062 }
2063 if (fAxis && !strcmp(fAxis->GetName(),"yaxis")) {
2064 Float_t xoff = 0., yoff = 0.;
2066 xx += xoff;
2067 yy += yoff;
2068 }
2069 typolabel = label;
2070 typolabel.ReplaceAll("-", "#minus");
2071 textaxis.PaintLatex(gPad->GetX1() + xx*(gPad->GetX2() - gPad->GetX1()),
2072 gPad->GetY1() + yy*(gPad->GetY2() - gPad->GetY1()),
2073 0,
2074 textaxis.GetTextSize(),
2075 typolabel.Data());
2076 }
2077 }
2078 }
2079 }
2080
2081// Log axis
2082
2083 if (optionLog && ndiv) {
2084 UInt_t xi1=0,xi2=0,wi=0,yi1=0,yi2=0,hi=0,xl=0,xh=0;
2086 if ((wmin == wmax) || (ndiv == 0)) {
2087 Error(where, "wmin (%f) == wmax (%f), or ndiv == 0", wmin, wmax);
2088 return;
2089 }
2090 if (wmin <= 0) {
2091 Error(where, "negative logarithmic axis");
2092 return;
2093 }
2094 if (wmax <= 0) {
2095 Error(where, "negative logarithmic axis");
2096 return;
2097 }
2099 if (xmnlog > 0) xmnlog += 1.E-6;
2100 else xmnlog -= 1.E-6;
2101 x00 = 0;
2102 x11 = axis_length;
2103 h2 = TMath::Log10(wmax);
2104 h2sav = h2;
2105 if (h2 > 0) h2 += 1.E-6;
2106 else h2 -= 1.E-6;
2107 ih1 = int(xmnlog);
2108 ih2 = 1+int(h2);
2109 nbinin = ih2-ih1+1;
2110 axmul = (x11-x00)/(h2sav-xmnlog);
2111
2112 std::vector<Double_t> ticksx, ticksy, gridsx, gridsy;
2113
2114 if (!drawGridOnly) {
2115 ticksx.reserve(nbinin*2);
2116 ticksy.reserve(nbinin*2);
2117 }
2118 if (optionGrid) {
2119 gridsx.reserve(nbinin*2);
2120 gridsy.reserve(nbinin*2);
2121 }
2122
2123 struct LogLabel {
2124 Int_t id = 0, num = 0;
2125 Double_t u = 0., v = 0., value = 0.;
2126 TString lbl;
2127 };
2128 std::vector<LogLabel> loglabels;
2129 if (!drawGridOnly && !optionUnlab)
2130 loglabels.reserve(nbinin);
2131
2132
2133// Plot decade and intermediate tick marks
2134 decade = ih1-2;
2135 labelnumber = ih1;
2136 if ( xmnlog > 0 && (xmnlog-Double_t(ih1) > 0) ) labelnumber++;
2139 for (j=1; j<=nbinin; j++) {
2140
2141// Plot decade
2143 decade++;
2144 if (x0 == x1 && j == 1) ylabel += charheight*0.33;
2145 if (y0 == y1 && j == 1) ylabel -= charheight*0.65;
2147 //the following statement is a trick to circumvent a gcc bug
2148 if (j < 0) printf("j=%d\n",j);
2149 if (x00 > xone) goto L160;
2150 if ((xone-x11)>epsilon) break;
2151 xtwo = xone;
2152 y = 0;
2153 if (!mside) y -= atick[0];
2156 if (optionVert) {
2157 if ((x0 != x1) && (y0 != y1)) {
2158 if (mside) {
2159 xpl1=xpl2;
2160 if (cosphi > 0) ypl1 = ypl2 + atick[0];
2161 else ypl1 = ypl2 - atick[0];
2162 }
2163 else {
2164 xpl1 = 0.5*(xpl1 + xpl2);
2165 xpl2 = xpl1;
2166 ypl1 = 0.5*(ypl1 + ypl2) + atick[0];
2167 ypl2 = 0.5*(ypl1 + ypl2) - atick[0];
2168 }
2169 }
2170 }
2171 if (!drawGridOnly) {
2172 ticksx.emplace_back(xpl1);
2173 ticksx.emplace_back(xpl2);
2174 ticksy.emplace_back(ypl1);
2175 ticksy.emplace_back(ypl2);
2176 }
2177
2178 if (optionGrid) {
2181 gridsx.emplace_back(xpl1);
2182 gridsx.emplace_back(xpl2);
2183 gridsy.emplace_back(ypl1);
2184 gridsy.emplace_back(ypl2);
2185 }
2186
2187 if (!drawGridOnly && !optionUnlab) {
2188
2189// We generate labels (numeric only).
2191 if (noExponent) {
2193 snprintf(label,256, "%f", rlab);
2194 LabelsLimits(label,first,last);
2195 while (last > first) {
2196 if (label[last] != '0') break;
2197 label[last] = 0;
2198 last--;
2199 }
2200 if (label[last] == '.') {label[last] = 0; last--;}
2201 } else {
2202 snprintf(label,256, "%d", labelnumber);
2203 LabelsLimits(label,first,last);
2204 }
2206 if ((x0 == x1) && !optionPara) {
2207 if (lside < 0) {
2208 if (mside < 0) {
2209 if (labelnumber == 0) nch=1;
2210 else nch=2;
2211 xx += nch*charheight;
2212 } else {
2213 xx += 0.25*charheight;
2214 }
2215 }
2216 xx += 0.25*charheight;
2217 }
2218 if ((y0 == y1) && !optionDown && !optionUp) {
2219 if (noExponent) yy += 0.33*charheight;
2220 }
2221 if (n1a == 0) return;
2222 kmod = nbinin/n1a;
2223 if (kmod == 0) kmod=1000000;
2224 if ((nbinin <= n1a) || (j == 1) || (j == nbinin) || ((nbinin > n1a) && (j%kmod == 0))) {
2225 if (labelnumber == 0) {
2226 snprintf(chtemp,256, "1");
2227 } else if (labelnumber == 1) {
2228 snprintf(chtemp,256, "10");
2229 } else {
2230 if (noExponent) {
2231 chtemp = &label[first];
2232 } else {
2233 snprintf(chtemp,256, "10^{%d}", labelnumber);
2234 }
2235 }
2236 if (fNModLabs) {
2240 }
2241 typolabel = chtemp;
2242 typolabel.ReplaceAll("-", "#minus");
2243 if (autotoff) {
2244 UInt_t w,h;
2245 textaxis.SetText(0.,0., typolabel.Data());
2246 textaxis.GetBoundingBox(w,h);
2247 double scale=gPad->GetWw()*gPad->GetWNDC();
2248 if (scale>0.0) toffset = TMath::Max(toffset,(double)w/scale);
2249 }
2250 loglabels.emplace_back();
2251 auto &back = loglabels.back();
2252 back.id = changelablogid;
2253 back.num = changelablognum;
2254 back.u = gPad->GetX1() + xx*(gPad->GetX2() - gPad->GetX1());
2255 back.v = gPad->GetY1() + yy*(gPad->GetY2() - gPad->GetY1());
2256 back.value = axis_value;
2257 back.lbl = typolabel;
2259 }
2260 labelnumber++;
2261 }
2262L160:
2263 for (k=2;k<10;k++) {
2264
2265// Plot intermediate tick marks
2267 if (x00 > xone) continue;
2268 if (xone > x11) goto L200;
2269 y = 0;
2270 if (!mside) y -= atick[1];
2271 xtwo = xone;
2274 if (optionVert) {
2275 if ((x0 != x1) && (y0 != y1)) {
2276 if (mside) {
2277 xpl1 = xpl2;
2278 if (cosphi > 0) ypl1 = ypl2 + atick[1];
2279 else ypl1 = ypl2 - atick[1];
2280 }
2281 else {
2282 xpl1 = 0.5*(xpl1+xpl2);
2283 xpl2 = xpl1;
2284 ypl1 = 0.5*(ypl1+ypl2) + atick[1];
2285 ypl2 = 0.5*(ypl1+ypl2) - atick[1];
2286 }
2287 }
2288 }
2289 idn = n1a*2;
2290 if ((nbinin <= idn) || ((nbinin > idn) && (k == 5))) {
2291 if (!drawGridOnly) {
2292 ticksx.emplace_back(xpl1);
2293 ticksx.emplace_back(xpl2);
2294 ticksy.emplace_back(ypl1);
2295 ticksy.emplace_back(ypl2);
2296 }
2297
2298// Draw the intermediate LOG labels if requested
2299
2302 if (noExponent) {
2303 rlab = axis_value;
2304 snprintf(chtemp,256, "%g", rlab);
2305 } else {
2306 if (labelnumber-1 == 0) {
2307 snprintf(chtemp,256, "%d", k);
2308 } else if (labelnumber-1 == 1) {
2309 snprintf(chtemp,256, "%d", 10*k);
2310 } else {
2311 snprintf(chtemp,256, "%d#times10^{%d}", k, labelnumber-1);
2312 }
2313 }
2315 if ((x0 == x1) && !optionPara) {
2316 if (lside < 0) {
2317 if (mside < 0) {
2318 if (labelnumber == 0) nch=1;
2319 else nch=2;
2320 xx += nch*charheight;
2321 } else {
2322 if (labelnumber >= 0) xx += 0.25*charheight;
2323 else xx += 0.50*charheight;
2324 }
2325 }
2326 xx += 0.25*charheight;
2327 }
2328 if ((y0 == y1) && !optionDown && !optionUp) {
2329 if (noExponent) yy += 0.33*charheight;
2330 }
2331 if (optionVert) {
2332 if ((x0 != x1) && (y0 != y1)) {
2334 if (cosphi > 0) yy += ylabel;
2335 else yy -= ylabel;
2336 }
2337 }
2338 textaxis.SetTitle(chtemp);
2339 Double_t u = gPad->GetX1() + xx*(gPad->GetX2() - gPad->GetX1());
2340 Double_t v = gPad->GetY1() + yy*(gPad->GetY2() - gPad->GetY1());
2341 if (firstintlab) {
2342 textaxis.GetBoundingBox(wi, hi); wi=(UInt_t)(wi*1.3); hi=(UInt_t)(hi*1.3);
2343 xi1 = gPad->XtoAbsPixel(u);
2344 yi1 = gPad->YtoAbsPixel(v);
2346 if (fNModLabs) {
2349 }
2350 typolabel = chtemp;
2351 typolabel.ReplaceAll("-", "#minus");
2352 loglabels.emplace_back();
2353 auto &back = loglabels.back();
2354 back.id = changelablogid;
2355 back.num = 0;
2356 back.u = u;
2357 back.v = v;
2358 back.value = axis_value;
2359 back.lbl = typolabel;
2361 } else {
2362 xi2 = gPad->XtoAbsPixel(u);
2363 yi2 = gPad->YtoAbsPixel(v);
2364 xl = TMath::Min(xi1,xi2);
2365 xh = TMath::Max(xi1,xi2);
2366 if ((x0 == x1 && yi1-hi <= yi2) || (y0 == y1 && xl+wi >= xh)){
2367 overlap = kTRUE;
2368 } else {
2369 xi1 = xi2;
2370 yi1 = yi2;
2371 textaxis.GetBoundingBox(wi, hi); wi=(UInt_t)(wi*1.3); hi=(UInt_t)(hi*1.3);
2372 if (fNModLabs) {
2375 }
2376 typolabel = chtemp;
2377 typolabel.ReplaceAll("-", "#minus");
2378 loglabels.emplace_back();
2379 auto &back = loglabels.back();
2380 back.id = changelablogid;
2381 back.num = 0;
2382 back.u = u;
2383 back.v = v;
2384 back.value = axis_value;
2385 back.lbl = typolabel;
2387 }
2388 }
2389 }
2390
2391// Draw the intermediate LOG grid if only three decades are requested
2392 if (optionGrid && nbinin <= 5 && ndiv > 100) {
2395 gridsx.emplace_back(xpl1);
2396 gridsx.emplace_back(xpl2);
2397 gridsy.emplace_back(ypl1);
2398 gridsy.emplace_back(ypl2);
2399 }
2400 } //endif ((nbinin <= idn) ||
2401 } //endfor (k=2;k<10;k++)
2402 } //endfor (j=1; j<=nbinin; j++)
2403L200:
2404 // paint ticks all together with one command
2405 if (ticksx.size() > 0) {
2407 gPad->PaintSegmentsNDC(ticksx.size() / 2, ticksx.data(), ticksy.data());
2408 }
2409
2410 // paint all labels after ticks
2411 for(auto & lbl : loglabels) {
2412 if (fNModLabs)
2413 ChangeLabelAttributes(lbl.id, lbl.num, &textaxis, chtemp, lbl.value, lbl.value*1e-6);
2414 textaxis.PaintLatex(lbl.u, lbl.v, 0, textaxis.GetTextSize(), lbl.lbl.Data());
2415 if (fNModLabs)
2417 }
2418
2419 // paint grid lines all together at the end
2420 if (gridsx.size() > 0) {
2421 linegrid.TAttLine::Modify();
2422 gPad->PaintSegmentsNDC(gridsx.size() / 2, gridsx.data(), gridsy.data());
2423 }
2424
2425 } //endif (optionLog && ndiv)
2426
2427// Draw axis title if it exists
2428 if (!drawGridOnly && strlen(GetTitle())) {
2429 textaxis.SetTextSize (GetTitleSize());
2431 if ((GetTextFont() % 10) > 2) {
2432 charheight /= ((x1==x0) ? padw : padh);
2433 }
2434 if (x1 == x0) {
2435 if (autotoff) {
2437 else ylabel = xlside*1.6*charheight;
2438 } else {
2440 }
2441 } else {
2443 }
2444 if (y1 == y0) {
2445 if (toffset == 0.) toffset = gStyle->GetTitleOffset("X");
2447 }
2450 else axispos = axis_length;
2452 if (x1 >= x0) {
2453 if (TestBit(TAxis::kCenterTitle)) textaxis.SetTextAlign(22);
2454 else textaxis.SetTextAlign(12);
2455 } else {
2456 if (TestBit(TAxis::kCenterTitle)) textaxis.SetTextAlign(22);
2457 else textaxis.SetTextAlign(32);
2458 }
2459 phil+=kPI;
2460 } else {
2461 if (x1 >= x0) {
2462 if (TestBit(TAxis::kCenterTitle)) textaxis.SetTextAlign(22);
2463 else textaxis.SetTextAlign(32);
2464 } else {
2465 if (TestBit(TAxis::kCenterTitle)) textaxis.SetTextAlign(22);
2466 else textaxis.SetTextAlign(12);
2467 }
2468 }
2470 textaxis.SetTextColor(TitleColor);
2471 textaxis.SetTextFont(TitleFont);
2472 textaxis.PaintLatex(gPad->GetX1() + xpl1*(gPad->GetX2() - gPad->GetX1()),
2473 gPad->GetY1() + ypl1*(gPad->GetY2() - gPad->GetY1()),
2474 phil*180/kPI,
2475 GetTitleSize(),
2476 GetTitle());
2477 }
2478
2479}
2480
2481////////////////////////////////////////////////////////////////////////////////
2482/// Internal method for axis labels optimisation. This method adjusts the bining
2483/// of the axis in order to have integer values for the labels.
2484///
2485/// \param[in] A1,A2 Old WMIN,WMAX
2486/// \param[out] binLow,binHigh New WMIN,WMAX
2487/// \param[in] nold Old NDIV (primary divisions)
2488/// \param[out] nbins New NDIV
2489/// \param[out] binWidth Bin width
2490
2492 ,Double_t &binLow, Double_t &binHigh, Int_t &nbins, Double_t &binWidth)
2493{
2494
2495 binWidth = TMath::Abs(A2-A1)/Double_t(nold);
2496 if (binWidth <= 1) { binWidth = 1; binLow = int(A1); }
2497 else {
2498 Int_t width = int(binWidth/5) + 1;
2499 binWidth = 5*width;
2500 binLow = int(A1/binWidth)*binWidth;
2501
2502// We determine binLow to have one tick mark at 0
2503// if there are negative labels.
2504
2505 if (A1 < 0) {
2506 for (Int_t ic=0; ic<1000; ic++) {
2507 Double_t rbl = binLow/binWidth;
2508 Int_t ibl = int(binLow/binWidth);
2509 if ( (rbl-ibl) == 0 || ic > width) { binLow -= 5; break;}
2510 }
2511 }
2512 }
2513 binHigh = int(A2);
2514 nbins = 0;
2515 Double_t xb = binLow;
2516 while (xb <= binHigh) {
2517 xb += binWidth;
2518 nbins++;
2519 }
2520 binHigh = xb - binWidth;
2521}
2522
2523////////////////////////////////////////////////////////////////////////////////
2524/// Internal method to find first and last character of a label.
2525
2526void TGaxis::LabelsLimits(const char *label, Int_t &first, Int_t &last)
2527{
2528 last = strlen(label)-1;
2529 for (Int_t i=0; i<=last; i++) {
2530 if (strchr("1234567890-+.", label[i]) ) { first = i; return; }
2531 }
2532 Error("LabelsLimits", "attempt to draw a blank label");
2533}
2534
2535////////////////////////////////////////////////////////////////////////////////
2536/// Internal method to rotate axis coordinates.
2537
2539 ,Double_t XT, Double_t YT, Double_t &U, Double_t &V)
2540{
2541 U = CFI*X-SFI*Y+XT;
2542 V = SFI*X+CFI*Y+YT;
2543}
2544
2545////////////////////////////////////////////////////////////////////////////////
2546/// Save primitive as a C++ statement(s) on output stream out
2547
2548void TGaxis::SavePrimitive(std::ostream &out, Option_t *option)
2549{
2550 SavePrimitiveConstructor(out, Class(), "gaxis",
2551 TString::Format("%g, %g, %g, %g, %14.12g, %14.12g, %d, \"%s\", %g", fX1, fY1, fX2, fY2,
2553
2554 SaveLineAttributes(out, "gaxis", 1, 1, 1);
2555 SaveTextAttributes(out, "gaxis", 11, 0, 1, 62, 0.04);
2556
2557 if (strlen(GetName()))
2558 out << " gaxis->SetName(\"" << GetName() << "\");\n";
2559 if (strlen(GetTitle()))
2560 out << " gaxis->SetTitle(\"" << TString(GetTitle()).ReplaceSpecialCppChars() << "\");\n";
2561 if (fTimeFormat.Length() > 0)
2562 out << " gaxis->SetTimeFormat(\"" << TString(fTimeFormat).ReplaceSpecialCppChars() << "\");\n";
2563
2564 out << " gaxis->SetLabelOffset(" << GetLabelOffset() << ");\n";
2565 out << " gaxis->SetLabelSize(" << GetLabelSize() << ");\n";
2566 if (fLabelColor != 1)
2567 out << " gaxis->SetLabelColor(" << TColor::SavePrimitiveColor(GetLabelColor()) << ");\n";
2568 if (fLabelFont != 62)
2569 out << " gaxis->SetLabelFont(" << GetLabelFont() << ");\n";
2571 out << " gaxis->SetMoreLogLabels();\n";
2572
2573 out << " gaxis->SetTickSize(" << GetTickSize() << ");\n";
2574 out << " gaxis->SetTitleOffset(" << GetTitleOffset() << ");\n";
2575 out << " gaxis->SetTitleSize(" << GetTitleSize() << ");\n";
2576
2578 out << " gaxis->SetNoExponent();\n";
2579 if (fModLabs) {
2580 TIter next(fModLabs);
2581 while (auto ml = static_cast<TAxisModLab *>(next())) {
2582 if (ml->GetLabNum() == 0)
2583 out << " gaxis->ChangeLabelByValue(" << ml->GetLabValue();
2584 else
2585 out << " gaxis->ChangeLabel(" << ml->GetLabNum();
2586 out << ", " << ml->GetAngle() << ", " << ml->GetSize() << ", " << ml->GetAlign() << ", "
2587 << TColor::SavePrimitiveColor(ml->GetColor()) << ", " << ml->GetFont() << ", \""
2588 << TString(ml->GetText()).ReplaceSpecialCppChars() << "\");\n";
2589 }
2590 }
2591
2592 SavePrimitiveDraw(out, "gaxis", option);
2593}
2594
2595////////////////////////////////////////////////////////////////////////////////
2596/// Set the decimals flag. By default, blank characters are stripped, and then the
2597/// label is correctly aligned. The dot, if last character of the string, is also
2598/// stripped, unless this option is specified. One can disable the option by
2599/// calling `axis.SetDecimals(kTRUE)`.
2600/// Note the bit is set in fBits (as opposed to fBits2 in TAxis!)
2601
2603{
2604 if (dot) SetBit(TAxis::kDecimals);
2606}
2607
2608////////////////////////////////////////////////////////////////////////////////
2609/// Specify a function to map the axis values.
2610
2612{
2614 if (!funcname || !funcname[0]) {
2615 fFunction = nullptr;
2616 return;
2617 }
2618 fFunction = (TF1*)gROOT->GetFunction(funcname);
2619 if (!fFunction) {
2620 Error("SetFunction", "unknown function: %s", funcname);
2621 } else {
2622 fWmin = fFunction->GetXmin();
2623 fWmax = fFunction->GetXmax();
2624 }
2625}
2626
2627////////////////////////////////////////////////////////////////////////////////
2628/// Search for axis modifier by index or value
2629
2631{
2632 if (!fModLabs)
2633 return nullptr;
2634
2635 TIter next(fModLabs);
2636 while (auto ml = (TAxisModLab*)next()) {
2637
2638 if (ml->GetLabNum() == 0) {
2639 if (TMath::Abs(v - ml->GetLabValue()) <= eps)
2640 return ml;
2641 } else if (indx != 0) {
2642 Bool_t match = ml->GetLabNum() == indx;
2643 if (!match && (ml->GetLabNum() < 0) && (indx > 0) && (numlabels > 0)) {
2645 Error("FindModLab", "reverse numbering in ChangeLabel doesn't work when more log labels are requested");
2646 return nullptr;
2647 }
2648
2649 match = indx == (ml->GetLabNum() + 2 + numlabels);
2650 }
2651 if (match) return ml;
2652 }
2653 }
2654
2655 return nullptr;
2656}
2657
2658
2659////////////////////////////////////////////////////////////////////////////////
2660/// Define new text attributes for the label number "labNum". It allows to do a
2661/// fine tuning of the labels. All the attributes can be changed, even the
2662/// label text itself.
2663///
2664/// \param[in] labNum Number of the label to be changed, negative numbers start from the end
2665/// \param[in] labAngle New angle value
2666/// \param[in] labSize New size (0 erase the label)
2667/// \param[in] labAlign New alignment value
2668/// \param[in] labColor New label color
2669/// \param[in] labFont New label font
2670/// \param[in] labText New label text
2671///
2672/// #### Example:
2673///
2674/// Begin_Macro(source)
2675/// {
2676/// auto c = new TCanvas("c1","Examples of TGaxis",900,100);
2677/// c->Range(-6,-0.1,6,0.1);
2678/// auto *axis = new TGaxis(-5.5,0.,5.5,0.,0.0,100,510,"S");
2679/// axis->SetName("axis1");
2680/// axis->SetTitle("Axis Title");
2681/// axis->SetTitleSize(0.2);
2682/// axis->SetLabelSize(0.2);
2683/// axis->SetTickSize(0.15);
2684/// axis->SetTitleColor(kBlue);
2685/// axis->SetTitleFont(42);
2686/// axis->ChangeLabel(1,-1,-1,-1,2);
2687/// axis->ChangeLabel(3,-1,0.);
2688/// axis->ChangeLabel(5,30.,-1,0);
2689/// axis->ChangeLabel(6,-1,-1,-1,3,-1,"6th label");
2690/// axis->ChangeLabel(-2,-1,-1,-1,3,-1,"2nd to last label");
2691/// axis->Draw();
2692/// }
2693/// End_Macro
2694///
2695/// #### Notes:
2696///
2697/// - If an attribute should not be changed just give the value "-1".
2698/// - If labnum=0 the list of modified labels is reset.
2699/// - To erase a label set labSize to 0.
2700/// - If labText is not specified or is an empty string, the text label is not changed.
2701
2704 const TString &labText)
2705{
2706 // special situation when mod labs taken from axis - one have to reset pointer
2707 if (fModLabs && !IsOwnedModLabs()) {
2708 fModLabs = nullptr;
2709 fNModLabs = 0;
2710 }
2711
2712 // Reset the list of modified labels.
2713 if (labNum == 0) {
2715 return;
2716 }
2717
2718 fNModLabs++;
2719 if (!fModLabs) {
2720 fModLabs = new TList();
2722 }
2723
2725 if (!ml) {
2726 ml = new TAxisModLab();
2727 ml->SetLabNum(labNum);
2728 fModLabs->Add(ml);
2729 }
2730
2731 ml->SetAngle(labAngle);
2732 ml->SetSize(labSize);
2733 ml->SetAlign(labAlign);
2734 ml->SetColor(labColor);
2735 ml->SetFont(labFont);
2736 ml->SetText(labText);
2737}
2738
2739////////////////////////////////////////////////////////////////////////////////
2740/// Define new text attributes for the label value "labValue". It allows to do a
2741/// fine tuning of the labels. All the attributes can be changed, even the
2742/// label text itself.
2743///
2744/// \param[in] labValue Axis value to be changed
2745/// \param[in] labAngle New angle value
2746/// \param[in] labSize New size (0 erase the label)
2747/// \param[in] labAlign New alignment value
2748/// \param[in] labColor New label color
2749/// \param[in] labFont New label font
2750/// \param[in] labText New label text
2751///
2752/// #### Example:
2753///
2754/// Begin_Macro(source)
2755/// {
2756/// auto c = new TCanvas("c1","Examples of TGaxis",900,100);
2757/// c->Range(-6,-0.1,6,0.1);
2758/// auto *axis = new TGaxis(-5.5,0.,5.5,0.,0.0,100,510,"S");
2759/// axis->SetName("axis1");
2760/// axis->SetTitle("Axis Title");
2761/// axis->SetTitleSize(0.2);
2762/// axis->SetLabelSize(0.2);
2763/// axis->SetTickSize(0.15);
2764/// axis->SetTitleColor(kBlue);
2765/// axis->SetTitleFont(42);
2766/// axis->ChangeLabelByValue(0., -1, -1, -1, kRed);
2767/// axis->ChangeLabelByValue(20., -1, 0);
2768/// axis->ChangeLabelByValue(40., 30.);
2769/// axis->ChangeLabelByValue(50., -1, -1, -1, kBlue, -1, "blue for 50.");
2770/// axis->ChangeLabelByValue(90., -1, -1, -1, kGreen, -1, "green for 90.");
2771/// axis->Draw();
2772/// }
2773/// End_Macro
2774///
2775/// #### Notes:
2776///
2777/// - If an attribute should not be changed just give the value "-1".
2778/// - To erase a label set labSize to 0
2779/// - If labText is not specified or is an empty string, the text label is not changed.
2780
2783 const TString &labText)
2784{
2785 // special situation when mod labs taken from axis - one have to reset pointer
2786 if (fModLabs && !IsOwnedModLabs()) {
2787 fModLabs = nullptr;
2788 fNModLabs = 0;
2789 }
2790
2791 fNModLabs++;
2792 if (!fModLabs) {
2793 fModLabs = new TList();
2795 }
2796
2797 TAxisModLab *ml = FindModLab(0, 0, labValue, 0.);
2798 if (!ml) {
2799 ml = new TAxisModLab();
2800 ml->SetLabValue(labValue);
2801 fModLabs->Add(ml);
2802 }
2803
2804 ml->SetAngle(labAngle);
2805 ml->SetSize(labSize);
2806 ml->SetAlign(labAlign);
2807 ml->SetColor(labColor);
2808 ml->SetFont(labFont);
2809 ml->SetText(labText);
2810}
2811
2812
2813static TAttText SavedAttText; ///< Global variable saving the current label's text angle. Used by TGaxis::ChangeLabelAttributes.
2814
2815////////////////////////////////////////////////////////////////////////////////
2816/// Helper method used by TGaxis::ChangeLabel.
2817/// Change the label attributes of label number i. If needed.
2818///
2819/// \param[in] i Current label number to be changed if needed
2820/// \param[in] nlabels Totals number of labels for this axis (useful when i is counted from the end)
2821/// \param[in] t Original TLatex string holding the label to be changed
2822/// \param[in] c Text string to be drawn
2823/// \param[in] value Axis value which should be changed
2824/// \param[in] eps Epsilon parameter for axis value, -1 means ignore axis value at all
2825
2826
2828{
2829 t->TAttText::Copy(SavedAttText);
2830
2831 auto ml = FindModLab(i, nlabels, value, eps);
2832
2833 if (ml) {
2834 if (ml->GetAngle()>=0.) t->SetTextAngle(ml->GetAngle());
2835 if (ml->GetSize()>=0.) t->SetTextSize(ml->GetSize());
2836 if (ml->GetAlign()>0) t->SetTextAlign(ml->GetAlign());
2837 if (ml->GetColor()>=0) t->SetTextColor(ml->GetColor());
2838 if (ml->GetFont()>0) t->SetTextFont(ml->GetFont());
2839 if (!ml->GetText().IsNull()) strlcpy(c, ml->GetText().Data(), 256);
2840 }
2841}
2842
2843////////////////////////////////////////////////////////////////////////////////
2844/// Helper method used by TGaxis::ChangeLabel.
2845/// Reset the labels' attributes to the values they had before the last call to
2846/// TGaxis::ChangeLabelAttributes.
2847
2849{
2850 SavedAttText.Copy(*t);
2851}
2852
2853////////////////////////////////////////////////////////////////////////////////
2854/// Static function to set `fgMaxDigits` for axis.`fgMaxDigits` is
2855/// the maximum number of digits permitted for the axis labels above which the
2856/// notation with 10^N is used.For example, to accept 6 digits number like 900000
2857/// on an axis call `TGaxis::SetMaxDigits(6)`. The default value is 5.
2858/// `fgMaxDigits` must be greater than 0.
2859/// Warning: this static function changes the max number of digits in all axes.
2860/// If you only want to change the digits of the current TGaxis instance, use
2861/// axis->SetNdivisions(N*1000000 + (axis->GetNdiv()%1000000))
2862/// instead of axis->SetMaxDigits(N).
2863
2868
2869////////////////////////////////////////////////////////////////////////////////
2870/// Change the name of the axis.
2871
2872void TGaxis::SetName(const char *name)
2873{
2874 fName = name;
2875}
2876
2877////////////////////////////////////////////////////////////////////////////////
2878/// Set the kMoreLogLabels bit flag. When this option is selected more labels are
2879/// drawn when in logarithmic scale and there is a small number of decades (less than 3).
2880/// Note that this option is automatically inherited from TAxis
2881
2887
2888////////////////////////////////////////////////////////////////////////////////
2889/// Set the NoExponent flag. By default, an exponent of the form 10^N is used
2890/// when the label values are either all very small or very large. One can disable
2891/// the exponent by calling axis.SetNoExponent(kTRUE).
2892
2898
2899////////////////////////////////////////////////////////////////////////////////
2900/// To set axis options.
2901
2903{
2904 fChopt = option;
2905}
2906
2907////////////////////////////////////////////////////////////////////////////////
2908/// Change the title of the axis.
2909
2910void TGaxis::SetTitle(const char *title)
2911{
2912 fTitle = title;
2913}
2914
2915////////////////////////////////////////////////////////////////////////////////
2916/// Change the format used for time plotting.
2917/// The format string for date and time use the same options as the one used
2918/// in the standard strftime C function, i.e. :
2919///
2920/// for date :
2921///
2922/// - `%a` abbreviated weekday name
2923/// - `%b` abbreviated month name
2924/// - `%d` day of the month (01-31)
2925/// - `%m` month (01-12)
2926/// - `%y` year without century
2927///
2928/// for time :
2929///
2930/// - `%H` hour (24-hour clock)
2931/// - `%I` hour (12-hour clock)
2932/// - `%p` local equivalent of AM or PM
2933/// - `%M` minute (00-59)
2934/// - `%S` seconds (00-61)
2935/// - `%%` %
2936
2938{
2940
2941 if (timeformat.Index("%F")>=0 || timeformat.IsNull()) {
2943 return;
2944 }
2945
2946 Int_t idF = fTimeFormat.Index("%F");
2947 if (idF>=0) {
2952 } else {
2955 }
2956}
2957
2958////////////////////////////////////////////////////////////////////////////////
2959/// Change the time offset. If option = "gmt", set display mode to GMT.
2960
2962{
2963 TString opt = option;
2964 opt.ToLower();
2965
2966 char tmp[20];
2967 time_t timeoff;
2968 struct tm* utctis;
2969 Int_t idF = fTimeFormat.Index("%F");
2970 if (idF>=0) fTimeFormat.Remove(idF);
2971 fTimeFormat.Append("%F");
2972
2973 timeoff = (time_t)((Long_t)(toffset));
2974
2975 // offset is always saved in GMT to allow file transport
2976 // to different time zones
2977 utctis = gmtime(&timeoff);
2978
2979 if (utctis != nullptr) {
2980 strftime(tmp, 20,"%Y-%m-%d %H:%M:%S",utctis);
2982 } else {
2983 fTimeFormat.Append("1970-01-01 00:00:00");
2984 }
2985
2986 // append the decimal part of the time offset
2988 snprintf(tmp,20,"s%g",ds);
2990
2991 // add GMT/local option
2992 if (opt.Contains("gmt")) fTimeFormat.Append(" GMT");
2993}
2994
2995////////////////////////////////////////////////////////////////////////////////
2996/// Static method to set X and Y offset of the axis 10^n notation.
2997/// It applies on axis belonging to an histogram (TAxis). It has no effect on standalone TGaxis.
2998/// It is in % of the pad size. It can be negative.
2999/// axis specifies which axis ("x","y"), default = "x"
3000/// if axis="xz" set the two axes
3001/// Redirected to TStyle::SetExponentOffset
3002
3007
3008////////////////////////////////////////////////////////////////////////////////
3009/// Stream an object of class TGaxis.
3010
3012{
3013 if (R__b.IsReading()) {
3014 UInt_t R__s, R__c;
3015 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
3016 if (R__v > 3) {
3017 R__b.ReadClassBuffer(TGaxis::Class(), this, R__v, R__s, R__c);
3018 return;
3019 }
3020 //====process old versions before automatic schema evolution
3023 R__b >> fNdiv;
3024 R__b >> fWmin;
3025 R__b >> fWmax;
3026 R__b >> fGridLength;
3027 R__b >> fTickSize;
3028 R__b >> fLabelOffset;
3029 R__b >> fLabelSize;
3030 R__b >> fTitleOffset;
3031 R__b >> fTitleSize;
3032 R__b >> fLabelFont;
3033 if (R__v > 2) {
3034 R__b >> fLabelColor;
3035 }
3040 if (R__v > 1) {
3042 fFunction = (TF1*)gROOT->GetFunction(fFunctionName.Data());
3043 }
3044 R__b.CheckByteCount(R__s, R__c, TGaxis::IsA());
3045 //====end of old versions
3046
3047 } else {
3048 R__b.WriteClassBuffer(TGaxis::Class(),this);
3049 }
3050}
3051
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
short Version_t
Class version identifier (short)
Definition RtypesCore.h:80
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:69
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:72
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
double Double_t
Double 8 bytes.
Definition RtypesCore.h:74
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
#define BIT(n)
Definition Rtypes.h:91
#define X(type, name)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
constexpr Double_t kPI
Definition TEllipse.cxx:25
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmin
Option_t Option_t SetLineColor
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
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 Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t SetTextFont
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmax
Option_t Option_t TPoint TPoint const char y1
char name[80]
Definition TGX11.cxx:148
const Int_t kHori
Definition TGaxis.cxx:38
static TAttText SavedAttText
Global variable saving the current label's text angle. Used by TGaxis::ChangeLabelAttributes.
Definition TGaxis.cxx:2813
float xmin
#define hi
float ymin
float xmax
float ymax
#define gROOT
Definition TROOT.h:417
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
#define gPad
#define snprintf
Definition civetweb.c:1579
Draw all kinds of Arrows.
Definition TArrow.h:29
virtual Color_t GetTitleColor() const
Definition TAttAxis.h:47
virtual Color_t GetLabelColor() const
Definition TAttAxis.h:39
virtual Color_t GetAxisColor() const
Definition TAttAxis.h:38
virtual Style_t GetTitleFont() const
Definition TAttAxis.h:48
virtual Float_t GetLabelOffset() const
Definition TAttAxis.h:41
virtual Style_t GetLabelFont() const
Definition TAttAxis.h:40
virtual Float_t GetTitleSize() const
Definition TAttAxis.h:45
virtual Float_t GetLabelSize() const
Definition TAttAxis.h:42
virtual Float_t GetTickLength() const
Definition TAttAxis.h:46
virtual Float_t GetTitleOffset() const
Definition TAttAxis.h:44
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:36
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:46
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:38
Width_t fLineWidth
Line width.
Definition TAttLine.h:26
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:44
virtual void Modify()
Change current line attributes if necessary.
Definition TAttLine.cxx:246
Style_t fLineStyle
Line style.
Definition TAttLine.h:25
Color_t fLineColor
Line color.
Definition TAttLine.h:24
virtual void SaveLineAttributes(std::ostream &out, const char *name, Int_t coldef=1, Int_t stydef=1, Int_t widdef=1)
Save line attributes as C++ statement(s) on output stream out.
Definition TAttLine.cxx:289
Text Attributes class.
Definition TAttText.h:21
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:48
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:38
Color_t fTextColor
Text color.
Definition TAttText.h:27
Float_t fTextAngle
Text angle.
Definition TAttText.h:24
virtual Color_t GetTextColor() const
Return the text color.
Definition TAttText.h:37
virtual void Streamer(TBuffer &)
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:49
virtual Float_t GetTextAngle() const
Return the text angle.
Definition TAttText.h:36
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:50
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:52
Font_t fTextFont
Text font.
Definition TAttText.h:28
virtual void SaveTextAttributes(std::ostream &out, const char *name, Int_t alidef=12, Float_t angdef=0, Int_t coldef=1, Int_t fondef=61, Float_t sizdef=1)
Save text attributes as C++ statement(s) on output stream out.
Definition TAttText.cxx:399
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:53
Short_t fTextAlign
Text alignment.
Definition TAttText.h:26
Float_t fTextSize
Text size.
Definition TAttText.h:25
TAxis helper class used to store the modified labels.
Definition TAxisModLab.h:21
Class to manage histogram axis.
Definition TAxis.h:32
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:137
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:482
@ kTickMinus
Definition TAxis.h:65
@ kLabelsUp
Definition TAxis.h:75
@ kCenterTitle
Definition TAxis.h:67
@ kRotateTitle
Definition TAxis.h:69
@ kNoExponent
Definition TAxis.h:71
@ kMoreLogLabels
Definition TAxis.h:77
@ kTickPlus
Definition TAxis.h:64
@ kLabelsDown
Definition TAxis.h:74
@ kLabelsHori
Definition TAxis.h:72
@ kDecimals
Definition TAxis.h:63
@ kCenterLabels
Bit 13 is used by TObject.
Definition TAxis.h:68
@ kLabelsVert
Definition TAxis.h:73
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:444
Bool_t GetDecimals() const
Definition TAxis.h:122
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:473
TList * GetModifiedLabels() const
Definition TAxis.h:124
virtual const char * GetTimeFormat() const
Definition TAxis.h:134
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:462
THashList * GetLabels() const
Definition TAxis.h:123
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
Bool_t IsOwner() const
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
static TString SavePrimitiveColor(Int_t ci)
Convert color in C++ statement which can be used in SetColor directives Produced statement either inc...
Definition TColor.cxx:2556
1-Dim function class
Definition TF1.h:182
virtual Double_t GetXmax() const
Definition TF1.h:525
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition TF1.cxx:1446
virtual Double_t GetXmin() const
Definition TF1.h:521
The axis painter class.
Definition TGaxis.h:26
virtual void SetNoExponent(Bool_t noExponent=kTRUE)
Set the NoExponent flag.
Definition TGaxis.cxx:2893
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition TGaxis.cxx:2937
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition TGaxis.cxx:1006
TGaxis()
TGaxis default constructor.
Definition TGaxis.cxx:692
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:130
void ChangeLabelAttributes(Int_t i, Int_t nlabels, TLatex *t, char *c, Double_t value=0., Double_t eps=-1.)
Helper method used by TGaxis::ChangeLabel.
Definition TGaxis.cxx:2827
Float_t fTitleSize
Size of title in NDC.
Definition TGaxis.h:37
Float_t GetGridLength() const
Definition TGaxis.h:78
void SetLabelFont(Int_t labelfont)
Definition TGaxis.h:107
void SetTitleSize(Float_t titlesize)
Definition TGaxis.h:131
void Streamer(TBuffer &) override
Stream an object of class TGaxis.
Definition TGaxis.cxx:3011
Float_t fTitleOffset
Offset of title wrt axis.
Definition TGaxis.h:36
TString fTitle
Axis title.
Definition TGaxis.h:44
Int_t fLabelFont
Font for labels.
Definition TGaxis.h:40
static TClass * Class()
TAxisModLab * FindModLab(Int_t indx, Int_t numlabels=0, Double_t v=0., Double_t eps=-1.) const
Search for axis modifier by index or value.
Definition TGaxis.cxx:2630
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2910
Int_t fLabelColor
Color for labels.
Definition TGaxis.h:39
TAxis * fAxis
! Pointer to original TAxis axis (if any)
Definition TGaxis.h:48
TString fTimeFormat
Time format, ex: 09/12/99 12:34:00.
Definition TGaxis.h:45
void SavePrimitive(std::ostream &out, Option_t *option="") override
Save primitive as a C++ statement(s) on output stream out.
Definition TGaxis.cxx:2548
TString fFunctionName
Name of mapping function pointed by fFunction.
Definition TGaxis.h:46
void SetLabelOffset(Float_t labeloffset)
Definition TGaxis.h:108
virtual void Rotate(Double_t X, Double_t Y, Double_t CFI, Double_t SFI, Double_t XT, Double_t YT, Double_t &U, Double_t &V)
Internal method to rotate axis coordinates.
Definition TGaxis.cxx:2538
Float_t GetLabelOffset() const
Definition TGaxis.h:82
void SetTimeOffset(Double_t toffset, Option_t *option="local")
Change the time offset. If option = "gmt", set display mode to GMT.
Definition TGaxis.cxx:2961
Float_t fTickSize
Size of primary tick mark in NDC.
Definition TGaxis.h:33
void ChangeLabelByValue(Double_t labValue, Double_t labAngle=-1., Double_t labSize=-1., Int_t labAlign=-1, Int_t labColor=-1, Int_t labFont=-1, const TString &labText="")
Define new text attributes for the label value "labValue".
Definition TGaxis.cxx:2781
~TGaxis() override
TGaxis default destructor.
Definition TGaxis.cxx:859
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition TGaxis.cxx:953
Int_t GetLabelFont() const
Definition TGaxis.h:81
Float_t fLabelOffset
Offset of label wrt axis.
Definition TGaxis.h:34
static void SetMaxDigits(Int_t maxd=5)
Static function to set fgMaxDigits for axis.
Definition TGaxis.cxx:2864
Float_t fLabelSize
Size of labels in NDC.
Definition TGaxis.h:35
Int_t fNdiv
Number of divisions.
Definition TGaxis.h:38
const char * GetTitle() const override
Returns title of object.
Definition TGaxis.h:88
TString fChopt
Axis options.
Definition TGaxis.h:42
TGaxis & operator=(const TGaxis &)
Assignment operator.
Definition TGaxis.cxx:826
TString fName
Axis name.
Definition TGaxis.h:43
Float_t GetTitleOffset() const
Definition TGaxis.h:84
TF1 * fFunction
! Pointer to function computing axis values
Definition TGaxis.h:47
Float_t GetTitleSize() const
Definition TGaxis.h:85
static Int_t GetMaxDigits()
Static function returning gStyle->GetAxisMaxDigits().
Definition TGaxis.cxx:945
virtual void CenterLabels(Bool_t center=kTRUE)
If center = kTRUE axis labels are centered in the center of the bin.
Definition TGaxis.cxx:894
const char * GetName() const override
Returns name of object.
Definition TGaxis.h:86
void SetLabelColor(Int_t labelcolor)
Definition TGaxis.h:106
virtual void AdjustBinSize(Double_t A1, Double_t A2, Int_t nold, Double_t &BinLow, Double_t &BinHigh, Int_t &nbins, Double_t &BinWidth)
Internal method for axis labels optimisation.
Definition TGaxis.cxx:2491
Float_t fGridLength
Length of the grid in NDC.
Definition TGaxis.h:32
Int_t GetLabelColor() const
Definition TGaxis.h:80
virtual void SetDecimals(Bool_t dot=kTRUE)
Set the decimals flag.
Definition TGaxis.cxx:2602
virtual void CenterTitle(Bool_t center=kTRUE)
If center = kTRUE axis title will be centered. The default is right adjusted.
Definition TGaxis.cxx:904
TList * fModLabs
List of modified labels.
Definition TGaxis.h:49
void ChangeLabel(Int_t labNum=0, Double_t labAngle=-1., Double_t labSize=-1., Int_t labAlign=-1, Int_t labColor=-1, Int_t labFont=-1, const TString &labText="")
Define new text attributes for the label number "labNum".
Definition TGaxis.cxx:2702
void CleanupModLabs()
Correctly cleanup fModLabs - delete content when owned by TGaxis.
Definition TGaxis.cxx:879
Double_t fWmax
Highest value on the axis.
Definition TGaxis.h:31
Float_t GetTickSize() const
Definition TGaxis.h:93
virtual TGaxis * DrawAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t wmin, Double_t wmax, Int_t ndiv=510, Option_t *chopt="", Double_t gridlength=0)
Draw this axis with new attributes.
Definition TGaxis.cxx:914
virtual void SetMoreLogLabels(Bool_t more=kTRUE)
Set the kMoreLogLabels bit flag.
Definition TGaxis.cxx:2882
void SetTickSize(Float_t ticksize)
Definition TGaxis.h:124
void Paint(Option_t *chopt="") override
Draw this axis with its current attributes.
Definition TGaxis.cxx:984
Int_t fNModLabs
Number of modified labels.
Definition TGaxis.h:41
Double_t fWmin
Lowest value on the axis.
Definition TGaxis.h:30
void SetLabelSize(Float_t labelsize)
Definition TGaxis.h:109
void SetFunction(const char *funcname="")
Specify a function to map the axis values.
Definition TGaxis.cxx:2611
virtual void SetName(const char *name)
Change the name of the axis.
Definition TGaxis.cxx:2872
static void SetExponentOffset(Float_t xoff=0., Float_t yoff=0., Option_t *axis="xy")
Static method to set X and Y offset of the axis 10^n notation.
Definition TGaxis.cxx:3003
void LabelsLimits(const char *label, Int_t &first, Int_t &last)
Internal method to find first and last character of a label.
Definition TGaxis.cxx:2526
Bool_t IsOwnedModLabs() const
Returns kTRUE when fModLabs owned by TGaxis and should be cleaned up.
Definition TGaxis.cxx:867
void ResetLabelAttributes(TLatex *t)
Helper method used by TGaxis::ChangeLabel.
Definition TGaxis.cxx:2848
Float_t GetLabelSize() const
Definition TGaxis.h:83
void SetOption(Option_t *option="")
To set axis options.
Definition TGaxis.cxx:2902
TClass * IsA() const override
Definition TGaxis.h:140
static void Optimize(Double_t A1, Double_t A2, Int_t nold, Double_t &BinLow, Double_t &BinHigh, Int_t &nbins, Double_t &BWID, Option_t *option="")
Static function to compute reasonable axis limits.
To draw Mathematical Formula.
Definition TLatex.h:20
Use the TLine constructor to create a simple line.
Definition TLine.h:22
Double_t fY1
Y of 1st point.
Definition TLine.h:26
Double_t fX1
X of 1st point.
Definition TLine.h:25
Double_t fX2
X of 2nd point.
Definition TLine.h:27
TLine & operator=(const TLine &src)
Assignment operator.
Definition TLine.cxx:67
Double_t fY2
Y of 2nd point.
Definition TLine.h:28
virtual void PaintLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2)
Draw this line with new coordinates in NDC.
Definition TLine.cxx:354
void Streamer(TBuffer &) override
Stream an object of class TLine.
Definition TLine.cxx:463
A doubly linked list.
Definition TList.h:38
void Add(TObject *obj) override
Definition TList.h:81
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:600
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:888
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1098
static void SavePrimitiveDraw(std::ostream &out, const char *variable_name, Option_t *option=nullptr)
Save invocation of primitive Draw() method Skipped if option contains "nodraw" string.
Definition TObject.cxx:845
static void SavePrimitiveConstructor(std::ostream &out, TClass *cl, const char *variable_name, const char *constructor_agrs="", Bool_t empty_line=kTRUE)
Save object constructor in the output stream "out".
Definition TObject.cxx:777
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:71
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:427
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
TString & ReplaceSpecialCppChars()
Find special characters which are typically used in printf() calls and replace them by appropriate es...
Definition TString.cxx:1121
const char * Data() const
Definition TString.h:386
TString & Remove(Ssiz_t pos)
Definition TString.h:696
virtual void Streamer(TBuffer &)
Stream a string object.
Definition TString.cxx:1492
TString & Append(const char *cs)
Definition TString.h:583
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2459
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:643
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:662
Double_t GetTimeOffset() const
Definition TStyle.h:271
Int_t GetAxisMaxDigits() const
Method returns maximum number of digits permitted for the axis labels above which the notation with 1...
Definition TStyle.cxx:1158
Color_t GetGridColor() const
Definition TStyle.h:224
Style_t GetGridStyle() const
Definition TStyle.h:225
void SetExponentOffset(Float_t xoff=0., Float_t yoff=0., Option_t *axis="XY")
Method set X and Y offset of the axis 10^n notation.
Definition TStyle.cxx:1837
Float_t GetTitleOffset(Option_t *axis="X") const
Return title offset.
Definition TStyle.cxx:1229
void SetAxisMaxDigits(Int_t maxd=5)
Method set maximum number of digits permitted for the axis labels above which the notation with 10^N ...
Definition TStyle.cxx:1881
Width_t GetGridWidth() const
Definition TStyle.h:226
Int_t GetStripDecimals() const
Definition TStyle.h:270
void GetExponentOffset(Float_t &xoff, Float_t &yoff, Option_t *axis="X") const
Method returns X and Y offset of the axis 10^n notation.
Definition TStyle.cxx:1856
static time_t MktimeFromUTC(tm_t *tmstruct)
Equivalent of standard routine "mktime" but using the assumption that tm struct is filled with UTC,...
Double_t y[n]
Definition legend1.C:17
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Double_t ATan2(Double_t y, Double_t x)
Returns the principal value of the arc tangent of y/x, expressed in radians.
Definition TMath.h:657
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:732
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:605
constexpr Double_t Pi()
Definition TMath.h:40
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:599
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:773
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
TLine l
Definition textangle.C:4