TGo4Fitter.cxx

Go to the documentation of this file.
00001 // $Id: TGo4Fitter.cxx 610 2010-04-06 15:50:06Z linev $
00002 //-----------------------------------------------------------------------
00003 //       The GSI Online Offline Object Oriented (Go4) Project
00004 //         Experiment Data Processing at EE department, GSI
00005 //-----------------------------------------------------------------------
00006 // Copyright (C) 2000- GSI Helmholtzzentrum für Schwerionenforschung GmbH
00007 //                     Planckstr. 1, 64291 Darmstadt, Germany
00008 // Contact:            http://go4.gsi.de
00009 //-----------------------------------------------------------------------
00010 // This software can be used under the license agreements as stated
00011 // in Go4License.txt file which is part of the distribution.
00012 //-----------------------------------------------------------------------
00013 
00014 #include "TGo4Fitter.h"
00015 
00016 #include <stdlib.h>
00017 
00018 #include "Riostream.h"
00019 #include "TClass.h"
00020 #include "TMath.h"
00021 #include "TH1.h"
00022 #include "TGraph.h"
00023 #include "TCanvas.h"
00024 #include "TObjArray.h"
00025 #include "TObjString.h"
00026 #include "TROOT.h"
00027 #include "THStack.h"
00028 #include "TArrayD.h"
00029 
00030 #include "TGo4FitData.h"
00031 #include "TGo4FitDataHistogram.h"
00032 #include "TGo4FitDataGraph.h"
00033 #include "TGo4FitModel.h"
00034 #include "TGo4FitModelGauss1.h"
00035 #include "TGo4FitModelGauss2.h"
00036 #include "TGo4FitModelPolynom.h"
00037 #include "TGo4FitAmplEstimation.h"
00038 #include "TGo4FitSlot.h"
00039 #include "TGo4FitMinuit.h"
00040 
00041 TGo4Fitter::TGo4Fitter() :
00042    TGo4FitterAbstract(),
00043    fxDatas(), fxModels(), fiFitFunctionType(0), fiMemoryUsage(0),
00044    fxUserFitFunction(0), fxDrawObjs(0)
00045 {
00046 }
00047 
00048 TGo4Fitter::TGo4Fitter(const char* iName, const char* iTitle) :
00049    TGo4FitterAbstract(iName, iTitle),
00050    fxDatas(), fxModels(), fiFitFunctionType(0), fiMemoryUsage(0), fxUserFitFunction(0), fxDrawObjs(0)
00051 {
00052    fxDatas.SetOwner(kTRUE);
00053    fxModels.SetOwner(kTRUE);
00054 }
00055 
00056 TGo4Fitter::TGo4Fitter(const char* iName, Int_t iFitFunctionType, Bool_t IsAddStandardActions) :
00057    TGo4FitterAbstract(iName,"TGo4Fitter object"),
00058    fxDatas(), fxModels(), fiFitFunctionType(0), fiMemoryUsage(100), fxUserFitFunction(0), fxDrawObjs(0)
00059 {
00060    fxDatas.SetOwner(kTRUE);
00061    fxModels.SetOwner(kTRUE);
00062    SetFitFunctionType(iFitFunctionType);
00063    if (IsAddStandardActions) AddStandardActions();
00064 }
00065 
00066 TGo4Fitter::~TGo4Fitter()
00067 {
00068    CheckDuplicatesOnSlot();
00069    MoveDrawObjectsToROOT();
00070 }
00071 
00072 void TGo4Fitter::SetMemoryUsage(Int_t iMemoryUsage)
00073 {
00074   if (iMemoryUsage<0) fiMemoryUsage=0; else
00075     if (iMemoryUsage>100) fiMemoryUsage=100; else
00076       fiMemoryUsage = iMemoryUsage;
00077 }
00078 
00079 void TGo4Fitter::CollectAllPars()
00080 {
00081    TGo4FitterAbstract::CollectAllPars();
00082 
00083    for(Int_t ndata=0;ndata<GetNumData();ndata++)
00084      GetData(ndata)->CollectParsTo(*this);
00085 
00086    for(Int_t nmodel=0;nmodel<GetNumModel();nmodel++) {
00087      TGo4FitModel* model = GetModel(nmodel);
00088      for (Int_t n=0;n<model->NumAssigments();n++)
00089        if (FindData(model->AssignmentName(n))) {
00090           model->CollectParsTo(*this);
00091           break;
00092        }
00093    }
00094 }
00095 
00096 void TGo4Fitter::Clear(Option_t* option)
00097 {
00098    TGo4FitterAbstract::Clear(option);
00099    DeleteAllData();
00100    DeleteAllModels();
00101 }
00102 
00103 TGo4FitData* TGo4Fitter::GetData(Int_t n)
00104 {
00105    return (n>=0) && (n<GetNumData()) ? dynamic_cast<TGo4FitData*> (fxDatas[n]) : 0;
00106 }
00107 
00108 const char* TGo4Fitter::GetDataName(Int_t n)
00109 {
00110    return GetData(n) ? GetData(n)->GetName() : 0;
00111 }
00112 
00113 TGo4FitData* TGo4Fitter::FindData(const char* DataName)
00114 {
00115    return (DataName==0) ? 0 : dynamic_cast<TGo4FitData*> (fxDatas.FindObject(DataName));
00116 }
00117 
00118 TGo4FitData* TGo4Fitter::AddData(TGo4FitData* data)
00119 {
00120    fxDatas.Add(data);
00121    SetParsListChange();
00122    SetUpdateSlotList();
00123    return data;
00124 }
00125 
00126 TGo4FitDataHistogram* TGo4Fitter::AddH1(const char* DataName, TH1* histo, Bool_t Owned, Double_t lrange, Double_t rrange)
00127 {
00128    TGo4FitDataHistogram *data = new TGo4FitDataHistogram(DataName, histo, Owned);
00129    if ((lrange<rrange) || (rrange!=0.)) data->SetRange(0,lrange,rrange);
00130    AddData(data);
00131    return data;
00132 }
00133 
00134 TGo4FitDataHistogram* TGo4Fitter::SetH1(const char* DataName, TH1* histo, Bool_t Owned)
00135 {
00136    TGo4FitDataHistogram* data = dynamic_cast<TGo4FitDataHistogram*> (FindData(DataName));
00137    if (data!=0) data->SetHistogram(histo, Owned);
00138    return data;
00139 }
00140 
00141 
00142 TGo4FitDataGraph* TGo4Fitter::AddGraph(const char* DataName, TGraph* gr, Bool_t Owned, Double_t lrange, Double_t rrange)
00143 {
00144    TGo4FitDataGraph *data = new TGo4FitDataGraph(DataName, gr, Owned);
00145    if ((lrange<rrange) || (rrange!=0.)) data->SetRange(0,lrange,rrange);
00146    AddData(data);
00147    return data;
00148 }
00149 
00150 TGo4FitDataGraph* TGo4Fitter::SetGraph(const char* DataName, TGraph* gr, Bool_t Owned)
00151 {
00152    TGo4FitDataGraph *data = dynamic_cast<TGo4FitDataGraph*> (FindData(DataName));
00153    if (data!=0) data->SetGraph(gr, Owned);
00154    return data;
00155 }
00156 
00157 void TGo4Fitter::CheckSlotsBeforeDelete(TGo4FitComponent* comp)
00158 {
00159   if (comp)
00160     for (Int_t n=0;n<comp->NumSlots();n++) {
00161        TGo4FitSlot* slot = comp->GetSlot(n);
00162        ClearSlot(slot, kFALSE);
00163        for(Int_t n2=0;n2<NumSlots();n2++) {
00164          TGo4FitSlot* slot2 = GetSlot(n2);
00165          if (slot2->GetConnectedSlot()==slot)
00166            slot2->ClearConnectionToSlot();
00167        }
00168 
00169     }
00170 }
00171 
00172 TGo4FitData* TGo4Fitter::RemoveData(const char* DataName, Bool_t IsDel)
00173 {
00174    TGo4FitData* dat = FindData(DataName);
00175    if (dat) {
00176       SetParsListChange();
00177       SetUpdateSlotList();
00178       fxDatas.Remove(dat);
00179       if(IsDel) { CheckSlotsBeforeDelete(dat); delete dat; dat = 0; }
00180       fxDatas.Compress();
00181    }
00182    return dat;
00183 }
00184 
00185 void TGo4Fitter::DeleteAllData()
00186 {
00187    fxDatas.Delete();
00188    fxDatas.Compress();
00189    SetParsListChange();
00190    SetUpdateSlotList();
00191 }
00192 
00193 TGo4FitModel* TGo4Fitter::GetModel(Int_t n)
00194 {
00195    return (n>=0) && (n<GetNumModel()) ? dynamic_cast<TGo4FitModel*> (fxModels[n]) : 0;
00196 }
00197 
00198 TGo4FitModel* TGo4Fitter::FindModel(const char* ModelName)
00199 {
00200    return (ModelName==0) ? 0 : dynamic_cast<TGo4FitModel*> (fxModels.FindObject(ModelName));
00201 }
00202 
00203 TGo4FitModel* TGo4Fitter::AddModel(TGo4FitModel* model)
00204 {
00205    fxModels.Add(model);
00206    SetParsListChange();
00207    SetUpdateSlotList();
00208    return model;
00209 }
00210 
00211 TGo4FitModel* TGo4Fitter::AddModel(const char* DataName, TGo4FitModel* model)
00212 {
00213    model->AssignToData(DataName);
00214    fxModels.Add(model);
00215    SetParsListChange();
00216    SetUpdateSlotList();
00217    return model;
00218 }
00219 
00220 TGo4FitComponent* TGo4Fitter::GetComp(Int_t n)
00221 {
00222    if(n<GetNumData()) return GetData(n); else return GetModel(n-GetNumData());
00223 }
00224 
00225 void TGo4Fitter::AddPolynomX(const char* DataName, const char* NamePrefix, Int_t MaxOrder, Int_t GroupIndex, Double_t lrange, Double_t rrange)
00226 {
00227    if (DataName==0) return;
00228 
00229    Bool_t flag = kFALSE;
00230    Int_t NumTry = 0;
00231    Bool_t createmodel = kFALSE;
00232 
00233    do {
00234        TString Prefix(NamePrefix);
00235        if (NumTry>0) Prefix+=NumTry;
00236        flag = kFALSE;
00237        Bool_t findsame = kFALSE;
00238 
00239        for(Int_t Order=0; Order<=MaxOrder; Order++) {
00240          TString Name(Prefix);
00241          Name += "_";
00242          Name += Order;
00243          findsame = FindModel(Name.Data());
00244          if (findsame && !createmodel) break;
00245 
00246          if (createmodel) {
00247            TGo4FitModelPolynom* comp = new TGo4FitModelPolynom(Name, Order);
00248            comp->SetGroupIndex(GroupIndex);
00249            if ((lrange<rrange) || (rrange!=0.)) comp->SetRange(0,lrange,rrange);
00250            AddModel(DataName, comp);
00251          }
00252        }
00253 
00254        flag = kTRUE;
00255        if (findsame) { NumTry++; createmodel = kFALSE; } else
00256          if (createmodel) flag = kFALSE;
00257                      else createmodel = kTRUE;
00258 
00259    } while (flag);
00260 }
00261 
00262 void TGo4Fitter::AddPolynomX(const char* DataName, const char* NamePrefix, TArrayD& Coef, Int_t GroupIndex)
00263 {
00264    if (DataName==0) return;
00265 
00266    Bool_t flag = kFALSE;
00267    Int_t NumTry = 0;
00268    Bool_t createmodel = kFALSE;
00269 
00270    do {
00271        Bool_t findsame = kFALSE;
00272 
00273        for (Int_t n=0;n<Coef.GetSize();n++) {
00274           TString Name(NamePrefix);
00275           if (NumTry>0) Name+=NumTry;
00276           Name+="_";
00277           Name+=n;
00278           findsame = FindModel(Name.Data());
00279           if (findsame && !createmodel) break;
00280 
00281           if (createmodel) {
00282              TGo4FitModelPolynom* model = new TGo4FitModelPolynom(Name, n);
00283              model->SetAmplValue(Coef[n]);
00284              model->SetGroupIndex(GroupIndex);
00285              AddModel(DataName, model);
00286           }
00287        }
00288 
00289        flag = kTRUE;
00290        if (findsame) { NumTry++; createmodel = kFALSE; } else
00291          if (createmodel) flag = kFALSE;
00292                      else createmodel = kTRUE;
00293 
00294    } while(flag);
00295 }
00296 
00297 void TGo4Fitter::AddPolynoms(const char* DataName, const char* NamePrefix, Int_t MaxOrder, Int_t NumAxis, Int_t GroupIndex)
00298 {
00299    if (DataName==0) return;
00300    TArrayD Orders(NumAxis);
00301    Orders.Reset(0.);
00302 
00303    Bool_t flag = kFALSE;
00304    Int_t NumTry = 0;
00305    Bool_t createmodel = kFALSE;
00306 
00307    do {
00308 
00309        TString Prefix(NamePrefix);
00310        if (NumTry>0) Prefix+=NumTry;
00311        flag = kFALSE;
00312        Bool_t findsame = kFALSE;
00313 
00314        do {
00315          TString Name(Prefix);
00316          for(Int_t n=0; n<NumAxis; n++) {
00317             Name+="_";
00318             Name+=Int_t(Orders[n]);
00319          }
00320          findsame = FindModel(Name.Data());
00321          if (findsame && !createmodel) break;
00322 
00323          if (createmodel) {
00324            TGo4FitModelPolynom* comp = new TGo4FitModelPolynom(Name, Orders);
00325            comp->SetGroupIndex(GroupIndex);
00326            AddModel(DataName, comp);
00327          }
00328 
00329          Int_t nn = 0;
00330          do {
00331            Orders[nn] += 1.;
00332            if (Orders[nn]<=MaxOrder) break;
00333            Orders[nn]=0;
00334            nn++;
00335          } while (nn<NumAxis);
00336          flag = (nn<NumAxis);
00337        } while (flag);
00338 
00339        flag = kTRUE;
00340        if (findsame) { NumTry++; createmodel = kFALSE; } else
00341          if (createmodel) flag = kFALSE;
00342                      else createmodel = kTRUE;
00343 
00344    } while (flag);
00345 }
00346 
00347 TGo4FitModelGauss1* TGo4Fitter::AddGauss1(const char* DataName, const char* ModelName, Double_t iPosition, Double_t iWidth, Double_t iAmpl, Int_t Axis)
00348 {
00349    TGo4FitModelGauss1* gauss = new TGo4FitModelGauss1(ModelName, iPosition, iWidth, Axis);
00350    gauss->SetAmplValue(iAmpl);
00351    AddModel(DataName, gauss);
00352    return gauss;
00353 }
00354 
00355 TGo4FitModel* TGo4Fitter::CloneModel(const char* ModelName, const char* NewName)
00356 {
00357    TGo4FitModel* mod = FindModel(ModelName);
00358    if (mod==0) return 0;
00359 
00360    TString newname;
00361    int cnt = 0;
00362 
00363    do {
00364       newname = NewName ? NewName : mod->GetName();
00365       if (cnt>0) {
00366          newname += "_";
00367          newname += cnt;
00368       }
00369       cnt++;
00370    } while (FindModel(newname.Data()));
00371 
00372    TGo4FitModel* newmod = (TGo4FitModel*) mod->Clone(newname.Data());
00373 
00374    return AddModel(newmod);
00375 }
00376 
00377 TGo4FitModel* TGo4Fitter::RemoveModel(const char * ModelName, Bool_t IsDel)
00378 {
00379    TGo4FitModel* mod = FindModel(ModelName);
00380    if (mod) {
00381       SetParsListChange();
00382       SetUpdateSlotList();
00383       fxModels.Remove(mod);
00384       if(IsDel) { CheckSlotsBeforeDelete(mod); delete mod; mod = 0; }
00385       fxModels.Compress();
00386    }
00387    return mod;
00388 }
00389 
00390 Int_t TGo4Fitter::NumModelsAssosiatedTo(const char* DataName)
00391 {
00392    Int_t res = 0;
00393    for (Int_t n=0;n<GetNumModel();n++)
00394       if (GetModel(n)->IsAssignTo(DataName)) res++;
00395    return res;
00396 }
00397 
00398 void TGo4Fitter::DeleteModelsAssosiatedTo(const char* DataName)
00399 {
00400    Int_t n=0;
00401    while (n<GetNumModel()) {
00402       TGo4FitModel* model = GetModel(n++);
00403       if (model->IsAssignTo(DataName)){
00404         if (model->NumAssigments()==1) {
00405            SetParsListChange();
00406            SetUpdateSlotList();
00407            fxModels.Remove(model);
00408            delete model;
00409            fxModels.Compress();
00410            n--;
00411         } else model->ClearAssignmentTo(DataName);
00412       }
00413    }
00414 }
00415 
00416 void TGo4Fitter::DeleteAllModels()
00417 {
00418    fxModels.Delete();
00419    fxModels.Compress();
00420    SetParsListChange();
00421    SetUpdateSlotList();
00422 }
00423 
00424 void TGo4Fitter::AssignModelTo(const char* ModelName, const char* DataName, Double_t RatioValue, Bool_t FixRatio)
00425 {
00426   TGo4FitModel* model = FindModel(ModelName);
00427   if (model) {
00428      if (DataName!=0)
00429         model->AssignToData(DataName, RatioValue, FixRatio);
00430      else {
00431         model->ClearAssignments();
00432         for (int n=0; n<GetNumData(); n++)
00433            model->AssignToData(GetData(n)->GetName(), RatioValue, FixRatio);
00434      }
00435      SetParsListChange();
00436   }
00437 }
00438 
00439 void TGo4Fitter::ClearModelAssignmentTo(const char* ModelName, const char* DataName)
00440 {
00441    TGo4FitModel* model = FindModel(ModelName);
00442    if (model==0) return;
00443    if (DataName!=0) model->ClearAssignmentTo(DataName);
00444                else model->ClearAssignments();
00445    SetParsListChange();
00446 }
00447 
00448 void TGo4Fitter::ChangeDataNameInAssignments(const char* oldname, const char* newname)
00449 {
00450    for(Int_t n=0;n<GetNumModel();n++)
00451      GetModel(n)->ChangeDataNameInAssignments(oldname,newname);
00452 }
00453 
00454 Bool_t TGo4Fitter::InitFitterData()
00455 {
00456 
00457    Int_t dbuf = -1, mbuf = -1;
00458    switch (GetMemoryUsage()) {
00459       case 0: dbuf = 0; mbuf = 0; break;
00460       case 1: dbuf = 1; mbuf = 0; break;
00461       case 2: dbuf = 1; mbuf = 1; break;
00462       default: dbuf = -1; mbuf = -1;
00463    }
00464 
00465    for(Int_t i1=0;i1<GetNumData();i1++) {
00466 
00467       TGo4FitData *data = GetData(i1);
00468       if (!data->Initialize(dbuf)) return kFALSE;
00469       for(Int_t i2=0;i2<GetNumModel();i2++)
00470         GetModel(i2)->ConnectToDataIfAssigned(data);
00471    }
00472 
00473    for(Int_t i2=0;i2<GetNumModel();i2++) {
00474       TGo4FitModel *fModel = GetModel(i2);
00475       if (!fModel->Initialize(mbuf)) return kFALSE;
00476    }
00477 
00478    if( (fiFitFunctionType == ff_user) && (fxUserFitFunction==0) ) {
00479       cout << " User fit function not set. Switch to least squares " << endl;
00480       fiFitFunctionType = ff_least_squares;
00481    }
00482 
00483    return kTRUE;
00484 }
00485 
00486 void TGo4Fitter::FinalizeFitterData()
00487 {
00488    for(Int_t i=0;i<GetNumData();i++) GetData(i)->Finalize();
00489 
00490    for(Int_t i=0;i<GetNumModel();i++) GetModel(i)->Finalize();
00491 }
00492 
00493 Double_t TGo4Fitter::PointFitFunction(Int_t FitFunctionType, Double_t value, Double_t modelvalue, Double_t standdev)
00494 {
00495    switch (FitFunctionType) {
00496       case ff_least_squares: {
00497         Double_t zn1 = (value-modelvalue);
00498         return zn1*zn1; }
00499       case ff_chi_square: {
00500         if (standdev<=0.) return 0.;
00501         Double_t zn2 = (value-modelvalue);
00502         return zn2*zn2/standdev; }
00503       case ff_chi_Pearson: {
00504         if (modelvalue<=0.) return 0.;
00505         Double_t zn3 = (value-modelvalue);
00506         return zn3*zn3/modelvalue; }
00507       case ff_chi_Neyman: {
00508         Double_t zn4 = (value-modelvalue);
00509         return zn4*zn4/((value<1.) ? 1. : value); }
00510       case ff_chi_gamma: {
00511         if (value<0.) return 0.;
00512         Double_t zn5 = (value+((value<1.) ? 0. : 1.)-modelvalue);
00513         return zn5*zn5/(value+1.); }
00514       case ff_ML_Poisson:
00515         if (modelvalue<=0.) return 0.;
00516         return modelvalue - value*TMath::Log(modelvalue);
00517       case ff_user:
00518         if (fxUserFitFunction==0) return 0;
00519         return fxUserFitFunction(value, modelvalue, standdev);
00520       default:
00521         return (value-modelvalue)*(value-modelvalue);
00522    }
00523 }
00524 
00525 Double_t TGo4Fitter::CalculateFCN(Int_t FitFunctionType, TGo4FitData* selectdata)
00526 {
00527 
00528   if (GetMemoryUsage()>0)  RebuildAll();
00529 
00530   Double_t fSum = 0.;
00531 
00532   for(Int_t n=0;n<GetNumData();n++) {
00533     TGo4FitData* dat = GetData(n);
00534     if (selectdata && (dat!=selectdata)) continue;
00535     Double_t DataAmpl = dat->GetAmplValue();
00536 
00537     if (dat->BuffersAllocated()) {
00538        Int_t size = dat->GetBinsSize();
00539        Double_t* values = dat->GetBinsValues();
00540        Double_t* res = dat->GetBinsResult();
00541        Double_t* devs = dat->GetBinsDevs();
00542 
00543        for(Int_t nbin=0;nbin<size;nbin++)
00544          fSum += PointFitFunction(FitFunctionType, DataAmpl*values[nbin], res[nbin], DataAmpl*DataAmpl*devs[nbin] );
00545     } else {
00546 
00547        TGo4FitDataIter* iter = dat->MakeIter();
00548        if (!iter->Reset()) { delete iter; continue; }
00549 
00550        TObjArray Models;
00551 
00552        TArrayD Ampls(GetNumModel());
00553        for(Int_t nm=0;nm<GetNumModel();nm++)
00554          if (GetModel(nm)->IsAssignTo(dat->GetName())) {
00555            TGo4FitModel* model = GetModel(nm);
00556            Models.Add(model);
00557            model->BeforeEval(iter->ScalesSize());
00558            Ampls[Models.GetLast()] = model->GetAmplValue() * model->GetRatioValueFor(dat->GetName());
00559          }
00560 
00561        do {
00562           Double_t value = DataAmpl * iter->Value();
00563           Double_t deviat = DataAmpl * DataAmpl * iter->StandardDeviation();
00564 
00565           Double_t modelvalue = 0.;
00566           for(Int_t nm=0;nm<=Models.GetLast();nm++) {
00567              TGo4FitModel* model = dynamic_cast<TGo4FitModel*> (Models.At(nm));
00568              modelvalue += Ampls[nm] * model->EvaluateAtPoint(iter);
00569            }
00570 
00571           fSum += PointFitFunction(FitFunctionType, value, modelvalue, deviat);
00572 
00573        } while (iter->Next());
00574 
00575        for(Int_t nm=0;nm<=Models.GetLast();nm++)
00576           ((TGo4FitModel*) Models.At(nm))->AfterEval();
00577 
00578        delete iter;
00579     }
00580   }
00581 
00582   return fSum;
00583 }
00584 
00585 Double_t TGo4Fitter::CalculateFitFunction(Double_t* pars, Int_t FitFunctionType, const char* DataName)
00586 {
00587 
00588    if (FitFunctionType<0) FitFunctionType = GetFitFunctionType();
00589 
00590    if (pars) {
00591      ExecuteDependencies(pars);
00592      SetParsValues(pars);
00593    }
00594 
00595    return CalculateFCN(FitFunctionType, FindData(DataName));
00596 }
00597 
00598 Int_t TGo4Fitter::CalculateNDF(const char* DataName)
00599 {
00600    TGo4FitData* selectdata = FindData(DataName);
00601 
00602    Int_t NDF = 0;
00603 
00604    if (selectdata!=0) {
00605      NDF = selectdata->DefineBinsSize();
00606      for(Int_t nm=0;nm<GetNumModel();nm++) {
00607         TGo4FitModel* model = GetModel(nm);
00608         if (model->IsAssignTo(selectdata->GetName()))
00609         NDF -= model->NumFreePars();
00610      }
00611    } else {
00612      for (Int_t n=0;n<GetNumData();n++)
00613        NDF += GetData(n)->DefineBinsSize();
00614      NDF -= NumFreePars();
00615    }
00616 
00617    return NDF;
00618 }
00619 
00620 Double_t TGo4Fitter::DoCalculation()
00621 {
00622    return CalculateFCN(fiFitFunctionType);
00623 }
00624 
00625 Int_t TGo4Fitter::DoNDFCalculation()
00626 {
00627    return CalculateNDF(0);
00628 }
00629 
00630 void TGo4Fitter::RebuildAll(Bool_t ForceBuild)
00631 {
00632    for(Int_t i2=0;i2<GetNumModel();i2++)
00633       GetModel(i2)->RebuildShape(ForceBuild);
00634 
00635    for(Int_t i1=0;i1<GetNumData();i1++) {
00636       TGo4FitData* data = GetData(i1);
00637       if (!data->BuffersAllocated()) continue;
00638 
00639       Int_t size = data->GetBinsSize();
00640       Double_t* result = data->GetBinsResult();
00641       for (Int_t nbin=0;nbin<size;nbin++) result[nbin] = 0.;
00642 
00643       for(Int_t i2=0;i2<GetNumModel();i2++) {
00644          TGo4FitModel *model = GetModel(i2);
00645          if (model->IsAssignTo(data->GetName()))
00646             model->AddModelToDataResult(data);
00647       }
00648    }
00649 }
00650 
00651 void TGo4Fitter::EstimateAmplitudes(Int_t NumIters)
00652 {
00653    TGo4FitAmplEstimation abc("this",NumIters);
00654    abc.DoAction(this);
00655 }
00656 
00657 void TGo4Fitter::AddAmplEstimation(Int_t NumIters)
00658 {
00659    AddAction(new TGo4FitAmplEstimation("AmplEstim",NumIters));
00660 }
00661 
00662 void TGo4Fitter::AddStandardActions()
00663 {
00664    AddAmplEstimation();
00665    AddSimpleMinuit();
00666 }
00667 
00668 void TGo4Fitter::FillSlotList(TSeqCollection* list)
00669 {
00670    TGo4FitterAbstract::FillSlotList(list);
00671    for(Int_t i=0;i<GetNumComp();i++)
00672      GetComp(i)->FillSlotList(list);
00673 }
00674 
00675 Bool_t TGo4Fitter::ModelBuffersAllocated(TGo4FitModel* model)
00676 {
00677   return model==0 ? kFALSE : model->BuffersAllocated();
00678 }
00679 
00680 Bool_t TGo4Fitter::DataBuffersAllocated(TGo4FitData* data)
00681 {
00682   return data==0 ? kFALSE : data->BuffersAllocated();
00683 }
00684 
00685 Int_t TGo4Fitter::GetDataBinsSize(TGo4FitData* data)
00686 {
00687    return (data==0) ? 0 : data->GetBinsSize();
00688 }
00689 
00690 Double_t* TGo4Fitter::GetDataBinsValues(TGo4FitData* data)
00691 {
00692    return (data==0) ? 0 : data->GetBinsValues();
00693 }
00694 
00695 Double_t* TGo4Fitter::GetDataBinsDevs(TGo4FitData* data)
00696 {
00697    return (data==0) ? 0 : data->GetBinsDevs();
00698 }
00699 
00700 Double_t* TGo4Fitter::GetDataBinsResult(TGo4FitData* data)
00701 {
00702    return (data==0) ? 0 : data->GetBinsResult();
00703 }
00704 
00705 Double_t* TGo4Fitter::GetModelBinsValues(TGo4FitModel* model, const char* DataName)
00706 {
00707    return (model==0) ? 0 : model->GetModelBins(DataName);
00708 }
00709 
00710 void TGo4Fitter::Print(Option_t* option) const
00711 {
00712    TString Opt(option);
00713    if (Opt=="Ampls") { PrintAmpls(); return; } else
00714    if (Opt=="Pars") { PrintPars(); return; } else
00715    if (Opt=="Results") { PrintResults(); return; } else
00716    if (Opt=="Lines") { PrintLines(); return; }
00717 
00718    TGo4FitterAbstract::Print(option);
00719    cout << "Fitiing function type: ";
00720    switch (fiFitFunctionType) {
00721      case ff_chi_square   : cout << "ff_chi_square" << endl; break;
00722      case ff_chi_Pearson  : cout << "ff_chi_Pearson" << endl; break;
00723      case ff_chi_Neyman   : cout << "ff_chi_Neyman" << endl; break;
00724      case ff_chi_gamma    : cout << "ff_chi_gamma" << endl; break;
00725      case ff_ML_Poisson   : cout << "ff_ML_Poisson" << endl; break;
00726      case ff_user         : cout << "user defined" << endl; break;
00727      default: cout << "ff_least_squares" << endl;
00728    }
00729    cout << endl << "   LIST OF DATA OBJECTS" << endl;
00730    fxDatas.Print(option);
00731    cout << endl << "   LIST OF MODEL OBJECTS" << endl;
00732    fxModels.Print(option);
00733 }
00734 
00735 Bool_t TGo4Fitter::CalculatesMomentums(const char* DataName, Bool_t UseRanges, Bool_t SubstractModels, Double_t& first, Double_t& second)
00736 {
00737   TGo4FitData* data = FindData(DataName);
00738   if (data==0) return kFALSE;
00739 
00740   TGo4FitDataIter* iter = data->MakeIter();
00741   if (iter==0) return kFALSE;
00742 
00743   Int_t size = iter->CountPoints(UseRanges);
00744   if (size==0) { delete iter; return kFALSE; }
00745 
00746   TObjArray Models;
00747   if (SubstractModels)
00748     for(Int_t nm=0; nm<GetNumModel(); nm++)
00749       if (GetModel(nm)->IsAssignTo(DataName))
00750         Models.Add(GetModel(nm));
00751 
00752   TArrayD Ampls(Models.GetLast()+1);
00753   for(Int_t n=0;n<=Models.GetLast();n++) {
00754      TGo4FitModel* model = (TGo4FitModel*) Models[n];
00755      model->BeforeEval(iter->ScalesSize());
00756      Ampls[n] = model->GetAmplValue() * model->GetRatioValueFor(DataName);
00757   }
00758 
00759   TArrayD bins(size), scales(size);
00760 
00761   Int_t pnt=0;
00762 
00763   if (iter->Reset(UseRanges)) do {
00764     Double_t value = iter->Value();
00765     for(Int_t n=0;n<=Models.GetLast();n++) {
00766       TGo4FitModel* model = (TGo4FitModel*) Models[n];
00767       value -= Ampls[n] * model->EvaluateAtPoint(iter);
00768     }
00769     value = TMath::Abs(value);
00770     bins[pnt] = value;
00771     scales[pnt] = iter->x();
00772     pnt++;
00773   } while (iter->Next(UseRanges));
00774 
00775   delete iter;
00776 
00777   for(Int_t n=0;n<=Models.GetLast();n++) {
00778      TGo4FitModel* model = (TGo4FitModel*) Models[n];
00779      model->AfterEval();
00780   }
00781 
00782   Int_t niter=0;
00783 
00784   do {
00785      Double_t sum00=0.;
00786      Double_t sum11=0.;
00787      Double_t sum22=0.;
00788      for (Int_t pnt=0;pnt<size;pnt++)
00789        if ((bins[pnt]>0.) && ((niter==0) || (TMath::Abs(scales[pnt]-first)<second*2.))) {
00790             sum00 += bins[pnt];
00791             sum11 += bins[pnt]*scales[pnt];
00792             sum22 += bins[pnt]*scales[pnt]*scales[pnt];
00793        }
00794 
00795      if (sum00>0.) {
00796        Double_t mid = sum11/sum00;
00797        Double_t dev = TMath::Sqrt(sum22/sum00-mid*mid);
00798 
00799        if (niter>0)
00800          if ((dev/second>0.8) && (dev/second<1.2)) niter=10;
00801 
00802        first = mid; second = dev;
00803 
00804       } else niter=10;
00805 
00806   } while (niter++<8);
00807 
00808   return kTRUE;
00809 }
00810 
00811 Double_t TGo4Fitter::CalculatesIntegral(const char* DataName, const char* ModelName, Bool_t onlycounts)
00812 {
00813     TGo4FitData* data = FindData(DataName);
00814     if (data==0) return 0.;
00815 
00816     TGo4FitModel* model = ModelName!=0 ? FindModel(ModelName) : 0;
00817     if ((ModelName!=0) && (model==0)) return 0.;
00818 
00819     TGo4FitDataIter* iter = data->MakeIter();
00820     if (iter==0) return 0.;
00821 
00822     double sum = 0.;
00823     double ampl = 1.;
00824 
00825     if (!iter->Reset(kTRUE)) {
00826        delete iter;
00827        return 0.;
00828     }
00829 
00830     if (model!=0) {
00831       model->BeforeEval(iter->ScalesSize());
00832       ampl = model->GetAmplValue() * model->GetRatioValueFor(DataName);
00833     }
00834 
00835     do {
00836        double dx = onlycounts ? 1. : iter->xWidths();
00837        double value = model==0 ? iter->Value() : model->EvaluateAtPoint(iter);
00838        sum += ampl*value*dx;
00839     } while (iter->Next(kTRUE));
00840 
00841     if (model!=0)
00842       model->AfterEval();
00843 
00844     delete iter;
00845 
00846     return sum;
00847 }
00848 
00849 Double_t TGo4Fitter::CalculatesModelIntegral(const char* ModelName, Bool_t OnlyCounts)
00850 {
00851    TGo4FitModel* model = FindModel(ModelName);
00852    if (model==0) return 0.;
00853    return CalculatesIntegral(model->AssignmentName(0), ModelName, OnlyCounts);
00854 }
00855 
00856 TObject* TGo4Fitter::CreateDrawObject(const char* ResName, const char* DataName, Bool_t IsModel, const char* ModelName)
00857 {
00858     TGo4FitData* data = FindData(DataName);
00859     if (data==0) return 0;
00860 
00861     TObjArray Models;
00862     if (IsModel) {
00863       TGo4FitModel* model = FindModel(ModelName);
00864       if (model) Models.Add(model); else {
00865         Int_t groupindex = -1;
00866 
00867         if (ModelName!=0) {
00868           TString modelname(ModelName);
00869           if (modelname=="Background") groupindex = 0; else
00870           if (modelname.Index("Group",0,TString::kExact)==0) {
00871              modelname.Remove(0,5);
00872              char* err = 0;
00873              groupindex = strtol(modelname.Data(),&err,10);
00874              if (err && (*err!=0)) groupindex=-1;
00875           }
00876         }
00877 
00878         for(Int_t nm=0; nm<GetNumModel(); nm++) {
00879           TGo4FitModel* model = GetModel(nm);
00880           if (model->IsAssignTo(DataName))
00881             if ((groupindex<0) || (model->GetGroupIndex()==groupindex))
00882               Models.Add(model);
00883         }
00884       }
00885       if (Models.GetLast()<0) return 0;
00886     }
00887 
00888     TGo4FitDataIter* iter = data->MakeIter();
00889     if (iter==0) return 0;
00890 
00891     if (!iter->Reset(kFALSE)) { delete iter; return 0; }
00892 
00893     TH1* histo = 0;
00894     Int_t ndim = 0;
00895     TGraph* gr = 0;
00896     Bool_t UseRanges = kTRUE;
00897 
00898     if (iter->HasIndexes() && (iter->IndexesSize()==iter->ScalesSize()) && iter->HasWidths()) {
00899        histo = iter->CreateHistogram(ResName, kFALSE, !IsModel);
00900 
00901        if (histo) {
00902           ndim = histo->GetDimension();
00903           UseRanges = Models.GetLast() >= 0;
00904        }
00905     } else {
00906        gr = iter->CreateGraph(ResName, kTRUE, !IsModel);
00907        UseRanges = kTRUE;
00908     }
00909 
00910     if (((histo!=0) || (gr!=0)) && IsModel) {
00911        TArrayD Ampls(Models.GetLast()+1);
00912 
00913        for(Int_t n=0;n<=Models.GetLast();n++) {
00914          TGo4FitModel* model = (TGo4FitModel*) Models[n];
00915          model->BeforeEval(iter->ScalesSize());
00916          Ampls[n] = model->GetAmplValue() * model->GetRatioValueFor(DataName);
00917        }
00918 
00919        if (iter->Reset(UseRanges)) do {
00920           Double_t zn = 0;
00921           for(Int_t n=0;n<=Models.GetLast();n++) {
00922              TGo4FitModel* model = (TGo4FitModel*) Models[n];
00923              zn += Ampls[n] * model->EvaluateAtPoint(iter);
00924           }
00925           if (histo)
00926              switch(ndim) {
00927                case 1: histo->SetBinContent(iter->Indexes()[0]+1,zn); break;
00928                case 2: histo->SetBinContent(iter->Indexes()[0]+1,iter->Indexes()[1]+1,zn); break;
00929                case 3: histo->SetBinContent(iter->Indexes()[0]+1,iter->Indexes()[1]+1,iter->Indexes()[2]+1,zn); break;
00930              }
00931           if(gr) {
00932             (gr->GetX())[iter->Point()] = iter->x();
00933             (gr->GetY())[iter->Point()] = zn;
00934           }
00935 
00936        } while (iter->Next(UseRanges));
00937 
00938        for(Int_t n=0;n<=Models.GetLast();n++) {
00939          TGo4FitModel* model = (TGo4FitModel*) Models[n];
00940          model->AfterEval();
00941        }
00942     }
00943 
00944     delete iter;
00945 
00946     if (gr && IsModel)
00947      for(Int_t n1=0;n1<gr->GetN()-1;n1++)
00948        for(Int_t n2=n1+1;n2<gr->GetN();n2++)
00949          if ((gr->GetX())[n1]>(gr->GetX())[n2]) {
00950             Double_t xx = (gr->GetX())[n1];
00951             (gr->GetX())[n1] = (gr->GetX())[n2];
00952             (gr->GetX())[n2] = xx;
00953             Double_t yy = (gr->GetY())[n1];
00954             (gr->GetY())[n1] = (gr->GetY())[n2];
00955             (gr->GetY())[n2] = yy;
00956          }
00957 
00958     TNamed* res = 0;
00959     if (histo) res = histo; else res = gr;
00960     if (res) {
00961       TString title;
00962       if (IsModel)
00963         if (ModelName) { title = "Draw of model "; title+=ModelName; }
00964                   else { title = "Draw of full model of "; title+=DataName; }
00965         else { title = "Draw of data "; title+=DataName; }
00966       res->SetTitle(title.Data());
00967     }
00968 
00969     return res;
00970 }
00971 
00972 
00973 /*   valid format for draw options
00974 
00975    "" - draw all data
00976    "*" - draw all data with models
00977    "**" - draw all data with models and all components
00978    "DataName" - draw select data with model
00979    "DataName-" - draw select data without model
00980    "DataName*" - draw select data with model and components
00981    "DataName-, Background" - draw data and sum of components, belongs to background group (index=0)
00982    "DataName-, Group1" - draw data and sum of components, belongs to group 1
00983    "ModelName" - draw model component and correspondent data
00984 */
00985 
00986 void TGo4Fitter::Draw(Option_t* option)
00987 {
00988    TString opt(option);
00989 
00990    TCanvas *fCanvas = 0;
00991 
00992    if ((opt.Length()>0) && (opt[0]=='#')) {
00993       opt.Remove(0,1);
00994       TString CanvasName;
00995       Int_t n=0;
00996       do {
00997         CanvasName = "Canvas";
00998         CanvasName+=n++;
00999       } while (gROOT->FindObject(CanvasName.Data()));
01000       fCanvas = new TCanvas(CanvasName,TString("Draw of fitter ")+GetName()+" "+opt,3);
01001       fCanvas->cd();
01002    }
01003 
01004    Bool_t drawdata = kFALSE;
01005    TGo4FitData *selectdata = 0;
01006    TObjArray selectmodels;
01007    selectmodels.SetOwner(kTRUE);
01008    Bool_t drawcomp = kFALSE;
01009    Bool_t drawmodel = kFALSE;
01010 
01011    if (opt=="*") { opt = "";  drawdata = kTRUE; }
01012 
01013    while (opt.Length()>0) {
01014      Int_t len = opt.Index(",",0,TString::kExact);
01015 
01016      if (len<0) len = opt.Length();
01017      if (len==0) break;
01018 
01019      TString optpart(opt.Data(), len);
01020      while ((optpart.Length()>0) && (optpart[0]==' ')) optpart.Remove(0,1);
01021 
01022      Bool_t find = kFALSE;
01023 
01024      for(Int_t n=0;n<GetNumData();n++)
01025        if (optpart.Index(GetDataName(n),0,TString::kExact)==0) {
01026          selectdata = GetData(n);
01027          drawdata = kTRUE;
01028          drawmodel = kTRUE;
01029          find = kTRUE;
01030          optpart.Remove(0,strlen(GetDataName(n)));
01031          if (optpart=="*") drawcomp = kTRUE; else
01032          if (optpart=="-") drawmodel = kFALSE;
01033          break;
01034        }
01035 
01036      if (!find) {
01037        selectmodels.Add(new TObjString(optpart));
01038        TGo4FitModel* model = FindModel(optpart.Data());
01039        if (model && (selectdata==0))
01040          for(Int_t n=0;n<GetNumData();n++)
01041            if (model->IsAssignTo(GetDataName(n)))
01042              selectdata = GetData(n);
01043      }
01044 
01045      opt.Remove(0,len);
01046      if (opt.Length()>0) opt.Remove(0,1);
01047    }
01048 
01049    if ((selectdata==0) && !drawdata)
01050      if (GetNumData()>0) selectdata = GetData(0);
01051 
01052    MoveDrawObjectsToROOT();
01053    fxDrawObjs = new TObjArray();
01054 
01055    for(Int_t n=0;n<GetNumData();n++) {
01056       TGo4FitData* data = GetData(n);
01057       if (selectdata && (data!=selectdata)) continue;
01058 
01059       if (drawdata) {
01060           TObject* obj = CreateDrawObject(TString(data->GetName())+"_bins", data->GetName(), kFALSE);
01061 
01062           TAttLine* line = dynamic_cast<TAttLine*> (obj);
01063           if (line) {
01064             line->SetLineColor(1);
01065             line->SetLineWidth(1);
01066           }
01067           if (obj) fxDrawObjs->Add(obj);
01068       }
01069 
01070       if (drawmodel) {
01071          TObject* mobj = CreateDrawObject(TString(data->GetName())+"_fullmodel", data->GetName(), kTRUE);
01072 
01073          TAttLine* line = dynamic_cast<TAttLine*> (mobj);
01074          if (line) {
01075            line->SetLineColor(4);
01076            line->SetLineWidth(2);
01077          }
01078          if (mobj) fxDrawObjs->Add(mobj);
01079       }
01080 
01081       if (drawcomp)
01082         for(Int_t nmodel=0;nmodel<GetNumModel();nmodel++) {
01083            TGo4FitModel *model = GetModel(nmodel);
01084            if ( !model->IsAssignTo(data->GetName())) continue;
01085 
01086            TObject* cobj = CreateDrawObject(TString(data->GetName())+"_"+model->GetName(), data->GetName(), kTRUE, model->GetName());
01087 
01088            TAttLine* line = dynamic_cast<TAttLine*> (cobj);
01089            if (line) {
01090              line->SetLineColor(6);
01091              line->SetLineWidth(1);
01092            }
01093            if (cobj) fxDrawObjs->Add(cobj);
01094         }
01095 
01096       for (Int_t n=0;n<=selectmodels.GetLast();n++) {
01097         TString name = ((TObjString*) (selectmodels[n]))->String();
01098 
01099         TObject* cobj = CreateDrawObject(TString(data->GetName())+"_" +name, data->GetName(), kTRUE, name.Data());
01100 
01101         TAttLine* line = dynamic_cast<TAttLine*> (cobj);
01102         if (line) {
01103           line->SetLineColor(6);
01104           line->SetLineWidth(1);
01105         }
01106         if (cobj) fxDrawObjs->Add(cobj);
01107       }
01108    }
01109 
01110    if (fxDrawObjs->GetLast()==0) fxDrawObjs->At(0)->Draw(); else
01111    if (fxDrawObjs->GetLast()>0)  {
01112       Bool_t allhisto = kTRUE;
01113       for (Int_t n=0;n<=fxDrawObjs->GetLast();n++)
01114         if (!(fxDrawObjs->At(n)->InheritsFrom(TH1::Class()))) allhisto = kFALSE;
01115       if (allhisto) {
01116          THStack* stack = new THStack(TString("Stack")+"_"+fxDrawObjs->At(0)->GetName(),fxDrawObjs->At(0)->GetName());
01117          for (Int_t n=0;n<=fxDrawObjs->GetLast();n++) stack->Add((TH1*)fxDrawObjs->At(n));
01118          fxDrawObjs->Clear();
01119          fxDrawObjs->Add(stack);
01120          stack->Draw("nostack");
01121       } else
01122       for (Int_t n=0;n<=fxDrawObjs->GetLast();n++)
01123         if (n==0) fxDrawObjs->At(n)->Draw("A*");
01124              else fxDrawObjs->At(n)->Draw("L");
01125    }
01126 
01127    if (fCanvas!=0) fCanvas->Update();
01128 }
01129 
01130 void TGo4Fitter::PrintAmpls() const
01131 {
01132    cout << endl << "*** LIST OF AMPLITUDES VALUE ***" << endl;
01133    for(Int_t n=0;n<GetNumComp();n++) {
01134        TGo4FitComponent* comp = ((TGo4Fitter*) this)->GetComp(n);
01135        if (comp->GetAmplPar() != 0)
01136           cout << "    " << comp->GetAmplFullName() << "   " << comp->GetAmplValue() << "   " << comp->GetAmplError() << endl;
01137    }
01138 }
01139 
01140 void TGo4Fitter::PrintLines() const
01141 {
01142   cout << endl << "    *** LIST OF LINES PARAMETERS ***" << endl;
01143 
01144   int MaxAxis = 0;
01145   for (Int_t n=0; n<GetNumModel();n++) {
01146      TGo4FitModel* m = ((TGo4Fitter*) this)->GetModel(n);
01147      if (m==0) continue;
01148      Double_t zn;
01149      for (int naxis=0;naxis<3;naxis++)
01150         if (m->GetPosition(naxis,zn) || m->GetWidth(naxis,zn)) MaxAxis = naxis;
01151   }
01152 
01153   cout << setw(10) << "Name" << setw(12) << "Ampl";
01154   for(Int_t naxis=0;naxis<=MaxAxis;naxis++)
01155     cout << setw(11) << "Pos" << naxis << setw(11) << "Width" << naxis;
01156   cout << endl;
01157 
01158   for (Int_t n=0; n<GetNumModel();n++) {
01159      TGo4FitModel* m = ((TGo4Fitter*) this)->GetModel(n);
01160      if (m==0) continue;
01161      cout << setw(10) << m->GetName() << setw(12) << m->GetAmplValue();
01162 
01163      for (int naxis=0;naxis<=MaxAxis;naxis++) {
01164         Double_t pos, width;
01165         cout << setw(12);
01166         if (m->GetPosition(naxis,pos)) cout << pos;
01167                                   else cout << "---";
01168         cout << setw(12);
01169         if (m->GetWidth(naxis,width)) cout << width;
01170                                  else cout << "---";
01171         }
01172      cout << endl;
01173   }
01174 }
01175 
01176 
01177 void TGo4Fitter::ProvideLastDrawObjects(TObjArray& lst)
01178 {
01179    if (fxDrawObjs) {
01180       lst.AddAll(fxDrawObjs);
01181       delete fxDrawObjs;
01182       fxDrawObjs = 0;
01183    }
01184 }
01185 
01186 void TGo4Fitter::MoveDrawObjectsToROOT()
01187 {
01188    if (fxDrawObjs) {
01189       for(Int_t n=0;n<=fxDrawObjs->GetLast();n++)
01190          gROOT->Add(fxDrawObjs->At(n));
01191       delete fxDrawObjs;
01192       fxDrawObjs = 0;
01193    }
01194 }
01195 
01196 TString TGo4Fitter::FindNextName(const char* Head, Int_t start, Bool_t isModel)
01197 {
01198    TString name;
01199    Int_t n = start;
01200    do {
01201      name.Form("%s%d", Head, n++);
01202    } while (isModel ? FindModel(name.Data())!=0 : FindData(name.Data())!=0 );
01203    return name;
01204 }
01205 
01206 void TGo4Fitter::Streamer(TBuffer& b)
01207 {
01208    if (b.IsReading()) {
01209       TGo4Fitter::Class()->ReadBuffer(b, this);
01210       CheckDuplicatesOnSlot();
01211       SetParsListChange();
01212       SetUpdateSlotList();
01213    } else {
01214       PrepareSlotsForWriting();
01215       TGo4Fitter::Class()->WriteBuffer(b, this);
01216    }
01217 }

Generated on Thu Oct 28 15:54:12 2010 for Go4-Fitpackagev4.04-2 by  doxygen 1.5.1