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