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 #include "KVIDGridEditor.h"
19 #include "KVInputDialog.h"
21 //ClassImp(interval_painter)
22 
23 // Default values for mass-fit parameters
24 
25 
28 {
29  {"Limit range of fit", false},
30  {"PID min for fit", 0.},
31  {"PID max for fit", 10.},
32  {"Minimum probability [%]", 50.},
33  {"Minimum #sigma", 1.e-2},
34  {"Maximum #sigma", 5.e-2},
35  {"+ve bkg. slope", false}
36 };
37 
38 
39 
43 
44 void KVItvFinderDialog::delete_painter_from_painter_list(KVPIDIntervalPainter* p)
45 {
46  // remove painter from list and modify the 'left_painter' and 'right_painter' references
47  // in any adjacent painters/intervals, then delete painter
48 
49  std::unique_ptr<KVPIDIntervalPainter> _p(p);
50  auto pleft = p->get_left_interval();
51  auto pright = p->get_right_interval();
52  if (pleft) pleft->set_right_interval(pright);
53  if (pright) pright->set_left_interval(pleft);
54  fItvPaint.Remove(p);
55 }
56 
57 
58 
60 
62 {
63  fGrid = gg;
64  fHisto = hh;
65 
66  fPoints = new TGraph;
67  fPoints->SetMarkerStyle(23);
68  fNPoints = 0;
69 
70  gStyle->SetOptStat(0);
71  gStyle->SetOptTitle(0);
72 
73  gROOT->ProcessLine(Form("KVItvFinderDialog* _dummy_itv=(KVItvFinderDialog*)%p", this));
74 
75  fMain = new TGTransientFrame(gClient->GetDefaultRoot(), gClient->GetDefaultRoot(), 10, 10);
76  // Here is the recipe for cleanly closing a window
77  // (see https://root-forum.cern.ch/t/error-in-rootx11errorhandler-baddrawable-quot/8095/6)
78  fMain->Connect("CloseWindow()", "KVItvFinderDialog", this, "DoClose()");
79  fMain->DontCallClose();
80  fMain->SetCleanup(kDeepCleanup);
81  // afterwards, in the destructor do fMain->CloseWindow(), and in DoClose(), do 'delete this'
82 
83  // Default constructor
84  TGHorizontalFrame* fCanvasFrame = new TGHorizontalFrame(fMain, 627, 7000, kHorizontalFrame);
85  // fCanvasFrame->SetBackgroundColor(fColor);
86 
87 
88  TRootEmbeddedCanvas* fRootEmbeddedCanvas615 = new TRootEmbeddedCanvas(0, fCanvasFrame, 800, 440);
89  // to replace the TCanvas in a TRootEmbeddedCanvas, just delete the original like so:
90  // (see https://root-forum.cern.ch/t/error-in-rootx11errorhandler-baddrawable-quot/8095/6)
91  auto WID = fRootEmbeddedCanvas615->GetCanvasWindowId();
92  delete fRootEmbeddedCanvas615->GetCanvas();
93  fCanvas = new TCanvas("c123", 10, 10, WID);
94  fCanvas->AddExec("toto", "if(_dummy_itv)_dummy_itv->HandleKey();");
95  fRootEmbeddedCanvas615->AdoptCanvas(fCanvas);
96  fPad = fCanvas->cd();
97  fCanvas->SetRightMargin(0.02);
98  fCanvas->SetTopMargin(0.02);
99  fCanvas->SetLeftMargin(0.08);
100  fCanvas->SetBottomMargin(0.07);
101 
102  fCanvasFrame->AddFrame(fRootEmbeddedCanvas615, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
103  fMain->AddFrame(fCanvasFrame, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 0, 0, 0, 0));
104 
105  TGVerticalFrame* fControlOscillo = new TGVerticalFrame(fCanvasFrame, 2000, 7000, kVerticalFrame);
106 
107  {
108  const char* xpms[] = {
109  "filesaveas.xpm",
110  "profile_t.xpm",
111  "bld_copy.png",
112  "ed_new.png",
113  "refresh2.xpm",
114  "sm_delete.xpm",
115  "h1_t.xpm",
116  "query_new.xpm",
117  "tb_back.xpm",
118  "bld_colorselect.png",
119  "latex.xpm",
120  "move_cursor.png",
121  0
122  };
123  // toolbar tool tip text
124  const char* tips[] = {
125  "Save intervals in current grid",
126  "Find intervals",
127  "Create a new interval set",
128  "Create a new interval",
129  "Update interval lists",
130  "Remove selected intervals",
131  "Multigauss fit to isotopes in interval set",
132  "Set parameters for fit",
133  "Remove fit from selected interval set",
134  "Test identification",
135  "Set log scale on y axis",
136  "Unzoom the histogram",
137  0
138  };
139  int spacing[] = {
140  5,
141  20,
142  0,
143  0,
144  0,
145  20,
146  50,
147  0,
148  0,
149  50,
150  80,
151  0,
152  0
153  };
154  const char* method[] = {
155  "SaveGrid()",
156  "Identify()",
157  "NewIntervalSet()",
158  "NewInterval()",
159  "UpdateLists()",
160  "RemoveInterval()",
161  "FitIsotopes()",
162  "SetFitParameters()",
163  "RemoveFit()",
164  "TestIdent()",
165  "SetLogy()",
166  "UnzoomHisto()",
167  0
168  };
169  fNbButtons = 0;
170  ToolBarData_t t[50];
171  fToolBar = new TGToolBar(fControlOscillo, 450, 80);
172  int i = 0;
173  while (xpms[i]) {
174  t[i].fPixmap = xpms[i];
175  t[i].fTipText = tips[i];
176  t[i].fStayDown = kFALSE;
177  t[i].fId = i + 1;
178  t[i].fButton = NULL;
179  TGButton* bb = fToolBar->AddButton(fControlOscillo, &t[i], spacing[i]);
180  bb->Connect("Clicked()", "KVItvFinderDialog", this, method[i]);
181  fNbButtons++;
182  i++;
183  }
184  fControlOscillo->AddFrame(fToolBar, new TGLayoutHints(kLHintsTop | kLHintsExpandX));
185  }
186 
187  fIntervalSetListView = new KVListView(interval_set::Class(), fControlOscillo, 450, 200);
188  fIntervalSetListView->SetDataColumns(3);
189  fIntervalSetListView->SetDataColumn(0, "Z", "GetZ", kTextLeft);
190  fIntervalSetListView->SetDataColumn(1, "PIDs", "GetNPID", kTextCenterX);
191  fIntervalSetListView->SetDataColumn(2, "Masses", "GetListOfMasses", kTextLeft);
192  fIntervalSetListView->Connect("SelectionChanged()", "KVItvFinderDialog", this, "DisplayPIDint()");
193  fIntervalSetListView->SetDoubleClickAction("KVItvFinderDialog", this, "ZoomOnCanvas()");
194  fIntervalSetListView->AllowContextMenu(kFALSE);
195  fControlOscillo->AddFrame(fIntervalSetListView, new TGLayoutHints(kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
196 
197  fIntervalListView = new KVListView(interval::Class(), fControlOscillo, 450, 180);
198  fIntervalListView->SetDataColumns(5);
199  fIntervalListView->SetDataColumn(0, "Z", "GetZ", kTextLeft);
200  fIntervalListView->SetDataColumn(1, "A", "GetA", kTextCenterX);
201  fIntervalListView->SetDataColumn(2, "min", "GetPIDmin", kTextCenterX);
202  fIntervalListView->SetDataColumn(3, "pid", "GetPID", kTextCenterX);
203  fIntervalListView->SetDataColumn(4, "max", "GetPIDmax", kTextCenterX);
204 
205 
206 
207  {
208  const char* xpms[] = {
209  "arrow_down.xpm",
210  "arrow_up.xpm",
211  0
212  };
213  const char* tips[] = {
214  "Decrease A by one",
215  "Increase A by one",
216  0
217  };
218  int spacing[] = {
219  120,
220  0,
221  0
222  };
223  const char* method[] = {
224  "MassesDown()",
225  "MassesUp()",
226  0
227  };
228  fNbButtons = 0;
229  ToolBarData_t t[50];
230  fToolBar2 = new TGToolBar(fControlOscillo, 450, 80);
231  int i = 0;
232  while (xpms[i]) {
233  t[i].fPixmap = xpms[i];
234  t[i].fTipText = tips[i];
235  t[i].fStayDown = kFALSE;
236  t[i].fId = i + 1;
237  t[i].fButton = NULL;
238  TGButton* bb = fToolBar2->AddButton(fControlOscillo, &t[i], spacing[i]);
239  bb->Connect("Clicked()", "KVItvFinderDialog", this, method[i]);
240  fNbButtons++;
241  i++;
242  }
243  fControlOscillo->AddFrame(fToolBar2, new TGLayoutHints(kLHintsTop | kLHintsExpandX));
244  }
245 
246  // fCurrentView->ActivateSortButtons();
247  fIntervalListView->Connect("SelectionChanged()", "KVItvFinderDialog", this, "SelectionITVChanged()");
248  // fCurrentView->SetDoubleClickAction("FZCustomFrameManager",this,"ChangeParValue()");
249  fIntervalListView->AllowContextMenu(kFALSE);
250 
251  fControlOscillo->AddFrame(fIntervalListView, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 2, 2, 2));
252 
253  fCanvasFrame->AddFrame(fControlOscillo, new TGLayoutHints(kLHintsExpandY, 0, 0, 0, 0));
254 
255 
256  //layout and display window
257  fMain->MapSubwindows();
258  fMain->Resize(fMain->GetDefaultSize());
259 
260  // position relative to the parent's window
261  fMain->CenterOnParent();
262 
263  fMain->SetWindowName("Masses Identification");
264  fMain->RequestFocus();
265  fMain->MapWindow();
266 
267  fIntervalSetListView->Display(((KVIDZAFromZGrid*)fGrid)->GetIntervalSets());
268  current_interval_set = nullptr;
269  fPad->cd();
270 
271  LinearizeHisto(100);
272  fLinearHisto->SetLineColor(kBlack);
273  fLinearHisto->SetFillColor(kGray + 1);
274  fLinearHisto->Draw("hist");
275 
276  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};
277  for (int ii = 0; ii < 30; ii++) fNpeaks[ii] = tmp[ii];
278 
279  fSig = 0.1;
280  fRat = 0.0001;
281 
282  DrawIntervals();
283  PrintHelp();
284 
285 }
286 
287 
288 
289 
291 
293 {
294  auto list = fIntervalSetListView->GetSelectedObjects();
295  Int_t nSelected = list.GetSize();
296  if (nSelected == 1) {
297  current_interval_set = (interval_set*)list.At(0);
298  fIntervalListView->Display(current_interval_set->GetIntervals());
299  }
300  else {
301  current_interval_set = nullptr;
302  fIntervalListView->RemoveAll();
303  }
305 }
306 
307 
308 
310 
312 {
313  fPad->cd();
314  fItvPaint.Execute("HighLight", "0");
315 
316  if (fIntervalListView->GetLastSelectedObject()) {
317  int zz = ((interval*)fIntervalListView->GetLastSelectedObject())->GetZ();
318  int aa = ((interval*)fIntervalListView->GetLastSelectedObject())->GetA();
319  KVPIDIntervalPainter* painter = (KVPIDIntervalPainter*)fItvPaint.FindObject(Form("%d_%d", zz, aa));
320  if (!painter) Info("SelectionITVChanged", "%d %d not found...", zz, aa);
321  painter->HighLight();
322  }
323  fCanvas->Modified();
324  fCanvas->Update();
325 }
326 
327 
328 
330 
332 {
333  auto list = fIntervalSetListView->GetSelectedObjects();
334  Int_t nSelected = list.GetEntries();
335  if (nSelected == 1) {
336  current_interval_set = (interval_set*)list.At(0);
337  fIntervalListView->Display(current_interval_set->GetIntervals());
338  }
339  else {
340  current_interval_set = nullptr;
341  fIntervalListView->RemoveAll();
342  }
343 }
344 
345 
346 
349 
351 {
352  // Display the interval set for a given Z when the user double clicks on it
353 
354  if (!fIntervalSetListView->GetLastSelectedObject()) {
355  current_interval_set = nullptr;
356  return;
357  }
358  current_interval_set = dynamic_cast<interval_set*>(fIntervalSetListView->GetLastSelectedObject());
359  auto zz = current_interval_set->GetZ();
360 
361  fLinearHisto->GetXaxis()->SetRangeUser(zz - 0.5, zz + 0.5);
362 
363  fItvPaint.Execute("SetDisplayLabel", "0");
364 
365  std::unique_ptr<KVSeqCollection> tmp(fItvPaint.GetSubListWithMethod(Form("%d", zz), "GetZ"));
366 
367  tmp->Execute("SetDisplayLabel", "1");
368 
369  // Check - if no mass fit is displayed, we look to see if the grid has a saved
370  // multigauss fit from a previous session, and if so we display it
372  if (fGrid->GetParameters()->HasParameter(Form("MASSFIT_%d", zz))) {
373  KVString massfit = fGrid->GetParameters()->GetTStringValue(Form("MASSFIT_%d", zz));
374  massfit.ReplaceAll(":", "=");
375  KVNameValueList fitparams;
376  fitparams.Set(massfit);
377  KVMultiGaussIsotopeFit fitfunc(zz, fitparams);
378  fitfunc.DrawFitWithGaussians("same");
379  // deactivate intervals in painter
380  tmp->Execute("DeactivateIntervals", "");
381  }
382  }
383 
384  fCanvas->Modified();
385  fCanvas->Update();
386 }
387 
388 
389 
391 
393 {
394  interval_set* itvs = 0;
395  last_drawn_interval = nullptr;
396  TIter it(fGrid->GetIntervalSets());
397  while ((itvs = (interval_set*)it())) {
398  DrawInterval(itvs);
399  }
400 }
401 
402 
403 
405 
407 {
408  fPad->cd();
409  interval* itv = nullptr;
410  // give a different colour to each interval
411  auto nitv = itvs->GetIntervals()->GetEntries();
412  auto cstep = TColor::GetPalette().GetSize() / (nitv + 1);
413  int i = 1;
414  auto deactivate_intervals = fGrid->GetParameters()->HasParameter(Form("MASSFIT_%d", itvs->GetZ()));
415 
416  TIter itt(itvs->GetIntervals());
417  while ((itv = (interval*)itt())) {
418  KVPIDIntervalPainter* dummy = new KVPIDIntervalPainter(itv, fLinearHisto, TColor::GetPalette()[cstep * i], last_drawn_interval);
419  ++i;
420  if (label) dummy->SetDisplayLabel();
421  if (deactivate_intervals) dummy->DeactivateIntervals();
422  dummy->Draw();
423  dummy->SetCanvas(fCanvas);
424  dummy->Connect("IntMod()", "KVItvFinderDialog", this, "UpdatePIDList()");
425  fItvPaint.Add(dummy);
426  last_drawn_interval = dummy;
427  }
428 }
429 
430 
431 
436 
438 {
439  // empty an interval set, effectively removing it from the interval sets which will be saved with the grid.
440  //
441  // we also remove any previous fits from the grid's parameters
442 
443  std::vector<int> alist;
444  for (int ii = 0; ii < itvs->GetNPID(); ii++) {
445  interval* itv = (interval*)itvs->GetIntervals()->At(ii);
446  KVPIDIntervalPainter* pid = (KVPIDIntervalPainter*)fItvPaint.FindObject(Form("%d_%d", itv->GetZ(), itv->GetA()));
447  delete_painter_from_painter_list(pid);
448  alist.push_back(itv->GetA());
449  }
450  itvs->GetIntervals()->Clear();
451  fIntervalSetListView->RemoveAll();
452  fGrid->RemoveIntervalSet(itvs);
453  UpdateLists();
454  // remove any fit displayed in pad
455  KVMultiGaussIsotopeFit fitfunc(itvs->GetZ(), alist);
456  fitfunc.UnDraw(fPad);
457  // mop up any stray gaussians (from intervals which have been removed)
459 
460  // remove from grid parameters
461  if (fGrid->GetParameters()->HasParameter(Form("MASSFIT_%d", itvs->GetZ()))) {
462  fGrid->GetParameters()->RemoveParameter(Form("MASSFIT_%d", itvs->GetZ()));
463  KVNumberList zlist(fGrid->GetParameters()->GetStringValue("MASSFITS"));
464  zlist.Remove(itvs->GetZ());
465  fGrid->GetParameters()->SetValue("MASSFITS", zlist.AsString());
466  }
467  fCanvas->Modified();
468  fCanvas->Update();
469 }
470 
471 
472 
474 
476 {
477  fLinearHisto = fGrid->LinearizeHistoToPID(fHisto, nbins);
478 }
479 
480 
481 
484 
486 {
487  // KVBase::OpenContextMenu("Identify(double,double)",this);
488  Identify(0.1, 0.001);
489 }
490 
491 
492 
494 
495 void KVItvFinderDialog::Identify(double sigma, double ratio)
496 {
497  fSig = sigma;
498  fRat = ratio;
499 
500  fPad->cd();
501  auto list = fIntervalSetListView->GetSelectedObjects();
502  if (list.IsEmpty()) {
504  for (int ii = 0; ii < fGrid->GetIntervalSets()->GetSize(); ii++) DrawInterval((interval_set*)fGrid->GetIntervalSets()->At(ii), 0);
505  }
506  else {
507  for (int ii = 0; ii < list.GetEntries(); ii++) {
508  interval_set* itvs = (interval_set*) list.At(ii);
509  ProcessIdentification(itvs->GetZ(), itvs->GetZ());
510  DrawInterval(itvs, 0);
511  }
512  }
513 
514  fCanvas->Modified();
515  fCanvas->Update();
516 
517 }
518 
519 
520 
522 
524 {
525  ExportToGrid();
526 
527  TString currentdir(gSystem->ExpandPathName("."));
528 
529  TString fn = fHisto->GetName();
530  fn += ".dat";
531 
532  Int_t ret_code;
533  new TGMsgBox(
534  gClient->GetRoot(),
535  gClient->GetDefaultRoot(),
536  "KVIDGridEditor::SaveCurrentGrid", Form("Do you wat to save the grid here : %s", fn.Data()),
537  kMBIconExclamation, kMBYes | kMBNo, &ret_code
538  );
539 
540  if (ret_code == kMBYes) {
541  fGrid->WriteAsciiFile(Form("%s", fn.Data()));
542  return;
543  }
544 
545  static TString dir(".");
546  const char* filetypes[] = {
547  "ID Grid files", "*.dat",
548  "All files", "*",
549  0, 0
550  };
551  TGFileInfo fi;
552  fi.fFileTypes = filetypes;
553  fi.fIniDir = StrDup(dir);
554  new TGFileDialog(gClient->GetDefaultRoot(), gClient->GetDefaultRoot(), kFDSave, &fi);
555  if (fi.fFilename) {
556  TString filenam(fi.fFilename);
557  if (filenam.Contains("toto")) filenam.ReplaceAll("toto", fGrid->GetName());
558  if (!filenam.Contains('.')) filenam += ".dat";
559  fGrid->WriteAsciiFile(filenam.Data());
560  }
561  dir = fi.fIniDir;
562  fGrid->ReloadPIDRanges();
563 
564  fIntervalSetListView->Display(((KVIDZAFromZGrid*)fGrid)->GetIntervalSets());
565  current_interval_set = nullptr;
566  fIntervalListView->RemoveAll();
567 
568  fItvPaint.Clear();
569  DrawIntervals();
570 }
571 
572 
573 
576 
578 {
579  // Write all PID intervals in grid parameters "PIDRANGE", "PIDRANGE%d", etc.
580 
581  fGrid->ClearPIDIntervals();
582  KVNumberList pids;
583  interval_set* itvs = 0;
584  TIter npid(fGrid->GetIntervalSets());
585  while ((itvs = (interval_set*)npid())) {
586  if (!itvs->GetNPID()) continue;
587  pids.Add(itvs->GetZ());
588  }
589  fGrid->GetParameters()->SetValue("PIDRANGE", pids.AsString());
590 
591  itvs = 0;
592  TIter next(fGrid->GetIntervalSets());
593  while ((itvs = (interval_set*)next())) {
594  if (!itvs->GetNPID()) continue;
595  KVString par = Form("PIDRANGE%d", itvs->GetZ());
596  KVString val = "";
597  interval* itv = 0;
598  TIter ni(itvs->GetIntervals());
599  while ((itv = (interval*)ni())) {
600  val += Form("%d:%lf,%lf,%lf|", itv->GetA(), itv->GetPIDmin(), itv->GetPID(), itv->GetPIDmax());
601  }
602  val.Remove(val.Length() - 1);
603  fGrid->GetParameters()->SetValue(par.Data(), val.Data());
604  }
605 }
606 
607 
608 
610 
612 {
613  auto list = fIntervalSetListView->GetSelectedObjects();
614  if (list.IsEmpty() || list.GetEntries() > 1) {
615  current_interval_set = nullptr;
616  return;
617  }
618 
619  current_interval_set = (interval_set*)list.At(0);
620 
621  fPad->WaitPrimitive("TMarker");
622  auto mm = dynamic_cast<TMarker*>(fPad->GetListOfPrimitives()->Last());
623  assert(mm);
624  double pid = mm->GetX();
625  delete mm;
626 
627  int aa = 0;
628  int iint = 0;
629 
630  // try to guess mass from position (PID)
631  // typical isotope separation in PID is 0.12 (e.g. for carbon isotopes)
632  // assume that PID=z means A=2*Z
633  auto aa_guessstimate = TMath::Nint(current_interval_set->GetZ() * 2 + (pid - current_interval_set->GetZ()) / 0.12);
634 //Info("NewINt","pid = %f guess a=%d",pid,aa_guessstimate);
635  if (!current_interval_set->GetNPID()) {
636  aa = aa_guessstimate;
637  iint = 0;
638  }
639  else if (pid < ((interval*)current_interval_set->GetIntervals()->First())->GetPID()) { // to left of all others
640  aa = ((interval*)current_interval_set->GetIntervals()->First())->GetA() - 1;
641  // NO MORE : use guesstimate as long as it is smaller than A of previously defined interval with largest PID
642  // NOW : use 'aa_guessstimate' only for first interval
643  //Info("NewInt","before first interval, with a=%d",aa+1);
644 // if (aa_guessstimate < aa + 1) aa = aa_guessstimate;
645  iint = 0;
646  }
647  else if (pid > ((interval*)current_interval_set->GetIntervals()->Last())->GetPID()) { // to right of all others
648  aa = ((interval*)current_interval_set->GetIntervals()->Last())->GetA() + 1;
649  // NO MORE : use guesstimate as long as it is larger than A of previously defined interval with smallest PID
650  // NOW : use 'aa_guessstimate' only for first interval
651  //Info("NewInt","after last interval, with a=%d",aa-1);
652 // if (aa_guessstimate > aa - 1) aa = aa_guessstimate;
653  iint = current_interval_set->GetNPID();
654  }
655  else {
656  // look for intervals between which the new one is places
657  for (int ii = 1; ii < current_interval_set->GetNPID(); ii++) {
658  if (pid > ((interval*)current_interval_set->GetIntervals()->At(ii - 1))->GetPID()
659  && pid < ((interval*)current_interval_set->GetIntervals()->At(ii))->GetPID()) {
660  aa = ((interval*)current_interval_set->GetIntervals()->At(ii - 1))->GetA() + 1;
661  // use guesstimate if it is in between masses of adjacent intervals (in terms of PID)
662  if ((aa_guessstimate > (aa - 1)) &&
663  (aa_guessstimate < ((interval*)current_interval_set->GetIntervals()->At(ii))->GetA()))
664  aa = aa_guessstimate;
665  iint = ii;
666  break;
667  }
668  }
669  }
670 
671  interval* itv = new interval(current_interval_set->GetZ(), aa, mm->GetX(), mm->GetX() - 0.05, mm->GetX() + 0.05);
672  current_interval_set->GetIntervals()->AddAt(itv, iint);
673 
674  // find intervals which are now left (smaller mass) and right (higher mass) than this one
675  interval* left_interval = iint > 0 ? (interval*)current_interval_set->GetIntervals()->At(iint - 1) : nullptr;
676  interval* right_interval = iint < current_interval_set->GetIntervals()->GetEntries() - 1 ? (interval*)current_interval_set->GetIntervals()->At(iint + 1) : nullptr;
677  // find the corresponding painters
678  KVPIDIntervalPainter* left_painter{nullptr}, *right_painter{nullptr};
679  TIter next_painter(&fItvPaint);
680  KVPIDIntervalPainter* pidpnt;
681  while ((pidpnt = (KVPIDIntervalPainter*)next_painter())) {
682  if (pidpnt->GetInterval() == left_interval) left_painter = pidpnt;
683  else if (pidpnt->GetInterval() == right_interval) right_painter = pidpnt;
684  }
685 
686  // give a different colour to each interval
687  auto nitv = current_interval_set->GetIntervals()->GetEntries();
688  auto cstep = TColor::GetPalette().GetSize() / (nitv + 1);
689 
690  KVPIDIntervalPainter* dummy = new KVPIDIntervalPainter(itv, fLinearHisto, TColor::GetPalette()[cstep * (iint + 1)],
691  left_painter);
692  // set up links between painters
693  if (right_painter) {
694  right_painter->set_left_interval(dummy);
695  dummy->set_right_interval(right_painter);
696  }
697  fPad->cd();
698  dummy->Draw();
699  dummy->Connect("IntMod()", "KVItvFinderDialog", this, "UpdatePIDList()");
700  dummy->SetDisplayLabel(1);
701  dummy->SetCanvas(fCanvas);
702  fItvPaint.Add(dummy);
703 
704  fIntervalListView->Display(current_interval_set->GetIntervals());
705 
706  fItvPaint.Execute("Update", "");
707 
708  fCanvas->Modified();
709  fCanvas->Update();
710 }
711 
712 
713 
715 
717 {
718  auto list = fIntervalSetListView->GetSelectedObjects();
719  if (list.IsEmpty() || list.GetEntries() > 1) {
720  current_interval_set = nullptr;
721  return;
722  }
723 
724  current_interval_set = (interval_set*)list.At(0);
725 
726  int aa = 0;
727  int iint = 0;
728 
729  // try to guess mass from position (PID)
730  // typical isotope separation in PID is 0.12 (e.g. for carbon isotopes)
731  // assume that PID=z means A=2*Z
732  auto aa_guessstimate = TMath::Nint(current_interval_set->GetZ() * 2 + (pid - current_interval_set->GetZ()) / 0.12);
733 //Info("NewINt","pid = %f guess a=%d",pid,aa_guessstimate);
734  if (!current_interval_set->GetNPID()) {
735  aa = aa_guessstimate;
736  iint = 0;
737  }
738  else if (pid < ((interval*)current_interval_set->GetIntervals()->First())->GetPID()) { // to left of all others
739  aa = ((interval*)current_interval_set->GetIntervals()->First())->GetA() - 1;
740  // NO MORE : use guesstimate as long as it is smaller than A of previously defined interval with largest PID
741  // NOW : use 'aa_guessstimate' only for first interval
742  //Info("NewInt","before first interval, with a=%d",aa+1);
743 // if (aa_guessstimate < aa + 1) aa = aa_guessstimate;
744  iint = 0;
745  }
746  else if (pid > ((interval*)current_interval_set->GetIntervals()->Last())->GetPID()) { // to right of all others
747  aa = ((interval*)current_interval_set->GetIntervals()->Last())->GetA() + 1;
748  // NO MORE : use guesstimate as long as it is larger than A of previously defined interval with smallest PID
749  // NOW : use 'aa_guessstimate' only for first interval
750  //Info("NewInt","after last interval, with a=%d",aa-1);
751 // if (aa_guessstimate > aa - 1) aa = aa_guessstimate;
752  iint = current_interval_set->GetNPID();
753  }
754  else {
755  // look for intervals between which the new one is places
756  for (int ii = 1; ii < current_interval_set->GetNPID(); ii++) {
757  if (pid > ((interval*)current_interval_set->GetIntervals()->At(ii - 1))->GetPID()
758  && pid < ((interval*)current_interval_set->GetIntervals()->At(ii))->GetPID()) {
759  aa = ((interval*)current_interval_set->GetIntervals()->At(ii - 1))->GetA() + 1;
760  // use guesstimate if it is in between masses of adjacent intervals (in terms of PID)
761  if ((aa_guessstimate > (aa - 1)) &&
762  (aa_guessstimate < ((interval*)current_interval_set->GetIntervals()->At(ii))->GetA()))
763  aa = aa_guessstimate;
764  iint = ii;
765  break;
766  }
767  }
768  }
769 
770  interval* itv = new interval(current_interval_set->GetZ(), aa, pid, pid - 0.05, pid + 0.05);
771  current_interval_set->GetIntervals()->AddAt(itv, iint);
772 
773  // find intervals which are now left (smaller mass) and right (higher mass) than this one
774  interval* left_interval = iint > 0 ? (interval*)current_interval_set->GetIntervals()->At(iint - 1) : nullptr;
775  interval* right_interval = iint < current_interval_set->GetIntervals()->GetEntries() - 1 ? (interval*)current_interval_set->GetIntervals()->At(iint + 1) : nullptr;
776  // find the corresponding painters
777  KVPIDIntervalPainter* left_painter{nullptr}, *right_painter{nullptr};
778  TIter next_painter(&fItvPaint);
779  KVPIDIntervalPainter* pidpnt;
780  while ((pidpnt = (KVPIDIntervalPainter*)next_painter())) {
781  if (pidpnt->GetInterval() == left_interval) left_painter = pidpnt;
782  else if (pidpnt->GetInterval() == right_interval) right_painter = pidpnt;
783  }
784 
785  // give a different colour to each interval
786  auto nitv = current_interval_set->GetIntervals()->GetEntries();
787  auto cstep = TColor::GetPalette().GetSize() / (nitv + 1);
788 
789  KVPIDIntervalPainter* dummy = new KVPIDIntervalPainter(itv, fLinearHisto, TColor::GetPalette()[cstep * (iint + 1)],
790  left_painter);
791  // set up links between painters
792  if (right_painter) {
793  right_painter->set_left_interval(dummy);
794  dummy->set_right_interval(right_painter);
795  }
796  fPad->cd();
797  dummy->Draw();
798  dummy->Connect("IntMod()", "KVItvFinderDialog", this, "UpdatePIDList()");
799  dummy->SetDisplayLabel(1);
800  dummy->SetCanvas(fCanvas);
801  fItvPaint.Add(dummy);
802 
803  fIntervalListView->Display(current_interval_set->GetIntervals());
804 
805  fItvPaint.Execute("Update", "");
806 
807  fCanvas->Modified();
808  fCanvas->Update();
809 
810 }
811 
812 
813 
815 
817 {
818  if (fGrid->GetIntervalSets()->GetSize() == 0) fNextIntervalZ = 1;
819  else fNextIntervalZ = ((interval_set*)fGrid->GetIntervalSets()->Last())->GetZ() + 1;
820  // open dialog asking for user to confirm (or change) Z of new interval set
821  bool ok = false; TString myZ; myZ.Form("%d", fNextIntervalZ);
822  new KVInputDialog(fMain, "Enter Z for new set of isotopes:", &myZ, &ok);
823  if(ok && myZ.IsDigit())
824  {
825  fNextIntervalZ = myZ.Atoi();
826  fGrid->AddIntervalSet(new interval_set(fNextIntervalZ, KVIDZAFromZGrid::kIntType));
827  UpdateLists();
828  }
829 }
830 
831 
832 
834 
835 void KVItvFinderDialog::remove_interval_from_interval_set(interval_set* itvs, interval* itv, bool remove_fit)
836 {
837  KVPIDIntervalPainter* pid = (KVPIDIntervalPainter*)fItvPaint.FindObject(Form("%d_%d", itv->GetZ(), itv->GetA()));
838  itvs->GetIntervals()->Remove(itv);
839  delete_painter_from_painter_list(pid);
840  if (remove_fit) {
841  // remove any fits from pad corresponding to intervals
842  KVMultiGaussIsotopeFit::UnDrawGaussian(itvs->GetZ(), itv->GetA(), fPad);
843  }
844 }
845 
846 
847 
849 
851 {
852  auto list = fIntervalSetListView->GetSelectedObjects();
853  Int_t nSelected = list.GetEntries();
854  current_interval_set = nullptr;
855 
856  if (nSelected == 1) {
857  current_interval_set = (interval_set*)list.At(0);
858  list = fIntervalListView->GetSelectedObjects();
859  nSelected = list.GetEntries();
860  if (nSelected >= 1) {
861  for (int ii = 0; ii < nSelected; ii++) {
862  interval* itv = (interval*) list.At(ii);
863  remove_interval_from_interval_set(current_interval_set, itv);
864  }
865  fIntervalListView->Display(current_interval_set->GetIntervals());
866  fCanvas->Modified();
867  fCanvas->Update();
868  }
869  else ClearInterval(current_interval_set);
870  }
871  else if (nSelected > 1) {
872  for (int ii = 0; ii < nSelected; ii++) {
873  auto itvs = (interval_set*)list.At(ii);
874  ClearInterval(itvs);
875  }
876  }
877  gIDGridEditor->ResetGridColors();
878  gIDGridEditor->UpdateViewer();
879 }
880 
881 
882 
884 
886 {
887  auto list = fIntervalSetListView->GetSelectedObjects();
888  Int_t nSelected = list.GetEntries();
889 
890  current_interval_set = nullptr;
891  if (nSelected == 1) {
892  current_interval_set = (interval_set*)list.At(0);
893 
894  list = fIntervalListView->GetSelectedObjects();
895  nSelected = list.GetSize();
896 
897  if (nSelected == 1) {
898  interval* itv = (interval*) list.At(0);
899  itv->SetA(itv->GetA() + 1);
900  fItvPaint.Execute("Update", "");
901  // change the name of any gaussian in the pad associated with this isotope
902  auto gfit = (TNamed*)fPad->GetPrimitive(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA() - 1));
903  if (gfit) gfit->SetName(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA()));
904  fCanvas->Modified();
905  fCanvas->Update();
906  }
907  else {
908  TIter next_itv(&list);
909  interval* itv;
910  while ((itv = (interval*)next_itv())) {
911  itv->SetA(itv->GetA() + 1);
912  // change the name of any gaussian in the pad associated with this isotope
913  auto gfit = (TNamed*)fPad->GetPrimitive(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA() - 1));
914  if (gfit) gfit->SetName(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA()));
915  }
916  fItvPaint.Execute("Update", "");
917  fCanvas->Modified();
918  fCanvas->Update();
919  }
920  }
921 }
922 
923 
924 
926 
928 {
929  auto list = fIntervalSetListView->GetSelectedObjects();
930  Int_t nSelected = list.GetEntries();
931 
932  current_interval_set = nullptr;
933  if (nSelected == 1) {
934  current_interval_set = (interval_set*)list.At(0);
935  list = fIntervalListView->GetSelectedObjects();
936  nSelected = list.GetEntries();
937 
938  if (nSelected == 1) {
939  interval* itv = (interval*) list.At(0);
940  itv->SetA(itv->GetA() - 1);
941  fItvPaint.Execute("Update", "");
942  // change the name of any gaussian in the pad associated with this isotope
943  auto gfit = (TNamed*)fPad->GetPrimitive(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA() + 1));
944  if (gfit) gfit->SetName(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA()));
945  fCanvas->Modified();
946  fCanvas->Update();
947  }
948  else {
949  TIter next_itv(&list);
950  interval* itv;
951  while ((itv = (interval*)next_itv())) {
952  itv->SetA(itv->GetA() - 1);
953  // change the name of any gaussian in the pad associated with this isotope
954  auto gfit = (TNamed*)fPad->GetPrimitive(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA() + 1));
955  if (gfit) gfit->SetName(KVMultiGaussIsotopeFit::get_name_of_isotope_gaussian(itv->GetZ(), itv->GetA()));
956  }
957  fItvPaint.Execute("Update", "");
958  fCanvas->Modified();
959  fCanvas->Update();
960  }
961  }
962 }
963 
964 
965 
967 
969 {
970  fIntervalSetListView->Display(((KVIDZAFromZGrid*)fGrid)->GetIntervalSets());
971  auto list = fIntervalSetListView->GetSelectedObjects();
972  Int_t nSelected = list.GetEntries();
973  interval_set* itvs = 0;
974  if (nSelected == 1) {
975  current_interval_set = (interval_set*)list.At(0);
976  fIntervalListView->Display(current_interval_set->GetIntervals());
977  }
978  else {
979  current_interval_set = nullptr;
980  fIntervalListView->RemoveAll();
981  }
982 }
983 
984 
985 
988 
990 {
991  //fGrid->SetOnlyZId(0);
992  fGrid->Initialize();
993  ExportToGrid();
994 
995  fGrid->ReloadPIDRanges();
996 
997  fIntervalSetListView->Display(((KVIDZAFromZGrid*)fGrid)->GetIntervalSets());
998  current_interval_set = nullptr;
999  fIntervalListView->RemoveAll();
1000 
1001  fItvPaint.Clear();
1002  DrawIntervals();
1003 
1004  new KVTestIDGridDialog(gClient->GetDefaultRoot(), gClient->GetDefaultRoot(), 10, 10, fGrid, fHisto);
1005 }
1006 
1007 
1008 
1010 
1012 {
1013  fCanvas->SetLogy(!fCanvas->GetLogy());
1014  fCanvas->Modified();
1015  fCanvas->Update();
1016 }
1017 
1018 
1019 
1021 
1023 {
1024  fItvPaint.Execute("SetDisplayLabel", "0");
1025  current_interval_set = nullptr;
1026  fLinearHisto->GetXaxis()->UnZoom();
1027  fCanvas->Modified();
1028  fCanvas->Update();
1029 }
1030 
1031 
1032 
1043 
1045 {
1046  // fit the PID spectrum for the currently selected interval set (Z).
1047  //
1048  // for an interval with N isotopes, we use N gaussians plus an exponential (decreasing)
1049  // background. each gaussian has the same width. the centroids of the gaussians are first
1050  // fixed to the positions of the PID markers, the intensity and width of the peaks
1051  // (plus the background) are fitted.
1052  // then another fit is performed without constraining the centroids.
1053  //
1054  // finally the PID markers (PID of each interval) are modified according to the fitted centroid positions.
1055 
1056  if (!current_interval_set) return;
1057 
1058  KVNumberList alist;
1059  std::vector<double> pidlist;
1060  TIter nxt_int(current_interval_set->GetIntervals());
1061  interval* intvl = nullptr;
1062  while ((intvl = (interval*)nxt_int())) {
1063  alist.Add(intvl->GetA());
1064  pidlist.push_back(intvl->GetPID());
1065  }
1066  KVMultiGaussIsotopeFit fitfunc(current_interval_set->GetZ(), current_interval_set->GetNPID(),
1067  current_interval_set->GetZ() - 0.5, current_interval_set->GetZ() + 0.5,
1068  alist, pidlist);
1069 
1070  bool fit_limited = false;
1071  // check user fit parameters
1072  if (mass_fit_parameters.GetBoolValue("Limit range of fit")) {
1073  // if the user's range is not valid for the current interval set, we ignore it
1074  if (mass_fit_parameters.GetDoubleValue("PID min for fit") >= current_interval_set->GetZ() - 0.5
1075  && mass_fit_parameters.GetDoubleValue("PID max for fit") <= current_interval_set->GetZ() + 0.5)
1076  {
1077  fitfunc.SetFitRange(mass_fit_parameters.GetDoubleValue("PID min for fit"),
1078  mass_fit_parameters.GetDoubleValue("PID max for fit"));
1079  fit_limited = true;
1080  }
1081  }
1082  fitfunc.SetSigmaLimits(mass_fit_parameters.GetDoubleValue("Minimum #sigma"),
1083  mass_fit_parameters.GetDoubleValue("Maximum #sigma"));
1084  if(negative_bkg_slope_changed)
1085  fitfunc.PositiveBkgSlope(mass_fit_parameters.GetBoolValue("+ve bkg. slope"));
1086 
1087  fLinearHisto->Fit(&fitfunc, "NR");
1088 
1089  // now release the centroids
1090  fitfunc.ReleaseCentroids();
1091 
1092  fLinearHisto->Fit(&fitfunc, "NRME");
1093 
1094  // if fit was limited to a range, remove the limits
1095  if(fit_limited)
1096  fitfunc.SetFitRange(current_interval_set->GetZ() - 0.5,current_interval_set->GetZ() + 0.5);
1097 
1098  // remove any previous fit from pad
1099  fitfunc.UnDraw();
1100  // mop up any stray gaussians (from intervals which have been removed)
1101  KVMultiGaussIsotopeFit::UnDrawAnyGaussian(current_interval_set->GetZ(), fPad);
1102 
1103  // draw fit with individual gaussians
1104  fitfunc.DrawFitWithGaussians("same");
1105 
1106  // deactivate intervals for fitted masses
1107  std::unique_ptr<KVSeqCollection> tmp(fItvPaint.GetSubListWithMethod(Form("%d", current_interval_set->GetZ()), "GetZ"));
1108  tmp->Execute("DeactivateIntervals", "");
1109 
1110  // set interval limits according to regions of most probable mass
1111  int most_prob_A = 0;
1112  nxt_int.Reset();
1113  intvl = nullptr;
1114  // minimum probability for which isotopes are taken into account
1115  double min_proba = mass_fit_parameters.GetDoubleValue("Minimum probability [%]") / 100.;
1116  double delta_pid = 0.001;
1117  TList accepted_intervals;//any intervals not in this list at the end of the procedure will be removed
1118  for (double pid = fitfunc.GetPIDmin() ; pid <= fitfunc.GetPIDmax(); pid += delta_pid) {
1119  double proba;
1120  auto Amax = fitfunc.GetMostProbableA(pid, proba);
1121  if(!Amax)
1122  continue;
1123  if (proba > min_proba) {
1124  if (most_prob_A) {
1125  if (*Amax > most_prob_A) {
1126  intvl->SetPIDmax(pid - delta_pid);
1127  most_prob_A = *Amax;
1128  intvl = (interval*)nxt_int();
1129  while (intvl->GetA() < most_prob_A) {
1130  intvl = (interval*)nxt_int();
1131  }
1132  accepted_intervals.Add(intvl);
1133  intvl->SetPIDmin(pid);
1134  }
1135  }
1136  else {
1137  most_prob_A = *Amax;
1138  intvl = (interval*)nxt_int();
1139  while (intvl->GetA() < most_prob_A) {
1140  intvl = (interval*)nxt_int();
1141  }
1142  accepted_intervals.Add(intvl);
1143  intvl->SetPIDmin(pid);
1144  }
1145  }
1146  else if (most_prob_A) {
1147  intvl->SetPIDmax(pid - delta_pid);
1148  most_prob_A = 0;
1149  }
1150  }
1151  nxt_int.Reset();
1152  int ig(1);
1153  // update PID positions from fitted centroids
1154  nxt_int.Reset();
1155  KVNumberList remaining_gaussians, remaining_alist;
1156  auto vec_alist = alist.GetArray();
1157  while ((intvl = (interval*)nxt_int())) {
1158  // in case we removed some peaks
1159  while (vec_alist[ig - 1] < intvl->GetA()) {
1160  ++ig;
1161  }
1162  intvl->SetPID(fitfunc.GetCentroid(ig));
1163  remaining_gaussians.Add(ig);
1164  remaining_alist.Add(intvl->GetA());
1165  ++ig;
1166  }
1167  UpdatePIDList();
1168  fItvPaint.Execute("Update", "");
1169 
1170  fPad->Modified();
1171  fPad->Update();
1172 
1173  // save results in grid parameters
1174  KVNumberList zlist;
1175  if (fGrid->GetParameters()->HasStringParameter("MASSFITS"))
1176  zlist.Set(fGrid->GetParameters()->GetStringValue("MASSFITS"));
1177  zlist.Add(current_interval_set->GetZ());
1178  fGrid->GetParameters()->SetValue("MASSFITS", zlist.AsString());
1179  TString massfit = Form("MASSFIT_%d", current_interval_set->GetZ());
1180  KVNameValueList fitparams;
1181  fitparams.SetValue("Ng", alist.GetNValues());
1182  fitparams.SetValue("Alist", alist.AsQuotedString());
1183  fitparams.SetValue("PIDmin", fitfunc.GetPIDmin());
1184  fitparams.SetValue("PIDmax", fitfunc.GetPIDmax());
1185  fitparams.SetValue("Bkg_cst", fitfunc.GetBackgroundConstant());
1186  fitparams.SetValue("Bkg_slp", fitfunc.GetBackgroundSlope());
1187  fitparams.SetValue("GausWid", fitfunc.GetGaussianWidth(0));
1188  fitparams.SetValue("PIDvsA_a0", fitfunc.GetPIDvsAfit_a0());
1189  fitparams.SetValue("PIDvsA_a1", fitfunc.GetPIDvsAfit_a1());
1190  fitparams.SetValue("PIDvsA_a2", fitfunc.GetPIDvsAfit_a2());
1191  for (ig = 1; ig <= alist.GetNValues(); ++ig) {
1192  fitparams.SetValue(Form("Norm_%d", ig), fitfunc.GetGaussianNorm(ig));
1193  }
1194  auto sanitized = fitparams.Get().ReplaceAll("=", ":");
1195  fGrid->GetParameters()->SetValue(massfit, sanitized);
1196  gIDGridEditor->ResetGridColors();
1197  gIDGridEditor->UpdateViewer();
1198 }
1199 
1200 
1201 
1204 
1206 {
1207  // Open dialog to modify parameters for multigauss mass fit
1208 
1209  bool cancel = false;
1210  auto bkg_slope = mass_fit_parameters.GetBoolValue("+ve bkg. slope");
1211  auto dialog = new KVNameValueListGUI(fMain, &mass_fit_parameters, &cancel);
1212  dialog->EnableDependingOnBool("PID min for fit", "Limit range of fit");
1213  dialog->EnableDependingOnBool("PID max for fit", "Limit range of fit");
1214  dialog->DisplayDialog();
1215  negative_bkg_slope_changed = (mass_fit_parameters.GetBoolValue("+ve bkg. slope") != bkg_slope);
1216 }
1217 
1218 
1219 
1222 
1224 {
1225  // Remove fit of currently selected interval set from pad
1226 
1227  if (!current_interval_set) return;
1228 
1229  std::vector<int> alist;
1230  TIter nxt_int(current_interval_set->GetIntervals());
1231  interval* intvl = nullptr;
1232  while ((intvl = (interval*)nxt_int())) {
1233  alist.push_back(intvl->GetA());
1234  }
1235  KVMultiGaussIsotopeFit fitfunc(current_interval_set->GetZ(), alist);
1236 
1237  fitfunc.UnDraw(fPad);
1238  // mop up any stray gaussians (from intervals which have been removed)
1239  KVMultiGaussIsotopeFit::UnDrawAnyGaussian(current_interval_set->GetZ(), fPad);
1240 
1241  fPad->Modified();
1242  fPad->Update();
1243 }
1244 
1245 
1246 
1248 
1250 {
1251 
1252  if (!fCanvas) return;
1253  if (fCanvas->GetEvent() == kMouseMotion) return;
1254 
1255  switch (fCanvas->GetEvent()) {
1256  case kButton2Up:
1257  FitIsotopes();
1258  break;
1259  case kButton1Double:
1260  fCanvas->SetLogy(!fCanvas->GetLogy());
1261  break;
1262  case kButton1Shift:
1263  AddInterval(fCanvas->AbsPixeltoX(fCanvas->GetEventX()));
1264  break;
1265  }
1266 
1267 }
1268 
1269 
1270 
1272 
1274 {
1275  std::cout << "Mouse shortcuts : Wheel-click Fit intervals of current Z" << std::endl;
1276  std::cout << " Double-click Set/Unset log scale on Y axis" << std::endl;
1277  std::cout << " Shift-click Add an interval where clicked" << std::endl;
1278 }
1279 
1280 
1281 
1283 
1285 {
1286  interval_set* itvs = fGrid->GetIntervalSet(zz);
1287  if (!itvs) {
1288  itvs = new interval_set(zz, KVIDZAFromZGrid::kIntType);
1289  fGrid->AddIntervalSet(itvs);
1290  }
1291  else ClearInterval(itvs);
1292 
1293 
1294  if (zz == 1) fLinearHisto->SetAxisRange(0.9, zz + 0.5, "X");
1295  else fLinearHisto->SetAxisRange(zz - 0.5, zz + 0.5, "X");
1296 
1297  int nfound = fSpectrum.Search(fLinearHisto, fSig, "goff", ((zz == 2) ? 0.1 * fRat : fRat));
1298 
1299 #if ROOT_VERSION_CODE > ROOT_VERSION(5,99,01)
1300  Double_t* xpeaks = fSpectrum.GetPositionX();
1301 // Double_t* ypeaks = fSpectrum.GetPositionY();
1302 #else
1303  Float_t* xpeaks = fSpectrum.GetPositionX();
1304 // Float_t* ypeaks = fSpectrum.GetPositionY();
1305 #endif
1306 
1307  nfound = TMath::Min(fNpeaks[zz - 1], nfound);
1308 
1309  int idx[nfound];
1310  TMath::Sort(nfound, xpeaks, idx, 0);
1311 
1312  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};
1313  int zref = zrefs[zz - 1];
1314 
1315  int idref = -1;
1316  for (int p = 0; p < nfound; p++) {
1317  if (std::abs(xpeaks[idx[p]] - xpeaks[0]) < .0001) idref = p;
1318  }
1319  Info("FindPIDIntervals", "Z=%d : idref = %d ", zz, idref);
1320 
1321  for (int p = 0; p < nfound; p++) {
1322 // Info("FindPIDIntervals","Z=%d : (%.2lf %.2lf) (%d %d) ",zz,xpeaks[p],ypeaks[p],idx[p],p);
1323  double pid = xpeaks[idx[p]];//ff->GetParameter(3 * ii + 1);
1324  itvs->add(zref + (p - idref), pid, pid - 0.05, pid + 0.05);
1325  }
1326 
1327 
1328 }
1329 
1330 
1331 
1333 
1335 {
1336  Double_t result = 0;
1337  int np = par[0];
1338  for (Int_t p = 0; p < np; p++) {
1339  Double_t norm = par[3 * p + 3];
1340  Double_t mean = par[3 * p + 1];
1341  Double_t sigma = par[3 * p + 2];
1342  result += norm * TMath::Gaus(x[0], mean, sigma);
1343  }
1344  return result;
1345 }
1346 
1347 
1349 
1351 {
1352 
1353  if (zmin < 0) zmin = ((KVIDentifier*)fGrid->GetIdentifiers()->First())->GetZ();
1354  if (zmax < 0) zmax = ((KVIDentifier*)fGrid->GetIdentifiers()->Last())->GetZ();
1355 
1356  for (int z = zmin; z <= zmax; z++) FindPIDIntervals(z);
1357 
1358 }
1359 
1360 
1361 
1362 
1363 
1364 
1365 
1366 
1367 
1368 
kMouseMotion
kButton1Double
kButton1Shift
kButton2Up
int Int_t
kVerticalFrame
kHorizontalFrame
float Float_t
constexpr Bool_t kFALSE
double Double_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
char * Form(const char *fmt,...)
char * StrDup(const char *str)
R__EXTERN TStyle * gStyle
R__EXTERN TSystem * gSystem
const Char_t * GetName() const override
Definition: KVIDGraph.cpp:1416
const KVNameValueList * GetParameters() const
Definition: KVIDGraph.h:362
void WriteAsciiFile(const Char_t *filename)
Open, write and close ascii file containing this grid.
Definition: KVIDGraph.cpp:408
const KVList * GetIdentifiers() const
Definition: KVIDGraph.h:372
Hybrid charge & mass identification grid.
const KVList * GetIntervalSets() const
void Initialize() override
interval_set * GetIntervalSet(int zint) const
void AddIntervalSet(interval_set *)
add an interval set to the grid, updating the corresponding parameters
TH1 * LinearizeHistoToPID(const TH2 *hdata, int nbins=100) const override
void RemoveIntervalSet(int zint)
Remove interval set for given Z from grid.
Base class for graphical cuts used in particle identification.
Definition: KVIDentifier.h:28
General purpose dialog box asking for some input in the form of a string.
Definition: KVInputDialog.h:24
GUI for finding/fixing mass identification intervals.
void DrawInterval(interval_set *itvs, bool label=0)
void ClearInterval(interval_set *itvs)
void ProcessIdentification(Int_t zmin=-1, Int_t zmax=-1)
void AddInterval(double pid)
void Identify()
KVBase::OpenContextMenu("Identify(double,double)",this);.
void SetFitParameters()
Open dialog to modify parameters for multigauss mass fit.
void FindPIDIntervals(Int_t zz)
KVItvFinderDialog(KVIDZAFromZGrid *gg, TH2 *hh)
static KVNameValueList mass_fit_parameters
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 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:147
virtual void SetDataColumns(Int_t ncolumns)
Definition: KVListView.cpp:92
void SetDoubleClickAction(const char *receiver_class, void *receiver, const char *slot)
Definition: KVListView.cpp:211
virtual void Display(const TCollection *l)
Definition: KVListView.h:174
KVUnownedList GetSelectedObjects() const
Definition: KVListView.h:253
TObject * GetLastSelectedObject() const
Definition: KVListView.h:239
virtual void RemoveAll()
Definition: KVListView.h:194
void AllowContextMenu(Bool_t on=kTRUE)
Definition: KVListView.h:292
virtual void SetDataColumn(Int_t index, const Char_t *name, const Char_t *method="", Int_t mode=kTextCenterX)
Definition: KVListView.cpp:107
Function for fitting PID mass spectra.
static TString get_name_of_isotope_gaussian(int z, int a)
static TString get_name_of_multifit(int z)
double GetGaussianWidth(int) const
static void UnDrawAnyGaussian(int z, TVirtualPad *pad=gPad)
Remove the graphical representation of any gaussian for this Z from the given pad.
void DrawFitWithGaussians(Option_t *opt="", const TString &fit_title="") const
void SetSigmaLimits(double smin, double smax)
void PositiveBkgSlope(bool yes=true)
void SetFitRange(double min, double max)
Change range of fit.
std::optional< int > GetMostProbableA(double PID, double &P) const
double GetGaussianNorm(int i) const
void ReleaseCentroids()
Release the constraint on the positions of the centroids.
void UnDraw(TVirtualPad *pad=gPad) const
Remove the graphical representation of this fit from the given pad.
static void UnDrawGaussian(int z, int a, TVirtualPad *pad=gPad)
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:86
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:136
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()
TAxis * GetXaxis()
virtual TFitResultPtr Fit(const char *formula, Option_t *option="", Option_t *goption="", Double_t xmin=0, Double_t xmax=0)
void Draw(Option_t *option="") override
virtual void SetAxisRange(Double_t xmin, Double_t xmax, Option_t *axis="X")
void Reset()
void Add(TObject *obj) override
TObject * Last() const override
const char * GetName() const override
static TClass * Class()
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)
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
Int_t Atoi() const
const char * Data() const
Bool_t IsDigit() const
void Form(const char *fmt,...)
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)
const Double_t sigma
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)