KaliVeda
Toolkit for HIC analysis
KVItvFinderDialog.cpp
1 //Created by KVClassFactory on Mon Jan 23 10:03:13 2017
2 //Author: Diego Gruyer
3 
4 #include "KVItvFinderDialog.h"
5 #include "TRandom.h"
6 #include "TRootEmbeddedCanvas.h"
7 #include "TStyle.h"
8 #include "TSystem.h"
9 #include "TROOT.h"
10 #include "TGMsgBox.h"
11 #include "TGFileDialog.h"
12 #include "KVTestIDGridDialog.h"
13 #include "KVIdentificationResult.h"
14 #include "KVNameValueListGUI.h"
15 #include <KVMultiGaussIsotopeFit.h>
16 #include "KeySymbols.h"
17 #include <thread>
18 
20 //ClassImp(interval_painter)
21 
22 // Set default values for mass-fit parameters
23 
24 
27  {"Limit range of fit", false},
28  {"PID min for fit", 0.},
29  {"PID max for fit", 10.},
30  {"Minimum probability [%]", 50.},
31  {"Minimum #sigma", 1.e-2},
32  {"Maximum #sigma", 5.e-2}
33 };
34 
35 
36 
40 
42 {
43  // remove painter from list and modify the 'left_painter' and 'right_painter' references
44  // in any adjacent painters/intervals, then delete painter
45 
46  std::unique_ptr<KVPIDIntervalPainter> _p(p);
47  auto pleft = p->get_left_interval();
48  auto pright = p->get_right_interval();
49  if (pleft) pleft->set_right_interval(pright);
50  if (pright) pright->set_left_interval(pleft);
52 }
53 
54 
55 
57 
59 {
60  fGrid = gg;
61  fHisto = hh;
62 
63  fPoints = new TGraph;
65  fNPoints = 0;
66 
67  gStyle->SetOptStat(0);
68  gStyle->SetOptTitle(0);
69 
70  gROOT->ProcessLine(Form("KVItvFinderDialog* _dummy_itv=(KVItvFinderDialog*)%p", this));
71 
72  fMain = new TGTransientFrame(gClient->GetDefaultRoot(), gClient->GetDefaultRoot(), 10, 10);
73  // Here is the recipe for cleanly closing a window
74  // (see https://root-forum.cern.ch/t/error-in-rootx11errorhandler-baddrawable-quot/8095/6)
75  fMain->Connect("CloseWindow()", "KVItvFinderDialog", this, "DoClose()");
78  // afterwards, in the destructor do fMain->CloseWindow(), and in DoClose(), do 'delete this'
79 
80  // Default constructor
81  TGHorizontalFrame* fCanvasFrame = new TGHorizontalFrame(fMain, 627, 7000, kHorizontalFrame);
82  // fCanvasFrame->SetBackgroundColor(fColor);
83 
84 
85  TRootEmbeddedCanvas* fRootEmbeddedCanvas615 = new TRootEmbeddedCanvas(0, fCanvasFrame, 800, 440);
86  // to replace the TCanvas in a TRootEmbeddedCanvas, just delete the original like so:
87  // (see https://root-forum.cern.ch/t/error-in-rootx11errorhandler-baddrawable-quot/8095/6)
88  auto WID = fRootEmbeddedCanvas615->GetCanvasWindowId();
89  delete fRootEmbeddedCanvas615->GetCanvas();
90  fCanvas = new TCanvas("c123", 10, 10, WID);
91  fCanvas->AddExec("toto", "if(_dummy_itv)_dummy_itv->HandleKey();");
92  fRootEmbeddedCanvas615->AdoptCanvas(fCanvas);
93  fPad = fCanvas->cd();
94  fCanvas->SetRightMargin(0.02);
95  fCanvas->SetTopMargin(0.02);
96  fCanvas->SetLeftMargin(0.08);
97  fCanvas->SetBottomMargin(0.07);
98 
99  fCanvasFrame->AddFrame(fRootEmbeddedCanvas615, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
100  fMain->AddFrame(fCanvasFrame, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 0, 0, 0, 0));
101 
102  TGVerticalFrame* fControlOscillo = new TGVerticalFrame(fCanvasFrame, 2000, 7000, kVerticalFrame);
103 
104  {
105  const char* xpms[] = {
106  "filesaveas.xpm",
107  "profile_t.xpm",
108  "bld_copy.png",
109  "ed_new.png",
110  "refresh2.xpm",
111  "sm_delete.xpm",
112  "h1_t.xpm",
113  "query_new.xpm",
114  "tb_back.xpm",
115  "bld_colorselect.png",
116  "latex.xpm",
117  "move_cursor.png",
118  0
119  };
120  // toolbar tool tip text
121  const char* tips[] = {
122  "Save intervals in current grid",
123  "Find intervals",
124  "Create a new interval set",
125  "Create a new interval",
126  "Update interval lists",
127  "Remove selected intervals",
128  "Multigauss fit to isotopes in interval set",
129  "Set parameters for fit",
130  "Remove fit from selected interval set",
131  "Test identification",
132  "Set log scale on y axis",
133  "Unzoom the histogram",
134  0
135  };
136  int spacing[] = {
137  5,
138  20,
139  0,
140  0,
141  0,
142  20,
143  50,
144  0,
145  0,
146  50,
147  80,
148  0,
149  0
150  };
151  const char* method[] = {
152  "SaveGrid()",
153  "Identify()",
154  "NewIntervalSet()",
155  "NewInterval()",
156  "UpdateLists()",
157  "RemoveInterval()",
158  "FitIsotopes()",
159  "SetFitParameters()",
160  "RemoveFit()",
161  "TestIdent()",
162  "SetLogy()",
163  "UnzoomHisto()",
164  0
165  };
166  fNbButtons = 0;
167  ToolBarData_t t[50];
168  fToolBar = new TGToolBar(fControlOscillo, 450, 80);
169  int i = 0;
170  while (xpms[i]) {
171  t[i].fPixmap = xpms[i];
172  t[i].fTipText = tips[i];
173  t[i].fStayDown = kFALSE;
174  t[i].fId = i + 1;
175  t[i].fButton = NULL;
176  TGButton* bb = fToolBar->AddButton(fControlOscillo, &t[i], spacing[i]);
177  bb->Connect("Clicked()", "KVItvFinderDialog", this, method[i]);
178  fNbButtons++;
179  i++;
180  }
181  fControlOscillo->AddFrame(fToolBar, new TGLayoutHints(kLHintsTop | kLHintsExpandX));
182  }
183 
184  fIntervalSetListView = new KVListView(interval_set::Class(), fControlOscillo, 450, 200);
186  fIntervalSetListView->SetDataColumn(0, "Z", "GetZ", kTextLeft);
187  fIntervalSetListView->SetDataColumn(1, "PIDs", "GetNPID", kTextCenterX);
188  fIntervalSetListView->SetDataColumn(2, "Masses", "GetListOfMasses", kTextLeft);
189  fIntervalSetListView->Connect("SelectionChanged()", "KVItvFinderDialog", this, "DisplayPIDint()");
190  fIntervalSetListView->SetDoubleClickAction("KVItvFinderDialog", this, "ZoomOnCanvas()");
192  fControlOscillo->AddFrame(fIntervalSetListView, new TGLayoutHints(kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
193 
194  fIntervalListView = new KVListView(interval::Class(), fControlOscillo, 450, 180);
196  fIntervalListView->SetDataColumn(0, "Z", "GetZ", kTextLeft);
197  fIntervalListView->SetDataColumn(1, "A", "GetA", kTextCenterX);
198  fIntervalListView->SetDataColumn(2, "min", "GetPIDmin", kTextCenterX);
199  fIntervalListView->SetDataColumn(3, "pid", "GetPID", kTextCenterX);
200  fIntervalListView->SetDataColumn(4, "max", "GetPIDmax", kTextCenterX);
201 
202 
203 
204  {
205  const char* xpms[] = {
206  "arrow_down.xpm",
207  "arrow_up.xpm",
208  0
209  };
210  const char* tips[] = {
211  "Decrease A by one",
212  "Increase A by one",
213  0
214  };
215  int spacing[] = {
216  120,
217  0,
218  0
219  };
220  const char* method[] = {
221  "MassesDown()",
222  "MassesUp()",
223  0
224  };
225  fNbButtons = 0;
226  ToolBarData_t t[50];
227  fToolBar2 = new TGToolBar(fControlOscillo, 450, 80);
228  int i = 0;
229  while (xpms[i]) {
230  t[i].fPixmap = xpms[i];
231  t[i].fTipText = tips[i];
232  t[i].fStayDown = kFALSE;
233  t[i].fId = i + 1;
234  t[i].fButton = NULL;
235  TGButton* bb = fToolBar2->AddButton(fControlOscillo, &t[i], spacing[i]);
236  bb->Connect("Clicked()", "KVItvFinderDialog", this, method[i]);
237  fNbButtons++;
238  i++;
239  }
240  fControlOscillo->AddFrame(fToolBar2, new TGLayoutHints(kLHintsTop | kLHintsExpandX));
241  }
242 
243  // fCurrentView->ActivateSortButtons();
244  fIntervalListView->Connect("SelectionChanged()", "KVItvFinderDialog", this, "SelectionITVChanged()");
245  // fCurrentView->SetDoubleClickAction("FZCustomFrameManager",this,"ChangeParValue()");
247 
248  fControlOscillo->AddFrame(fIntervalListView, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 2, 2, 2));
249 
250  fCanvasFrame->AddFrame(fControlOscillo, new TGLayoutHints(kLHintsExpandY, 0, 0, 0, 0));
251 
252 
253  //layout and display window
254  fMain->MapSubwindows();
256 
257  // position relative to the parent's window
259 
260  fMain->SetWindowName("Masses Identification");
261  fMain->RequestFocus();
262  fMain->MapWindow();
263 
264  fIntervalSetListView->Display(((KVIDZAFromZGrid*)fGrid)->GetIntervalSets());
265  current_interval_set = nullptr;
266  fPad->cd();
267 
268  LinearizeHisto(100);
271  fLinearHisto->Draw("hist");
272 
273  int tmp[30] = {3, 3, 3, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6};
274  for (int ii = 0; ii < 30; ii++) fNpeaks[ii] = tmp[ii];
275 
276  fSig = 0.1;
277  fRat = 0.0001;
278 
279  DrawIntervals();
280  PrintHelp();
281 
282 }
283 
284 
285 
286 
288 
290 {
291  std::unique_ptr<TList> list(fIntervalSetListView->GetSelectedObjects());
292  Int_t nSelected = list->GetSize();
293  if (nSelected == 1) {
294  current_interval_set = (interval_set*)list->At(0);
296  }
297  else {
298  current_interval_set = nullptr;
300  }
302 }
303 
304 
305 
307 
309 {
310  fPad->cd();
311  fItvPaint.Execute("HighLight", "0");
312 
314  int zz = ((interval*)fIntervalListView->GetLastSelectedObject())->GetZ();
315  int aa = ((interval*)fIntervalListView->GetLastSelectedObject())->GetA();
316  KVPIDIntervalPainter* painter = (KVPIDIntervalPainter*)fItvPaint.FindObject(Form("%d_%d", zz, aa));
317  if (!painter) Info("SelectionITVChanged", "%d %d not found...", zz, aa);
318  painter->HighLight();
319  }
320  fCanvas->Modified();
321  fCanvas->Update();
322 }
323 
324 
325 
327 
329 {
330  std::unique_ptr<TList> list(fIntervalSetListView->GetSelectedObjects());
331  Int_t nSelected = list->GetSize();
332  if (nSelected == 1) {
333  current_interval_set = (interval_set*)list->At(0);
335  }
336  else {
337  current_interval_set = nullptr;
339  }
340 }
341 
342 
343 
346 
348 {
349  // Display the interval set for a given Z when the user double clicks on it
350 
352  current_interval_set = nullptr;
353  return;
354  }
356  auto zz = current_interval_set->GetZ();
357 
358  fLinearHisto->GetXaxis()->SetRangeUser(zz - 0.5, zz + 0.5);
359 
360  fItvPaint.Execute("SetDisplayLabel", "0");
361 
362  std::unique_ptr<KVSeqCollection> tmp(fItvPaint.GetSubListWithMethod(Form("%d", zz), "GetZ"));
363 
364  tmp->Execute("SetDisplayLabel", "1");
365 
366  // Check - if no mass fit is displayed, we look to see if the grid has a saved
367  // multigauss fit from a previous session, and if so we display it
368  if (!fPad->GetPrimitive(KVMultiGaussIsotopeFit::get_name_of_multifit(zz))) {
369  if (fGrid->GetParameters()->HasParameter(Form("MASSFIT_%d", zz))) {
370  KVString massfit = fGrid->GetParameters()->GetTStringValue(Form("MASSFIT_%d", zz));
371  massfit.ReplaceAll(":", "=");
372  KVNameValueList fitparams;
373  fitparams.Set(massfit);
374  KVMultiGaussIsotopeFit fitfunc(zz, fitparams);
375  fitfunc.DrawFitWithGaussians("same");
376  // deactivate intervals in painter
377  tmp->Execute("DeactivateIntervals", "");
378  }
379  }
380 
381  fCanvas->Modified();
382  fCanvas->Update();
383 }
384 
385 
386 
388 
390 {
391  interval_set* itvs = 0;
392  last_drawn_interval = nullptr;
393  TIter it(fGrid->GetIntervalSets());
394  while ((itvs = (interval_set*)it())) {
395  DrawInterval(itvs);
396  }
397 }
398 
399 
400 
402 
404 {
405  fPad->cd();
406  interval* itv = nullptr;
407  // give a different colour to each interval
408  auto nitv = itvs->GetIntervals()->GetEntries();
409  auto cstep = TColor::GetPalette().GetSize() / (nitv + 1);
410  int i = 1;
411  auto deactivate_intervals = fGrid->GetParameters()->HasParameter(Form("MASSFIT_%d", itvs->GetZ()));
412 
413  TIter itt(itvs->GetIntervals());
414  while ((itv = (interval*)itt())) {
416  ++i;
417  if (label) dummy->SetDisplayLabel();
418  if (deactivate_intervals) dummy->DeactivateIntervals();
419  dummy->Draw();
420  dummy->SetCanvas(fCanvas);
421  dummy->Connect("IntMod()", "KVItvFinderDialog", this, "UpdatePIDList()");
422  fItvPaint.Add(dummy);
423  last_drawn_interval = dummy;
424  }
425 }
426 
427 
428 
433 
435 {
436  // empty an interval set, effectively removing it from the interval sets which will be saved with the grid.
437  //
438  // we also remove any previous fits from the grid's parameters
439 
440  std::vector<int> alist;
441  for (int ii = 0; ii < itvs->GetNPID(); ii++) {
442  interval* itv = (interval*)itvs->GetIntervals()->At(ii);
443  KVPIDIntervalPainter* pid = (KVPIDIntervalPainter*)fItvPaint.FindObject(Form("%d_%d", itv->GetZ(), itv->GetA()));
445  alist.push_back(itv->GetA());
446  }
447  itvs->GetIntervals()->Clear();
448  UpdateLists();
449  // remove any fit displayed in pad
450  KVMultiGaussIsotopeFit fitfunc(itvs->GetZ(), alist);
451  fitfunc.UnDraw(fPad);
452  // mop up any stray gaussians (from intervals which have been removed)
453  KVMultiGaussIsotopeFit::UnDrawAnyGaussian(itvs->GetZ(), fPad);
454 
455  // remove from grid parameters
456  if (fGrid->GetParameters()->HasParameter(Form("MASSFIT_%d", itvs->GetZ()))) {
457  fGrid->GetParameters()->RemoveParameter(Form("MASSFIT_%d", itvs->GetZ()));
458  KVNumberList zlist(fGrid->GetParameters()->GetStringValue("MASSFITS"));
459  zlist.Remove(itvs->GetZ());
460  fGrid->GetParameters()->SetValue("MASSFITS", zlist.AsString());
461  }
462  fCanvas->Modified();
463  fCanvas->Update();
464 }
465 
466 
467 
469 
471 {
472  Double_t zmin = ((KVIDentifier*)fGrid->GetIdentifiers()->First())->GetPID() - 1.0;
473  Double_t zmax = 0;
474 
475  for (int iz = 1; iz < fGrid->GetIdentifiers()->GetSize() + 1; iz++) {
477  if (tmp && tmp->GetPID() > zmax) zmax = tmp->GetPID();
478  }
479 
480  Int_t zbins = (Int_t)(zmax - zmin) * nbins;
481 
482  fLinearHisto = new TH1F("fLinearHisto", "fLinearHisto", zbins, zmin, zmax);
483 
484  fGrid->SetOnlyZId();
485 
486  // use multi-threading capacities
487  auto available_cpu = WITH_MULTICORE_CPU;
488  Int_t xbins_per_cpu = fHisto->GetNbinsX() / available_cpu;
489 
490  std::vector<std::thread> jobs; // threads to do the work
491 
492  // to clean up copies of grid
493  KVList grid_copies;
494 
495  // do not add copies of grid to ID grid manager
496  auto save_auto_add = KVIDGraph::GetAutoAdd();
497  KVIDGraph::SetAutoAdd(false);
498 
499  std::cout << "Will run " << available_cpu << " threads, each for " << xbins_per_cpu << " bins in X" << std::endl;
500 
501  int nthreads = available_cpu;
502  // join threads
503  std::cout << "Histo linearization using " << nthreads << " threads..." << std::endl;
504 
505  for (int job = 0; job < available_cpu; ++job) {
506  auto imin = 1 + job * xbins_per_cpu;
507  auto imax = (job + 1) * xbins_per_cpu;
508  if (job == available_cpu - 1) imax = fHisto->GetNbinsX();
509 
510  // make new copy of grid
511  auto grid_copy = new KVIDZAFromZGrid(*fGrid);
512  grid_copy->Initialize();
513  grid_copies.Add(grid_copy);
514 
515  // start new thread
516  jobs.push_back(std::thread([ =, &nthreads]() {
517 
519 
520  bool no_mass_id_zone_defined = (grid_copy->GetInfos()->FindObject("MassID") == nullptr);
521 
522  for (int i = imin; i <= imax; ++i) {
523  for (int j = 1; j <= fHisto->GetNbinsY(); j++) {
524  Stat_t poids = fHisto->GetBinContent(i, j);
525  if (poids == 0) continue;
526 
527  Axis_t x0 = fHisto->GetXaxis()->GetBinCenter(i);
528  Axis_t y0 = fHisto->GetYaxis()->GetBinCenter(j);
529  Axis_t wx = fHisto->GetXaxis()->GetBinWidth(i);
530  Axis_t wy = fHisto->GetYaxis()->GetBinWidth(j);
531 
532  if (x0 < 4) continue;
533 
534  Double_t x, y;
535  Int_t kmax = (Int_t) TMath::Min(20., poids);
536  Double_t weight = (kmax == 20 ? poids / 20. : 1.);
537  for (int k = 0; k < kmax; k++) {
538  x = gRandom->Uniform(x0 - .5 * wx, x0 + .5 * wx);
539  y = gRandom->Uniform(y0 - .5 * wy, y0 + .5 * wy);
540  if (grid_copy->IsIdentifiable(x, y)) {
541  idr.Clear();
542  grid_copy->KVIDZAGrid::Identify(x, y, &idr);
543  if (no_mass_id_zone_defined || idr.HasFlag(grid_copy->GetName(), "MassID")) {
544  Float_t PID = idr.PID;
545  fLinearHisto->Fill(PID, weight);
546  }
547  }
548  }
549  }
550  }
551  --nthreads;
552  std::cout << "...remaining threads: " << nthreads << std::endl;
553  }));
554  }
555  for (auto& j : jobs) {
556  if (j.joinable()) j.join();
557  }
558 
559  // reset automatic grid adding to previous state
560  KVIDGraph::SetAutoAdd(save_auto_add);
561 }
562 
563 
564 
567 
569 {
570  // KVBase::OpenContextMenu("Identify(double,double)",this);
571  Identify(0.1, 0.001);
572 }
573 
574 
575 
577 
578 void KVItvFinderDialog::Identify(double sigma, double ratio)
579 {
580  fSig = sigma;
581  fRat = ratio;
582 
583  fPad->cd();
584  std::unique_ptr<TList> list(fIntervalSetListView->GetSelectedObjects());
585  if (!list->GetSize()) {
587  for (int ii = 0; ii < fGrid->GetIntervalSets()->GetSize(); ii++) DrawInterval((interval_set*)fGrid->GetIntervalSets()->At(ii), 0);
588  }
589  else {
590  for (int ii = 0; ii < list->GetSize(); ii++) {
591  interval_set* itvs = (interval_set*) list->At(ii);
592  ProcessIdentification(itvs->GetZ(), itvs->GetZ());
593  DrawInterval(itvs, 0);
594  }
595  }
596 
597  fCanvas->Modified();
598  fCanvas->Update();
599 
600 }
601 
602 
603 
605 
607 {
608  ExportToGrid();
609 
610  TString currentdir(gSystem->ExpandPathName("."));
611 
612  TString fn = fHisto->GetName();
613  fn += ".dat";
614 
615  Int_t ret_code;
616  new TGMsgBox(
617  gClient->GetRoot(),
618  gClient->GetDefaultRoot(),
619  "KVIDGridEditor::SaveCurrentGrid", Form("Do you wat to save the grid here : %s", fn.Data()),
620  kMBIconExclamation, kMBYes | kMBNo, &ret_code
621  );
622 
623  if (ret_code == kMBYes) {
624  fGrid->WriteAsciiFile(Form("%s", fn.Data()));
625  return;
626  }
627 
628  static TString dir(".");
629  const char* filetypes[] = {
630  "ID Grid files", "*.dat",
631  "All files", "*",
632  0, 0
633  };
634  TGFileInfo fi;
635  fi.fFileTypes = filetypes;
636  fi.fIniDir = StrDup(dir);
637  new TGFileDialog(gClient->GetDefaultRoot(), gClient->GetDefaultRoot(), kFDSave, &fi);
638  if (fi.fFilename) {
639  TString filenam(fi.fFilename);
640  if (filenam.Contains("toto")) filenam.ReplaceAll("toto", fGrid->GetName());
641  if (!filenam.Contains('.')) filenam += ".dat";
642  fGrid->WriteAsciiFile(filenam.Data());
643  }
644  dir = fi.fIniDir;
646 
647  fIntervalSetListView->Display(((KVIDZAFromZGrid*)fGrid)->GetIntervalSets());
648  current_interval_set = nullptr;
650 
651  fItvPaint.Clear();
652  DrawIntervals();
653 }
654 
655 
656 
659 
661 {
662  // Write all PID intervals in grid parameters "PIDRANGE", "PIDRANGE%d", etc.
663 
665  KVNumberList pids;
666  interval_set* itvs = 0;
667  TIter npid(fGrid->GetIntervalSets());
668  while ((itvs = (interval_set*)npid())) {
669  if (!itvs->GetNPID()) continue;
670  pids.Add(itvs->GetZ());
671  }
672  fGrid->GetParameters()->SetValue("PIDRANGE", pids.AsString());
673 
674  itvs = 0;
675  TIter next(fGrid->GetIntervalSets());
676  while ((itvs = (interval_set*)next())) {
677  if (!itvs->GetNPID()) continue;
678  KVString par = Form("PIDRANGE%d", itvs->GetZ());
679  KVString val = "";
680  interval* itv = 0;
681  TIter ni(itvs->GetIntervals());
682  while ((itv = (interval*)ni())) {
683  val += Form("%d:%lf,%lf,%lf|", itv->GetA(), itv->GetPIDmin(), itv->GetPID(), itv->GetPIDmax());
684  }
685  val.Remove(val.Length() - 1);
686  fGrid->GetParameters()->SetValue(par.Data(), val.Data());
687  }
688 }
689 
690 
691 
693 
695 {
696  std::unique_ptr<TList> list(fIntervalSetListView->GetSelectedObjects());
697  if (!list->GetSize() || list->GetSize() > 1) {
698  current_interval_set = nullptr;
699  return;
700  }
701 
702  current_interval_set = (interval_set*)list->At(0);
703 
704  fPad->WaitPrimitive("TMarker");
705  auto mm = dynamic_cast<TMarker*>(fPad->GetListOfPrimitives()->Last());
706  assert(mm);
707  double pid = mm->GetX();
708  delete mm;
709 
710  int aa = 0;
711  int iint = 0;
712 
713  // try to guess mass from position (PID)
714  // typical isotope separation in PID is 0.12 (e.g. for carbon isotopes)
715  // assume that PID=z means A=2*Z
716  auto aa_guessstimate = TMath::Nint(current_interval_set->GetZ() * 2 + (pid - current_interval_set->GetZ()) / 0.12);
717 //Info("NewINt","pid = %f guess a=%d",pid,aa_guessstimate);
718  if (!current_interval_set->GetNPID()) {
719  aa = aa_guessstimate;
720  iint = 0;
721  }
722  else if (pid < ((interval*)current_interval_set->GetIntervals()->First())->GetPID()) { // to left of all others
723  aa = ((interval*)current_interval_set->GetIntervals()->First())->GetA() - 1;
724  // NO MORE : use guesstimate as long as it is smaller than A of previously defined interval with largest PID
725  // NOW : use 'aa_guessstimate' only for first interval
726  //Info("NewInt","before first interval, with a=%d",aa+1);
727 // if (aa_guessstimate < aa + 1) aa = aa_guessstimate;
728  iint = 0;
729  }
730  else if (pid > ((interval*)current_interval_set->GetIntervals()->Last())->GetPID()) { // to right of all others
731  aa = ((interval*)current_interval_set->GetIntervals()->Last())->GetA() + 1;
732  // NO MORE : use guesstimate as long as it is larger than A of previously defined interval with smallest PID
733  // NOW : use 'aa_guessstimate' only for first interval
734  //Info("NewInt","after last interval, with a=%d",aa-1);
735 // if (aa_guessstimate > aa - 1) aa = aa_guessstimate;
736  iint = current_interval_set->GetNPID();
737  }
738  else {
739  // look for intervals between which the new one is places
740  for (int ii = 1; ii < current_interval_set->GetNPID(); ii++) {
741  if (pid > ((interval*)current_interval_set->GetIntervals()->At(ii - 1))->GetPID()
742  && pid < ((interval*)current_interval_set->GetIntervals()->At(ii))->GetPID()) {
743  aa = ((interval*)current_interval_set->GetIntervals()->At(ii - 1))->GetA() + 1;
744  // use guesstimate if it is in between masses of adjacent intervals (in terms of PID)
745  if ((aa_guessstimate > (aa - 1)) &&
746  (aa_guessstimate < ((interval*)current_interval_set->GetIntervals()->At(ii))->GetA()))
747  aa = aa_guessstimate;
748  iint = ii;
749  break;
750  }
751  }
752  }
753 
754  interval* itv = new interval(current_interval_set->GetZ(), aa, mm->GetX(), mm->GetX() - 0.05, mm->GetX() + 0.05);
755  current_interval_set->GetIntervals()->AddAt(itv, iint);
756 
757  // find intervals which are now left (smaller mass) and right (higher mass) than this one
758  interval* left_interval = iint > 0 ? (interval*)current_interval_set->GetIntervals()->At(iint - 1) : nullptr;
759  interval* right_interval = iint < current_interval_set->GetIntervals()->GetEntries() - 1 ? (interval*)current_interval_set->GetIntervals()->At(iint + 1) : nullptr;
760  // find the corresponding painters
761  KVPIDIntervalPainter* left_painter{nullptr}, *right_painter{nullptr};
762  TIter next_painter(&fItvPaint);
763  KVPIDIntervalPainter* pidpnt;
764  while ((pidpnt = (KVPIDIntervalPainter*)next_painter())) {
765  if (pidpnt->GetInterval() == left_interval) left_painter = pidpnt;
766  else if (pidpnt->GetInterval() == right_interval) right_painter = pidpnt;
767  }
768 
769  // give a different colour to each interval
770  auto nitv = current_interval_set->GetIntervals()->GetEntries();
771  auto cstep = TColor::GetPalette().GetSize() / (nitv + 1);
772 
773  KVPIDIntervalPainter* dummy = new KVPIDIntervalPainter(itv, fLinearHisto, TColor::GetPalette()[cstep * (iint + 1)],
774  left_painter);
775  // set up links between painters
776  if (right_painter) {
777  right_painter->set_left_interval(dummy);
778  dummy->set_right_interval(right_painter);
779  }
780  fPad->cd();
781  dummy->Draw();
782  dummy->Connect("IntMod()", "KVItvFinderDialog", this, "UpdatePIDList()");
783  dummy->SetDisplayLabel(1);
784  dummy->SetCanvas(fCanvas);
785  fItvPaint.Add(dummy);
786 
788 
789  fItvPaint.Execute("Update", "");
790 
791  fCanvas->Modified();
792  fCanvas->Update();
793 }
794 
795 
796 
798 
800 {
801  std::unique_ptr<TList> list(fIntervalSetListView->GetSelectedObjects());
802  if (!list->GetSize() || list->GetSize() > 1) {
803  current_interval_set = nullptr;
804  return;
805  }
806 
807  current_interval_set = (interval_set*)list->At(0);
808 
809  int aa = 0;
810  int iint = 0;
811 
812  // try to guess mass from position (PID)
813  // typical isotope separation in PID is 0.12 (e.g. for carbon isotopes)
814  // assume that PID=z means A=2*Z
815  auto aa_guessstimate = TMath::Nint(current_interval_set->GetZ() * 2 + (pid - current_interval_set->GetZ()) / 0.12);
816 //Info("NewINt","pid = %f guess a=%d",pid,aa_guessstimate);
817  if (!current_interval_set->GetNPID()) {
818  aa = aa_guessstimate;
819  iint = 0;
820  }
821  else if (pid < ((interval*)current_interval_set->GetIntervals()->First())->GetPID()) { // to left of all others
822  aa = ((interval*)current_interval_set->GetIntervals()->First())->GetA() - 1;
823  // NO MORE : use guesstimate as long as it is smaller than A of previously defined interval with largest PID
824  // NOW : use 'aa_guessstimate' only for first interval
825  //Info("NewInt","before first interval, with a=%d",aa+1);
826 // if (aa_guessstimate < aa + 1) aa = aa_guessstimate;
827  iint = 0;
828  }
829  else if (pid > ((interval*)current_interval_set->GetIntervals()->Last())->GetPID()) { // to right of all others
830  aa = ((interval*)current_interval_set->GetIntervals()->Last())->GetA() + 1;
831  // NO MORE : use guesstimate as long as it is larger than A of previously defined interval with smallest PID
832  // NOW : use 'aa_guessstimate' only for first interval
833  //Info("NewInt","after last interval, with a=%d",aa-1);
834 // if (aa_guessstimate > aa - 1) aa = aa_guessstimate;
835  iint = current_interval_set->GetNPID();
836  }
837  else {
838  // look for intervals between which the new one is places
839  for (int ii = 1; ii < current_interval_set->GetNPID(); ii++) {
840  if (pid > ((interval*)current_interval_set->GetIntervals()->At(ii - 1))->GetPID()
841  && pid < ((interval*)current_interval_set->GetIntervals()->At(ii))->GetPID()) {
842  aa = ((interval*)current_interval_set->GetIntervals()->At(ii - 1))->GetA() + 1;
843  // use guesstimate if it is in between masses of adjacent intervals (in terms of PID)
844  if ((aa_guessstimate > (aa - 1)) &&
845  (aa_guessstimate < ((interval*)current_interval_set->GetIntervals()->At(ii))->GetA()))
846  aa = aa_guessstimate;
847  iint = ii;
848  break;
849  }
850  }
851  }
852 
853  interval* itv = new interval(current_interval_set->GetZ(), aa, pid, pid - 0.05, pid + 0.05);
854  current_interval_set->GetIntervals()->AddAt(itv, iint);
855 
856  // find intervals which are now left (smaller mass) and right (higher mass) than this one
857  interval* left_interval = iint > 0 ? (interval*)current_interval_set->GetIntervals()->At(iint - 1) : nullptr;
858  interval* right_interval = iint < current_interval_set->GetIntervals()->GetEntries() - 1 ? (interval*)current_interval_set->GetIntervals()->At(iint + 1) : nullptr;
859  // find the corresponding painters
860  KVPIDIntervalPainter* left_painter{nullptr}, *right_painter{nullptr};
861  TIter next_painter(&fItvPaint);
862  KVPIDIntervalPainter* pidpnt;
863  while ((pidpnt = (KVPIDIntervalPainter*)next_painter())) {
864  if (pidpnt->GetInterval() == left_interval) left_painter = pidpnt;
865  else if (pidpnt->GetInterval() == right_interval) right_painter = pidpnt;
866  }
867 
868  // give a different colour to each interval
869  auto nitv = current_interval_set->GetIntervals()->GetEntries();
870  auto cstep = TColor::GetPalette().GetSize() / (nitv + 1);
871 
872  KVPIDIntervalPainter* dummy = new KVPIDIntervalPainter(itv, fLinearHisto, TColor::GetPalette()[cstep * (iint + 1)],
873  left_painter);
874  // set up links between painters
875  if (right_painter) {
876  right_painter->set_left_interval(dummy);
877  dummy->set_right_interval(right_painter);
878  }
879  fPad->cd();
880  dummy->Draw();
881  dummy->Connect("IntMod()", "KVItvFinderDialog", this, "UpdatePIDList()");
882  dummy->SetDisplayLabel(1);
883  dummy->SetCanvas(fCanvas);
884  fItvPaint.Add(dummy);
885 
887 
888  fItvPaint.Execute("Update", "");
889 
890  fCanvas->Modified();
891  fCanvas->Update();
892 
893 }
894 
895 
896 
898 
900 {
901  if (fGrid->GetIntervalSets()->GetSize() == 0) fNextIntervalZ = 1;
902  else fNextIntervalZ = ((interval_set*)fGrid->GetIntervalSets()->Last())->GetZ() + 1;
903  // KVBase::OpenContextMenu("SetNextIntervalZ()",this);
905  UpdateLists();
906 }
907 
908 
909 
911 
913 {
914  KVPIDIntervalPainter* pid = (KVPIDIntervalPainter*)fItvPaint.FindObject(Form("%d_%d", itv->GetZ(), itv->GetA()));
915  itvs->GetIntervals()->Remove(itv);
917  if (remove_fit) {
918  // remove any fits from pad corresponding to intervals
919  KVMultiGaussIsotopeFit::UnDrawGaussian(itvs->GetZ(), itv->GetA(), fPad);
920  }
921 }
922 
923 
924 
926 
928 {
929  std::unique_ptr<TList> list(fIntervalSetListView->GetSelectedObjects());
930  Int_t nSelected = list->GetSize();
931  current_interval_set = nullptr;
932 
933  if (nSelected == 1) {
934  current_interval_set = (interval_set*)list->At(0);
935  list.reset(fIntervalListView->GetSelectedObjects());
936  nSelected = list->GetSize();
937  if (nSelected >= 1) {
938  for (int ii = 0; ii < nSelected; ii++) {
939  interval* itv = (interval*) list->At(ii);
941  }
943  fCanvas->Modified();
944  fCanvas->Update();
945  }
947  }
948  else if (nSelected > 1) {
949  for (int ii = 0; ii < nSelected; ii++) {
950  auto itvs = (interval_set*)list->At(ii);
951  ClearInterval(itvs);
952  }
953  }
954 }
955 
956 
957 
959 
961 {
962  std::unique_ptr<TList> list(fIntervalSetListView->GetSelectedObjects());
963  Int_t nSelected = list->GetSize();
964 
965  current_interval_set = nullptr;
966  if (nSelected == 1) {
967  current_interval_set = (interval_set*)list->At(0);
968 
969  list.reset(fIntervalListView->GetSelectedObjects());
970  nSelected = list->GetSize();
971 
972  if (nSelected == 1) {
973  interval* itv = (interval*) list->At(0);
974  itv->SetA(itv->GetA() + 1);
975  fItvPaint.Execute("Update", "");
976  // change the name of any gaussian in the pad associated with this isotope
977  auto gfit = (TNamed*)fPad->GetPrimitive(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA() - 1));
978  if (gfit) gfit->SetName(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA()));
979  fCanvas->Modified();
980  fCanvas->Update();
981  }
982  else {
983  TIter next_itv(list.get());
984  interval* itv;
985  while ((itv = (interval*)next_itv())) {
986  itv->SetA(itv->GetA() + 1);
987  // change the name of any gaussian in the pad associated with this isotope
988  auto gfit = (TNamed*)fPad->GetPrimitive(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA() - 1));
989  if (gfit) gfit->SetName(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA()));
990  }
991  fItvPaint.Execute("Update", "");
992  fCanvas->Modified();
993  fCanvas->Update();
994  }
995  }
996 }
997 
998 
999 
1001 
1003 {
1004  std::unique_ptr<TList> list(fIntervalSetListView->GetSelectedObjects());
1005  Int_t nSelected = list->GetSize();
1006 
1007  current_interval_set = nullptr;
1008  if (nSelected == 1) {
1009  current_interval_set = (interval_set*)list->At(0);
1010  list.reset(fIntervalListView->GetSelectedObjects());
1011  nSelected = list->GetSize();
1012 
1013  if (nSelected == 1) {
1014  interval* itv = (interval*) list->At(0);
1015  itv->SetA(itv->GetA() - 1);
1016  fItvPaint.Execute("Update", "");
1017  // change the name of any gaussian in the pad associated with this isotope
1018  auto gfit = (TNamed*)fPad->GetPrimitive(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA() + 1));
1019  if (gfit) gfit->SetName(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA()));
1020  fCanvas->Modified();
1021  fCanvas->Update();
1022  }
1023  else {
1024  TIter next_itv(list.get());
1025  interval* itv;
1026  while ((itv = (interval*)next_itv())) {
1027  itv->SetA(itv->GetA() - 1);
1028  // change the name of any gaussian in the pad associated with this isotope
1029  auto gfit = (TNamed*)fPad->GetPrimitive(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA() + 1));
1030  if (gfit) gfit->SetName(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA()));
1031  }
1032  fItvPaint.Execute("Update", "");
1033  fCanvas->Modified();
1034  fCanvas->Update();
1035  }
1036  }
1037 }
1038 
1039 
1040 
1042 
1044 {
1045  fIntervalSetListView->Display(((KVIDZAFromZGrid*)fGrid)->GetIntervalSets());
1046  std::unique_ptr<TList> list(fIntervalSetListView->GetSelectedObjects());
1047  Int_t nSelected = list->GetSize();
1048  interval_set* itvs = 0;
1049  if (nSelected == 1) {
1050  current_interval_set = (interval_set*)list->At(0);
1052  }
1053  else {
1054  current_interval_set = nullptr;
1056  }
1057 }
1058 
1059 
1060 
1063 
1065 {
1066  //fGrid->SetOnlyZId(0);
1067  fGrid->Initialize();
1068  ExportToGrid();
1069 
1071 
1072  fIntervalSetListView->Display(((KVIDZAFromZGrid*)fGrid)->GetIntervalSets());
1073  current_interval_set = nullptr;
1075 
1076  fItvPaint.Clear();
1077  DrawIntervals();
1078 
1079  new KVTestIDGridDialog(gClient->GetDefaultRoot(), gClient->GetDefaultRoot(), 10, 10, fGrid, fHisto);
1080 }
1081 
1082 
1083 
1085 
1087 {
1089  fCanvas->Modified();
1090  fCanvas->Update();
1091 }
1092 
1093 
1094 
1096 
1098 {
1099  fItvPaint.Execute("SetDisplayLabel", "0");
1100  current_interval_set = nullptr;
1102  fCanvas->Modified();
1103  fCanvas->Update();
1104 }
1105 
1106 
1107 
1118 
1120 {
1121  // fit the PID spectrum for the currently selected interval set (Z).
1122  //
1123  // for an interval with N isotopes, we use N gaussians plus an exponential (decreasing)
1124  // background. each gaussian has the same width. the centroids of the gaussians are first
1125  // fixed to the positions of the PID markers, the intensity and width of the peaks
1126  // (plus the background) are fitted.
1127  // then another fit is performed without constraining the centroids.
1128  //
1129  // finally the PID markers (PID of each interval) are modified according to the fitted centroid positions.
1130 
1131  if (!current_interval_set) return;
1132 
1133  KVNumberList alist;
1134  std::vector<double> pidlist;
1136  interval* intvl = nullptr;
1137  while ((intvl = (interval*)nxt_int())) {
1138  alist.Add(intvl->GetA());
1139  pidlist.push_back(intvl->GetPID());
1140  }
1143  alist, pidlist);
1144 
1145  // check user fit parameters
1146  if (mass_fit_parameters.GetBoolValue("Limit range of fit")) {
1147  // if the user's range is not valid for the current interval set, we ignore it
1148  if (mass_fit_parameters.GetDoubleValue("PID min for fit") >= current_interval_set->GetZ() - 0.5
1149  && mass_fit_parameters.GetDoubleValue("PID max for fit") <= current_interval_set->GetZ() + 0.5)
1150  fitfunc.SetFitRange(mass_fit_parameters.GetDoubleValue("PID min for fit"),
1151  mass_fit_parameters.GetDoubleValue("PID max for fit"));
1152 
1153  }
1154  fitfunc.SetSigmaLimits(mass_fit_parameters.GetDoubleValue("Minimum #sigma"),
1155  mass_fit_parameters.GetDoubleValue("Maximum #sigma"));
1156 
1157  fLinearHisto->Fit(&fitfunc, "NR");
1158 
1159  // now release the centroids
1160  fitfunc.ReleaseCentroids();
1161 
1162  fLinearHisto->Fit(&fitfunc, "NRME");
1163 
1164  // remove any previous fit from pad
1165  fitfunc.UnDraw();
1166  // mop up any stray gaussians (from intervals which have been removed)
1167  KVMultiGaussIsotopeFit::UnDrawAnyGaussian(current_interval_set->GetZ(), fPad);
1168 
1169  // draw fit with individual gaussians
1170  fitfunc.DrawFitWithGaussians("same");
1171 
1172  // deactivate intervals for fitted masses
1173  std::unique_ptr<KVSeqCollection> tmp(fItvPaint.GetSubListWithMethod(Form("%d", current_interval_set->GetZ()), "GetZ"));
1174  tmp->Execute("DeactivateIntervals", "");
1175 
1176  // set interval limits according to regions of most probable mass
1177  int most_prob_A = 0;
1178  nxt_int.Reset();
1179  // minimum probability for which isotopes are taken into account
1180  double min_proba = mass_fit_parameters.GetDoubleValue("Minimum probability [%]") / 100.;
1181  double delta_pid = 0.001;
1182  TList accepted_intervals;//any intervals not in this list at the end of the procedure will be removed
1183  for (double pid = fitfunc.GetPIDmin() ; pid <= fitfunc.GetPIDmax(); pid += delta_pid) {
1184  double proba;
1185  auto Amax = fitfunc.GetMostProbableA(pid, proba);
1186  if (proba > min_proba) {
1187  if (most_prob_A) {
1188  if (Amax > most_prob_A) {
1189  //std::cout << pid << " " << Amax << " " << proba << std::endl;
1190  //std::cout << "got PIDmax for A=" << intvl->GetA() << std::endl;
1191  intvl->SetPIDmax(pid - delta_pid);
1192  most_prob_A = Amax;
1193  intvl = (interval*)nxt_int();
1194  while (intvl->GetA() < most_prob_A) {
1195  intvl = (interval*)nxt_int();
1196  }
1197  accepted_intervals.Add(intvl);
1198  intvl->SetPIDmin(pid);
1199  //std::cout << "got PIDmin for A=" << intvl->GetA() << std::endl;
1200  }
1201  }
1202  else {
1203  most_prob_A = Amax;
1204  intvl = (interval*)nxt_int();
1205  while (intvl->GetA() < most_prob_A) {
1206  intvl = (interval*)nxt_int();
1207  }
1208  accepted_intervals.Add(intvl);
1209  intvl->SetPIDmin(pid);
1210  //std::cout << pid << " " << Amax << " " << proba << std::endl;
1211  //std::cout << "got PIDmin for A=" << intvl->GetA() << std::endl;
1212  }
1213  }
1214  else if (most_prob_A) {
1215  intvl->SetPIDmax(pid - delta_pid);
1216  //std::cout << pid << " " << Amax << " " << proba << std::endl;
1217  //std::cout << "got PIDmax for A=" << intvl->GetA() << std::endl;
1218  most_prob_A = 0;
1219  }
1220  }
1221  nxt_int.Reset();
1222 // TList intervals_to_remove;
1223 // while ((intvl = (interval*)nxt_int())) {
1224 // if (!accepted_intervals.FindObject(intvl)) intervals_to_remove.Add(intvl);
1225 // }
1226 // if (intervals_to_remove.GetEntries()) {
1227 // // remove intervals below minimum probability (leave gaussians on display)
1228 // TIter it_rem(&intervals_to_remove);
1229 // while ((intvl = (interval*)it_rem())) remove_interval_from_interval_set(current_interval_set, intvl, false);
1230 // }
1231 // intervals_to_remove.Clear();
1232  int ig(1);
1233  // update PID positions from fitted centroids
1234  nxt_int.Reset();
1235  KVNumberList remaining_gaussians, remaining_alist;
1236  auto vec_alist = alist.GetArray();
1237  while ((intvl = (interval*)nxt_int())) {
1238  // in case we removed some peaks
1239  while (vec_alist[ig - 1] < intvl->GetA()) {
1240  ++ig;
1241  }
1242  intvl->SetPID(fitfunc.GetCentroid(ig));
1243  remaining_gaussians.Add(ig);
1244  remaining_alist.Add(intvl->GetA());
1245  ++ig;
1246  }
1247 // if (intervals_to_remove.GetEntries()) {
1248 // // remove intervals with centroids outside PID limits
1249 // TIter it_rem(&intervals_to_remove);
1250 // while ((intvl = (interval*)it_rem())) remove_interval_from_interval_set(current_interval_set, intvl, false);
1251 // }
1252  UpdatePIDList();
1253  fItvPaint.Execute("Update", "");
1254 
1255  fPad->Modified();
1256  fPad->Update();
1257 
1258  // save results in grid parameters
1259  KVNumberList zlist;
1260  if (fGrid->GetParameters()->HasStringParameter("MASSFITS"))
1261  zlist.Set(fGrid->GetParameters()->GetStringValue("MASSFITS"));
1262  zlist.Add(current_interval_set->GetZ());
1263  fGrid->GetParameters()->SetValue("MASSFITS", zlist.AsString());
1264  TString massfit = Form("MASSFIT_%d", current_interval_set->GetZ());
1265  KVNameValueList fitparams;
1266  fitparams.SetValue("Ng", alist.GetNValues());
1267  fitparams.SetValue("Alist", alist.AsQuotedString());
1268  fitparams.SetValue("PIDmin", fitfunc.GetPIDmin());
1269  fitparams.SetValue("PIDmax", fitfunc.GetPIDmax());
1270  fitparams.SetValue("Bkg_cst", fitfunc.GetBackgroundConstant());
1271  fitparams.SetValue("Bkg_slp", fitfunc.GetBackgroundSlope());
1272  fitparams.SetValue("GausWid", fitfunc.GetGaussianWidth(0));
1273  fitparams.SetValue("PIDvsA_a0", fitfunc.GetPIDvsAfit_a0());
1274  fitparams.SetValue("PIDvsA_a1", fitfunc.GetPIDvsAfit_a1());
1275  fitparams.SetValue("PIDvsA_a2", fitfunc.GetPIDvsAfit_a2());
1276  for (ig = 1; ig <= alist.GetNValues(); ++ig) {
1277  fitparams.SetValue(Form("Norm_%d", ig), fitfunc.GetGaussianNorm(ig));
1278  }
1279  auto sanitized = fitparams.Get().ReplaceAll("=", ":");
1280  fGrid->GetParameters()->SetValue(massfit, sanitized);
1281 }
1282 
1283 
1284 
1287 
1289 {
1290  // Open dialog to modify parameters for multigauss mass fit
1291 
1292  bool cancel = false;
1293  auto dialog = new KVNameValueListGUI(fMain, &mass_fit_parameters, &cancel);
1294  dialog->EnableDependingOnBool("PID min for fit", "Limit range of fit");
1295  dialog->EnableDependingOnBool("PID max for fit", "Limit range of fit");
1296  dialog->DisplayDialog();
1297 }
1298 
1299 
1300 
1303 
1305 {
1306  // Remove fit of currently selected interval set from pad
1307 
1308  if (!current_interval_set) return;
1309 
1310  std::vector<int> alist;
1312  interval* intvl = nullptr;
1313  while ((intvl = (interval*)nxt_int())) {
1314  alist.push_back(intvl->GetA());
1315  }
1317 
1318  fitfunc.UnDraw(fPad);
1319  // mop up any stray gaussians (from intervals which have been removed)
1320  KVMultiGaussIsotopeFit::UnDrawAnyGaussian(current_interval_set->GetZ(), fPad);
1321 
1322  fPad->Modified();
1323  fPad->Update();
1324 }
1325 
1326 
1327 
1329 
1331 {
1332 
1333  if (!fCanvas) return;
1334  if (fCanvas->GetEvent() == kMouseMotion) return;
1335 
1336  switch (fCanvas->GetEvent()) {
1337  case kButton2Up:
1338  FitIsotopes();
1339  break;
1340  case kButton1Double:
1342  break;
1343  case kButton1Shift:
1345  break;
1346  }
1347 
1348 }
1349 
1350 
1351 
1353 
1355 {
1356  std::cout << "Mouse shortcuts : Wheel-click Fit intervals of current Z" << std::endl;
1357  std::cout << " Double-click Set/Unset log scale on Y axis" << std::endl;
1358  std::cout << " Shift-click Add an interval where clicked" << std::endl;
1359 }
1360 
1361 
1362 
1364 
1366 {
1367  interval_set* itvs = fGrid->GetIntervalSet(zz);
1368  if (!itvs) {
1369  itvs = new interval_set(zz, KVIDZAFromZGrid::kIntType);
1370  fGrid->GetIntervalSets()->Add(itvs);
1371  }
1372  else ClearInterval(itvs);
1373 
1374 
1375  if (zz == 1) fLinearHisto->SetAxisRange(0.9, zz + 0.5, "X");
1376  else fLinearHisto->SetAxisRange(zz - 0.5, zz + 0.5, "X");
1377 
1378  int nfound = fSpectrum.Search(fLinearHisto, fSig, "goff", ((zz == 2) ? 0.1 * fRat : fRat));
1379 
1380 #if ROOT_VERSION_CODE > ROOT_VERSION(5,99,01)
1381  Double_t* xpeaks = fSpectrum.GetPositionX();
1382 // Double_t* ypeaks = fSpectrum.GetPositionY();
1383 #else
1384  Float_t* xpeaks = fSpectrum.GetPositionX();
1385 // Float_t* ypeaks = fSpectrum.GetPositionY();
1386 #endif
1387 
1388  nfound = TMath::Min(fNpeaks[zz - 1], nfound);
1389 
1390  int idx[nfound];
1391  TMath::Sort(nfound, xpeaks, idx, 0);
1392 
1393  int zrefs[] = {1, 4, 7, 9, 11, 12, 15, 16, 19, 21, 23, 25, 27, 29, 31, 34, 35, 38, 40, 42, 44, 47, 49, 51, 53};
1394  int zref = zrefs[zz - 1];
1395 
1396  int idref = -1;
1397  for (int p = 0; p < nfound; p++) {
1398  if (abs(xpeaks[idx[p]] - xpeaks[0]) < .0001) idref = p;
1399  }
1400  Info("FindPIDIntervals", "Z=%d : idref = %d ", zz, idref);
1401 
1402  for (int p = 0; p < nfound; p++) {
1403 // Info("FindPIDIntervals","Z=%d : (%.2lf %.2lf) (%d %d) ",zz,xpeaks[p],ypeaks[p],idx[p],p);
1404  double pid = xpeaks[idx[p]];//ff->GetParameter(3 * ii + 1);
1405  itvs->add(zref + (p - idref), pid, pid - 0.05, pid + 0.05);
1406  }
1407 
1408 
1409 }
1410 
1411 
1412 
1414 
1416 {
1417  Double_t result = 0;
1418  int np = par[0];
1419  for (Int_t p = 0; p < np; p++) {
1420  Double_t norm = par[3 * p + 3];
1421  Double_t mean = par[3 * p + 1];
1422  Double_t sigma = par[3 * p + 2];
1423  result += norm * TMath::Gaus(x[0], mean, sigma);
1424  }
1425  return result;
1426 }
1427 
1428 
1430 
1432 {
1433 
1434  if (zmin < 0) zmin = ((KVIDentifier*)fGrid->GetIdentifiers()->First())->GetZ();
1435  if (zmax < 0) zmax = ((KVIDentifier*)fGrid->GetIdentifiers()->Last())->GetZ();
1436 
1437  for (int z = zmin; z <= zmax; z++) FindPIDIntervals(z);
1438 
1439 }
1440 
1441 
1442 
1443 
1444 
1445 
1446 
1447 
1448 
1449 
kMouseMotion
kButton1Double
kButton1Shift
kButton2Up
int Int_t
kVerticalFrame
kHorizontalFrame
float Float_t
double Axis_t
constexpr Bool_t kFALSE
double Double_t
double Stat_t
kGray
kBlack
#define gClient
kFDSave
kDeepCleanup
kLHintsExpandY
kLHintsTop
kLHintsExpandX
kMBNo
kMBYes
kMBIconExclamation
kTextCenterX
kTextLeft
winID h TVirtualViewer3D TVirtualGLPainter p
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 np
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 result
#define gROOT
R__EXTERN TRandom * gRandom
char * Form(const char *fmt,...)
char * StrDup(const char *str)
R__EXTERN TStyle * gStyle
R__EXTERN TSystem * gSystem
static void SetAutoAdd(Bool_t yes=kTRUE)
Definition: KVIDGraph.h:100
static Bool_t GetAutoAdd()
Definition: KVIDGraph.h:106
const Char_t * GetName() const override
Definition: KVIDGraph.cpp:1332
const KVNameValueList * GetParameters() const
Definition: KVIDGraph.h:288
void WriteAsciiFile(const Char_t *filename)
Open, write and close ascii file containing this grid.
Definition: KVIDGraph.cpp:404
const KVList * GetIdentifiers() const
Definition: KVIDGraph.h:298
Hybrid charge & mass identification grid.
void Initialize() override
interval_set * GetIntervalSet(int zint) const
void SetOnlyZId(Bool_t=kTRUE) override
KVList * GetIntervalSets()
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.
Double_t PID
= "real" Z if Zident==kTRUE and Aident==kFALSE, "real" A if Zident==Aident==kTRUE
void Clear(Option_t *opt="") override
Reset to initial values.
Bool_t HasFlag(std::string grid_name, TString flag)
GUI for finding/fixing mass identification intervals.
KVListView * fIntervalListView
void DrawInterval(interval_set *itvs, bool label=0)
KVIDZAFromZGrid * fGrid
TGTransientFrame * fMain
void ClearInterval(interval_set *itvs)
void ProcessIdentification(Int_t zmin=-1, Int_t zmax=-1)
void AddInterval(double pid)
void delete_painter_from_painter_list(KVPIDIntervalPainter *)
TVirtualPad * fPad
void Identify()
KVBase::OpenContextMenu("Identify(double,double)",this);.
void SetFitParameters()
Open dialog to modify parameters for multigauss mass fit.
interval_set * current_interval_set
void FindPIDIntervals(Int_t zz)
KVItvFinderDialog(KVIDZAFromZGrid *gg, TH2 *hh)
KVListView * fIntervalSetListView
static KVNameValueList mass_fit_parameters
for user control of multi-gaussian fit
void RemoveFit()
Remove fit of currently selected interval set from pad.
void ExportToGrid()
Write all PID intervals in grid parameters "PIDRANGE", "PIDRANGE%d", etc.
void TestIdent()
fGrid->SetOnlyZId(0);
void LinearizeHisto(int nbins)
Double_t fpeaks(Double_t *x, Double_t *par)
void remove_interval_from_interval_set(interval_set *itvs, interval *itv, bool remove_fit=true)
KVPIDIntervalPainter * last_drawn_interval
void ZoomOnCanvas()
Display the interval set for a given Z when the user double clicks on it.
Enhanced version of ROOT TGListView widget.
Definition: KVListView.h:146
virtual void SetDataColumns(Int_t ncolumns)
Definition: KVListView.cpp:91
void SetDoubleClickAction(const char *receiver_class, void *receiver, const char *slot)
Definition: KVListView.cpp:210
virtual void Display(const TCollection *l)
Definition: KVListView.h:173
TObject * GetLastSelectedObject() const
Definition: KVListView.h:231
TList * GetSelectedObjects() const
Definition: KVListView.h:245
virtual void RemoveAll()
Definition: KVListView.h:190
void AllowContextMenu(Bool_t on=kTRUE)
Definition: KVListView.h:283
virtual void SetDataColumn(Int_t index, const Char_t *name, const Char_t *method="", Int_t mode=kTextCenterX)
Definition: KVListView.cpp:106
Extended TList class which owns its objects by default.
Definition: KVList.h:28
Function for fitting PID mass spectra.
GUI for setting KVNameValueList parameters.
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
Double_t GetDoubleValue(const Char_t *name) const
void SetValue(const Char_t *name, value_type value)
void RemoveParameter(const Char_t *name)
Bool_t HasStringParameter(const Char_t *name) const
Bool_t GetBoolValue(const Char_t *name) const
KVString Get() const
const Char_t * GetStringValue(const Char_t *name) const
bool Set(const KVString &)
Bool_t HasParameter(const Char_t *name) const
TString GetTStringValue(const Char_t *name) const
Strings used to represent a set of ranges of values.
Definition: KVNumberList.h:85
const Char_t * AsQuotedString() const
const Char_t * AsString(Int_t maxchars=0) const
void Remove(Int_t)
Remove value 'n' from the list.
Int_t GetNValues() const
void Add(Int_t)
Add value 'n' to the list.
void Set(const TString &l)
Definition: KVNumberList.h:135
IntArray GetArray() const
Graphical representation of a PID interval in the KVIDZAFromZGrid mass assignation GUI.
void SetCanvas(TCanvas *cc)
interval * GetInterval() const
void Draw(Option_t *option="") override
void SetDisplayLabel(bool dis=true)
void HighLight(bool hi=true)
void set_right_interval(KVPIDIntervalPainter *i)
void Execute(const char *method, const char *params, Int_t *error=0) override
TObject * First() const override
KVSeqCollection * GetSubListWithMethod(const Char_t *retvalue, const Char_t *method) const
TObject * Remove(TObject *obj) override
Remove object from list.
void Add(TObject *obj) override
TObject * FindObject(const char *name) const override
TObject * Last() const override
Int_t GetSize() const override
void Clear(Option_t *option="") override
TObject * At(Int_t idx) const override
void AddAt(TObject *obj, Int_t idx) override
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition: KVString.h:73
GUI for testing identification grids.
Int_t GetSize() const
virtual void SetFillColor(Color_t fcolor)
virtual void SetLineColor(Color_t lcolor)
virtual void SetMarkerStyle(Style_t mstyle=1)
virtual void SetBottomMargin(Float_t bottommargin)
virtual void SetLeftMargin(Float_t leftmargin)
virtual void SetRightMargin(Float_t rightmargin)
virtual void SetTopMargin(Float_t topmargin)
virtual void UnZoom()
virtual void SetRangeUser(Double_t ufirst, Double_t ulast)
Int_t GetEventX() const override
TVirtualPad * cd(Int_t subpadnumber=0) override
void Update() override
Int_t GetEvent() const override
virtual Int_t GetEntries() const
static const TArrayI & GetPalette()
TGDimension GetDefaultSize() const override
virtual void AddFrame(TGFrame *f, TGLayoutHints *l=nullptr)
void MapSubwindows() override
void SetCleanup(Int_t mode=kLocalCleanup) override
char * fFilename
const char ** fFileTypes
char * fIniDir
virtual void Resize(TGDimension size)
void MapWindow() override
void DontCallClose()
void SetWindowName(const char *name=nullptr) override
virtual TGButton * AddButton(const TGWindow *w, TGPictureButton *button, Int_t spacing=0)
virtual void CenterOnParent(Bool_t croot=kTRUE, EPlacement pos=kCenter)
virtual void RequestFocus()
virtual Int_t GetNbinsY() const
TAxis * GetXaxis()
virtual TFitResultPtr Fit(const char *formula, Option_t *option="", Option_t *goption="", Double_t xmin=0, Double_t xmax=0)
virtual Int_t GetNbinsX() const
TAxis * GetYaxis()
void Draw(Option_t *option="") override
virtual Int_t Fill(const char *name, Double_t w)
virtual void SetAxisRange(Double_t xmin, Double_t xmax, Option_t *axis="X")
virtual Double_t GetBinContent(Int_t bin) const
void Reset()
void Add(TObject *obj) override
TObject * Last() const override
const char * GetName() const override
static TClass * Class()
virtual void Execute(const char *method, const char *params, Int_t *error=nullptr)
void AddExec(const char *name, const char *command) override
Double_t AbsPixeltoX(Int_t px) override
void Modified(Bool_t flag=1) override
void SetLogy(Int_t value=1) override
Int_t GetLogy() const override
Bool_t Connect(const char *signal, const char *receiver_class, void *receiver, const char *slot)
virtual Double_t Uniform(Double_t x1, Double_t x2)
void AdoptCanvas(TCanvas *c)
TCanvas * GetCanvas() const
Int_t GetCanvasWindowId() const
virtual Int_t Search(const TH1 *hist, Double_t sigma=2, Option_t *option="", Double_t threshold=0.05)
Double_t * GetPositionX() const
Ssiz_t Length() const
const char * Data() 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)
void SetOptTitle(Int_t tit=1)
void SetOptStat(Int_t stat=1)
virtual char * ExpandPathName(const char *path)
virtual void Modified(Bool_t flag=1)=0
virtual TList * GetListOfPrimitives() const=0
virtual TVirtualPad * cd(Int_t subpadnumber=0)=0
virtual void Update()=0
virtual TObject * WaitPrimitive(const char *pname="", const char *emode="")=0
virtual TObject * GetPrimitive(const char *name) const=0
void add(int aa, double pid, double pidmin=-1., double pidmax=-1.)
KVList * GetIntervals()
bool SetPID(double pid)
double GetPID()
double GetPIDmin()
void SetPIDmin(double pidmin)
void SetA(int aa)
double GetPIDmax()
void SetPIDmax(double pidmax)
RVec< PromoteType< T > > abs(const RVec< T > &v)
const Double_t sigma
Double_t y[n]
Double_t x[n]
void Info(const char *location, const char *fmt,...)
Double_t Min(Double_t a, Double_t b)
Double_t Gaus(Double_t x, Double_t mean=0, Double_t sigma=1, Bool_t norm=kFALSE)
Int_t Nint(T x)
void Sort(Index n, const Element *a, Index *index, Bool_t down=kTRUE)
const char * fTipText
TGButton * fButton
Bool_t fStayDown
const char * fPixmap
ClassImp(TPyArg)