00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "TGo4FitterAbstract.h"
00015
00016 #include "Riostream.h"
00017
00018 #include "TArrayD.h"
00019 #include "TArrayI.h"
00020 #include "TVectorD.h"
00021 #include "TFormula.h"
00022 #include "TClass.h"
00023 #include "TString.h"
00024 #include "TObjString.h"
00025 #include "TVirtualPad.h"
00026
00027 #include "TGo4FitterConfig.h"
00028 #include "TGo4FitDependency.h"
00029 #include "TGo4FitterAction.h"
00030 #include "TGo4FitterOutput.h"
00031 #include "TGo4FitMinuit.h"
00032 #include "TGo4FitParameter.h"
00033
00034
00035 TGo4FitterAbstract::TGo4FitterAbstract() :
00036 TGo4FitParsList(), TGo4FitSlotList(),
00037 fxActions(), fxResults(),
00038 fxCurrentConfig(0), fbParsChange(kTRUE),
00039 fbInitializationDone(kFALSE), fbNeedToFinalize(kFALSE), fbParsAsResults(kFALSE)
00040 {
00041 }
00042
00043 TGo4FitterAbstract::TGo4FitterAbstract(const char * iName, const char * iTitle) :
00044 TGo4FitParsList(iName,iTitle,kFALSE), TGo4FitSlotList(),
00045 fxActions(), fxResults(),
00046 fxCurrentConfig(0), fbParsChange(kTRUE),
00047 fbInitializationDone(kFALSE), fbNeedToFinalize(kFALSE), fbParsAsResults(kFALSE)
00048 {
00049 fxActions.SetOwner(kTRUE);
00050 }
00051
00052 TGo4FitterAbstract::~TGo4FitterAbstract()
00053 {
00054 if (fbNeedToFinalize) Finalize();
00055 }
00056
00057 void TGo4FitterAbstract::Clear(Option_t* option)
00058 {
00059 TGo4FitParsList::Clear(option);
00060 DeleteActions();
00061 }
00062
00063 void TGo4FitterAbstract::CollectAllPars()
00064 {
00065 ClearPars();
00066 if (fxCurrentConfig)
00067 fxCurrentConfig->GetParsNew().CollectParsTo(*this);
00068 fbParsChange = kFALSE;
00069 }
00070
00071 void TGo4FitterAbstract::CopyParsValuesFrom(TGo4FitterAbstract* fitter)
00072 {
00073 if (fitter==0) return;
00074 fitter->CollectAllPars();
00075 CollectAllPars();
00076
00077 for(Int_t n=0;n<NumPars();n++) {
00078 TGo4FitParameter* dest = Get(n);
00079 const TGo4FitParameter* src = fitter->FindPar(dest->GetFullName());
00080 if (src!=0) dest->SetValue(src->GetValue());
00081 }
00082 }
00083
00084 Bool_t TGo4FitterAbstract::GetParFixed(const char* ParName)
00085 {
00086 Bool_t fixed = TGo4FitParsList::GetParFixed(ParName);
00087 if (fxCurrentConfig && !fixed)
00088 fixed = fxCurrentConfig->GetParFixed(ParName);
00089 return fixed;
00090 }
00091
00092 Bool_t TGo4FitterAbstract::GetParRange(const char* ParName, Double_t& RangeMin, Double_t& RangeMax)
00093 {
00094 Bool_t get = kFALSE;
00095 if (fxCurrentConfig)
00096 get = fxCurrentConfig->GetParRange(ParName,RangeMin,RangeMax);
00097 if (!get) get = TGo4FitParsList::GetParRange(ParName,RangeMin,RangeMax);
00098 return get;
00099 }
00100
00101 Bool_t TGo4FitterAbstract::GetParEpsilon(const char* ParName, Double_t& Epsilon)
00102 {
00103 Bool_t get = kFALSE;
00104 if (fxCurrentConfig)
00105 get = fxCurrentConfig->GetParEpsilon(ParName,Epsilon);
00106 if (!get) get = TGo4FitParsList::GetParEpsilon(ParName,Epsilon);
00107 return get;
00108 }
00109
00110
00111 Bool_t TGo4FitterAbstract::InitializeDependencies(TObjArray& Dependencies, Bool_t BlockPars, Bool_t DoInit)
00112 {
00113 for(Int_t i=0;i<=Dependencies.GetLast();i++) {
00114 TGo4FitDependency *dep = (TGo4FitDependency*) Dependencies[i];
00115
00116 Int_t parindx = 0;
00117 TGo4FitParameter* deppar = 0;
00118 if (dep->GetParameter().Length()==0) parindx=-1; else {
00119 deppar = Find(dep->GetParameter().Data());
00120 if (deppar==0) { cout << "Error dependence parameter: " << dep->GetParameter().Data() << endl; return kFALSE; }
00121 parindx = GetParIndex(deppar);
00122 }
00123
00124 if (dep->GetExpression().Length()>0) {
00125 TString formula(dep->GetExpression().Data());
00126 for(Int_t n=0;n<NumPars();n++) {
00127 if (n == parindx) continue;
00128 TString repl("[");
00129 repl+=n;
00130 repl+="]";
00131 formula.ReplaceAll(GetParFullName(n),repl);
00132 }
00133 TFormula* fx = new TFormula("test",formula.Data());
00134 Int_t err = fx->Compile(formula.Data());
00135 delete fx;
00136 if (err!=0) {
00137 cout << "Error in dependence: " << formula.Data() << " code " << err << endl;
00138 return kFALSE;
00139 }
00140 if (DoInit) dep->Initialize(parindx, formula.Data());
00141
00142 } else if (DoInit) dep->Initialize(parindx,0);
00143
00144 if (BlockPars) deppar->SetBlocked();
00145 }
00146 return kTRUE;
00147 }
00148
00149 void TGo4FitterAbstract::RunDependenciesList(TObjArray& Dependencies, Double_t* pars)
00150 {
00151 for(Int_t i=0;i<=Dependencies.GetLast();i++)
00152 ((TGo4FitDependency*) Dependencies[i]) -> ExecuteDependency(pars);
00153 }
00154
00155 void TGo4FitterAbstract::FinalizeDependencies(TObjArray& Dependencies)
00156 {
00157 for(Int_t i=0;i<=Dependencies.GetLast();i++) {
00158 TGo4FitDependency *dep = (TGo4FitDependency*) Dependencies[i];
00159 dep->Finalize();
00160 }
00161 }
00162
00163 void TGo4FitterAbstract::ExecuteDependencies(Double_t* pars)
00164 {
00165 if ((pars!=0) && (fxCurrentConfig!=0))
00166 RunDependenciesList(fxCurrentConfig->GetParsDepend(), pars );
00167 }
00168
00169 Bool_t TGo4FitterAbstract::IsSuitableConfig(TGo4FitterConfig* Config)
00170 {
00171 if (Config==0) return kFALSE;
00172 Bool_t res = kTRUE;
00173 try {
00174 fxCurrentConfig=Config;
00175 CollectAllPars();
00176 res = InitializeDependencies(Config->GetParsInit(), kFALSE,kFALSE);
00177 res = res && InitializeDependencies(Config->GetParsDepend(), kFALSE,kFALSE);
00178 res = res && InitializeDependencies(Config->GetResults(), kFALSE,kFALSE);
00179
00180 fxCurrentConfig=0;
00181 CollectAllPars();
00182
00183 } catch(...) {
00184 fxCurrentConfig=0;
00185 CollectAllPars();
00186 throw;
00187 }
00188
00189 return res;
00190 }
00191
00192 Bool_t TGo4FitterAbstract::ApplyConfig(TGo4FitterConfig* Config)
00193 {
00194 if (fxCurrentConfig!=0) {
00195 FinalizeDependencies(fxCurrentConfig->GetParsInit());
00196 FinalizeDependencies(fxCurrentConfig->GetParsDepend());
00197 FinalizeDependencies(fxCurrentConfig->GetResults());
00198 }
00199
00200 fxCurrentConfig = Config;
00201 CollectAllPars();
00202
00203 Bool_t res = kTRUE;
00204
00205 if (fxCurrentConfig) {
00206 res = res && InitializeDependencies(fxCurrentConfig->GetParsInit(), kFALSE, kTRUE);
00207 res = res && InitializeDependencies(fxCurrentConfig->GetParsDepend(), kTRUE, kTRUE);
00208 res = res && InitializeDependencies(fxCurrentConfig->GetResults(), kFALSE, kTRUE);
00209
00210 if (res) {
00211 TArrayD pars(NumPars());
00212 GetParsValues(pars.GetArray());
00213 RunDependenciesList(fxCurrentConfig->GetParsInit(), pars.GetArray() );
00214 SetParsValues(pars.GetArray());
00215 }
00216 }
00217
00218 if (!res) {
00219 FinalizeDependencies(fxCurrentConfig->GetParsInit());
00220 FinalizeDependencies(fxCurrentConfig->GetParsDepend());
00221 FinalizeDependencies(fxCurrentConfig->GetResults());
00222 fxCurrentConfig = 0;
00223 }
00224
00225 return res;
00226 }
00227
00228 Bool_t TGo4FitterAbstract::Initialize()
00229 {
00230 if (fbNeedToFinalize) Finalize();
00231 fbInitializationDone=kFALSE;
00232
00233 if (!CheckObjects()) return kFALSE;
00234
00235 fbNeedToFinalize = kTRUE;
00236
00237 CollectAllPars();
00238
00239 ClearParsBlocking();
00240
00241 if (!InitFitterData()) return kFALSE;
00242
00243 fbInitializationDone=kTRUE;
00244
00245 return kTRUE;
00246 }
00247
00248 Double_t TGo4FitterAbstract::CalculateFitFunction(Double_t* pars)
00249 {
00250 if (pars!=0) {
00251 ExecuteDependencies(pars);
00252 SetParsValues(pars);
00253 }
00254
00255 return DoCalculation();
00256 }
00257
00258 void TGo4FitterAbstract::Finalize()
00259 {
00260 Double_t FF = DoCalculation();
00261 Int_t NDF = DoNDFCalculation();
00262
00263 FinalizeFitterData();
00264
00265 if ((fxCurrentConfig!=0) && (fxCurrentConfig->GetResults().GetLast()>=0)) {
00266 TArrayD pars(NumPars());
00267 GetParsValues(pars.GetArray());
00268 fxResults.Set(fxCurrentConfig->GetResults().GetLast()+3);
00269
00270 for(Int_t i=0;i<=fxCurrentConfig->GetResults().GetLast();i++) {
00271 TGo4FitDependency *res = (TGo4FitDependency*) (fxCurrentConfig->GetResults())[i];
00272 fxResults[i] = res->ExecuteDependency(pars.GetArray());
00273 }
00274 } else {
00275 fxResults.Set(NumPars()+2);
00276 GetParsValues(fxResults.GetArray());
00277 }
00278
00279 fxResults[fxResults.GetSize()-2] = FF;
00280 fxResults[fxResults.GetSize()-1] = NDF;
00281
00282 if (fxCurrentConfig!=0)
00283 ApplyConfig(0);
00284
00285 fbNeedToFinalize = kFALSE;
00286 fbInitializationDone=kFALSE;
00287 }
00288
00289 void TGo4FitterAbstract::AddAction(TGo4FitterAction* Action)
00290 {
00291 fxActions.Add(Action);
00292 }
00293
00294 void TGo4FitterAbstract::AddActionAt(TGo4FitterAction* Action, Int_t indx)
00295 {
00296 fxActions.AddAt(Action, indx);
00297 }
00298
00299 TGo4FitterAction* TGo4FitterAbstract::GetAction(Int_t num)
00300 {
00301 if ((num<0) || (num>fxActions.GetLast())) return 0;
00302 return dynamic_cast<TGo4FitterAction*> (fxActions[num]);
00303 }
00304
00305 void TGo4FitterAbstract::DeleteAction(TGo4FitterAction* action)
00306 {
00307 if (action==0) return;
00308 if (fxActions.IndexOf(action)>=0) {
00309 fxActions.Remove(action);
00310 fxActions.Compress();
00311 }
00312 delete action;
00313 }
00314
00315 void TGo4FitterAbstract::ReplaceAction(TGo4FitterAction* action, Int_t dir)
00316 {
00317 Int_t indx = fxActions.IndexOf(action);
00318 if ((action==0) || (indx<0)) return;
00319 Int_t newindx = indx+dir;
00320 if ((newindx>=0) && (newindx<=fxActions.GetLast()) && (newindx!=indx)) {
00321 fxActions[indx] = fxActions[newindx];
00322 fxActions[newindx] = action;
00323 }
00324 }
00325
00326 void TGo4FitterAbstract::DoActions(Bool_t AllowFitterChange, TObjArray* Actions)
00327 {
00328 if (Actions==0) Actions = &fxActions;
00329
00330 Bool_t need = kFALSE;
00331 for(Int_t n=0;n<=Actions->GetLast();n++) {
00332 TGo4FitterAction* action = dynamic_cast<TGo4FitterAction*> (Actions->At(n));
00333 if (action)
00334 need = need || action->NeedBuffers();
00335 }
00336 if (need)
00337 if (!Initialize()) return;
00338
00339 for(Int_t n=0;n<=Actions->GetLast();n++) {
00340 TGo4FitterAction* action = dynamic_cast<TGo4FitterAction*> (Actions->At(n));
00341 if (action==0) continue;
00342 if (!AllowFitterChange && action->CanChangeFitter()) continue;
00343
00344 action->DoAction(this);
00345 CheckParsListChanging();
00346 }
00347
00348 if (need) Finalize();
00349 }
00350
00351 void TGo4FitterAbstract::DoAction(TGo4FitterAction* Action)
00352 {
00353 if (Action==0) return;
00354
00355 Bool_t need = Action->NeedBuffers();
00356
00357 if (need)
00358 if (!Initialize()) return;
00359
00360 Action->DoAction(this);
00361
00362 if (need) Finalize();
00363 }
00364
00365 void TGo4FitterAbstract::DoAction(Int_t indx)
00366 {
00367 DoAction(GetAction(indx));
00368 }
00369
00370 TObjArray* TGo4FitterAbstract::ProcessObjects(TObjArray* objs, Bool_t CloneFitter, Bool_t OnlyRequired, TObjArray* rownames, TObjArray* colnames)
00371 {
00372 if ((objs==0) || (objs->GetLast()<0)) return 0;
00373
00374 if (NumSlots()<=0) return 0;
00375
00376 TArrayI use(NumSlots()); use.Reset(-1);
00377
00378 Int_t numuse = 0;
00379 for (Int_t n=0;n<NumSlots();n++) {
00380 TGo4FitSlot* slot = GetSlot(n);
00381 if (slot==0) return 0;
00382 if (slot->GetObject()==0)
00383 if (slot->IsRequired() || !OnlyRequired) use[numuse++] = n;
00384 }
00385
00386 if ((numuse==0) || ((objs->GetLast()+1) % numuse != 0)) return 0;
00387
00388 Int_t nuse = 0;
00389 for (Int_t nobj=0;nobj<=objs->GetLast();nobj++) {
00390 TObject* obj = objs->At(nobj);
00391 if (obj==0) {
00392 cout << "Empty object in list" << endl;
00393 return 0;
00394 }
00395 TGo4FitSlot* slot = GetSlot(use[nuse++]);
00396 if (nuse==numuse) nuse=0;
00397 if (!slot->IsSuitable(obj)) {
00398 cout << "Object " << obj->GetName() << " of class " << obj->ClassName() <<
00399 " noncompatible with " << slot->GetClass()->GetName() << endl;
00400 return 0;
00401 }
00402 }
00403
00404 TObjArray* res = new TObjArray((objs->GetLast()+1) / numuse);
00405 res->SetOwner(kTRUE);
00406 TGo4FitterAbstract* resf = 0;
00407
00408 if (rownames!=0) { rownames->Clear(); rownames->SetOwner(kTRUE); }
00409 if (colnames!=0) { colnames->Clear(); colnames->SetOwner(kTRUE); }
00410
00411 if (CloneFitter) {
00412
00413 Int_t nobj = 0;
00414
00415 do {
00416 TGo4FitterAbstract* newfitter = dynamic_cast<TGo4FitterAbstract*> (Clone());
00417 if (newfitter==0) break;
00418 res->Add(newfitter);
00419
00420 if (newfitter->NumSlots()!=NumSlots()) break;
00421
00422 nuse = 0;
00423 while(nuse<numuse) {
00424 TGo4FitSlot* slot = newfitter->GetSlot(use[nuse++]);
00425 slot->SetObject(objs->At(nobj), kFALSE);
00426 if (nuse==1) newfitter->SetName(objs->At(nobj)->GetName());
00427 if ((nuse==1) && (colnames!=0)) colnames->Add(new TObjString(objs->At(nobj)->GetName()));
00428 nobj++;
00429 }
00430
00431 newfitter->DoActions();
00432
00433 resf = newfitter;
00434
00435 } while (nobj<=objs->GetLast());
00436
00437
00438 } else {
00439
00440 MemorizePars();
00441
00442 Int_t nobj = 0;
00443
00444 do {
00445
00446 nuse = 0;
00447 while(nuse<numuse) {
00448 TGo4FitSlot* slot = GetSlot(use[nuse++]);
00449 slot->SetObject(objs->At(nobj), kFALSE);
00450 if ((nuse==1) && (colnames!=0)) colnames->Add(new TObjString(objs->At(nobj)->GetName()));
00451 nobj++;
00452 }
00453
00454 RememberPars();
00455
00456 DoActions();
00457
00458 res->Add(new TVectorD(0, GetNumResults()-1, GetResults()->GetArray()));
00459
00460 } while (nobj<=objs->GetLast());
00461
00462 RememberPars();
00463
00464 resf = this;
00465 }
00466
00467 if ((rownames!=0) && (resf!=0)){
00468 if (resf->IsParsAsResults())
00469 for(Int_t n=0;n<resf->NumPars();n++) rownames->Add(new TObjString(resf->GetParFullName(n)));
00470 else
00471 for(Int_t n=0;n<resf->GetNumResults();n++) {
00472 TString rname("Result");
00473 rname+=n;
00474 rownames->Add(new TObjString(rname));
00475 }
00476 }
00477 nuse = 0;
00478 while(nuse<numuse) {
00479 TGo4FitSlot* slot = GetSlot(use[nuse++]);
00480 slot->SetObject(0, kFALSE);
00481 }
00482
00483 return res;
00484 }
00485
00486 void TGo4FitterAbstract::AddSimpleMinuit()
00487 {
00488 TGo4FitMinuit* fMinuit = new TGo4FitMinuit("Minuit");
00489 fMinuit->AddCommand("MIGRAD 500 1");
00490 AddAction(fMinuit);
00491 }
00492
00493 TGo4FitterOutput* TGo4FitterAbstract::AddOutputAction(const char* Action, const char* Option)
00494 {
00495 TGo4FitterOutput* act = new TGo4FitterOutput(Action,Option);
00496 AddAction(act);
00497 return act;
00498 }
00499
00500 void TGo4FitterAbstract::DeleteOutputActions()
00501 {
00502 for(Int_t n=0;n<=fxActions.GetLast();n++) {
00503 TGo4FitterOutput* action = dynamic_cast<TGo4FitterOutput*> (fxActions[n]);
00504 if (action) { fxActions.Remove(action); delete action; }
00505 }
00506 fxActions.Compress();
00507 }
00508
00509 Int_t TGo4FitterAbstract::NeedPadsNumber()
00510 {
00511 Int_t res = 0;
00512 for(Int_t n=0;n<GetNumActions(); n++) {
00513 TGo4FitterOutput* act = dynamic_cast<TGo4FitterOutput*> (GetAction(n));
00514 if (act && act->NeedPad()) res++;
00515 }
00516 return res;
00517 }
00518
00519 void TGo4FitterAbstract::SetPad(Int_t indx, TVirtualPad* pad)
00520 {
00521 Int_t i = 1;
00522 for(Int_t n=0;n<GetNumActions(); n++) {
00523 TGo4FitterOutput* act = dynamic_cast<TGo4FitterOutput*> (GetAction(n));
00524 if (act && act->NeedPad()) {
00525 if (i==indx) { act->SetPad(pad); return; }
00526 i++;
00527 }
00528 }
00529 }
00530
00531 Double_t TGo4FitterAbstract::GetResultValue(Int_t n) const
00532 {
00533 if ((n>=0) && (n<GetNumResults())) return fxResults[n];
00534 else return 0.;
00535 }
00536
00537 Double_t TGo4FitterAbstract::GetResultFF() const
00538 {
00539 if (fxResults.GetSize()>1) return fxResults[fxResults.GetSize()-2];
00540 else return 0;
00541 }
00542
00543 Int_t TGo4FitterAbstract::GetResultNDF() const
00544 {
00545 if (fxResults.GetSize()>1) return Int_t(fxResults[fxResults.GetSize()-1]);
00546 else return 0;
00547 }
00548
00549 void TGo4FitterAbstract::PrintResults() const
00550 {
00551 cout << endl << "*** LIST OF RESULT VALUE ***" << endl;
00552 cout << " Fit function = " << GetResultFF() << endl;
00553 cout << " NDF = " << GetResultNDF() << endl;
00554 for(Int_t n=0;n<GetNumResults();n++)
00555 cout << " Res " << n << " = " << GetResultValue(n) << endl;
00556 }
00557
00558 void TGo4FitterAbstract::Print(Option_t* option) const
00559 {
00560 cout << endl << "********** THIS IS PRINTOUT OF FITTER OBJECT **********" << endl;
00561 TGo4FitNamed::Print(option);
00562 TGo4FitParsList::Print(option);
00563 if (fxActions.GetLast()>=0) {
00564 cout << "Actions list: " << endl;
00565 fxActions.Print(option);
00566 }
00567 }
00568
00569 void TGo4FitterAbstract::Streamer(TBuffer& b)
00570 {
00571 if (b.IsReading()) {
00572 TGo4FitterAbstract::Class()->ReadBuffer(b, this);
00573 } else {
00574 PrepareSlotsForWriting();
00575 TGo4FitterAbstract::Class()->WriteBuffer(b, this);
00576 }
00577 }