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