KaliVeda
Toolkit for HIC analysis
KVIDZAFromZGrid.cpp
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 #include "TRandom.h"
9 #include <thread>
10 #include "KVMultiGaussIsotopeFit.h"
11 
15 
16 
17 
18 
23 {
24  // Default constructor
25  // Grid is declared as a 'ZOnlyGrid' by default (this is internal mechanics)
26 
27  init();
28  fFits.SetOwner();
29  SetOnlyZId();
30  fIgnoreMassID = false;
31 }
32 
33 
34 
35 
43 
45 {
46  // This method copies the current state of 'this' object into 'obj'
47  // You should add here any member variables, for example:
48  // (supposing a member variable KVIDZAFromZGrid::fToto)
49  // CastedObj.fToto = fToto;
50  // or
51  // CastedObj.SetToto( GetToto() );
52 
53  KVIDZAGrid::Copy(obj);
55  i.fPIDRange = fPIDRange;
56  i.fPIDRangeZList = fPIDRangeZList;
57  fTables.Copy(i.fTables);
58  fFits.Copy(i.fFits);
59  i.fIgnoreMassID = fIgnoreMassID;
60 }
61 
62 
63 
64 
66 
67 void KVIDZAFromZGrid::ReadFromAsciiFile(std::ifstream& gridfile)
68 {
69  fPIDRange = kFALSE;
71 
72  if (GetParameters()->HasParameter("PIDRANGE")) {
73  fPIDRange = kTRUE;
74  LoadPIDRanges();
75  }
76 
77  // if <PARAMETER> IgnoreMassID=1 appears in file, we are only using the PID intervals to clean
78  // up a messy de-e plot, not to give mass identification. particles will only be identified in Z.
79  if (GetParameters()->HasParameter("IgnoreMassID") && GetParameters()->GetIntValue("IgnoreMassID") == 1)
80  fIgnoreMassID = true;
81  else
82  fIgnoreMassID = false;
83 
84  check_pidranges_and_massfits();
85 }
86 
87 
88 
90 
91 void KVIDZAFromZGrid::WriteToAsciiFile(std::ofstream& gridfile)
92 {
93  ExportToGrid();
95 }
96 
97 
98 
100 
102 {
103  fPIDRangeZList.Clear();
104  KVIDentifier* id = 0;
105  TIter it(GetIdentifiers());
106  while ((id = (KVIDentifier*)it())) {
107  int zz = id->GetZ();
108  if (!GetParameters()->HasParameter(Form("PIDRANGE%d", zz))) continue;
109  KVString mes = GetParameters()->GetStringValue(Form("PIDRANGE%d", zz));
110  if (mes.IsWhitespace()) continue;
111  int type = (mes.Contains(",") ? 2 : 1);
112  interval_set* itv = new interval_set(zz, type);
113  itv->SetName(GetName());
114  mes.Begin("|");
115  while (!mes.End()) {
116  KVString tmp = mes.Next();
117  tmp.Begin(":");
118  int aa = tmp.Next().Atoi();
119  KVString val = tmp.Next();
120  double pidmin, pidmax, pid;
121  if (type == 1) itv->add(aa, val.Atof());
122  else if (type == 2) {
123  val.Begin(",");
124  pidmin = val.Next().Atof();
125  pid = val.Next().Atof();
126  pidmax = val.Next().Atof();
127  itv->add(aa, pid, pidmin, pidmax);
128 // itv->add(aa, pid, pid-0.02, pid+0.02);
129  }
130  }
131  fPIDRangeZList.Add(zz);
132  fTables.Add(itv);
133  }
134  fPIDRange = kTRUE;
135  GetParameters()->SetValue("PIDRANGE", fPIDRangeZList.AsString());
136 }
137 
138 
139 
141 
143 {
144  fTables.Clear();
145  fPIDRange = kFALSE;
146  fPIDRangeZList.Clear();
147 }
148 
149 
150 
152 
154 {
155  fTables.Clear();
156  LoadPIDRanges();
157 }
158 
159 
160 
162 
164 {
165  interval_set* itv = 0;
166  TIter it(&fTables);
167  while ((itv = (interval_set*)it())) if (itv->GetZ() == zint) return itv;
168  return 0;
169 }
170 
171 
172 
175 
177 {
178  // add an interval set to the grid, updating the corresponding parameters
179  fPIDRangeZList.Add(ivs->GetZ());
180  fTables.Add(ivs);
181 }
182 
183 
184 
187 
189 {
190  // Remove interval set for given Z from grid
192 }
193 
194 
195 
198 
200 {
201  // Remove interval set from grid, update parameters related to interval sets
202  auto z_int = itvs->GetZ();
203  fPIDRangeZList.Remove(z_int); // remove Z from PIDRANGE list
204  fTables.Remove(itvs);
205  delete itvs;
206 }
207 
208 
209 
216 
218 {
219 // ((interval_set*)fTables.At(12))->fIntervals.ls();
220 
221 // for (int zz = fZminInt; zz <= fZmaxInt; zz++) {
222 // Info("PrintPIDLimits", "Z=%2d [%.4lf %.4lf]", zz, ((interval_set*)fTables.At(zz - fZminInt))->fPIDmins.at(0),
223 // ((interval_set*)fTables.At(zz - fZminInt))->fPIDmaxs.at(((interval_set*)fTables.At(zz - fZminInt))->fNPIDs - 1));
224 // }
225 }
226 
227 
228 
230 
232 {
233  fPIDRangeZList.Clear();
234  if (GetParameters()->HasParameter("PIDRANGE")) GetParameters()->RemoveParameter("PIDRANGE");
235  for (int ii = 1; ii < 50; ii++) {
236  if (GetParameters()->HasParameter(Form("PIDRANGE%d", ii))) GetParameters()->RemoveParameter(Form("PIDRANGE%d", ii));
237  }
238 }
239 
240 
241 
250 
251 int KVIDZAFromZGrid::is_inside(double pid) const
252 {
253  // Look for a set of mass-interval definitions in which the given PID
254  // falls (PID from linearisation of Z identification).
255  //
256  // In principle this should be the set corresponding to Z=nint(PID),
257  // but if not Z+/-1 are also tried.
258  //
259  // Returns the value of Z for the set found (or 0 if no set found)
260 
261  int zint = TMath::Nint(pid);
262  interval_set* it = GetIntervalSet(zint);
263  if (it) {
264  if (it->is_inside(pid)) return zint;
265  else if (it->is_above(pid)) {
266 
267  it = GetIntervalSet(zint + 1);
268  if (it && it->is_inside(pid)) return zint + 1;
269  else return 0;
270  }
271  else {
272  it = GetIntervalSet(zint - 1);
273  if (it && it->is_inside(pid)) return zint - 1;
274  else return 0;
275  }
276  }
277  else return 0;
278 }
279 
280 
281 
291 
293 {
294  // General initialisation method for identification grid.
295  //
296  // This method MUST be called once before using the grid for identifications.
297  //
298  // + The ID lines are sorted.
299  // + The natural line widths of all ID lines are calculated.
300  // + The line with the largest Z (Zmax line) is found.
301  // + if a multi-gauss fit is associated with it, it is initialised with the saved parameters here
302 
303  SetOnlyZId();
305 
306  // set up mass fits (if any)
307  fFits.Clear();
308  if (GetParameters()->HasStringParameter("MASSFITS")) {
309  KVNumberList zlist(GetParameters()->GetStringValue("MASSFITS"));
310  for (auto z : zlist) {
311  auto massfit = GetParameters()->GetTStringValue(Form("MASSFIT_%d", z));
312  massfit.ReplaceAll(":", "=");
313  KVNameValueList fitparams;
314  fitparams.Set(massfit);
315  fFits.Add(new KVMultiGaussIsotopeFit(z, fitparams));
316  }
317  }
318 }
319 
320 
321 
327 
328 void KVIDZAFromZGrid::check_pidranges_and_massfits()
329 {
330  // Check for inconsistencies between 'PIDRANGE' and 'MASSFIT' parameters
331  //
332  // We also check & signal the inclusion of isotopes which are only resonances:
333  // 5Li, 6Be, 8Be, 9B, etc.
334 
335  if(fPar.HasParameter("MASSFITS"))
336  {
337  KVNumberList massfits(GetParameters()->GetStringValue("MASSFITS"));
338  // check same as PIDRANGE
339  KVNumberList pidrange(GetParameters()->GetStringValue("PIDRANGE"));
340  // exclude from massfits any missing pidrange
341  auto massfits_copy = massfits;
342  massfits.Inter(pidrange);
343  if(massfits != massfits_copy)
344  {
345  KVError::Error(this, "KVIDZAFromZGrid::check_pidranges_and_massfits",
346  "Grid %s has inconsistent MASSFITS (%s) and PIDRANGE (%s) - correcting...",
347  GetName(), massfits_copy.AsString(), pidrange.AsString());
348  GetParameters()->SetValue("MASSFITS", massfits.AsString());
349  // remove any fits which do not have a corresponding pidrange
350  for(auto z : massfits)
351  {
352  if(!GetParameters()->HasParameter(Form("PIDRANGE%d",z)))
353  {
354  KVError::Warning(this, "KVIDZAFromZGrid::check_pidranges_and_massfits",
355  "Grid %s : removing fit for Z=%d...",
356  GetName(), z);
357  GetParameters()->RemoveParameter(Form("MASSFITS_%d",z));
358  }
359  }
360  }
361  // for each MASSFIT_Z, check the 'Alist' compared to the masses given in PIDRANGEZ
362  // we signal any case where the list of fitted masses is not a subset of the pidrange masses
363  massfits = GetParameters()->GetStringValue("MASSFITS");
364  for (auto z : massfits) {
365  if(pidrange.Contains(z))
366  {
367  auto massfit = GetParameters()->GetTStringValue(Form("MASSFIT_%d", z));
368  massfit.ReplaceAll(":", "=");
369  KVNameValueList fitparams;
370  fitparams.Set(massfit);
371  KVNumberList alist(fitparams.GetStringValue("Alist"));
372  for(auto A : alist)
373  {
374  if(KVNucleus(z,A).IsResonance())
375  KVError::Error(this, "check_pidranges_and_massfits",
376  "Grid %s includes resonance %s", GetName(), KVNucleus(z,A).GetSymbol() );
377  }
378  KVNumberList pidalist;
379  KVString pidr = GetParameters()->GetStringValue(Form("PIDRANGE%d", z));
380  pidr.Begin("|");
381  while(!pidr.End())
382  {
383  auto pipi = pidr.Next();
384  pipi.Begin(":");
385  pidalist.Add(pipi.Next().Atoi());
386  }
387  auto alist_orig = alist;
388  alist.Inter(pidalist);
389  if(alist != alist_orig)
390  {
391  KVError::Warning(this, "check_pidranges_and_massfits",
392  "Grid %s has inconsistent masses for Z=%d for MASSFIT (%s) and PIDRANGE (%s)",
393  GetName(), z, alist_orig.AsString(), pidalist.AsString());
394  }
395  }
396  }
397  }
398 }
399 
400 
401 
403 
405 {
406  double P;
407  auto A = fitfunc->GetA(idr->PID, P);
408  if (A) {
409  idr->A = *A;
410  idr->PID = fitfunc->GetInterpolatedA(idr->PID);
411  if (P > 0.5) idr->IDquality = KVIDZAGrid::kICODE0; // probability of A is >50%
412  else idr->IDquality = KVIDZAGrid::kICODE3;// OK, slight ambiguity of A
413  }
414  else {
415  // no A returned => background noise
417  return false;
418  }
419  return true;
420 }
421 
422 
423 
425 
427 {
428  return (KVMultiGaussIsotopeFit*)fFits.FindObject(Form("MultiGaussIsotopeFit_Z=%d", z));
429 }
430 
431 
432 
436 
437 TH1* KVIDZAFromZGrid::LinearizeHistoToPID(const TH2* fHisto, int nbins) const
438 {
439  // Used to linearize only the part of the data which is to be identified in mass:
440  // this generates the histogram to be fitted with a KVMultiGaussIsotopeFit.
441 
442  Double_t zmin = ((KVIDentifier*)GetIdentifiers()->First())->GetPID() - 1.0;
443  Double_t zmax = 0;
444 
445  for (int iz = 1; iz < GetIdentifiers()->GetSize() + 1; iz++) {
446  KVIDentifier* tmp = (KVIDentifier*)GetIdentifiers()->At(iz);
447  if (tmp && tmp->GetPID() > zmax) zmax = tmp->GetPID();
448  }
449 
450  Int_t zbins = (Int_t)(zmax - zmin) * nbins;
451 
452  auto fLinearHisto = new TH1F("fLinearHisto", "fLinearHisto", zbins, zmin, zmax);
453 
454  const_cast<KVIDZAFromZGrid*>(this)->SetOnlyZId();
455 
456  // use multi-threading capacities
457  auto available_cpu = WITH_MULTICORE_CPU;
458  Int_t xbins_per_cpu = fHisto->GetNbinsX() / available_cpu;
459 
460  std::vector<std::thread> jobs; // threads to do the work
461 
462  // to clean up copies of grid
463  KVList grid_copies;
464 
465  // do not add copies of grid to ID grid manager
466  auto save_auto_add = KVIDGraph::GetAutoAdd();
467  KVIDGraph::SetAutoAdd(false);
468 
469  std::cout << "Will run " << available_cpu << " threads, each for " << xbins_per_cpu << " bins in X" << std::endl;
470 
471  int nthreads = available_cpu;
472  // join threads
473  std::cout << "Histo linearization using " << nthreads << " threads..." << std::endl;
474 
475  for (int job = 0; job < available_cpu; ++job) {
476  auto imin = 1 + job * xbins_per_cpu;
477  auto imax = (job + 1) * xbins_per_cpu;
478  if (job == available_cpu - 1) imax = fHisto->GetNbinsX();
479 
480  // make new copy of grid
481  auto grid_copy = new KVIDZAFromZGrid(*this);
482  grid_copy->Initialize();
483  grid_copies.Add(grid_copy);
484 
485  // start new thread
486  jobs.push_back(std::thread([ =, &nthreads]() {
487 
489 
490  bool no_mass_id_zone_defined = (grid_copy->GetInfos()->FindObject("MassID") == nullptr);
491 
492  for (int i = imin; i <= imax; ++i) {
493  for (int j = 1; j <= fHisto->GetNbinsY(); j++) {
494  Stat_t poids = fHisto->GetBinContent(i, j);
495  if (poids == 0) continue;
496 
497  Axis_t x0 = fHisto->GetXaxis()->GetBinCenter(i);
498  Axis_t y0 = fHisto->GetYaxis()->GetBinCenter(j);
499  Axis_t wx = fHisto->GetXaxis()->GetBinWidth(i);
500  Axis_t wy = fHisto->GetYaxis()->GetBinWidth(j);
501 
502  if (x0 < 4) continue;
503 
504  Double_t x, y;
505  Int_t kmax = (Int_t) TMath::Min(20., poids);
506  Double_t weight = (kmax == 20 ? poids / 20. : 1.);
507  for (int k = 0; k < kmax; k++) {
508  x = gRandom->Uniform(x0 - .5 * wx, x0 + .5 * wx);
509  y = gRandom->Uniform(y0 - .5 * wy, y0 + .5 * wy);
510  if (grid_copy->IsIdentifiable(x, y)) {
511  idr.Clear();
512  grid_copy->KVIDZAGrid::Identify(x, y, &idr);
513  if (no_mass_id_zone_defined || idr.HasFlag(grid_copy->GetName(), "MassID")) {
514  Float_t PID = idr.PID;
515  fLinearHisto->Fill(PID, weight);
516  }
517  }
518  }
519  }
520  }
521  --nthreads;
522  std::cout << "...remaining threads: " << nthreads << std::endl;
523  }));
524  }
525  for (auto& j : jobs) {
526  if (j.joinable()) j.join();
527  }
528 
529  // reset automatic grid adding to previous state
530  KVIDGraph::SetAutoAdd(save_auto_add);
531 
532  return fLinearHisto;
533 }
534 
535 
536 
548 
550 {
551  // Fill the KVIdentificationResult object with the results of identification for point (x,y)
552  // corresponding to some physically measured quantities related to a reconstructed nucleus.
553  //
554  // If identification is successful, idr->IDOK = true.
555  // In this case, idr->Aident and idr->Zident indicate whether isotopic or only Z identification
556  // was acheived.
557  //
558  // In case of unsuccessful identification, idr->IDOK = false,
559  // BUT idr->Zident and/or idr->Aident may be true: this is to indicate which kind of
560  // identification was attempted but failed (this changes the meaning of the quality code)
561 
562  idr->Aident = idr->Zident = kFALSE;
563 
564  KVIDZAGrid::Identify(x, y, idr);
565  idr->Zident = kTRUE; // meaning Z identification was attempted, even if it failed
566  if (!idr->IDOK) return;
567 
568  bool have_pid_range_for_Z = fPIDRange && fPIDRangeZList.Contains(idr->Z);
569  auto mass_fit_for_Z = GetMultiGaussFit(idr->Z);
570  bool have_mass_fit_for_Z = (mass_fit_for_Z != nullptr);
571  bool mass_id_success = false;
572 
573  if ((have_mass_fit_for_Z || have_pid_range_for_Z)
574  && (!fHasMassIDRegion || idr->HasFlag(GetName(), "MassID"))) { // if a mass ID region is defined, we must be inside it
575  // try mass identification
576  if (have_mass_fit_for_Z)
577  mass_id_success = MassIdentificationFromMultiGaussFit(mass_fit_for_Z, idr);
578  else
579  mass_id_success = (DeduceAfromPID(idr) > 0);
580  if (mass_id_success) {
581  // mass identification was at least attempted
582  // make sure grid's quality code is consistent with KVIdentificationResult
583  const_cast<KVIDZAFromZGrid*>(this)->fICode = idr->IDquality;
584  idr->Aident = kTRUE; // meaning A identification was attempted, even if it failed
585  }
586  else {
587  // the pid falls outside of any mass ranges for a Z which has assigned isotopes
588  // therefore although the Z identification was good, we cannot consider this
589  // particle to be identified
590  const_cast<KVIDZAFromZGrid*>(this)->fICode = kICODE4;
591  idr->IDquality = fICode; // otherwise identfication result quality code is not coherent with comment (see below)
592  }
593  idr->IDOK = (fICode < kICODE4);
594  }
595 
596  // ignore isotopic successful isotopic identification if fIgnoreMassID=true
597  if (fIgnoreMassID && idr->IDOK && idr->Aident) idr->Aident = false;
598 
599  // set comments in identification result
600  switch (fICode) {
601  case kICODE0:
602  idr->SetComment("ok");
603  break;
604  case kICODE1:
605  if (mass_id_success) idr->SetComment("slight ambiguity of A, which could be larger");
606  else idr->SetComment("slight ambiguity of Z, which could be larger");
607  break;
608  case kICODE2:
609  if (mass_id_success) idr->SetComment("slight ambiguity of A, which could be smaller");
610  else idr->SetComment("slight ambiguity of Z, which could be smaller");
611  break;
612  case kICODE3:
613  if (mass_id_success) idr->SetComment("slight ambiguity of A, which could be larger or smaller");
614  else idr->SetComment("slight ambiguity of Z, which could be larger or smaller");
615  break;
616  case kICODE4:
617  if (mass_id_success) idr->SetComment("point is outside of mass identification range");
618  else idr->SetComment("Z identification correct but no mass identification");
619  break;
620  case kICODE5:
621  if (mass_id_success) idr->SetComment("point is in between two isotopes A & A+2 (e.g. 5He, 8Be, 9B)");
622  else idr->SetComment("point is in between two lines of different Z, too far from either to be considered well-identified");
623  break;
624  case kICODE6:
625  idr->SetComment("(x,y) is below first line in grid");
626  break;
627  case kICODE7:
628  idr->SetComment("(x,y) is above last line in grid");
629  break;
630  default:
631  idr->SetComment("no identification: (x,y) out of range covered by grid");
632  }
633 }
634 
635 
636 
637 
643 
645 {
646  // First look for a set of mass intervals in which the PID of the identification result falls,
647  // if there is one (see KVIDZAFromZGrid::is_inside).
648  // If an interval set is found for a Z different to the original identification, idr->Z is changed.
649  // Then call interval_set::eval for the mass interval for this Z.
650 
651  int zint = is_inside(idr->PID);
652  if (!zint) return -1;
653  if (zint != idr->Z) idr->Z = zint;
654 
655  double res = 0.;
656  interval_set* it = GetIntervalSet(zint);
657  if (it) res = it->eval(idr);
658  return res;
659 }
660 
661 
662 
663 
665 
667 {
669 
670  interval_set* itvs = 0;
671  TIter npid(GetIntervalSets());
672  while ((itvs = (interval_set*)npid())) {
673  if (!itvs->GetNPID()) continue;
674  fPIDRangeZList.Add(itvs->GetZ());
675  }
676  GetParameters()->SetValue("PIDRANGE", fPIDRangeZList.AsString());
677 
678  itvs = 0;
679  TIter next(GetIntervalSets());
680  while ((itvs = (interval_set*)next())) {
681  if (!itvs->GetNPID()) continue;
682  KVString par = Form("PIDRANGE%d", itvs->GetZ());
683  KVString val = "";
684  interval* itv = 0;
685  TIter ni(itvs->GetIntervals());
686  while ((itv = (interval*)ni())) {
687  val += Form("%d:%lf,%lf,%lf|", itv->GetA(), itv->GetPIDmin(), itv->GetPID(), itv->GetPIDmax());
688  if(KVNucleus(itvs->GetZ(),itv->GetA()).IsResonance())
689  KVError::Error(this, "ExportToGrid", "Grid %s has interval set for Z=%d including resonance %s",
690  GetName(), itvs->GetZ(), KVNucleus(itvs->GetZ(),itv->GetA()).GetSymbol());
691  }
692  val.Remove(val.Length() - 1);
693  GetParameters()->SetValue(par.Data(), val.Data());
694  }
695  // now remove any massfits which do not have a corresponding pidrange
696  if(GetParameters()->HasParameter("MASSFITS"))
697  {
698  KVNumberList massfits(GetParameters()->GetStringValue("MASSFITS"));
699  auto massfits_copy = massfits;
700  massfits.Inter(fPIDRangeZList);
701  if(massfits != massfits_copy)
702  {
703  ::Info("KVIDZAFromZGrid::ExportToGrid()",
704  "Grid %s : will correct MASSFITS(%s) to be same as PIDRANGE(%s)",
705  GetName(), massfits.AsString(), fPIDRangeZList.AsString());
706  GetParameters()->SetValue("MASSFITS", fPIDRangeZList.AsString());
707  massfits = fPIDRangeZList;
708  }
709  // remove any fit not in MASSFITS/PIDRANGE list of Z
710  for(auto z : massfits)
711  {
712  if(!GetParameters()->HasParameter(Form("PIDRANGE%d",z)))
713  {
714  ::Info("KVIDZAFromZGrid::ExportToGrid()",
715  "Grid %s : removing fit for Z=%d for which no PIDRANGE exists (%s)",
716  GetName(), z, fPIDRangeZList.AsString());
717  GetParameters()->RemoveParameter(Form("MASSFITS_%d",z));
718  }
719  }
720  }
721 }
722 
723 
724 
725 
726 
728 
730 {
731  double pid = idr->PID;
732  if (pid < 0.5) return 0.;
733  // calculate interpolated mass from PID
734  double res = fPIDs.Eval(pid);
735  int ares = 0;
736 
738 
739  // look for mass interval PID is in
740  // in case it falls between two intervals remember also the interval
741  // immediately to the left & right of the PID
742  interval* left_int(nullptr), *right_int(nullptr);
743  interval* inter;
744  TIter it(&fIntervals);
745  while ((inter = (interval*)it())) {
746  if (inter->is_inside(pid)) {
747  ares = inter->GetA();
748  break;
749  }
750  else if (inter->is_left_of(pid)) {
751  left_int = inter;
752  }
753  else if (!right_int && inter->is_right_of(pid)) {
754  right_int = inter;
755  }
756  }
757  if (ares != 0) {
758  // the PID is inside a defined mass interval
759  idr->A = ares;
760  idr->PID = res;
762  }
763  else {
764  // the PID is not inside a defined mass interval
765  //
766  // * if it is in between two consecutive masses i.e. A and A+1 then it is
767  // Z- and A-identified with a slight ambiguity of A
768  // * if it is in between two non-consecutive masses i.e. A and A+2 then it
769  // is not identified (e.g. 5He, 8Be, 9B)
770  if (!right_int || !left_int) {
771  // case where no left or right interval were found
772  // to prevent from crashes but should not appen
773  idr->A = ares;
774  idr->PID = res;
776  }
777  else {
778  int dA = right_int->GetA() - left_int->GetA();
779  if (dA == 1) {
780  // OK, slight ambiguity of A
781  ares = TMath::Nint(res);
782  idr->A = ares;
783  idr->PID = res;
785  }
786  else {
787  // in a hole where no isotopes should be (e.g. 5He, 8Be, 9B)
788  idr->A = ares;
789  idr->PID = res;
791  }
792  }
793  }
794  }
795  else {
796  ares = TMath::Nint(res);
797  idr->A = ares;
798  idr->PID = res;
799  if (ares > fPIDs.GetX()[0] && ares < fPIDs.GetX()[fNPIDs - 1]) {
801  }
802  else {
804  }
805  }
806  return res;
807 }
808 
809 
810 
812 
813 bool interval_set::is_inside(double pid)
814 {
815  if (fType != KVIDZAFromZGrid::kIntType) return kTRUE;
816 
817 // Info("is_inside","min: %d max:%d npids:%d", ((interval*)fIntervals.At(0))->GetA(), ((interval*)fIntervals.At(fNPIDs-1))->GetA(), fNPIDs);
818 
819  if (pid > ((interval*)fIntervals.At(0))->GetPIDmin() && pid < ((interval*)fIntervals.At(fNPIDs - 1))->GetPIDmax()) return kTRUE;
820  else return kFALSE;
821 }
822 
823 
824 
826 
827 bool interval_set::is_above(double pid)
828 {
829  if (fType != KVIDZAFromZGrid::kIntType) return kTRUE;
830 
831  if (pid > ((interval*)fIntervals.At(fNPIDs - 1))->GetPIDmax()) return kTRUE;
832  else return kFALSE;
833 }
834 
835 
836 
837 
839 
841 {
842  if (!GetNPID()) return "-";
843  KVNumberList alist;
844  for (int ii = 0; ii < GetNPID(); ii++) alist.Add(((interval*)fIntervals.At(ii))->GetA());
845  return alist.AsString();
846 }
847 
848 
849 
851 
852 interval_set::interval_set(int zz, int type)
853 {
854  fType = type;
855  fZ = zz;
856  fNPIDs = 0;
857 }
858 
859 
860 
862 
863 void interval_set::add(int aa, double pid, double pidmin, double pidmax)
864 {
865  if (fType == KVIDZAFromZGrid::kIntType && !(pid > pidmin && pid < pidmax))
866  {
867  // sort into correct order: pidmin, pid, pidmax
868  std::map<double,int> toto;
869  ++toto[pidmin];
870  ++toto[pid];
871  ++toto[pidmax];
872  auto it = std::begin(toto);
873  pidmin = it->first;
874  ++it;
875  pid = it->first;
876  ++it;
877  pidmax = it->first;
878  }
879 
880  fPIDs.SetPoint(fNPIDs, pid, aa);
882  if (pid) fIntervals.AddLast(new interval(fZ, aa, pid, pidmin, pidmax));
883  }
884  fNPIDs++;
885 }
886 
887 
888 
889 
890 
int Int_t
float Float_t
double Axis_t
constexpr Bool_t kFALSE
double Double_t
double Stat_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 Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
R__EXTERN TRandom * gRandom
char * Form(const char *fmt,...)
virtual void WriteToAsciiFile(std::ofstream &gridfile)
Definition: KVIDGraph.cpp:446
static void SetAutoAdd(Bool_t yes=kTRUE)
Definition: KVIDGraph.h:156
static Bool_t GetAutoAdd()
Definition: KVIDGraph.h:162
const Char_t * GetName() const override
Definition: KVIDGraph.cpp:1416
const KVNameValueList * GetParameters() const
Definition: KVIDGraph.h:362
const KVList * GetIdentifiers() const
Definition: KVIDGraph.h:372
Hybrid charge & mass identification grid.
const KVList * GetIntervalSets() const
bool MassIdentificationFromMultiGaussFit(KVMultiGaussIsotopeFit *, KVIdentificationResult *) const
void Initialize() override
KVMultiGaussIsotopeFit * GetMultiGaussFit(int z) const
interval_set * GetIntervalSet(int zint) const
void WriteToAsciiFile(std::ofstream &gridfile) override
void Identify(Double_t x, Double_t y, KVIdentificationResult *) const override
virtual double DeduceAfromPID(KVIdentificationResult *idr) const
void AddIntervalSet(interval_set *)
add an interval set to the grid, updating the corresponding parameters
TH1 * LinearizeHistoToPID(const TH2 *hdata, int nbins=100) const override
void SetOnlyZId(Bool_t=kTRUE) override
void RemoveIntervalSet(int zint)
Remove interval set for given Z from grid.
void ReadFromAsciiFile(std::ifstream &gridfile) override
void Copy(TObject &obj) const override
void ReadFromAsciiFile(std::ifstream &gridfile) override
void Copy(TObject &) const override
Copy this to 'obj'.
Definition: KVIDZAGrid.cpp:66
void Initialize() override
void Identify(Double_t x, Double_t y, KVIdentificationResult *) const override
Base class for graphical cuts used in particle identification.
Definition: KVIDentifier.h:28
virtual Double_t GetPID() const
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
void Clear(Option_t *opt="") override
Reset to initial values.
Bool_t HasFlag(std::string grid_name, TString flag)
Bool_t Zident
=kTRUE if Z of particle established
Extended TList class which owns its objects by default.
Definition: KVList.h:22
Function for fitting PID mass spectra.
std::optional< int > GetA(double PID, double &P) const
double GetInterpolatedA(double PID) const
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
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 Set(const KVString &)
TString GetTStringValue(const Char_t *name) const
Description of properties and kinematics of atomic nuclei.
Definition: KVNucleus.h:108
const Char_t * GetSymbol(Option_t *opt="") const
Definition: KVNucleus.cpp:43
Bool_t IsResonance(std::optional< int > z={}, std::optional< int > a={}) const
Definition: KVNucleus.cpp:1961
Strings used to represent a set of ranges of values.
Definition: KVNumberList.h:86
void Inter(const KVNumberList &list)
Bool_t Contains(Int_t val) const
returns kTRUE if the value 'val' is contained in the ranges defined by the number list
void Clear(Option_t *="") override
Empty number list, reset it to initial state.
const Char_t * AsString(Int_t maxchars=0) const
void Remove(Int_t)
Remove value 'n' from the list.
void Add(Int_t)
Add value 'n' to the list.
void Copy(TObject &obj) const override
TObject * First() const override
TObject * Remove(TObject *obj) override
Remove object from list.
void Add(TObject *obj) override
TObject * FindObject(const char *name) const override
void AddLast(TObject *obj) override
Int_t GetSize() const override
void Clear(Option_t *option="") override
TObject * At(Int_t idx) const override
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition: KVString.h:73
void Begin(TString delim) const
Definition: KVString.cpp:565
Bool_t End() const
Definition: KVString.cpp:634
KVString Next(Bool_t strip_whitespace=kFALSE) const
Definition: KVString.cpp:695
void Add(TObject *obj) override
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
TObject * FindObject(const char *name) const override
virtual Int_t GetNbinsY() const
TAxis * GetXaxis()
virtual Int_t GetNbinsX() const
TAxis * GetYaxis()
virtual Double_t GetBinContent(Int_t bin) const
virtual void SetName(const char *name)
virtual void Info(const char *method, const char *msgfmt,...) const
virtual Double_t Uniform(Double_t x1, Double_t x2)
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
TString & ReplaceAll(const char *s1, const char *s2)
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]
void Error(UserClass p, const char *location, const char *va_(fmt),...)
Definition: KVError.h:116
void Warning(UserClass p, const char *location, const char *va_(fmt),...)
Definition: KVError.h:125
void init()
Double_t Min(Double_t a, Double_t b)
Int_t Nint(T x)
ClassImp(TPyArg)