GSI Object Oriented Online Offline (Go4)  GO4-6.3.0
TGo4PolyCond.cxx
Go to the documentation of this file.
1 // $Id$
2 //-----------------------------------------------------------------------
3 // The GSI Online Offline Object Oriented (Go4) Project
4 // Experiment Data Processing at EE department, GSI
5 //-----------------------------------------------------------------------
6 // Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
7 // Planckstr. 1, 64291 Darmstadt, Germany
8 // Contact: http://go4.gsi.de
9 //-----------------------------------------------------------------------
10 // This software can be used under the license agreements as stated
11 // in Go4License.txt file which is part of the distribution.
12 //-----------------------------------------------------------------------
13 
14 #include "TGo4PolyCond.h"
15 
16 #include "TMath.h"
17 #include "TROOT.h"
18 #include "TH2.h"
19 #include "TList.h"
20 #include "TCutG.h"
21 
22 #include "TGo4PolyCondPainter.h"
23 #include "TGo4Log.h"
24 
27 //#define POLYCOND_UPDATE_WITHCLONE 1
28 
29 
30 TString TGo4PolyCond::fgxURL_NPOINTS="npolygon";
31 TString TGo4PolyCond::fgxURL_XPRE="x";
32 TString TGo4PolyCond::fgxURL_YPRE="y";
33 
35 {
36  TString res;
37  Int_t cnt = 0;
38  do {
39  res.Form("CutG_%d",cnt++);
40  } while (gROOT->GetListOfSpecials()->FindObject(res));
41  return res;
42 }
43 
44 // ----------------------------------------------------------
46  TGo4Condition(),
47  fxCut(nullptr),
48  fxCutHis(nullptr)
49 {
50  SetDimension(2);
51  //SetBit(kCanDelete, kFALSE);
52 }
53 // ----------------------------------------------------------
54 TGo4PolyCond::TGo4PolyCond(const char *name, const char *title) :
55  TGo4Condition(name,title),
56  fxCut(nullptr),
57  fxCutHis(nullptr)
58 {
59  SetDimension(2);
60  //SetBit(kCanDelete, kFALSE);
61 }
62 // ----------------------------------------------------------
64 {
65  // UnDraw(); // JAM 2016 - do it before cut has vanished!
66 
67  ClearCutHis();
68 
69  if (fxCut) {
70  delete fxCut;
71  fxCut = nullptr; // JAM2016: reset for Unpaint in PolyCondView?
72  }
73 }
74 
75 // ----------------------------------------------------------
77 {
79  ClearCutHis(); // discard internal cut histogram
80 }
81 
82 // ----------------------------------------------------------
84 {
85  if (fxCutHis) {
86  delete fxCutHis;
87  fxCutHis = nullptr;
88  }
89 }
90 
91 // ----------------------------------------------------------
92 Double_t TGo4PolyCond::GetXLow() const
93 {
94  if(!fxCut) return 0.;
95  Int_t n = fxCut->GetN();
96  auto xarr = fxCut->GetX();
97  fxCut->SetBit(kMustCleanup,0);
98  Int_t nxmin = TMath::LocMin(n,xarr);
99  return xarr[nxmin];
100 }
101 
102 Double_t TGo4PolyCond::GetXUp() const
103 {
104  if(!fxCut) return 0.;
105  Int_t n=fxCut->GetN();
106  auto xarr=fxCut->GetX();
107  Int_t nxmax=TMath::LocMax(n,xarr);
108  return xarr[nxmax];
109 }
110 
111 Double_t TGo4PolyCond::GetYLow() const
112 {
113  if(!fxCut) return 0;
114  Int_t n=fxCut->GetN();
115  auto yarr=fxCut->GetY();
116  Int_t nymin=TMath::LocMin(n,yarr);
117  return yarr[nymin];
118 }
119 
120 Double_t TGo4PolyCond::GetYUp() const
121 {
122  if(!fxCut) return 0.;
123  Int_t n = fxCut->GetN();
124  auto yarr = fxCut->GetY();
125  Int_t nymax = TMath::LocMax(n,yarr);
126  return yarr[nymax];
127 }
128 
130 {
131  return kTRUE;
132 }
133 
134 // ----------------------------------------------------------
135 TCutG *TGo4PolyCond::GetCut(Bool_t changeowner)
136 {
137  TCutG *tempcut = fxCut;
138 
139  if(changeowner) {
140  fxCut = nullptr;
141  ClearCutHis(); // discard internal histogram
142  }
143  return tempcut;
144 }
145 
146 // ----------------------------------------------------------
148 {
149  TCutG *tempcut = source->GetCut(false); // get fxCut pointer
150  if(tempcut) {
151  CleanupSpecials(); // JAM2016: Clone might delete cut of same name from list of specials, remove it first
152  TCutG *ret= (TCutG *)tempcut->Clone(GetName());
153  CleanupSpecials();
154  return ret;
155  }
156 
157  return nullptr;
158 }
159 // ----------------------------------------------------------
160 void TGo4PolyCond::SetValues(TCutG *newcut)
161 {
162  if(!newcut) return;
163 #ifdef POLYCOND_UPDATE_WITHCLONE
164  if(fxCut) delete fxCut;
165  CleanupSpecials(); // JAM2016: Clone might delete cut of same name from list of specials, remove it first
166  //fxCut = (TCutG*) newcut->Clone(NextAvailableName());
167  fxCut = (TCutG*) newcut->Clone(GetName());
168  fxCut->SetBit(kCanDelete,kFALSE);
169  CleanupSpecials();
170 #else
171  Int_t pn = newcut->GetN();
172  if(!fxCut) {
173  fxCut = new TCutG(GetName(),pn);
174  fxCut->SetBit(kMustCleanup);
175  TGo4PolyCond::CleanupSpecials(); // JAM2016
176  }
177  else
178  {
179  fxCut->Set(pn);
180  }
181  Double_t xp = 0, yp = 0;
182  for (Int_t i = 0; i < pn; ++i) {
183  newcut->GetPoint(i, xp, yp);
184  fxCut->SetPoint(i, xp, yp);
185  }
186 
187 
188 #endif
189  // when updated from view, we store graphical attributes:
190  SetLineColor(newcut->GetLineColor());
191  SetLineWidth(newcut->GetLineWidth());
192  SetLineStyle(newcut->GetLineStyle());
193  SetFillColor(newcut->GetFillColor());
194  SetFillStyle(newcut->GetFillStyle());
195 
196  ClearCutHis(); // fxCut changed, so discard previous fxCut histogram
197 }
198  // ----------------------------------------------------------
199 void TGo4PolyCond::SetValuesDirect(TCutG * newcut)
200 {
201  if(!newcut) return;
202  if(fxCut && fxCut!=newcut) delete fxCut;
203 
204  fxCut = newcut;
205  //fxCut->SetName(NextAvailableName()); // JAM2016
206  fxCut->SetName(GetName());
207 
208  // when updated from view, we store graphical attributes:
209  SetLineColor(newcut->GetLineColor());
210  SetLineWidth(newcut->GetLineWidth());
211  SetLineStyle(newcut->GetLineStyle());
212  SetFillColor(newcut->GetFillColor());
213  SetFillStyle(newcut->GetFillStyle());
214 
215  ClearCutHis(); // fxCut changed, so discard previous fxCut histogram
216 }
217 
218 // ----------------------------------------------------------
219 void TGo4PolyCond::SetValues(Double_t * x, Double_t * y, Int_t len)
220 {
221  if(fxCut) delete fxCut;
222  TGo4PolyCond::CleanupSpecials(); // JAM2016
223  //fxCut = new TCutG(NextAvailableName(), len, x, y);
224  fxCut = new TCutG(GetName(), len, x, y);
225  fxCut->SetBit(kMustCleanup);
226  //fxCut->SetBit(kCanDelete,kFALSE);
227  TGo4PolyCond::CleanupSpecials(); // JAM2016
228 
229  ClearCutHis(); // discard previous fxCut histogram
230 }
231 
232 // ----------------------------------------------------------
233 Bool_t TGo4PolyCond::Test(Double_t x, Double_t y)
234 {
235  IncCounts();
236  if(!IsEnabled() || !fxCut){
237  if(FixedResult()) IncTrueCounts();
238  return FixedResult();
239  }
240  Bool_t outside = (fxCut->IsInside(x,y) == 0);
241  if(outside) return IsFalse();
242  IncTrueCounts();
243  return IsTrue();
244 }
245 
246 // ----------------------------------------------------------
247 void TGo4PolyCond::PrintCondition(Bool_t points)
248 {
250  if(points) {
251  if(!fxCut)
252  std::cout << "No polygon specified!" << std::endl;
253  else
254  fxCut->Print(nullptr);
255  }
256 }
257 
258 // -----------------------------------------------
259 // PrintBar switch is handled in condition baseclass now.
260 //void TGo4PolyCond::Print(Option_t *opt) const{
262 // TGo4PolyCond *const localthis= const_cast<TGo4PolyCond *const>(this);
263 // localthis->PrintBar();
264 //}
265 // ----------------------------------------------------------
266 Bool_t TGo4PolyCond::UpdateFrom(TGo4Condition *cond, Bool_t counts)
267 {
268  if(!TGo4Condition::UpdateFrom(cond,counts)) return kFALSE;
269  if(cond->InheritsFrom(TGo4PolyCond::Class())) {
270 
271 #ifdef POLYCOND_UPDATE_WITHCLONE
272  TCutG * temp = CloneCut((TGo4PolyCond*)cond); // get clone from source, still valid there!
273  CleanupSpecials(); // remove all references to cloned TCutG from list of specials
274  if(temp)
275  {
276  TCutG *old = fxCut; // JAM2016 change cut before deleting the old one!
277  fxCut = temp;
278  if(old) delete old;
279  ClearCutHis();
280  return kTRUE;
281  }
282  else
283  {
284  return kFALSE;
285  }
286 #else
287  /* JAM2016: try to avoid streaming the cut multiple times when updating condition:*/
288  TGo4PolyCond *source=(TGo4PolyCond*)cond;
289  TCutG * srccut = source->GetCut(false);
290 
291  if(!srccut) return kFALSE;
292  CleanupSpecials(); // redundant? do it to get rid of entries from streamer!?
293  Int_t pn = srccut->GetN();
294  fxCut->Set(pn);
295  Double_t xp = 0, yp = 0;
296  for (Int_t i = 0; i < pn; ++i) {
297  srccut->GetPoint(i, xp, yp);
298  fxCut->SetPoint(i, xp, yp);
299  }
300 
301  // still need this to reassign the bins of statistics histogram:
302  ClearCutHis();
303 
304  return kTRUE;
305 #endif
306 
307  }
308  else
309  {
310  std::cout << "Cannot update " << GetName() << " from " << cond->ClassName() << std::endl;
311  return kFALSE;
312  }
313 }
314 
315 
316 Bool_t TGo4PolyCond::UpdateFromUrl(const char *rest_url_opt)
317 {
318  if (!TGo4Condition::UpdateFromUrl(rest_url_opt))
319  return kFALSE;
320  TString message;
321  message.Form("TGo4PolyCond::UpdateFromUrl - condition %s: with url:%s", GetName(), rest_url_opt);
322  TGo4Log::Message(1, "%s", message.Data());
323 
324  // evaluate options that change array of points
326  message = "";
327  Int_t npoints = GetUrlOptionAsInt(TGo4PolyCond::fgxURL_NPOINTS, -1);
328  if (npoints >= 0) {
329  TString xname, yname;
330  Double_t *X = new Double_t[npoints];
331  Double_t *Y = new Double_t[npoints];
332  for (Int_t i = 0; i < npoints; ++i) {
333  xname.Form("%s%d", TGo4PolyCond::fgxURL_XPRE.Data(), i);
334  yname.Form("%s%d", TGo4PolyCond::fgxURL_YPRE.Data(), i);
335  X[i] = GetUrlOptionAsDouble(xname.Data(), 0.);
336  Y[i] = GetUrlOptionAsDouble(yname.Data(), 0.);
337  message.Append(TString::Format(" X[%i]=%f, Y[%i]=%f\n", i, X[i], i, Y[i]));
338  }
339  SetValues(X, Y, npoints);
340  delete[] X;
341  delete[] Y;
342  }
343  message.Append(" - setting Polygon condition to new values!");
344  TGo4Log::Message(1, "%s", message.Data());
345  }
346  return kTRUE;
347 }
348 
349 Double_t TGo4PolyCond::GetIntegral(TH1 *histo, Option_t *opt)
350 {
351  return fxCut ? fxCut->IntegralHist(dynamic_cast<TH2 *>(histo),opt) : 0.;
352 }
353 
354 Double_t TGo4PolyCond::GetMean(TH1 *histo, Int_t axis)
355 {
356  if (IsCutHis(histo))
357  return fxCutHis->GetMean(axis);
358 
359  return -1;
360 }
361 
362 Double_t TGo4PolyCond::GetRMS(TH1 *histo, Int_t axis)
363 {
364  if (IsCutHis(histo))
365  return fxCutHis->GetRMS(axis);
366 
367  return -1;
368 }
369 
370 Double_t TGo4PolyCond::GetSkewness(TH1 *histo, Int_t axis)
371 {
372  if (IsCutHis(histo))
373  return fxCutHis->GetSkewness(axis);
374 
375  return -1;
376 }
377 
378 Double_t TGo4PolyCond::GetCurtosis(TH1 *histo, Int_t axis)
379 {
380  if (IsCutHis(histo))
381  return fxCutHis->GetKurtosis(axis);
382 
383  return -1;
384 }
385 
386 Double_t TGo4PolyCond::GetXMax(TH1 *histo)
387 {
388  if (IsCutHis(histo)) {
389  TAxis *xax = fxCutHis->GetXaxis();
390  Int_t maxbin = fxCutHis->GetMaximumBin();
391  Int_t xmaxbin = maxbin % (fxCutHis->GetNbinsX() + 2);
392  return xax->GetBinCenter(xmaxbin);
393  }
394  return -1;
395 }
396 
397 Double_t TGo4PolyCond::GetYMax(TH1 *histo)
398 {
399  if (IsCutHis(histo)) {
400  TAxis *yax = fxCutHis->GetYaxis();
401  Int_t maxbin = fxCutHis->GetMaximumBin();
402  Int_t maxybin = maxbin / (fxCutHis->GetNbinsX() + 2);
403  return yax->GetBinCenter(maxybin);
404  }
405 
406  return -1;
407 }
408 
409 Double_t TGo4PolyCond::GetCMax(TH1 *histo)
410 {
411  if (IsCutHis(histo))
412  return fxCutHis->GetMaximum();
413 
414  return -1;
415 }
416 
418 {
419  if (!painter)
420  return;
421  if (painter->InheritsFrom(TGo4PolyCondPainter::Class())) {
422  if (fxPainter)
423  delete fxPainter;
424  fxPainter = painter;
425  fxPainter->SetCondition(this);
426  } else {
427  TGo4Log::Warn("Could not set painter of class %s for TGo4PolyCond %s", painter->ClassName(), GetName());
428  }
429 }
430 
431 
433 {
434  TGo4ConditionPainter *painter=new TGo4PolyCondPainter(GetName());
435  painter->SetCondition(this);
436  return painter;
437 }
438 
439 
440 Bool_t TGo4PolyCond::IsCutHis(TH1 *source)
441 {
442  if (fxCutHis)
443  return kTRUE;
444 
445  TH2 *his = dynamic_cast<TH2 *>(source);
446  if (!his)
447  return kFALSE;
448 
449  fxCutHis = (TH2 *) his->Clone();
450  Int_t nx = fxCutHis->GetNbinsX();
451  Int_t ny = fxCutHis->GetNbinsY();
452  TAxis *xaxis = fxCutHis->GetXaxis();
453  TAxis *yaxis = fxCutHis->GetYaxis();
454  xaxis->SetRange(0, 0); // expand work histogram to full range
455  yaxis->SetRange(0, 0);
456  // set all bins outside fxCut to zero:
457  for (Int_t i = 0; i < nx; ++i) {
458  Double_t x = xaxis->GetBinCenter(i);
459  for (Int_t j = 0; j < ny; ++j) {
460  Double_t y = yaxis->GetBinCenter(j);
461  if (fxCut && !(fxCut->IsInside(x, y)))
462  fxCutHis->SetBinContent(i, j, 0);
463  }
464  }
465  // prepare statistics:
466  Stat_t s[11] = {0}; // dimension is kNstat of TH1.cxx
467  fxCutHis->PutStats(s); // reset previous stats
468  fxCutHis->GetStats(s); // recalculate
469  fxCutHis->PutStats(s); // put back
470  fxCutHis->SetDirectory(nullptr); // important for first draw from marker setup file!
471 
472  return kTRUE;
473 }
474 
475 
476 // ----------------------------------------------------------
478 {
479  TSeqCollection *specials = gROOT->GetListOfSpecials();
480  TIter iter(specials);
481  while(auto ob = iter()) {
482  if(ob->InheritsFrom(TCutG::Class()))
483  specials->Remove(ob);
484  }
485 }
486 
488 {
489  Int_t size = sizeof(*this);
490  if (GetName()) size += strlen(GetName());
491  if (GetTitle()) size += strlen(GetTitle());
492  if (fxCut) {
493  size += sizeof(*fxCut);
494  size += fxCut->GetMaxSize()*2*sizeof(Double_t);
495  }
496  return size;
497 }
498 
499 void TGo4PolyCond::SavePrimitive(std::ostream &out, Option_t *opt)
500 {
501  static int cnt = 0;
502  TString line, varname = MakeScript(out, TString::Format("polycond%d", cnt++).Data(), opt);
503 
504  if (!fxCut || (fxCut->GetN() == 0)) {
505  line.Form(" %s->SetValues(0, 0, 0);", varname.Data());
506  } else {
507  TString xname = varname;
508  xname.ReplaceAll("->At(","_sub");
509  xname.ReplaceAll(")","");
510  TString yname = xname + "_y";
511  xname = xname + "_x";
512  line.Form(" Double_t %s[%d], %s[%d];", xname.Data(), fxCut->GetN(), yname.Data(), fxCut->GetN());
513  out << line << std::endl;
514  for (Int_t n = 0; n < fxCut->GetN(); n++) {
515  Double_t x, y;
516  fxCut->GetPoint(n, x, y);
517  line.Form(" %s[%d] = %f; %s[%d] = %f;", xname.Data(), n, x, yname.Data(), n, y);
518  out << line << std::endl;
519  }
520  line.Form(" %s->SetValues(%s, %s, %d);", varname.Data(), xname.Data(), yname.Data(), fxCut->GetN());
521  }
522 
523  out << line << std::endl;
524 }
void SetPainter(TGo4ConditionPainter *painter) override
Bool_t UrlOptionHasKey(const char *key)
Double_t GetIntegral(TH1 *histo, Option_t *opt="") override
void ClearCutHis()
static TString fgxURL_XPRE
Definition: TGo4PolyCond.h:128
Double_t GetMean(TH1 *histo, Int_t axis=1) override
TCutG * GetCut(Bool_t changeowner) override
virtual Bool_t UpdateFrom(TGo4Condition *cond, Bool_t counts)
static TString NextAvailableName()
Double_t GetYLow() const override
virtual void PrintCondition(Bool_t full=kTRUE)
TCutG * CloneCut(TGo4PolyCond *source)
void SetValuesDirect(TCutG *newcut)
Bool_t IsCutHis(TH1 *source)
TCutG * fxCut
Definition: TGo4PolyCond.h:145
static void CleanupSpecials()
virtual void SetValues()
Definition: TGo4Condition.h:93
const char * MakeScript(std::ostream &out, const char *varname, Option_t *opt="", const char *arrextraargs=nullptr)
Double_t GetXLow() const override
Bool_t IsPolygonType() const override
static TString fgxURL_YPRE
Definition: TGo4PolyCond.h:130
static const char * Message(Int_t prio, const char *text,...) GO4_PRINTF2_ARGS
Definition: TGo4Log.cxx:206
Double_t GetXUp() const override
Double_t GetYUp() const override
virtual Bool_t UpdateFromUrl(const char *rest_url_opt)
Bool_t IsFalse() const
virtual void SetWorkHistogram(TH1 *histo)
Int_t GetMemorySize() const override
Double_t GetCurtosis(TH1 *histo, Int_t axis=1) override
virtual void SetCondition(TGo4Condition *con)
Double_t GetRMS(TH1 *histo, Int_t axis=1) override
Double_t GetYMax(TH1 *histo) override
virtual ~TGo4PolyCond()
Double_t GetSkewness(TH1 *histo, Int_t axis=1) override
virtual Bool_t Test()
TGo4ConditionPainter * fxPainter
TGo4ConditionPainter * CreatePainter() override
void SavePrimitive(std::ostream &fs, Option_t *opt="") override
void SetWorkHistogram(TH1 *histo) override
Bool_t IsEnabled() const
Definition: TGo4Condition.h:82
Double_t GetCMax(TH1 *histo) override
Bool_t FixedResult() const
Int_t GetUrlOptionAsInt(const char *key, Int_t def_value)
Bool_t UpdateFrom(TGo4Condition *cond, Bool_t counts) override
Double_t GetXMax(TH1 *histo) override
static TString fgxURL_NPOINTS
Definition: TGo4PolyCond.h:126
static void Warn(const char *text,...) GO4_PRINTF_ARGS
Definition: TGo4Log.cxx:307
Bool_t UpdateFromUrl(const char *rest_url_opt) override
Double_t GetUrlOptionAsDouble(const char *key, Double_t def_value)
void SetDimension(Int_t d)
void PrintCondition(Bool_t points=kTRUE) override
Bool_t IsTrue() const