GSI Object Oriented Online Offline (Go4)  GO4-6.3.0
TGo4FitterAbstract.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 "TGo4FitterAbstract.h"
15 
16 #include <iostream>
17 
18 #include "TBuffer.h"
19 #include "TArrayD.h"
20 #include "TArrayI.h"
21 #include "TVectorD.h"
22 #include "TFormula.h"
23 #include "TClass.h"
24 #include "TString.h"
25 #include "TObjString.h"
26 
27 #include "TGo4FitterConfig.h"
28 #include "TGo4FitDependency.h"
29 #include "TGo4FitterOutput.h"
30 #include "TGo4FitMinuit.h"
31 #include "TGo4FitParameter.h"
32 
34  : TGo4FitParsList(), TGo4FitSlotList(), fxActions(), fxResults(), fbParsChange(kTRUE),
35  fbInitializationDone(kFALSE), fbNeedToFinalize(kFALSE), fbParsAsResults(kFALSE)
36 {
37 }
38 
39 TGo4FitterAbstract::TGo4FitterAbstract(const char *iName, const char *iTitle)
40  : TGo4FitParsList(iName, iTitle, kFALSE), TGo4FitSlotList(), fxActions(), fxResults(),
41  fbParsChange(kTRUE), fbInitializationDone(kFALSE), fbNeedToFinalize(kFALSE), fbParsAsResults(kFALSE)
42 {
43  fxActions.SetOwner(kTRUE);
44 }
45 
47 {
48  if (fbNeedToFinalize)
49  Finalize();
50 }
51 
52 void TGo4FitterAbstract::Clear(Option_t *option)
53 {
54  TGo4FitParsList::Clear(option);
55  DeleteActions();
56 }
57 
59 {
60  ClearPars();
61  if (fxCurrentConfig)
63  fbParsChange = kFALSE;
64 }
65 
67 {
68  if (!fitter)
69  return;
70  fitter->CollectAllPars();
72 
73  for (Int_t n = 0; n < NumPars(); n++) {
74  TGo4FitParameter *dest = Get(n);
75  const TGo4FitParameter *src = fitter->FindPar(dest->GetFullName());
76  if (src)
77  dest->SetValue(src->GetValue());
78  }
79 }
80 
81 Bool_t TGo4FitterAbstract::GetParFixed(const char *ParName)
82 {
83  Bool_t fixed = TGo4FitParsList::GetParFixed(ParName);
84  if (fxCurrentConfig && !fixed)
85  fixed = fxCurrentConfig->GetParFixed(ParName);
86  return fixed;
87 }
88 
89 Bool_t TGo4FitterAbstract::GetParRange(const char *ParName, Double_t &RangeMin, Double_t &RangeMax)
90 {
91  Bool_t get = kFALSE;
92  if (fxCurrentConfig)
93  get = fxCurrentConfig->GetParRange(ParName, RangeMin, RangeMax);
94  if (!get)
95  get = TGo4FitParsList::GetParRange(ParName, RangeMin, RangeMax);
96  return get;
97 }
98 
99 Bool_t TGo4FitterAbstract::GetParEpsilon(const char *ParName, Double_t &Epsilon)
100 {
101  Bool_t get = kFALSE;
102  if (fxCurrentConfig)
103  get = fxCurrentConfig->GetParEpsilon(ParName, Epsilon);
104  if (!get)
105  get = TGo4FitParsList::GetParEpsilon(ParName, Epsilon);
106  return get;
107 }
108 
109 Bool_t TGo4FitterAbstract::InitializeDependencies(TObjArray &Dependencies, Bool_t BlockPars, Bool_t DoInit)
110 {
111  for (Int_t i = 0; i <= Dependencies.GetLast(); i++) {
112  TGo4FitDependency *dep = (TGo4FitDependency *)Dependencies[i];
113 
114  Int_t parindx = 0;
115  TGo4FitParameter *deppar = nullptr;
116  if (dep->GetParameter().IsNull())
117  parindx = -1;
118  else {
119  deppar = Find(dep->GetParameter().Data());
120  if (!deppar) {
121  std::cout << "Error dependence parameter: " << dep->GetParameter().Data() << std::endl;
122  return kFALSE;
123  }
124  parindx = GetParIndex(deppar);
125  }
126 
127  if (dep->GetExpression().Length() > 0) {
128  TString formula(dep->GetExpression().Data());
129  for (Int_t n = 0; n < NumPars(); n++) {
130  if (n == parindx)
131  continue;
132  TString repl("[");
133  repl += n;
134  repl += "]";
135  formula.ReplaceAll(GetParFullName(n), repl);
136  }
137  TFormula *fx = new TFormula("test", formula.Data());
138  Int_t err = fx->Compile(formula.Data());
139  delete fx;
140  if (err != 0) {
141  std::cout << "Error in dependence: " << formula.Data() << " code " << err << std::endl;
142  return kFALSE;
143  }
144  if (DoInit)
145  dep->Initialize(parindx, formula.Data());
146 
147  } else if (DoInit)
148  dep->Initialize(parindx, nullptr);
149 
150  if (BlockPars)
151  deppar->SetBlocked();
152  }
153  return kTRUE;
154 }
155 
156 void TGo4FitterAbstract::RunDependenciesList(TObjArray &Dependencies, Double_t *pars)
157 {
158  for (Int_t i = 0; i <= Dependencies.GetLast(); i++)
159  ((TGo4FitDependency *)Dependencies[i])->ExecuteDependency(pars);
160 }
161 
162 void TGo4FitterAbstract::FinalizeDependencies(TObjArray &Dependencies)
163 {
164  for (Int_t i = 0; i <= Dependencies.GetLast(); i++) {
165  TGo4FitDependency *dep = (TGo4FitDependency *)Dependencies[i];
166  dep->Finalize();
167  }
168 }
169 
171 {
172  if (pars && fxCurrentConfig)
174 }
175 
177 {
178  if (!Config)
179  return kFALSE;
180  Bool_t res = kTRUE;
181  try {
182  fxCurrentConfig = Config;
183  CollectAllPars();
184  res = InitializeDependencies(Config->GetParsInit(), kFALSE, kFALSE);
185  res = res && InitializeDependencies(Config->GetParsDepend(), kFALSE, kFALSE);
186  res = res && InitializeDependencies(Config->GetResults(), kFALSE, kFALSE);
187 
188  fxCurrentConfig = nullptr;
189  CollectAllPars();
190 
191  } catch (...) {
192  fxCurrentConfig = nullptr;
193  CollectAllPars();
194  throw;
195  }
196 
197  return res;
198 }
199 
201 {
202  if (fxCurrentConfig) {
206  }
207 
208  fxCurrentConfig = Config;
209  CollectAllPars();
210 
211  Bool_t res = kTRUE;
212 
213  if (fxCurrentConfig) {
214  res = res && InitializeDependencies(fxCurrentConfig->GetParsInit(), kFALSE, kTRUE);
215  res = res && InitializeDependencies(fxCurrentConfig->GetParsDepend(), kTRUE, kTRUE);
216  res = res && InitializeDependencies(fxCurrentConfig->GetResults(), kFALSE, kTRUE);
217 
218  if (res) {
219  TArrayD pars(NumPars());
220  GetParsValues(pars.GetArray());
221  RunDependenciesList(fxCurrentConfig->GetParsInit(), pars.GetArray());
222  SetParsValues(pars.GetArray());
223  }
224  }
225 
226  if (!res) {
227  FinalizeDependencies(fxCurrentConfig->GetParsInit());
228  FinalizeDependencies(fxCurrentConfig->GetParsDepend());
229  FinalizeDependencies(fxCurrentConfig->GetResults());
230  fxCurrentConfig = nullptr;
231  }
232 
233  return res;
234 }
235 
237 {
238  if (fbNeedToFinalize)
239  Finalize();
240  fbInitializationDone = kFALSE;
241 
242  if (!CheckObjects())
243  return kFALSE;
244 
245  fbNeedToFinalize = kTRUE;
246 
247  CollectAllPars();
248 
250 
251  if (!InitFitterData())
252  return kFALSE;
253 
254  fbInitializationDone = kTRUE;
255 
256  return kTRUE;
257 }
258 
260 {
261  if (pars) {
262  ExecuteDependencies(pars);
263  SetParsValues(pars);
264  }
265 
266  return DoCalculation();
267 }
268 
270 {
271  Double_t FF = DoCalculation();
272  Int_t NDF = DoNDFCalculation();
273 
275 
276  if (fxCurrentConfig && (fxCurrentConfig->GetResults().GetLast() >= 0)) {
277  TArrayD pars(NumPars());
278  GetParsValues(pars.GetArray());
279  fxResults.Set(fxCurrentConfig->GetResults().GetLast() + 3);
280 
281  for (Int_t i = 0; i <= fxCurrentConfig->GetResults().GetLast(); i++) {
283  fxResults[i] = res->ExecuteDependency(pars.GetArray());
284  }
285  } else {
286  fxResults.Set(NumPars() + 2);
287  GetParsValues(fxResults.GetArray());
288  }
289 
290  fxResults.SetAt(FF, fxResults.GetSize() - 2);
291  fxResults.SetAt(NDF, fxResults.GetSize() - 1);
292 
293  if (fxCurrentConfig)
294  ApplyConfig(nullptr);
295 
296  fbNeedToFinalize = kFALSE;
297  fbInitializationDone = kFALSE;
298 }
299 
301 {
302  fxActions.Add(Action);
303 }
304 
306 {
307  fxActions.AddAt(Action, indx);
308 }
309 
311 {
312  if ((num < 0) || (num > fxActions.GetLast()))
313  return nullptr;
314  return dynamic_cast<TGo4FitterAction *>(fxActions[num]);
315 }
316 
318 {
319  if (!action)
320  return;
321  if (fxActions.IndexOf(action) >= 0) {
322  fxActions.Remove(action);
323  fxActions.Compress();
324  }
325  delete action;
326 }
327 
329 {
330  Int_t indx = fxActions.IndexOf(action);
331  if (!action || (indx < 0))
332  return;
333  Int_t newindx = indx + dir;
334  if ((newindx >= 0) && (newindx <= fxActions.GetLast()) && (newindx != indx)) {
335  fxActions[indx] = fxActions[newindx];
336  fxActions[newindx] = action;
337  }
338 }
339 
340 void TGo4FitterAbstract::DoActions(Bool_t AllowFitterChange, TObjArray *Actions)
341 {
342  if (!Actions)
343  Actions = &fxActions;
344 
345  Bool_t need = kFALSE;
346  for (Int_t n = 0; n <= Actions->GetLast(); n++) {
347  TGo4FitterAction *action = dynamic_cast<TGo4FitterAction *>(Actions->At(n));
348  if (action)
349  need = need || action->NeedBuffers();
350  }
351 
352  if (need)
353  if (!Initialize())
354  return;
355 
356  for (Int_t n = 0; n <= Actions->GetLast(); n++) {
357  TGo4FitterAction *action = dynamic_cast<TGo4FitterAction *>(Actions->At(n));
358  if (!action)
359  continue;
360  if (!AllowFitterChange && action->CanChangeFitter())
361  continue;
362 
363  action->DoAction(this);
365  }
366 
367  if (need)
368  Finalize();
369 }
370 
372 {
373  if (!Action)
374  return;
375 
376  Bool_t need = Action->NeedBuffers();
377 
378  if (need)
379  if (!Initialize())
380  return;
381 
382  Action->DoAction(this);
383 
384  if (need)
385  Finalize();
386 }
387 
389 {
390  DoAction(GetAction(indx));
391 }
392 
393 TObjArray *TGo4FitterAbstract::ProcessObjects(TObjArray *objs, Bool_t CloneFitter, Bool_t OnlyRequired,
394  TObjArray *rownames, TObjArray *colnames)
395 {
396  if (!objs || (objs->GetLast() < 0))
397  return nullptr;
398 
399  if (NumSlots() <= 0)
400  return nullptr;
401 
402  TArrayI use(NumSlots());
403  use.Reset(-1);
404 
405  Int_t numuse = 0;
406  for (Int_t n = 0; n < NumSlots(); n++) {
407  TGo4FitSlot *slot = GetSlot(n);
408  if (!slot)
409  return nullptr;
410  if (!slot->GetObject())
411  if (slot->IsRequired() || !OnlyRequired)
412  use[numuse++] = n;
413  }
414 
415  if ((numuse == 0) || ((objs->GetLast() + 1) % numuse != 0))
416  return nullptr;
417 
418  Int_t nuse = 0;
419  for (Int_t nobj = 0; nobj <= objs->GetLast(); nobj++) {
420  TObject *obj = objs->At(nobj);
421  if (!obj) {
422  std::cout << "Empty object in list" << std::endl;
423  return nullptr;
424  }
425  TGo4FitSlot *slot = GetSlot(use[nuse++]);
426  if (nuse == numuse)
427  nuse = 0;
428  if (!slot->IsSuitable(obj)) {
429  std::cout << "Object " << obj->GetName() << " of class " << obj->ClassName() << " noncompatible with "
430  << slot->GetClass()->GetName() << std::endl;
431  return nullptr;
432  }
433  }
434 
435  TObjArray *res = new TObjArray((objs->GetLast() + 1) / numuse);
436  res->SetOwner(kTRUE);
437  TGo4FitterAbstract *resf = nullptr;
438 
439  if (rownames) {
440  rownames->Clear();
441  rownames->SetOwner(kTRUE);
442  }
443  if (colnames) {
444  colnames->Clear();
445  colnames->SetOwner(kTRUE);
446  }
447 
448  if (CloneFitter) {
449 
450  Int_t nobj = 0;
451 
452  do {
453  TGo4FitterAbstract *newfitter = dynamic_cast<TGo4FitterAbstract *>(Clone());
454  if (!newfitter)
455  break;
456  res->Add(newfitter);
457 
458  if (newfitter->NumSlots() != NumSlots())
459  break;
460 
461  nuse = 0;
462  while (nuse < numuse) {
463  TGo4FitSlot *slot = newfitter->GetSlot(use[nuse++]);
464  slot->SetObject(objs->At(nobj), kFALSE);
465  if (nuse == 1)
466  newfitter->SetName(objs->At(nobj)->GetName());
467  if ((nuse == 1) && colnames)
468  colnames->Add(new TObjString(objs->At(nobj)->GetName()));
469  nobj++;
470  }
471 
472  newfitter->DoActions();
473 
474  resf = newfitter;
475 
476  } while (nobj <= objs->GetLast());
477 
478  } else {
479 
480  MemorizePars();
481 
482  Int_t nobj = 0;
483 
484  do {
485 
486  nuse = 0;
487  while (nuse < numuse) {
488  TGo4FitSlot *slot = GetSlot(use[nuse++]);
489  slot->SetObject(objs->At(nobj), kFALSE);
490  if ((nuse == 1) && colnames)
491  colnames->Add(new TObjString(objs->At(nobj)->GetName()));
492  nobj++;
493  }
494 
495  RememberPars();
496 
497  DoActions();
498 
499  res->Add(new TVectorD(0, GetNumResults() - 1, GetResults()->GetArray()));
500 
501  } while (nobj <= objs->GetLast());
502 
503  RememberPars();
504 
505  resf = this;
506  }
507 
508  if (rownames && resf) {
509  if (resf->IsParsAsResults())
510  for (Int_t n = 0; n < resf->NumPars(); n++)
511  rownames->Add(new TObjString(resf->GetParFullName(n)));
512  else
513  for (Int_t n = 0; n < resf->GetNumResults(); n++) {
514  TString rname("Result");
515  rname += n;
516  rownames->Add(new TObjString(rname));
517  }
518  }
519  nuse = 0;
520  while (nuse < numuse) {
521  TGo4FitSlot *slot = GetSlot(use[nuse++]);
522  slot->SetObject(nullptr, kFALSE);
523  }
524 
525  return res;
526 }
527 
529 {
530  TGo4FitMinuit *fMinuit = new TGo4FitMinuit("Minuit");
531  fMinuit->AddCommand("MIGRAD 500 1");
532  AddAction(fMinuit);
533 }
534 
535 TGo4FitterOutput *TGo4FitterAbstract::AddOutputAction(const char *Action, const char *Option)
536 {
537  TGo4FitterOutput *act = new TGo4FitterOutput(Action, Option);
538  AddAction(act);
539  return act;
540 }
541 
543 {
544  for (Int_t n = 0; n <= fxActions.GetLast(); n++) {
545  TGo4FitterOutput *action = dynamic_cast<TGo4FitterOutput *>(fxActions[n]);
546  if (action) {
547  fxActions.Remove(action);
548  delete action;
549  }
550  }
551  fxActions.Compress();
552 }
553 
555 {
556  Int_t res = 0;
557  for (Int_t n = 0; n < GetNumActions(); n++) {
558  TGo4FitterOutput *act = dynamic_cast<TGo4FitterOutput *>(GetAction(n));
559  if (act && act->NeedPad())
560  res++;
561  }
562  return res;
563 }
564 
565 void TGo4FitterAbstract::SetPad(Int_t indx, TVirtualPad *pad)
566 {
567  Int_t i = 1; // puds numbering starts from 1
568  for (Int_t n = 0; n < GetNumActions(); n++) {
569  TGo4FitterOutput *act = dynamic_cast<TGo4FitterOutput *>(GetAction(n));
570  if (act && act->NeedPad()) {
571  if (i == indx) {
572  act->SetPad(pad);
573  return;
574  }
575  i++;
576  }
577  }
578 }
579 
580 Double_t TGo4FitterAbstract::GetResultValue(Int_t n) const
581 {
582  if ((n >= 0) && (n < GetNumResults()))
583  return fxResults.At(n);
584  return 0.;
585 }
586 
588 {
589  if (fxResults.GetSize() < 2)
590  return 0;
591  return fxResults.GetArray()[fxResults.GetSize() - 1];
592 }
593 
595 {
596  if (fxResults.GetSize() < 2)
597  return 0.;
598  return fxResults.GetArray()[fxResults.GetSize() - 2];
599 }
600 
602 {
603  std::cout << std::endl << "*** LIST OF RESULT VALUE ***" << std::endl;
604  std::cout << " Fit function = " << GetResultFF() << std::endl;
605  std::cout << " NDF = " << GetResultNDF() << std::endl;
606  for (Int_t n = 0; n < GetNumResults(); n++)
607  std::cout << " Res " << n << " = " << GetResultValue(n) << std::endl;
608 }
609 
610 void TGo4FitterAbstract::Print(Option_t *option) const
611 {
612  std::cout << std::endl << "********** THIS IS PRINTOUT OF FITTER OBJECT **********" << std::endl;
613  TGo4FitNamed::Print(option);
614  TGo4FitParsList::Print(option);
615  if (fxActions.GetLast() >= 0) {
616  std::cout << "Actions list: " << std::endl;
617  fxActions.Print(option);
618  }
619 }
620 
621 void TGo4FitterAbstract::Streamer(TBuffer &b)
622 {
623  if (b.IsReading()) {
624  TGo4FitterAbstract::Class()->ReadBuffer(b, this);
625  } else {
627  TGo4FitterAbstract::Class()->WriteBuffer(b, this);
628  }
629 }
Double_t GetValue() const
virtual void FinalizeFitterData()
void Print(Option_t *option="") const override
TObjArray & GetResults()
void DoAction(TGo4FitterAction *Action)
TGo4FitSlot * GetSlot(Int_t nslot)
void DeleteAction(TGo4FitterAction *action)
virtual Double_t DoCalculation()
Bool_t NeedPad() const
virtual Bool_t GetParEpsilon(const char *ParName, Double_t &Epsilon)
void AddCommand(const char *iCommand)
virtual void MemorizePars()
void AddAction(TGo4FitterAction *Action)
virtual Bool_t GetParEpsilon(const char *ParName, Double_t &Epsilon)
const TArrayD * GetResults()
virtual Bool_t InitFitterData()
const char * GetFullName()
void Initialize(Int_t iNumPar, const char *iFormula)
void ReplaceAction(TGo4FitterAction *action, Int_t dir)
Bool_t IsParsAsResults() const
void CopyParsValuesFrom(TGo4FitterAbstract *fitter)
void RunDependenciesList(TObjArray &Dependencies, Double_t *pars)
void FinalizeDependencies(TObjArray &Dependencies)
Int_t NumPars() override
void PrepareSlotsForWriting()
virtual Bool_t CanChangeFitter() const
TClass * GetClass() const
Definition: TGo4FitSlot.h:61
virtual void DoAction(TGo4FitterAbstract *)=0
TObjArray & GetParsDepend()
virtual void CollectAllPars()
virtual Bool_t GetParFixed(const char *ParName)
Bool_t GetParEpsilon(const char *ParName, Double_t &Epsilon) override
void SetPad(TVirtualPad *iPad)
Bool_t SetObject(TObject *iObject, Bool_t iOwned=kFALSE, Bool_t CheckClass=kTRUE)
const char * GetParFullName(Int_t n)
Bool_t IsSuitable(TObject *obj) const
Definition: TGo4FitSlot.cxx:92
TGo4FitterConfig * fxCurrentConfig
TGo4FitParameter * FindPar(const char *ParName)
Double_t GetResultFF() const
virtual Bool_t GetParRange(const char *ParName, Double_t &RangeMin, Double_t &RangeMax)
const TString & GetParameter() const
Bool_t GetParFixed(const char *ParName) override
TGo4FitParameter * Find(const char *ParName)
Bool_t InitializeDependencies(TObjArray &Dependencies, Bool_t BlockPars, Bool_t DoInit)
TGo4FitParameter * Get(Int_t n) override
Bool_t CheckObjects(Bool_t MakeOut=kTRUE)
Bool_t IsRequired() const
Definition: TGo4FitSlot.h:192
Int_t GetParIndex(const TGo4FitParameter *par)
void Print(Option_t *option="") const override
virtual Bool_t GetParFixed(const char *ParName)
void SetValue(Double_t iValue)
virtual void RememberPars()
TGo4FitterAction * GetAction(Int_t num)
Int_t GetNumResults() const
virtual Bool_t Initialize()
virtual Bool_t NeedBuffers() const
TGo4FitterOutput * AddOutputAction(const char *Action, const char *Option=nullptr)
Double_t CalculateFitFunction(Double_t *pars=nullptr)
TObject * GetObject() const
void Clear(Option_t *option="") override
TObjArray * ProcessObjects(TObjArray *objs, Bool_t CloneFitter=kTRUE, Bool_t OnlyRequired=kTRUE, TObjArray *rownames=nullptr, TObjArray *colnames=nullptr)
TGo4FitParsList & GetParsNew()
void SetPad(Int_t indx, TVirtualPad *pad)
Double_t GetResultValue(Int_t n) const
Bool_t GetParRange(const char *ParName, Double_t &RangeMin, Double_t &RangeMax) override
void AddActionAt(TGo4FitterAction *Action, Int_t indx)
void Print(Option_t *option="") const override
Int_t GetNumActions() const
Double_t ExecuteDependency(Double_t *Params)
Bool_t IsSuitableConfig(TGo4FitterConfig *Config)
void GetParsValues(Double_t *pars)
void DoActions(Bool_t AllowFitterChange=kFALSE, TObjArray *Actions=nullptr)
Bool_t ApplyConfig(TGo4FitterConfig *Config)
virtual Int_t DoNDFCalculation()
virtual void CollectParsTo(TGo4FitParsList &list)
const TString & GetExpression() const
virtual Bool_t GetParRange(const char *ParName, Double_t &RangeMin, Double_t &RangeMax)
TObjArray & GetParsInit()
void ExecuteDependencies(Double_t *pars)
void SetParsValues(Double_t *pars)