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