KaliVeda  1.12/06
Heavy-Ion Analysis Toolkit
KVIDZAFromZGrid.cpp
Go to the documentation of this file.
1 //Created by KVClassFactory on Tue Mar 8 10:00:16 2016
2 //Author: Diego Gruyer
3 
4 #include "KVIDZAFromZGrid.h"
5 #include "TMultiGraph.h"
6 #include "KVIDZALine.h"
7 #include "TCanvas.h"
8 
12 
13 
14 
15 
20 {
21  // Default constructor
22  // Grid is declared as a 'ZOnlyGrid' by default (this is internal mechanics)
23 
24  init();
25  fTables.SetOwner(kTRUE);
26  SetOnlyZId();
27  fIgnoreMassID = false;
28 }
29 
30 
31 
34 
36 {
37  // Destructor
38 }
39 
40 
41 
42 
50 
52 {
53  // This method copies the current state of 'this' object into 'obj'
54  // You should add here any member variables, for example:
55  // (supposing a member variable KVIDZAFromZGrid::fToto)
56  // CastedObj.fToto = fToto;
57  // or
58  // CastedObj.SetToto( GetToto() );
59 
60  KVIDZAGrid::Copy(obj);
61  //KVIDZAFromZGrid& CastedObj = (KVIDZAFromZGrid&)obj;
62 }
63 
64 
65 
66 
75 
76 void KVIDZAFromZGrid::ReadFromAsciiFile(std::ifstream& gridfile)
77 {
78 // fPIDRange = kFALSE;
79 // KVIDGraph::ReadFromAsciiFile(gridfile);
80 // if (GetParameters()->HasParameter("PIDRANGE")) {
81 // fPIDRange = kTRUE;
82 // fZmaxInt = GetParameters()->GetIntValue("PIDRANGE");
83 // LoadPIDRanges();
84 // }
85 
86  fPIDRange = kFALSE;
87 // fHasMassCut = kFALSE;
89 
90 // if (GetIdentifier("MassID")) fHasMassCut = kTRUE;
91 
92  if (GetParameters()->HasParameter("PIDRANGE")) {
93  fPIDRange = kTRUE;
94  TString pidrange = GetParameters()->GetStringValue("PIDRANGE");
95  if (pidrange.Contains("-")) {
96  TString min = (pidrange(0, pidrange.Index("-")));
97  fZminInt = min.Atoi();
98  min = (pidrange(pidrange.Index("-") + 1, pidrange.Length()));
99  fZmaxInt = min.Atoi();
100  }
101  else {
102  fZminInt = 1;
103  fZmaxInt = pidrange.Atoi();
104  }
105  LoadPIDRanges();
106  }
107  // if <PARAMETER> IgnoreMassID=1 appears in file, we are only using the PID intervals to clean
108  // up a messy de-e plot, not to give mass identification. particles will only be identified in Z.
109  if (GetParameters()->HasParameter("IgnoreMassID") && GetParameters()->GetIntValue("IgnoreMassID") == 1)
110  fIgnoreMassID = true;
111  else
112  fIgnoreMassID = false;
113 }
114 
115 
116 
118 
119 void KVIDZAFromZGrid::WriteToAsciiFile(std::ofstream& gridfile)
120 {
121  ExportToGrid();
122  KVIDGraph::WriteToAsciiFile(gridfile);
123 }
124 
125 
126 
128 
130 {
131  fZminInt = 100000;
132  fZmaxInt = 0;
133 
134  KVIDentifier* id = 0;
135  TIter it(GetIdentifiers());
136  while ((id = (KVIDentifier*)it())) {
137  int zz = id->GetZ();
138  if (!GetParameters()->HasParameter(Form("PIDRANGE%d", zz))) continue;
139  KVString mes = GetParameters()->GetStringValue(Form("PIDRANGE%d", zz));
140  if (mes.IsWhitespace()) continue;
141  int type = (mes.Contains(",") ? 2 : 1);
142  interval_set* itv = new interval_set(zz, type);
143  itv->SetName(GetName());
144  mes.Begin("|");
145  while (!mes.End()) {
146  KVString tmp = mes.Next();
147  tmp.Begin(":");
148  int aa = tmp.Next().Atoi();
149  KVString val = tmp.Next();
150  double pidmin, pidmax, pid;
151  if (type == 1) itv->add(aa, val.Atof());
152  else if (type == 2) {
153  val.Begin(",");
154  pidmin = val.Next().Atof();
155  pid = val.Next().Atof();
156  pidmax = val.Next().Atof();
157  itv->add(aa, pid, pidmin, pidmax);
158 // itv->add(aa, pid, pid-0.02, pid+0.02);
159  }
160  }
161  if (zz < fZminInt) fZminInt = zz;
162  if (zz > fZmaxInt) fZmaxInt = zz;
163  fTables.Add(itv);
164  }
165  fPIDRange = kTRUE;
166  // PrintPIDLimits();
167 }
168 
169 
170 
172 
174 {
175  fTables.Clear("all");
176  fPIDRange = kFALSE;
177 }
178 
179 
180 
182 
184 {
185  fTables.Clear("all");
186  LoadPIDRanges();
187 }
188 
189 
190 
192 
194 {
195  interval_set* itv = 0;
196  TIter it(&fTables);
197  while ((itv = (interval_set*)it())) if (itv->GetZ() == zint) return itv;
198  return 0;
199 }
200 
201 
202 
209 
211 {
212 // ((interval_set*)fTables.At(12))->fIntervals.ls();
213 
214 // for (int zz = fZminInt; zz <= fZmaxInt; zz++) {
215 // Info("PrintPIDLimits", "Z=%2d [%.4lf %.4lf]", zz, ((interval_set*)fTables.At(zz - fZminInt))->fPIDmins.at(0),
216 // ((interval_set*)fTables.At(zz - fZminInt))->fPIDmaxs.at(((interval_set*)fTables.At(zz - fZminInt))->fNPIDs - 1));
217 // }
218 }
219 
220 
221 
223 
225 {
226  if (fPar->HasParameter("PIDRANGE")) fPar->RemoveParameter("PIDRANGE");
227  for (int ii = 1; ii < 30; ii++) {
228  if (fPar->HasParameter(Form("PIDRANGE%d", ii))) fPar->RemoveParameter(Form("PIDRANGE%d", ii));
229  }
230 }
231 
232 
233 
240 
241 int KVIDZAFromZGrid::is_inside(double pid) const
242 {
243  // Look for a set of mass-interval definitions in which the given PID
244  // falls (PID from linearisation of Z identification).
245  // In principle this should be the set corresponding to Z=nint(PID),
246  // but if not Z+/-1 are also tried.
247  // Returns the value of Z for the set found (or 0 if no set found)
248 
249  int zint = TMath::Nint(pid);
250  interval_set* it = GetIntervalSet(zint);
251  if (it) {
252  if (it->is_inside(pid)) return zint;
253  else if (it->is_above(pid)) {
254 
255  it = GetIntervalSet(zint + 1);
256  if (it && it->is_inside(pid)) return zint + 1;
257  else return 0;
258  }
259  else {
260  it = GetIntervalSet(zint - 1);
261  if (it && it->is_inside(pid)) return zint - 1;
262  else return 0;
263  }
264  }
265  else return 0;
266 }
267 
268 
269 
276 
278 {
279  // General initialisation method for identification grid.
280  // This method MUST be called once before using the grid for identifications.
281  // The ID lines are sorted.
282  // The natural line widths of all ID lines are calculated.
283  // The line with the largest Z (Zmax line) is found.
284 
285  SetOnlyZId();
287  // Zmax should be Z of last line in sorted list
288 
289  TIter it(GetIdentifiers());
290  KVIDentifier* id = 0;
291 
292  fZMax = 0;
293  while ((id = (KVIDentifier*)it())) {
294  if (!id->InheritsFrom("KVIDZALine")) continue;
295  int zz = ((KVIDZALine*)id)->GetZ();
296  if (zz > fZMax) fZMax = zz;
297  }
298 
299  // set to true if grid has a limited region for mass identification, indicated by an info "MassID"
300  fHasMassIDRegion = (GetInfos()->FindObject("MassID") != nullptr);
301 }
302 
303 
304 
316 
318 {
319  // Fill the KVIdentificationResult object with the results of identification for point (x,y)
320  // corresponding to some physically measured quantities related to a reconstructed nucleus.
321  //
322  // If identification is successful, idr->IDOK = true.
323  // In this case, idr->Aident and idr->Zident indicate whether isotopic or only Z identification
324  // was acheived.
325  //
326  // In case of unsuccessful identification, idr->IDOK = false,
327  // BUT idr->Zident and/or idr->Aident may be true: this is to indicate which kind of
328  // identification was attempted but failed (this changes the meaning of the quality code)
329 
330  idr->Aident = idr->Zident = kFALSE;
331 
332  KVIDZAGrid::Identify(x, y, idr);
333  idr->Zident = kTRUE; // meaning Z identification was attempted, even if it failed
334  if (!idr->IDOK) return;
335 
336  bool have_pid_range_for_Z = fPIDRange && (idr->Z <= fZmaxInt) && (idr->Z > fZminInt - 1);
337  bool mass_id_success = false;
338 
339  if (have_pid_range_for_Z
340  && (!fHasMassIDRegion || idr->IdentifyingGridHasFlag("MassID"))) { // if a mass ID region is defined, we must be inside it
341  // try mass identification
342  mass_id_success = (DeduceAfromPID(idr) > 0);
343  if (mass_id_success) {
344  // mass identification was at least attempted
345  // make sure grid's quality code is consistent with KVIdentificationResult
346  const_cast<KVIDZAFromZGrid*>(this)->fICode = idr->IDquality;
347  idr->Aident = kTRUE; // meaning A identification was attempted, even if it failed
348  }
349  else {
350  // the pid falls outside of any mass ranges for a Z which has assigned isotopes
351  // therefore although the Z identification was good, we cannot consider this
352  // particle to be identified
353  const_cast<KVIDZAFromZGrid*>(this)->fICode = kICODE4;
354  idr->IDquality = fICode; // otherwise identfication result quality code is not coherent with comment (see below)
355  }
356  idr->IDOK = (fICode < kICODE4);
357  }
358 
359  // ignore isotopic successful isotopic identification if fIgnoreMassID=true
360  if (fIgnoreMassID && idr->IDOK && idr->Aident) idr->Aident = false;
361 
362  // set comments in identification result
363  switch (fICode) {
364  case kICODE0:
365  idr->SetComment("ok");
366  break;
367  case kICODE1:
368  if (mass_id_success) idr->SetComment("slight ambiguity of A, which could be larger");
369  else idr->SetComment("slight ambiguity of Z, which could be larger");
370  break;
371  case kICODE2:
372  if (mass_id_success) idr->SetComment("slight ambiguity of A, which could be smaller");
373  else idr->SetComment("slight ambiguity of Z, which could be smaller");
374  break;
375  case kICODE3:
376  if (mass_id_success) idr->SetComment("slight ambiguity of A, which could be larger or smaller");
377  else idr->SetComment("slight ambiguity of Z, which could be larger or smaller");
378  break;
379  case kICODE4:
380  if (mass_id_success) idr->SetComment("point is outside of mass identification range");
381  else idr->SetComment("point is in between two lines of different Z, too far from either to be considered well-identified");
382  break;
383  case kICODE5:
384  if (mass_id_success) idr->SetComment("point is in between two isotopes A & A+2 (e.g. 5He, 8Be, 9B)");
385  else idr->SetComment("point is in between two lines of different Z, too far from either to be considered well-identified");
386  break;
387  case kICODE6:
388  idr->SetComment("(x,y) is below first line in grid");
389  break;
390  case kICODE7:
391  idr->SetComment("(x,y) is above last line in grid");
392  break;
393  default:
394  idr->SetComment("no identification: (x,y) out of range covered by grid");
395  }
396 }
397 
398 
399 
400 
406 
408 {
409  // First look for a set of mass intervals in which the PID of the identification result falls,
410  // if there is one (see KVIDZAFromZGrid::is_inside).
411  // If an interval set is found for a Z different to the original identification, idr->Z is changed.
412  // Then call interval_set::eval for the mass interval for this Z.
413 
414  int zint = is_inside(idr->PID);
415  if (!zint) return -1;
416  if (zint != idr->Z) idr->Z = zint;
417 
418  double res = 0.;
419  interval_set* it = GetIntervalSet(zint);
420  if (it) res = it->eval(idr);
421  return res;
422 }
423 
424 
425 
426 
428 
430 {
432  KVNumberList pids;
433  interval_set* itvs = 0;
434  TIter npid(GetIntervalSets());
435  while ((itvs = (interval_set*)npid())) {
436  if (!itvs->GetNPID()) continue;
437  pids.Add(itvs->GetZ());
438  }
439  GetParameters()->SetValue("PIDRANGE", pids.AsString());
440 
441  itvs = 0;
442  TIter next(GetIntervalSets());
443  while ((itvs = (interval_set*)next())) {
444  if (!itvs->GetNPID()) continue;
445  KVString par = Form("PIDRANGE%d", itvs->GetZ());
446  KVString val = "";
447  interval* itv = 0;
448  TIter ni(itvs->GetIntervals());
449  while ((itv = (interval*)ni())) {
450  val += Form("%d:%lf,%lf,%lf|", itv->GetA(), itv->GetPIDmin(), itv->GetPID(), itv->GetPIDmax());
451  }
452  val.Remove(val.Length() - 1);
453  GetParameters()->SetValue(par.Data(), val.Data());
454  }
455 }
456 
457 
458 
459 
460 
462 
464 {
465  double pid = idr->PID;
466  if (pid < 0.5) return 0.;
467  // calculate interpolated mass from PID
468  double res = fPIDs.Eval(pid);
469  int ares = 0;
470 
472 
473  // look for mass interval PID is in
474  // in case it falls between two intervals remember also the interval
475  // immediately to the left & right of the PID
476  interval* left_int(nullptr), *right_int(nullptr);
477  interval* inter;
478  TIter it(&fIntervals);
479  while ((inter = (interval*)it())) {
480  if (inter->is_inside(pid)) {
481  ares = inter->GetA();
482  break;
483  }
484  else if (inter->is_left_of(pid)) {
485  left_int = inter;
486  }
487  else if (!right_int && inter->is_right_of(pid)) {
488  right_int = inter;
489  }
490  }
491  if (ares != 0) {
492  // the PID is inside a defined mass interval
493  idr->A = ares;
494  idr->PID = res;
496  }
497  else {
498  // the PID is not inside a defined mass interval
499  //
500  // * if it is in between two consecutive masses i.e. A and A+1 then it is
501  // Z- and A-identified with a slight ambiguity of A
502  // * if it is in between two non-consecutive masses i.e. A and A+2 then it
503  // is not identified (e.g. 5He, 8Be, 9B)
504  if (!right_int || !left_int) {
505  // case where no left or right interval were found
506  // to prevent from crashes but should not appen
507  idr->A = ares;
508  idr->PID = res;
510  }
511  else {
512  int dA = right_int->GetA() - left_int->GetA();
513  if (dA == 1) {
514  // OK, slight ambiguity of A
515  ares = TMath::Nint(res);
516  idr->A = ares;
517  idr->PID = res;
519  }
520  else {
521  // in a hole where no isotopes should be (e.g. 5He, 8Be, 9B)
522  idr->A = ares;
523  idr->PID = res;
525  }
526  }
527  }
528  }
529  else {
530  ares = TMath::Nint(res);
531  idr->A = ares;
532  idr->PID = res;
533  if (ares > fPIDs.GetX()[0] && ares < fPIDs.GetX()[fNPIDs - 1]) {
535  }
536  else {
538  }
539  }
540  return res;
541 }
542 
543 
544 
546 
547 bool interval_set::is_inside(double pid)
548 {
549  if (fType != KVIDZAFromZGrid::kIntType) return kTRUE;
550 
551 // Info("is_inside","min: %d max:%d npids:%d", ((interval*)fIntervals.At(0))->GetA(), ((interval*)fIntervals.At(fNPIDs-1))->GetA(), fNPIDs);
552 
553  if (pid > ((interval*)fIntervals.At(0))->GetPIDmin() && pid < ((interval*)fIntervals.At(fNPIDs - 1))->GetPIDmax()) return kTRUE;
554  else return kFALSE;
555 }
556 
557 
558 
560 
561 bool interval_set::is_above(double pid)
562 {
563  if (fType != KVIDZAFromZGrid::kIntType) return kTRUE;
564 
565  if (pid > ((interval*)fIntervals.At(fNPIDs - 1))->GetPIDmax()) return kTRUE;
566  else return kFALSE;
567 }
568 
569 
570 
571 
573 
575 {
576  if (!GetNPID()) return "-";
577  KVNumberList alist;
578  for (int ii = 0; ii < GetNPID(); ii++) alist.Add(((interval*)fIntervals.At(ii))->GetA());
579  return alist.AsString();
580 }
581 
582 
583 
585 
586 interval_set::interval_set(int zz, int type)
587 {
588  fType = type;
589  fZ = zz;
590  fNPIDs = 0;
592 }
593 
594 
595 
601 
602 void interval_set::add(int aa, double pid, double pidmin, double pidmax)
603 {
604 // if (fNPIDs && pid < fPIDs.GetX()[fNPIDs - 1]) {
605 // Error("add", "Please give me peaks in the right order for Z=%d and A=%d...", fZ, aa);
606 // return;
607 // }
608  if (fType == KVIDZAFromZGrid::kIntType && !(pid > pidmin && pid < pidmax)) {
609  Error("add", "Wrong interval for Z=%d and A=%d: [%.4lf %.4lf %.4lf] (%s)", fZ, aa, pidmin, pid, pidmax, GetName());
610  return;
611  }
612 
613  fPIDs.SetPoint(fNPIDs, pid, aa);
615  if (pid) fIntervals.AddLast(new interval(fZ, aa, pid, pidmin, pidmax));
616  }
617  fNPIDs++;
618 }
619 
620 
621 
622 
623 
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
const Bool_t kFALSE
double Double_t
const Bool_t kTRUE
int type
char * Form(const char *fmt,...)
virtual void WriteToAsciiFile(std::ofstream &gridfile)
Definition: KVIDGraph.cpp:459
KVNameValueList * fPar
parameters associated to grid
Definition: KVIDGraph.h:44
virtual void ReadFromAsciiFile(std::ifstream &gridfile)
Definition: KVIDGraph.cpp:616
KVList * GetInfos() const
Definition: KVIDGraph.h:295
const Char_t * GetName() const
Definition: KVIDGraph.cpp:1320
KVNameValueList * GetParameters() const
Definition: KVIDGraph.h:280
KVList * GetIdentifiers() const
Definition: KVIDGraph.h:285
void Initialize()
Definition: KVIDGrid.cpp:218
Hybrid identification grid.
Bool_t fHasMassIDRegion
set to true if grid has a limited region for mass identification, indicated by an info "MassID"
interval_set * GetIntervalSet(int zint) const
virtual void WriteToAsciiFile(std::ofstream &gridfile)
void SetOnlyZId(Bool_t=kTRUE)
void Copy(TObject &obj) const
virtual double DeduceAfromPID(KVIdentificationResult *idr) const
virtual void ReadFromAsciiFile(std::ifstream &gridfile)
KVList * GetIntervalSets()
virtual ~KVIDZAFromZGrid()
Destructor.
int is_inside(double pid) const
virtual void Identify(Double_t x, Double_t y, KVIdentificationResult *) const
virtual void Copy(TObject &) const
Copy this to 'obj'.
Definition: KVIDZAGrid.cpp:71
virtual void Identify(Double_t x, Double_t y, KVIdentificationResult *) const
UShort_t fZMax
largest Z of lines in grid
Definition: KVIDZAGrid.h:69
Int_t fICode
code de retour
Definition: KVIDZAGrid.h:84
Base class for identification ridge lines corresponding to different nuclear species.
Definition: KVIDZALine.h:32
Base class for graphical cuts used in particle identification.
Definition: KVIDentifier.h:27
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
Bool_t IdentifyingGridHasFlag(TString flag)
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
void SetValue(const Char_t *name, value_type value)
void RemoveParameter(const Char_t *name)
const Char_t * GetStringValue(const Char_t *name) const
Bool_t HasParameter(const Char_t *name) const
Strings used to represent a set of ranges of values.
Definition: KVNumberList.h:83
const Char_t * AsString(Int_t maxchars=0) const
void Add(Int_t)
Add value 'n' to the list.
virtual void AddLast(TObject *obj)
virtual void SetOwner(Bool_t enable=kTRUE)
virtual void Clear(Option_t *option="")
virtual TObject * At(Int_t idx) const
virtual void Add(TObject *obj)
virtual TObject * FindObject(const char *name) const
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition: KVString.h:72
void Begin(TString delim) const
Definition: KVString.cpp:562
Bool_t End() const
Definition: KVString.cpp:625
KVString Next(Bool_t strip_whitespace=kFALSE) const
Definition: KVString.cpp:675
virtual void SetPoint(Int_t i, Double_t x, Double_t y)
Double_t * GetX() const
virtual Double_t Eval(Double_t x, TSpline *spline=nullptr, Option_t *option="") const
virtual const char * GetName() const
virtual void SetName(const char *name)
virtual Bool_t InheritsFrom(const char *classname) const
virtual void Error(const char *method, const char *msgfmt,...) const
Ssiz_t Length() const
Int_t Atoi() const
Double_t Atof() const
const char * Data() const
Bool_t IsWhitespace() const
TString & Remove(EStripType s, char c)
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
TString GetListOfMasses()
bool is_inside(double pid)
bool is_above(double pid)
void add(int aa, double pid, double pidmin=-1., double pidmax=-1.)
double eval(KVIdentificationResult *idr)
interval_set(int zz, int type)
KVList * GetIntervals()
bool is_right_of(double pid)
double GetPID()
bool is_left_of(double pid)
double GetPIDmin()
double GetPIDmax()
bool is_inside(double pid)
Double_t y[n]
Double_t x[n]
Int_t Nint(T x)