KaliVeda
Toolkit for HIC analysis
KVIDZAGrid.cpp
1 /***************************************************************************
2  KVIDZAGrid.cpp - description
3  -------------------
4  begin : Nov 24 2004
5  copyright : (C) 2004 by J.D. Frankland
6  email : frankland@ganil.fr
7 
8 $Id: KVIDZAGrid.cpp,v 1.24 2009/05/05 15:57:52 franklan Exp $
9 ***************************************************************************/
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  ***************************************************************************/
19 
20 
21 #include "KVIDZAGrid.h"
22 #include "KVIDZALine.h"
23 #include "KVIDCutLine.h"
24 #include "TCanvas.h"
25 #include "TROOT.h"
26 #include "KVIdentificationResult.h"
27 
28 
31 
34 {
35  //default ctor.
36  init();
37 }
38 
39 
40 
43 
44 KVIDZAGrid::~KVIDZAGrid()
45 {
46  //default dtor.
47 }
48 
49 
50 
53 
55 {
56  //Copy constructor
57  init();
58  grid.Copy(*this);
59 }
60 
61 
62 
65 
66 void KVIDZAGrid::Copy(TObject& obj) const
67 {
68  //Copy this to 'obj'
69  KVIDGrid::Copy(obj);
70  KVIDZAGrid& i = (KVIDZAGrid&)obj;
71  // find the fZmax and fZmaxline pointer for new copy
72  i.Initialize();
73 }
74 
75 
76 
77 
80 
82 {
83  //initialisation
84  fZMax = 0;
85  fZMaxLine = 0;
86 
87  kinfi = kinf = ksup = ksups = -1;
88  dinf = dsup = dinfi = dsups = 0.;
89  winf = wsup = winfi = wsups = 0.;
90  Zinfi = Zinf = Zsup = Zsups = Ainfi = Ainf = Asup = Asups = 0;
91  fDistanceClosest = -1.;
92  fClosest = fLsups = fLsup = fLinf = fLinfi = 0;
93  fIdxClosest = -1;
94 }
95 
96 
97 
98 
101 
103 {
104  // Remove and destroy identifier
105 
106  gROOT->ProcessLine("if(gROOT->FindObject(\"gIDGridEditorCanvas\")) gIDGridEditor->Clear()");
107 
108  Int_t toto = -1;
109  KVIDZALine* tmpline = 0;
110  if ((A > 0) && (!IsOnlyZId())) {
111  if ((tmpline = GetZALine(Z, A, toto))) RemoveIdentifier((KVIDentifier*)tmpline);
112  }
113  else {
114  if (!IsOnlyZId()) {
115  KVList* tmplist = (KVList*)fIdentifiers.GetSubListWithMethod(Form("%d", Z), "GetZ");
116  TIter next_id(tmplist);
117  while ((tmpline = (KVIDZALine*)next_id())) {
118  if (tmpline) RemoveIdentifier((KVIDentifier*)tmpline);
119  }
120  delete tmplist;
121  }
122  else if ((tmpline = GetZLine(Z, toto))) RemoveIdentifier((KVIDentifier*)tmpline);
123  }
124 }
125 
126 
127 
128 
131 
133 {
134  // Remove and destroy identifiers
135  KVNumberList ZL(ZList);
136  ZL.Begin();
137  while (!ZL.End()) {
138  Int_t Z = ZL.Next();
139  RemoveLine(Z, -1);
140  }
141 }
142 
143 
144 
145 
151 
153 {
154  //Returns ID line for which GetZ() returns 'z'. index=index of line found in
155  //fIDLines list (-1 if not found).
156  //To increase speed, this is done by dichotomy, rather than by looping over
157  //all the lines in the list.
158 
159  index = -1;
160  Int_t nlines = GetNumberOfIdentifiers();
161  UInt_t idx_min = 0; //minimum index
162  UInt_t idx_max = nlines - 1; // maximum index
163  //as a first guess, we suppose that the lines are numbered sequentially from
164  //Z=1 (index 0) to Z=zmax=nlines (index nlines-1) with no gaps
165  UInt_t idx = ((UInt_t) z - 1 > idx_max ? idx_max : (UInt_t) z - 1);
166 
167  while (idx_max > idx_min + 1) {
168 
170  Int_t zline = line->GetZ();
171  //Found it ?
172  if (zline == z) {
173  index = idx;
174  return line;
175  }
176 
177 
178  if (z > zline) {
179  //increase index
180  idx_min = idx;
181  idx += (Int_t)((idx_max - idx) / 2 + 0.5);
182  }
183  else {
184  //decrease index
185  idx_max = idx;
186  idx -= (Int_t)((idx - idx_min) / 2 + 0.5);
187  }
188  }
189  //if one of these two lines has the right Z, return its pointer
190  KVIDZALine* line = (KVIDZALine*) GetIdentifierAt(idx_min);
191  if (line->GetZ() == z) {
192  index = idx_min;
193  return line;
194  }
195  line = (KVIDZALine*) GetIdentifierAt(idx_max);
196  if (line->GetZ() == z) {
197  index = idx_max;
198  return line;
199  }
200  //if not, there is no line in the grid with the right Z
201  return 0;
202 }
203 
204 
205 
206 
212 
214 {
215  //Returns ID line corresponding to nucleus (Z,A) and its index in fIDLines.
216  //First we use GetLine(z) to find a line with the right Z (in
217  //principal there are several in the grid), then search for the correct
218  //isotope among these.
219 
220  Int_t idx;
221  index = -1;
222  KVIDZALine* line = GetZLine(z, idx);
223  //no line with correct Z ?
224  if (!line)
225  return 0;
226  //got right mass?
227  if (line->GetA() == a) {
228  index = idx;
229  return line;
230  }
231  //increase/decreas index depending on if mass of line is greater than or less than a
232  if (a > line->GetA()) {
233  for (int i = idx; i < (int) GetNumberOfIdentifiers(); i++) {
235  if (line->GetZ() != z)
236  return 0; //no longer correct Z
237  if (line->GetA() == a) {
238  index = i;
239  return line;
240  }
241  }
242  //gone to the end of the list and still not found it
243  return 0;
244  }
245  else if (a < line->GetA()) {
246  for (int i = idx; i > 0; i--) {
248  if (line->GetZ() != z)
249  return 0; //no longer correct Z
250  if (line->GetA() == a) {
251  index = i;
252  return line;
253  }
254  }
255  //got to start of list and still not found
256  return 0;
257  }
258  return 0;
259 }
260 
261 
262 
263 
287 
289 {
290  //Calculate natural "width" of each line in the grid.
291  //The lines in the grid are first sorted so that they are in order of ascending 'Y'
292  //i.e. first line is 1H, last line is the heaviest isotope (highest line).
293  //
294  //Then, for a given line :
295  //
296  // **** if the grid is to be used for A & Z identification (default)**** :
297  // - if the next line (above) has the same Z, we use the separation between these
298  // two lines corresponding to different isotopes of the same element
299  // - if the next line (above) has a different Z, but the line before (below) has
300  // the same Z, we use the separation between the line below and this one
301  // - if neither adjacent line has the same Z, the width is set to 16000 (huge).
302  //
303  // **** if the grid is to be used for Z identification (fOnlyZid=kTRUE)**** :
304  // - we use the separation between each pair of lines
305  //
306  //In each case we find D_L (the separation between the two lines at their extreme left)
307  //and D_R (their separation at extreme right). The width of the line is then calculated
308  //from these two using the method KVIDZALine::SetAsymWidth (which may be overridden in child
309  //classes).
310 
311 
312 // Info("CalculateLineWidths",
313 // "For grid %s (%s vs. %s, runs %s).", GetName(), GetVarY(), GetVarX(), GetRunList());
314 
315  for (Int_t i = 0; i < (Int_t) GetNumberOfIdentifiers(); i++) {
316 
317  KVIDentifier* obj = GetIdentifierAt(i);
318  if (!obj->InheritsFrom("KVIDZALine")) continue;
319  KVIDZALine* _line = (KVIDZALine*) obj;
320 // KVIDZALine* _line = (KVIDZALine*) GetIdentifierAt(i);
321 
322  //Z of lines above and below this line - Zxx=-1 if there is no line above or below
323  Int_t Zhi =
324  (i <
326  1 ? ((KVIDZALine*) GetIdentifierAt(i + 1))->GetZ() : -1);
327  Int_t Zlo = (i > 0 ? ((KVIDZALine*) GetIdentifierAt(i - 1))->GetZ() : -1);
328  Int_t Z = _line->GetZ();
329 
330  // find line for comparison.
331  // if we are dealing with a grid with several isotopes for each Z, the priority
332  // is to calculate isotopic line widths using lines with same Z, different A.
333  // if the grid is 'OnlyZId' it should have only one line per Z, so we calculate
334  // widths by comparing neighbouring Z.
335  // if the grid is not 'OnlyZId', it may still have some lines with just one isotope
336  // per Z, in this case we calculate a width based on the separation from the
337  // neighbouring Z, as if it were 'OnlyZId'.
338  Int_t i_other;// index of line used to calculate width
339  if (IsOnlyZId()) { //grid is 'OnlyZId':calculate widths by comparing neighbouring Z.
340  i_other = (Zhi > -1 ? i + 1 : (Zlo > -1 ? i - 1 : -1));
341  }
342  else {
343  //grid with several isotopes for each Z:calculate isotopic widths using lines with same Z, different A
344  i_other = (Zhi == Z ? i + 1 : (Zlo == Z ? i - 1 : -1));
345  }
346  if (!IsOnlyZId() && i_other < 0) { //grid is not 'OnlyZId' but only one isotope for this Z
347  i_other = (Zhi > -1 ? i + 1 : (Zlo > -1 ? i - 1 : -1));
348  }
349 
350  //default width of 16000 in case of "orphan" line
351  if (i_other < 0) {
352  //Info("CalculateLineWidths", "No line found for comparison with %s. Width set to 16000", _line->GetName());
353  _line->SetWidth(16000.);
354  continue; // skip to next line
355  }
356 
357  KVIDZALine* _otherline = (KVIDZALine*) GetIdentifierAt(i_other);
358 
359  //calculate asymptotic distances between lines at left and right.
360  //do this by finding which line's endpoint is between both endpoints of the other line
361  Double_t D_L, D_R;
362 
363  //*************** LEFT SIDE ********************************
364 
365  //get coordinates of first point of our line
366  Double_t x1, y1;
367  _line->GetStartPoint(x1, y1);
368  KVIDZALine* _aline, *_bline;
369 
370  if (_otherline->IsBetweenEndPoints(x1, y1, "x")) {
371 
372  //first point of our line is "inside" the X-coords of the other line:
373  //asymptotic distance LEFT is distance from our line's starting point (x1,Y1) to the other line
374  _aline = _otherline;
375  _bline = _line;
376 
377  }
378  else {
379 
380  //first point of other line is "inside" the X-coords of the our line:
381  //asymptotic distance LEFT is distance from other line's starting point (x1,Y1) to our line
382  _aline = _line;
383  _bline = _otherline;
384  _otherline->GetStartPoint(x1, y1);
385 
386  }
387 
388  //calculate D_L
389  Int_t dummy = 0;
390  D_L = _aline->DistanceToLine(x1, y1, dummy);
391 
392  //make sure that D_L is positive : if not, we try to calculate other way (inverse line and starting point)
393  if (D_L < 0.) {
394 
395  Double_t oldD_L = D_L;
396 
397  _aline->GetStartPoint(x1, y1);
398  D_L = _bline->DistanceToLine(x1, y1, dummy);
399 
400  //still no good ? then we keep the smallest absolute value
401  if (D_L < 0.) {
402  D_L = TMath::Abs(TMath::Max(D_L, oldD_L));
403  }
404  }
405  //*************** RIGHT SIDE ********************************
406 
407  //get coordinates of last point of our line
408  _line->GetEndPoint(x1, y1);
409 
410  if (_otherline->IsBetweenEndPoints(x1, y1, "x")) {
411 
412  //last point of our line is "inside" the X-coords of the other line:
413  //asymptotic distance RIGHT is distance from our line's end point (x1,Y1) to the other line
414  _aline = _otherline;
415  _bline = _line;
416 
417  }
418  else {
419 
420  //last point of other line is "inside" the X-coords of the our line:
421  //asymptotic distance RIGHT is distance from other line's end point (x1,Y1) to our line
422  _aline = _line;
423  _bline = _otherline;
424  _otherline->GetEndPoint(x1, y1);
425 
426  }
427 
428  //calculate D_R
429  D_R = _aline->DistanceToLine(x1, y1, dummy);
430 
431  //make sure that D_R is positive : if not, we try to calculate other way (inverse line and end point)
432  if (D_R < 0.) {
433 
434  Double_t oldD_R = D_R;
435 
436  _aline->GetEndPoint(x1, y1);
437  D_R = _bline->DistanceToLine(x1, y1, dummy);
438 
439  //still no good ? then we keep the smallest absolute value
440  if (D_R < 0.) {
441  D_R = TMath::Abs(TMath::Max(D_R, oldD_R));
442  }
443  }
444  //*************** SET NATURAL WIDTH OF LINE ********************************
445 
446  _line->SetAsymWidth(D_L, D_R);
447 
448 
449  //Info("CalculateLineWidths", "...width for line %s set to : %f (D_L=%f,D_R=%f)", _line->GetName(), _line->GetWidth(), D_L, D_R);
450  }
451 }
452 
453 
454 
455 
459 
461 {
462  //This method displays the grid as in KVIDGrid::Draw, but
463  //the natural line widths are shown as error bars
464 
465  if (!gPad) {
466  new TCanvas("c1", GetName());
467  }
468  else {
469  gPad->SetTitle(GetName());
470  }
471  if (!gPad->GetListOfPrimitives()->GetSize()) {
472  //calculate size of pad necessary to show grid
473  if (GetXmin() == GetXmax())
474  const_cast < KVIDZAGrid* >(this)->FindAxisLimits();
475  gPad->DrawFrame(GetXmin(), GetYmin(), GetXmax(), GetYmax());
476  }
477  TIter nextID(GetIdentifiers());
478  KVIDZALine* line;
479  while ((line = (KVIDZALine*)nextID())) {
480  line->GetLineWithWidth()->Draw("3PL");
481  }
482  {
483  GetCuts()->R__FOR_EACH(KVIDLine, Draw)("PL");
484  }
485  gPad->Modified();
486  gPad->Update();
487 }
488 
489 
490 
491 
518 
520 {
521  // This method will locate (at most) four lines close to the point (x,y), the point must
522  // lie within the endpoints (in X) of each line (the lines "embrace" the point).
523  // Returns kTRUE if at least one line is found. Identification can then be carried out with
524  // either IdentZA or IdentZ (see Identify).
525  // Returns kFALSE if no lines are found (not even a closest embracing line).
526  //
527  // We look for two lines above the point and two lines below the point, as in one of the following two cases:
528  //
529  // ------------------------ ksups ---------------------
530  //
531  // closest ---> ------------------------ ksup ---------------------
532  // X
533  //
534  // X
535  // ------------------------ kinf --------------------- <--- closest
536  //
537  // ------------------------ kinfi ---------------------
538  //
539  // First we find the closest embracing line to the point, using FindNearestEmbracingIDLine.
540  // Then we search above and below for the other 'embracing' lines. Note that no condition is
541  // applied regarding the distances to these lines: the lines must have been sorted in order of increasing
542  // ordinate before hand in Initialize(), we simply use the order of lines in the list of identifiers.
543  // The Z, A, width and distance to each of these lines are stored in the variables
544  // Zsups, Asups, wsups, dsups
545  // etc. etc. to be used by IdentZA or IdentZ.
546 
547 
548  kinfi = kinf = ksup = ksups = -1;
549  dinf = dsup = dinfi = dsups = 0.;
550  winf = wsup = winfi = wsups = 16000.;
551  Zinfi = Zinf = Zsup = Zsups = Ainfi = Ainf = Asup = Asups = -1;
552  fDistanceClosest = -1.;
553  fClosest = fLsups = fLsup = fLinf = fLinfi = 0;
554  fIdxClosest = -1;
555 
557 
558  if (!fClosest) return kFALSE; // no lines found
559 
560  Int_t dummy = 0;
561  if (kinf > -1 && kinf == fIdxClosest) {
562  //point is above closest line, closest line is "kinf"
563  //need to look for 2 lines above (ksup, ksups) and 1 line below (kinfi)
564  fLinf = fClosest;
565  if (fLinf->InheritsFrom("KVIDZALine")) {
566  winf = ((KVIDZALine*)fLinf)->GetWidth();
567  Zinf = fLinf->GetZ();
568  Ainf = fLinf->GetA();
569  }
570  if (ksup > -1) {
572  if (fLsup->InheritsFrom("KVIDZALine")) {
573  wsup = ((KVIDZALine*)fLsup)->GetWidth();
574  Zsup = fLsup->GetZ();
575  Asup = fLsup->GetA();
576  }
577  }
578  }
579  else if (ksup > -1 && ksup == fIdxClosest) {
580  //point is below closest line, closest line is "ksup"
581  //need to look for 1 line above (ksups) and 2 lines below (kinf, kinfi)
582  fLsup = fClosest;
583  if (fLsup->InheritsFrom("KVIDZALine")) {
584  wsup = ((KVIDZALine*)fLsup)->GetWidth();
585  Zsup = fLsup->GetZ();
586  Asup = fLsup->GetA();
587  }
588  if (kinf > -1) {
590  if (fLinf->InheritsFrom("KVIDZALine")) {
591  winf = ((KVIDZALine*)fLinf)->GetWidth();
592  Zinf = fLinf->GetZ();
593  Ainf = fLinf->GetA();
594  }
595  }
596  }
597  else {
598  Error("FindFourEmbracingLines",
599  "I do not understand the result of FindNearestEmbracingIDLine!!!");
600  return kFALSE;
601  }
602 
603 
604  if (kinf > -1) {
605  // look for kinfi line -> next line below 'inf' line
606  kinfi = kinf;
607  fLinfi = FindNextEmbracingLine(kinfi, -1, x, y, "x");
608  if (!fLinfi) kinfi = -1; // no 'infi' line found
609  else {
610  dinfi = TMath::Abs(fLinfi->DistanceToLine(x, y, dummy));
611  if (fLinfi->InheritsFrom("KVIDZALine")) {
612  winfi = ((KVIDZALine*)fLinfi)->GetWidth();
613  Zinfi = fLinfi->GetZ();
614  Ainfi = fLinfi->GetA();
615  }
616  }
617  }
618  if (ksup > -1) {
619  // look for ksups line -> next line above 'sup' line
620  ksups = ksup;
621  fLsups = FindNextEmbracingLine(ksups, 1, x, y, "x");
622  if (!fLsups) ksups = -1; // no 'sups' line found
623  else {
624  dsups = TMath::Abs(fLsups->DistanceToLine(x, y, dummy));
625  if (fLsups->InheritsFrom("KVIDZALine")) {
626  wsups = ((KVIDZALine*)fLsups)->GetWidth();
627  Zsups = fLsups->GetZ();
628  Asups = fLsups->GetA();
629  }
630  }
631  }
632  return kTRUE;
633 }
634 
635 
636 
637 
643 
645 {
646  //Finds Z, A and 'real A' for point (x,y) once closest lines to point have been found
647  //by calling method FindFourEmbracingLines beforehand.
648  //This is a line-for-line copy of the latter part of IdnCsOr, even the same
649  //variable names and comments have been used (as much as possible).
650 
651  fICode = kICODE0;
652  Z = -1;
653  A = -1;
654  Aint = 0;
655  /* cout << "kinfi = " << kinfi << " Zinfi = " << Zinfi << " Ainfi = " << Ainfi << " winfi = " << winfi << " dinfi = " << dinfi << endl;
656  cout << "kinf = " << kinf << " Zinf = " << Zinf << " Ainf = " << Ainf << " winf = " << winf << " dinf = " << dinf << endl;
657  cout << "ksup = " << ksup << " Zsup = " << Zsup << " Asup = " << Asup << " wsup = " << wsup << " dsup = " << dsup << endl;
658  cout << "ksups = " << ksups << " Zsups = " << Zsups << " Asups = " << Asups << " wsups = " << wsups << " dsups = " << dsups << endl;
659  */
660  Int_t ibif = 0;
661  Int_t k = -1;
662  Double_t yy, y1, y2;
663  Int_t ix1, ix2;
664  yy = y1 = y2 = 0;
665  ix1 = ix2 = 0;
666  if (ksup > -1) {
667  if (kinf > -1) {
668  //cout << " /******************* 2 lignes encadrant le point ont ete trouvees ************************/" << endl;
669  Double_t dt = dinf + dsup; //distance between the 2 lines
670  if (Zinf == Zsup) {
671  // cout << " /****************meme Z**************/" << endl;
672  Z = Zinf;
673  Int_t dA = Asup - Ainf;
674  Double_t dist = dt / dA; //distance between the 2 lines normalised to difference in A of lines
675  /*** A = Asup ***/
676  if (dinf > dsup) { //point is closest to upper line, 'sup' line
677  ibif = 1;
678  k = ksup;
679  yy = -dsup;
680  A = Asup;
681  Aint = Asup;
682  if (ksups > -1) { // there is a 'sups' line above the 2 which encadrent le point
683  y2 = dsups - dsup;
684  if (Zsups == Zsup) {
685  ibif = 0;
686  y2 /= 2.;
687  ix2 = Asups - Asup;
688  }
689  else {
690  y2 /= 2.;
691  Double_t x2 = wsup;
692  x2 = 0.5 * TMath::Max(x2, dist);
693  y2 = TMath::Min(y2, x2);
694  ix2 = 1;
695  }
696  }
697  else { // ksups == -1 i.e. no 'sups' line
698  y2 = wsup;
699  y2 = 0.5 * TMath::Max(y2, dist);
700  ix2 = 1;
701  }
702  y1 = -dt / 2.;
703  ix1 = -dA;
704  }
705  /*** A = Ainf ***/
706  else { //point is closest to lower line, 'inf' line
707  ibif = 2;
708  k = kinf;
709  yy = dinf;
710  A = Ainf;
711  Aint = Ainf;
712  if (kinfi > -1) { // there is a 'infi' line below the 2 which encadrent le point
713  y1 = 0.5 * (dinfi - dinf);
714  if (Zinfi == Zinf) {
715  ibif = 0;
716  ix1 = Ainfi - Ainf;
717  y1 = -y1;
718  }
719  else {
720  Double_t x1 = winf;
721  x1 = 0.5 * TMath::Max(x1, dist);
722  y1 = -TMath::Min(y1, x1);
723  ix1 = -1;
724  }
725  }
726  else { // kinfi = -1 i.e. no 'infi' line
727  y1 = winf;
728  y1 = -0.5 * TMath::Max(y1, dist);
729  ix1 = -1;
730  }
731  y2 = dt / 2.;
732  ix2 = dA;
733  }
734  }
735  else {
736  //cout << " /****************Z differents**************/ " << endl;
737  /*** Z = Zsup ***/
738  ibif = 3;
739  if (dinf > dsup) { // closest to upper 'sup' line
740  k = ksup;
741  yy = -dsup;
742  Z = Zsup;
743  A = Asup;
744  Aint = Asup;
745  y1 = 0.5 * wsup;
746  if (ksups > -1) { // there is a 'sups' line above the 2 which encadrent the point
747  y2 = dsups - dsup;
748  if (Zsups == Zsup) {
749  ibif = 2;
750  ix2 = Asups - Asup;
751  Double_t x1 = y2 / ix2 / 2.;
752  y1 = TMath::Max(y1, x1);
753  y1 = -TMath::Min(y1, dt / 2.);
754  ix1 = -1;
755  y2 /= 2.;
756  }
757  else {
758  y2 /= 2.;
759  y2 = TMath::Min(y1, y2);
760  ix2 = 1;
761  y1 = -TMath::Min(y1, dt / 2.);
762  ix1 = -1;
763  }
764  }
765  else { // ksups == -1, i.e. no 'sups' line
766  fICode = kICODE7; //a gauche de la ligne fragment, Z est alors un Zmin et le plus probable
767  y2 = y1;
768  ix2 = 1;
769  y1 = -TMath::Min(y1, dt / 2.);
770  ix1 = -1;
771  }
772  }
773  /*** Z = Zinf ***/
774  else { // closest to lower 'inf' line
775  k = kinf;
776  yy = dinf;
777  Z = Zinf;
778  A = Ainf;
779  Aint = Ainf;
780  y2 = 0.5 * winf;
781  if (kinfi > -1) { // there is a 'infi' line below the 2 which encadrent the point
782  y1 = dinfi - dinf;
783  if (Zinfi == Zinf) {
784  ibif = 1;
785  ix1 = Ainfi - Ainf;
786  Double_t x2 = -y1 / ix1 / 2.;
787  y2 = TMath::Max(y2, x2);
788  y2 = TMath::Min(y2, dt / 2.);
789  ix2 = 1;
790  y1 /= -2.;
791  }
792  else {
793  y1 = -TMath::Min(y2, y1 / 2.);
794  ix1 = -1;
795  y2 = TMath::Min(y2, dt / 2.);
796  ix2 = 1;
797  }
798  }
799  else { // no kinfi line, kinfi==-1
800  y1 = -y2;
801  ix1 = -1;
802  y2 = TMath::Min(y2, dt / 2.);
803  ix1 = 1;
804  }
805  }
806  }
807  }//if(kinf>-1)...
808  else if (Zsup > 0) {
809  //cout<<" /****************** Seule une ligne superieure a ete trouvee *********************/" << endl;
810  ibif = 3;
811  k = ksup;
812  yy = -dsup;
813  Z = Zsup;
814  A = Asup;
815  Aint = Asup;
816  y1 = 0.5 * wsup;
817  if (ksups > -1) { // there is a 'sups' line above the closest line to the point
818  y2 = dsups - dsup;
819  if (Zsups == Zsup) {
820  ibif = 2;
821  ix2 = Asups - Asup;
822  Double_t x1 = y2 / ix2 / 2.;
823  y1 = -TMath::Max(y1, x1);
824  ix1 = -1;
825  y2 /= 2.;
826  }
827  else {
828  y2 /= 2.;
829  y2 = TMath::Min(y1, y2);
830  ix2 = 1;
831  y1 = -y1;
832  ix1 = -1;
833  }
834  }
835  else { // no 'sups' line above closest line
836  fICode = kICODE7; //Z est alors un Zmin et le plus probable
837  y2 = y1;
838  ix2 = 1;
839  y1 = -y1;
840  ix1 = -1;
841  }
842  if (yy >= y1)
843  fICode = kICODE0; // we are within the 'natural width' of the last line
844  else {
845  fICode = kICODE6; // we are too far from first line to extrapolate correctly
846  Z = Zsup - 1; // give Z below first line of grid, but this is an upper limit
847  }
848  }
849  else {
850  fICode = kICODE8; // Z indetermine ou (x,y) hors limites
851  }
852  }
853  else if (kinf > -1) {
854 
855  //cout <<"/****************** Seule une ligne inferieure a ete trouvee ***********************/" << endl;
856 
857  ibif = 3;
858  k = kinf;
859  Z = Zinf;
860  A = Ainf;
861  Aint = Ainf;
862  yy = dinf;
863  y2 = 0.5 * winf;
864  if (kinfi > -1) {
865  y1 = dinfi - dinf;
866  if (Zinfi == Zinf) {
867  ibif = 1;
868  ix1 = Ainfi - Ainf;
869  Double_t x2 = -y1 / ix1 / 2.;
870  y2 = TMath::Max(y2, x2);
871  ix2 = 1;
872  y1 /= -2.;
873  }
874  else {
875  y1 = -TMath::Min(y2, y1 / 2.);
876  ix1 = -1;
877  ix2 = 1;
878  }
879  }
880  else {
881  y1 = -y2;
882  ix1 = -1;
883  ix2 = 1;
884  }
885  if (yy <= y2)
886  fICode = kICODE0; // we are within the 'natural width' of the last line
887  else
888  fICode = kICODE7; // we are too far from last line to extrapolate correctly
889 
890  }
891  /*****************Aucune ligne n'a ete trouvee*********************************/
892  else {
893  fICode = kICODE8; // Z indetermine ou (x,y) hors limites
894  }
895  /****************Test des bornes********************************************/
896  if (k > -1 && fICode == kICODE0) {
897  if (yy > y2)
898  fICode = kICODE4; // Z ok, masse hors limite superieure ou egale a A
899  }
900  if (k > -1 && (fICode == kICODE0 || fICode == kICODE7)) {
901  if (yy < y1)
902  fICode = kICODE5; // Z ok, masse hors limite inferieure ou egale a A
903  }
904  if (fICode == kICODE4 || fICode == kICODE5) {
905  A = -1;
906  Aint = 0;
907  }
908  /****************Interpolation de la masse: da = f*log(1+b*dy)********************/
909  if (fICode == kICODE0) {
910  Double_t deltaA = 0.;
911  Bool_t i = kFALSE;
912  Double_t dt, dist = y1 * y2;
913  dt = 0.;
914  if (ix2 == -ix1) { //dA1 = dA2
915  if (dist != 0) {
916  dt = -(y1 + y2) / dist;
917  i = kTRUE;
918  }
919  /*else
920  Warning("IdentZA","%s : cannot calculate interpolated mass, Areal will equal Aint (Z=%d Aint=%d fICode=%d)",
921  GetName(), Z, Aint, fICode);*/
922  }
923  else if (ix2 == -ix1 * 2) { // dA2 = 2*dA1
924  Double_t tmp = y1 * y1 - 4. * dist;
925  if (tmp > 0 && dist != 0) {
926  dt = -(y1 + 2. * y2 -
927  TMath::Sqrt(tmp)) / dist / 2.;
928  i = kTRUE;
929  }
930  /*else
931  Warning("IdentZA","%s : cannot calculate interpolated mass, Areal will equal Aint (Z=%d Aint=%d fICode=%d)",
932  GetName(), Z, Aint, fICode);*/
933  }
934  else if (ix1 == -ix2 * 2) { // dA1 = 2*dA2
935  Double_t tmp = y2 * y2 - 4. * dist;
936  if (tmp > 0 && dist != 0) {
937  dt = -(y2 + 2. * y1 +
938  TMath::Sqrt(tmp)) / dist / 2.;
939  i = kTRUE;
940  }
941  /*else
942  Warning("IdentZA","%s : cannot calculate interpolated mass, Areal will equal Aint (Z=%d Aint=%d fICode=%d)",
943  GetName(), Z, Aint, fICode);*/
944  }
945  if (i) {
946  dist = dt * y2;
947  if (TMath::Abs(dist) < 0.001) {
948  if (y2 != 0)
949  deltaA = yy * ix2 / y2 / 2.;
950  /*else
951  Warning("IdentZA","%s : cannot calculate interpolated mass (y2=%f), Areal will equal Aint (Z=%d Aint=%d fICode=%d)",
952  GetName(), y2, Z, Aint, fICode);*/
953  }
954  else {
955  if (dist > -1. && dt * yy > -1.)
956  deltaA = ix2 / 2. / TMath::Log(1. + dist) * TMath::Log(1. + dt * yy);
957  /*else
958  Warning("IdentZA","%s : cannot calculate interpolated mass (dist=%f dt*yy=%f), Areal will equal Aint (Z=%d Aint=%d fICode=%d)",
959  GetName(), dist, dt*yy, Z, Aint, fICode);*/
960  }
961  A += deltaA;
962  }
963  }
964  /***************D'autres masses sont-elles possibles ?*************************/
965  if (fICode == kICODE0 && (ibif > 0 && ibif < 4)) {
966  if (ibif != 2) { /***Masse superieure***/
967  //We look at next line in the complete list of lines, after the closest line.
968  //If it has the same Z as the closest line, but was excluded from research for closest line
969  //because the point lies outside the endpoints, there remains a doubt about the mass:
970  //on rajoute 1 a fICode, effectivement on le met = kICODE1
971  Int_t idx = fIdxClosest; // index of closest line
972  if (idx > -1 && ++idx < GetNumberOfIdentifiers()) {
973  KVIDentifier* nextline = GetIdentifierAt(idx);
974  if (nextline->GetZ() == Z
975  && !((KVIDLine*)nextline)->IsBetweenEndPoints(x, y, "x")) {
976  fICode++; // Z ok, mais les masses superieures a A sont possibles
977  //cout <<"//on rajoute 1 a fICode, effectivement on le met = kICODE1" << endl;
978  }
979  }
980  }
981  if (ibif != 1) { /***Masse inferieure***/
982  //We look at line below the closest line in the complete list of lines.
983  //If it has the same Z as the closest line, but was excluded from research for closest line
984  //because the point lies outside the endpoints, there remains a doubt about the mass:
985  //on rajoute 2 a fICode, so it can be = kICODE2 or kICODE3
986  Int_t idx = fIdxClosest;
987  if (idx > -1 && --idx >= 0) {
988  KVIDentifier* nextline = GetIdentifierAt(idx);
989  if (nextline->GetZ() == Z
990  && !((KVIDLine*)nextline)->IsBetweenEndPoints(x, y, "x")) {
991  fICode += 2;
992  //cout << "//on rajoute 2 a fICode, so it can be = kICODE2 or kICODE3" << endl;
993  }
994  }
995  }
996  }
997 
998  if (fICode < kICODE4) ReCheckQuality(Z, A);
999 
1000 
1001  //cout << "Z = " << Z << " A = " << A << " icode = " << fICode << endl;
1002 }
1003 
1004 
1005 
1022 
1024 {
1025  //Recheck the identification quality using the 'manual' width set for each Z in the parameter list
1026  //
1027  //If abs(Aint-Areal)> ManualWidth + ManualWidthScaling*sqrt(Z), kIDCode5 is returned.
1028  //To be activated, a parameter "ManualWidth" should be added to the grid's parameter list.
1029  //
1030  //Acceptable values for FAZIA are :
1031  // * ManualWidth : 0.3
1032  // * ManualWidthScaling : 0.05
1033  //
1034  // Example of use :
1035  //~~~~{.cpp}
1036  //KVIDZAGrid grid;
1037  //grid.ReadAsciiFile("my_grid_file.dat");
1038  //grid.SetManualWidth(0.3,0.05);
1039  //~~~~
1040 
1041  double da = 1.;
1042  double das = 0.;
1043 
1044  if (!GetParameters()->HasParameter("ManualWidth")) return;
1045  da = GetParameters()->GetDoubleValue("ManualWidth");
1046 
1047  if (GetParameters()->HasParameter("ManualWidthScaling")) das = GetParameters()->GetDoubleValue("ManualWidthScaling");
1048  da += das * TMath::Sqrt(Z);
1049 
1050  int aa = TMath::Nint(A);
1051 
1052  KVNucleus nn(Z, aa);
1053  if (nn.GetLifeTime() < 1e-9) fICode = kICODE5;
1054 
1055 // if (Z == 1 && aa == 1) da *= .75;
1056  if (TMath::Abs(aa - A) > da) fICode = kICODE5;
1057 }
1058 
1059 
1060 
1062 
1063 void KVIDZAGrid::SetManualWidth(Double_t manual_width, Double_t manual_width_scaling)
1064 {
1065  GetParameters()->SetValue("ManualWidth", manual_width);
1066  GetParameters()->SetValue("ManualWidthScaling", manual_width_scaling);
1067 }
1068 
1069 
1070 
1071 
1076 
1078 {
1079  // Finds Z & 'real Z' for point (x,y) once closest lines to point have been found (see GetNearestIDLine).
1080  // This is is based on the algorithm developed by L. Tassan-Got in IdnCsOr, even the same
1081  // variable names and comments have been used (as much as possible).
1082 
1083  fICode = kICODE0;
1084  Z = -1;
1085  Aint = 0;
1086  Zint = 0;
1087  /* cout << "kinfi = " << kinfi << " Zinfi = " << Zinfi << " Ainfi = " << Ainfi << " winfi = " << winfi << " dinfi = " << dinfi << endl;
1088  cout << "kinf = " << kinf << " Zinf = " << Zinf << " Ainf = " << Ainf << " winf = " << winf << " dinf = " << dinf << endl;
1089  cout << "ksup = " << ksup << " Zsup = " << Zsup << " Asup = " << Asup << " wsup = " << wsup << " dsup = " << dsup << endl;
1090  cout << "ksups = " << ksups << " Zsups = " << Zsups << " Asups = " << Asups << " wsups = " << wsups << " dsups = " << dsups << endl;
1091  */
1092  Int_t ibif = 0;
1093  Int_t k = -1;
1094  Double_t yy, y1, y2;
1095  Int_t ix1, ix2;
1096  yy = y1 = y2 = 0;
1097  ix1 = ix2 = 0;
1098 
1099  if (ksup > -1) { // there is a line above the point
1100  if (kinf > -1) { // there is a line below the point
1101 
1102  //printf("------------>/* We found a line above and a line below the point */\n");
1103 
1104  Double_t dt = dinf + dsup; //distance between the 2 lines
1105  Int_t dZ = Zsup - Zinf;
1106  Double_t dist = dt / (1.0 * dZ); //distance between the 2 lines normalised to difference in Z of lines
1107 
1108  /*** Z = Zsup ***/
1109  if (dinf > dsup) { //point is closest to upper line, 'sup' line
1110  ibif = 1;
1111  k = ksup;
1112  yy = -dsup;
1113  Z = Zsup;
1114  Zint = Zsup;
1115  Aint = Asup;
1116  if (ksups > -1) { // there is a 'sups' line above the 2 which encadrent le point
1117  y2 = dsups - dsup;
1118 
1119  ibif = 0;
1120  y2 /= 2.;
1121  ix2 = Zsups - Zsup;
1122  }
1123  else { // ksups == -1 i.e. no 'sups' line
1124  y2 = wsup;
1125  y2 = 0.5 * TMath::Max(y2, dist);
1126  ix2 = 1;
1127  }
1128  y1 = -dt / 2.;
1129  ix1 = -dZ;
1130  }
1131  /*** Z = Zinf ***/
1132  else { //point is closest to lower line, 'inf' line
1133  ibif = 2;
1134  k = kinf;
1135  yy = dinf;
1136  Z = Zinf;
1137  Zint = Zinf;
1138  Aint = Ainf;
1139  if (kinfi > -1) { // there is a 'infi' line below the 2 which encadrent le point
1140  y1 = 0.5 * (dinfi - dinf);
1141 
1142  ibif = 0;
1143  ix1 = Zinfi - Zinf;
1144  y1 = -y1;
1145 
1146  }
1147  else { // kinfi = -1 i.e. no 'infi' line
1148  y1 = winf;
1149  y1 = -0.5 * TMath::Max(y1, dist);
1150  ix1 = -1;
1151  }
1152  y2 = dt / 2.;
1153  ix2 = dZ;
1154  }
1155 
1156  }//if(kinf>-1)...*******************************************************
1157  else {
1158  //printf("------------>/* Only a line above the point was found, no line below */\n");
1159  /* This means the point is below the first Z line of the grid (?) */
1160  ibif = 3;
1161  k = ksup;
1162  yy = -dsup;
1163  Z = Zsup;
1164  Zint = Zsup;
1165  Aint = Asup;
1166  y1 = 0.5 * wsup;
1167  if (ksups > -1) { // there is a 'sups' line above the closest line to the point
1168  y2 = dsups - dsup;
1169 
1170  ibif = 2;
1171  ix2 = Zsups - Zsup;
1172  Double_t x1 = y2 / ix2 / 2.;
1173  y1 = -TMath::Max(y1, x1);
1174  ix1 = -1;
1175  y2 /= 2.;
1176 
1177  }
1178  else { // no 'sups' line above closest line
1179  y2 = y1;
1180  ix2 = 1;
1181  y1 = -y1;
1182  ix1 = -1;
1183  }
1184  if (yy >= y1)
1185  fICode = kICODE0; // we are within the 'natural width' of the last line
1186  else {
1187  fICode = kICODE6; // we are too far from first line to extrapolate correctly
1188  Z = Zsup - 1; // give Z below first line of grid, but this is an upper limit
1189  Zint = Zsup - 1;
1190  Aint = 0;
1191  }
1192  }
1193  } //if(ksup>-1)***************************************************************
1194  else if (kinf > -1) {
1195 
1196  //printf("------------>/* Only a line below the point was found, no line above */\n");
1197  /* This means the point is above the last Z line of the grid (?) */
1198  ibif = 3;
1199  k = kinf;
1200  Z = Zinf;
1201  Zint = Zinf;
1202  Aint = Ainf;
1203  yy = dinf;
1204  y2 = 0.5 * winf;
1205  if (kinfi > -1) { // there is a 'infi' line below the closest line to the point
1206  y1 = dinfi - dinf;
1207  ibif = 1;
1208  ix1 = Zinfi - Zinf;
1209  Double_t x2 = -y1 / ix1 / 2.;
1210  y2 = TMath::Max(y2, x2);
1211  ix2 = 1;
1212  y1 /= -2.;
1213  }
1214  else {
1215  y1 = -y2;
1216  ix1 = -1;
1217  ix2 = 1;
1218  }
1219  if (yy <= y2)
1220  fICode = kICODE0; // we are within the 'natural width' of the last line
1221  else {
1222  fICode = kICODE7; // we are too far from last line to extrapolate correctly
1223  Z = Zinf + 1; // give Z above last line in grid, it is a lower limit
1224  Zint = Zinf + 1;
1225  Aint = 0;//calculate mass from Z
1226  }
1227 
1228  }
1229  /*no lines found at all*/
1230  else {
1231  fICode = kICODE8; // Z indetermine ou (x,y) hors limites
1232  }
1233 
1234 
1235  /****************Test des bornes********************************************/
1236  if (k > -1 && fICode == kICODE0) {
1237  if (yy > y2)
1238  fICode = kICODE4; // Z ok, masse hors limite superieure ou egale a A
1239  }
1240  if (k > -1 && fICode == kICODE0) {
1241  if (yy < y1)
1242  fICode = kICODE5; // Z ok, masse hors limite inferieure ou egale a A
1243  }
1244  if (fICode == kICODE4 || fICode == kICODE5) Aint = 0;
1245 
1246  /****************Interpolation to find 'real Z': dz = f*log(1+b*dy)********************/
1247 
1248  if (fICode < kICODE6) {
1249  Double_t deltaZ = 0.;
1250  Bool_t i = kFALSE;
1251  Double_t dt, dist = y1 * y2;
1252  dt = 0.;
1253  if (ix2 == -ix1) { //dZ1 = dZ2
1254  if (dist != 0) {
1255  dt = -(y1 + y2) / dist;
1256  i = kTRUE;
1257  }
1258  /*else
1259  Warning("IdentZ","%s : cannot calculate interpolated charge, Zreal will equal Zint (Zint=%d fICode=%d)",
1260  GetName(), Zint, fICode);*/
1261  }
1262  else if (ix2 == -ix1 * 2) { // dZ2 = 2*dZ1
1263  Double_t tmp = y1 * y1 - 4. * dist;
1264  if (tmp > 0. && dist != 0) {
1265  dt = -(y1 + 2. * y2 -
1266  TMath::Sqrt(tmp)) / dist / 2.;
1267  i = kTRUE;
1268  }
1269  /*else
1270  Warning("IdentZ","%s : cannot calculate interpolated charge, Zreal will equal Zint (Zint=%d fICode=%d)",
1271  GetName(), Zint, fICode);*/
1272  }
1273  else if (ix1 == -ix2 * 2) { // dZ1 = 2*dZ2
1274  Double_t tmp = y2 * y2 - 4. * dist;
1275  if (tmp > 0. && dist != 0) {
1276  dt = -(y2 + 2. * y1 +
1277  TMath::Sqrt(tmp)) / dist / 2.;
1278  i = kTRUE;
1279  }
1280  /*else
1281  Warning("IdentZ","%s : cannot calculate interpolated charge, Zreal will equal Zint (Zint=%d fICode=%d)",
1282  GetName(), Zint, fICode);*/
1283  }
1284  if (i) {
1285  dist = dt * y2;
1286  if (TMath::Abs(dist) < 0.001) {
1287  if (y2 != 0)
1288  deltaZ = yy * ix2 / y2 / 2.;
1289  /*else
1290  Warning("IdentZ","%s : cannot calculate interpolated charge (y2=%f), Zreal will equal Zint (Zint=%d fICode=%d)",
1291  GetName(), y2, Zint, fICode);*/
1292  }
1293  else {
1294  if (dist > -1. && dt * yy > -1.)
1295  deltaZ = ix2 / 2. / TMath::Log(1. + dist) * TMath::Log(1. + dt * yy);
1296  /*else
1297  Warning("IdentZ","%s : cannot calculate interpolated charge (dist=%f dt*yy=%f), Zreal will equal Zint (Zint=%d fICode=%d)",
1298  GetName(), dist, dt*yy, Zint, fICode);*/
1299  }
1300  Z += deltaZ;
1301  }
1302  }
1303  /***************Is there still a doubt about the Z ?*************************/
1304  if (fICode == kICODE0 && (ibif > 0 && ibif < 4)) {
1305  /***z superieure***/
1306  if (ibif != 2) {
1307  //We look at next line in the complete list of lines, after the closest line.
1308  //If it was excluded from research for closest line
1309  //because the point lies outside the endpoints, there remains a doubt about the Z:
1310  //on rajoute 1 a fICode, effectivement on le met = kICODE1
1311  Int_t idx = fIdxClosest;
1312  if (idx > -1 && ++idx < GetNumberOfIdentifiers()) {
1313  KVIDLine* nextline = (KVIDLine*)GetIdentifierAt(idx);
1314  if (!nextline->IsBetweenEndPoints(x, y, "x")) {
1315  fICode++; // Z might be bigger than we think
1316  //cout <<"//on rajoute 1 a fICode, effectivement on le met = kICODE1" << endl;
1317  }
1318  }
1319  }
1320  /***z inferieure***/
1321  if (ibif != 1) {
1322  //We look at line below the closest line in the complete list of lines.
1323  //If it was excluded from research for closest line
1324  //because the point lies outside the endpoints, there remains a doubt about the Z:
1325  //on rajoute 2 a fICode, so it can be = kICODE2 or kICODE3
1326  Int_t idx = fIdxClosest;
1327  if (idx > -1 && --idx >= 0) {
1328  KVIDLine* nextline = (KVIDLine*) GetIdentifierAt(idx);
1329  if (!nextline->IsBetweenEndPoints(x, y, "x")) {
1330  fICode += 2;
1331  //cout << "//on rajoute 2 a fICode, so it can be = kICODE2 or kICODE3" << endl;
1332  }
1333  }
1334  }
1335  }
1336 
1337 }
1338 
1339 
1340 
1341 
1367 
1369 {
1370  // Fill the KVIdentificationResult object with the results of identification for point (x,y)
1371  // corresponding to some physically measured quantities related to a reconstructed nucleus.
1372  //
1373  // By default (OnlyZId()=kFALSE) this means identifying the Z & A of the nucleus.
1374  // In this case, we consider that the nucleus' Z & A have been correctly measured
1375  // if the 'quality code' returned by IdentZA() is < kICODE4:
1376  // we set idr->Zident and idr->Aident to kTRUE if fICode<kICODE4
1377  //
1378  // If OnlyZId()=kTRUE, only the Z of the nucleus is established.
1379  // In this case, we consider that the nucleus' Z has been correctly measured
1380  // if the 'quality code' returned by IdentZ() is < kICODE4, thus:
1381  // we set idr->Zident to kTRUE if fICode<kICODE4
1382  // The mass idr->A is set to the mass of the nearest line.
1383  //
1384  // Real & integer masses for isotopically identified particles
1385  // ===================================================
1386  // For points lying between two lines of same Z and different A (fICode<kIDCode4)
1387  // the "real" mass is given by interpolation between the two masses.
1388  // The integer mass is the A of the line closest to the point.
1389  // This means that the integer A is not always = nint("real" A),
1390  // as for example if a grid is drawn with lines for 7Be & 9Be but not 8Be
1391  // (usual case), then particles between the two lines can have "real" masses
1392  // between 7.5 and 8.5, but their integer A will be =7 or =9, never 8.
1393  //
1394 
1395  SetInfos(x, y, idr);
1396 
1397  idr->IDOK = kFALSE;
1398  idr->Aident = idr->Zident = kFALSE;
1399 
1400  if (!const_cast<KVIDZAGrid*>(this)->FindFourEmbracingLines(x, y, "above")) {
1401  //no lines corresponding to point were found
1402  const_cast < KVIDZAGrid* >(this)->fICode = kICODE8; // Z indetermine ou (x,y) hors limites
1403  idr->IDquality = kICODE8;
1404  idr->SetComment("no identification: (x,y) out of range covered by grid");
1405  return;
1406  }
1407  if (IsOnlyZId() ||
1408  (fHasMassIDRegion && !idr->HasFlag(GetName(),"MassID")))
1409  {
1410  Double_t Z;
1411  const_cast < KVIDZAGrid* >(this)->IdentZ(x, y, Z);
1412  idr->IDquality = fICode;
1413  if (fICode < kICODE4 || fICode == kICODE7) {
1414  idr->Zident = kTRUE;
1415  }
1416  if (fICode < kICODE4) {
1417  idr->IDOK = kTRUE;
1418  }
1419  idr->Z = Zint;
1420  idr->PID = Z;
1421  idr->A = Aint;
1422 
1423  switch (fICode) {
1424  case kICODE0:
1425  idr->SetComment("ok");
1426  break;
1427  case kICODE1:
1428  idr->SetComment("slight ambiguity of Z, which could be larger");
1429  break;
1430  case kICODE2:
1431  idr->SetComment("slight ambiguity of Z, which could be smaller");
1432  break;
1433  case kICODE3:
1434  idr->SetComment("slight ambiguity of Z, which could be larger or smaller");
1435  break;
1436  case kICODE4:
1437  idr->SetComment("point is in between two lines of different Z, too far from either to be considered well-identified");
1438  break;
1439  case kICODE5:
1440  idr->SetComment("point is in between two lines of different Z, too far from either to be considered well-identified");
1441  break;
1442  case kICODE6:
1443  idr->SetComment("(x,y) is below first line in grid");
1444  break;
1445  case kICODE7:
1446  idr->SetComment("(x,y) is above last line in grid");
1447  break;
1448  default:
1449  idr->SetComment("no identification: (x,y) out of range covered by grid");
1450  }
1451  }
1452  else {
1453 
1454  Int_t Z;
1455  Double_t A;
1456  const_cast < KVIDZAGrid* >(this)->IdentZA(x, y, Z, A);
1457  idr->IDquality = fICode;
1458  idr->Z = Z;
1459  idr->PID = A;
1460 
1461  if (fICode < kICODE4 || fICode == kICODE7) {
1462  idr->Zident = kTRUE;
1463  }
1464  idr->A = Aint;
1465  if (fICode < kICODE4) {
1466  idr->Aident = kTRUE;
1467  idr->IDOK = kTRUE;
1468  }
1469  switch (fICode) {
1470  case kICODE0:
1471  idr->SetComment("ok");
1472  break;
1473  case kICODE1:
1474  idr->SetComment("slight ambiguity of A, which could be larger");
1475  break;
1476  case kICODE2:
1477  idr->SetComment("slight ambiguity of A, which could be smaller");
1478  break;
1479  case kICODE3:
1480  idr->SetComment("slight ambiguity of A, which could be larger or smaller");
1481  break;
1482  case kICODE4:
1483  idr->SetComment("point is in between two isotopes of different Z, too far from either to be considered well-identified");
1484  break;
1485  case kICODE5:
1486  idr->SetComment("point is in between two isotopes of different Z, too far from either to be considered well-identified");
1487  break;
1488  case kICODE6:
1489  idr->SetComment("(x,y) is below first line in grid");
1490  break;
1491  case kICODE7:
1492  idr->SetComment("(x,y) is above last line in grid");
1493  break;
1494  default:
1495  idr->SetComment("no identification: (x,y) out of range covered by grid");
1496  }
1497  }
1498 }
1499 
1500 
1501 
1502 
1509 
1511 {
1512  // General initialisation method for identification grid.
1513  // This method MUST be called once before using the grid for identifications.
1514  // The ID lines are sorted.
1515  // The natural line widths of all ID lines are calculated.
1516  // The line with the largest Z (Zmax line) is found.
1517 
1519  // Zmax should be Z of last line in sorted list
1521  if (fZMaxLine) fZMax = fZMaxLine->GetZ();
1522  else fZMax = 0; // protection au cas ou il n y a aucune ligne de Z
1523  // set to true if grid has a limited region for mass identification, indicated by an info "MassID"
1524  fHasMassIDRegion = (GetInfos()->FindObject("MassID") != nullptr);
1525 }
1526 
1527 
1528 
1529 
1530 
1533 
1534 void KVIDZAGrid::Streamer(TBuffer& R__b)
1535 {
1536  // Stream an object of class KVIDZAGrid.
1537 
1538  UInt_t R__s, R__c;
1539  if (R__b.IsReading()) {
1540  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1541  if (R__v < 2) {
1542  R__v = R__b.ReadVersion(&R__s, &R__c);// read version of KVIDZGrid
1543  if (R__v != 1) {
1544  Warning("Streamer", "Reading KVIDZGrid with version=%d", R__v);
1545  }
1546  KVIDGrid::Streamer(R__b);
1547  R__b >> fZMax;
1548  }
1549  else {
1550  R__b.ReadClassBuffer(KVIDZAGrid::Class(), this, R__v, R__s, R__c);
1551  }
1552  }
1553  else {
1554  R__b.WriteClassBuffer(KVIDZAGrid::Class(), this);
1555  }
1556 }
1557 
1558 
1559 
1560 // void KVIDZAGrid::MakeEDeltaEZGrid(Int_t Zmin, Int_t Zmax, Int_t npoints, Double_t gamma)
1561 // {
1562 // // Generate dE-Eres grid for associated ID telescope.
1563 // // 1 line per Z is generated, using mass formula set for grid.
1564 // // For each (Z,A) we calculate npoints corresponding to incident energies from the punch-through
1565 // // of the first member up to the punch-through of the second.
1566 // // gamma controls the spacing of the incident energies:
1567 // // gamma = 1 : equidistant steps in Einc
1568 // // gamma > 1 : steps at low Einc are more closely spaced, more & more for gamma >> 1
1569 //
1570 // KVIDTelescope* tel = ((KVIDTelescope*)fTelescopes.At(0));
1571 // if (!tel)
1572 // {
1573 // Error("MakeEDeltaEZGrid",
1574 // "No identification telescope associated to this grid");
1575 // return;
1576 // }
1577 // KVDetector *dEDet = tel->GetDetector(1);
1578 // KVDetector *ErDet = tel->GetDetector(2);
1579 // if (!ErDet)
1580 // {
1581 // Error("MakeEDeltaEZGrid",
1582 // "This identification telescope only has one member !");
1583 // return;
1584 // }
1585 // Double_t x_scale = GetXScaleFactor();
1586 // Double_t y_scale = GetYScaleFactor();
1587 // //clear old lines from grid (and scaling parameters)
1588 // Clear();
1589 //
1590 // //loop over Z
1591 // KVNucleus part;
1592 // //set mass formula used for calculating A from Z
1593 // part.SetMassFormula(GetMassFormula());
1594 //
1595 // Info("MakeEDeltaEZGrid",
1596 // "Calculating grid: dE detector = %s, E detector = %s",
1597 // dEDet->GetName(), ErDet->GetName());
1598 //
1599 // for (Int_t z=Zmin; z<=Zmax; z++)
1600 // {
1601 //
1602 // part.SetZ(z);
1603 //
1604 // //loop over energy
1605 // //first find :
1606 // // E1 = dE punch through + 0.1 MeV
1607 // // E2 = 95% of energy at which particle passes Eres
1608 // //then perform npoints calculations between these two energies and use these
1609 // //to construct a KVIDZLine
1610 //
1611 // Double_t E1, E2, E1bis;
1612 // E1bis = dEDet->GetEIncOfMaxDeltaE(z, part.GetA());
1613 // E1 = dEDet->GetPunchThroughEnergy(z, part.GetA()) + 0.1;
1614 // if(E1 < E1bis) E1 = E1bis;
1615 // E2 = 0.95*dEDet->GetIncidentEnergyFromERes(z, part.GetA(), ErDet->GetPunchThroughEnergy(z, part.GetA()));
1616 // Info("MakeEDeltaEZGrid","Z= %d, E1=%lf E2=%lf",z,E1,E2);
1617 //
1618 // // check we are within limits of validity of energy loss tables
1619 // if ( E2 > dEDet->GetEmaxValid(z, part.GetA()) )
1620 // {
1621 // Warning("MakeEDeltaEZGrid",
1622 // "Emax=%f MeV for Z=%d : beyond validity of range tables. Will use max limit=%f MeV",
1623 // E2, z, dEDet->GetEmaxValid(z,part.GetA()));
1624 // E2 = dEDet->GetEmaxValid(z,part.GetA());
1625 // }
1626 // if ( E2 > dEDet->GetEmaxValid(z, part.GetA()) )
1627 // {
1628 // Warning("MakeEDeltaEZGrid",
1629 // "Emax=%f MeV for Z=%d : beyond validity of range tables. Will use max limit=%f MeV",
1630 // E2, z, dEDet->GetEmaxValid(z,part.GetA()));
1631 // E2 = dEDet->GetEmaxValid(z,part.GetA());
1632 // }
1633 //
1634 // KVIDentifier *line = NewLine("ID");
1635 // Add("ID", line);
1636 // line->SetZ(z);
1637 // line->SetMassFormula(part.GetMassFormula());
1638 //
1639 // Double_t dE = (E2 - E1) / pow((npoints - 1.),gamma);
1640 //
1641 // Int_t npoints_added = 0;
1642 //
1643 // for (int i = 0; npoints_added < npoints; i++)
1644 // {
1645 //
1646 // Double_t E = E1 + dE*pow(i,gamma);
1647 //
1648 // Double_t Eres = 0.0;
1649 // dEDet->Clear();
1650 // ErDet->Clear();
1651 // part.SetEnergy(E);
1652 // dEDet->DetectParticle(&part);
1653 // ErDet->DetectParticle(&part);
1654 // Eres = ErDet->GetEnergy();
1655 //
1656 // line->SetPoint(npoints_added, Eres, dEDet->GetEnergy());
1657 // npoints_added++;
1658 // }
1659 // }
1660 // //if this grid has scaling factors, we need to apply them to the result
1661 // if (x_scale != 1)
1662 // SetXScaleFactor(x_scale);
1663 // if (y_scale != 1)
1664 // SetYScaleFactor(y_scale);
1665 // }
1666 
1667 
1675 
1677 {
1678  // Create a new graph/grid using the subset of lines of this grid contained in TList 'lines'.
1679  // By default the new graph/grid will be of the same class as this one, unless graph_class !=0,
1680  // in which case it must contain the address of a TClass object representing a class which
1681  // derives from KVIDGraph.
1682  // A clone of each line will be made and added to the new graph, which will have the same
1683  // name and be associated with the same ID telescopes as this one.
1684 
1685  if (!graph_class) graph_class = IsA();
1686  if (!graph_class->InheritsFrom("KVIDGraph")) {
1687  Error("MakeSubsetGraph", "Called with graph class %s, does not derive from KVIDGraph",
1688  graph_class->GetName());
1689  return 0;
1690  }
1691  KVIDGraph* new_graph = (KVIDGraph*)graph_class->New();
1692  new_graph->AddIDTelescopes(&fTelescopes);
1693  new_graph->SetOnlyZId(IsOnlyZId());
1694  new_graph->SetRuns(GetRuns());
1695  new_graph->SetVarX(GetVarX());
1696  new_graph->SetVarY(GetVarY());
1697  if (IsOnlyZId()) {
1698  new_graph->SetMassFormula(GetMassFormula());
1699  }
1700  // loop over lines in list, make clones and add to graph
1701  TIter next(lines);
1702  KVIDentifier* id;
1703  while ((id = (KVIDentifier*)next())) {
1704  KVIDentifier* idd = (KVIDentifier*)id->Clone();
1705  //id->Copy(*idd);
1706  //idd->ResetBit(kCanDelete);
1707  new_graph->AddIdentifier(idd);
1708  }
1709  return new_graph;
1710 }
1711 
1712 
1713 
1720 
1721 KVIDGraph* KVIDZAGrid::MakeSubsetGraph(Int_t Zmin, Int_t Zmax, const Char_t* graph_class)
1722 {
1723  // Create a new graph/grid using the subset of lines of this grid with Zmin <= Z <= Zmax.
1724  // By default the new graph/grid will be of the same class as this one, unless graph_class !="",
1725  // in which case it must contain the name of a class which derives from KVIDGraph.
1726  // A clone of each line will be made and added to the new graph, which will have the same
1727  // name and be associated with the same ID telescopes as this one.
1728 
1729  TList* lines = new TList; // subset of lines to clone
1730  TIter next(&fIdentifiers);
1731  KVIDentifier* l;
1732  while ((l = (KVIDentifier*)next())) {
1733  if (l->GetZ() >= Zmin && l->GetZ() <= Zmax) lines->Add(l);
1734  }
1735  TClass* cl = 0;
1736  if (strcmp(graph_class, "")) cl = TClass::GetClass(graph_class);
1737  KVIDGraph* gr = MakeSubsetGraph(lines, cl);
1738  lines->Clear();
1739  delete lines;
1740  return gr;
1741 }
1742 
1743 
1745 
1747 
1748 // This class is for backwards compatibility only
1750 // and must not be used.
1752 
1753 
1754 
1757 void KVIDZGrid::Streamer(TBuffer& R__b)
1758 {
1759  // Stream an object of class KVIDZGrid.
1760 
1761  UInt_t R__s, R__c;
1762  if (R__b.IsReading()) {
1763  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
1764  if (R__v != 1) {
1765  Warning("Streamer", "Reading KVIDZGrid with version=%d", R__v);
1766  }
1767  KVIDGrid::Streamer(R__b);
1768  R__b >> fZMax;
1769  }
1770 }
1771 
1772 
int Int_t
unsigned int UInt_t
#define e(i)
bool Bool_t
short Version_t
char Char_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char y1
#define gROOT
char * Form(const char *fmt,...)
#define gPad
Base class for particle identification in a 2D map.
Definition: KVIDGraph.h:32
Axis_t GetYmax() const
Definition: KVIDGraph.h:433
void Draw(Option_t *opt="") override
Definition: KVIDGraph.cpp:888
void RemoveIdentifier(KVIDentifier *)
Remove and destroy identifier.
Definition: KVIDGraph.cpp:335
KVList fIdentifiers
list of identification objects
Definition: KVIDGraph.h:40
void SetVarY(const char *v) override
Definition: KVIDGraph.h:566
Axis_t GetXmax() const
Definition: KVIDGraph.h:429
Int_t GetNumberOfIdentifiers() const
Definition: KVIDGraph.h:364
Bool_t IsOnlyZId() const
Definition: KVIDGraph.h:57
Int_t GetMassFormula() const
Definition: KVIDGraph.h:474
const KVList * GetCuts() const
Definition: KVIDGraph.h:344
const KVList * GetInfos() const
Definition: KVIDGraph.h:354
void SetVarX(const char *v) override
Definition: KVIDGraph.h:562
const Char_t * GetName() const override
Definition: KVIDGraph.cpp:1339
KVIDentifier * GetIdentifierAt(Int_t index) const
Definition: KVIDGraph.h:307
const KVNumberList & GetRuns() const
Definition: KVIDGraph.h:297
void FindAxisLimits()
Calculate X/Y min/max of all objects in graph.
Definition: KVIDGraph.cpp:1073
Axis_t GetYmin() const
Definition: KVIDGraph.h:425
const KVNameValueList * GetParameters() const
Definition: KVIDGraph.h:324
void SetMassFormula(Int_t)
Definition: KVIDGraph.cpp:1480
TList fTelescopes
ID telescopes for which grid is valid.
Definition: KVIDGraph.h:50
void AddIDTelescopes(const TList *)
Associate this graph with all ID telescopes in list.
Definition: KVIDGraph.cpp:1523
virtual void AddIdentifier(KVIDentifier *id)
Definition: KVIDGraph.h:376
virtual void SetInfos(Double_t, Double_t, KVIdentificationResult *) const
loop over KVIDGraph::fInfoZones to set flags in KVIdentificationResult
Definition: KVIDGraph.cpp:1304
Axis_t GetXmin() const
Definition: KVIDGraph.h:421
void SetRuns(const KVNumberList &nl)
Set list of runs for which grid is valid.
Definition: KVIDGraph.cpp:1323
void Copy(TObject &) const override
Copy this to 'obj'.
Definition: KVIDGraph.cpp:115
virtual void SetOnlyZId(Bool_t yes=kTRUE)
Definition: KVIDGraph.cpp:1503
const KVList * GetIdentifiers() const
Definition: KVIDGraph.h:334
void Initialize() override
Definition: KVIDGrid.cpp:218
KVIDLine * FindNearestEmbracingIDLine(Double_t x, Double_t y, const Char_t *position, const Char_t *axis, Int_t &idx, Int_t &idx_min, Int_t &idx_max, Double_t &dist, Double_t &dist_min, Double_t &dist_max) const
Definition: KVIDGrid.h:163
KVIDLine * FindNextEmbracingLine(Int_t &index, Int_t inc_index, Double_t x, Double_t y, const Char_t *axis) const
Definition: KVIDGrid.h:236
Base class for lines/cuts used for particle identification in 2D data maps.
Definition: KVIDLine.h:143
Double_t DistanceToLine(Double_t px, Double_t py, Int_t &)
Definition: KVIDLine.h:246
void GetStartPoint(Double_t &x, Double_t &y) const
Bool_t IsBetweenEndPoints(Double_t x, Double_t y, const Char_t *axis="") const
void GetEndPoint(Double_t &x, Double_t &y) const
Identification grid with lines corresponding to different nuclear isotopes (KVIDZALine)
Definition: KVIDZAGrid.h:66
void CalculateLineWidths() override
Definition: KVIDZAGrid.cpp:288
Double_t dsups
Definition: KVIDZAGrid.h:88
Double_t fDistanceClosest
distance from point to closest line
Definition: KVIDZAGrid.h:83
Int_t Zsups
Definition: KVIDZAGrid.h:90
KVIDLine * fLsup
Definition: KVIDZAGrid.h:80
Double_t wsup
Definition: KVIDZAGrid.h:89
Int_t Zinf
Definition: KVIDZAGrid.h:90
void init()
initialisation
Definition: KVIDZAGrid.cpp:81
Int_t Ainfi
Definition: KVIDZAGrid.h:91
KVIDLine * fClosest
closest line to last-identified point
Definition: KVIDZAGrid.h:78
Int_t Ainf
Definition: KVIDZAGrid.h:91
void ReCheckQuality(Int_t &Z, Double_t &A)
virtual KVIDZALine * GetZLine(Int_t z, Int_t &) const
Definition: KVIDZAGrid.cpp:152
KVIDLine * fLinf
Definition: KVIDZAGrid.h:81
Int_t Zsup
Definition: KVIDZAGrid.h:90
Int_t Asups
Definition: KVIDZAGrid.h:91
void DrawLinesWithWidth()
Definition: KVIDZAGrid.cpp:460
void RemoveZLines(const Char_t *ZList)
Remove and destroy identifiers.
Definition: KVIDZAGrid.cpp:132
Int_t kinfi
Definition: KVIDZAGrid.h:87
virtual void IdentZ(Double_t x, Double_t y, Double_t &Z)
Int_t Asup
Definition: KVIDZAGrid.h:91
void Copy(TObject &) const override
Copy this to 'obj'.
Definition: KVIDZAGrid.cpp:66
Int_t ksup
Definition: KVIDZAGrid.h:87
KVIDZALine * fZMaxLine
line with biggest Z and A
Definition: KVIDZAGrid.h:71
Int_t ksups
used by IdentZA and IdentZ
Definition: KVIDZAGrid.h:87
Double_t winf
Definition: KVIDZAGrid.h:89
Double_t dinf
Definition: KVIDZAGrid.h:88
Int_t kinf
Definition: KVIDZAGrid.h:87
KVIDLine * fLsups
Definition: KVIDZAGrid.h:79
Double_t wsups
Definition: KVIDZAGrid.h:89
UShort_t fZMax
largest Z of lines in grid
Definition: KVIDZAGrid.h:70
Double_t dsup
Definition: KVIDZAGrid.h:88
KVIDZAGrid()
default ctor.
Definition: KVIDZAGrid.cpp:33
virtual void IdentZA(Double_t x, Double_t y, Int_t &Z, Double_t &A)
Definition: KVIDZAGrid.cpp:644
Int_t fIdxClosest
index of closest line in main list fIdentifiers
Definition: KVIDZAGrid.h:84
Int_t Zinfi
Definition: KVIDZAGrid.h:90
Bool_t fHasMassIDRegion
set to true if grid has a limited region for mass identification, indicated by an info contour "MassI...
Definition: KVIDZAGrid.h:95
Int_t fICode
code de retour
Definition: KVIDZAGrid.h:85
Double_t winfi
Definition: KVIDZAGrid.h:89
KVIDLine * fLinfi
Definition: KVIDZAGrid.h:82
Int_t Zint
Z of line used to identify particle.
Definition: KVIDZAGrid.h:94
void SetManualWidth(Double_t manual_width=.3, Double_t manual_width_scaling=0.05)
KVIDGraph * MakeSubsetGraph(Int_t Zmin, Int_t Zmax, const Char_t *="")
virtual void MakeEDeltaEZGrid(Int_t Zmin, Int_t Zmax, Int_t npoints=20, Double_t gamma = 2);//*MENU*
Double_t dinfi
Definition: KVIDZAGrid.h:88
void Initialize() override
virtual Bool_t FindFourEmbracingLines(Double_t x, Double_t y, const Char_t *position)
Definition: KVIDZAGrid.cpp:519
Int_t Aint
mass of line used to identify particle
Definition: KVIDZAGrid.h:93
void RemoveLine(Int_t Z, Int_t A=-1)
Remove and destroy identifier.
Definition: KVIDZAGrid.cpp:102
virtual KVIDZALine * GetZALine(Int_t z, Int_t a, Int_t &) const
Definition: KVIDZAGrid.cpp:213
void Identify(Double_t x, Double_t y, KVIdentificationResult *) const override
Base class for identification ridge lines corresponding to different nuclear species.
Definition: KVIDZALine.h:33
virtual void SetAsymWidth(Double_t d_l, Double_t d_r)
Definition: KVIDZALine.cpp:214
void SetWidth(Double_t w)
Definition: KVIDZALine.h:65
Base class for graphical cuts used in particle identification.
Definition: KVIDentifier.h:28
virtual Int_t GetA() const
Definition: KVIDentifier.h:76
virtual Int_t GetZ() const
Definition: KVIDentifier.h:80
Full result of one attempted particle identification.
Bool_t IDOK
general quality of identification, =kTRUE if acceptable identification made
void SetComment(const Char_t *c)
Bool_t Aident
= kTRUE if A of particle established
Double_t PID
= "real" Z if Zident==kTRUE and Aident==kFALSE, "real" A if Zident==Aident==kTRUE
Int_t A
A of particle found (if Aident==kTRUE)
Int_t Z
Z of particle found (if Zident==kTRUE)
Int_t IDquality
specific quality code returned by identification procedure
Bool_t HasFlag(std::string grid_name, TString flag)
Bool_t Zident
=kTRUE if Z of particle established
Extended TList class which owns its objects by default.
Definition: KVList.h:22
Double_t GetDoubleValue(const Char_t *name) const
void SetValue(const Char_t *name, value_type value)
Description of properties and kinematics of atomic nuclei.
Definition: KVNucleus.h:123
Double_t GetLifeTime(Int_t z=-1, Int_t a=-1) const
Definition: KVNucleus.cpp:1037
Strings used to represent a set of ranges of values.
Definition: KVNumberList.h:85
Bool_t End(void) const
Definition: KVNumberList.h:199
void Begin(void) const
Int_t Next(void) const
KVSeqCollection * GetSubListWithMethod(const Char_t *retvalue, const Char_t *method) const
TObject * FindObject(const char *name) const override
TObject * Last() const override
virtual Version_t ReadVersion(UInt_t *start=nullptr, UInt_t *bcnt=nullptr, const TClass *cl=nullptr)=0
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=nullptr)=0
Bool_t IsReading() const
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
static TClass * GetClass(Bool_t load=kTRUE, Bool_t silent=kFALSE)
Bool_t InheritsFrom(const char *cl) const override
void Streamer(TBuffer &) override
const char * GetVarX() const
static TClass * Class()
TClass * IsA() const override
const char * GetVarY() const
void Clear(Option_t *option="") override
void Add(TObject *obj) override
const char * GetName() const override
virtual void Warning(const char *method, const char *msgfmt,...) const
virtual Bool_t InheritsFrom(const char *classname) const
virtual void Error(const char *method, const char *msgfmt,...) const
virtual void Draw(Option_t *option="")
TLine * line
Double_t y[n]
Double_t x[n]
TGraphErrors * gr
double dist(AxisAngle const &r1, AxisAngle const &r2)
void init()
Double_t Min(Double_t a, Double_t b)
Int_t Nint(T x)
Double_t Log(Double_t x)
Double_t Sqrt(Double_t x)
Double_t Abs(Double_t d)
Double_t Max(Double_t a, Double_t b)
TLine l
TArc a
ClassImp(TPyArg)