GammaWare  Head Version for release 0.9
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MatPlayer.cpp
Go to the documentation of this file.
1 //
2 //
3 // MatPlayer Version 0.1
4 // MatPlayer is used to analyse a 2D histogram by putting gates interactively.
5 //
6 // A MatPlayer object must be connected to a TCanvas and a TH2D histogram. It is done by using SetCanvas & SetMatrix.
7 // Once a canvas and a matrix has been linked, any key pressed on the defined canvas gives a gate (TBox) that can be
8 // modify graphically. The gates on the current canvas are use to
9 //
10 // Olivier Stezowski -
11 //
12 //
13 //
14 
15 //#ifndef __CINT__
16 
17 /*
18 #ifndef ROOT_KeySymbols
19 #include "RTypes.h"
20 #endif
21 
22 #ifndef ROOT_TROOT
23 #include "TROOT.h"
24 #endif
25 
26 #ifndef ROOT_TROOT
27 #include <TFrame.h>
28 #endif
29 
30 #ifndef ROOT_TApplication
31 #include "TApplication.h"
32 #endif
33 
34 #ifndef ROOT_TString
35 #include "TString.h"
36 #endif
37 
38 */
39 
40 #include "KeySymbols.h"
41 
42 #ifndef ROOT_TStyle
43 #include "TStyle.h"
44 #endif
45 
46 #ifndef ROOT_TCanvas
47 #include "TCanvas.h"
48 #endif
49 
50 #ifndef ROOT_TSpectrum
51 #include "TSpectrum.h"
52 #endif
53 
54 #ifndef ROOT_TFrame
55 #include "TFrame.h"
56 #endif
57 
58 #ifndef ROOT_TROOT
59 #include "TROOT.h"
60 #endif
61 
62 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
63 #include "TMath.h"
64 #endif
65 
66 #ifndef GW_MATPLAYER_H
67 #include "MatPlayer.h"
68 #endif
69 
70 using namespace std;
71 using namespace Gw;
72 
74 
75 Int_t MatPlayer::fLastX = 0, MatPlayer::fLastY = 0; TList *MatPlayer::fgPlayers = NULL;
76 
77 MatPlayer::MatPlayer() : TNamed("Matplayer","To set gates interactively in a Canvas")
78 {
79 // constructor
80  fMat = NULL; fPx = fPy = fTotx = fToty = fBx = fBy = NULL;
81 
82  fLastGates.SetOwner(kTRUE);
83  // fGatesY.SetOwner(kTRUE); fGatesBX.SetOwner(kTRUE); fGatesBY.SetOwner(kTRUE);
84 
85  gStyle->SetOptStat(0);
86 
87  fStep.first = fStep.second = 1.0;
88 
89  fWidthGate.first = new TFormula("MatPlayer_WX","pol0"); fWidthGate.first->SetParameter(0,2.5);
90  fWidthGate.second = new TFormula("MatPlayer_WY","pol0"); fWidthGate.second->SetParameter(0,2.5);
91 
92  fBoxX.SetFillColor(2); fBoxX.SetFillStyle(3002);
93  fBoxY.SetFillColor(4); fBoxY.SetFillStyle(3013);
94  fBoxBX.SetFillColor(16); fBoxBX.SetFillStyle(3016);
95  fBoxBY.SetFillColor(16); fBoxBY.SetFillStyle(3020);
96 
97  if ( fgPlayers == NULL ) { fgPlayers = new TList(); fgPlayers->SetOwner(kTRUE); }
98  fgPlayers->Add(this);
99 }
100 
102 {
103 // destructor
104  Clear();
105  if ( fWidthGate.first ) delete fWidthGate.first; if (fWidthGate.second ) delete fWidthGate.second;
106 
107  fgPlayers->Remove(this);
108 }
109 
110 void MatPlayer::Clear(const Option_t */*opt*/)
111 {
112  if ( fTotx ) delete fTotx; fTotx = NULL; if ( fToty ) delete fToty; fToty = NULL;
113 
114  if ( fPx ) delete fPx; fPx = NULL; if ( fPy ) delete fPy; fPy = NULL;
115  if ( fBx ) delete fBx; fBx = NULL; if ( fBy ) delete fBy; fBy = NULL;
116 }
117 
119 {
120 // to connect the current canvas to the interactive gating
121  TVirtualPad *pad = TVirtualPad::Pad(); TCanvas *c = NULL;
122 
123  if ( pad ) {
124  c = pad->GetCanvas();
125  c->Clear(); c->Divide(1,1,0.001,0.001); c->cd(1);
126  }
127  else {
128  if ( (c = dynamic_cast<TCanvas *>(gROOT->GetListOfCanvases()->FindObject("DefaultMatPlayer"))) == NULL ) {
129  c = new TCanvas("DefaultMatPlayer","Canvas to interact with MatPlayer",1);
130  c->Divide(1,1,0.001,0.001); c->cd(1);
131  }
132  }
133 
134  c->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
135  "Gw::MatPlayer",this,"XEventAction(Int_t,Int_t,Int_t,TObject*)");
136 
137  cout << " - Info - Interactive gating (by pressing any key) is now possible on any pad of the canvas " << c->GetName() << endl;
138 }
139 
140 void MatPlayer::SetMatrix(const char *matname)
141 {
142  TObject *obj = gDirectory->Get(matname);
143  if ( obj == NULL ) {
144  cout << "Cannot find matrix named " << matname << " in the current TDirectory " << endl;
145  } else {
146  if ( obj->InheritsFrom("TH2") ) {
147  SetMatrix(dynamic_cast<TH2 *>(obj)); SetName(obj->GetName());
148  }
149  else
150  cout << "Object named " << matname << " is not a matrix !! " << endl;
151  }
152 }
153 
154 void MatPlayer::SetMatrix(TH2 *mat)
155 {
156  TString hname; TH1D *Px, *Py, *Bx, *By, *Totx, *Toty;
157 
158 // nothing checked to avoid wrong pointers for mat .. except that this function is private
159  if ( fMat == mat ) return;
160 
161  fMat = mat; Totx = Toty = Px = Py = Bx = By = NULL;
162 
163 // it creates necessary histograms (or checks if they already exist) from mat on the same location (TDirectory) than the matrix
164  if ( mat->GetDirectory() ) { // mat belongs to a TDirectory .. so check if the histograms have already been created
165  hname = mat->GetName(); hname += "_tx" ;
166  Totx = dynamic_cast<TH1D *>( mat->GetDirectory()->Get(hname.Data()) );
167  hname = mat->GetName(); hname += "_ty" ;
168  Toty = dynamic_cast<TH1D *>( mat->GetDirectory()->Get(hname.Data()) );
169  hname = mat->GetName(); hname += "_px" ;
170  Px = dynamic_cast<TH1D *>( mat->GetDirectory()->Get(hname.Data()) );
171  hname = mat->GetName(); hname += "_py" ;
172  Py = dynamic_cast<TH1D *>( mat->GetDirectory()->Get(hname.Data()) );
173  hname = mat->GetName(); hname += "_bx" ;
174  Bx = dynamic_cast<TH1D *>( mat->GetDirectory()->Get(hname.Data()) );
175  hname = mat->GetName(); hname += "_by" ;
176  By = dynamic_cast<TH1D *>( mat->GetDirectory()->Get(hname.Data()) );
177  }
178  // histograms to store full projection
179  if ( Totx == NULL ) { hname = mat->GetName(); hname += "_tx"; Totx = mat->ProjectionX(hname.Data()); }
180  if ( Toty == NULL ) { hname = mat->GetName(); hname += "_ty"; Toty = mat->ProjectionY(hname.Data()); }
181 
182  // histograms to store gated spectra
183  if ( Px == NULL ) { hname = mat->GetName(); hname += "_px"; Px = (TH1D *)Totx->Clone(hname.Data()); Px->Reset("ICE"); }
184  if ( Py == NULL ) { hname = mat->GetName(); hname += "_py"; Py = (TH1D *)Toty->Clone(hname.Data()); Py->Reset("ICE"); }
185 
186  // histograms to store background spectra
187  if ( Bx == NULL ) hname = mat->GetName(); hname += "_bx"; Bx = (TH1D *)Totx->Clone(hname.Data()); Bx->Reset("ICE");
188  if ( By == NULL ) hname = mat->GetName(); hname += "_by"; By = (TH1D *)Toty->Clone(hname.Data()); By->Reset("ICE");
189 
190 // now keep a local copy protected from delete
191  // remove previous projection
192  Clear();
193 
194  // clone local histograms and set directory to NULL
195  fPx = dynamic_cast<TH1D *>( Px->Clone("MatPlayer_px") ); fPx->SetDirectory(0);
196  fPy = dynamic_cast<TH1D *>( Py->Clone("MatPlayer_py") ); fPy->SetDirectory(0);
197  fBx = dynamic_cast<TH1D *>( Bx->Clone("MatPlayer_bx") ); fBx->SetDirectory(0);
198  fBy = dynamic_cast<TH1D *>( By->Clone("MatPlayer_by") ); fBy->SetDirectory(0);
199 
200  fTotx = dynamic_cast<TH1D *>( Totx->Clone("MatPlayer_tx") ); fTotx->SetDirectory(0);
201  fToty = dynamic_cast<TH1D *>( Toty->Clone("MatPlayer_ty") ); fToty->SetDirectory(0);
202 
203  Totx->Draw();
204 }
205 
206 Double_t MatPlayer::GetWidthGate(Double_t pos, Option_t *o)
207 {
208  TString opt = o;
209  if ( opt.Contains("Gx") ) return fWidthGate.first->Eval(pos);
210  else return fWidthGate.second->Eval(pos);
211 }
212 
213 void MatPlayer::SetGateX(Option_t *o)
214 {
215  Double_t posx, posy;
216  bool isTH2; TString opt = o; Double_t w, x1, x2, y1, y2; TH1 *hist; TObject *obj; TFrame *frame;
217 
218  // check for a valid TPad and the first histogram
219  TVirtualPad *pad = TVirtualPad::Pad(); if ( pad == NULL ) return;
220  posx = pad->PadtoX(pad->AbsPixeltoX(fLastX));
221  posy = pad->PadtoY(pad->AbsPixeltoY(fLastY));
222 
223  TIter next(pad->GetListOfPrimitives()); // look for an histogram
224  frame = pad->GetFrame();
225  isTH2 = false;
226  hist = NULL;
227  while ( (obj = next()) ) {
228  if ( obj->InheritsFrom("TH1") ) {
229  hist = dynamic_cast<TH1 *>(obj); if ( obj->InheritsFrom("TH2") ) isTH2 = true; break; }
230  }
231  if ( hist == NULL || frame == NULL ) { cout << "Cannot add a gate, no spectrum selected " << endl; return; }
232 
233  // default is a horizontal gate on X
234  TBox *box = &fBoxX;
235  w = GetWidthGate(posx,"Gx");
236  x1 = posx-w/2.0; y1 = frame->GetY1(); x2 = posx+w/2.0; y2 = frame->GetY2();
237 
238  // gate on Y depends if the histogram is a 1D or 2D histogram
239  if ( opt.Contains("Gy") ) {
240  box = &fBoxY;
241  if ( isTH2 ) { // horizontal gate
242  w = GetWidthGate(posy,"Gy");
243  x1 = frame->GetX1(); y1 = posy-w/2.0; x2 = frame->GetX2(); y2 =posy+w/2.0;
244  }
245  else { // vertical gate
246  w = GetWidthGate(posx,"Gy");
247  x1 = posx-w/2.0; y1 = frame->GetY1(); x2 = posx+w/2.0; y2 = frame->GetY2();
248  }
249  }
250  if ( opt.Contains("Bx") ) {
251  box = &fBoxBX; w = GetWidthGate(posx,"Gx");
252  x1 = posx-w/2.0; y1 = frame->GetY1(); x2 = posx+w/2.0; y2 = frame->GetY2();
253  }
254  if ( opt.Contains("By") ) {
255  box = &fBoxBY;
256  if ( isTH2 ) { // horizontal gate
257  w = GetWidthGate(posy,"Gy");
258  x1 = frame->GetX1(); y1 = posy-w/2.0; x2 = frame->GetX2(); y2 =posy+w/2.0;
259  }
260  else { // vertical gate
261  w = GetWidthGate(posx,"Gy");
262  x1 = posx-w/2.0; y1 = frame->GetY1(); x2 = posx+w/2.0; y2 = frame->GetY2();
263  }
264  }
265 
266  // Add one gates
267  box->DrawBox(x1,y1,x2,y2); pad->Update();
268 }
269 
270 bool MatPlayer::IsBox(const TBox *box, const TBox *boxref) const
271 {
272  return ( box->GetFillStyle() == boxref->GetFillStyle() && box->GetFillColor() == boxref->GetFillColor() );
273 }
274 
275 Int_t MatPlayer::InitGating(Option_t *o)
276 {
277 // Init gating - It looks in the current pad for gates (boxes) with the good characteristics (color and fill style).
278 // It returns the number of gates found
279 
280  TObject *obj; TString opt = o;
281 
282  if ( TVirtualPad::Pad() == NULL ) return 0;
283 
284  TIter next(TVirtualPad::Pad()->GetListOfPrimitives()); // look for an histogram
285  bool isTH2 = false, overlap;
286  while ( (obj = next()) ) {
287  if ( obj->InheritsFrom("TH1") ) {
288  if ( obj->InheritsFrom("TH2") ) isTH2 = true; break; }
289  } // while
290 
291 // look for gates and cuts and prepare them for gating
292  TBox *boxnew, *boxadd ; fLastGates.Delete(); // remove previous gates
293 
294  // re-start iteration and look for the right gates
295  next.Reset();
296  while ( (boxnew = (TBox *)next()) ) { // look for a box and keep a copy that can be i=used for gating
297  if ( boxnew->InheritsFrom("TBox") && opt.Contains("x") ) {
298  // Gate on X
299  if ( IsBox(boxnew,&fBoxX) ) {
300  // look for an existing gate that overlaps this one
301  TIter existing(&fLastGates);
302  overlap = false;
303  while ( (boxadd = (TBox *)existing()) ) {
304  if ( (boxnew->GetX1() >= boxadd->GetX1() && boxnew->GetX1() <= boxadd->GetX2()) ||
305  (boxnew->GetX2() >= boxadd->GetX1() && boxnew->GetX2() <= boxadd->GetX2()) ) { overlap = true; break; }
306  }
307  if ( overlap == false ) { fLastGates.Add(boxnew->Clone()); } // new gate or
308  else { // change current box settings
309  boxadd->SetX1( TMath::Min(boxadd->GetX1(),boxnew->GetX1()) );
310  boxadd->SetX2( TMath::Max(boxadd->GetX2(),boxnew->GetX2()) );
311  }
312  }
313  // Background gate on X
314  if ( IsBox(boxnew,&fBoxBX) ) {
315  // look for an existing gate that overlaps this one
316  TIter existing(&fLastGates);
317  overlap = false;
318  while ( (boxadd = (TBox *)existing()) ) {
319  if ( (boxnew->GetX1() >= boxadd->GetX1() && boxnew->GetX1() <= boxadd->GetX2()) ||
320  (boxnew->GetX2() >= boxadd->GetX1() && boxnew->GetX2() <= boxadd->GetX2()) ) { overlap = kTRUE; break; }
321  }
322  if ( overlap == false ) { fLastGates.Add(boxnew->Clone()); } // new gate or
323  else { // change current box settings
324  boxadd->SetX1( TMath::Min(boxadd->GetX1(),boxnew->GetX1()) );
325  boxadd->SetX2( TMath::Max(boxadd->GetX2(),boxnew->GetX2()) );
326  }
327  }
328  } // x
329  if ( boxnew->InheritsFrom("TBox") && opt.Contains("y") ) {
330  // Gate on Y ... Y1 and Y2 are used for real gating ... so in case gates are set on a 1D histogram
331  // one should use X1 and X2
332  Double_t realY1, realY2;
333  if ( isTH2 ) { //
334  realY1 = boxnew->GetY1();
335  realY2 = boxnew->GetY2();
336  }
337  else {
338  realY1 = boxnew->GetX1();
339  realY2 = boxnew->GetX2();
340  }
341  if ( IsBox(boxnew,&fBoxY) ) {
342  // look for an existing gate that overlaps this one
343  TIter existing(&fLastGates);
344  overlap = false;
345  while ( (boxadd = (TBox *)existing()) ) {
346  if ( (realY1 >= boxadd->GetY1() && realY1 <= boxadd->GetY2()) ||
347  (realY2 >= boxadd->GetY1() && realY2 <= boxadd->GetY2()) ) { overlap = true; break; }
348  }
349  if ( overlap == false ) {
350  TBox *box = dynamic_cast<TBox *>(boxnew->Clone());
351  box->SetY1(realY1);
352  box->SetY2(realY2);
353  fLastGates.Add(box);
354  } // new gate
355  else { // change current box settings
356  boxadd->SetY1( TMath::Min(boxadd->GetY1(),realY1) );
357  boxadd->SetY2( TMath::Max(boxadd->GetY2(),realY2) );
358  }
359  }
360  // Background gate on Y
361  if ( IsBox(boxnew,&fBoxBY) ) {
362  // look for an existing gate that overlaps this one
363  TIter existing(&fLastGates);
364  overlap = false;
365  while ( (boxadd = (TBox *)existing()) ) {
366  if ( (realY1 >= boxadd->GetY1() && realY1 <= boxadd->GetY2()) ||
367  (realY2 >= boxadd->GetY1() && realY2 <= boxadd->GetY2()) ) { overlap = true; break; }
368  }
369  if ( overlap == false ) {
370  TBox *box = dynamic_cast<TBox *>(boxnew->Clone());
371  box->SetY1(realY1);
372  box->SetY2(realY2);
373  fLastGates.Add(box);
374  } // new gate
375  else { // change current box settings
376  boxadd->SetX1( TMath::Min(boxadd->GetX1(),realY1) );
377  boxadd->SetX2( TMath::Max(boxadd->GetX2(),realY2) );
378  }
379  }
380  } // y
381  } // while
382 
383  // now merge if overlaps
384  cout << " Nb Gates found in the current pad : " << fLastGates.GetSize() << endl; return fLastGates.GetSize();
385 }
386 
387 
388 void MatPlayer::ShowGates(Option_t *o)
389 {
390 //
391 // look for an histogram in the current pad. If one is found, it displays the boxes saved in fLastGates
392 //
393 
394  TObject *obj; TBox *box; TString opt = o;
395 
396  if ( TVirtualPad::Pad() == NULL ) return ;
397 
398  TIter next(TVirtualPad::Pad()->GetListOfPrimitives()); // look for an histogram
399 // bool isTH2 = false;
400  while ( (obj = next()) ) {
401  if ( obj->InheritsFrom("TH1") ) {
402  if ( obj->InheritsFrom("TH2") ) /*isTH2 = true;*/ break; }
403  } // while
404 
405  TFrame *frame = TVirtualPad::Pad()->GetFrame();
406 
407  TIter existing(&fLastGates);
408  while ( (box = (TBox *) existing()) ) { //
409  // Gate on X
410  if ( IsBox(box,&fBoxX) ) {
411  box->DrawBox(box->GetX1(),frame->GetY1(),box->GetX2(),frame->GetY2());
412  }
413  if ( IsBox(box,&fBoxBX) ) {
414  box->DrawBox(box->GetX1(),frame->GetY1(),box->GetX2(),frame->GetY2());
415  }
416  }
417 }
418 
420 {
421 // to reset the conditions of gating
422  TObject *obj; TList toremove;
423 
424  if ( TVirtualPad::Pad() == NULL ) return;
425 
426  TIter next(TVirtualPad::Pad()->GetListOfPrimitives());
427  while ( (obj = next()) ) { // look for a box and keep a reference
428  if ( obj->InheritsFrom("TBox") ) { toremove.Add(obj); }
429  }
430  TIter remove(&toremove);
431  while ( (obj = remove()) ) { // remove lines
432  TVirtualPad::Pad()->GetListOfPrimitives()->Remove(obj);
433  }
434  toremove.Delete();
435 
436  TVirtualPad::Pad()->Update();
437 }
438 
439 void MatPlayer::ProjectionY(Option_t *option)
440 {
441 // Gating on a gamma-gamma matrix
442  TString opt = option;
443 
444  if ( fMat == NULL ) {
445  cout << "Cannot Project in MatPlayer::ProjectionY, no matrix selected ! " << endl; return;
446  }
447  if ( InitGating("Gx") == 0 ) return; // init gating from boxes drawn in the current pad
448 
449 // start gating by reseting first the histograms
450  fPy->Reset("ICE"); fBy->Reset("ICE");
451 
452  bool isbg; Float_t w, wb; TBox *box; TH1D *h, *hb;
453 
454  isbg = false; w = wb = 0.0; h = hb = NULL;
455  TIter next(&fLastGates);
456  while ( (box = (TBox *)next()) ) { // make successive projections
457  if ( IsBox(box,&fBoxX) ) { // projection
458  w += box->GetX2() - box->GetX1();
459  fPy->Add( h = fMat->ProjectionY("MatPlayer_tmp_py",fPx->FindBin(box->GetX1()),fPx->FindBin(box->GetX2()) ) );
460  }
461  if ( IsBox(box,&fBoxBX) ) { // background
462  isbg = true; wb += box->GetX2() - box->GetX1();
463  fBy->Add( hb = fMat->ProjectionY("MatPlayer_tmp_by",fPx->FindBin(box->GetX1()),fPx->FindBin(box->GetX2()) ) );
464  }
465  }
466  if ( h ) delete h; if ( hb ) delete hb;
467 
468  // do background substraction
469  if ( isbg ) {
470  fPy->Add(fBy,-w/wb);
471  hb = dynamic_cast<TH1D *>( fMat->GetDirectory()->Get( Form("%s_by",fMat->GetName()) ) );
472  if ( hb ) {
473  hb->Reset("ICE");
474  hb->Add(fBy);
475  hb->Scale(w/wb);
476  }
477  }
478  // move content of gated in local in global
479  h = dynamic_cast<TH1D *>( fMat->GetDirectory()->Get( Form("%s_py",fMat->GetName()) ) );
480  if ( h ) {
481  h->Reset("ICE");
482  h->Add(fPy);
483  }
484 
485  fPy->Draw(); cout << " Projection on Y DONE \n ";
486 }
487 
488 
489 void MatPlayer::XEventAction(Int_t event, Int_t px, Int_t py, TObject */*sel*/)
490 {
491 // Do action depending on X actions
492 
493  TVirtualPad *pad = gROOT->GetSelectedPad(); if ( pad == NULL ) return;
494 
495  switch (event) {
496  case kMouseMotion:
497  // to keep track of the last mouse position
498  fLastX = px; fLastY = py;
499  break;
500 
501  case kKeyPress:
502  {
503  Int_t key = px, keysym = py;
504  switch ((EKeySym)keysym) {
505  case kKey_Left:
506  cout<<"left arrow"<<endl;
507  break;
508  case kKey_Right:
509  cout<<"rightarrow"<<endl;
510  break;
511  case kKey_Down:
512  cout<<"down arrow"<<endl;
513  break;
514  case kKey_Up:
515  cout<<"up arrow"<<endl;
516  break;
517  case kKey_x:
518  // set a gate on the x axis
519  SetGateX("Gx");
520  break;
521  case kKey_X:
522  //
523  break;
524  case kKey_y:
525  // set a gate at y position
526  SetGateX("Gy");
527  break;
528  case kKey_Y:
529  ProjectionY(""); pad->Update();
530  break;
531  case kKey_b:
532  SetGateX("Bx");
533  break;
534  case kKey_B:
535  SetGateX("By");
536  break;
537  case kKey_h:
538  cout << "Keys used to interact with MatPlayer: " << endl;
539  cout << "\t x: add a gate on the x-axis " << endl;
540  cout << "\t y: add a gate on the y-axis " << endl;
541  cout << "\t b: background gate on the x-axis " << endl;
542  cout << "\t B: background gate on the y-axis " << endl;
543  cout << "\t X: Processed X-Gating " << endl;
544  cout << "\t Y: Processed Y-Gating " << endl;
545  cout << "\t r: Remove all gates in the current pad " << endl;
546  cout << "\t s: Show last gates in the current pad " << endl;
547  break;
548  case kKey_r:
549  Reset(); pad->Update();
550  case kKey_s:
551  ShowGates(""); pad->Update();
552  break;
553  default :
554  break;
555  }
556  if ( gDebug ) cout << "key " << key << "key " << keysym << endl;
557  }
558  break;
559 
560  default :
561  break;
562  } // switch
563 }
564 
565 void MatPlayer::SubstractBG(const char *matname, Option_t *option)
566 {
567  TString opt = option;
568 
569  // Test Option
570  if ( (!opt.Contains("RAD")) && (!opt.Contains("SNIP")) ) {
571  cout << "Bad options - Choose 'RAD' or 'SNIP' " << endl; return;
572  }
573 
574  TObject *obj = gROOT->FindObject(matname);
575  if ( obj == NULL ) {
576  cout << "Cannot find matrix named " << matname << endl;
577  } else {
578  if ( obj->InheritsFrom("TH2") ) {
579  if ( opt.Contains("RAD") ) SubstractBG_RAD((TH2 *)obj);
580  if ( opt.Contains("SNIP")) SubstractBG_SNIP((TH2 *)obj);
581  }
582  else cout << "Object named "<< matname << " is not a matrix !! ";
583  }
584 }
585 
586 void MatPlayer::SubstractBG_RAD(TH2 *mat)
587 {
588  Int_t i, j; TSpectrum worker; // use to substract a background on the x and y projection
589 
590  TH1D *proji, *projj;
591  Float_t *ptoti, *ptotj, *bgi, *bgj; Stat_t T;
592 
593 // to get the projection on X and Y
594  proji = mat->ProjectionX("tmp_rad_x"); projj = mat->ProjectionY("tmp_rad_y");
595 
596 //Smooth projection
597  proji->Smooth(2); projj->Smooth(2);
598 
599 // to normalize with the total number of counts in the matrix.
600  T = mat->Integral();
601  cout << " Number of counts in the gamma-gamma matrix: " << T << endl;
602 
603  ptoti = new Float_t[mat->GetNbinsX()]; bgi = new Float_t[mat->GetNbinsX()];
604  ptotj = new Float_t[mat->GetNbinsY()]; bgj = new Float_t[mat->GetNbinsY()];
605  for ( i = 0; i < mat->GetNbinsX(); i++ ) { ptoti[i] = bgi[i] = proji->GetBinContent(i+1); }
606  for ( j = 0; j < mat->GetNbinsY(); j++ ) { ptotj[j] = bgj[j] = projj->GetBinContent(j+1); }
607 
608  delete proji; delete projj;
609 
610  // worker.Background(bgi,mat->GetNbinsX(),40);worker.Background(bgj,mat->GetNbinsY(),40);
611  // worker.Background1(bgi,mat->GetNbinsX(),40);worker.Background1(bgj,mat->GetNbinsY(),40);
612  //worker.Background1General(bgi,mat->GetNbinsX(),20,BACK1_INCREASING_WINDOW,BACK1_ORDER2,BACK1_INCLUDE_COMPTON);
613  //worker.Background1General(bgj,mat->GetNbinsY(),20,BACK1_INCREASING_WINDOW,BACK1_ORDER2,BACK1_INCLUDE_COMPTON);
614 
615 // now do the background substraction
616  cout << " Background substraction on " << mat->GetName() << " by using the RADFORD procedure ..." << endl;
617 
618  Stat_t c, cmin = 0;
619  for ( i = 0; i < mat->GetNbinsX(); i++ ) {
620  for ( j = 0; j < mat->GetNbinsY(); j++ ) {
621 
622  cout << " [" << i << "," << j << "] \r" ;
623  // printf(" [%d,%d] \r",i,j);
624 
625  c = mat->GetBinContent(i+1,j+1);
626  c = c - (ptoti[i]*ptotj[j] - (ptoti[i]-bgi[i])*(ptotj[j]-bgj[j]))/T;
627  if ( c < 0 && c < cmin ) { cmin = c; }
628 
629  mat->SetBinContent(i+1,j+1,c);
630  } // j
631  } // i
632  cout << " ... DONE. Lowest value in the background substracted matrix " << cmin << endl;
633 
634  delete [] ptoti; delete [] ptotj; delete [] bgi; delete [] bgj;
635 }
636 
637 void MatPlayer::SubstractBG_SNIP(TH2 *mat)
638 {
639 // 2D Background substraction
640 // Based on the implementation given by M.Morhac NIM A,401 (1997) 113-132
641 // Based on SNIP procedure (Sensitive Nonlinear Iterative Peak)
642 
643  Int_t param = 3;
644 
645  cout << "*********************************************\n";
646  cout << "* Background Substraction with SNIP Procedure\n";
647  cout << "* Number of iterations : " << param << endl;
648  cout << "*********************************************\n";
649  cout << "* TH2 name : " << mat->GetName() << endl;
650 
651  Int_t dimX, dimY;
652  Float_t **v, **w, **y;
653 
654  Double_t P1, P2, P3, P4, S1, S2, S3, S4, a1, a2;
655 
656 
657  dimX = mat->GetNbinsX(); dimY = mat->GetNbinsY();
658  if (dimX <= 0) {cout << "Error, dimX <= 0\n"; return;}
659  if (dimY <= 0) {cout << "Error, dimY <= 0\n"; return;}
660 
661  v = new Float_t*[dimX]; w = new Float_t*[dimX], y = new Float_t*[dimX];
662  for (Int_t i=0 ; i<dimX ; i++){
663  v[i] = new Float_t[dimY];
664  w[i] = new Float_t[dimY];
665  y[i] = new Float_t[dimY];
666  }
667 
668  // Fill v
669  for (Int_t i=0 ; i<dimX ; i++){
670  for (Int_t j=0 ; j<dimY ; j++){
671  y[i][j] = mat->GetBinContent(i+1,j+1);
672  v[i][j] = mat->GetBinContent(i+1,j+1);
673  }
674  }
675 
676 
677  // LLS operator
678  for (Int_t i=0 ; i<dimX ; i++){
679  for (Int_t j=0 ; j<dimY ; j++){
680  v[i][j] = TMath::Log( TMath::Log( TMath::Sqrt(y[i][j] + 1) + 1) + 1);
681 
682  }
683  }
684 
685  //SNIP Algorithm
686  for (Int_t p=1 ; p<=param ; p++){
687  for (Int_t i=p ; i<dimX-p ; i++){
688  for (Int_t j=p ; j<dimY-p ; j++){
689  P1 = v[i+p][j+p];
690  P2 = v[i-p][j+p];
691  P3 = v[i+p][j-p];
692  P4 = v[i-p][j-p];
693 
694  S1 = v[i+p][j];
695  S2 = v[i][j+p];
696  S3 = v[i][j-p];
697  S4 = v[i-p][j-p];
698 
699  S1 = TMath::Max(S1,(P1+P3)/2) - (P1+P3)/2;
700  S2 = TMath::Max(S2,(P1+P2)/2) - (P1+P2)/2;
701  S3 = TMath::Max(S3,(P3+P4)/2) - (P3+P4)/2;
702  S4 = TMath::Max(S4,(P2+P4)/2) - (P2+P4)/2;
703 
704  a1 = v[i][j];
705  a2 = (S1+S4)/2 + (S2+S3)/2 + (P1+P2+P3+P4)/4;
706  w[i][j] = TMath::Min(a1,a2);
707  } //j
708  } //i
709  for (Int_t i=p ; i<dimX-p ; i++){
710  for (Int_t j=p ; j<dimY-p ; j++){
711  v[i][j] = w[i][j];
712  }
713  }
714  // printf ("[ %i ]\n",p);
715 
716  //TEST
717  /*for (Int_t i=0 ; i<dimX ; i++){
718  for (Int_t j=0 ; j<dimY ; j++){
719  mat->SetBinContent(i+1,j+1,y[i][j]-v[i][j]);
720  }
721  }*/
722  //ENDOFTEST
723 
724  //if (p==1) mat->ProjectionX("p=1")->Draw();
725  //else mat->ProjectionX("p=1")->DrawClone("SAME");
726 
727 
728  } //p
729 
730 
731  // Inverse LLS operator
732  for (Int_t i=0 ; i<dimX ; i++){
733  for (Int_t j=0 ; j<dimY ; j++){
734  v[i][j] = TMath::Exp( TMath::Exp( v[i][j] - 1) -1 ) * TMath::Exp( TMath::Exp( v[i][j]-1) - 1) -1;
735 
736  }
737  }
738 
739  //fill mat
740  for (Int_t i=0 ; i<dimX ; i++){
741  for (Int_t j=0 ; j<dimY ; j++){
742  mat->SetBinContent(i+1,j+1,y[i][j]-v[i][j]);
743  }
744  }
745 
746  //Delete useless pointers
747  for (Int_t i=0 ; i<dimX ; i++){
748  delete [] v[i];
749  delete [] w[i];
750  delete [] y[i];
751  }
752  delete [] v;
753  delete [] w;
754  delete [] y;
755 
756 }
void SetCanvas()
set current canvas as the mother of the current pad
Definition: MatPlayer.cpp:118
virtual ~MatPlayer()
Definition: MatPlayer.cpp:101
Int_t InitGating(Option_t *opt="Gx")
Definition: MatPlayer.cpp:275
static void SubstractBG(const char *, Option_t *)
Generic method to substract background of the current matrix.
Definition: MatPlayer.cpp:565
Double_t GetWidthGate(Double_t pos, Option_t *opt="Gx")
get width for gate at position pos
Definition: MatPlayer.cpp:206
ClassImp(MatPlayer)
void ShowGates(Option_t *o="BGx")
to show the gates used for the last gating
Definition: MatPlayer.cpp:388
void SetGateX(Option_t *opt="Gx")
set a gate using the last mouse position
Definition: MatPlayer.cpp:213
void Reset()
to reset the conditions of gating in the current pad
Definition: MatPlayer.cpp:419
void ProjectionY(Option_t *option)
to project
Definition: MatPlayer.cpp:439
ADF::LogMessage & endl(ADF::LogMessage &log)
MatPlayer is a tool to play with 2D matrices.
Definition: MatPlayer.h:55
void XEventAction(Int_t event, Int_t px, Int_t py, TObject *obj)
slots
Definition: MatPlayer.cpp:489