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