Thermal-FIST  1.3
Package for hadron resonance gas model applications
ThermalModelFit.cpp
Go to the documentation of this file.
1 /*
2  * Thermal-FIST package
3  *
4  * Copyright (c) 2014-2019 Volodymyr Vovchenko
5  *
6  * GNU General Public License (GPLv3 or later)
7  */
9 
10 #include <fstream>
11 #include <cstdio>
12 #include <cstdlib>
13 #include <ctime>
14 #include <iostream>
15 #include <iomanip>
16 #include <sstream>
17 
18 #ifdef USE_MINUIT
19 #include "Minuit2/FCNBase.h"
20 #include "Minuit2/FunctionMinimum.h"
21 #include "Minuit2/MnMigrad.h"
22 #include "Minuit2/MnMinos.h"
23 #include "Minuit2/MnHesse.h"
24 #include "Minuit2/MnUserParameterState.h"
25 //#include "Minuit2/MnPrint.h"
26 //#include "Minuit2/SimplexMinimizer.h"
27 #endif
28 
30 #include "HRGBase/Utility.h"
31 #include "HRGPCE/ThermalModelPCE.h"
32 
33 namespace thermalfist {
34 
35  #ifdef USE_MINUIT
36 
37  using namespace ROOT::Minuit2;
38 
39  namespace {
40 
41  class FitFCN : public FCNBase {
42 
43  public:
44 
45  FitFCN(ThermalModelFit *thmfit_, bool verbose_ = true) : m_THMFit(thmfit_), m_verbose(verbose_) {
46  }
47 
48  ~FitFCN() {}
49 
50  double operator()(const std::vector<double>& par) const {
51  m_THMFit->Increment();
52  double chi2 = 0.;
53  if (par[2]<0.) return 1e12;
54  if (par[3]<0.) return 1e12;
55 
56  m_THMFit->SetParameterValue("T", par[0]);
57  m_THMFit->SetParameterValue("muB", par[1]);
58  m_THMFit->SetParameterValue("gammaS", par[2]);
59  m_THMFit->SetParameterValue("R", par[3]);
60  m_THMFit->SetParameterValue("Rc", par[4]);
61  m_THMFit->SetParameterValue("gammaq", par[5]);
62  m_THMFit->SetParameterValue("muQ", par[6]);
63  m_THMFit->SetParameterValue("muS", par[7]);
64  m_THMFit->SetParameterValue("muC", par[8]);
65  m_THMFit->SetParameterValue("gammac", par[9]);
66  m_THMFit->SetParameterValue("Tkin", par[10]);
67 
68  m_THMFit->model()->SetTemperature(par[0]);
69 
70  if (!m_THMFit->model()->ConstrainMuB())
71  m_THMFit->model()->SetBaryonChemicalPotential(par[1]);
72 
73  m_THMFit->model()->SetGammaS(par[2]);
74 
75  m_THMFit->model()->SetVolumeRadius(par[3]);
76 
77  if (m_THMFit->FixVcOverV())
78  m_THMFit->model()->SetCanonicalVolume(m_THMFit->model()->Volume() * m_THMFit->VcOverV());
79  else
80  m_THMFit->model()->SetCanonicalVolumeRadius(par[4]);
81 
82 
83  m_THMFit->model()->SetGammaq(par[5]);
84 
85  m_THMFit->model()->SetGammaC(par[9]);
86 
87  if (m_THMFit->model()->ConstrainMuQ())
88  m_THMFit->model()->SetElectricChemicalPotential(-par[1] / 50.);
89  else
90  m_THMFit->model()->SetElectricChemicalPotential(par[6]);
91 
92  if (m_THMFit->model()->ConstrainMuS())
93  m_THMFit->model()->SetStrangenessChemicalPotential(par[1] / 5.);
94  else
95  m_THMFit->model()->SetStrangenessChemicalPotential(par[7]);
96 
97  if (m_THMFit->model()->ConstrainMuC())
98  m_THMFit->model()->SetCharmChemicalPotential(par[1] / 5.);
99  else
100  m_THMFit->model()->SetCharmChemicalPotential(par[8]);
101 
102  m_THMFit->model()->SetParameters(m_THMFit->model()->Parameters());
103 
104  //m_THMFit->model()->SetQoverB(m_THMFit->QoverB());
105 
107 
108  m_THMFit->model()->ConstrainChemicalPotentials();
109 
110  if (m_THMFit->UseTkin()) {
111  m_THMFit->modelpce()->SetChemicalFreezeout(m_THMFit->model()->Parameters(), m_THMFit->model()->ChemicalPotentials());
112  m_THMFit->modelpce()->CalculatePCE(par[10]);
113  }
114  else {
115  m_THMFit->model()->CalculateDensities();
116  }
117 
118  // If current chemical potentials lead to
119  // Bose-Einstein function divergence (\mu > m),
120  // then effectively discard parameter of the current iteration by setting chi^2 to 10^12
122  printf("%15d ", m_THMFit->Iters());
123  printf("Issue with Bose-Einstein condensation, discarding this iteration...\n");
124  return m_THMFit->Chi2() = chi2 = 1.e12;
125  }
126 
127  // Ratios first
128  for (size_t i = 0; i < m_THMFit->FittedQuantities().size(); ++i) {
129  if (m_THMFit->FittedQuantities()[i].type == FittedQuantity::Ratio) {
130  const ExperimentRatio &ratio = m_THMFit->FittedQuantities()[i].ratio;
131  double dens1 = m_THMFit->model()->GetDensity(ratio.fPDGID1, ratio.fFeedDown1);
132  double dens2 = m_THMFit->model()->GetDensity(ratio.fPDGID2, ratio.fFeedDown2);
133  double ModelRatio = dens1 / dens2;
134  m_THMFit->ModelData(i) = ModelRatio;
135  if (m_THMFit->FittedQuantities()[i].toFit)
136  chi2 += (ModelRatio - ratio.fValue) * (ModelRatio - ratio.fValue) / ratio.fError / ratio.fError;
137  }
138  }
139 
140  // Yields second
141  for (size_t i = 0; i < m_THMFit->FittedQuantities().size(); ++i) {
142  if (m_THMFit->FittedQuantities()[i].type == FittedQuantity::Multiplicity) {
143  const ExperimentMultiplicity &multiplicity = m_THMFit->FittedQuantities()[i].mult;
144  double dens = m_THMFit->model()->GetDensity(multiplicity.fPDGID, multiplicity.fFeedDown);
145  double ModelMult = dens * m_THMFit->model()->Parameters().V;
146  m_THMFit->ModelData(i) = ModelMult;
147  if (m_THMFit->FittedQuantities()[i].toFit)
148  chi2 += (ModelMult - multiplicity.fValue) * (ModelMult - multiplicity.fValue) / multiplicity.fError / multiplicity.fError;
149  }
150  }
151 
152  if (m_verbose) {
153  printf("%15d ", m_THMFit->Iters());
154  printf("%15lf ", chi2);
155  if (m_THMFit->Parameters().T.toFit)
156  printf("%15lf ", par[0]);
157  if (m_THMFit->Parameters().muB.toFit)
158  printf("%15lf ", m_THMFit->model()->Parameters().muB);
159  if (m_THMFit->Parameters().muQ.toFit)
160  printf("%15lf ", m_THMFit->model()->Parameters().muQ);
161  if (m_THMFit->Parameters().muS.toFit)
162  printf("%15lf ", m_THMFit->model()->Parameters().muS);
163  if (m_THMFit->Parameters().muC.toFit)
164  printf("%15lf ", m_THMFit->model()->Parameters().muC);
165  if (m_THMFit->Parameters().R.toFit)
166  printf("%15lf ", par[3]);
167  if (m_THMFit->Parameters().Rc.toFit)
168  printf("%15lf ", par[4]);
169  if (m_THMFit->Parameters().gammaq.toFit)
170  printf("%15lf ", m_THMFit->model()->Parameters().gammaq);
171  if (m_THMFit->Parameters().gammaS.toFit)
172  printf("%15lf ", m_THMFit->model()->Parameters().gammaS);
173  if (m_THMFit->Parameters().gammaC.toFit)
174  printf("%15lf ", m_THMFit->model()->Parameters().gammaC);
175  if (m_THMFit->Parameters().Tkin.toFit)
176  printf("%15lf ", par[10]);
177  printf("\n");
178 
179  if (m_THMFit->model()->Ensemble() == ThermalModelBase::CE)
180  printf("B = %10.5lf\tQ = %10.5lf\tS = %10.5lf\tC = %10.5lf\n",
181  m_THMFit->model()->CalculateBaryonDensity() * m_THMFit->model()->Parameters().V,
182  m_THMFit->model()->CalculateChargeDensity() * m_THMFit->model()->Parameters().V,
183  m_THMFit->model()->CalculateStrangenessDensity() * m_THMFit->model()->Parameters().V,
184  m_THMFit->model()->CalculateCharmDensity() * m_THMFit->model()->Parameters().V);
185  }
186 
187  m_THMFit->Chi2() = chi2;
188  if (m_THMFit->model()->Ensemble() == ThermalModelBase::CE) {
189  m_THMFit->BT() = m_THMFit->model()->CalculateBaryonDensity() * m_THMFit->model()->Parameters().V;
190  m_THMFit->QT() = m_THMFit->model()->CalculateChargeDensity() * m_THMFit->model()->Parameters().V;
191  m_THMFit->ST() = m_THMFit->model()->CalculateStrangenessDensity() * m_THMFit->model()->Parameters().V;
192  m_THMFit->CT() = m_THMFit->model()->CalculateCharmDensity() * m_THMFit->model()->Parameters().V;
193  }
194 
195  if (chi2!=chi2) {
196  chi2 = 1.e12;
197  printf("**WARNING** chi2 evaluated to NaN\n");
198  }
199 
200  return chi2;
201  }
202 
203  double Up() const {return 1.;}
204 
205  private:
206  ThermalModelFit *m_THMFit;
207  int m_iter;
208  bool m_verbose;
209  };
210  }
211 
212  #endif
213 
215  m_model(model_), m_modelpce(NULL), m_Parameters(model_->Parameters()), m_FixVcToV(true), m_VcOverV(1.),
216  m_YieldsAtTkin(false), m_SahaForNuclei(true), m_PCEFreezeLongLived(false), m_PCEWidthCut(0.015)
217  {
218  }
219 
220 
222  {
223  }
224 
225  ThermalModelFitParameters ThermalModelFit::PerformFit(bool verbose, bool AsymmErrors) {
226  #ifdef USE_MINUIT
227  m_ModelData.resize(m_Quantities.size(), 0.);
228 
229  m_Parameters.B = m_model->Parameters().B;
230  m_Parameters.Q = m_model->Parameters().Q;
231  m_Parameters.S = m_model->Parameters().S;
232  m_Parameters.C = m_model->Parameters().C;
233 
234  if (UseTkin()) {
235  m_modelpce = new ThermalModelPCE(m_model, m_PCEFreezeLongLived, m_PCEWidthCut);
236  if (!m_SahaForNuclei) {
237  m_modelpce->SetStabilityFlags(m_modelpce->ComputePCEStabilityFlags(m_model->TPS(), m_SahaForNuclei, m_PCEFreezeLongLived, m_PCEWidthCut));
238  }
239  }
240 
241  m_Iters = 0;
242  FitFCN mfunc(this, verbose);
243  std::vector<double> params(11, 0.);
244  params[0] = m_Parameters.T.value;
245  params[1] = m_Parameters.muB.value;
246  params[2] = m_Parameters.gammaS.value;
247  params[3] = m_Parameters.R.value;
248  params[4] = m_Parameters.Rc.value;
249  params[5] = m_Parameters.gammaq.value;
250  params[6] = m_Parameters.muQ.value;
251  params[7] = m_Parameters.muS.value;
252  params[8] = m_Parameters.muC.value;
253  params[9] = m_Parameters.gammaC.value;
254  params[10] = m_Parameters.Tkin.value;
255 
256  MnUserParameters upar;
257  upar.Add("T", m_Parameters.T.value, m_Parameters.T.error, m_Parameters.T.xmin, m_Parameters.T.xmax);
258  upar.Add("muB", m_Parameters.muB.value, m_Parameters.muB.error, m_Parameters.muB.xmin, m_Parameters.muB.xmax);
259  upar.Add("gammaS", m_Parameters.gammaS.value, m_Parameters.gammaS.error, m_Parameters.gammaS.xmin, m_Parameters.gammaS.xmax);
260  upar.Add("R", m_Parameters.R.value, m_Parameters.R.error, m_Parameters.R.xmin, m_Parameters.R.xmax);
261  upar.Add("Rc", m_Parameters.Rc.value, m_Parameters.Rc.error, m_Parameters.Rc.xmin, m_Parameters.Rc.xmax);
262  upar.Add("gammaq", m_Parameters.gammaq.value, m_Parameters.gammaq.error, m_Parameters.gammaq.xmin, m_Parameters.gammaq.xmax);
263  upar.Add("muQ", m_Parameters.muQ.value, m_Parameters.muQ.error, m_Parameters.muQ.xmin, m_Parameters.muQ.xmax);
264  upar.Add("muS", m_Parameters.muS.value, m_Parameters.muS.error, m_Parameters.muS.xmin, m_Parameters.muS.xmax);
265  upar.Add("muC", m_Parameters.muC.value, m_Parameters.muC.error, m_Parameters.muC.xmin, m_Parameters.muC.xmax);
266  upar.Add("gammaC", m_Parameters.gammaC.value, m_Parameters.gammaC.error, m_Parameters.gammaC.xmin, m_Parameters.gammaC.xmax);
267  upar.Add("Tkin", m_Parameters.Tkin.value, m_Parameters.Tkin.error, m_Parameters.Tkin.xmin, m_Parameters.Tkin.xmax);
268 
269  int nparams = 11;
270 
271  // If only ratios fitted then volume drops out
272  //if (m_Multiplicities.size() == 0 && m_model->Ensemble() == ThermalModelBase::GCE)
273  if (m_Multiplicities.size() == 0)
274  m_Parameters.SetParameterFitFlag("R", false);
275 
276  // If GCE, or Vc fixed to V, then correlation volume drops out
277  if (m_model->Ensemble() == ThermalModelBase::GCE || this->FixVcOverV())
278  m_Parameters.SetParameterFitFlag("Rc", false);
279 
280  // If full CE, or S/B fixed, then muB drops out
282  || m_model->ConstrainMuB()
283  || !m_model->TPS()->hasBaryons())
284  m_Parameters.SetParameterFitFlag("muB", false);
285 
286  // If full CE, or Q/B fixed, or no charged particles, then muQ drops out
288  || m_model->ConstrainMuQ()
289  || !m_model->TPS()->hasCharged())
290  m_Parameters.SetParameterFitFlag("muQ", false);
291 
292  // If full CE, SCE, or S fixed to zero, or no strange particles then muS drops out
294  || m_model->ConstrainMuS()
295  || !m_model->TPS()->hasStrange())
296  m_Parameters.SetParameterFitFlag("muS", false);
297 
298  // If not GCE, or C fixed to zero, or no charm particles then muC drops out
300  || m_model->ConstrainMuC()
301  || !m_model->TPS()->hasCharmed())
302  m_Parameters.SetParameterFitFlag("muC", false);
303 
304  // If no strangeness, then gammaS drops out (but beware of neutral particles with strange quarks!)
305  if (!m_model->TPS()->hasStrange())
306  m_Parameters.SetParameterFitFlag("gammaS", false);
307 
308  // If no charm, then gammaC drops out (but beware of neutral particles with charm quarks!)
309  if (!m_model->TPS()->hasCharmed())
310  m_Parameters.SetParameterFitFlag("gammaC", false);
311 
312  // If not using PCE, no point using Tkin
313  if (!UseTkin())
314  m_Parameters.SetParameterFitFlag("Tkin", false);
315 
316  if (!m_Parameters.T.toFit) { upar.Fix("T"); nparams--; }
317  if (!m_Parameters.R.toFit) { upar.Fix("R"); nparams--; }
318  if (!m_Parameters.Rc.toFit) { upar.Fix("Rc"); nparams--; }
319  if (!m_Parameters.muB.toFit) { upar.Fix("muB"); nparams--; }
320  if (!m_Parameters.muQ.toFit) { upar.Fix("muQ"); nparams--; }
321  if (!m_Parameters.muS.toFit) { upar.Fix("muS"); nparams--; }
322  if (!m_Parameters.muC.toFit) { upar.Fix("muC"); nparams--; }
323  if (!m_Parameters.gammaq.toFit) { upar.Fix("gammaq"); nparams--; }
324  if (!m_Parameters.gammaS.toFit) { upar.Fix("gammaS"); nparams--; }
325  if (!m_Parameters.gammaC.toFit) { upar.Fix("gammaC"); nparams--; }
326  if (!m_Parameters.Tkin.toFit) { upar.Fix("Tkin"); nparams--; }
327 
328 
329  m_Ndf = GetNdf();
330 
331  bool repeat = 0;
332 
334 
335  if (nparams>0) {
336 
337  if (verbose) {
338  printf("Starting a thermal fit...\n\n");
339  printf("%15s ", "Iteration");
340  printf("%15s ", "chi2");
341  if (m_Parameters.T.toFit)
342  printf("%15s ", "T [GeV]");
343  if (m_Parameters.muB.toFit)
344  printf("%15s ", "muB [GeV]");
345  if (m_Parameters.muQ.toFit)
346  printf("%15s ", "muQ [GeV]");
347  if (m_Parameters.muS.toFit)
348  printf("%15s ", "muS [GeV]");
349  if (m_Parameters.muC.toFit)
350  printf("%15s ", "muC [GeV]");
351  if (m_Parameters.R.toFit)
352  printf("%15s ", "R [fm]");
353  if (m_Parameters.Rc.toFit)
354  printf("%15s ", "Rc [fm]");
355  if (m_Parameters.gammaq.toFit)
356  printf("%15s ", "gammaq");
357  if (m_Parameters.gammaS.toFit)
358  printf("%15s ", "gammaS");
359  if (m_Parameters.gammaC.toFit)
360  printf("%15s ", "gammaC");
361  if (m_Parameters.Tkin.toFit)
362  printf("%15s ", "Tkin [GeV]");
363  printf("\n");
364  }
365 
366  MnMigrad migrad(mfunc, upar);
367 
368  FunctionMinimum min = migrad();
369 
370  if (verbose)
371  printf("\nMinimum found! Now calculating the error matrix...\n\n");
372 
373  MnHesse hess;
374  hess(mfunc, min);
375 
376  ret = m_Parameters;
377 
378  if (AsymmErrors) {
379  MnMinos mino(mfunc, min);
380  std::pair<double, double> errs;
381  if (m_Parameters.T.toFit) { errs = mino(0); ret.T.errm = abs(errs.first); ret.T.errp = abs(errs.second); }
382  if (m_Parameters.muB.toFit) { errs = mino(1); ret.muB.errm = abs(errs.first); ret.muB.errp = abs(errs.second); }
383  if (m_Parameters.gammaS.toFit) { errs = mino(2); ret.gammaS.errm = abs(errs.first); ret.gammaS.errp = abs(errs.second); }
384  if (m_Parameters.R.toFit) { errs = mino(3); ret.R.errm = abs(errs.first); ret.R.errp = abs(errs.second); }
385  if (m_Parameters.Rc.toFit) { errs = mino(4); ret.Rc.errm = abs(errs.first); ret.Rc.errp = abs(errs.second); }
386  if (m_Parameters.gammaq.toFit) { errs = mino(5); ret.gammaq.errm = abs(errs.first); ret.gammaq.errp = abs(errs.second); }
387  }
388 
389  ret.T.value = (min.UserParameters()).Params()[0];
390  ret.T.error = (min.UserParameters()).Errors()[0];
391  ret.muB.value = (min.UserParameters()).Params()[1];
392  ret.muB.error = (min.UserParameters()).Errors()[1];
393  ret.gammaS.value = (min.UserParameters()).Params()[2];
394  ret.gammaS.error = (min.UserParameters()).Errors()[2];
395  ret.R.value = (min.UserParameters()).Params()[3];
396  ret.R.error = (min.UserParameters()).Errors()[3];
397  ret.Rc.value = (min.UserParameters()).Params()[4];
398  ret.Rc.error = (min.UserParameters()).Errors()[4];
399  ret.gammaq.value = (min.UserParameters()).Params()[5];
400  ret.gammaq.error = (min.UserParameters()).Errors()[5];
401  ret.muQ.value = (min.UserParameters()).Params()[6];
402  ret.muQ.error = (min.UserParameters()).Errors()[6];
403  ret.muS.value = (min.UserParameters()).Params()[7];
404  ret.muS.error = (min.UserParameters()).Errors()[7];
405  ret.muC.value = (min.UserParameters()).Params()[8];
406  ret.muC.error = (min.UserParameters()).Errors()[8];
407  ret.gammaC.value = (min.UserParameters()).Params()[9];
408  ret.gammaC.error = (min.UserParameters()).Errors()[9];
409  ret.Tkin.value = (min.UserParameters()).Params()[10];
410  ret.Tkin.error = (min.UserParameters()).Errors()[10];
411 
412  if (!m_Parameters.Rc.toFit && FixVcOverV()) {
413  ret.Rc.value = ret.R.value * pow(VcOverV(), 1./3.);
414  ret.Rc.error = 0.;
415  }
416 
417  //if (repeat) {
418  // m_model->SetUseWidth(true);
419 
420  // upar.SetValue("T", (min.UserParameters()).Params()[0]);
421  // upar.SetValue("muB", (min.UserParameters()).Params()[1]);
422  // upar.SetValue("gammaS", (min.UserParameters()).Params()[2]);
423  // upar.SetValue("R", (min.UserParameters()).Params()[3]);
424  // upar.SetValue("Rc", (min.UserParameters()).Params()[4]);
425  // upar.SetValue("gammaq", (min.UserParameters()).Params()[5]);
426  // upar.SetValue("muQ", (min.UserParameters()).Params()[6]);
427  // upar.SetValue("muS", (min.UserParameters()).Params()[7]);
428  // upar.SetValue("muC", (min.UserParameters()).Params()[8]);
429  // upar.SetValue("gammaC", (min.UserParameters()).Params()[9]);
430  // upar.SetValue("Tkin", (min.UserParameters()).Params()[10]);
431 
432  // MnMigrad migradd(mfunc, upar);
433  // min = migradd();
434 
435  // ret = m_Parameters;
436  // ret.T.value = (min.UserParameters()).Params()[0];
437  // ret.T.error = (min.UserParameters()).Errors()[0];
438  // ret.muB.value = (min.UserParameters()).Params()[1];
439  // ret.muB.error = (min.UserParameters()).Errors()[1];
440  // ret.gammaS.value = (min.UserParameters()).Params()[2];
441  // ret.gammaS.error = (min.UserParameters()).Errors()[2];
442  // ret.R.value = (min.UserParameters()).Params()[3];
443  // ret.R.error = (min.UserParameters()).Errors()[3];
444  // ret.Rc.value = (min.UserParameters()).Params()[4];
445  // ret.Rc.error = (min.UserParameters()).Errors()[4];
446  // ret.gammaq.value = (min.UserParameters()).Params()[5];
447  // ret.gammaq.error = (min.UserParameters()).Errors()[5];
448  // ret.muQ.value = (min.UserParameters()).Params()[6];
449  // ret.muQ.error = (min.UserParameters()).Errors()[6];
450  // ret.muS.value = (min.UserParameters()).Params()[7];
451  // ret.muS.error = (min.UserParameters()).Errors()[7];
452  // ret.muC.value = (min.UserParameters()).Params()[8];
453  // ret.muC.error = (min.UserParameters()).Errors()[8];
454  // ret.gammaC.value = (min.UserParameters()).Params()[9];
455  // ret.gammaC.error = (min.UserParameters()).Errors()[9];
456  // ret.Tkin.value = (min.UserParameters()).Params()[10];
457  // ret.Tkin.error = (min.UserParameters()).Errors()[10];
458  //}
459  }
460  else {
461  ret = m_Parameters;
462 
463  ret.T.value = upar.Params()[0];
464  ret.T.error = upar.Errors()[0];
465  ret.muB.value = upar.Params()[1];
466  ret.muB.error = upar.Errors()[1];
467  ret.gammaS.value = upar.Params()[2];
468  ret.gammaS.error = upar.Errors()[2];
469  ret.R.value = upar.Params()[3];
470  ret.R.error = upar.Errors()[3];
471  ret.Rc.value = upar.Params()[4];
472  ret.Rc.error = upar.Errors()[4];
473  ret.gammaq.value = upar.Params()[5];
474  ret.gammaq.error = upar.Errors()[5];
475  ret.muQ.value = upar.Params()[6];
476  ret.muQ.error = upar.Errors()[6];
477  ret.muS.value = upar.Params()[7];
478  ret.muS.error = upar.Errors()[7];
479  ret.muC.value = upar.Params()[8];
480  ret.muC.error = upar.Errors()[8];
481  ret.gammaC.value = upar.Params()[9];
482  ret.gammaC.error = upar.Errors()[9];
483  ret.Tkin.value = upar.Params()[10];
484  ret.Tkin.error = upar.Errors()[10];
485  }
486 
487 
489 
490  parames.B = m_model->Parameters().B;
491  parames.S = m_model->Parameters().S;
492  parames.Q = m_model->Parameters().Q;
493  parames.C = m_model->Parameters().C;
494  //m_model->SetParameters(parames);
495  //m_model->FixParameters();
496  if (!ret.muQ.toFit && m_model->ConstrainMuQ()) {
497  ret.muQ.value = m_model->Parameters().muQ;
498  ret.muQ.error = 0.;
499  }
500  if (!ret.muS.toFit && m_model->ConstrainMuS()) {
501  ret.muS.value = m_model->Parameters().muS;
502  ret.muS.error = 0.;
503  }
504  if (!ret.muC.toFit && m_model->ConstrainMuC()) {
505  ret.muC.value = m_model->Parameters().muC;
506  ret.muC.error = 0.;
507  }
508  m_Parameters = ret;
509 
510  params[0] = ret.T.value;
511  params[1] = ret.muB.value;
512  params[2] = ret.gammaS.value;
513  params[3] = ret.R.value;
514  params[4] = ret.Rc.value;
515  params[5] = ret.gammaq.value;
516  params[6] = ret.muQ.value;
517  params[7] = ret.muS.value;
518  params[8] = ret.muC.value;
519  params[9] = ret.gammaC.value;
520  params[10] = ret.Tkin.value;
521 
522  ret.chi2 = mfunc(params);
523  int ndf = 0;
524  for (size_t i = 0; i < m_Quantities.size(); ++i)
525  if (m_Quantities[i].toFit) ndf++;
526  ndf = ndf - nparams;
527 
528  ret.chi2ndf = ret.chi2 / ndf;
529  ret.ndf = ndf;
530 
531  if (!AsymmErrors) {
532  for (size_t i = 0; i < ret.ParameterList.size(); ++i) {
533  ret.GetParameter(i).errm = ret.GetParameter(i).errp = ret.GetParameter(i).error;
534  }
535  }
536 
537 
538  m_Parameters = ret;
539 
540 
541  m_ExtendedParameters = ThermalModelFitParametersExtended(m_model);
542 
543  if (m_modelpce != NULL) {
544  delete m_modelpce;
545  m_modelpce = NULL;
546  }
547 
548  if (verbose)
549  printf("Thermal fit finished\n\n");
550  return ret;
551  #else
552  printf("**ERROR** Cannot fit without MINUIT2 library!\n");
553  exit(1);
554  #endif
555  }
556 
558  m_model->SetParameters(m_Parameters.GetThermalModelParameters());
559  m_model->FixParameters();
560  m_model->CalculateDensities();
561 
562  for (size_t i = 0; i < m_Quantities.size(); ++i) {
563  if (m_Quantities[i].type == FittedQuantity::Ratio) {
564  const ExperimentRatio &ratio = m_Quantities[i].ratio;
565  int ind1 = m_model->TPS()->PdgToId(ratio.fPDGID1);
566  int ind2 = m_model->TPS()->PdgToId(ratio.fPDGID2);
567  double dens1 = m_model->GetDensity(ratio.fPDGID1, ratio.fFeedDown1);
568  double dens2 = m_model->GetDensity(ratio.fPDGID2, ratio.fFeedDown2);
569  std::cout << m_model->TPS()->Particles()[ind1].Name() << "/" << m_model->TPS()->Particles()[ind2].Name() << " = " <<
570  dens1 / dens2 << " " << ratio.fValue << " " << ratio.fError << "\n";
571  }
572  }
573  }
574 
576  printf("%20s\n", "Fit parameters");
577  for(int i=0;i<6;++i) {
578  FitParameter param = m_Parameters.GetParameter(i);
579  if (param.name == "Tkin" && !m_YieldsAtTkin)
580  continue;
581  if (param.toFit) {
582  printf("%10s = %10lf %2s %lf\n", param.name.c_str(), param.value, "+-", param.error);
583  }
584  }
585  if (m_model->Ensemble() == ThermalModelBase::CE) {
586  printf("%10s = %10lf\n", "B", m_model->CalculateBaryonDensity() * m_model->Volume());
587  printf("%10s = %10lf\n", "S", m_model->CalculateStrangenessDensity() * m_model->Volume());
588  printf("%10s = %10lf\n", "Q", m_model->CalculateChargeDensity() * m_model->Volume());
589  }
590  printf("\n");
591  }
592 
593 
595  // No longer needed, done at the end of PerformFit
596  //m_model->SetParameters(m_Parameters.GetThermalModelParameters());
597  //m_model->SetQoverB(m_QBgoal);
598  //m_model->FixParameters();
599  //m_model->CalculateDensities();
600 
601  for (size_t i = 0; i < m_Quantities.size(); ++i) {
602  if (m_Quantities[i].type == FittedQuantity::Multiplicity) {
603  const ExperimentMultiplicity &mult = m_Quantities[i].mult;
604 
605  double dens1 = m_model->GetDensity(mult.fPDGID, mult.fFeedDown);
606 
607  std::string tname = m_model->TPS()->GetNameFromPDG(mult.fPDGID);
608 
609  if (mult.fPDGID == 1)
610  printf("%10s\t%11s\t%6lf %2s %lf\n", "Npart", "Experiment:",
611  mult.fValue, "+-", mult.fError);
612  else if (mult.fPDGID == 33340)
613  printf("%10s\t%11s\t%6lf %2s %lf\n", (m_model->TPS()->ParticleByPDG(3334).Name() + " + " + m_model->TPS()->ParticleByPDG(-3334).Name()).c_str(), "Experiment:",
614  mult.fValue, "+-", mult.fError);
615  else
616  printf("%10s\t%11s\t%6lf %2s %lf\n", tname.c_str(), "Experiment:", mult.fValue, "+-", mult.fError);
617  printf("%10s\t%11s\t%6lf %2s %lf\n", "", "Model:", dens1 * m_model->Parameters().V, "+-", 0.);
618  printf("%10s\t%11s\t%6lf\n", "", "Deviation:", (dens1 * m_model->Parameters().V - mult.fValue) / mult.fError);
619  printf("\n");
620 
621  }
622  }
623 
624  }
625 
627  //m_model->SetParameters(m_Parameters.GetThermalModelParameters());
628  //m_model->SetQoverB(m_QBgoal);
629  //m_model->FixParameters();
630  //m_model->CalculateDensities();
631 
632  for (size_t i = 0; i < m_Quantities.size(); ++i) {
633  if (m_Quantities[i].type == FittedQuantity::Multiplicity) {
634  const ExperimentMultiplicity &mult = m_Quantities[i].mult;
635 
636  double dens1 = m_model->GetDensity(mult.fPDGID, mult.fFeedDown);
637 
638  std::string tname = m_model->TPS()->GetNameFromPDG(mult.fPDGID);
639 
640  if (mult.fPDGID == 1)
641  printf("%10s\t%11s\t%6lf %2s %lf\n", "Npart", "Experiment:",
642  mult.fValue, "+-", mult.fError);
643  else if (mult.fPDGID == 33340)
644  printf("%10s\t%11s\t%6lf %2s %lf\n", (m_model->TPS()->ParticleByPDG(3334).Name() + " + " + m_model->TPS()->ParticleByPDG(-3334).Name()).c_str(), "Experiment:",
645  mult.fValue, "+-", mult.fError);
646  else
647  printf("%10s\t%11s\t%6lf %2s %lf\n", tname.c_str(), "Experiment:", mult.fValue, "+-", mult.fError);
648  printf("%10s\t%11s\t%6lf %2s %lf\n", "", "Model:", dens1 * m_model->Parameters().V, "+-", 0.);
649  printf("%10s\t%11s\t%6lf\n", "", "Deviation:", (dens1 * m_model->Parameters().V - mult.fValue) / mult.fError);
650  printf("\n");
651 
652  }
653  }
654 
655  for (size_t i = 0; i < m_Quantities.size(); ++i) {
656  if (m_Quantities[i].type == FittedQuantity::Ratio) {
657  const ExperimentRatio &ratio = m_Quantities[i].ratio;
658  double dens1 = m_model->GetDensity(ratio.fPDGID1, ratio.fFeedDown1);
659  double dens2 = m_model->GetDensity(ratio.fPDGID2, ratio.fFeedDown2);
660  std::string name1 = m_model->TPS()->GetNameFromPDG(ratio.fPDGID1);
661  std::string name2 = m_model->TPS()->GetNameFromPDG(ratio.fPDGID2);
662  if (ratio.fPDGID1 == 1)
663  name1 = "Npart";
664  if (ratio.fPDGID2 == 1)
665  name2 = "Npart";
666  if (ratio.fPDGID1 == 33340)
667  name1 = m_model->TPS()->ParticleByPDG(3334).Name() + " + " + m_model->TPS()->ParticleByPDG(-3334).Name();
668  if (ratio.fPDGID2 == 33340)
669  name2 = m_model->TPS()->ParticleByPDG(3334).Name() + " + " + m_model->TPS()->ParticleByPDG(-3334).Name();
670  printf("%10s\t%11s\t%6lf %2s %lf\n", (std::string(name1 + "/" + name2)).c_str(), "Experiment:",
671  ratio.fValue, "+-", ratio.fError);
672  printf("%10s\t%11s\t%6lf %2s %lf\n", "", "Model:", dens1 / dens2, "+-", 0.);
673  printf("%10s\t%11s\t%6lf\n", "", "Deviation:", (dens1 / dens2 - ratio.fValue) / ratio.fError);
674  printf("\n");
675  }
676  }
677  }
678 
679  void ThermalModelFit::PrintYieldsTable(std::string filename) {
680  FILE *f = fopen(filename.c_str(), "w");
681 
682  fprintf(f, "%15s\t%25s\t%15s\t%15s\t%15s\t%15s\t%15s\t%15s\t%15s\t%15s\t%15s\n",
683  "N", "Name", "Data", "Error", "Fit", "Deviation", "Deviation2",
684  "Residual", "ResidualError", "Data/Model", "Data/ModelError");
685 
686  //m_model->SetParameters(m_Parameters.GetThermalModelParameters());
687  //m_model->SetQoverB(m_QBgoal);
688  //m_model->FixParameters();
689  //m_model->CalculateDensities();
690  for(size_t i=0;i<m_Multiplicities.size();++i) {
691  double dens1 = m_model->GetDensity(m_Multiplicities[i].fPDGID, m_Multiplicities[i].fFeedDown);
692 
693  std::string tname = m_model->TPS()->GetNameFromPDG(m_Multiplicities[i].fPDGID);
694  if (m_Multiplicities[i].fPDGID==1) tname = "Npart";
695  else if (m_Multiplicities[i].fPDGID==33340) tname = m_model->TPS()->ParticleByPDG(3334).Name() + " + " + m_model->TPS()->ParticleByPDG(-3334).Name();
696  fprintf(f, "%15d\t%25s\t%15lf\t%15lf\t%15lf\t%15lf\t%15lf\t%15lf\t%15lf\t%15lf\t%15lf\n", static_cast<int>(i)+1,
697  tname.c_str(), m_Multiplicities[i].fValue, m_Multiplicities[i].fError, dens1 * m_model->Parameters().V,
698  (m_Multiplicities[i].fValue-dens1 * m_model->Parameters().V)/m_Multiplicities[i].fError,
699  -(m_Multiplicities[i].fValue-dens1 * m_model->Parameters().V)/m_Multiplicities[i].fError,
700  (dens1 * m_model->Parameters().V-m_Multiplicities[i].fValue)/(dens1 * m_model->Parameters().V),
701  m_Multiplicities[i].fError/(dens1 * m_model->Parameters().V),
702  m_Multiplicities[i].fValue/(dens1 * m_model->Parameters().V),
703  m_Multiplicities[i].fError/(dens1 * m_model->Parameters().V));
704  }
705  for(size_t i=0;i<m_Ratios.size();++i) {
706  double dens1 = m_model->GetDensity(m_Ratios[i].fPDGID1, m_Ratios[i].fFeedDown1);
707  double dens2 = m_model->GetDensity(m_Ratios[i].fPDGID2, m_Ratios[i].fFeedDown2);
708  std::string name1 = m_model->TPS()->GetNameFromPDG(m_Ratios[i].fPDGID1);
709  std::string name2 = m_model->TPS()->GetNameFromPDG(m_Ratios[i].fPDGID2);
710  if (m_Ratios[i].fPDGID1==1) name1 = "Npart";
711  if (m_Ratios[i].fPDGID2==1) name2 = "Npart";
712  if (m_Ratios[i].fPDGID1==33340) name1 = m_model->TPS()->ParticleByPDG(3334).Name() + " + " + m_model->TPS()->ParticleByPDG(-3334).Name();
713  if (m_Ratios[i].fPDGID2==33340) name2 = m_model->TPS()->ParticleByPDG(3334).Name() + " + " + m_model->TPS()->ParticleByPDG(-3334).Name();
714 
715  fprintf(f, "%15d\t%25s\t%15lf\t%15lf\t%15lf\t%15lf\t%15lf\t%15lf\t%15lf\t%15lf\t%15lf\n", static_cast<int>(i)+1,
716  (std::string(name1 + "/" + name2)).c_str(), m_Ratios[i].fValue, m_Ratios[i].fError, dens1 / dens2,
717  (m_Ratios[i].fValue - dens1 / dens2)/m_Ratios[i].fError,
718  -(m_Ratios[i].fValue - dens1 / dens2)/m_Ratios[i].fError,
719  (dens1 / dens2-m_Ratios[i].fValue)/(dens1 / dens2),
720  m_Ratios[i].fError/(dens1 / dens2),
721  m_Ratios[i].fValue/(dens1 / dens2),
722  m_Ratios[i].fError/(dens1 / dens2));
723  }
724 
725  fclose(f);
726  }
727 
728  void ThermalModelFit::PrintYieldsTable2(std::string filename) {
729  FILE *f = fopen(filename.c_str(), "w");
730 
731  fprintf(f, "%15s\t%25s\t%15s\t%15s\t%15s\t%15s\n", "N", "Name", "Data", "Error", "Fit", "Deviation");
732  //m_model->SetParameters(m_Parameters.GetThermalModelParameters());
733  //m_model->SetQoverB(m_QBgoal);
734  //m_model->FixParameters();
735  //m_model->CalculateDensities();
736  for(size_t i=0;i<m_Multiplicities.size();++i) {
737 
738  double dens1 = m_model->GetDensity(m_Multiplicities[i].fPDGID, m_Multiplicities[i].fFeedDown);
739  std::string tname = m_model->TPS()->GetNameFromPDG(m_Multiplicities[i].fPDGID);
740  if (m_Multiplicities[i].fPDGID==1) tname = "Npart";
741  else if (m_Multiplicities[i].fPDGID==33340) tname = m_model->TPS()->ParticleByPDG(3334).Name() + " + " + m_model->TPS()->ParticleByPDG(-3334).Name();
742  fprintf(f, "%15lf\t%25s\t%15lf\t%15lf\t%15lf\t%15lf\n", i+1 - 0.3, tname.c_str(), m_Multiplicities[i].fValue, m_Multiplicities[i].fError, dens1 * m_model->Parameters().V, (m_Multiplicities[i].fValue-dens1 * m_model->Parameters().V)/m_Multiplicities[i].fError);
743  fprintf(f, "%15lf\t%25s\t%15lf\t%15lf\t%15lf\t%15lf\n", i+1 + 0.3, tname.c_str(), m_Multiplicities[i].fValue, m_Multiplicities[i].fError, dens1 * m_model->Parameters().V, (m_Multiplicities[i].fValue-dens1 * m_model->Parameters().V)/m_Multiplicities[i].fError);
744  }
745  for(size_t i=0;i<m_Ratios.size();++i) {
746  double dens1 = m_model->GetDensity(m_Ratios[i].fPDGID1, m_Ratios[i].fFeedDown1);
747  double dens2 = m_model->GetDensity(m_Ratios[i].fPDGID2, m_Ratios[i].fFeedDown2);
748 
749  std::string name1 = m_model->TPS()->GetNameFromPDG(m_Ratios[i].fPDGID1);
750  std::string name2 = m_model->TPS()->GetNameFromPDG(m_Ratios[i].fPDGID2);
751  if (m_Ratios[i].fPDGID1==1) name1 = "Npart";
752  if (m_Ratios[i].fPDGID2==1) name2 = "Npart";
753  if (m_Ratios[i].fPDGID1==33340) name1 = m_model->TPS()->ParticleByPDG(3334).Name() + " + " + m_model->TPS()->ParticleByPDG(-3334).Name();
754  if (m_Ratios[i].fPDGID2==33340) name2 = m_model->TPS()->ParticleByPDG(3334).Name() + " + " + m_model->TPS()->ParticleByPDG(-3334).Name();
755 
756  fprintf(f, "%15lf\t%25s\t%15lf\t%15lf\t%15lf\t%15lf\n", i+1 - 0.3, (std::string(name1 + "/" + name2)).c_str(), m_Ratios[i].fValue, m_Ratios[i].fError, dens1 / dens2, (m_Ratios[i].fValue - dens1 / dens2)/m_Ratios[i].fError);
757  fprintf(f, "%15lf\t%25s\t%15lf\t%15lf\t%15lf\t%15lf\n", i+1 + 0.3, (std::string(name1 + "/" + name2)).c_str(), m_Ratios[i].fValue, m_Ratios[i].fError, dens1 / dens2, (m_Ratios[i].fValue - dens1 / dens2)/m_Ratios[i].fError);
758  }
759 
760  fclose(f);
761  }
762 
763  void ThermalModelFit::PrintYieldsLatex(std::string filename, std::string name) {
764  FILE *f = fopen(filename.c_str(), "w");
765  fprintf(f, "\\begin{tabular}{|c|c|c|c|}\n");
766  fprintf(f, "\\hline\n");
767  fprintf(f, "\\multicolumn{4}{|c|}{%s} \\\\\n", name.c_str());
768  fprintf(f, "\\hline\n");
769  fprintf(f, "Yield & Measurement & Fit & Deviation \\\\\n");
770  fprintf(f, "\\hline\n");
771  //m_model->SetParameters(m_Parameters.GetThermalModelParameters());
772  //m_model->SetQoverB(m_QBgoal);
773  //m_model->FixParameters();
774  //m_model->CalculateDensities();
775  for(size_t i=0;i<m_Multiplicities.size();++i) {
776  double dens1 = m_model->GetDensity(m_Multiplicities[i].fPDGID, m_Multiplicities[i].fFeedDown);
777 
778  std::string tname = m_model->TPS()->GetNameFromPDG(m_Multiplicities[i].fPDGID);
779 
780  if (m_Multiplicities[i].fPDGID==1) tname = "Npart";
781  else if (m_Multiplicities[i].fPDGID==33340) tname = m_model->TPS()->ParticleByPDG(3334).Name() + " + " + m_model->TPS()->ParticleByPDG(-3334).Name();
782  fprintf(f, "$%s$ & $%.4lf \\pm %.4lf$ & $%.4lf$ & $%.4lf$ \\\\\n", tname.c_str(), m_Multiplicities[i].fValue, m_Multiplicities[i].fError, dens1 * m_model->Parameters().V, (dens1 * m_model->Parameters().V-m_Multiplicities[i].fValue)/m_Multiplicities[i].fError);
783  }
784  for(size_t i=0;i<m_Ratios.size();++i) {
785  int ind1 = m_model->TPS()->PdgToId(m_Ratios[i].fPDGID1);
786  int ind2 = m_model->TPS()->PdgToId(m_Ratios[i].fPDGID2);
787  double dens1 = m_model->GetDensity(m_Ratios[i].fPDGID1, m_Ratios[i].fFeedDown1);
788  double dens2 = m_model->GetDensity(m_Ratios[i].fPDGID2, m_Ratios[i].fFeedDown2);
789 
790  std::string name1 = m_model->TPS()->Particles()[ind1].Name();
791  std::string name2 = m_model->TPS()->Particles()[ind2].Name();
792  if (m_Ratios[i].fPDGID1==1) name1 = "Npart";
793  if (m_Ratios[i].fPDGID2==1) name2 = "Npart";
794  if (m_Ratios[i].fPDGID1==33340) name1 = m_model->TPS()->Particles()[m_model->TPS()->PdgToId(3334)].Name() + " + " + m_model->TPS()->Particles()[m_model->TPS()->PdgToId(-3334)].Name();
795  if (m_Ratios[i].fPDGID2==33340) name2 = m_model->TPS()->Particles()[m_model->TPS()->PdgToId(3334)].Name() + " + " + m_model->TPS()->Particles()[m_model->TPS()->PdgToId(-3334)].Name();
796  fprintf(f, "$%s$ & $%.4lf \\pm %.4lf$ & $%.4lf$ & $%.4lf$ \\\\\n", (std::string(name1 + "/" + name2)).c_str(), m_Ratios[i].fValue, m_Ratios[i].fError, dens1 / dens2 , (dens1 / dens2 - m_Ratios[i].fValue)/m_Ratios[i].fError);
797  }
798  fprintf(f, "\\hline\n");
799  fprintf(f, "\\end{tabular}\n");
800 
801  fprintf(f, "\\begin{tabular}{|c|c|}\n");
802  fprintf(f, "\\hline\n");
803  fprintf(f, "\\multicolumn{2}{|c|}{%s} \\\\\n", name.c_str());
804  fprintf(f, "\\hline\n");
805  fprintf(f, "Parameter & Fit result \\\\\n");
806  fprintf(f, "\\hline\n");
807  for(int i=0;i<6;++i) {
808  FitParameter param = m_Parameters.GetParameter(i);
809  if (param.toFit) {
810  double tval = param.value, terr = param.error;
811  if (param.name=="T" || param.name.substr(0,2)=="mu") { tval *= 1000.; terr *= 1000.; }
812  fprintf(f, "$%s$ & $%.2lf \\pm %.2lf$ \\\\\n", param.name.c_str(), tval, terr);
813  }
814  }
815  fprintf(f, "$%s$ & $%.2lf/%d$ \\\\\n", "\\chi^2/N_{\\rm df}", m_Parameters.chi2ndf * GetNdf(), GetNdf());
816  fprintf(f, "\\hline\n");
817  fprintf(f, "\\end{tabular}\n");
818 
819  fclose(f);
820  }
821 
822  void ThermalModelFit::PrintYieldsLatexAll(std::string filename, std::string name, bool asymm) {
823  FILE *f = fopen(filename.c_str(), "w");
824  fprintf(f, "\\begin{tabular}{|c|c|c|c|}\n");
825  fprintf(f, "\\hline\n");
826  fprintf(f, "\\multicolumn{4}{|c|}{%s} \\\\\n", name.c_str());
827  fprintf(f, "\\hline\n");
828  fprintf(f, "Yield & Measurement & Fit \\\\\n");
829  fprintf(f, "\\hline\n");
830  //m_model->SetParameters(m_Parameters.GetThermalModelParameters());
831  //m_model->SetQoverB(m_QBgoal);
832  //m_model->FixParameters();
833  //m_model->CalculateDensities();
834 
835  std::vector<std::string> prt(0);
836  std::vector<long long> pdgs(0);
837  std::vector<int> fl(m_Multiplicities.size(), 0);
838  prt.push_back("\\pi^+"); pdgs.push_back(211);
839  prt.push_back("\\pi^-"); pdgs.push_back(-211);
840  prt.push_back("K^+"); pdgs.push_back(321);
841  prt.push_back("K^-"); pdgs.push_back(-321);
842  prt.push_back("p"); pdgs.push_back(2212);
843  prt.push_back("\\bar{p}"); pdgs.push_back(-2212);
844  prt.push_back("\\Lambda"); pdgs.push_back(3122);
845  prt.push_back("\\bar{\\Lambda}"); pdgs.push_back(-3122);
846  prt.push_back("\\Sigma^+"); pdgs.push_back(3222);
847  prt.push_back("\\bar{\\Sigma}^+"); pdgs.push_back(-3222);
848  prt.push_back("\\Sigma^-"); pdgs.push_back(3112);
849  prt.push_back("\\bar{\\Sigma}^-"); pdgs.push_back(-3112);
850  prt.push_back("\\Xi^0"); pdgs.push_back(3322);
851  prt.push_back("\\bar{\\Xi}^0"); pdgs.push_back(-3322);
852  prt.push_back("\\Xi^-"); pdgs.push_back(3312);
853  prt.push_back("\\bar{\\Xi}^-"); pdgs.push_back(-3312);
854  prt.push_back("\\Omega"); pdgs.push_back(3334);
855  prt.push_back("\\bar{\\Omega}"); pdgs.push_back(-3334);
856  prt.push_back("\\pi^0"); pdgs.push_back(111);
857  prt.push_back("K^0_S"); pdgs.push_back(310);
858  prt.push_back("\\eta"); pdgs.push_back(221);
859  prt.push_back("\\omega"); pdgs.push_back(223);
860  prt.push_back("K^{*+}"); pdgs.push_back(323);
861  prt.push_back("K^{*-}"); pdgs.push_back(-323);
862  prt.push_back("K^{*0}"); pdgs.push_back(313);
863  prt.push_back("\\bar{K^{*0}}"); pdgs.push_back(-313);
864  //prt.push_back("K^*(892)"); pdgs.push_back(323);
865  prt.push_back("\\rho^+"); pdgs.push_back(213);
866  prt.push_back("\\rho^-"); pdgs.push_back(-213);
867  prt.push_back("\\rho^0"); pdgs.push_back(113);
868  prt.push_back("\\eta'"); pdgs.push_back(331);
869  prt.push_back("\\phi"); pdgs.push_back(333);
870  prt.push_back("\\Lambda(1520)"); pdgs.push_back(3124);
871 
872 
873 
874  prt.push_back("d"); pdgs.push_back(1000010020);
875  prt.push_back("^3He"); pdgs.push_back(1000020030);
876  prt.push_back("^3_{\\Lambda}H"); pdgs.push_back(1010010030);
877  prt.push_back("D^+"); pdgs.push_back(411);
878  prt.push_back("D^-"); pdgs.push_back(-411);
879  prt.push_back("D^0"); pdgs.push_back(421);
880  prt.push_back("\\bar{D}^0"); pdgs.push_back(-421);
881 
882  for(size_t i=0;i<prt.size();++i) {
883  bool isexp = false;
884  int tj = -1;
885  for(size_t j=0;j<m_Multiplicities.size();++j)
886  if (pdgs[i]==m_Multiplicities[j].fPDGID) { isexp = true; fl[j] = 1; tj = j; break; }
887 
888  if (m_model->TPS()->PdgToId(pdgs[i]) == -1) continue;
889 
890  double dens1 = 0.;
891  dens1 = m_model->GetDensity(pdgs[i], Feeddown::StabilityFlag);
892 
893  if (isexp) dens1 = m_model->GetDensity(pdgs[i], m_Multiplicities[tj].fFeedDown);
894 
895  std::string tname = prt[i];
896 
897  if (!isexp) {
898  if (dens1 * m_model->Parameters().V>1.e-3) fprintf(f, "$%s$ & & $%.3g$ \\\\\n", tname.c_str(), dens1 * m_model->Parameters().V);
899  else {
900  char tnum[400];
901  sprintf(tnum, "%.2E", dens1 * m_model->Parameters().V);
902  double val = 0.;
903  int step = 0;
904  char valst[6];
905  char stepst[6];
906  for(int ii=0;ii<4;++ii) valst[ii] = tnum[ii];
907  valst[4] = 0;
908  for(int ii=0;ii<4;++ii) stepst[ii] = tnum[5+ii];
909  stepst[4] = 0;
910  val = atof(valst);
911  step = atoi(stepst);
912  fprintf(f, "$%s$ & & $%.2lf \\cdot 10^{%d}$ \\\\\n", tname.c_str(), val, step);
913  }
914  }
915  else {
916  if (m_Multiplicities[tj].fValue>0.999) fprintf(f, "$%s$ & $%.4g \\pm %.4g$ & $%.4g$ \\\\\n", tname.c_str(), m_Multiplicities[tj].fValue, m_Multiplicities[tj].fError, dens1 * m_model->Parameters().V);//, (dens1 * m_model->Parameters().V-m_Multiplicities[tj].fValue)/m_Multiplicities[tj].fError);
917  else if (dens1 * m_model->Parameters().V>1.e-3) fprintf(f, "$%s$ & $%.3g \\pm %.3g$ & $%.3g$ \\\\\n", tname.c_str(), m_Multiplicities[tj].fValue, m_Multiplicities[tj].fError, dens1 * m_model->Parameters().V);//, (dens1 * m_model->Parameters().V-m_Multiplicities[tj].fValue)/m_Multiplicities[tj].fError);
918  else fprintf(f, "$%s$ & $%.6g \\pm %.6g$ & $%.3g$ \\\\\n", tname.c_str(), m_Multiplicities[tj].fValue, m_Multiplicities[tj].fError, dens1 * m_model->Parameters().V);//, (dens1 * m_model->Parameters().V-m_Multiplicities[tj].fValue)/m_Multiplicities[tj].fError);
919  }
920  }
921 
922  for(size_t i=0;i<m_Multiplicities.size();++i)
923  if (!fl[i]) {
924  double dens1 = m_model->GetDensity(m_Multiplicities[i].fPDGID, m_Multiplicities[i].fFeedDown);
925 
926  std::string tname = m_model->TPS()->GetNameFromPDG(m_Multiplicities[i].fPDGID);
927  if (m_Multiplicities[i].fPDGID==1) tname = "Npart";
928  else if (m_Multiplicities[i].fPDGID==33340) tname = m_model->TPS()->Particles()[m_model->TPS()->PdgToId(3334)].Name() + " + " + m_model->TPS()->Particles()[m_model->TPS()->PdgToId(-3334)].Name();
929  fprintf(f, "$%s$ & $%.4lf \\pm %.4lf$ & $%.4lf$ & $%.4lf$ \\\\\n", tname.c_str(), m_Multiplicities[i].fValue, m_Multiplicities[i].fError, dens1 * m_model->Parameters().V, (dens1 * m_model->Parameters().V-m_Multiplicities[i].fValue)/m_Multiplicities[i].fError);
930  }
931  for(size_t i=0;i<m_Ratios.size();++i) {
932  double dens1 = m_model->GetDensity(m_Ratios[i].fPDGID1, m_Ratios[i].fFeedDown1);
933  double dens2 = m_model->GetDensity(m_Ratios[i].fPDGID2, m_Ratios[i].fFeedDown2);
934 
935  std::string name1 = m_model->TPS()->GetNameFromPDG(m_Ratios[i].fPDGID1);
936  std::string name2 = m_model->TPS()->GetNameFromPDG(m_Ratios[i].fPDGID2);
937  if (m_Ratios[i].fPDGID1==1) name1 = "Npart";
938  if (m_Ratios[i].fPDGID2==1) name2 = "Npart";
939  if (m_Ratios[i].fPDGID1==33340) name1 = m_model->TPS()->Particles()[m_model->TPS()->PdgToId(3334)].Name() + " + " + m_model->TPS()->Particles()[m_model->TPS()->PdgToId(-3334)].Name();
940  if (m_Ratios[i].fPDGID2==33340) name2 = m_model->TPS()->Particles()[m_model->TPS()->PdgToId(3334)].Name() + " + " + m_model->TPS()->Particles()[m_model->TPS()->PdgToId(-3334)].Name();
941  fprintf(f, "$%s$ & $%.4lf \\pm %.4lf$ & $%.4lf$ & $%.4lf$ \\\\\n", (std::string(name1 + "/" + name2)).c_str(), m_Ratios[i].fValue, m_Ratios[i].fError, dens1 / dens2 , (dens1 / dens2 - m_Ratios[i].fValue)/m_Ratios[i].fError);
942  }
943  fprintf(f, "\\hline\n");
944  fprintf(f, "\\end{tabular}\n");
945 
946  fprintf(f, "\\begin{tabular}{|c|c|}\n");
947  fprintf(f, "\\hline\n");
948  fprintf(f, "\\multicolumn{2}{|c|}{%s} \\\\\n", name.c_str());
949  fprintf(f, "\\hline\n");
950  fprintf(f, "Parameter & Fit result \\\\\n");
951  fprintf(f, "\\hline\n");
952  for(int i=0;i<9;++i) {
953  FitParameter param = m_Parameters.GetParameter(i);
954  if (param.toFit) {
955  double tval = param.value, terr = param.error, terrp = param.errp, terrm = param.errm;
956  if (param.name=="T" || param.name.substr(0,2)=="mu") { tval *= 1000.; terr *= 1000.; terrp *= 1000.; terrm *= 1000.; }
957  if (!asymm) fprintf(f, "$%s$ & $%.3lf \\pm %.3lf$ \\\\\n", param.name.c_str(), tval, terr);
958  else fprintf(f, "$%s$ & $%.3lf^{+%.3lf}_{-%.3lf}$ \\\\\n", param.name.c_str(), tval, terrp, terrm);
959  }
960  }
961  fprintf(f, "$%s$ & $%.2lf/%d$ \\\\\n", "\\chi^2/N_{\\rm df}", m_Parameters.chi2ndf * GetNdf(), GetNdf());
962  fprintf(f, "\\hline\n");
963  fprintf(f, "\\end{tabular}\n");
964 
965  fclose(f);
966  }
967 
968  std::string ThermalModelFit::GetCurrentTime() {
969  time_t rawtime;
970  struct tm * timeinfo;
971  char buffer[1000];
972 
973  time(&rawtime);
974  timeinfo = localtime(&rawtime);
975 
976  strftime(buffer, sizeof(buffer), "%d-%m-%Y at %I:%M:%S", timeinfo);
977  std::string str(buffer);
978 
979  return str;
980  }
981 
982  void ThermalModelFit::PrintFitLog(std::string filename, std::string comment, bool asymm)
983  {
984  std::ostream *fout;
985  if (filename != "")
986  fout = new std::ofstream(filename.c_str());
987  else
988  fout = &std::cout;
989 
990  //FILE *f;
991  //if (filename != "") {
992  // f = fopen(filename.c_str(), "w");
993  //}
994  //else {
995  // f = stdout;
996  //}
997 
998  if (comment != "")
999  *fout << comment << std::endl << std::endl;
1000  //fprintf(f, "%s\n\n", comment.c_str());
1001 
1002  //fprintf(f, "Performed on %s\n\n", GetCurrentTime().c_str());
1003  *fout << "Performed on " << GetCurrentTime() << std::endl << std::endl;
1004 
1005  //fprintf(f, "chi2/dof = %lf/%d = %lf\n\n", m_Parameters.chi2, m_Parameters.ndf, m_Parameters.chi2ndf);
1006  *fout << "chi2/dof = " << m_Parameters.chi2 << "/" << m_Parameters.ndf << " = " << m_Parameters.chi2ndf << std::endl << std::endl;
1007 
1008  std::pair<double, double> accuracy = ModelDescriptionAccuracy();
1009  //fprintf(f, "Data description accuracy = (%.2lf +- %.2lf) %%\n\n", accuracy.first * 100., accuracy.second * 100.);
1010  *fout << "Data description accuracy = ("
1011  << std::fixed
1012  << std::setprecision(2)
1013  << accuracy.first * 100. << " +- " << accuracy.second * 100. << ") %" << std::endl << std::endl;
1014 
1015  fout->unsetf(std::ios_base::floatfield);
1016  *fout << std::setprecision(6);
1017 
1018  //fprintf(f, "Extracted parameters:\n");
1019  *fout << "Extracted parameters:" << std::endl;
1020  for (int i = 0; i < 10 ; ++i) {
1021  if (i == 6 && m_model->Ensemble() != ThermalModelBase::SCE && m_model->Ensemble() != ThermalModelBase::CE)
1022  continue;
1023  FitParameter param = m_Parameters.GetParameter(i);
1024  std::string sunit = "";
1025  std::string tname = "";
1026  double tmn = 1.;
1027  if (param.name == "T" || param.name.substr(0, 2) == "mu") {
1028  sunit = "[MeV]";
1029  tmn = 1.e3;
1030  }
1031  else if (param.name == "R" || param.name == "Rc") {
1032  sunit = "[fm]";
1033  }
1034  tname = param.name + sunit;
1035 
1036  if (param.name == "Rc" && m_model->Ensemble() == ThermalModelBase::GCE)
1037  continue;
1038 
1039  if (param.name == "muS" && (m_model->Ensemble() == ThermalModelBase::SCE || m_model->Ensemble() == ThermalModelBase::CE))
1040  continue;
1041 
1042  if (param.name == "muB" && m_model->Ensemble() == ThermalModelBase::CE)
1043  continue;
1044 
1045  if (param.name == "muQ" && m_model->Ensemble() == ThermalModelBase::CE)
1046  continue;
1047 
1048  if ((param.name == "muS" || param.name == "gammaS") && !m_model->TPS()->hasStrange())
1049  continue;
1050  if (param.name == "muQ" && !m_model->TPS()->hasCharged())
1051  continue;
1052  if ((param.name == "muC" || param.name == "gammaC") && !m_model->TPS()->hasCharmed())
1053  continue;
1054 
1055  if (param.toFit) {
1056  double tval = param.value, terr = param.error, terrp = param.errp, terrm = param.errm;
1057 
1058  if (param.name == "Tkin" && !m_YieldsAtTkin)
1059  continue;
1060 
1061  if (param.name != "R" && param.name != "Rc") {
1062  if (!asymm)
1063  *fout << std::setw(15) << tname
1064  << " = "
1065  << std::setw(15) << tval * tmn
1066  << " +- "
1067  << std::left << std::setw(15) << terr * tmn << std::right
1068  << std::endl;
1069  //fprintf(f, "%15s = %15lf +- %-15lf\n", tname.c_str(), tval * tmn, terr * tmn);
1070  else
1071  *fout << std::setw(15) << tname
1072  << " = "
1073  << std::setw(15) << tval * tmn
1074  << " + "
1075  << std::left << std::setw(15) << terrp * tmn << std::right
1076  << " - "
1077  << std::left << std::setw(15) << terrm * tmn << std::right
1078  << std::endl;
1079  //fprintf(f, "%15s = %15lf + %-15lf - %-15lf\n", tname.c_str(), tval * tmn, terrp * tmn, terrm * tmn);
1080  }
1081  else {
1082  if (!asymm) {
1083  *fout << std::setw(15) << tname
1084  << " = "
1085  << std::setw(15) << tval * tmn
1086  << " +- "
1087  << std::left << std::setw(15) << terr * tmn << std::right
1088  << "\t";
1089  //fprintf(f, "%15s = %15lf +- %-15lf\t", tname.c_str(), tval * tmn, terr * tmn);
1090  std::string tname2 = "V[fm3]";
1091  if (param.name == "Rc")
1092  tname2 = "Vc[fm3]";
1093  *fout << std::setw(15) << tname2
1094  << " = "
1095  << std::setw(15) << 4. / 3. * xMath::Pi() * pow(tval * tmn, 3)
1096  << " +- "
1097  << std::left << std::setw(15) << 4. * xMath::Pi() * pow(tval * tmn, 2) * terr * tmn << std::right
1098  << std::endl;
1099  //fprintf(f, "%15s = %15lf +- %-15lf\n", tname2.c_str(), 4. / 3. * xMath::Pi() * pow(tval * tmn, 3), 4. * xMath::Pi() * pow(tval * tmn, 2) * terr * tmn);
1100  }
1101  else {
1102  *fout << std::setw(15) << tname
1103  << " = "
1104  << std::setw(15) << tval * tmn
1105  << " + "
1106  << std::left << std::setw(15) << terrp * tmn << std::right
1107  << " - "
1108  << std::left << std::setw(15) << terrm * tmn << std::right
1109  << "\t";
1110  //fprintf(f, "%15s = %15lf + %-15lf - %-15lf\t", tname.c_str(), tval * tmn, terrp * tmn, terrm * tmn);
1111  std::string tname2 = "V[fm3]";
1112  if (param.name == "Rc")
1113  tname2 = "Vc[fm3]";
1114  *fout << std::setw(15) << tname2
1115  << " = "
1116  << std::setw(15) << 4. / 3. * xMath::Pi() * pow(tval * tmn, 3)
1117  << " + "
1118  << std::left << std::setw(15) << 4. * xMath::Pi() * pow(tval * tmn, 2) * terrp * tmn << std::right
1119  << " - "
1120  << std::left << std::setw(15) << 4. * xMath::Pi() * pow(tval * tmn, 2) * terrm * tmn << std::right
1121  << std::endl;
1122  //fprintf(f, "%15s = %15lf + %-15lf - %-15lf\n", tname2.c_str(), 4. / 3. * xMath::Pi() * pow(tval * tmn, 3), 4. * xMath::Pi() * pow(tval * tmn, 2) * terrp * tmn, 4. * xMath::Pi() * pow(tval * tmn, 2) * terrm * tmn);
1123  }
1124  }
1125  }
1126  else {
1127  double tval = param.value;
1128  if (param.name != "R" && param.name != "Rc")
1129  *fout << std::setw(15) << tname
1130  << " = "
1131  << std::setw(15) << tval * tmn
1132  << " (FIXED)" << std::endl;
1133  //fprintf(f, "%15s = %15lf (FIXED)\n", tname.c_str(), tval * tmn);
1134  else {
1135  //fprintf(f, "%15s = %15lf (FIXED)\t", tname.c_str(), tval * tmn);
1136  *fout << std::setw(15) << tname
1137  << " = "
1138  << std::setw(15) << tval * tmn
1139  << " (FIXED)" << "\t";
1140  std::string tname2 = "V[fm3]";
1141  if (param.name == "Rc")
1142  tname2 = "Vc[fm3]";
1143  *fout << std::setw(15) << tname2
1144  << " = "
1145  << std::setw(15) << 4. / 3. * xMath::Pi() * pow(tval * tmn, 3)
1146  << " (FIXED)" << std::endl;
1147  //fprintf(f, "%15s = %15lf (FIXED)\n", tname2.c_str(), 4. / 3. * xMath::Pi() * pow(tval * tmn, 3));
1148  }
1149  }
1150  }
1151 
1152  //fprintf(f, "\n\n");
1153  *fout << std::endl << std::endl;
1154 
1155  *fout << "Yields:" << std::endl;
1156  //fprintf(f, "Yields:\n");
1157  for (size_t i = 0; i<m_Multiplicities.size(); ++i) {
1158  double dens1 = m_model->GetDensity(m_Multiplicities[i].fPDGID, m_Multiplicities[i].fFeedDown);
1159 
1160  std::string tname = m_model->TPS()->GetNameFromPDG(m_Multiplicities[i].fPDGID);
1161  if (m_Multiplicities[i].fPDGID == 1) tname = "Npart";
1162  else if (m_Multiplicities[i].fPDGID == 33340) tname = m_model->TPS()->Particles()[m_model->TPS()->PdgToId(3334)].Name() + " + " + m_model->TPS()->Particles()[m_model->TPS()->PdgToId(-3334)].Name();
1163 
1164  *fout << std::setw(25) << tname
1165  << " Experiment: ";
1166 
1167  if (m_Multiplicities[i].fValue > 1.e-5 && m_Multiplicities[i].fError > 1.e-5)
1168  fout->unsetf(std::ios_base::floatfield);
1169  else
1170  *fout << std::scientific;
1171 
1172  *fout << std::setw(15) << m_Multiplicities[i].fValue;
1173  *fout << " +- ";
1174  *fout << std::left << std::setw(15) << m_Multiplicities[i].fError << std::right << " ";
1175  *fout << "Model: ";
1176  *fout << std::left << std::setw(15) << dens1 * m_model->Parameters().V << std::right << " ";
1177 
1178  fout->unsetf(std::ios_base::floatfield);
1179 
1180  *fout << "Std.dev.: ";
1181  *fout << std::left << std::setw(15) << (dens1* m_model->Parameters().V - m_Multiplicities[i].fValue) / m_Multiplicities[i].fError << std::right << " ";
1182  *fout << std::endl;
1183 
1184  //if (m_Multiplicities[i].fValue > 1.e-5 && m_Multiplicities[i].fError > 1.e-5)
1185  // fprintf(f, "%25s Experiment: %15lf +- %-15lf Model: %-15lf Std.dev.: %-15lf \n", tname.c_str(), m_Multiplicities[i].fValue, m_Multiplicities[i].fError, dens1 * m_model->Parameters().V, (dens1 * m_model->Parameters().V - m_Multiplicities[i].fValue) / m_Multiplicities[i].fError);
1186  //else
1187  // fprintf(f, "%25s Experiment: %15E +- %-15E Model: %-15E Std.dev.: %-15lf \n", tname.c_str(), m_Multiplicities[i].fValue, m_Multiplicities[i].fError, dens1 * m_model->Parameters().V, (dens1 * m_model->Parameters().V - m_Multiplicities[i].fValue) / m_Multiplicities[i].fError);
1188  }
1189 
1190  for (size_t i = 0; i<m_Ratios.size(); ++i) {
1191  double dens1 = m_model->GetDensity(m_Ratios[i].fPDGID1, m_Ratios[i].fFeedDown1);
1192  double dens2 = m_model->GetDensity(m_Ratios[i].fPDGID2, m_Ratios[i].fFeedDown2);
1193 
1194  std::string name1 = m_model->TPS()->GetNameFromPDG(m_Ratios[i].fPDGID1);
1195  std::string name2 = m_model->TPS()->GetNameFromPDG(m_Ratios[i].fPDGID2);
1196  if (m_Ratios[i].fPDGID1 == 1) name1 = "Npart";
1197  if (m_Ratios[i].fPDGID2 == 1) name2 = "Npart";
1198  if (m_Ratios[i].fPDGID1 == 33340) name1 = m_model->TPS()->Particles()[m_model->TPS()->PdgToId(3334)].Name() + " + " + m_model->TPS()->Particles()[m_model->TPS()->PdgToId(-3334)].Name();
1199  if (m_Ratios[i].fPDGID2 == 33340) name2 = m_model->TPS()->Particles()[m_model->TPS()->PdgToId(3334)].Name() + " + " + m_model->TPS()->Particles()[m_model->TPS()->PdgToId(-3334)].Name();
1200 
1201  *fout << std::setw(25) << std::string(name1 + "/" + name2)
1202  << " Experiment: ";
1203 
1204  if (m_Ratios[i].fValue > 1.e-5 && m_Ratios[i].fError > 1.e-5)
1205  fout->unsetf(std::ios_base::floatfield);
1206  else
1207  *fout << std::scientific;
1208 
1209  *fout << std::setw(15) << m_Ratios[i].fValue;
1210  *fout << " +- ";
1211  *fout << std::left << std::setw(15) << m_Ratios[i].fError << std::right << " ";
1212  *fout << "Model: ";
1213  *fout << std::left << std::setw(15) << dens1 / dens2 << std::right << " ";
1214 
1215  fout->unsetf(std::ios_base::floatfield);
1216 
1217  *fout << "Std.dev.: ";
1218  *fout << std::left << std::setw(15) << (dens1 / dens2 - m_Ratios[i].fValue) / m_Ratios[i].fError << std::right << " ";
1219  *fout << std::endl;
1220 
1221  //if (m_Ratios[i].fValue > 1.e-5 && m_Ratios[i].fError > 1.e-5)
1222  // fprintf(f, "%25s Experiment: %15lf +- %-15lf Model: %-15lf Std.dev.: %-15lf \n", (std::string(name1 + "/" + name2)).c_str(), m_Ratios[i].fValue, m_Ratios[i].fError, dens1 / dens2, (dens1 / dens2 - m_Ratios[i].fValue) / m_Ratios[i].fError);
1223  //else
1224  // fprintf(f, "%25s Experiment: %15E +- %-15E Model: %-15E Std.dev.: %-15lf \n", (std::string(name1 + "/" + name2)).c_str(), m_Ratios[i].fValue, m_Ratios[i].fError, dens1 / dens2, (dens1 / dens2 - m_Ratios[i].fValue) / m_Ratios[i].fError);
1225  }
1226 
1227  //if (f != stdout)
1228  // fclose(f);
1229  if (filename != "" && fout != NULL) {
1230  delete fout;
1231  }
1232  }
1233 
1234  using namespace std;
1235 
1236  std::pair<double, double> ThermalModelFit::ModelDescriptionAccuracy() const
1237  {
1238  double chi2total = 0.;
1239  std::vector<double> weights;
1240  std::vector<double> vals, errors;
1241  for (int i = 0; i < ModelDataSize(); ++i) {
1242  const FittedQuantity &quantity = FittedQuantities()[i];
1243  if (quantity.toFit) {
1244  vals.push_back(fabs(m_ModelData[i] / quantity.Value() - 1));
1245  errors.push_back(quantity.ValueError() / quantity.Value() * m_ModelData[i] / quantity.Value());
1246 
1247  double chi2contrib = (m_ModelData[i] - quantity.Value()) * (m_ModelData[i] - quantity.Value()) / quantity.ValueError() / quantity.ValueError();
1248 
1249  chi2total += chi2contrib;
1250  weights.push_back(chi2contrib);
1251  }
1252  }
1253 
1254  for (size_t i = 0; i < weights.size(); ++i) {
1255  weights[i] /= chi2total;
1256  }
1257 
1258  double mean = 0., error = 0.;
1259  for (size_t i = 0; i < vals.size(); ++i) {
1260  mean += vals[i] * weights[i];
1261  error += errors[i] * weights[i];
1262  }
1263 
1264  return make_pair(mean, error);
1265  }
1266 
1267  std::vector<FittedQuantity> ThermalModelFit::loadExpDataFromFile(const std::string & filename) {
1268  std::vector<FittedQuantity> ret(0);
1269  fstream fin;
1270  fin.open(filename.c_str());
1271  if (fin.is_open()) {
1272  char tmpc[2000];
1273  fin.getline(tmpc, 2000);
1274  string tmp = string(tmpc);
1275  vector<string> elems = CuteHRGHelper::split(tmp, '#');
1276 
1277  int flnew = 0;
1278  if (elems.size() < 1 || CuteHRGHelper::split(elems[0], ';').size() < 4)
1279  flnew = 1;
1280  else
1281  flnew = 0;
1282 
1283  fin.clear();
1284  fin.seekg(0, ios::beg);
1285 
1286  if (flnew == 1)
1287  ret = loadExpDataFromFile_NewFormat(fin);
1288  else
1289  ret = loadExpDataFromFile_OldFormat(fin);
1290 
1291  fin.close();
1292  }
1293  return ret;
1294  }
1295 
1296  std::vector<FittedQuantity> ThermalModelFit::loadExpDataFromFile_OldFormat(std::fstream & fin)
1297  {
1298  std::vector<FittedQuantity> ret(0);
1299  if (fin.is_open()) {
1300  string tmp;
1301  char tmpc[2000];
1302  fin.getline(tmpc, 2000);
1303  tmp = string(tmpc);
1304  while (1) {
1305  vector<string> fields = CuteHRGHelper::split(tmp, ';');
1306  if (fields.size()<4) break;
1307  int type = atoi(fields[0].c_str());
1308  long long pdgid1 = stringToLongLong(fields[1]), pdgid2 = 0;
1309  double value = 0., error = 0., error2 = 0.;
1310  int feeddown1 = 1, feeddown2 = 1;
1311  if (type) {
1312  pdgid2 = stringToLongLong(fields[2]);
1313  value = atof(fields[3].c_str());
1314  if (fields.size() >= 5) error = atof(fields[4].c_str());
1315  if (fields.size() >= 6) {
1316  error2 = atof(fields[5].c_str());
1317  error = sqrt(error*error + error2*error2);
1318  }
1319  if (fields.size() >= 7) feeddown1 = atoi(fields[6].c_str());
1320  if (fields.size() >= 8) feeddown2 = atoi(fields[7].c_str());
1321  }
1322  else {
1323  value = atof(fields[2].c_str());
1324  error = atof(fields[3].c_str());
1325  if (fields.size() >= 5) {
1326  error2 = atof(fields[4].c_str());
1327  error = sqrt(error*error + error2*error2);
1328  }
1329  if (fields.size() >= 6) feeddown1 = atoi(fields[5].c_str());
1330  }
1331 
1332  if (type) ret.push_back(FittedQuantity(ExperimentRatio(pdgid1, pdgid2, value, error, static_cast<Feeddown::Type>(feeddown1), static_cast<Feeddown::Type>(feeddown2))));
1333  else ret.push_back(FittedQuantity(ExperimentMultiplicity(pdgid1, value, error, static_cast<Feeddown::Type>(feeddown1))));
1334 
1335  fin.getline(tmpc, 500);
1336  tmp = string(tmpc);
1337  }
1338  fin.close();
1339  }
1340  return ret;
1341  }
1342 
1343  std::vector<FittedQuantity> ThermalModelFit::loadExpDataFromFile_NewFormat(std::fstream & fin)
1344  {
1345  std::vector<FittedQuantity> ret(0);
1346  if (fin.is_open()) {
1347  char cc[2000];
1348  while (!fin.eof()) {
1349  fin.getline(cc, 2000);
1350  string tmp = string(cc);
1351  vector<string> elems = CuteHRGHelper::split(tmp, '#');
1352  if (elems.size() < 1)
1353  continue;
1354 
1355  istringstream iss(elems[0]);
1356 
1357  int fitflag;
1358  long long pdgid1, pdgid2;
1359  int feeddown1, feeddown2;
1360  double value, error;
1361 
1362  if (iss >> fitflag >> pdgid1 >> pdgid2 >> feeddown1 >> feeddown2 >> value >> error) {
1363  if (pdgid2 != 0) ret.push_back(FittedQuantity(ExperimentRatio(pdgid1, pdgid2, value, error, static_cast<Feeddown::Type>(feeddown1), static_cast<Feeddown::Type>(feeddown2))));
1364  else ret.push_back(FittedQuantity(ExperimentMultiplicity(pdgid1, value, error, static_cast<Feeddown::Type>(feeddown1))));
1365 
1366  if (fitflag != 0)
1367  ret[ret.size() - 1].toFit = true;
1368  else
1369  ret[ret.size() - 1].toFit = false;
1370  }
1371  }
1372  }
1373  return ret;
1374  }
1375 
1376  void ThermalModelFit::saveExpDataToFile(const std::vector<FittedQuantity>& outQuantities, const std::string & filename)
1377  {
1378  std::ofstream fout(filename.c_str());
1379  if (fout.is_open()) {
1380  fout << "#"
1381  << std::setw(14) << "is_fitted"
1382  << std::setw(15) << "pdg1"
1383  << std::setw(15) << "pdg2"
1384  << std::setw(15) << "feeddown1"
1385  << std::setw(15) << "feeddown2"
1386  << std::setw(15) << "value"
1387  << std::setw(15) << "error"
1388  << std::endl;
1389  for (size_t i = 0; i < outQuantities.size(); ++i) {
1390  if (outQuantities[i].type == FittedQuantity::Multiplicity) {
1391  fout << std::setw(15) << static_cast<int>(outQuantities[i].toFit)
1392  << std::setw(15) << outQuantities[i].mult.fPDGID
1393  << std::setw(15) << 0
1394  << std::setw(15) << outQuantities[i].mult.fFeedDown
1395  << std::setw(15) << 0
1396  << std::setw(15) << outQuantities[i].mult.fValue
1397  << std::setw(15) << outQuantities[i].mult.fError
1398  << std::endl;
1399  }
1400  else {
1401  fout << std::setw(15) << static_cast<int>(outQuantities[i].toFit)
1402  << std::setw(15) << outQuantities[i].ratio.fPDGID1
1403  << std::setw(15) << outQuantities[i].ratio.fPDGID2
1404  << std::setw(15) << outQuantities[i].ratio.fFeedDown1
1405  << std::setw(15) << outQuantities[i].ratio.fFeedDown2
1406  << std::setw(15) << outQuantities[i].ratio.fValue
1407  << std::setw(15) << outQuantities[i].ratio.fError
1408  << std::endl;
1409  }
1410  }
1411  fout.close();
1412  }
1413  else {
1414  printf("**WARNING** ThermalModelFit::saveExpDataToFile: Cannot open file for writing data!");
1415  }
1416  }
1417 
1419  int nparams = 11;
1420  if (!m_Parameters.T.toFit) nparams--;
1421  if (!m_Parameters.muB.toFit) nparams--;
1422  if (!m_Parameters.muS.toFit) nparams--;
1423  if (!m_Parameters.muQ.toFit) nparams--;
1424  if (!m_Parameters.muC.toFit) nparams--;
1425  if (!m_Parameters.gammaq.toFit) nparams--;
1426  if (!m_Parameters.gammaS.toFit) nparams--;
1427  if (!m_Parameters.gammaC.toFit) nparams--;
1428  if (!m_Parameters.R.toFit || (m_Multiplicities.size()==0 && m_model->Ensemble() == ThermalModelBase::GCE)) nparams--;
1429  if (!m_Parameters.Rc.toFit || (m_model->Ensemble() != ThermalModelBase::CE && m_model->Ensemble() != ThermalModelBase::SCE && m_model->Ensemble() != ThermalModelBase::CCE)) nparams--;
1430  if (!m_Parameters.Tkin.toFit || !UseTkin()) nparams--;
1431  int ndof = 0;
1432  for (size_t i = 0; i < m_Quantities.size(); ++i)
1433  if (m_Quantities[i].toFit) ndof++;
1434  return (ndof - nparams);
1435  }
1436 
1437 
1438 } // namespace thermalfist
Abstract base class for an HRG model implementation.
long long stringToLongLong(const std::string &str)
bool toFit
Whether this quantity contributes to the of a fit.
std::vector< std::string > split(const std::string &s, char delim)
FitParameter T
All the fit parameters.
Class implementing HRG in partial chemical equilibrium.
virtual void FixParameters()
Method which actually implements ConstrainChemicalPotentials() (for backward compatibility).
Contains some helper functions.
double Pi()
Pi constant.
Definition: xMath.h:24
ThermalModelParameters GetThermalModelParameters()
Return ThermalModelParameters corresponding to the this ThermalModelFitParameters.
virtual void SetStabilityFlags(const std::vector< int > &StabilityFlags)
Manually set the PCE stability flags for all species.
int PdgToId(long long pdgid)
Transforms PDG ID to a 0-based particle id number.
Feeddown::Type fFeedDown2
The feeddown contributions to be included for the yield in the denominator.
std::string GetNameFromPDG(long long pdgid)
Get the name of particle species with the specified PDG ID.
Grand canonical ensemble.
int ndf
Number of degrees of freedom.
Structure describing the measurement to be fitted or compared to model.
virtual void SetParameters(const ThermalModelParameters &params)
The thermal parameters.
~ThermalModelFit(void)
Destroy the Thermal Model Fit object.
Structure containing all thermal parameters of the model.
virtual double CalculateStrangenessDensity()
Charm-canonical ensemble.
void PrintYieldsLatex(std::string filename="Yield.dat", std::string name="A+A")
long long fPDGID
PDG code of the particle yield.
ThermalModelEnsemble Ensemble()
The statistical ensemble of the current HRG model.
FitParameter GetParameter(const std::string &name) const
Get the FitParameter by its name.
long long fPDGID1
PDG code of the particle yield in the numerator.
void PrintFitLog(std::string filename="", std::string comment="Thermal fit", bool asymm=false)
Prints the result of the fitting procedure to a file.
Structure containing the experimental ratio of yields to be fitted.
Feeddown::Type fFeedDown
The feeddown contributions to be included.
ThermalModelFit(ThermalModelBase *model)
Construct a new ThermalModelFit object.
double fError
Experimental error of the yield ratio.
double fValue
Experimental value of the yield ratio.
double GetDensity(long long PDGID, int feeddown)
Same as GetDensity(int,Feeddown::Type)
const std::string & Name() const
Particle&#39;s name.
Extended structure for calculating uncertainties in non-fit quantities resulting from uncertanties in...
const std::vector< ThermalParticle > & Particles() const
Returns the vector of all particle species.
double xmax
Lower and uppers bounds on parameter value.
std::string name
Name of the parameter.
int GetNdf() const
Number of degrees of freedom in the fit.
virtual void CalculateDensities()
Calculates the primordial and total (after decays) densities of all species.
void SetParameterFitFlag(const std::string &name, bool toFit)
Set whether the FitParameter with a given name should be fitted.
Structure holding information about parameters of a thermal fit.
std::vector< FitParameter * > ParameterList
Vector of pointer to all the parameters.
Structure for an arbitrary fit parameter.
bool toFit
Whether the parameter is fitted or fixed.
void PrintYieldsTable2(std::string filename="Yield.dat")
ThermalModelFit class.
FitParameter Tkin
Since version 1.3: Kinetic freeze-out temperature.
double ValueError() const
Error of the measurement.
void PrintYieldsLatexAll(std::string filename="Yield.dat", std::string name="A+A", bool asymm=false)
Strangeness-canonical ensemble.
static std::vector< FittedQuantity > loadExpDataFromFile(const std::string &filename)
Load the experimental data from a file.
bool calculationHadBECIssue
Whether > m Bose-Einstein condensation issue was encountered for a Bose gas.
static void saveExpDataToFile(const std::vector< FittedQuantity > &outQuantities, const std::string &filename)
ThermalModelFitParameters PerformFit(bool verbose=true, bool AsymmErrors=false)
The thermal fit procedure.
void PrintYieldsTable(std::string filename="Yield.dat")
const std::vector< FittedQuantity > & FittedQuantities() const
Return a vector of the fitted quantities (data)
void PrintParameters()
Print function.
const ThermalModelParameters & Parameters() const
Structure containing the experimental yield (multiplicity) to be fitted.
long long fPDGID2
PDG code of the particle yield in the denominator.
double error
Parameter error (symmetric)
The main namespace where all classes and functions of the Thermal-FIST library reside.
double Value() const
Value of the measurement.
Feeddown::Type fFeedDown1
The feeddown contributions to be included for the yield in the numerator.
Feeddown from all particles marked as unstable.
Definition: ParticleDecay.h:37
virtual bool IsConservedChargeCanonical(ConservedCharge::Name charge) const
Whether the given conserved charge is treated canonically.
double Volume() const
System volume (fm )
ThermalParticleSystem * TPS()
double errm
Asymmetric errors.
static std::vector< int > ComputePCEStabilityFlags(const ThermalParticleSystem *TPS, bool SahaEquationForNuclei=true, bool FreezeLongLived=false, double WidthCut=0.015)
Computes the PCE stability flags based on the provided particle list and a number of parameters...
ThermalParticle & ParticleByPDG(long long pdgid)
ThermalParticle object corresponding to particle species with a provided PDG ID.
std::pair< double, double > ModelDescriptionAccuracy() const
Returns a relative error of the data description (and its uncertainty estimate)