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