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