KaliVeda  1.13/01
Heavy-Ion Analysis Toolkit
KVGaxis.cpp
Go to the documentation of this file.
1 //Created by KVClassFactory on Wed Jun 19 16:07:04 2013
2 //Author: dgruyer
3 
4 #include "KVGaxis.h"
5 #include "TMath.h"
6 
7 #include "Riostream.h"
8 #include "TROOT.h"
9 #include "TGaxis.h"
10 #include "TVirtualPad.h"
11 //#include "TPad.h"
12 #include "TVirtualX.h"
13 #include "TLine.h"
14 #include "TLatex.h"
15 #include "TStyle.h"
16 #include "TF1.h"
17 #include "TAxis.h"
18 #include "THashList.h"
19 #include "TObjString.h"
20 #include "TMath.h"
21 #include "THLimitsFinder.h"
22 #include "TColor.h"
23 #include "TClass.h"
24 #include "TTimeStamp.h"
25 #include "TSystem.h"
26 
28 const Int_t kHori = BIT(9);
29 
31 
32 
33 
36 {
37  fNbins = 0;
38  fBins = 0;
39  fLabels = 0;
40  fFormat = "%lf";
41  // Default constructor
42 }
43 
44 
45 
46 //KVGaxis::KVGaxis(const KVGaxis& obj) : TGaxis()
47 //{
48 // // Copy constructor
49 // // This ctor is used to make a copy of an existing object (for example
50 // // when a method returns an object), and it is always a good idea to
51 // // implement it.
52 // // If your class allocates memory in its constructor(s) then it is ESSENTIAL :-)
53 
54 // obj.Copy(*this);
55 //}
56 
57 
58 
60 
61 KVGaxis::KVGaxis(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) :
62  TGaxis(xmin, ymin, xmax, ymax, wmin, wmax, ndiv, chopt, gridlength)
63 {
64  fNbins = 0;
65  fBins = 0;
66  fLabels = 0;
67  fFormat = "%lf";
68  // Write your code here
69 }
70 
71 
72 
73 
75 
76 KVGaxis::KVGaxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, const char* funcname, Int_t ndiv, Option_t* chopt, Double_t gridlength) :
77  TGaxis(xmin, ymin, xmax, ymax, funcname, ndiv, chopt, gridlength)
78 {
79  fNbins = 0;
80  fBins = 0;
81  fLabels = 0;
82  fFormat = "%lf";
83  // Write your code here
84 }
85 
86 
87 
89 
90 KVGaxis::KVGaxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Int_t nbins, Double_t* bins, Double_t wmin, Double_t wmax, Int_t ndiv, Option_t* chopt, Double_t gridlength, char** labels):
91  TGaxis(xmin, ymin, xmax, ymax, (wmin == wmax ? (xmin == xmax ? ymin : xmin) : wmin), (wmin == wmax ? (xmin == xmax ? ymax : xmax) : wmax), ndiv, chopt, gridlength)
92 {
93  fNbins = nbins;
94  fBins = bins;
95  fNdiv = fNbins;
96  fFormat = "%lf";
97  fLabels = labels;
98 }
99 
100 
101 
102 
105 
107 {
108  // Destructor
109 }
110 
111 
112 
113 //void KVGaxis::Copy(TObject& obj) const
114 //{
115 // // This method copies the current state of 'this' object into 'obj'
116 // // You should add here any member variables, for example:
117 // // (supposing a member variable KVGaxis::fToto)
118 // // CastedObj.fToto = fToto;
119 // // or
120 // // CastedObj.SetToto( GetToto() );
121 
122 // TGaxis::Copy(obj);
123 // //KVGaxis& CastedObj = (KVGaxis&)obj;
124 //}
125 
126 
127 
129 
131  Double_t& wmin, Double_t& wmax, Int_t& ndiv, Option_t* chopt,
132  Double_t gridlength, Bool_t drawGridOnly)
133 {
134  const char* where = "PaintAxis";
135 
136  TString opt(chopt);
137  if (!fNbins) return TGaxis::PaintAxis(xmin, ymin, xmax, ymax, wmin, wmax, ndiv, chopt, gridlength, drawGridOnly);
138 
139  Double_t alfa, beta, ratio1, ratio2, grid_side;
140  Double_t axis_lengthN = 0;
141  Double_t axis_length0 = 0;
142  Double_t axis_length1 = 0;
143  Double_t axis_length;
144  Double_t atick[3];
145  Double_t tick_side;
146  Double_t charheight;
147  Double_t phil, phi, sinphi, cosphi, asinphi, acosphi;
148  Double_t binLow = 0., binLow2 = 0., binLow3 = 0.;
149  Double_t binHigh = 0., binHigh2 = 0., binHigh3 = 0.;
150  Double_t binWidth = 0., binWidth2 = 0., binWidth3 = 0.;
151  Double_t xpl1, xpl2, ypl1, ypl2;
152  Double_t xtick = 0;
153  Double_t xtick0, xtick1, dxtick = 0;
154  Double_t ytick, ytick0, ytick1;
155  Double_t wlabel, dwlabel;
156  Double_t xfactor, yfactor;
157  Double_t xlabel, ylabel, dxlabel;
158  Double_t xone, xtwo;
159  Double_t rlab;
160  Double_t x0, x1, y0, y1, xx0, xx1, yy0, yy1;
161  xx0 = xx1 = yy0 = yy1 = 0;
162  Double_t xxmin, xxmax, yymin, yymax;
163  xxmin = xxmax = yymin = yymax = 0;
164  Double_t xlside, xmside;
165  Double_t ww, af, rne;
166  Double_t xx, yy;
167  Double_t xmnlog, x00, x11, h2, h2sav, axmul, y;
168  Float_t chupxvsav, chupyvsav;
169  Double_t rtxw, rtyw;
170  Int_t nlabels, nticks, nticks0, nticks1;
171  Int_t i, j, k, l, decade, ltick;
172  Int_t mside, lside;
173  Int_t nexe = 0;
174  Int_t lnlen = 0;
175  Int_t iexe, if1, if2, na, nf, ih1, ih2, nbinin, nch, kmod;
176  Int_t optionLog, optionBlank, optionVert, optionPlus, optionMinus, optionUnlab, optionPara;
177  Int_t optionDown, optionRight, optionLeft, optionCent, optionEqual, optionDecimals = 0, optionDot;
178  Int_t optionY, optionText, optionGrid, optionSize, optionNoopt, optionInt, optionM, optionUp, optionX;
179  Int_t optionTime;
180  Int_t first, last, labelnumber;
181  Int_t xalign, yalign;
182  Int_t nn1, nn2, nn3, n1a, n2a, n3a, nb2, nb3;
183  Int_t nbins = 10, n1aold, nn1old;
184  n1aold = nn1old = 0;
185  Int_t ndyn;
186  Int_t nhilab = 0;
187  Int_t idn;
188  Bool_t flexe = 0;
189  Bool_t flexpo, flexne;
190  char* label;
191  char* chtemp;
192  char* coded;
193  char chlabel[256];
194  char kchtemp[256];
195  char chcoded[8];
196  TLine* linegrid;
197  TString timeformat;
198  time_t timelabel;
199  Double_t timed, wTimeIni;
200  struct tm* utctis;
201  Double_t rangeOffset = 0;
202 
203  Double_t epsilon = 1e-5;
204  const Double_t kPI = TMath::Pi();
205  //*-*-______________________________________
206 
207  Double_t rwmi = wmin;
208  Double_t rwma = wmax;
209  chtemp = &kchtemp[0];
210  label = &chlabel[0];
211  linegrid = 0;
212 
213  fFunction = (TF1*)gROOT->GetFunction(fFunctionName.Data());
214 
215  Bool_t noExponent = TestBit(TAxis::kNoExponent);
216 
217  //*-*- If moreLogLabels = kTRUE more Log Intermediate Labels are drawn.
218  Bool_t moreLogLabels = TestBit(TAxis::kMoreLogLabels);
219 
220  //*-*- the following parameters correspond to the pad range in NDC
221  //*-*- and the WC coordinates in the pad
222 
223  Double_t padh = gPad->GetWh() * gPad->GetAbsHNDC();
224  Double_t rwxmin = gPad->GetX1();
225  Double_t rwxmax = gPad->GetX2();
226  Double_t rwymin = gPad->GetY1();
227  Double_t rwymax = gPad->GetY2();
228 
229  if (strchr(chopt, 'G')) optionLog = 1;
230  else optionLog = 0;
231  if (strchr(chopt, 'B')) optionBlank = 1;
232  else optionBlank = 0;
233  if (strchr(chopt, 'V')) optionVert = 1;
234  else optionVert = 0;
235  if (strchr(chopt, '+')) optionPlus = 1;
236  else optionPlus = 0;
237  if (strchr(chopt, '-')) optionMinus = 1;
238  else optionMinus = 0;
239  if (strchr(chopt, 'U')) optionUnlab = 1;
240  else optionUnlab = 0;
241  if (strchr(chopt, 'P')) optionPara = 1;
242  else optionPara = 0;
243  if (strchr(chopt, 'O')) optionDown = 1;
244  else optionDown = 0;
245  if (strchr(chopt, 'R')) optionRight = 1;
246  else optionRight = 0;
247  if (strchr(chopt, 'L')) optionLeft = 1;
248  else optionLeft = 0;
249  if (strchr(chopt, 'C')) optionCent = 1;
250  else optionCent = 0;
251  if (strchr(chopt, '=')) optionEqual = 1;
252  else optionEqual = 0;
253  if (strchr(chopt, 'Y')) optionY = 1;
254  else optionY = 0;
255  if (strchr(chopt, 'T')) optionText = 1;
256  else optionText = 0;
257  if (strchr(chopt, 'W')) optionGrid = 1;
258  else optionGrid = 0;
259  if (strchr(chopt, 'S')) optionSize = 1;
260  else optionSize = 0;
261  if (strchr(chopt, 'N')) optionNoopt = 1;
262  else optionNoopt = 0;
263  if (strchr(chopt, 'I')) optionInt = 1;
264  else optionInt = 0;
265  if (strchr(chopt, 'M')) optionM = 1;
266  else optionM = 0;
267  if (strchr(chopt, '0')) optionUp = 1;
268  else optionUp = 0;
269  if (strchr(chopt, 'X')) optionX = 1;
270  else optionX = 0;
271  if (strchr(chopt, 't')) optionTime = 1;
272  else optionTime = 0;
273  if (strchr(chopt, '.')) optionDot = 1;
274  else optionDot = 0;
275  if (TestBit(TAxis::kTickPlus)) optionPlus = 2;
276  if (TestBit(TAxis::kTickMinus)) optionMinus = 2;
277  if (TestBit(TAxis::kCenterLabels)) optionM = 1;
278  if (TestBit(TAxis::kDecimals)) optionDecimals = 1;
279  if (!gStyle->GetStripDecimals()) optionDecimals = 1;
280  if (fAxis) {
281  if (fAxis->GetLabels()) {
282  optionM = 1;
283  optionText = 1;
284  ndiv = fAxis->GetLast() - fAxis->GetFirst() + 1;
285  }
286  }
287  if (ndiv < 0) {
288  Error(where, "Invalid number of divisions: %d", ndiv);
289  return;
290  }
291 
292  if (fNbins) {
293  optionNoopt = kTRUE;
294  optionSize = 1;
295  }
296 
297  //*-*- Set the grid length
298 
299  if (optionGrid) {
300  if (gridlength == 0) gridlength = 0.8;
301  linegrid = new TLine();
302  linegrid->SetLineColor(gStyle->GetGridColor());
303  if (linegrid->GetLineColor() == 0) linegrid->SetLineColor(GetLineColor());
304  linegrid->SetLineStyle(gStyle->GetGridStyle());
305  linegrid->SetLineWidth(gStyle->GetGridWidth());
306  }
307 
308  //*-*- No labels if the axis label offset is big.
309  //*-*- In that case the labels are not visible anyway.
310 
311  if (GetLabelOffset() > 1.1) optionUnlab = 1;
312 
313  //*-*- Determine time format
314 
315  Int_t idF = fTimeFormat.Index("%F");
316  if (idF >= 0) {
317  timeformat = fTimeFormat(0, idF);
318  }
319  else {
320  timeformat = fTimeFormat;
321  }
322 
323  //GMT option
324  if (fTimeFormat.Index("GMT") >= 0) optionTime = 2;
325 
326  // Determine the time offset and correct for time offset not being integer.
327  Double_t timeoffset = 0;
328  if (optionTime) {
329  if (idF >= 0) {
330  Int_t lnF = fTimeFormat.Length();
331  TString stringtimeoffset = fTimeFormat(idF + 2, lnF);
332  Int_t year, mm, dd, hh, mi, ss;
333  if (sscanf(stringtimeoffset.Data(), "%d-%d-%d %d:%d:%d", &year, &mm, &dd, &hh, &mi, &ss) == 6) {
334  struct tm tp;
335  tp.tm_year = year - 1900;
336  tp.tm_mon = mm - 1;
337  tp.tm_mday = dd;
338  tp.tm_hour = hh;
339  tp.tm_min = mi;
340  tp.tm_sec = ss;
341  tp.tm_isdst = -1; //automatic determination of daylight saving time
342  TString tz = (TString)gSystem->Getenv("TZ"); //save timezone
343  Bool_t isUTC = kFALSE;
344  if (gSystem->Getenv("TZ") && tz.Length() == 0) isUTC = kTRUE;
345  gSystem->Setenv("TZ", "UTC"); //sets timezone to UTC
346  tzset();
347  timeoffset = mktime(&tp);
348  //restore TZ
349  if (tz.Length()) {
350  gSystem->Setenv("TZ", tz.Data());
351  }
352  else {
353  if (isUTC) gSystem->Setenv("TZ", "");
354  else gSystem->Unsetenv("TZ");
355  }
356  tzset();
357  // Add the time offset's decimal part if it is there
358  Int_t ids = stringtimeoffset.Index("s");
359  if (ids >= 0) {
360  Float_t dp;
361  Int_t lns = stringtimeoffset.Length();
362  TString sdp = stringtimeoffset(ids + 1, lns);
363  sscanf(sdp.Data(), "%g", &dp);
364  timeoffset += dp;
365  }
366  }
367  else {
368  Error(where, "Time offset has not the right format");
369  }
370  }
371  else {
372  timeoffset = gStyle->GetTimeOffset();
373  }
374  wmin += timeoffset - (int)(timeoffset);
375  wmax += timeoffset - (int)(timeoffset);
376 
377  // correct for time offset at a good limit (min, hour, day, month, year)
378  struct tm* tp0;
379  time_t timetp = (time_t)((Long_t)(timeoffset));
380  Double_t range = wmax - wmin;
381  Long_t rangeBase = 60;
382  if (range > 60) rangeBase = 60 * 20; // minutes
383  if (range > 3600) rangeBase = 3600 * 20; // hours
384  if (range > 86400) rangeBase = 86400 * 20; // days
385  if (range > 2419200) rangeBase = 31556736; // months (average # days)
386  rangeOffset = (Double_t)((Long_t)(timeoffset) % rangeBase);
387  if (range > 31536000) {
388  tp0 = gmtime(&timetp);
389  tp0->tm_mon = 0;
390  tp0->tm_mday = 1;
391  tp0->tm_hour = 0;
392  tp0->tm_min = 0;
393  tp0->tm_sec = 0;
394  tp0->tm_isdst = 1; // daylight saving time is on.
395  rangeBase = (timetp - mktime(tp0)); // years
396  rangeOffset = (Double_t)(rangeBase);
397  }
398  wmax += rangeOffset;
399  wmin += rangeOffset;
400  }
401 
402  //*-*- Determine number of divisions 1, 2 and 3
403  n1a = ndiv % 100;
404  n2a = (ndiv % 10000 - n1a) / 100;
405  n3a = ndiv / 10000;
406  nn3 = TMath::Max(n3a, 1);
407  nn2 = TMath::Max(n2a, 1) * nn3;
408  nn1 = TMath::Max(n1a, 1) * nn2 + 1;
409  nticks = nn1;
410 
411  nn3 = 1;
412  nn2 = 1;
413  nn1 = fNbins;
414  nticks = nn1;
415 
416 
417  //*-*- Axis bining optimization is ignored if:
418  //*-*- - the first and the last label are equal
419  //*-*- - the number of divisions is 0
420  //*-*- - less than 1 primary division is requested
421  //*-*- - logarithmic scale is requested
422 
423  if (wmin == wmax || ndiv == 0 || n1a <= 1 || optionLog) {
424  optionNoopt = 1;
425  optionInt = 0;
426  }
427 
428  //*-*- Axis bining optimization
429  if ((wmax - wmin) < 1 && optionInt) {
430  Error(where, "option I not available");
431  optionInt = 0;
432  }
433  if (!optionNoopt || optionInt) {
434 
435  //*-*- Primary divisions optimization
436  //*-*- When integer labelling is required, Optimize is invoked first
437  //*-*- and only if the result is not an integer labelling, AdjustBinSize is invoked.
438 
439  THLimitsFinder::Optimize(wmin, wmax, n1a, binLow, binHigh, nbins, binWidth, fChopt.Data());
440  if (optionInt) {
441  if (binLow != Double_t(int(binLow)) || binWidth != Double_t(int(binWidth))) {
442  AdjustBinSize(wmin, wmax, n1a, binLow, binHigh, nbins, binWidth);
443  }
444  }
445  if ((wmin - binLow) > epsilon) {
446  binLow += binWidth;
447  nbins--;
448  }
449  if ((binHigh - wmax) > epsilon) {
450  binHigh -= binWidth;
451  nbins--;
452  }
453  if (xmax == xmin) {
454  rtyw = (ymax - ymin) / (wmax - wmin);
455  xxmin = xmin;
456  xxmax = xmax;
457  yymin = rtyw * (binLow - wmin) + ymin;
458  yymax = rtyw * (binHigh - wmin) + ymin;
459  }
460  else {
461  rtxw = (xmax - xmin) / (wmax - wmin);
462  xxmin = rtxw * (binLow - wmin) + xmin;
463  xxmax = rtxw * (binHigh - wmin) + xmin;
464  if (ymax == ymin) {
465  yymin = ymin;
466  yymax = ymax;
467  }
468  else {
469  alfa = (ymax - ymin) / (xmax - xmin);
470  beta = (ymin * xmax - ymax * xmin) / (xmax - xmin);
471  yymin = alfa * xxmin + beta;
472  yymax = alfa * xxmax + beta;
473  }
474  }
475  if (fFunction) {
476  yymin = ymin;
477  yymax = ymax;
478  xxmin = xmin;
479  xxmax = xmax;
480  }
481  else {
482  wmin = binLow;
483  wmax = binHigh;
484  }
485 
486  //*-*- Secondary divisions optimization
487  nb2 = n2a;
488  if (!optionNoopt && n2a > 1 && binWidth > 0) {
489  THLimitsFinder::Optimize(wmin, wmin + binWidth, n2a, binLow2, binHigh2, nb2, binWidth2, fChopt.Data());
490  }
491 
492  //*-*- Tertiary divisions optimization
493  nb3 = n3a;
494  if (!optionNoopt && n3a > 1 && binWidth2 > 0) {
495  THLimitsFinder::Optimize(binLow2, binLow2 + binWidth2, n3a, binLow3, binHigh3, nb3, binWidth3, fChopt.Data());
496  }
497  n1aold = n1a;
498  nn1old = nn1;
499  n1a = nbins;
500  nn3 = TMath::Max(nb3, 1);
501  nn2 = TMath::Max(nb2, 1) * nn3;
502  nn1 = TMath::Max(n1a, 1) * nn2 + 1;
503  nticks = nn1;
504  }
505 
506  //*-*- Coordinates are normalized
507 
508  ratio1 = 1 / (rwxmax - rwxmin);
509  ratio2 = 1 / (rwymax - rwymin);
510  x0 = ratio1 * (xmin - rwxmin);
511  x1 = ratio1 * (xmax - rwxmin);
512  y0 = ratio2 * (ymin - rwymin);
513  y1 = ratio2 * (ymax - rwymin);
514  if (!optionNoopt || optionInt) {
515  xx0 = ratio1 * (xxmin - rwxmin);
516  xx1 = ratio1 * (xxmax - rwxmin);
517  yy0 = ratio2 * (yymin - rwymin);
518  yy1 = ratio2 * (yymax - rwymin);
519  }
520 
521  if ((x0 == x1) && (y0 == y1)) {
522  Error(where, "length of axis is 0");
523  return;
524  }
525 
526  //*-*- Return wmin, wmax and the number of primary divisions
527  if (optionX) {
528  ndiv = n1a;
529  return;
530  }
531 
532  Int_t maxDigits = 5;
533  if (fAxis) maxDigits = fgMaxDigits;
534 
535  TLatex* textaxis = new TLatex();
536  SetLineStyle(1); // axis line style
537  textaxis->SetTextColor(GetTextColor());
538  textaxis->SetTextFont(GetTextFont());
539 
540  if (!gPad->IsBatch()) {
541  gVirtualX->GetCharacterUp(chupxvsav, chupyvsav);
542  gVirtualX->SetClipOFF(gPad->GetCanvasID());
543  }
544 
545  //*-*- Compute length of axis
546  axis_length = TMath::Sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
547  if (axis_length == 0) {
548  Error(where, "length of axis is 0");
549  goto L210;
550  }
551  if (!optionNoopt || optionInt) {
552  axis_lengthN = TMath::Sqrt((xx1 - xx0) * (xx1 - xx0) + (yy1 - yy0) * (yy1 - yy0));
553  axis_length0 = TMath::Sqrt((xx0 - x0) * (xx0 - x0) + (yy0 - y0) * (yy0 - y0));
554  axis_length1 = TMath::Sqrt((x1 - xx1) * (x1 - xx1) + (y1 - yy1) * (y1 - yy1));
555  if (axis_lengthN < epsilon) {
556  optionNoopt = 1;
557  optionInt = 0;
558  wmin = rwmi;
559  wmax = rwma;
560  n1a = n1aold;
561  nn1 = nn1old;
562  nticks = nn1;
563  if (optionTime) {
564  wmin += timeoffset - (int)(timeoffset) + rangeOffset;
565  wmax += timeoffset - (int)(timeoffset) + rangeOffset;
566  }
567  }
568  }
569 
570  if (x0 == x1) {
571  phi = 0.5 * kPI;
572  phil = phi;
573  }
574  else {
575  phi = TMath::ATan2((y1 - y0), (x1 - x0));
576  Int_t px0 = gPad->UtoPixel(x0);
577  Int_t py0 = gPad->VtoPixel(y0);
578  Int_t px1 = gPad->UtoPixel(x1);
579  Int_t py1 = gPad->VtoPixel(y1);
580  if (x0 < x1) phil = TMath::ATan2(Double_t(py0 - py1), Double_t(px1 - px0));
581  else phil = TMath::ATan2(Double_t(py1 - py0), Double_t(px0 - px1));
582  }
583  cosphi = TMath::Cos(phi);
584  sinphi = TMath::Sin(phi);
585  acosphi = TMath::Abs(cosphi);
586  asinphi = TMath::Abs(sinphi);
587  if (acosphi <= epsilon) {
588  acosphi = 0;
589  cosphi = 0;
590  }
591  if (asinphi <= epsilon) {
592  asinphi = 0;
593  sinphi = 0;
594  }
595 
596  //*-*- mside positive, tick marks on positive side
597  //*-*- mside negative, tick marks on negative side
598  //*-*- mside zero, tick marks on both sides
599  //*-*- Default is positive except for vertical axis
600 
601  mside = 1;
602  if (x0 == x1 && y1 > y0) mside = -1;
603  if (optionPlus) mside = 1;
604  if (optionMinus) mside = -1;
605  if (optionPlus && optionMinus) mside = 0;
606  xmside = mside;
607  lside = -mside;
608  if (optionEqual) lside = mside;
609  if (optionPlus && optionMinus) {
610  lside = -1;
611  if (optionEqual) lside = 1;
612  }
613  xlside = lside;
614 
615  //*-*- Tick marks size
616  if (xmside >= 0) tick_side = 1;
617  else tick_side = -1;
618  if (optionSize) atick[0] = tick_side * axis_length * fTickSize;
619  else atick[0] = tick_side * axis_length * 0.03;
620 
621  atick[1] = 0.5 * atick[0];
622  atick[2] = 0.5 * atick[1];
623 
624  //*-*- Set the side of the grid
625  if ((x0 == x1) && (y1 > y0)) grid_side = -1;
626  else grid_side = 1;
627 
628  //*-*- Compute Values if Function is given
629  if (fFunction) {
630  rwmi = fFunction->Eval(wmin);
631  rwma = fFunction->Eval(wmax);
632  if (rwmi > rwma) {
633  Double_t t = rwma;
634  rwma = rwmi;
635  rwmi = t;
636  }
637  }
638 
639  //*-*- Draw the axis if needed...
640  if (!optionBlank) {
641  xpl1 = x0;
642  xpl2 = x1;
643  ypl1 = y0;
644  ypl2 = y1;
645  PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
646  }
647 
648  //*-*- Draw axis title if it exists
649  if (!drawGridOnly && strlen(GetTitle())) {
650  textaxis->SetTextSize(GetTitleSize());
651  charheight = GetTitleSize();
652  if ((GetTextFont() % 10) > 2) {
653  charheight = charheight / gPad->GetWh();
654  }
655  Double_t toffset = GetTitleOffset();
657  if (x1 == x0) ylabel = xlside * 1.6 * charheight * toffset;
658  else ylabel = xlside * 1.3 * charheight * toffset;
659  if (y1 == y0) ylabel = xlside * 1.6 * charheight * toffset;
660  Double_t axispos;
661  if (TestBit(TAxis::kCenterTitle)) axispos = 0.5 * axis_length;
662  else axispos = axis_length;
664  if (x1 >= x0) {
665  if (TestBit(TAxis::kCenterTitle)) textaxis->SetTextAlign(22);
666  else textaxis->SetTextAlign(12);
667  Rotate(axispos, ylabel, cosphi, sinphi, x0, y0, xpl1, ypl1);
668  }
669  else {
670  if (TestBit(TAxis::kCenterTitle)) textaxis->SetTextAlign(22);
671  else textaxis->SetTextAlign(32);
672  Rotate(axispos, ylabel, cosphi, sinphi, x0, y0, xpl1, ypl1);
673  }
674  textaxis->PaintLatex(gPad->GetX1() + xpl1 * (gPad->GetX2() - gPad->GetX1()),
675  gPad->GetY1() + ypl1 * (gPad->GetY2() - gPad->GetY1()),
676  phil = (kPI + phil) * 180 / kPI,
677  GetTitleSize(),
678  GetTitle());
679  }
680  else {
681  if (x1 >= x0) {
682  if (TestBit(TAxis::kCenterTitle)) textaxis->SetTextAlign(22);
683  else textaxis->SetTextAlign(32);
684  Rotate(axispos, ylabel, cosphi, sinphi, x0, y0, xpl1, ypl1);
685  }
686  else {
687  if (TestBit(TAxis::kCenterTitle)) textaxis->SetTextAlign(22);
688  else textaxis->SetTextAlign(12);
689  Rotate(axispos, ylabel, cosphi, sinphi, x0, y0, xpl1, ypl1);
690  }
691  textaxis->PaintLatex(gPad->GetX1() + xpl1 * (gPad->GetX2() - gPad->GetX1()),
692  gPad->GetY1() + ypl1 * (gPad->GetY2() - gPad->GetY1()),
693  phil * 180 / kPI,
694  GetTitleSize(),
695  GetTitle());
696  }
697  }
698 
699  //*-*- No bining
700 
701  if (ndiv == 0)goto L210;
702  if (wmin == wmax) {
703  Error(where, "wmin (%f) == wmax (%f)", wmin, wmax);
704  goto L210;
705  }
706 
707  //*-*- Labels preparation:
708  //*-*- Get character height
709  //*-*- Compute the labels orientation in case of overlaps
710  //*-*- (with alphanumeric labels for horizontal axis).
711 
712  charheight = GetLabelSize();
713  if (optionText && GetLabelFont() % 10 != 3) charheight *= 0.66666;
714  textaxis->SetTextFont(GetLabelFont());
715  if ((GetLabelFont() % 10 < 2) && optionLog) // force TLatex mode in PaintLatex
716  textaxis->SetTextFont((Int_t)(GetLabelFont() / 10) * 10 + 2);
717  textaxis->SetTextColor(GetLabelColor());
718  textaxis->SetTextSize(charheight);
719  textaxis->SetTextAngle(GetTextAngle());
720  if (GetLabelFont() % 10 > 2) {
721  charheight /= padh;
722  }
723  if (!optionUp && !optionDown && !optionY && !optionUnlab) {
724  if (!drawGridOnly && optionText && ((ymin == ymax) || (xmin == xmax))) {
725  textaxis->SetTextAlign(32);
726  optionText = 2;
727  Int_t nl = fAxis->GetLast() - fAxis->GetFirst() + 1;
728  Double_t angle = 0;
729  for (i = fAxis->GetFirst(); i <= fAxis->GetLast(); i++) {
730  textaxis->SetText(0, 0, fAxis->GetBinLabel(i));
731  if (textaxis->GetXsize() < (xmax - xmin) / nl) continue;
732  angle = -20;
733  break;
734  }
735  for (i = fAxis->GetFirst(); i <= fAxis->GetLast(); i++) {
736  if ((!strcmp(fAxis->GetName(), "xaxis") && !gPad->TestBit(kHori))
737  || (!strcmp(fAxis->GetName(), "yaxis") && gPad->TestBit(kHori))) {
738  if (nl > 50) angle = 90;
739  if (fAxis->TestBit(TAxis::kLabelsHori)) angle = 0;
740  if (fAxis->TestBit(TAxis::kLabelsVert)) angle = 90;
741  if (fAxis->TestBit(TAxis::kLabelsUp)) angle = 20;
742  if (fAxis->TestBit(TAxis::kLabelsDown)) angle = -20;
743  if (angle == 0) textaxis->SetTextAlign(23);
744  if (angle == -20) textaxis->SetTextAlign(12);
745  Double_t s = -3;
746  if (ymin == gPad->GetUymax()) {
747  if (angle == 0) textaxis->SetTextAlign(21);
748  s = 3;
749  }
750  textaxis->PaintLatex(fAxis->GetBinCenter(i),
751  ymin + s * fAxis->GetLabelOffset() * (gPad->GetUymax() - gPad->GetUymin()),
752  angle,
753  textaxis->GetTextSize(),
754  fAxis->GetBinLabel(i));
755  }
756  else if ((!strcmp(fAxis->GetName(), "yaxis") && !gPad->TestBit(kHori))
757  || (!strcmp(fAxis->GetName(), "xaxis") && gPad->TestBit(kHori))) {
758  Double_t s = -3;
759  if (xmin == gPad->GetUxmax()) {
760  textaxis->SetTextAlign(12);
761  s = 3;
762  }
763  textaxis->PaintLatex(xmin + s * fAxis->GetLabelOffset() * (gPad->GetUxmax() - gPad->GetUxmin()),
764  fAxis->GetBinCenter(i),
765  0,
766  textaxis->GetTextSize(),
767  fAxis->GetBinLabel(i));
768  }
769  else {
770  textaxis->PaintLatex(xmin - 3 * fAxis->GetLabelOffset() * (gPad->GetUxmax() - gPad->GetUxmin()),
771  ymin + (i - 0.5) * (ymax - ymin) / nl,
772  0,
773  textaxis->GetTextSize(),
774  fAxis->GetBinLabel(i));
775  }
776  }
777  }
778  }
779 
780  //*-*- Now determine orientation of labels on axis
781  if (!gPad->IsBatch()) {
782  if (cosphi > 0) gVirtualX->SetCharacterUp(-sinphi, cosphi);
783  else gVirtualX->SetCharacterUp(sinphi, -cosphi);
784  if (x0 == x1) gVirtualX->SetCharacterUp(0, 1);
785  if (optionVert) gVirtualX->SetCharacterUp(0, 1);
786  if (optionPara) gVirtualX->SetCharacterUp(-sinphi, cosphi);
787  if (optionDown) gVirtualX->SetCharacterUp(cosphi, sinphi);
788  }
789 
790  //*-*- Now determine text alignment
791  xalign = 2;
792  yalign = 1;
793  if (x0 == x1) xalign = 3;
794  if (y0 != y1) yalign = 2;
795  if (optionCent) xalign = 2;
796  if (optionRight) xalign = 3;
797  if (optionLeft) xalign = 1;
798  if (TMath::Abs(cosphi) > 0.9) {
799  xalign = 2;
800  }
801  else {
802  if (cosphi * sinphi > 0) xalign = 1;
803  if (cosphi * sinphi < 0) xalign = 3;
804  }
805  textaxis->SetTextAlign(10 * xalign + yalign);
806 
807  //*-*- Position of labels in Y
808  if (x0 == x1) {
809  if (optionPlus && !optionMinus) {
810  if (optionEqual) ylabel = fLabelOffset / 2 + atick[0];
811  else ylabel = -fLabelOffset;
812  }
813  else {
814  ylabel = fLabelOffset;
815  if (lside < 0) ylabel += atick[0];
816  }
817  }
818  else if (y0 == y1) {
819  if (optionMinus && !optionPlus) {
820  if ((GetLabelFont() % 10) == 3) {
821  ylabel = fLabelOffset + 0.5 *
822  ((gPad->AbsPixeltoY(0) - gPad->AbsPixeltoY((Int_t)fLabelSize)) /
823  (gPad->GetY2() - gPad->GetY1()));
824  }
825  else {
826  ylabel = fLabelOffset + 0.5 * fLabelSize;
827  }
828  ylabel += TMath::Abs(atick[0]);
829  }
830  else {
831  ylabel = -fLabelOffset;
832  if (mside <= 0) ylabel -= TMath::Abs(atick[0]);
833  }
834  if (optionLog) ylabel -= 0.5 * charheight;
835  }
836  else {
837  if (mside + lside >= 0) ylabel = fLabelOffset;
838  else ylabel = -fLabelOffset;
839  }
840  if (optionText) ylabel /= 2;
841 
842  //*-*- Draw the linear tick marks if needed...
843  if (!optionLog) {
844  if (ndiv) {
845  if (fNbins) nticks = fNbins;
846  if (fFunction) {
847  dxtick = (binHigh - binLow) / Double_t(nticks - 1);
848  }
849  else {
850  if (optionNoopt && !optionInt) dxtick = axis_length / Double_t(nticks - 1);
851  else dxtick = axis_lengthN / Double_t(nticks - 1);
852  if (fNbins) dxtick = axis_length / (fWmax - fWmin);
853  }
854  for (k = 0; k < nticks; k++) {
855  ltick = 2;
856  if (k % nn3 == 0) ltick = 1;
857  if (k % nn2 == 0) ltick = 0;
858  if (fFunction) {
859  Double_t xf = binLow + Double_t(k) * dxtick;
860  Double_t zz = fFunction->Eval(xf) - rwmi;
861  xtick = zz * axis_length / TMath::Abs(rwma - rwmi);
862  }
863  else {
864  if (fNbins) xtick = (fBins[k] - fWmin) * dxtick;
865  else xtick = Double_t(k) * dxtick;
866  }
867  ytick = 0;
868  if (!mside) ytick -= atick[ltick];
869  if (optionNoopt && !optionInt) {
870  Rotate(xtick, ytick, cosphi, sinphi, x0, y0, xpl2, ypl2);
871  Rotate(xtick, atick[ltick], cosphi, sinphi, x0, y0, xpl1, ypl1);
872  }
873  else {
874  Rotate(xtick, ytick, cosphi, sinphi, xx0, yy0, xpl2, ypl2);
875  Rotate(xtick, atick[ltick], cosphi, sinphi, xx0, yy0, xpl1, ypl1);
876  }
877  if (optionVert) {
878  if ((x0 != x1) && (y0 != y1)) {
879  if (mside) {
880  xpl1 = xpl2;
881  if (cosphi > 0) ypl1 = ypl2 + atick[ltick];
882  else ypl1 = ypl2 - atick[ltick];
883  }
884  else {
885  xpl1 = 0.5 * (xpl1 + xpl2);
886  xpl2 = xpl1;
887  ypl1 = 0.5 * (ypl1 + ypl2) + atick[ltick];
888  ypl2 = 0.5 * (ypl1 + ypl2) - atick[ltick];
889  }
890  }
891  }
892  if (!drawGridOnly) PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
893 
894  if (optionGrid) {
895  if (ltick == 0) {
896  if (optionNoopt && !optionInt) {
897  Rotate(xtick, 0, cosphi, sinphi, x0, y0, xpl2, ypl2);
898  Rotate(xtick, grid_side * gridlength, cosphi, sinphi, x0, y0, xpl1, ypl1);
899  }
900  else {
901  Rotate(xtick, 0, cosphi, sinphi, xx0, yy0, xpl2, ypl2);
902  Rotate(xtick, grid_side * gridlength, cosphi, sinphi, xx0, yy0, xpl1, ypl1);
903  }
904  linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
905  }
906  }
907  }
908  xtick0 = 0;
909  xtick1 = xtick;
910 
911  if (fFunction) axis_length0 = binLow - wmin;
912  if ((!optionNoopt || optionInt) && axis_length0) {
913  nticks0 = Int_t(axis_length0 / dxtick);
914  if (nticks0 > 1000) nticks0 = 1000;
915  for (k = 0; k <= nticks0; k++) {
916  ltick = 2;
917  if (k % nn3 == 0) ltick = 1;
918  if (k % nn2 == 0) ltick = 0;
919  ytick0 = 0;
920  if (!mside) ytick0 -= atick[ltick];
921  if (fFunction) {
922  xtick0 = (fFunction->Eval(binLow - Double_t(k) * dxtick) - rwmi)
923  * axis_length / TMath::Abs(rwma - rwmi);
924  }
925  Rotate(xtick0, ytick0, cosphi, sinphi, xx0, yy0, xpl2, ypl2);
926  Rotate(xtick0, atick[ltick], cosphi, sinphi, xx0, yy0, xpl1, ypl1);
927  if (optionVert) {
928  if ((x0 != x1) && (y0 != y1)) {
929  if (mside) {
930  xpl1 = xpl2;
931  if (cosphi > 0) ypl1 = ypl2 + atick[ltick];
932  else ypl1 = ypl2 - atick[ltick];
933  }
934  else {
935  xpl1 = 0.5 * (xpl1 + xpl2);
936  xpl2 = xpl1;
937  ypl1 = 0.5 * (ypl1 + ypl2) + atick[ltick];
938  ypl2 = 0.5 * (ypl1 + ypl2) - atick[ltick];
939  }
940  }
941  }
942  if (!drawGridOnly) PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
943 
944  if (optionGrid) {
945  if (ltick == 0) {
946  Rotate(xtick0, 0, cosphi, sinphi, xx0, yy0, xpl2, ypl2);
947  Rotate(xtick0, grid_side * gridlength, cosphi, sinphi, xx0, yy0, xpl1, ypl1);
948  linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
949  }
950  }
951  xtick0 -= dxtick;
952  }
953  }
954 
955  if (fFunction) axis_length1 = wmax - binHigh;
956  if ((!optionNoopt || optionInt) && axis_length1) {
957  nticks1 = int(axis_length1 / dxtick);
958  if (nticks1 > 1000) nticks1 = 1000;
959  for (k = 0; k <= nticks1; k++) {
960  ltick = 2;
961  if (k % nn3 == 0) ltick = 1;
962  if (k % nn2 == 0) ltick = 0;
963  ytick1 = 0;
964  if (!mside) ytick1 -= atick[ltick];
965  if (fFunction) {
966  xtick1 = (fFunction->Eval(binHigh + Double_t(k) * dxtick) - rwmi)
967  * axis_length / TMath::Abs(rwma - rwmi);
968  }
969  Rotate(xtick1, ytick1, cosphi, sinphi, xx0, yy0, xpl2, ypl2);
970  Rotate(xtick1, atick[ltick], cosphi, sinphi, xx0, yy0, xpl1, ypl1);
971  if (optionVert) {
972  if ((x0 != x1) && (y0 != y1)) {
973  if (mside) {
974  xpl1 = xpl2;
975  if (cosphi > 0) ypl1 = ypl2 + atick[ltick];
976  else ypl1 = ypl2 - atick[ltick];
977  }
978  else {
979  xpl1 = 0.5 * (xpl1 + xpl2);
980  xpl2 = xpl1;
981  ypl1 = 0.5 * (ypl1 + ypl2) + atick[ltick];
982  ypl2 = 0.5 * (ypl1 + ypl2) - atick[ltick];
983  }
984  }
985  }
986  if (!drawGridOnly) PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
987  if (optionGrid) {
988  if (ltick == 0) {
989  Rotate(xtick1, 0, cosphi, sinphi, xx0, yy0, xpl2, ypl2);
990  Rotate(xtick1, grid_side * gridlength, cosphi, sinphi, xx0, yy0, xpl1, ypl1);
991  linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
992  }
993  }
994  xtick1 += dxtick;
995  }
996  }
997  }
998  }
999 
1000  //*-*- Draw the numeric labels if needed...
1001  if (!drawGridOnly && !optionUnlab) {
1002  if (!optionLog) {
1003  if (n1a) {
1004  //*-*- Spacing of labels
1005  if ((wmin == wmax) || (ndiv == 0)) {
1006  Error(where, "wmin (%f) == wmax (%f), or ndiv == 0", wmin, wmax);
1007  goto L210;
1008  }
1009  wlabel = wmin;
1010  dwlabel = (wmax - wmin) / Double_t(n1a);
1011  if (optionNoopt && !optionInt) dxlabel = axis_length / Double_t(n1a);
1012  else dxlabel = axis_lengthN / Double_t(n1a);
1013  if (fNbins) dxlabel = axis_length / (fWmax - fWmin);
1014 
1015  if (!optionText && !optionTime) {
1016 
1017  //*-*- We have to decide what format to generate
1018  //*-*- (for numeric labels only)
1019  //*-*- Test the magnitude, decide format
1020  flexe = kFALSE;
1021  nexe = 0;
1022  flexpo = kFALSE;
1023  flexne = kFALSE;
1024  ww = TMath::Max(TMath::Abs(wmin), TMath::Abs(wmax));
1025 
1026  //*-*- First case : (wmax-wmin)/n1a less than 0.001
1027  //*-*- (0.001 fgMaxDigits of 5 (fgMaxDigits) characters). Then we use x 10 n
1028  //*-*- format. If af >=0 x10 n cannot be used
1029  Double_t xmicros = 0.00099;
1030  if (maxDigits) xmicros = TMath::Power(10, -maxDigits);
1031  if (!noExponent && (TMath::Abs(wmax - wmin) / Double_t(n1a)) < xmicros) {
1032  af = TMath::Log10(ww) + epsilon;
1033  if (af < 0) {
1034  flexe = kTRUE;
1035  nexe = int(af);
1036  iexe = TMath::Abs(nexe);
1037  if (iexe % 3 == 1) iexe += 2;
1038  else if (iexe % 3 == 2) iexe += 1;
1039  if (nexe < 0) nexe = -iexe;
1040  else nexe = iexe;
1041  wlabel = wlabel * TMath::Power(10, iexe);
1042  dwlabel = dwlabel * TMath::Power(10, iexe);
1043  if1 = maxDigits;
1044  if2 = maxDigits - 2;
1045  goto L110;
1046  }
1047  }
1048  if (ww >= 1) af = TMath::Log10(ww);
1049  else af = TMath::Log10(ww * 0.0001);
1050  af += epsilon;
1051  nf = Int_t(af) + 1;
1052  if (!noExponent && nf > maxDigits) flexpo = kTRUE;
1053  if (!noExponent && nf < -maxDigits) flexne = kTRUE;
1054 
1055  //*-*- Use x 10 n format. (only powers of 3 allowed)
1056 
1057  if (flexpo) {
1058  flexe = kTRUE;
1059  while (1) {
1060  nexe++;
1061  ww /= 10;
1062  wlabel /= 10;
1063  dwlabel /= 10;
1064  if (nexe % 3 == 0 && ww <= TMath::Power(10, maxDigits - 1)) break;
1065  }
1066  }
1067 
1068  if (flexne) {
1069  flexe = kTRUE;
1070  rne = 1 / TMath::Power(10, maxDigits - 2);
1071  while (1) {
1072  nexe--;
1073  ww *= 10;
1074  wlabel *= 10;
1075  dwlabel *= 10;
1076  if (nexe % 3 == 0 && ww >= rne) break;
1077  }
1078  }
1079 
1080  na = 0;
1081  for (i = maxDigits - 1; i > 0; i--) {
1082  if (TMath::Abs(ww) < TMath::Power(10, i)) na = maxDigits - i;
1083  }
1084  ndyn = n1a;
1085  while (ndyn) {
1086  Double_t wdyn = TMath::Abs((wmax - wmin) / ndyn);
1087  if (wdyn <= 0.999 && na < maxDigits - 2) {
1088  na++;
1089  ndyn /= 10;
1090  }
1091  else break;
1092  }
1093 
1094  if2 = na;
1095  if1 = TMath::Max(nf + na, maxDigits) + 1;
1096 L110:
1097  if (TMath::Min(wmin, wmax) < 0)if1 = if1 + 1;
1098  if1 = TMath::Min(if1, 32);
1099 
1100  //*-*- In some cases, if1 and if2 are too small....
1101  while (dwlabel < TMath::Power(10, -if2)) {
1102  if1++;
1103  if2++;
1104  }
1105  coded = &chcoded[0];
1106  if (if1 > 14) if1 = 14;
1107  if (if2 > 14) if2 = 14;
1108  if (if2) snprintf(coded, 8, "%%%d.%df", if1, if2);
1109  else snprintf(coded, 8, "%%%d.%df", if1 + 1, 1);
1110  }
1111 
1112  //*-*- We draw labels
1113 
1114  snprintf(chtemp, 256, "%g", dwlabel);
1115  Int_t ndecimals = 0;
1116  if (optionDecimals) {
1117  char* dot = strchr(chtemp, '.');
1118  if (dot) {
1119  ndecimals = chtemp + strlen(chtemp) - dot;
1120  }
1121  else {
1122  char* exp;
1123  exp = strstr(chtemp, "e-");
1124  if (exp) {
1125  sscanf(&exp[2], "%d", &ndecimals);
1126  ndecimals++;
1127  }
1128  }
1129  }
1130  if (optionM) nlabels = n1a - 1;
1131  else nlabels = n1a;
1132  wTimeIni = wlabel;
1133  if (fNbins) nlabels = fNbins - 1;
1134  for (k = 0; k <= nlabels; k++) {
1135  if (fFunction) {
1136  Double_t xf = binLow + Double_t(k * nn2) * dxtick;
1137  Double_t zz = fFunction->Eval(xf) - rwmi;
1138  wlabel = xf;
1139  xlabel = zz * axis_length / TMath::Abs(rwma - rwmi);
1140  }
1141  else {
1142  if (fNbins) xlabel = dxlabel * (fBins[k] - fWmin);
1143  else xlabel = dxlabel * k;
1144  }
1145  if (optionM) xlabel += 0.5 * dxlabel;
1146 
1147  if (!optionText && !optionTime) {
1148  snprintf(label, 256, &chcoded[0], wlabel);
1149  if (fNbins) label = Form(fFormat, fBins[k]);
1150  if (fLabels) label = Form("%s", fLabels[k]);
1151  label[28] = 0;
1152  wlabel += dwlabel;
1153 
1154  LabelsLimits(label, first, last); //Eliminate blanks
1155 
1156  if (label[first] == '.') { //check if '.' is preceded by a digit
1157  strncpy(chtemp, "0", 256);
1158  strlcat(chtemp, &label[first], 256);
1159  strncpy(label, chtemp, 256);
1160  first = 1;
1161  last = strlen(label);
1162  }
1163  if (label[first] == '-' && label[first + 1] == '.') {
1164  strncpy(chtemp, "-0", 256);
1165  strlcat(chtemp, &label[first + 1], 256);
1166  strncpy(label, chtemp, 256);
1167  first = 1;
1168  last = strlen(label);
1169  }
1170 
1171  //*-*- We eliminate the non significant 0 after '.'
1172  if (ndecimals) {
1173  char* adot = strchr(label, '.');
1174  if (adot) adot[ndecimals] = 0;
1175  }
1176  else {
1177  while (label[last] == '0') {
1178  label[last] = 0;
1179  last--;
1180  }
1181  }
1182 
1183  //*-*- We eliminate the dot, unless dot is forced.
1184  if (label[last] == '.') {
1185  if (!optionDot) {
1186  label[last] = 0;
1187  last--;
1188  }
1189  }
1190 
1191  //*-*- Make sure the label is not "-0"
1192  if (last - first == 1 && label[first] == '-'
1193  && label[last] == '0') {
1194  strncpy(label, "0", 256);
1195  label[last] = 0;
1196  }
1197  if (fLabels) label = Form("%s", fLabels[k]);
1198  }
1199 
1200  //*-*- Generate the time labels
1201 
1202  if (optionTime) {
1203  timed = wlabel + (int)(timeoffset) - rangeOffset;
1204  timelabel = (time_t)((Long_t)(timed));
1205  if (optionTime == 1) {
1206  utctis = localtime(&timelabel);
1207  }
1208  else {
1209  utctis = gmtime(&timelabel);
1210  }
1211  TString timeformattmp;
1212  if (timeformat.Length() < 220) timeformattmp = timeformat;
1213  else timeformattmp = "#splitline{Format}{too long}";
1214 
1215  //*-*- Appends fractionnal part if seconds displayed
1216  if (dwlabel < 0.9) {
1217  double tmpdb;
1218  int tmplast;
1219  snprintf(label, 256, "%%S%7.5f", modf(timed, &tmpdb));
1220  tmplast = strlen(label) - 1;
1221 
1222  //*-*- We eliminate the non significiant 0 after '.'
1223  while (label[tmplast] == '0') {
1224  label[tmplast] = 0;
1225  tmplast--;
1226  }
1227 
1228  timeformattmp.ReplaceAll("%S", label);
1229  //*-*- replace the "0." at the begining by "s"
1230  timeformattmp.ReplaceAll("%S0.", "%Ss");
1231 
1232  }
1233 
1234  strftime(label, 256, timeformattmp.Data(), utctis);
1235  strncpy(chtemp, &label[0], 256);
1236  first = 0;
1237  last = strlen(label) - 1;
1238  wlabel = wTimeIni + (k + 1) * dwlabel;
1239  }
1240 
1241  //*-*- We generate labels (numeric or alphanumeric).
1242 
1243 // if(fLabels) label = fLabels[k];
1244  if (optionNoopt && !optionInt)
1245  Rotate(xlabel, ylabel, cosphi, sinphi, x0, y0, xx, yy);
1246  else Rotate(xlabel, ylabel, cosphi, sinphi, xx0, yy0, xx, yy);
1247  if (y0 == y1 && !optionDown && !optionUp) {
1248  yy -= 0.80 * charheight;
1249  }
1250  if (optionVert) {
1251  if (x0 != x1 && y0 != y1) {
1252  if (optionNoopt && !optionInt)
1253  Rotate(xlabel, 0, cosphi, sinphi, x0, y0, xx, yy);
1254  else Rotate(xlabel, 0, cosphi, sinphi, xx0, yy0, xx, yy);
1255  if (cosphi > 0) yy += ylabel;
1256  if (cosphi < 0) yy -= ylabel;
1257  }
1258  }
1259  if (!optionY || (x0 == x1)) {
1260  if (!optionText) {
1261  if (first > last) strncpy(chtemp, " ", 256);
1262  else strncpy(chtemp, &label[first], 256);
1263  textaxis->PaintLatex(gPad->GetX1() + xx * (gPad->GetX2() - gPad->GetX1()),
1264  gPad->GetY1() + yy * (gPad->GetY2() - gPad->GetY1()),
1265  0,
1266  textaxis->GetTextSize(),
1267  chtemp);
1268 // Info(where,"label : %s,%s",chtemp,fLabels[k]);
1269  }
1270  else {
1271  if (optionText == 1) textaxis->PaintLatex(gPad->GetX1() + xx * (gPad->GetX2() - gPad->GetX1()),
1272  gPad->GetY1() + yy * (gPad->GetY2() - gPad->GetY1()),
1273  0,
1274  textaxis->GetTextSize(),
1275  fAxis->GetBinLabel(k + fAxis->GetFirst()));
1276  }
1277  }
1278  else {
1279 
1280  //*-*- Text alignment is down
1281  if (!optionText) lnlen = last - first + 1;
1282  else {
1283  if (k + 1 > nhilab) lnlen = 0;
1284  }
1285  for (l = 1; l <= lnlen; l++) {
1286  if (!optionText) *chtemp = label[first + l - 2];
1287  else {
1288  if (lnlen == 0) strncpy(chtemp, " ", 256);
1289  else strncpy(chtemp, "1", 256);
1290  }
1291  textaxis->PaintLatex(gPad->GetX1() + xx * (gPad->GetX2() - gPad->GetX1()),
1292  gPad->GetY1() + yy * (gPad->GetY2() - gPad->GetY1()),
1293  0,
1294  textaxis->GetTextSize(),
1295  chtemp);
1296  yy -= charheight * 1.3;
1297  }
1298  }
1299  }
1300 
1301  //*-*- We use the format x 10 ** n
1302 
1303  if (flexe && !optionText && nexe) {
1304  snprintf(label, 256, "#times10^{%d}", nexe);
1305  if (x0 != x1) {
1306  xfactor = x1 - x0 + 0.1 * charheight;
1307  yfactor = 0;
1308  }
1309  else {
1310  xfactor = y1 - y0 + 0.1 * charheight;
1311  yfactor = 0;
1312  }
1313  Rotate(xfactor, yfactor, cosphi, sinphi, x0, y0, xx, yy);
1314  textaxis->SetTextAlign(11);
1315  if (GetLabelFont() % 10 < 2) // force TLatex mode in PaintLatex
1316  textaxis->SetTextFont((Int_t)(GetLabelFont() / 10) * 10 + 2);
1317  textaxis->PaintLatex(gPad->GetX1() + xx * (gPad->GetX2() - gPad->GetX1()),
1318  gPad->GetY1() + yy * (gPad->GetY2() - gPad->GetY1()),
1319  0,
1320  textaxis->GetTextSize(),
1321  label);
1322  }
1323  }
1324  }
1325  }
1326 
1327  //*-*- Log axis
1328 
1329  if (optionLog && ndiv) {
1330  UInt_t xi1 = 0, xi2, wi, yi1 = 0, yi2, hi, xl, xh;
1331  Bool_t firstintlab = kTRUE, overlap = kFALSE;
1332  if ((wmin == wmax) || (ndiv == 0)) {
1333  Error(where, "wmin (%f) == wmax (%f), or ndiv == 0", wmin, wmax);
1334  goto L210;
1335  }
1336  if (wmin <= 0) {
1337  Error(where, "negative logarithmic axis");
1338  goto L210;
1339  }
1340  if (wmax <= 0) {
1341  Error(where, "negative logarithmic axis");
1342  goto L210;
1343  }
1344  xmnlog = TMath::Log10(wmin);
1345  if (xmnlog > 0) xmnlog += 1.E-6;
1346  else xmnlog -= 1.E-6;
1347  x00 = 0;
1348  x11 = axis_length;
1349  h2 = TMath::Log10(wmax);
1350  h2sav = h2;
1351  if (h2 > 0) h2 += 1.E-6;
1352  else h2 -= 1.E-6;
1353  ih1 = int(xmnlog);
1354  ih2 = 1 + int(h2);
1355  nbinin = ih2 - ih1 + 1;
1356  axmul = (x11 - x00) / (h2sav - xmnlog);
1357 
1358  //*-*- Plot decade and intermediate tick marks
1359  decade = ih1 - 2;
1360  labelnumber = ih1;
1361  if (xmnlog > 0 && (xmnlog - Double_t(ih1) > 0)) labelnumber++;
1362  for (j = 1; j <= nbinin; j++) {
1363 
1364  //*-*- Plot decade
1365  firstintlab = kTRUE, overlap = kFALSE;
1366  decade++;
1367  if (x0 == x1 && j == 1) ylabel += charheight * 0.33;
1368  if (y0 == y1 && j == 1) ylabel -= charheight * 0.65;
1369  xone = x00 + axmul * (Double_t(decade) - xmnlog);
1370  //the following statement is a trick to circumvent a gcc bug
1371  if (j < 0) printf("j=%d\n", j);
1372  if (x00 > xone) goto L160;
1373  if ((xone - x11) > epsilon) break;
1374  xtwo = xone;
1375  y = 0;
1376  if (!mside) y -= atick[0];
1377  Rotate(xone, y, cosphi, sinphi, x0, y0, xpl2, ypl2);
1378  Rotate(xtwo, atick[0], cosphi, sinphi, x0, y0, xpl1, ypl1);
1379  if (optionVert) {
1380  if ((x0 != x1) && (y0 != y1)) {
1381  if (mside) {
1382  xpl1 = xpl2;
1383  if (cosphi > 0) ypl1 = ypl2 + atick[0];
1384  else ypl1 = ypl2 - atick[0];
1385  }
1386  else {
1387  xpl1 = 0.5 * (xpl1 + xpl2);
1388  xpl2 = xpl1;
1389  ypl1 = 0.5 * (ypl1 + ypl2) + atick[0];
1390  ypl2 = 0.5 * (ypl1 + ypl2) - atick[0];
1391  }
1392  }
1393  }
1394  if (!drawGridOnly) PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
1395 
1396  if (optionGrid) {
1397  Rotate(xone, 0, cosphi, sinphi, x0, y0, xpl2, ypl2);
1398  Rotate(xone, grid_side * gridlength, cosphi, sinphi, x0, y0, xpl1, ypl1);
1399  linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
1400  }
1401 
1402  if (!drawGridOnly && !optionUnlab) {
1403 
1404  //*-*- We generate labels (numeric only).
1405 // if(fLabels) label = fLabels[k];
1406  if (noExponent) {
1407  rlab = TMath::Power(10, labelnumber);
1408  snprintf(label, 256, "%f", rlab);
1409  LabelsLimits(label, first, last);
1410  while (last > first) {
1411  if (label[last] != '0') break;
1412  label[last] = 0;
1413  last--;
1414  }
1415  if (label[last] == '.') {
1416  label[last] = 0;
1417  last--;
1418  }
1419  }
1420  else {
1421  snprintf(label, 256, "%d", labelnumber);
1422  LabelsLimits(label, first, last);
1423  }
1424  Rotate(xone, ylabel, cosphi, sinphi, x0, y0, xx, yy);
1425  if ((x0 == x1) && !optionPara) {
1426  if (lside < 0) {
1427  if (mside < 0) {
1428  if (labelnumber == 0) nch = 1;
1429  else nch = 2;
1430  xx += nch * charheight;
1431  }
1432  else {
1433  xx += 0.25 * charheight;
1434  }
1435  }
1436  xx += 0.25 * charheight;
1437  }
1438  if ((y0 == y1) && !optionDown && !optionUp) {
1439  if (noExponent) yy += 0.33 * charheight;
1440  }
1441  if (n1a == 0)goto L210;
1442  kmod = nbinin / n1a;
1443  if (kmod == 0) kmod = 1000000;
1444  if ((nbinin <= n1a) || (j == 1) || (j == nbinin) || ((nbinin > n1a)
1445  && (j % kmod == 0))) {
1446  if (labelnumber == 0) {
1447  textaxis->PaintTextNDC(xx, yy, "1");
1448  }
1449  else if (labelnumber == 1) {
1450  textaxis->PaintTextNDC(xx, yy, "10");
1451  }
1452  else {
1453  if (noExponent) {
1454  textaxis->PaintTextNDC(xx, yy, &label[first]);
1455  }
1456  else {
1457  snprintf(chtemp, 256, "10^{%d}", labelnumber);
1458  textaxis->PaintLatex(gPad->GetX1() + xx * (gPad->GetX2() - gPad->GetX1()),
1459  gPad->GetY1() + yy * (gPad->GetY2() - gPad->GetY1()),
1460  0, textaxis->GetTextSize(), chtemp);
1461 
1462  }
1463  }
1464  }
1465  labelnumber++;
1466  }
1467 L160:
1468  for (k = 2; k < 10; k++) {
1469 
1470  //*-*- Plot intermediate tick marks
1471  xone = x00 + axmul * (TMath::Log10(Double_t(k)) + Double_t(decade) - xmnlog);
1472  if (x00 > xone) continue;
1473  if (xone > x11) goto L200;
1474  y = 0;
1475  if (!mside) y -= atick[1];
1476  xtwo = xone;
1477  Rotate(xone, y, cosphi, sinphi, x0, y0, xpl2, ypl2);
1478  Rotate(xtwo, atick[1], cosphi, sinphi, x0, y0, xpl1, ypl1);
1479  if (optionVert) {
1480  if ((x0 != x1) && (y0 != y1)) {
1481  if (mside) {
1482  xpl1 = xpl2;
1483  if (cosphi > 0) ypl1 = ypl2 + atick[1];
1484  else ypl1 = ypl2 - atick[1];
1485  }
1486  else {
1487  xpl1 = 0.5 * (xpl1 + xpl2);
1488  xpl2 = xpl1;
1489  ypl1 = 0.5 * (ypl1 + ypl2) + atick[1];
1490  ypl2 = 0.5 * (ypl1 + ypl2) - atick[1];
1491  }
1492  }
1493  }
1494  idn = n1a * 2;
1495  if ((nbinin <= idn) || ((nbinin > idn) && (k == 5))) {
1496  if (!drawGridOnly) PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
1497 
1498  //*-*- Draw the intermediate LOG labels if requested
1499 
1500  if (moreLogLabels && !optionUnlab && !drawGridOnly && !overlap) {
1501  if (noExponent) {
1502  rlab = Double_t(k) * TMath::Power(10, labelnumber - 1);
1503  snprintf(chtemp, 256, "%g", rlab);
1504  }
1505  else {
1506  if (labelnumber - 1 == 0) {
1507  snprintf(chtemp, 256, "%d", k);
1508  }
1509  else if (labelnumber - 1 == 1) {
1510  snprintf(chtemp, 256, "%d", 10 * k);
1511  }
1512  else {
1513  snprintf(chtemp, 256, "%d#times10^{%d}", k, labelnumber - 1);
1514  }
1515  }
1516  Rotate(xone, ylabel, cosphi, sinphi, x0, y0, xx, yy);
1517  if ((x0 == x1) && !optionPara) {
1518  if (lside < 0) {
1519  if (mside < 0) {
1520  if (labelnumber == 0) nch = 1;
1521  else nch = 2;
1522  xx += nch * charheight;
1523  }
1524  else {
1525  if (labelnumber >= 0) xx += 0.25 * charheight;
1526  else xx += 0.50 * charheight;
1527  }
1528  }
1529  xx += 0.25 * charheight;
1530  }
1531  if ((y0 == y1) && !optionDown && !optionUp) {
1532  if (noExponent) yy += 0.33 * charheight;
1533  }
1534  if (optionVert) {
1535  if ((x0 != x1) && (y0 != y1)) {
1536  Rotate(xone, ylabel, cosphi, sinphi, x0, y0, xx, yy);
1537  if (cosphi > 0) yy += ylabel;
1538  else yy -= ylabel;
1539  }
1540  }
1541  textaxis->SetTitle(chtemp);
1542  Double_t u = gPad->GetX1() + xx * (gPad->GetX2() - gPad->GetX1());
1543  Double_t v = gPad->GetY1() + yy * (gPad->GetY2() - gPad->GetY1());
1544  if (firstintlab) {
1545  textaxis->GetBoundingBox(wi, hi);
1546  wi = (UInt_t)(wi * 1.3);
1547  hi *= (UInt_t)(hi * 1.3);
1548  xi1 = gPad->XtoAbsPixel(u);
1549  yi1 = gPad->YtoAbsPixel(v);
1550  firstintlab = kFALSE;
1551  textaxis->PaintLatex(u, v, 0, textaxis->GetTextSize(), chtemp);
1552  }
1553  else {
1554  xi2 = gPad->XtoAbsPixel(u);
1555  yi2 = gPad->YtoAbsPixel(v);
1556  xl = TMath::Min(xi1, xi2);
1557  xh = TMath::Max(xi1, xi2);
1558  if ((x0 == x1 && yi1 - hi <= yi2) || (y0 == y1 && xl + wi >= xh)) {
1559  overlap = kTRUE;
1560  }
1561  else {
1562  xi1 = xi2;
1563  yi1 = yi2;
1564  textaxis->GetBoundingBox(wi, hi);
1565  wi = (UInt_t)(wi * 1.3);
1566  hi *= (UInt_t)(hi * 1.3);
1567  textaxis->PaintLatex(u, v, 0, textaxis->GetTextSize(), chtemp);
1568  }
1569  }
1570  }
1571 
1572  //*-*- Draw the intermediate LOG grid if only three decades are requested
1573  if (optionGrid && nbinin <= 5 && ndiv > 100) {
1574  Rotate(xone, 0, cosphi, sinphi, x0, y0, xpl2, ypl2);
1575  Rotate(xone, grid_side * gridlength, cosphi, sinphi, x0, y0, xpl1, ypl1);
1576  linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
1577  }
1578  } //endif ((nbinin <= idn) ||
1579  } //endfor (k=2;k<10;k++)
1580  } //endfor (j=1; j<=nbinin; j++)
1581 L200:
1582  Int_t kuku = 0;
1583  if (kuku) { }
1584  } //endif (optionLog && ndiv)
1585 
1586 
1587 L210:
1588  if (optionGrid) delete linegrid;
1589  delete textaxis;
1590 }
1591 
1592 
1593 
int Int_t
unsigned int UInt_t
long Long_t
const Int_t kHori
Definition: KVGaxis.cpp:28
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
#define e(i)
const Bool_t kFALSE
bool Bool_t
double Double_t
float Float_t
const Bool_t kTRUE
const char Option_t
#define BIT(n)
const Double_t kPI
float xmin
float ymin
float xmax
float type_of_call hi(const int &, const int &)
float ymax
double exp(double)
#define gROOT
char * Form(const char *fmt,...)
R__EXTERN TStyle * gStyle
R__EXTERN TSystem * gSystem
#define gPad
#define gVirtualX
#define snprintf
Extension of TGaxis class optimised for KVGraph visualisation.
Definition: KVGaxis.h:17
Double_t * fBins
Definition: KVGaxis.h:20
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)
Definition: KVGaxis.cpp:130
const char * fFormat
Definition: KVGaxis.h:21
KVGaxis()
Definition: KVGaxis.cpp:35
virtual ~KVGaxis()
Destructor.
Definition: KVGaxis.cpp:106
char ** fLabels
Definition: KVGaxis.h:22
Int_t fNbins
Definition: KVGaxis.h:19
virtual Float_t GetLabelOffset() const
virtual Color_t GetLineColor() const
virtual void SetLineStyle(Style_t lstyle)
virtual void SetLineWidth(Width_t lwidth)
virtual void SetLineColor(Color_t lcolor)
virtual Float_t GetTextSize() const
virtual void SetTextAlign(Short_t align=11)
virtual Font_t GetTextFont() const
virtual Color_t GetTextColor() const
virtual void SetTextAngle(Float_t tangle=0)
virtual Float_t GetTextAngle() const
virtual void SetTextColor(Color_t tcolor=1)
virtual void SetTextFont(Font_t tfont=62)
virtual void SetTextSize(Float_t tsize=1)
virtual Double_t GetBinCenter(Int_t bin) const
kMoreLogLabels
const char * GetBinLabel(Int_t bin) const
THashList * GetLabels() const
Int_t GetLast() const
Int_t GetFirst() const
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
static Int_t fgMaxDigits
Definition: KVGaxis.cpp:27
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)
virtual const char * GetTitle() const
TAxis * fAxis
TString fTimeFormat
TString fFunctionName
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)
Float_t GetLabelOffset() const
Float_t fTickSize
Int_t GetLabelFont() const
Float_t fLabelOffset
Float_t fLabelSize
Int_t fNdiv
TString fChopt
Float_t GetTitleOffset() const
TF1 * fFunction
Float_t GetTitleSize() const
virtual void AdjustBinSize(Double_t A1, Double_t A2, Int_t nold, Double_t &BinLow, Double_t &BinHigh, Int_t &nbins, Double_t &BinWidth)
Int_t GetLabelColor() const
Double_t fWmax
Double_t fWmin
void LabelsLimits(const char *label, Int_t &first, Int_t &last)
Float_t GetLabelSize() const
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="")
Double_t GetXsize()
void GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle=kFALSE)
virtual void PaintLatex(Double_t x, Double_t y, Double_t angle, Double_t size, const char *text)
virtual void PaintLineNDC(Double_t u1, Double_t v1, Double_t u2, Double_t v2)
virtual const char * GetName() const
virtual void SetTitle(const char *title="")
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
virtual void Error(const char *method, const char *msgfmt,...) const
Ssiz_t Length() const
const char * Data() const
TString & ReplaceAll(const char *s1, const char *s2)
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Double_t GetTimeOffset() const
Color_t GetGridColor() const
Style_t GetGridStyle() const
Width_t GetGridWidth() const
Int_t GetStripDecimals() const
virtual const char * Getenv(const char *env)
virtual void Unsetenv(const char *name)
virtual void Setenv(const char *name, const char *value)
virtual void SetText(Double_t x, Double_t y, const char *text)
virtual void PaintTextNDC(Double_t u, Double_t v, const char *text)
double beta(double x, double y)
Double_t y[n]
const long double s
Definition: KVUnits.h:94
const long double mm
Definition: KVUnits.h:69
Double_t Min(Double_t a, Double_t b)
Double_t ATan2(Double_t y, Double_t x)
Double_t Power(Double_t x, Double_t y)
Double_t Sqrt(Double_t x)
Double_t Cos(Double_t)
constexpr Double_t Pi()
Double_t Abs(Double_t d)
Double_t Sin(Double_t)
Double_t Max(Double_t a, Double_t b)
Double_t Log10(Double_t x)
v
auto * l
REAL epsilon