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