GSI Object Oriented Online Offline (Go4)  GO4-6.3.0
TGo4FitAmplEstimation.cxx
Go to the documentation of this file.
1 // $Id$
2 //-----------------------------------------------------------------------
3 // The GSI Online Offline Object Oriented (Go4) Project
4 // Experiment Data Processing at EE department, GSI
5 //-----------------------------------------------------------------------
6 // Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
7 // Planckstr. 1, 64291 Darmstadt, Germany
8 // Contact: http://go4.gsi.de
9 //-----------------------------------------------------------------------
10 // This software can be used under the license agreements as stated
11 // in Go4License.txt file which is part of the distribution.
12 //-----------------------------------------------------------------------
13 
14 #include "TGo4FitAmplEstimation.h"
15 
16 #include <iostream>
17 
18 #include "TMath.h"
19 #include "TMatrixD.h"
20 #include "TVectorD.h"
21 #include "TArrayC.h"
22 #include "TArrayD.h"
23 
24 #include "TGo4Fitter.h"
25 #include "TGo4FitModel.h"
26 #include "TGo4FitData.h"
27 #include "TGo4FitParameter.h"
28 
30 
31 TGo4FitAmplEstimation::TGo4FitAmplEstimation(const char *Name, Int_t NumIters)
32  : TGo4FitterAction(Name, "Estimate amplitude action"), fiNumIters(NumIters)
33 {
34 }
35 
37 
39 {
40  auto f = dynamic_cast<TGo4Fitter *>(Fitter);
41  if (!f)
42  return;
43  if (!CalculateWithBuffers(f))
45 }
46 
47 Double_t
48 TGo4FitAmplEstimation::PointWeight(Int_t niter, Int_t FFtype, Double_t value, Double_t modelvalue, Double_t standdev)
49 {
50  switch (FFtype) {
51  case TGo4Fitter::ff_least_squares: return 1.;
52  case TGo4Fitter::ff_chi_square: return (standdev <= 0.) ? 0. : 1. / standdev;
55  if (niter == 0)
56  return (value < 0.) ? 0. : 1. / (value + 1.);
57  else
58  return (modelvalue <= 0.) ? 0. : 1. / modelvalue;
59  case TGo4Fitter::ff_chi_Neyman: return (value < 1.) ? 1. : 1. / value;
60  case TGo4Fitter::ff_chi_gamma: return (value < 0.) ? 0. : 1. / (value + 1.);
61  case TGo4Fitter::ff_user: return 1.;
62  }
63  return 1.;
64 }
65 
67 {
68  if (!fitter->IsInitialized())
69  return kFALSE;
70 
71  for (Int_t n = 0; n < fitter->GetNumData(); n++)
72  if (!fitter->DataBuffersAllocated(fitter->GetData(n)))
73  return kFALSE;
74 
75  for (Int_t n = 0; n < fitter->GetNumModel(); n++)
76  if (!fitter->ModelBuffersAllocated(fitter->GetModel(n)))
77  return kFALSE;
78 
79  TObjArray comps, fixedcomps;
80 
81  for (Int_t n = 0; n < fitter->GetNumModel(); n++) {
82  TGo4FitModel *fModel = fitter->GetModel(n);
83 
84  Bool_t assigned = kFALSE;
85  for (Int_t na = 0; na < fModel->NumAssigments(); na++)
86  if (fitter->FindData(fModel->AssignmentName(na))) {
87  assigned = kTRUE;
88  break;
89  }
90  if (!assigned)
91  continue;
92 
93  if (fModel->GetAmplPar() && !fModel->GetAmplPar()->GetFixed())
94  comps.Add(fModel);
95  else
96  fixedcomps.Add(fModel);
97  }
98 
99  Int_t ncomp = comps.GetLast() + 1;
100  if (ncomp <= 0)
101  return kFALSE;
102 
103  TMatrixD matr(ncomp, ncomp);
104  TVectorD vector(ncomp);
105 
106  Double_t **DopData = new Double_t *[fitter->GetNumData()];
107  for (Int_t n = 0; n < fitter->GetNumData(); n++)
108  DopData[n] = new Double_t[fitter->GetDataBinsSize(fitter->GetData(n))];
109 
110  Double_t **Weights = new Double_t *[fitter->GetNumData()];
111  for (Int_t n = 0; n < fitter->GetNumData(); n++)
112  Weights[n] = new Double_t[fitter->GetDataBinsSize(fitter->GetData(n))];
113 
114  Int_t niter = 0;
115  Int_t FFtype = fitter->GetFitFunctionType();
116  Bool_t changed = kFALSE;
117 
118  do {
119 
120  fitter->RebuildAll();
121 
122  for (Int_t ndata = 0; ndata < fitter->GetNumData(); ndata++) {
123  TGo4FitData *data = fitter->GetData(ndata);
124 
125  Int_t size = fitter->GetDataBinsSize(data);
126  Double_t ampl = data->GetAmplValue();
127 
128  Double_t *values = fitter->GetDataBinsValues(data);
129  Double_t *result = fitter->GetDataBinsResult(data);
130  Double_t *devs = fitter->GetDataBinsDevs(data);
131  Double_t *weight = Weights[ndata];
132 
133  for (Int_t nbin = 0; nbin < size; nbin++)
134  weight[nbin] = PointWeight(niter, FFtype, ampl * values[nbin], result[nbin], ampl * ampl * devs[nbin]);
135  }
136 
137  for (Int_t n1 = 0; n1 < ncomp; n1++)
138  for (Int_t n2 = n1; n2 < ncomp; n2++) {
139  Double_t fSum = 0.;
140  for (Int_t ndata = 0; ndata < fitter->GetNumData(); ndata++) {
141  Double_t *bins1 = fitter->GetModelBinsValues((TGo4FitModel *)comps[n1], fitter->GetDataName(ndata));
142  Double_t *bins2 = fitter->GetModelBinsValues((TGo4FitModel *)comps[n2], fitter->GetDataName(ndata));
143  if (bins1 && bins2) {
144  Int_t size = fitter->GetDataBinsSize(fitter->GetData(ndata));
145  Double_t *weight = Weights[ndata];
146  for (Int_t nbin = 0; nbin < size; nbin++)
147  fSum += bins1[nbin] * bins2[nbin] * weight[nbin];
148  }
149  }
150  matr(n1, n2) = fSum;
151  matr(n2, n1) = fSum;
152  }
153 
154  // calculating difference between data and fixed components
155  for (Int_t ndata = 0; ndata < fitter->GetNumData(); ndata++) {
156  TGo4FitData *data = fitter->GetData(ndata);
157  Int_t size = fitter->GetDataBinsSize(data);
158  Double_t dampl = data->GetAmplValue();
159  Double_t *values = fitter->GetDataBinsValues(data);
160  Double_t *bins = DopData[ndata];
161 
162  for (Int_t nbin = 0; nbin < size; nbin++)
163  bins[nbin] = dampl * values[nbin];
164 
165  for (Int_t n = 0; n <= fixedcomps.GetLast(); n++) {
166  TGo4FitModel *model = (TGo4FitModel *)fixedcomps[n];
167  Double_t *mbins = fitter->GetModelBinsValues(model, data->GetName());
168  if (mbins) {
169  Double_t mampl = model->GetAmplValue();
170  for (Int_t nbin = 0; nbin < size; nbin++)
171  bins[nbin] -= mampl * mbins[nbin];
172  }
173  }
174  }
175 
176  // filling vector
177 
178  for (Int_t n = 0; n < ncomp; n++) {
179  Double_t fSum = 0.;
180  for (Int_t ndata = 0; ndata < fitter->GetNumData(); ndata++) {
181  Double_t *bins1 = fitter->GetModelBinsValues((TGo4FitModel *)comps[n], fitter->GetDataName(ndata));
182  if (!bins1)
183  continue;
184  Int_t size = fitter->GetDataBinsSize(fitter->GetData(ndata));
185  Double_t *bins = DopData[ndata];
186  Double_t *weight = Weights[ndata];
187  for (Int_t nbin = 0; nbin < size; nbin++)
188  fSum += bins[nbin] * bins1[nbin] * weight[nbin];
189  }
190  vector(n) = fSum;
191  }
192 
193  if (matr.Determinant() == 0.) {
194  std::cerr << " Amplitude estimation algorithm failed. " << std::endl;
195  std::cerr
196  << " Determinant of matrix == 0.; This may be due to equivalent model components or zero model at all"
197  << std::endl;
198  break;
199  }
200 
201  matr.Invert();
202  vector *= matr;
203 
204  for (Int_t n = 0; n < ncomp; n++) {
205  TGo4FitModel *model = (TGo4FitModel *)comps[n];
206  model->SetAmplValue(vector(n));
207  if (matr(n, n) > 0.)
208  model->SetAmplError(TMath::Sqrt(matr(n, n)));
209  }
210 
211  changed = kFALSE;
212  niter++;
213  if (niter < fiNumIters)
214  if ((FFtype == TGo4Fitter::ff_chi_Pearson) || (FFtype == TGo4Fitter::ff_ML_Poisson))
215  changed = kTRUE;
216 
217  } while (changed);
218 
219  for (Int_t n = 0; n < fitter->GetNumData(); n++)
220  delete[] Weights[n];
221  delete[] Weights;
222 
223  for (Int_t n = 0; n < fitter->GetNumData(); n++)
224  delete[] DopData[n];
225  delete[] DopData;
226 
227  return kTRUE;
228 }
229 
231 {
232  if (!fitter)
233  return kFALSE;
234 
235  Int_t nmodel = fitter->GetNumModel();
236  TArrayI refindex(fitter->GetNumModel());
237  refindex.Reset(-1);
238  TArrayI fixedindex(fitter->GetNumModel());
239  fixedindex.Reset(-1);
240 
241  Int_t ncomp = 0;
242  Int_t nfixed = 0;
243 
244  for (Int_t n = 0; n < nmodel; n++) {
245  TGo4FitModel *model = fitter->GetModel(n);
246  Bool_t assigned = kFALSE;
247  for (Int_t na = 0; na < model->NumAssigments(); na++)
248  if (fitter->FindData(model->AssignmentName(na))) {
249  assigned = kTRUE;
250  break;
251  }
252  if (!assigned)
253  continue;
254 
255  if (model->GetAmplPar() && !model->GetAmplPar()->GetFixed())
256  refindex[ncomp++] = n;
257  else
258  fixedindex[nfixed++] = n;
259  }
260 
261  if (ncomp <= 0)
262  return kFALSE;
263 
264  TMatrixD matr(ncomp, ncomp);
265  TVectorD vector(ncomp);
266 
267  TArrayC Usage(nmodel);
268  TArrayD ModelValues(nmodel);
269  TArrayD ModelAmpls(nmodel);
270 
271  Int_t niter = 0;
272  Int_t FFtype = fitter->GetFitFunctionType();
273  Bool_t changed = kFALSE;
274 
275  do {
276  matr = 0.;
277  vector = 0.;
278 
279  for (Int_t ndata = 0; ndata < fitter->GetNumData(); ndata++) {
280  TGo4FitData *data = fitter->GetData(ndata);
281  auto iter = data->MakeIter();
282  if (!iter)
283  return kFALSE;
284 
285  Double_t dampl = data->GetAmplValue();
286 
287  if (iter->Reset()) {
288  Usage.Reset(0);
289  ModelAmpls.Reset(0.);
290  ModelValues.Reset(0.);
291  for (Int_t n = 0; n < nmodel; n++) {
292  TGo4FitModel *model = fitter->GetModel(n);
293  if (model->IsAssignTo(data->GetName())) {
294  Usage[n] = 1;
295  ModelAmpls[n] = model->GetAmplValue() * model->GetRatioValueFor(data->GetName());
296  model->BeforeEval(iter->IndexesSize());
297  }
298  }
299 
300  do {
301  Double_t result = 0.;
302  for (Int_t n = 0; n < nmodel; n++)
303  if (Usage[n]) {
304  ModelValues[n] = fitter->GetModel(n)->EvaluateAtPoint(iter);
305  result += ModelAmpls[n] * ModelValues[n];
306  }
307  Double_t weight =
308  PointWeight(niter, FFtype, dampl * iter->Value(), result, dampl * dampl * iter->StandardDeviation());
309  if (weight <= 0.)
310  continue;
311 
312  for (Int_t i1 = 0; i1 < ncomp; i1++)
313  for (Int_t i2 = i1; i2 < ncomp; i2++) {
314  Double_t zn = matr(i1, i2);
315  zn += ModelValues[refindex[i1]] * ModelValues[refindex[i2]] * weight;
316  matr(i1, i2) = zn;
317  if (i1 != i2)
318  matr(i2, i1) = zn;
319  }
320 
321  Double_t dvalue = dampl * iter->Value();
322  for (Int_t nf = 0; nf < nfixed; nf++)
323  dvalue -= ModelAmpls[fixedindex[nf]] * ModelValues[fixedindex[nf]];
324 
325  for (Int_t i1 = 0; i1 < ncomp; i1++) {
326  Double_t zn = vector(i1);
327  zn += ModelValues[refindex[i1]] * dvalue * weight;
328  vector(i1) = zn;
329  }
330 
331  } while (iter->Next());
332 
333  for (Int_t n = 0; n < nmodel; n++)
334  if (Usage[n])
335  fitter->GetModel(n)->AfterEval();
336  }
337  }
338 
339  if (matr.Determinant() == 0.) {
340  std::cerr << " Amplitude estimation algorithm failed. " << std::endl;
341  std::cerr
342  << " Determinant of matrix == 0.; This may be due to equivalent model components or zero model at all"
343  << std::endl;
344  return kFALSE;
345  }
346 
347  matr.Invert();
348  vector *= matr;
349 
350  for (Int_t n = 0; n < ncomp; n++) {
351  TGo4FitModel *model = fitter->GetModel(refindex[n]);
352  model->SetAmplValue(vector(n));
353  if (matr(n, n) > 0.)
354  model->SetAmplError(TMath::Sqrt(matr(n, n)));
355  }
356 
357  changed = kFALSE;
358  niter++;
359  if (niter < fiNumIters)
360  if ((FFtype == TGo4Fitter::ff_chi_Pearson) || (FFtype == TGo4Fitter::ff_ML_Poisson))
361  changed = kTRUE;
362 
363  } while (changed);
364 
365  return kTRUE;
366 }
367 
368 void TGo4FitAmplEstimation::Print(Option_t *option) const
369 {
370  TGo4FitterAction::Print(option);
371  std::cout << " number of iterations " << fiNumIters << std::endl;
372 }
Int_t GetNumData() const
Definition: TGo4Fitter.h:123
void RebuildAll(Bool_t ForceBuild=kFALSE)
Definition: TGo4Fitter.cxx:697
Double_t PointWeight(Int_t niter, Int_t FFtype, Double_t value, Double_t modelvalue, Double_t standdev)
void Print(Option_t *option="") const override
void SetAmplError(Double_t iError)
Double_t * GetDataBinsDevs(TGo4FitData *data) const
Definition: TGo4Fitter.cxx:764
void DoAction(TGo4FitterAbstract *Fitter) override
void SetAmplValue(Double_t iAmpl)
const char * AssignmentName(Int_t n)
Definition: TGo4FitModel.h:129
Double_t * GetDataBinsResult(TGo4FitData *data) const
Definition: TGo4Fitter.cxx:769
Int_t GetDataBinsSize(TGo4FitData *data) const
Definition: TGo4Fitter.cxx:754
Bool_t CalculateWithIterators(TGo4Fitter *fitter)
Bool_t IsAssignTo(const char *DataName) const
Definition: TGo4FitModel.h:141
virtual Double_t EvaluateAtPoint(TGo4FitData *data, Int_t nbin, Bool_t UseRanges=kTRUE)
Bool_t IsInitialized() const
Double_t * GetDataBinsValues(TGo4FitData *data) const
Definition: TGo4Fitter.cxx:759
TGo4FitModel * GetModel(Int_t n)
Definition: TGo4Fitter.cxx:200
Bool_t GetFixed() const
virtual Bool_t BeforeEval(Int_t ndim)
virtual void AfterEval()
Definition: TGo4FitModel.h:253
Int_t GetNumModel() const
Definition: TGo4Fitter.h:178
TGo4FitData * GetData(Int_t n)
Definition: TGo4Fitter.cxx:104
virtual std::unique_ptr< TGo4FitDataIter > MakeIter()
Definition: TGo4FitData.h:175
Int_t NumAssigments() const
Definition: TGo4FitModel.h:124
Int_t GetFitFunctionType() const
Definition: TGo4Fitter.h:85
void Print(Option_t *option="") const override
Bool_t DataBuffersAllocated(TGo4FitData *data)
Definition: TGo4Fitter.cxx:749
Bool_t CalculateWithBuffers(TGo4Fitter *fitter)
const char * GetDataName(Int_t n)
Definition: TGo4Fitter.cxx:109
Double_t * GetModelBinsValues(TGo4FitModel *model, const char *DataName) const
Definition: TGo4Fitter.cxx:774
TGo4FitData * FindData(const char *DataName)
Definition: TGo4Fitter.cxx:114
Double_t GetRatioValueFor(const char *DataName)
Bool_t ModelBuffersAllocated(TGo4FitModel *model)
Definition: TGo4Fitter.cxx:744
TGo4FitParameter * GetAmplPar()