musrfit  1.9.2
PMsrHandler.cpp
Go to the documentation of this file.
1 /***************************************************************************
2 
3  PMsrHandler.cpp
4 
5  Author: Andreas Suter
6  e-mail: andreas.suter@psi.ch
7 
8 ***************************************************************************/
9 
10 /***************************************************************************
11  * Copyright (C) 2007-2023 by Andreas Suter *
12  * andreas.suter@psi.ch *
13  * *
14  * This program is free software; you can redistribute it and/or modify *
15  * it under the terms of the GNU General Public License as published by *
16  * the Free Software Foundation; either version 2 of the License, or *
17  * (at your option) any later version. *
18  * *
19  * This program is distributed in the hope that it will be useful, *
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22  * GNU General Public License for more details. *
23  * *
24  * You should have received a copy of the GNU General Public License *
25  * along with this program; if not, write to the *
26  * Free Software Foundation, Inc., *
27  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
28  ***************************************************************************/
29 
30 #include <math.h>
31 
32 #include <string>
33 #include <iostream>
34 #include <fstream>
35 
36 #include <TString.h>
37 #include <TObjArray.h>
38 #include <TObjString.h>
39 #include <TDatime.h>
40 
41 #include "PMusr.h"
42 #include "PMsrHandler.h"
43 
44 //--------------------------------------------------------------------------
45 // Constructor
46 //--------------------------------------------------------------------------
52 PMsrHandler::PMsrHandler(const Char_t *fileName, PStartupOptions *startupOptions, const Bool_t fourierOnly) :
53  fFourierOnly(fourierOnly), fStartupOptions(startupOptions), fFileName(fileName)
54 {
55  // init variables
56  fMsrBlockCounter = 0;
57 
58  fTitle = "";
59 
60  fCopyStatisticsBlock = false;
61  fStatistic.fValid = false;
62  fStatistic.fChisq = true;
63  fStatistic.fMin = -1.0;
64  fStatistic.fNdf = 0;
67  fStatistic.fNdfPerHisto.clear();
68 
69  // check if the file name given is a path-file-name, and if yes, split it into path and file name.
70  if (fFileName.Contains("/")) {
71  Int_t idx = -1;
72  while (fFileName.Index("/", idx+1) != -1) {
73  idx = fFileName.Index("/", idx+1);
74  }
76  fMsrFileDirectoryPath.Remove(idx+1);
77  } else {
78  fMsrFileDirectoryPath = "./";
79  }
80 }
81 
82 //--------------------------------------------------------------------------
83 // Destructor
84 //--------------------------------------------------------------------------
89 {
90  fParam.clear();
91  fTheory.clear();
92  fFunctions.clear();
93  fRuns.clear();
94  fCommands.clear();
95  fPlots.clear();
96  fStatistic.fStatLines.clear();
98  fStatistic.fNdfPerHisto.clear();
99  fParamInUse.clear();
100 }
101 
102 //--------------------------------------------------------------------------
103 // ReadMsrFile (public)
104 //--------------------------------------------------------------------------
113 {
114  std::ifstream f;
115  std::string str;
116  TString line;
117  Int_t line_no = 0;
118  Int_t result = PMUSR_SUCCESS;
119 
120  PMsrLineStructure current;
121 
122  PMsrLines fit_parameter;
123  PMsrLines theory;
124  PMsrLines functions;
125  PMsrLines global;
126  PMsrLines run;
127  PMsrLines commands;
128  PMsrLines fourier;
129  PMsrLines plot;
130  PMsrLines statistic;
131 
132  // init stuff
134 
135  // open msr-file
136  f.open(fFileName.Data(), std::iostream::in);
137  if (!f.is_open()) {
139  }
140 
141  fMsrBlockCounter = -1; // no msr block
142 
143  // read msr-file
144  while (!f.eof()) {
145 
146  // read a line
147  getline(f, str);
148  line = str.c_str();
149  line_no++;
150 
151  current.fLineNo = line_no;
152  current.fLine = line;
153 
154  if (line.BeginsWith("#") || line.IsWhitespace()) { // if the line is a comment/empty go to the next one
155  continue;
156  }
157 
158  // remove leading spaces
159  line.Remove(TString::kLeading, ' ');
160 
161  if (!line.IsWhitespace()) { // if not an empty line, handle it
162  // check for a msr block
163  if (line_no == 1) { // title
164  fTitle = line;
165  } else if (line.BeginsWith("FITPARAMETER")) { // FITPARAMETER block tag
167  } else if (line.BeginsWith("THEORY")) { // THEORY block tag
169  theory.push_back(current);
170  } else if (line.BeginsWith("FUNCTIONS")) { // FUNCTIONS block tag
172  functions.push_back(current);
173  } else if (line.BeginsWith("GLOBAL")) { // GLOBAL block tag
175  global.push_back(current);
176  } else if (line.BeginsWith("RUN")) { // RUN block tag
178  run.push_back(current);
179  } else if (line.BeginsWith("COMMANDS")) { // COMMANDS block tag
181  commands.push_back(current);
182  } else if (line.BeginsWith("FOURIER")) { // FOURIER block tag
184  fourier.push_back(current);
185  } else if (line.BeginsWith("PLOT")) { // PLOT block tag
187  plot.push_back(current);
188  } else if (line.BeginsWith("STATISTIC")) { // STATISTIC block tag
190  statistic.push_back(current);
191  } else { // the read line is some real stuff
192 
193  switch (fMsrBlockCounter) {
194  case MSR_TAG_FITPARAMETER: // FITPARAMETER block
195  fit_parameter.push_back(current);
196  break;
197  case MSR_TAG_THEORY: // THEORY block
198  theory.push_back(current);
199  break;
200  case MSR_TAG_FUNCTIONS: // FUNCTIONS block
201  functions.push_back(current);
202  break;
203  case MSR_TAG_GLOBAL: // GLOBAL block
204  global.push_back(current);
205  break;
206  case MSR_TAG_RUN: // RUN block
207  run.push_back(current);
208  break;
209  case MSR_TAG_COMMANDS: // COMMANDS block
210  commands.push_back(current);
211  break;
212  case MSR_TAG_FOURIER: // FOURIER block
213  fourier.push_back(current);
214  break;
215  case MSR_TAG_PLOT: // PLOT block
216  plot.push_back(current);
217  break;
218  case MSR_TAG_STATISTIC: // STATISTIC block
219  statistic.push_back(current);
220  break;
221  default:
222  break;
223  }
224  }
225  }
226  }
227 
228  // close msr-file
229  f.close();
230 
231  // execute handler of the various blocks
232  if (!HandleFitParameterEntry(fit_parameter))
233  result = PMUSR_MSR_SYNTAX_ERROR;
234  if (result == PMUSR_SUCCESS)
235  if (!HandleTheoryEntry(theory))
236  result = PMUSR_MSR_SYNTAX_ERROR;
237  if (result == PMUSR_SUCCESS)
238  if (!HandleFunctionsEntry(functions))
239  result = PMUSR_MSR_SYNTAX_ERROR;
240  if ((result == PMUSR_SUCCESS) && (global.size()>0))
241  if (!HandleGlobalEntry(global))
242  result = PMUSR_MSR_SYNTAX_ERROR;
243  if (result == PMUSR_SUCCESS)
244  if (!HandleRunEntry(run))
245  result = PMUSR_MSR_SYNTAX_ERROR;
246  if (result == PMUSR_SUCCESS)
247  if (!HandleCommandsEntry(commands))
248  result = PMUSR_MSR_SYNTAX_ERROR;
249  if (result == PMUSR_SUCCESS)
250  if (!HandleFourierEntry(fourier))
251  result = PMUSR_MSR_SYNTAX_ERROR;
252  if (result == PMUSR_SUCCESS)
253  if (!HandlePlotEntry(plot))
254  result = PMUSR_MSR_SYNTAX_ERROR;
255  if (result == PMUSR_SUCCESS)
256  if (!HandleStatisticEntry(statistic))
257  result = PMUSR_MSR_SYNTAX_ERROR;
258 
259  // check if chisq or max.log likelihood
260  fStatistic.fChisq = true;
261  for (UInt_t i=0; i<fCommands.size(); i++) {
262  if (fCommands[i].fLine.Contains("MAX_LIKELIHOOD"))
263  fStatistic.fChisq = false; // max.log likelihood
264  }
265 
266  // fill parameter-in-use vector
267  if ((result == PMUSR_SUCCESS) && !fFourierOnly)
268  FillParameterInUse(theory, functions, run);
269 
270  // check that each run fulfills the minimum requirements
271  if (result == PMUSR_SUCCESS)
272  if (!CheckRunBlockIntegrity())
273  result = PMUSR_MSR_SYNTAX_ERROR;
274 
275  // check that parameter names are unique
276  if ((result == PMUSR_SUCCESS) && !fFourierOnly) {
277  UInt_t parX, parY;
278  if (!CheckUniquenessOfParamNames(parX, parY)) {
279  std::cerr << std::endl << ">> PMsrHandler::ReadMsrFile: **SEVERE ERROR** parameter name " << fParam[parX].fName.Data() << " is identical for parameter no " << fParam[parX].fNo << " and " << fParam[parY].fNo << "!";
280  std::cerr << std::endl << ">> Needs to be fixed first!";
281  std::cerr << std::endl;
282  result = PMUSR_MSR_SYNTAX_ERROR;
283  }
284  }
285 
286  // check that if maps are present in the theory- and/or function-block,
287  // that there are really present in the run block
288  if ((result == PMUSR_SUCCESS) && !fFourierOnly)
289  if (!CheckMaps())
290  result = PMUSR_MSR_SYNTAX_ERROR;
291 
292 
293  // check that if functions are present in the theory- and/or run-block, that they
294  // are really present in the function block
295  if (result == PMUSR_SUCCESS)
296  if (!CheckFuncs())
297  result = PMUSR_MSR_SYNTAX_ERROR;
298 
299  // check that if histogram grouping is present that it makes any sense
300  if (result == PMUSR_SUCCESS)
301  if (!CheckHistoGrouping())
302  result = PMUSR_MSR_SYNTAX_ERROR;
303 
304  // check that if addrun is present that the given parameter make any sense
305  if (result == PMUSR_SUCCESS)
306  if (!CheckAddRunParameters())
307  result = PMUSR_MSR_SYNTAX_ERROR;
308 
309  // check that if RRF settings are present, the RUN block settings do correspond
310  if (result == PMUSR_SUCCESS)
311  if (!CheckRRFSettings())
312  result = PMUSR_MSR_SYNTAX_ERROR;
313 
314  if (result == PMUSR_SUCCESS) {
315  CheckMaxLikelihood(); // check if the user wants to use max likelihood with asymmetry/non-muSR fit (which is not implemented)
316  CheckLegacyLifetimecorrection(); // check if lifetimecorrection is found in RUN blocks, if yes transfer it to PLOT blocks
317  }
318 
319  // check if the given phases in the Fourier block are in agreement with the Plot block settings
320  if ((fFourier.fPhase.size() > 1) && (fPlots.size() > 0)) {
321  if (fFourier.fPhase.size() != fPlots[0].fRuns.size()) {
322  std::cerr << std::endl << ">> PMsrHandler::ReadMsrFile: **ERROR** if more than one phase is given in the Fourier block,";
323  std::cerr << std::endl << ">> it needs to correspond to the number of runs in the Plot block!" << std::endl;
324  result = PMUSR_MSR_SYNTAX_ERROR;
325  }
326  }
327 
328  // clean up
329  fit_parameter.clear();
330  theory.clear();
331  functions.clear();
332  global.clear();
333  run.clear();
334  commands.clear();
335  fourier.clear();
336  plot.clear();
337  statistic.clear();
338 
339  return result;
340 }
341 
342 //--------------------------------------------------------------------------
343 // WriteMsrLogFile (public)
344 //--------------------------------------------------------------------------
356 Int_t PMsrHandler::WriteMsrLogFile(const Bool_t messages)
357 {
358  const UInt_t prec = 6; // default output precision for float/doubles
359  UInt_t neededPrec = 0;
360  UInt_t neededWidth = 9;
361 
362  Int_t tag, lineNo = 0, number;
363  Int_t runNo = -1, addRunNo = 0;
364  Int_t plotNo = -1;
365  std::string line;
366  TString logFileName, str, sstr, *pstr;
367  TObjArray *tokens = nullptr;
368  TObjString *ostr = nullptr;
369  Bool_t found = false;
370  Bool_t statisticBlockFound = false;
371  Bool_t partialStatisticBlockFound = true;
372 
373  PBoolVector t0TagMissing; // needed for proper musrt0 handling
374  for (UInt_t i=0; i<fRuns.size(); i++) {
375  t0TagMissing.push_back(true);
376  }
377  std::vector<PBoolVector> addt0TagMissing; // needed for proper musrt0 handling
378  PBoolVector bvec;
379  for (UInt_t i=0; i<fRuns.size(); i++) {
380  bvec.clear();
381  for (UInt_t j=0; j<fRuns[i].GetAddT0BinEntries(); j++)
382  bvec.push_back(true);
383  addt0TagMissing.push_back(bvec);
384  }
385  PBoolVector backgroundTagMissing; // needed for proper musrt0 handling
386  for (UInt_t i=0; i<fRuns.size(); i++) {
387  backgroundTagMissing.push_back(true);
388  }
389  PBoolVector dataTagMissing; // needed for proper musrt0 handling
390  for (UInt_t i=0; i<fRuns.size(); i++) {
391  dataTagMissing.push_back(true);
392  }
393 
394  // add some counters needed in connection to addruns
395  Int_t addT0Counter = 0;
396  Int_t addT0GlobalCounter = 0;
397 
398  std::ifstream fin;
399  std::ofstream fout;
400 
401  // check msr-file for any missing tags first
402  // open msr-file for reading
403  fin.open(fFileName.Data(), std::iostream::in);
404  if (!fin.is_open()) {
406  }
407  while (!fin.eof()) {
408  // read a line
409  getline(fin, line);
410  str = line.c_str();
411 
412  if (str.BeginsWith("RUN")) {
413  runNo++;
414  continue;
415  }
416 
417  if (runNo == -1)
418  continue;
419 
420  if (str.BeginsWith("t0"))
421  t0TagMissing[runNo] = false;
422  else if (str.BeginsWith("background"))
423  backgroundTagMissing[runNo] = false;
424  else if (str.BeginsWith("data"))
425  dataTagMissing[runNo] = false;
426  }
427  fin.close();
428 
429  // construct log file name
430  // first find the last '.' in the filename
431  Int_t idx = -1;
432  while (fFileName.Index(".", idx+1) != -1) {
433  idx = fFileName.Index(".", idx+1);
434  }
435  if (idx == -1)
436  return PMUSR_MSR_SYNTAX_ERROR;
437 
438  // remove extension
439  logFileName = fFileName;
440  logFileName.Remove(idx+1);
441  logFileName += "mlog";
442 
443  // open msr-file for reading
444  fin.open(fFileName.Data(), std::iostream::in);
445  if (!fin.is_open()) {
447  }
448 
449  // open mlog-file for writing
450  fout.open(logFileName.Data(), std::iostream::out);
451  if (!fout.is_open()) {
453  }
454 
455  tag = MSR_TAG_TITLE;
456  lineNo = 0;
457  runNo = -1;
458  // read msr-file
459  while (!fin.eof()) {
460 
461  // read a line
462  getline(fin, line);
463  str = line.c_str();
464  lineNo++;
465 
466  // check for tag
467  if (str.BeginsWith("FITPARAMETER")) { // FITPARAMETER block tag
468  tag = MSR_TAG_FITPARAMETER;
469  } else if (str.BeginsWith("THEORY")) { // THEORY block tag
470  tag = MSR_TAG_THEORY;
471  fout << str.Data() << std::endl;
472  continue;
473  } else if (str.BeginsWith("FUNCTIONS")) { // FUNCTIONS block tag
474  tag = MSR_TAG_FUNCTIONS;
475  fout << str.Data() << std::endl;
476  continue;
477  } else if (str.BeginsWith("GLOBAL")) { // GLOBAL block tag
478  tag = MSR_TAG_GLOBAL;
479  fout << str.Data() << std::endl;
480  continue;
481  } else if (str.BeginsWith("RUN")) { // RUN block tag
482  tag = MSR_TAG_RUN;
483  runNo++;
484 
485  addT0Counter = 0; // reset counter
486  } else if (str.BeginsWith("COMMANDS")) { // COMMANDS block tag
487  tag = MSR_TAG_COMMANDS;
488  fout << str.Data() << std::endl;
489  continue;
490  } else if (str.BeginsWith("FOURIER")) { // FOURIER block tag
491  tag = MSR_TAG_FOURIER;
492  fout << str.Data() << std::endl;
493  continue;
494  } else if (str.BeginsWith("PLOT")) { // PLOT block tag
495  tag = MSR_TAG_PLOT;
496  plotNo++;
497  } else if (str.BeginsWith("STATISTIC")) { // STATISTIC block tag
498  tag = MSR_TAG_STATISTIC;
499  }
500 
501  // handle blocks
502  switch (tag) {
503  case MSR_TAG_TITLE:
504  if (lineNo == 1)
505  fout << fTitle.Data() << std::endl;
506  else
507  fout << str.Data() << std::endl;
508  break;
510  tokens = str.Tokenize(" \t");
511  if (tokens->GetEntries() == 0) { // not a parameter line
512  fout << str.Data() << std::endl;
513  } else {
514  ostr = dynamic_cast<TObjString*>(tokens->At(0));
515  sstr = ostr->GetString();
516  if (sstr.IsDigit()) { // parameter
517  number = sstr.Atoi();
518  number--;
519  // make sure number makes sense
520  assert ((number >= 0) && (number < (Int_t)fParam.size()));
521  // parameter no
522  fout.width(9);
523  fout << std::right << fParam[number].fNo;
524  fout << " ";
525  // parameter name
526  fout.width(11);
527  fout << std::left << fParam[number].fName.Data();
528  fout << " ";
529  // value of the parameter
530  if (fParam[number].fStep == 0.0) // if fixed parameter take all significant digits
531  neededPrec = LastSignificant(fParam[number].fValue);
532  else // step/neg.error given hence they will limited the output precission of the value
533  neededPrec = NeededPrecision(fParam[number].fStep)+1;
534  if ((fParam[number].fStep != 0.0) && fParam[number].fPosErrorPresent && (NeededPrecision(fParam[number].fPosError)+1 > neededPrec))
535  neededPrec = NeededPrecision(fParam[number].fPosError)+1;
536  if (neededPrec < 6)
537  neededWidth = 9;
538  else
539  neededWidth = neededPrec + 3;
540  fout.width(neededWidth);
541  fout.setf(std::ios::fixed, std::ios::floatfield);
542  fout.precision(neededPrec);
543  fout << std::left << fParam[number].fValue;
544  fout << " ";
545  // value of step/error/neg.error
546  fout.width(11);
547  fout.setf(std::ios::fixed);
548  if (fParam[number].fStep == 0.0)
549  neededPrec = 0;
550  fout.precision(neededPrec);
551  fout << std::left << fParam[number].fStep;
552  fout << " ";
553  fout.width(11);
554  fout.setf(std::ios::fixed);
555  fout.precision(neededPrec);
556  if ((fParam[number].fNoOfParams == 5) || (fParam[number].fNoOfParams == 7)) // pos. error given
557  if (fParam[number].fPosErrorPresent && (fParam[number].fStep != 0)) // pos error is a number
558  fout << std::left << fParam[number].fPosError;
559  else // pos error is a none
560  fout << std::left << "none";
561  else // no pos. error
562  fout << std::left << "none";
563  fout << " ";
564  fout.unsetf(std::ios::floatfield);
565  // boundaries
566  if (fParam[number].fNoOfParams > 5) {
567  fout.width(7);
568  fout.precision(prec);
569  if (fParam[number].fLowerBoundaryPresent)
570  fout << std::left << fParam[number].fLowerBoundary;
571  else
572  fout << std::left << "none";
573  fout << " ";
574  fout.width(7);
575  fout.precision(prec);
576  if (fParam[number].fUpperBoundaryPresent)
577  fout << std::left << fParam[number].fUpperBoundary;
578  else
579  fout << std::left << "none";
580  fout << " ";
581  }
582  fout << std::endl;
583  } else { // not a parameter, hence just copy it
584  fout << str.Data() << std::endl;
585  }
586  // clean up tokens
587  delete tokens;
588  }
589  break;
590  case MSR_TAG_THEORY:
591  found = false;
592  for (UInt_t i=0; i<fTheory.size(); i++) {
593  if (fTheory[i].fLineNo == lineNo) {
594  fout << fTheory[i].fLine.Data() << std::endl;
595  found = true;
596  }
597  }
598  if (!found) {
599  fout << str.Data() << std::endl;
600  }
601  break;
602  case MSR_TAG_FUNCTIONS:
603  sstr = str;
604  sstr.Remove(TString::kLeading, ' ');
605  if (str.BeginsWith("fun")) {
606  if (FilterNumber(sstr, "fun", 0, number)) {
607  idx = GetFuncIndex(number); // get index of the function number
608  sstr = fFuncHandler->GetFuncString(idx);
609  sstr.ToLower();
610  fout << sstr.Data() << std::endl;
611  }
612  } else {
613  fout << str.Data() << std::endl;
614  }
615  break;
616  case MSR_TAG_GLOBAL:
617  sstr = str;
618  if (sstr.BeginsWith("fittype")) {
619  fout.width(16);
620  switch (fGlobal.GetFitType()) {
622  fout << std::left << "fittype" << MSR_FITTYPE_SINGLE_HISTO << " (single histogram fit)" << std::endl;
623  break;
625  fout << std::left << "fittype" << MSR_FITTYPE_SINGLE_HISTO_RRF << " (single histogram RRF fit)" << std::endl;
626  break;
627  case MSR_FITTYPE_ASYM:
628  fout << std::left << "fittype" << MSR_FITTYPE_ASYM << " (asymmetry fit)" << std::endl ;
629  break;
631  fout << std::left << "fittype" << MSR_FITTYPE_ASYM_RRF << " (asymmetry RRF fit)" << std::endl ;
632  break;
634  fout << std::left << "fittype" << MSR_FITTYPE_MU_MINUS << " (mu minus fit)" << std::endl ;
635  break;
636  case MSR_FITTYPE_BNMR:
637  fout << std::left << "fittype" << MSR_FITTYPE_BNMR << " (beta-NMR fit)" << std::endl ;
638  break;
640  fout << std::left << "fittype" << MSR_FITTYPE_NON_MUSR << " (non muSR fit)" << std::endl ;
641  break;
642  default:
643  break;
644  }
645  } else if (sstr.BeginsWith("rrf_freq", TString::kIgnoreCase) && (fGlobal.GetFitType() == MSR_FITTYPE_SINGLE_HISTO_RRF)) {
646  fout.width(16);
647  fout << std::left << "rrf_freq ";
648  fout.width(8);
649  neededPrec = LastSignificant(fGlobal.GetRRFFreq(fGlobal.GetRRFUnit().Data()),10);
650  fout.precision(neededPrec);
651  fout << std::left << std::fixed << fGlobal.GetRRFFreq(fGlobal.GetRRFUnit().Data());
652  fout << " " << fGlobal.GetRRFUnit();
653  fout << std::endl;
654  } else if (sstr.BeginsWith("rrf_phase", TString::kIgnoreCase) && (fGlobal.GetFitType() == MSR_FITTYPE_SINGLE_HISTO_RRF)) {
655  fout.width(16);
656  fout << "rrf_phase ";
657  fout.width(8);
658  fout << std::left << fGlobal.GetRRFPhase();
659  fout << std::endl;
660  } else if (sstr.BeginsWith("rrf_packing", TString::kIgnoreCase) && (fGlobal.GetFitType() == MSR_FITTYPE_SINGLE_HISTO_RRF)) {
661  fout.width(16);
662  fout << "rrf_packing ";
663  fout.width(8);
664  fout << std::left << fGlobal.GetRRFPacking();
665  fout << std::endl;
666  } else if (sstr.BeginsWith("data")) {
667  fout.width(16);
668  fout << std::left << "data";
669  for (UInt_t j=0; j<4; j++) {
670  if (fGlobal.GetDataRange(j) > 0) {
671  fout.width(8);
672  fout << std::left << fGlobal.GetDataRange(j);
673  }
674  }
675  fout << std::endl;
676  } else if (sstr.BeginsWith("t0")) {
677  fout.width(16);
678  fout << std::left << "t0";
679  for (UInt_t j=0; j<fGlobal.GetT0BinSize(); j++) {
680  fout.width(8);
681  fout.precision(1);
682  fout.setf(std::ios::fixed,std::ios::floatfield);
683  fout << std::left << fGlobal.GetT0Bin(j);
684  }
685  fout << std::endl;
686  } else if (sstr.BeginsWith("addt0")) {
687  fout.width(16);
688  fout << std::left << "addt0";
689  for (Int_t j=0; j<fGlobal.GetAddT0BinSize(addT0GlobalCounter); j++) {
690  fout.width(8);
691  fout.precision(1);
692  fout.setf(std::ios::fixed,std::ios::floatfield);
693  fout << std::left << fGlobal.GetAddT0Bin(addT0GlobalCounter, j);
694  }
695  fout << std::endl;
696  addT0GlobalCounter++;
697  } else if (sstr.BeginsWith("fit")) {
698  fout.width(16);
699  fout << std::left << "fit";
700  if (fGlobal.IsFitRangeInBin()) { // fit range given in bins
701  fout << "fgb";
702  if (fGlobal.GetFitRangeOffset(0) > 0)
703  fout << "+" << fGlobal.GetFitRangeOffset(0);
704  fout << " lgb";
705  if (fGlobal.GetFitRangeOffset(1) > 0)
706  fout << "-" << fGlobal.GetFitRangeOffset(1);
707  neededPrec = LastSignificant(fGlobal.GetFitRange(0));
708  if (LastSignificant(fGlobal.GetFitRange(1)) > neededPrec)
709  neededPrec = LastSignificant(fGlobal.GetFitRange(1));
710  fout.precision(neededPrec);
711  fout << " # in time: " << fGlobal.GetFitRange(0) << ".." << fGlobal.GetFitRange(1) << " (usec)";
712  } else { // fit range given in time
713  for (UInt_t j=0; j<2; j++) {
714  if (fGlobal.GetFitRange(j) == -1)
715  break;
716  neededWidth = 7;
717  neededPrec = LastSignificant(fGlobal.GetFitRange(j));
718  fout.width(neededWidth);
719  fout.precision(neededPrec);
720  fout << std::left << std::fixed << fGlobal.GetFitRange(j);
721  if (j==0)
722  fout << " ";
723  }
724  }
725  fout << std::endl;
726  } else if (sstr.BeginsWith("packing")) {
727  fout.width(16);
728  fout << std::left << "packing";
729  fout << fGlobal.GetPacking() << std::endl;
730  } else {
731  fout << str.Data() << std::endl;
732  }
733  break;
734  case MSR_TAG_RUN:
735  sstr = str;
736  sstr.Remove(TString::kLeading, ' ');
737  if (sstr.BeginsWith("RUN")) {
738  addRunNo = 0; // reset counter
739  fout << "RUN " << fRuns[runNo].GetRunName()->Data() << " ";
740  pstr = fRuns[runNo].GetBeamline();
741  if (pstr == nullptr) {
742  std::cerr << std::endl << ">> PMsrHandler::WriteMsrLogFile: **ERROR** Couldn't obtain beamline data." << std::endl;
743  assert(0);
744  }
745  pstr->ToUpper();
746  fout << pstr->Data() << " ";
747  pstr = fRuns[runNo].GetInstitute();
748  if (pstr == nullptr) {
749  std::cerr << std::endl << ">> PMsrHandler::WriteMsrLogFile: **ERROR** Couldn't obtain institute data." << std::endl;
750  assert(0);
751  }
752  pstr->ToUpper();
753  fout << pstr->Data() << " ";
754  pstr = fRuns[runNo].GetFileFormat();
755  if (pstr == nullptr) {
756  std::cerr << std::endl << ">> PMsrHandler::WriteMsrLogFile: **ERROR** Couldn't obtain file format data." << std::endl;
757  assert(0);
758  }
759  pstr->ToUpper();
760  fout << pstr->Data() << " (name beamline institute data-file-format)" << std::endl;
761  } else if (sstr.BeginsWith("ADDRUN")) {
762  addRunNo++;
763  fout << "ADDRUN " << fRuns[runNo].GetRunName(addRunNo)->Data() << " ";
764  pstr = fRuns[runNo].GetBeamline(addRunNo);
765  if (pstr == nullptr) {
766  std::cerr << std::endl << ">> PMsrHandler::WriteMsrLogFile: **ERROR** Couldn't obtain beamline data (addrun)." << std::endl;
767  assert(0);
768  }
769  pstr->ToUpper();
770  fout << pstr->Data() << " ";
771  pstr = fRuns[runNo].GetInstitute(addRunNo);
772  if (pstr == nullptr) {
773  std::cerr << std::endl << ">> PMsrHandler::WriteMsrLogFile: **ERROR** Couldn't obtain institute data (addrun)." << std::endl;
774  assert(0);
775  }
776  pstr->ToUpper();
777  fout << pstr->Data() << " ";
778  pstr = fRuns[runNo].GetFileFormat(addRunNo);
779  if (pstr == nullptr) {
780  std::cerr << std::endl << ">> PMsrHandler::WriteMsrLogFile: **ERROR** Couldn't obtain file format data (addrun)." << std::endl;
781  assert(0);
782  }
783  pstr->ToUpper();
784  fout << pstr->Data() << " (name beamline institute data-file-format)" << std::endl;
785  } else if (sstr.BeginsWith("fittype")) {
786  fout.width(16);
787  switch (fRuns[runNo].GetFitType()) {
789  fout << std::left << "fittype" << MSR_FITTYPE_SINGLE_HISTO << " (single histogram fit)" << std::endl;
790  break;
792  fout << std::left << "fittype" << MSR_FITTYPE_SINGLE_HISTO_RRF << " (single histogram RRF fit)" << std::endl;
793  break;
794  case MSR_FITTYPE_ASYM:
795  fout << std::left << "fittype" << MSR_FITTYPE_ASYM << " (asymmetry fit)" << std::endl ;
796  break;
798  fout << std::left << "fittype" << MSR_FITTYPE_ASYM_RRF << " (asymmetry RRF fit)" << std::endl ;
799  break;
801  fout << std::left << "fittype" << MSR_FITTYPE_MU_MINUS << " (mu minus fit)" << std::endl ;
802  break;
803  case MSR_FITTYPE_BNMR:
804  fout << std::left << "fittype" << MSR_FITTYPE_BNMR << " (beta-NMR fit)" << std::endl ;
805  break;
807  fout << std::left << "fittype" << MSR_FITTYPE_NON_MUSR << " (non muSR fit)" << std::endl ;
808  break;
809  default:
810  break;
811  }
812  } else if (sstr.BeginsWith("alpha ")) {
813  fout.width(16);
814  fout << std::left << "alpha";
815  // check of alpha is given as a function
816  if (fRuns[runNo].GetAlphaParamNo() >= MSR_PARAM_FUN_OFFSET)
817  fout << "fun" << fRuns[runNo].GetAlphaParamNo()-MSR_PARAM_FUN_OFFSET;
818  else
819  fout << fRuns[runNo].GetAlphaParamNo();
820  fout << std::endl;
821  } else if (sstr.BeginsWith("beta ")) {
822  fout.width(16);
823  fout << std::left << "beta";
824  if (fRuns[runNo].GetBetaParamNo() >= MSR_PARAM_FUN_OFFSET)
825  fout << "fun" << fRuns[runNo].GetBetaParamNo()-MSR_PARAM_FUN_OFFSET;
826  else
827  fout << fRuns[runNo].GetBetaParamNo();
828  fout << std::endl;
829  } else if (sstr.BeginsWith("norm")) {
830  fout.width(16);
831  fout << std::left << "norm";
832  // check if norm is given as a function
833  if (fRuns[runNo].GetNormParamNo() >= MSR_PARAM_FUN_OFFSET)
834  fout << "fun" << fRuns[runNo].GetNormParamNo()-MSR_PARAM_FUN_OFFSET;
835  else
836  fout << fRuns[runNo].GetNormParamNo();
837  fout << std::endl;
838  } else if (sstr.BeginsWith("backgr.fit")) {
839  fout.width(16);
840  fout << std::left << "backgr.fit";
841  fout << fRuns[runNo].GetBkgFitParamNo() << std::endl;
842  } else if (sstr.BeginsWith("lifetime ")) {
843  fout.width(16);
844  fout << std::left << "lifetime";
845  fout << fRuns[runNo].GetLifetimeParamNo() << std::endl;
846  } else if (sstr.BeginsWith("lifetimecorrection")) {
847  // obsolate, hence do nothing here
848  } else if (sstr.BeginsWith("map")) {
849  fout << "map ";
850  for (UInt_t j=0; j<fRuns[runNo].GetMap()->size(); j++) {
851  fout.width(5);
852  fout << std::right << fRuns[runNo].GetMap(j);
853  }
854  // if there are less maps then 10 fill with zeros
855  if (fRuns[runNo].GetMap()->size() < 10) {
856  for (UInt_t j=fRuns[runNo].GetMap()->size(); j<10; j++)
857  fout << " 0";
858  }
859  fout << std::endl;
860  } else if (sstr.BeginsWith("forward")) {
861  if (fRuns[runNo].GetForwardHistoNoSize() == 0) {
862  std::cerr << std::endl << ">> PMsrHandler::WriteMsrLogFile: **WARNING** 'forward' tag without any data found!";
863  std::cerr << std::endl << ">> Something is VERY fishy, please check your msr-file carfully." << std::endl;
864  } else {
865  TString result("");
866  PIntVector forward;
867  for (UInt_t i=0; i<fRuns[runNo].GetForwardHistoNoSize(); i++)
868  forward.push_back(fRuns[runNo].GetForwardHistoNo(i));
869  MakeDetectorGroupingString("forward", forward, result);
870  forward.clear();
871  fout << result.Data() << std::endl;
872  }
873  } else if (sstr.BeginsWith("backward")) {
874  if (fRuns[runNo].GetBackwardHistoNoSize() == 0) {
875  std::cerr << std::endl << ">> PMsrHandler::WriteMsrLogFile: **WARNING** 'backward' tag without any data found!";
876  std::cerr << std::endl << ">> Something is VERY fishy, please check your msr-file carfully." << std::endl;
877  } else {
878  TString result("");
879  PIntVector backward;
880  for (UInt_t i=0; i<fRuns[runNo].GetBackwardHistoNoSize(); i++)
881  backward.push_back(fRuns[runNo].GetBackwardHistoNo(i));
882  MakeDetectorGroupingString("backward", backward, result);
883  backward.clear();
884  fout << result.Data() << std::endl;
885  }
886  } else if (sstr.BeginsWith("backgr.fix")) {
887  fout.width(16);
888  fout << std::left << "backgr.fix";
889  for (UInt_t j=0; j<2; j++) {
890  if (fRuns[runNo].GetBkgFix(j) != PMUSR_UNDEFINED) {
891  fout.precision(prec);
892  fout.width(12);
893  fout << std::left << fRuns[runNo].GetBkgFix(j);
894  }
895  }
896  fout << std::endl;
897  } else if (sstr.BeginsWith("background")) {
898  backgroundTagMissing[runNo] = false;
899  fout.width(16);
900  fout << std::left << "background";
901  for (UInt_t j=0; j<4; j++) {
902  if (fRuns[runNo].GetBkgRange(j) > 0) {
903  fout.width(8);
904  fout << std::left << fRuns[runNo].GetBkgRange(j);
905  }
906  }
907  if (fRuns[runNo].GetBkgEstimated(0) != PMUSR_UNDEFINED) {
908  Int_t precision=4;
909  if ((Int_t)log10(fRuns[runNo].GetBkgEstimated(0))+1 >= 4)
910  precision = 2;
911  fout << " # estimated bkg: ";
912  fout << std::fixed;
913  fout.precision(precision);
914  fout << fRuns[runNo].GetBkgEstimated(0);
915  if (fRuns[runNo].GetBkgEstimated(1) != PMUSR_UNDEFINED) {
916  fout << " / ";
917  fout << std::fixed;
918  fout.precision(precision);
919  fout << fRuns[runNo].GetBkgEstimated(1);
920  }
921  }
922  fout << std::endl;
923  } else if (sstr.BeginsWith("data")) {
924  dataTagMissing[runNo] = false;
925  fout.width(16);
926  fout << std::left << "data";
927  for (UInt_t j=0; j<4; j++) {
928  if (fRuns[runNo].GetDataRange(j) > 0) {
929  fout.width(8);
930  fout << std::left << fRuns[runNo].GetDataRange(j);
931  }
932  }
933  fout << std::endl;
934  } else if (sstr.BeginsWith("t0")) {
935  t0TagMissing[runNo] = false;
936  fout.width(16);
937  fout << std::left << "t0";
938  for (UInt_t j=0; j<fRuns[runNo].GetT0BinSize(); j++) {
939  fout.width(8);
940  fout.precision(1);
941  fout.setf(std::ios::fixed,std::ios::floatfield);
942  fout << std::left << fRuns[runNo].GetT0Bin(j);
943  }
944  fout << std::endl;
945  } else if (sstr.BeginsWith("addt0")) {
946  addt0TagMissing[runNo][addT0Counter] = false;
947  if (fRuns[runNo].GetAddT0BinSize(addT0Counter) <=0) {
948  std::cerr << std::endl << ">> PMsrHandler::WriteMsrLogFile: **WARNING** 'addt0' tag without any data found!";
949  std::cerr << std::endl << ">> Something is VERY fishy, please check your msr-file carfully." << std::endl;
950  } else {
951  fout.width(16);
952  fout << std::left << "addt0";
953  for (Int_t j=0; j<fRuns[runNo].GetAddT0BinSize(addT0Counter); j++) {
954  fout.width(8);
955  fout.precision(1);
956  fout.setf(std::ios::fixed,std::ios::floatfield);
957  fout << std::left << fRuns[runNo].GetAddT0Bin(addT0Counter, j);
958  }
959  fout << std::endl;
960  addT0Counter++;
961  }
962  } else if (sstr.BeginsWith("xy-data")) {
963  if (fRuns[runNo].GetXDataIndex() != -1) { // indices
964  fout.width(16);
965  fout << std::left << "xy-data";
966  fout.width(8);
967  fout.precision(2);
968  fout << std::left << std::fixed << fRuns[runNo].GetXDataIndex();
969  fout.width(8);
970  fout.precision(2);
971  fout << std::left << std::fixed << fRuns[runNo].GetYDataIndex();
972  fout << std::endl;
973  } else if (!fRuns[runNo].GetXDataLabel()->IsWhitespace()) { // labels
974  fout.width(16);
975  fout << std::left << "xy-data";
976  fout.width(8);
977  fout << std::left << std::fixed << fRuns[runNo].GetXDataLabel()->Data();
978  fout << " ";
979  fout.width(8);
980  fout << std::left << std::fixed << fRuns[runNo].GetYDataLabel()->Data();
981  fout << std::endl;
982  }
983  } else if (sstr.BeginsWith("fit")) {
984  // check if missing t0/addt0/background/data tag are present eventhough the values are present, if so write these data values
985  // if ISIS data, do not do anything
986  if (t0TagMissing[runNo] && fRuns[runNo].GetInstitute()->CompareTo("isis", TString::kIgnoreCase)) {
987  if (fRuns[runNo].GetT0BinSize() > 0) {
988  fout.width(16);
989  fout << std::left << "t0";
990  for (UInt_t j=0; j<fRuns[runNo].GetT0BinSize(); j++) {
991  fout.width(8);
992  fout.precision(1);
993  fout.setf(std::ios::fixed,std::ios::floatfield);
994  fout << std::left << fRuns[runNo].GetT0Bin(j);
995  }
996  fout << std::endl;
997  }
998  }
999  for (UInt_t i=0; i<fRuns[runNo].GetAddT0BinEntries(); i++) {
1000  if (addt0TagMissing[runNo][i] && fRuns[runNo].GetInstitute()->CompareTo("isis", TString::kIgnoreCase)) {
1001  if (fRuns[runNo].GetAddT0BinSize(i) > 0) {
1002  fout.width(16);
1003  fout << std::left << "addt0";
1004  for (Int_t j=0; j<fRuns[runNo].GetAddT0BinSize(i); j++) {
1005  fout.width(8);
1006  fout.precision(1);
1007  fout.setf(std::ios::fixed,std::ios::floatfield);
1008  fout << std::left << fRuns[runNo].GetAddT0Bin(i, j);
1009  }
1010  fout << std::endl;
1011  }
1012  }
1013  }
1014  if (backgroundTagMissing[runNo]) {
1015  if (fRuns[runNo].GetBkgRange(0) >= 0) {
1016  fout.width(16);
1017  fout << std::left << "background";
1018  for (UInt_t j=0; j<4; j++) {
1019  if (fRuns[runNo].GetBkgRange(j) > 0) {
1020  fout.width(8);
1021  fout << std::left << fRuns[runNo].GetBkgRange(j);
1022  }
1023  }
1024  fout << std::endl;
1025  }
1026  }
1027  if (dataTagMissing[runNo]) {
1028  if (fRuns[runNo].GetDataRange(0) >= 0) {
1029  fout.width(16);
1030  fout << std::left << "data";
1031  for (UInt_t j=0; j<4; j++) {
1032  if (fRuns[runNo].GetDataRange(j) > 0) {
1033  fout.width(8);
1034  fout << std::left << fRuns[runNo].GetDataRange(j);
1035  }
1036  }
1037  fout << std::endl;
1038  }
1039  }
1040  // write fit range line
1041  fout.width(16);
1042  fout << std::left << "fit";
1043  if (fRuns[runNo].IsFitRangeInBin()) { // fit range given in bins
1044  fout << "fgb";
1045  if (fRuns[runNo].GetFitRangeOffset(0) > 0)
1046  fout << "+" << fRuns[runNo].GetFitRangeOffset(0);
1047  fout << " lgb";
1048  if (fRuns[runNo].GetFitRangeOffset(1) > 0)
1049  fout << "-" << fRuns[runNo].GetFitRangeOffset(1);
1050  neededPrec = LastSignificant(fRuns[runNo].GetFitRange(0));
1051  if (LastSignificant(fRuns[runNo].GetFitRange(1)) > neededPrec)
1052  neededPrec = LastSignificant(fRuns[runNo].GetFitRange(1));
1053  fout.precision(neededPrec);
1054  fout << " # in time: " << fRuns[runNo].GetFitRange(0) << ".." << fRuns[runNo].GetFitRange(1) << " (usec)";
1055  } else { // fit range given in time
1056  for (UInt_t j=0; j<2; j++) {
1057  if (fRuns[runNo].GetFitRange(j) == -1)
1058  break;
1059  neededWidth = 7;
1060  neededPrec = LastSignificant(fRuns[runNo].GetFitRange(j));
1061  fout.width(neededWidth);
1062  fout.precision(neededPrec);
1063  fout << std::left << std::fixed << fRuns[runNo].GetFitRange(j);
1064  if (j==0)
1065  fout << " ";
1066  }
1067  }
1068  fout << std::endl;
1069  } else if (sstr.BeginsWith("packing")) {
1070  fout.width(16);
1071  fout << std::left << "packing";
1072  fout << fRuns[runNo].GetPacking() << std::endl;
1073  } else {
1074  fout << str.Data() << std::endl;
1075  }
1076  break;
1077  case MSR_TAG_COMMANDS:
1078  fout << str.Data() << std::endl;
1079  break;
1080  case MSR_TAG_FOURIER:
1081  sstr = str;
1082  sstr.Remove(TString::kLeading, ' ');
1083  if (sstr.BeginsWith("units")) {
1084  fout << "units ";
1086  fout << "Gauss";
1087  } else if (fFourier.fUnits == FOURIER_UNIT_TESLA) {
1088  fout << "Tesla";
1089  } else if (fFourier.fUnits == FOURIER_UNIT_FREQ) {
1090  fout << "MHz ";
1091  } else if (fFourier.fUnits == FOURIER_UNIT_CYCLES) {
1092  fout << "Mc/s";
1093  }
1094  fout << " # units either 'Gauss', 'Tesla', 'MHz', or 'Mc/s'";
1095  fout << std::endl;
1096  } else if (sstr.BeginsWith("fourier_power")) {
1097  fout << "fourier_power " << fFourier.fFourierPower << std::endl;
1098  } else if (sstr.BeginsWith("dc-corrected")) {
1099  fout << "dc-corrected ";
1100  if (fFourier.fDCCorrected == true)
1101  fout << "true" << std::endl;
1102  else
1103  fout << "false" << std::endl;
1104  } else if (sstr.BeginsWith("apodization")) {
1105  fout << "apodization ";
1107  fout << "NONE ";
1108  } else if (fFourier.fApodization == FOURIER_APOD_WEAK) {
1109  fout << "WEAK ";
1110  } else if (fFourier.fApodization == FOURIER_APOD_MEDIUM) {
1111  fout << "MEDIUM";
1112  } else if (fFourier.fApodization == FOURIER_APOD_STRONG) {
1113  fout << "STRONG";
1114  }
1115  fout << " # NONE, WEAK, MEDIUM, STRONG";
1116  fout << std::endl;
1117  } else if (sstr.BeginsWith("plot")) {
1118  fout << "plot ";
1120  fout << "REAL ";
1121  } else if (fFourier.fPlotTag == FOURIER_PLOT_IMAG) {
1122  fout << "IMAG ";
1124  fout << "REAL_AND_IMAG";
1125  } else if (fFourier.fPlotTag == FOURIER_PLOT_POWER) {
1126  fout << "POWER";
1127  } else if (fFourier.fPlotTag == FOURIER_PLOT_PHASE) {
1128  fout << "PHASE";
1130  fout << "PHASE_OPT_REAL";
1131  }
1132  fout << " # REAL, IMAG, REAL_AND_IMAG, POWER, PHASE, PHASE_OPT_REAL";
1133  fout << std::endl;
1134  } else if (sstr.BeginsWith("phase")) {
1135  if (fFourier.fPhaseParamNo.size() > 0) {
1136  TString phaseParamStr = BeautifyFourierPhaseParameterString();
1137  fout << "phase " << phaseParamStr << std::endl;
1138  } else if (fFourier.fPhase.size() > 0) {
1139  fout << "phase ";
1140  for (UInt_t i=0; i<fFourier.fPhase.size()-1; i++) {
1141  fout << fFourier.fPhase[i] << ", ";
1142  }
1143  fout << fFourier.fPhase[fFourier.fPhase.size()-1] << std::endl;
1144  }
1145  } else if (sstr.BeginsWith("range_for_phase_correction")) {
1146  fout << "range_for_phase_correction " << fFourier.fRangeForPhaseCorrection[0] << " " << fFourier.fRangeForPhaseCorrection[1] << std::endl;
1147  } else if (sstr.BeginsWith("range ")) {
1148  fout.setf(std::ios::fixed,std::ios::floatfield);
1149  neededPrec = LastSignificant(fFourier.fPlotRange[0]);
1150  if (LastSignificant(fFourier.fPlotRange[1]) > neededPrec)
1151  neededPrec = LastSignificant(fFourier.fPlotRange[1]);
1152  fout.precision(neededPrec);
1153  fout << "range " << fFourier.fPlotRange[0] << " " << fFourier.fPlotRange[1] << std::endl;
1154  } else {
1155  fout << str.Data() << std::endl;
1156  }
1157  break;
1158  case MSR_TAG_PLOT:
1159  sstr = str;
1160  sstr.Remove(TString::kLeading, ' ');
1161  if (sstr.BeginsWith("PLOT")) {
1162  switch (fPlots[plotNo].fPlotType) {
1163  case MSR_PLOT_SINGLE_HISTO:
1164  fout << "PLOT " << fPlots[plotNo].fPlotType << " (single histo plot)" << std::endl;
1165  break;
1167  fout << "PLOT " << fPlots[plotNo].fPlotType << " (single histo RRF plot)" << std::endl;
1168  break;
1169  case MSR_PLOT_ASYM:
1170  fout << "PLOT " << fPlots[plotNo].fPlotType << " (asymmetry plot)" << std::endl;
1171  break;
1172  case MSR_PLOT_ASYM_RRF:
1173  fout << "PLOT " << fPlots[plotNo].fPlotType << " (asymmetry RRF plot)" << std::endl;
1174  break;
1175  case MSR_PLOT_MU_MINUS:
1176  fout << "PLOT " << fPlots[plotNo].fPlotType << " (mu minus plot)" << std::endl;
1177  break;
1178  case MSR_PLOT_BNMR:
1179  fout << "PLOT " << fPlots[plotNo].fPlotType << " (beta-NMR asymmetry plot)" << std::endl;
1180  break;
1181  case MSR_PLOT_NON_MUSR:
1182  fout << "PLOT " << fPlots[plotNo].fPlotType << " (non muSR plot)" << std::endl;
1183  break;
1184  default:
1185  break;
1186  }
1187  if (fPlots[plotNo].fLifeTimeCorrection) {
1188  fout << "lifetimecorrection" << std::endl;
1189  }
1190  } else if (sstr.BeginsWith("lifetimecorrection")) {
1191  // do nothing, since it is already handled in the lines above.
1192  // The reason why this handled that oddly is due to legacy issues
1193  // of this flag, i.e. transfer from RUN -> PLOT
1194  } else if (sstr.BeginsWith("runs")) {
1195  fout << "runs ";
1196  fout.precision(0);
1197  for (UInt_t j=0; j<fPlots[plotNo].fRuns.size(); j++) {
1198  fout.width(4);
1199  fout << fPlots[plotNo].fRuns[j];
1200  }
1201  fout << std::endl;
1202  } else if (sstr.BeginsWith("range")) {
1203  fout << "range ";
1204  neededPrec = LastSignificant(fPlots[plotNo].fTmin[0]);
1205  fout.precision(neededPrec);
1206  fout << fPlots[plotNo].fTmin[0];
1207  fout << " ";
1208  neededPrec = LastSignificant(fPlots[plotNo].fTmax[0]);
1209  fout.precision(neededPrec);
1210  fout << fPlots[plotNo].fTmax[0];
1211  if (fPlots[plotNo].fYmin.size() > 0) {
1212  fout << " ";
1213  neededPrec = LastSignificant(fPlots[plotNo].fYmin[0]);
1214  fout.precision(neededPrec);
1215  fout << fPlots[plotNo].fYmin[0] << " ";
1216  neededPrec = LastSignificant(fPlots[plotNo].fYmax[0]);
1217  fout.precision(neededPrec);
1218  fout << fPlots[plotNo].fYmax[0];
1219  }
1220  fout << std::endl;
1221  } else {
1222  fout << str.Data() << std::endl;
1223  }
1224  break;
1225  case MSR_TAG_STATISTIC:
1226  statisticBlockFound = true;
1227  sstr = str;
1228  sstr.Remove(TString::kLeading, ' ');
1229  if (sstr.BeginsWith("STATISTIC")) {
1230  TDatime dt;
1231  fout << "STATISTIC --- " << dt.AsSQLString() << std::endl;
1232  } else if (sstr.BeginsWith("chisq") || sstr.BeginsWith("maxLH")) {
1233  partialStatisticBlockFound = false;
1234  if (fStatistic.fValid) { // valid fit result
1235  if (fStatistic.fChisq) {
1236  str.Form(" chisq = %.1lf, NDF = %d, chisq/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
1237  } else {
1238  str.Form(" maxLH = %.1lf, NDF = %d, maxLH/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
1239  }
1240  fout << str.Data() << std::endl;
1241  if (messages)
1242  std::cout << std::endl << str.Data() << std::endl;
1243 
1244  // check if expected chisq needs to be written
1245  if (fStatistic.fMinExpected != 0.0) {
1246  if (fStatistic.fChisq) {
1247  str.Form(" expected chisq = %.1lf, NDF = %d, expected chisq/NDF = %lf",
1249  } else {
1250  str.Form(" expected maxLH = %.1lf, NDF = %d, expected maxLH/NDF = %lf",
1252  }
1253  if (fStartupOptions) {
1255  fout << str.Data() << std::endl;
1256  }
1257  if (messages)
1258  std::cout << std::endl << str.Data() << std::endl;
1259 
1260  for (UInt_t i=0; i<fStatistic.fMinExpectedPerHisto.size(); i++) {
1261  if (fStatistic.fNdfPerHisto[i] > 0) {
1262  if (fStatistic.fChisq) {
1263  str.Form(" run block %d: (NDF/red.chisq/red.chisq_e) = (%d/%lf/%lf)",
1265  } else {
1266  str.Form(" run block %d: (NDF/red.maxLH/red.maxLH_e) = (%d/%lf/%lf)",
1268  }
1269  if (fStartupOptions) {
1271  fout << str.Data() << std::endl;
1272  }
1273 
1274  if (messages)
1275  std::cout << str.Data() << std::endl;
1276  }
1277  }
1278  } else if (fStatistic.fNdfPerHisto.size() > 1) { // check if per run chisq needs to be written
1279  for (UInt_t i=0; i<fStatistic.fNdfPerHisto.size(); i++) {
1280  if (fStatistic.fChisq) {
1281  str.Form(" run block %d: (NDF/red.chisq) = (%d/%lf)",
1283  } else {
1284  str.Form(" run block %d: (NDF/maxLH.chisq) = (%d/%lf)",
1286  }
1287  if (fStartupOptions) {
1289  fout << str.Data() << std::endl;
1290  }
1291 
1292  if (messages)
1293  std::cout << str.Data() << std::endl;
1294  }
1295  }
1296  } else {
1297  fout << "*** FIT DID NOT CONVERGE ***" << std::endl;
1298  if (messages)
1299  std::cout << std::endl << "*** FIT DID NOT CONVERGE ***" << std::endl;
1300  }
1301  } else if (sstr.BeginsWith("*** FIT DID NOT CONVERGE ***")) {
1302  partialStatisticBlockFound = false;
1303  if (fStatistic.fValid) { // valid fit result
1304  if (fStatistic.fChisq) { // chisq
1305  str.Form(" chisq = %.1lf, NDF = %d, chisq/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
1306  } else {
1307  str.Form(" maxLH = %.1lf, NDF = %d, maxLH/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
1308  }
1309  fout << str.Data() << std::endl;
1310  if (messages)
1311  std::cout << std::endl << str.Data() << std::endl;
1312 
1313  // check if expected chisq needs to be written
1314  if (fStatistic.fMinExpected != 0.0) {
1315  if (fStatistic.fChisq) { // chisq
1316  str.Form(" expected chisq = %.1lf, NDF = %d, expected chisq/NDF = %lf",
1318  } else {
1319  str.Form(" expected maxLH = %.1lf, NDF = %d, expected maxLH/NDF = %lf",
1321  }
1322  if (fStartupOptions) {
1324  fout << str.Data() << std::endl;
1325  }
1326  if (messages)
1327  std::cout << str.Data() << std::endl;
1328 
1329  for (UInt_t i=0; i<fStatistic.fMinExpectedPerHisto.size(); i++) {
1330  if (fStatistic.fNdfPerHisto[i] > 0) {
1331  if (fStatistic.fChisq) { // chisq
1332  str.Form(" run block %d: (NDF/red.chisq/red.chisq_e) = (%d/%lf/%lf)",
1334  } else {
1335  str.Form(" run block %d: (NDF/red.maxLH/red.maxLH_e) = (%d/%lf/%lf)",
1337  }
1338  if (fStartupOptions) {
1340  fout << str.Data() << std::endl;
1341  }
1342 
1343  if (messages)
1344  std::cout << str.Data() << std::endl;
1345  }
1346  }
1347  } else if (fStatistic.fNdfPerHisto.size() > 1) { // check if per run chisq needs to be written
1348  for (UInt_t i=0; i<fStatistic.fNdfPerHisto.size(); i++) {
1349  if (fStatistic.fChisq) { // chisq
1350  str.Form(" run block %d: (NDF/red.chisq) = (%d/%lf)",
1352  } else {
1353  str.Form(" run block %d: (NDF/red.maxLH) = (%d/%lf)",
1355  }
1356  if (fStartupOptions) {
1358  fout << str.Data() << std::endl;
1359  }
1360 
1361  if (messages)
1362  std::cout << str.Data() << std::endl;
1363  }
1364  }
1365  } else {
1366  fout << "*** FIT DID NOT CONVERGE ***" << std::endl;
1367  if (messages)
1368  std::cout << std::endl << "*** FIT DID NOT CONVERGE ***" << std::endl;
1369  }
1370  } else {
1371  if (str.Length() > 0) {
1372  sstr = str;
1373  sstr.Remove(TString::kLeading, ' ');
1374  if (!sstr.BeginsWith("expected chisq") && !sstr.BeginsWith("expected maxLH") && !sstr.BeginsWith("run block"))
1375  fout << str.Data() << std::endl;
1376  } else { // only write endl if not eof is reached. This is preventing growing msr-files, i.e. more and more empty lines at the end of the file
1377  if (!fin.eof())
1378  fout << std::endl;
1379  }
1380  }
1381  break;
1382  default:
1383  break;
1384  }
1385  }
1386 
1387  // there was no statistic block present in the msr-input-file
1388  if (!statisticBlockFound) {
1389  partialStatisticBlockFound = false;
1390  std::cerr << std::endl << ">> PMsrHandler::WriteMsrLogFile: **WARNING** no STATISTIC block present, will write a default one" << std::endl;
1391  fout << "###############################################################" << std::endl;
1392  TDatime dt;
1393  fout << "STATISTIC --- " << dt.AsSQLString() << std::endl;
1394  if (fStatistic.fValid) { // valid fit result
1395  if (fStatistic.fChisq) {
1396  str.Form(" chisq = %.1lf, NDF = %d, chisq/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
1397  } else {
1398  str.Form(" maxLH = %.1lf, NDF = %d, maxLH/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
1399  }
1400  fout << str.Data() << std::endl;
1401  if (messages)
1402  std::cout << std::endl << str.Data() << std::endl;
1403 
1404  // check if expected chisq needs to be written
1405  if (fStatistic.fMinExpected != 0.0) {
1406  if (fStatistic.fChisq) {
1407  str.Form(" expected chisq = %.1lf, NDF = %d, expected chisq/NDF = %lf",
1409  } else {
1410  str.Form(" expected maxLH = %.1lf, NDF = %d, expected maxLH/NDF = %lf",
1412  }
1413  if (fStartupOptions) {
1415  fout << str.Data() << std::endl;
1416  }
1417  if (messages)
1418  std::cout << str.Data() << std::endl;
1419 
1420  for (UInt_t i=0; i<fStatistic.fMinExpectedPerHisto.size(); i++) {
1421  if (fStatistic.fNdfPerHisto[i] > 0) {
1422  if (fStatistic.fChisq) {
1423  str.Form(" run block %d: (NDF/red.chisq/red.chisq_e) = (%d/%lf/%lf)",
1425  } else {
1426  str.Form(" run block %d: (NDF/red.maxLH/red.maxLH_e) = (%d/%lf/%lf)",
1428  }
1429  if (fStartupOptions) {
1431  fout << str.Data() << std::endl;
1432  }
1433 
1434  if (messages)
1435  std::cout << str.Data() << std::endl;
1436  }
1437  }
1438  } else if (fStatistic.fNdfPerHisto.size() > 1) { // check if per run chisq needs to be written
1439  for (UInt_t i=0; i<fStatistic.fNdfPerHisto.size(); i++) {
1440  if (fStatistic.fChisq) {
1441  str.Form(" run block %d: (NDF/red.chisq) = (%d/%lf)",
1443  } else {
1444  str.Form(" run block %d: (NDF/red.maxLH) = (%d/%lf)",
1446  }
1447  if (fStartupOptions) {
1449  fout << str.Data() << std::endl;
1450  }
1451 
1452  if (messages)
1453  std::cout << str.Data() << std::endl;
1454  }
1455  }
1456  } else {
1457  fout << "*** FIT DID NOT CONVERGE ***" << std::endl;
1458  if (messages)
1459  std::cout << std::endl << "*** FIT DID NOT CONVERGE ***" << std::endl;
1460  }
1461  }
1462 
1463  // there was only a partial statistic block present in the msr-input-file
1464  if (partialStatisticBlockFound) {
1465  std::cerr << std::endl << ">> PMsrHandler::WriteMsrLogFile: **WARNING** garbage STATISTIC block present in the msr-input file.";
1466  std::cerr << std::endl << ">> ** WILL ADD SOME SENSIBLE STUFF, BUT YOU HAVE TO CHECK IT SINCE I AM **NOT** REMOVING THE GARBAGE! **" << std::endl;
1467  TDatime dt;
1468  fout << "STATISTIC --- " << dt.AsSQLString() << std::endl;
1469  if (fStatistic.fValid) { // valid fit result
1470  if (fStatistic.fChisq) { // chisq
1471  str.Form(" chisq = %.1lf, NDF = %d, chisq/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
1472  } else {
1473  str.Form(" maxLH = %.1lf, NDF = %d, maxLH/NDF = %lf", fStatistic.fMin, fStatistic.fNdf, fStatistic.fMin / fStatistic.fNdf);
1474  }
1475  fout << str.Data() << std::endl;
1476  if (messages)
1477  std::cout << std::endl << str.Data() << std::endl;
1478 
1479  // check if expected chisq needs to be written
1480  if (fStatistic.fMinExpected != 0.0) {
1481  if (fStatistic.fChisq) { // chisq
1482  str.Form(" expected chisq = %.1lf, NDF = %d, expected chisq/NDF = %lf",
1484  } else {
1485  str.Form(" expected maxLH = %.1lf, NDF = %d, expected maxLH/NDF = %lf",
1487  }
1488  if (fStartupOptions) {
1490  fout << str.Data() << std::endl;
1491  }
1492  if (messages)
1493  std::cout << str.Data() << std::endl;
1494 
1495  for (UInt_t i=0; i<fStatistic.fMinExpectedPerHisto.size(); i++) {
1496  if (fStatistic.fNdfPerHisto[i] > 0) {
1497  if (fStatistic.fChisq) { // chisq
1498  str.Form(" run block %d: (NDF/red.chisq/red.chisq_e) =(%d/%lf/%lf)",
1500  } else {
1501  str.Form(" run block %d: (NDF/red.maxLH/red.maxLH_e) =(%d/%lf/%lf)",
1503  }
1504  if (fStartupOptions) {
1506  fout << str.Data() << std::endl;
1507  }
1508 
1509  if (messages)
1510  std::cout << str.Data() << std::endl;
1511  }
1512  }
1513  } else if (fStatistic.fNdfPerHisto.size() > 1) { // check if per run chisq needs to be written
1514  for (UInt_t i=0; i<fStatistic.fNdfPerHisto.size(); i++) {
1515  if (fStatistic.fChisq) { // chisq
1516  str.Form(" run block %d: (NDF/red.chisq) = (%d/%lf)",
1518  } else {
1519  str.Form(" run block %d: (NDF/red.maxLH) = (%d/%lf)",
1521  }
1522  if (fStartupOptions) {
1524  fout << str.Data() << std::endl;
1525  }
1526 
1527  if (messages)
1528  std::cout << str.Data() << std::endl;
1529  }
1530  }
1531  } else {
1532  fout << "*** FIT DID NOT CONVERGE (4) ***" << std::endl;
1533  if (messages)
1534  std::cout << std::endl << "*** FIT DID NOT CONVERGE ***" << std::endl;
1535  }
1536  }
1537 
1538  // close files
1539  fout.close();
1540  fin.close();
1541 
1542  // clean up
1543  t0TagMissing.clear();
1544  backgroundTagMissing.clear();
1545  dataTagMissing.clear();
1546 
1547  return PMUSR_SUCCESS;
1548 }
1549 
1550 //--------------------------------------------------------------------------
1551 // WriteMsrFile (public)
1552 //--------------------------------------------------------------------------
1562 Int_t PMsrHandler::WriteMsrFile(const Char_t *filename, std::map<UInt_t, TString> *commentsPAR, \
1563  std::map<UInt_t, TString> *commentsTHE, \
1564  std::map<UInt_t, TString> *commentsFUN, \
1565  std::map<UInt_t, TString> *commentsRUN)
1566 {
1567  const UInt_t prec = 6; // output precision for float/doubles
1568  const TString hline = "###############################################################";
1569  UInt_t i = 0;
1570  std::map<UInt_t, TString>::iterator iter;
1571  TString str, *pstr;
1572 
1573  // open output file for writing
1574  std::ofstream fout(filename);
1575  if (!fout) {
1577  }
1578 
1579  // write TITLE
1580  fout << fTitle.Data() << std::endl;
1581  fout << hline.Data() << std::endl;
1582 
1583  // write FITPARAMETER block
1584  fout << "FITPARAMETER" << std::endl;
1585  fout << "# No Name Value Step Pos_Error Boundaries" << std::endl;
1586 
1587  for (i = 0; i < fParam.size(); ++i) {
1588  if (commentsPAR) {
1589  iter = commentsPAR->find(i+1);
1590  if (iter != commentsPAR->end()) {
1591  fout << std::endl;
1592  fout << "# " << iter->second.Data() << std::endl;
1593  fout << std::endl;
1594  commentsPAR->erase(iter);
1595  }
1596  }
1597  // parameter no
1598  fout.width(9);
1599  fout << std::right << fParam[i].fNo;
1600  fout << " ";
1601  // parameter name
1602  fout.width(11);
1603  fout << std::left << fParam[i].fName.Data();
1604  fout << " ";
1605  // value of the parameter
1606  fout.width(9);
1607  fout.precision(prec);
1608  fout << std::left << fParam[i].fValue;
1609  fout << " ";
1610  // value of step/error/neg.error
1611  fout.width(11);
1612  fout.precision(prec);
1613  fout << std::left << fParam[i].fStep;
1614  fout << " ";
1615  fout.width(11);
1616  fout.precision(prec);
1617  if ((fParam[i].fNoOfParams == 5) || (fParam[i].fNoOfParams == 7)) // pos. error given
1618  if (fParam[i].fPosErrorPresent && (fParam[i].fStep != 0)) // pos error is a number
1619  fout << std::left << fParam[i].fPosError;
1620  else // pos error is a none
1621  fout << std::left << "none";
1622  else // no pos. error
1623  fout << std::left << "none";
1624  fout << " ";
1625  // boundaries
1626  if (fParam[i].fNoOfParams > 5) {
1627  fout.width(7);
1628  fout.precision(prec);
1629  if (fParam[i].fLowerBoundaryPresent)
1630  fout << std::left << fParam[i].fLowerBoundary;
1631  else
1632  fout << std::left << "none";
1633  fout << " ";
1634  fout.width(7);
1635  fout.precision(prec);
1636  if (fParam[i].fUpperBoundaryPresent)
1637  fout << std::left << fParam[i].fUpperBoundary;
1638  else
1639  fout << std::left << "none";
1640  fout << " ";
1641  }
1642  fout << std::endl;
1643  }
1644  if (commentsPAR && !commentsPAR->empty()) {
1645  fout << std::endl;
1646  for(iter = commentsPAR->begin(); iter != commentsPAR->end(); ++iter) {
1647  fout << "# " << iter->second.Data() << std::endl;
1648  }
1649  commentsPAR->clear();
1650  }
1651  fout << std::endl;
1652  fout << hline.Data() << std::endl;
1653 
1654  // write THEORY block
1655  fout << "THEORY" << std::endl;
1656 
1657  for (i = 1; i < fTheory.size(); ++i) {
1658  if (commentsTHE) {
1659  iter = commentsTHE->find(i);
1660  if (iter != commentsTHE->end()) {
1661  fout << std::endl;
1662  fout << "# " << iter->second.Data() << std::endl;
1663  fout << std::endl;
1664  commentsTHE->erase(iter);
1665  }
1666  }
1667  fout << fTheory[i].fLine.Data() << std::endl;
1668  }
1669  if (commentsTHE && !commentsTHE->empty()) {
1670  fout << std::endl;
1671  for(iter = commentsTHE->begin(); iter != commentsTHE->end(); ++iter) {
1672  fout << "# " << iter->second.Data() << std::endl;
1673  }
1674  commentsTHE->clear();
1675  }
1676  fout << std::endl;
1677  fout << hline.Data() << std::endl;
1678 
1679  // write FUNCTIONS block
1680  // or comment it if there is none in the data structures
1681  if (fFunctions.size() < 2)
1682  fout << "# ";
1683  fout << "FUNCTIONS" << std::endl;
1684 
1685  for (i = 1; i < fFunctions.size(); ++i) {
1686  if (commentsFUN) {
1687  iter = commentsFUN->find(i);
1688  if (iter != commentsFUN->end()) {
1689  fout << std::endl;
1690  fout << "# " << iter->second.Data() << std::endl;
1691  fout << std::endl;
1692  commentsFUN->erase(iter);
1693  }
1694  }
1695  fout << fFunctions[i].fLine.Data() << std::endl;
1696  }
1697  if (commentsFUN && !commentsFUN->empty()) {
1698  fout << std::endl;
1699  for(iter = commentsFUN->begin(); iter != commentsFUN->end(); ++iter) {
1700  fout << "# " << iter->second.Data() << std::endl;
1701  }
1702  commentsFUN->clear();
1703  }
1704  fout << std::endl;
1705  fout << hline.Data() << std::endl;
1706 
1707  // write GLOBAL block
1708  if (fGlobal.IsPresent()) {
1709  fout << "GLOBAL" << std::endl;
1710 
1711  // fittype
1712  if (fGlobal.GetFitType() != -1) {
1713  fout.width(16);
1714  switch (fGlobal.GetFitType()) {
1716  fout << std::left << "fittype" << MSR_FITTYPE_SINGLE_HISTO << " (single histogram fit)" << std::endl;
1717  break;
1719  fout << std::left << "fittype" << MSR_FITTYPE_SINGLE_HISTO_RRF << " (single histogram RRF fit)" << std::endl;
1720  break;
1721  case MSR_FITTYPE_ASYM:
1722  fout << std::left << "fittype" << MSR_FITTYPE_ASYM << " (asymmetry fit)" << std::endl ;
1723  break;
1724  case MSR_FITTYPE_ASYM_RRF:
1725  fout << std::left << "fittype" << MSR_FITTYPE_ASYM_RRF << " (asymmetry RRF fit)" << std::endl ;
1726  break;
1727  case MSR_FITTYPE_MU_MINUS:
1728  fout << std::left << "fittype" << MSR_FITTYPE_MU_MINUS << " (mu minus fit)" << std::endl ;
1729  break;
1730  case MSR_FITTYPE_BNMR:
1731  fout << std::left << "fittype" << MSR_FITTYPE_BNMR << " (beta-NMR fit)" << std::endl ;
1732  break;
1733  case MSR_FITTYPE_NON_MUSR:
1734  fout << std::left << "fittype" << MSR_FITTYPE_NON_MUSR << " (non muSR fit)" << std::endl ;
1735  break;
1736  default:
1737  break;
1738  }
1739  }
1740 
1741  // RRF related stuff
1743  fout.width(16);
1744  fout << std::left << "rrf_freq ";
1745  fout.width(8);
1746  fout << std::left << fGlobal.GetRRFFreq(fGlobal.GetRRFUnit().Data());
1747  fout << " " << fGlobal.GetRRFUnit();
1748  fout << std::endl;
1749  }
1751  fout.width(16);
1752  fout << "rrf_phase ";
1753  fout.width(8);
1754  fout << std::left << fGlobal.GetRRFPhase();
1755  fout << std::endl;
1756  }
1758  fout.width(16);
1759  fout << "rrf_packing ";
1760  fout.width(8);
1761  fout << std::left << fGlobal.GetRRFPacking();
1762  fout << std::endl;
1763  }
1764 
1765  // data range
1766  if ((fGlobal.GetDataRange(0) != -1) || (fGlobal.GetDataRange(1) != -1) || (fGlobal.GetDataRange(2) != -1) || (fGlobal.GetDataRange(3) != -1)) {
1767  fout.width(16);
1768  fout << std::left << "data";
1769  for (UInt_t j=0; j<4; ++j) {
1770  if (fGlobal.GetDataRange(j) > 0) {
1771  fout.width(8);
1772  fout << std::left << fGlobal.GetDataRange(j);
1773  }
1774  }
1775  fout << std::endl;
1776  }
1777 
1778  // t0
1779  if (fGlobal.GetT0BinSize() > 0) {
1780  fout.width(16);
1781  fout << std::left << "t0";
1782  for (UInt_t j=0; j<fGlobal.GetT0BinSize(); ++j) {
1783  fout.width(8);
1784  fout.precision(1);
1785  fout.setf(std::ios::fixed,std::ios::floatfield);
1786  fout << std::left << fGlobal.GetT0Bin(j);
1787  }
1788  fout << std::endl;
1789  }
1790 
1791  // addt0
1792  for (UInt_t j = 0; j < fGlobal.GetAddT0BinEntries(); ++j) {
1793  if (fGlobal.GetAddT0BinSize(j) > 0) {
1794  fout.width(16);
1795  fout << std::left << "addt0";
1796  for (Int_t k=0; k<fGlobal.GetAddT0BinSize(j); ++k) {
1797  fout.width(8);
1798  fout.precision(1);
1799  fout.setf(std::ios::fixed,std::ios::floatfield);
1800  fout << std::left << fGlobal.GetAddT0Bin(j, k);
1801  }
1802  fout << std::endl;
1803  }
1804  }
1805 
1806  // fit range
1807  if ( (fGlobal.IsFitRangeInBin() && fGlobal.GetFitRangeOffset(0) != -1) ||
1808  (fGlobal.GetFitRange(0) != PMUSR_UNDEFINED) ) {
1809  fout.width(16);
1810  fout << std::left << "fit";
1811  if (fGlobal.IsFitRangeInBin()) { // fit range given in bins
1812  fout << "fgb";
1813  if (fGlobal.GetFitRangeOffset(0) > 0)
1814  fout << "+" << fGlobal.GetFitRangeOffset(0);
1815  fout << " lgb";
1816  if (fGlobal.GetFitRangeOffset(1) > 0)
1817  fout << "-" << fGlobal.GetFitRangeOffset(1);
1818  } else { // fit range given in time
1819  for (UInt_t j=0; j<2; j++) {
1820  if (fGlobal.GetFitRange(j) == -1)
1821  break;
1822  UInt_t neededWidth = 7;
1823  UInt_t neededPrec = LastSignificant(fGlobal.GetFitRange(j));
1824  fout.width(neededWidth);
1825  fout.precision(neededPrec);
1826  fout << std::left << std::fixed << fGlobal.GetFitRange(j);
1827  if (j==0)
1828  fout << " ";
1829  }
1830  }
1831  fout << std::endl;
1832  }
1833 
1834  // packing
1835  if (fGlobal.GetPacking() != -1) {
1836  fout.width(16);
1837  fout << std::left << "packing";
1838  fout << fGlobal.GetPacking() << std::endl;
1839  }
1840 
1841  fout << std::endl << hline.Data() << std::endl;
1842  }
1843 
1844  // write RUN blocks
1845  for (i = 0; i < fRuns.size(); ++i) {
1846  if (commentsRUN) {
1847  iter = commentsRUN->find(i + 1);
1848  if (iter != commentsRUN->end()) {
1849  if (!i)
1850  fout << std::endl;
1851  fout << "# " << iter->second.Data() << std::endl;
1852  fout << std::endl;
1853  commentsRUN->erase(iter);
1854  }
1855  }
1856  fout << "RUN " << fRuns[i].GetRunName()->Data() << " ";
1857  pstr = fRuns[i].GetBeamline();
1858  if (pstr == nullptr) {
1859  std::cerr << std::endl << ">> PMsrHandler::WriteMsrFile: **ERROR** Couldn't obtain beamline data." << std::endl;
1860  assert(0);
1861  }
1862  pstr->ToUpper();
1863  fout << pstr->Data() << " ";
1864  pstr = fRuns[i].GetInstitute();
1865  if (pstr == nullptr) {
1866  std::cerr << std::endl << ">> PMsrHandler::WriteMsrFile: **ERROR** Couldn't obtain institute data." << std::endl;
1867  assert(0);
1868  }
1869  pstr->ToUpper();
1870  fout << pstr->Data() << " ";
1871  pstr = fRuns[i].GetFileFormat();
1872  if (pstr == nullptr) {
1873  std::cerr << std::endl << ">> PMsrHandler::WriteMsrFile: **ERROR** Couldn't obtain file format data." << std::endl;
1874  assert(0);
1875  }
1876  pstr->ToUpper();
1877  fout << pstr->Data() << " (name beamline institute data-file-format)" << std::endl;
1878 
1879  // ADDRUN
1880  for (UInt_t j = 1; j < fRuns[i].GetRunNameSize(); ++j) {
1881  fout << "ADDRUN " << fRuns[i].GetRunName(j)->Data() << " ";
1882  pstr = fRuns[i].GetBeamline(j);
1883  if (pstr == nullptr) {
1884  std::cerr << std::endl << ">> PMsrHandler::WriteMsrFile: **ERROR** Couldn't obtain beamline data (addrun)." << std::endl;
1885  assert(0);
1886  }
1887  pstr->ToUpper();
1888  fout << pstr->Data() << " ";
1889  pstr = fRuns[i].GetInstitute(j);
1890  if (pstr == nullptr) {
1891  std::cerr << std::endl << ">> PMsrHandler::WriteMsrFile: **ERROR** Couldn't obtain institute data (addrun)." << std::endl;
1892  assert(0);
1893  }
1894  pstr->ToUpper();
1895  fout << pstr->Data() << " ";
1896  pstr = fRuns[i].GetFileFormat(j);
1897  if (pstr == nullptr) {
1898  std::cerr << std::endl << ">> PMsrHandler::WriteMsrFile: **ERROR** Couldn't obtain file format data (addrun)." << std::endl;
1899  assert(0);
1900  }
1901  pstr->ToUpper();
1902  fout << pstr->Data() << " (name beamline institute data-file-format)" << std::endl;
1903  }
1904 
1905  // fittype
1906  if (fRuns[i].GetFitType() != -1) {
1907  fout.width(16);
1908  switch (fRuns[i].GetFitType()) {
1910  fout << std::left << "fittype" << MSR_FITTYPE_SINGLE_HISTO << " (single histogram fit)" << std::endl;
1911  break;
1913  fout << std::left << "fittype" << MSR_FITTYPE_SINGLE_HISTO_RRF << " (single histogram RRF fit)" << std::endl;
1914  break;
1915  case MSR_FITTYPE_ASYM:
1916  fout << std::left << "fittype" << MSR_FITTYPE_ASYM << " (asymmetry fit)" << std::endl ;
1917  break;
1918  case MSR_FITTYPE_ASYM_RRF:
1919  fout << std::left << "fittype" << MSR_FITTYPE_ASYM_RRF << " (asymmetry RRF fit)" << std::endl ;
1920  break;
1921  case MSR_FITTYPE_MU_MINUS:
1922  fout << std::left << "fittype" << MSR_FITTYPE_MU_MINUS << " (mu minus fit)" << std::endl ;
1923  break;
1924  case MSR_FITTYPE_BNMR:
1925  fout << std::left << "fittype" << MSR_FITTYPE_BNMR << " (beta-NMR fit)" << std::endl ;
1926  break;
1927  case MSR_FITTYPE_NON_MUSR:
1928  fout << std::left << "fittype" << MSR_FITTYPE_NON_MUSR << " (non muSR fit)" << std::endl ;
1929  break;
1930  default:
1931  break;
1932  }
1933  }
1934 
1935  // alpha
1936  if (fRuns[i].GetAlphaParamNo() != -1) {
1937  fout.width(16);
1938  fout << std::left << "alpha";
1939  // check if alpha is give as a function
1940  if (fRuns[i].GetAlphaParamNo() >= MSR_PARAM_FUN_OFFSET)
1941  fout << "fun" << fRuns[i].GetAlphaParamNo()-MSR_PARAM_FUN_OFFSET;
1942  else
1943  fout << fRuns[i].GetAlphaParamNo();
1944  fout << std::endl;
1945  }
1946 
1947  // beta
1948  if (fRuns[i].GetBetaParamNo() != -1) {
1949  fout.width(16);
1950  fout << std::left << "beta";
1951  // check if beta is give as a function
1952  if (fRuns[i].GetBetaParamNo() >= MSR_PARAM_FUN_OFFSET)
1953  fout << "fun" << fRuns[i].GetBetaParamNo()-MSR_PARAM_FUN_OFFSET;
1954  else
1955  fout << fRuns[i].GetBetaParamNo();
1956  fout << std::endl;
1957  }
1958 
1959  // norm
1960  if (fRuns[i].GetNormParamNo() != -1) {
1961  fout.width(16);
1962  fout << std::left << "norm";
1963  // check if norm is give as a function
1964  if (fRuns[i].GetNormParamNo() >= MSR_PARAM_FUN_OFFSET)
1965  fout << "fun" << fRuns[i].GetNormParamNo()-MSR_PARAM_FUN_OFFSET;
1966  else
1967  fout << fRuns[i].GetNormParamNo();
1968  fout << std::endl;
1969  }
1970 
1971  // backgr.fit
1972  if (fRuns[i].GetBkgFitParamNo() != -1) {
1973  fout.width(16);
1974  fout << std::left << "backgr.fit";
1975  fout << fRuns[i].GetBkgFitParamNo() << std::endl;
1976  }
1977 
1978  // lifetime
1979  if (fRuns[i].GetLifetimeParamNo() != -1) {
1980  fout.width(16);
1981  fout << std::left << "lifetime";
1982  fout << fRuns[i].GetLifetimeParamNo() << std::endl;
1983  }
1984 
1985  // lifetimecorrection
1986  if ((fRuns[i].IsLifetimeCorrected()) && (fRuns[i].GetFitType() == MSR_FITTYPE_SINGLE_HISTO)) {
1987  fout << "lifetimecorrection" << std::endl;
1988  }
1989 
1990  // map
1991  fout << "map ";
1992  for (UInt_t j=0; j<fRuns[i].GetMap()->size(); ++j) {
1993  fout.width(5);
1994  fout << std::right << fRuns[i].GetMap(j);
1995  }
1996  // if there are less maps then 10 fill with zeros
1997  if (fRuns[i].GetMap()->size() < 10) {
1998  for (UInt_t j=fRuns[i].GetMap()->size(); j<10; ++j)
1999  fout << " 0";
2000  }
2001  fout << std::endl;
2002 
2003  // forward
2004  if (fRuns[i].GetForwardHistoNoSize() == 0) {
2005  std::cerr << std::endl << ">> PMsrHandler::WriteMsrFile: **WARNING** No 'forward' data found!";
2006  std::cerr << std::endl << ">> Something is VERY fishy, please check your msr-file carfully." << std::endl;
2007  } else {
2008  fout.width(16);
2009  fout << std::left << "forward";
2010  for (UInt_t j=0; j<fRuns[i].GetForwardHistoNoSize(); ++j) {
2011  fout.width(8);
2012  fout << fRuns[i].GetForwardHistoNo(j);
2013  }
2014  fout << std::endl;
2015  }
2016 
2017  // backward
2018  if (fRuns[i].GetBackwardHistoNoSize() > 0) {
2019  fout.width(16);
2020  fout << std::left << "backward";
2021  for (UInt_t j=0; j<fRuns[i].GetBackwardHistoNoSize(); ++j) {
2022  fout.width(8);
2023  fout << fRuns[i].GetBackwardHistoNo(j);
2024  }
2025  fout << std::endl;
2026  }
2027 
2028  // backgr.fix
2029  if ((fRuns[i].GetBkgFix(0) != PMUSR_UNDEFINED) || (fRuns[i].GetBkgFix(1) != PMUSR_UNDEFINED)) {
2030  fout.width(15);
2031  fout << std::left << "backgr.fix";
2032  for (UInt_t j=0; j<2; ++j) {
2033  if (fRuns[i].GetBkgFix(j) != PMUSR_UNDEFINED) {
2034  fout.precision(prec);
2035  fout.width(12);
2036  fout << std::left << fRuns[i].GetBkgFix(j);
2037  }
2038  }
2039  fout << std::endl;
2040  }
2041 
2042  // background
2043  if ((fRuns[i].GetBkgRange(0) != -1) || (fRuns[i].GetBkgRange(1) != -1) || (fRuns[i].GetBkgRange(2) != -1) || (fRuns[i].GetBkgRange(3) != -1)) {
2044  fout.width(16);
2045  fout << std::left << "background";
2046  for (UInt_t j=0; j<4; ++j) {
2047  if (fRuns[i].GetBkgRange(j) > 0) {
2048  fout.width(8);
2049  fout << std::left << fRuns[i].GetBkgRange(j);
2050  }
2051  }
2052  fout << std::endl;
2053  }
2054 
2055  // data
2056  if ((fRuns[i].GetDataRange(0) != -1) || (fRuns[i].GetDataRange(1) != -1) || (fRuns[i].GetDataRange(2) != -1) || (fRuns[i].GetDataRange(3) != -1)) {
2057  fout.width(16);
2058  fout << std::left << "data";
2059  for (UInt_t j=0; j<4; ++j) {
2060  if (fRuns[i].GetDataRange(j) > 0) {
2061  fout.width(8);
2062  fout << std::left << fRuns[i].GetDataRange(j);
2063  }
2064  }
2065  fout << std::endl;
2066  }
2067 
2068  // t0
2069  if (fRuns[i].GetT0BinSize() > 0) {
2070  fout.width(16);
2071  fout << std::left << "t0";
2072  for (UInt_t j=0; j<fRuns[i].GetT0BinSize(); ++j) {
2073  fout.width(8);
2074  fout.precision(1);
2075  fout.setf(std::ios::fixed,std::ios::floatfield);
2076  fout << std::left << fRuns[i].GetT0Bin(j);
2077  }
2078  fout << std::endl;
2079  }
2080 
2081  // addt0
2082  if (fRuns[i].GetAddT0BinEntries() > 0) {
2083  for (UInt_t j = 0; j < fRuns[i].GetRunNameSize() - 1; ++j) {
2084  if (fRuns[i].GetAddT0BinSize(j) > 0) {
2085  fout.width(16);
2086  fout << std::left << "addt0";
2087  for (Int_t k=0; k<fRuns[i].GetAddT0BinSize(j); ++k) {
2088  fout.width(8);
2089  fout.precision(1);
2090  fout.setf(std::ios::fixed,std::ios::floatfield);
2091  fout << std::left << fRuns[i].GetAddT0Bin(j, k);
2092  }
2093  fout << std::endl;
2094  }
2095  }
2096  }
2097 
2098  // xy-data
2099  if (fRuns[i].GetXDataIndex() != -1) { // indices
2100  fout.width(16);
2101  fout << std::left << "xy-data";
2102  fout.width(8);
2103  fout.precision(2);
2104  fout << std::left << std::fixed << fRuns[i].GetXDataIndex();
2105  fout.width(8);
2106  fout.precision(2);
2107  fout << std::left << std::fixed << fRuns[i].GetYDataIndex();
2108  fout << std::endl;
2109  } else if (!fRuns[i].GetXDataLabel()->IsWhitespace()) { // labels
2110  fout.width(16);
2111  fout << std::left << "xy-data";
2112  fout.width(8);
2113  fout << std::left << std::fixed << fRuns[i].GetXDataLabel()->Data();
2114  fout << " ";
2115  fout.width(8);
2116  fout << std::left << std::fixed << fRuns[i].GetYDataLabel()->Data();
2117  fout << std::endl;
2118  }
2119 
2120  // fit
2121  if ( (fRuns[i].IsFitRangeInBin() && fRuns[i].GetFitRangeOffset(0) != -1) ||
2122  (fRuns[i].GetFitRange(0) != PMUSR_UNDEFINED) ) {
2123  fout.width(16);
2124  fout << std::left << "fit";
2125  if (fRuns[i].IsFitRangeInBin()) { // fit range given in bins
2126  fout << "fgb";
2127  if (fRuns[i].GetFitRangeOffset(0) > 0)
2128  fout << "+" << fRuns[i].GetFitRangeOffset(0);
2129  fout << " lgb";
2130  if (fRuns[i].GetFitRangeOffset(1) > 0)
2131  fout << "-" << fRuns[i].GetFitRangeOffset(1);
2132  } else { // fit range given in time
2133  for (UInt_t j=0; j<2; j++) {
2134  if (fRuns[i].GetFitRange(j) == -1)
2135  break;
2136  UInt_t neededWidth = 7;
2137  UInt_t neededPrec = LastSignificant(fRuns[i].GetFitRange(j));
2138  fout.width(neededWidth);
2139  fout.precision(neededPrec);
2140  fout << std::left << std::fixed << fRuns[i].GetFitRange(j);
2141  if (j==0)
2142  fout << " ";
2143  }
2144  }
2145  fout << std::endl;
2146  }
2147 
2148  // packing
2149  if (fRuns[i].GetPacking() != -1) {
2150  fout.width(16);
2151  fout << std::left << "packing";
2152  fout << fRuns[i].GetPacking() << std::endl;
2153  }
2154 
2155  fout << std::endl;
2156  }
2157 
2158  if (commentsRUN && !commentsRUN->empty()) {
2159  for(iter = commentsRUN->begin(); iter != commentsRUN->end(); ++iter) {
2160  fout << "# " << iter->second.Data() << std::endl;
2161  }
2162  fout << std::endl;
2163  commentsRUN->clear();
2164  }
2165  fout << hline.Data() << std::endl;
2166 
2167  // write COMMANDS block
2168  fout << "COMMANDS" << std::endl;
2169  for (i = 0; i < fCommands.size(); ++i) {
2170  if (fCommands[i].fLine.BeginsWith("SET BATCH") || fCommands[i].fLine.BeginsWith("END RETURN"))
2171  continue;
2172  else
2173  fout << fCommands[i].fLine.Data() << std::endl;
2174  }
2175  fout << std::endl;
2176  fout << hline.Data() << std::endl;
2177 
2178  // write FOURIER block
2180  fout << "FOURIER" << std::endl;
2181 
2182  // units
2183  if (fFourier.fUnits) {
2184  fout << "units ";
2186  fout << "Gauss";
2187  } else if (fFourier.fUnits == FOURIER_UNIT_TESLA) {
2188  fout << "Tesla";
2189  } else if (fFourier.fUnits == FOURIER_UNIT_FREQ) {
2190  fout << "MHz ";
2191  } else if (fFourier.fUnits == FOURIER_UNIT_CYCLES) {
2192  fout << "Mc/s";
2193  }
2194  fout << " # units either 'Gauss', 'Tesla', 'MHz', or 'Mc/s'";
2195  fout << std::endl;
2196  }
2197 
2198  // fourier_power
2199  if (fFourier.fFourierPower != -1) {
2200  fout << "fourier_power " << fFourier.fFourierPower << std::endl;
2201  }
2202 
2203  // apodization
2204  if (fFourier.fApodization) {
2205  fout << "apodization ";
2207  fout << "NONE ";
2208  } else if (fFourier.fApodization == FOURIER_APOD_WEAK) {
2209  fout << "WEAK ";
2210  } else if (fFourier.fApodization == FOURIER_APOD_MEDIUM) {
2211  fout << "MEDIUM";
2212  } else if (fFourier.fApodization == FOURIER_APOD_STRONG) {
2213  fout << "STRONG";
2214  }
2215  fout << " # NONE, WEAK, MEDIUM, STRONG";
2216  fout << std::endl;
2217  }
2218 
2219  // plot
2220  if (fFourier.fPlotTag) {
2221  fout << "plot ";
2223  fout << "REAL ";
2224  } else if (fFourier.fPlotTag == FOURIER_PLOT_IMAG) {
2225  fout << "IMAG ";
2227  fout << "REAL_AND_IMAG";
2228  } else if (fFourier.fPlotTag == FOURIER_PLOT_POWER) {
2229  fout << "POWER";
2230  } else if (fFourier.fPlotTag == FOURIER_PLOT_PHASE) {
2231  fout << "PHASE";
2233  fout << "PHASE_OPT_REAL";
2234  }
2235  fout << " # REAL, IMAG, REAL_AND_IMAG, POWER, PHASE, PHASE_OPT_REAL";
2236  fout << std::endl;
2237  }
2238 
2239  // phase
2240  if (fFourier.fPhaseParamNo.size() > 0) {
2241  TString phaseParamStr = BeautifyFourierPhaseParameterString();
2242  fout << "phase " << phaseParamStr << std::endl;
2243  } else if (fFourier.fPhase.size() > 0) {
2244  fout << "phase ";
2245  for (UInt_t i=0; i<fFourier.fPhase.size()-1; i++) {
2246  fout << fFourier.fPhase[i] << ", ";
2247  }
2248  fout << fFourier.fPhase[fFourier.fPhase.size()-1] << std::endl;
2249  }
2250 
2251  // range_for_phase_correction
2252  if ((fFourier.fRangeForPhaseCorrection[0] != -1.0) || (fFourier.fRangeForPhaseCorrection[1] != -1.0)) {
2253  fout << "range_for_phase_correction " << fFourier.fRangeForPhaseCorrection[0] << " " << fFourier.fRangeForPhaseCorrection[1] << std::endl;
2254  }
2255 
2256  // range
2257  if ((fFourier.fPlotRange[0] != -1.0) || (fFourier.fPlotRange[1] != -1.0)) {
2258  fout.setf(std::ios::fixed,std::ios::floatfield);
2259  UInt_t neededPrec = LastSignificant(fFourier.fPlotRange[0]);
2260  if (LastSignificant(fFourier.fPlotRange[1]) > neededPrec)
2261  neededPrec = LastSignificant(fFourier.fPlotRange[1]);
2262  fout.precision(neededPrec);
2263  fout << "range " << fFourier.fPlotRange[0] << " " << fFourier.fPlotRange[1] << std::endl;
2264  }
2265 
2266 // // phase_increment -- not used in msr-files at the moment (can only be set through the xml-file)
2267 // if (fFourier.fPhaseIncrement) {
2268 // fout << "phase_increment " << fFourier.fPhaseIncrement << std::endl;
2269 // }
2270 
2271  fout << std::endl;
2272  fout << hline.Data() << std::endl;
2273  }
2274 
2275  // write PLOT blocks
2276  for (i = 0; i < fPlots.size(); ++i) {
2277  switch (fPlots[i].fPlotType) {
2278  case MSR_PLOT_SINGLE_HISTO:
2279  fout << "PLOT " << fPlots[i].fPlotType << " (single histo plot)" << std::endl;
2280  break;
2282  fout << "PLOT " << fPlots[i].fPlotType << " (single histo RRF plot)" << std::endl;
2283  break;
2284  case MSR_PLOT_ASYM:
2285  fout << "PLOT " << fPlots[i].fPlotType << " (asymmetry plot)" << std::endl;
2286  break;
2287  case MSR_PLOT_ASYM_RRF:
2288  fout << "PLOT " << fPlots[i].fPlotType << " (asymmetry RRF plot)" << std::endl;
2289  break;
2290  case MSR_PLOT_MU_MINUS:
2291  fout << "PLOT " << fPlots[i].fPlotType << " (mu minus plot)" << std::endl;
2292  break;
2293  case MSR_PLOT_BNMR:
2294  fout << "PLOT " << fPlots[i].fPlotType << " (beta-NMR asymmetry plot)" << std::endl;
2295  break;
2296  case MSR_PLOT_NON_MUSR:
2297  fout << "PLOT " << fPlots[i].fPlotType << " (non muSR plot)" << std::endl;
2298  break;
2299  default:
2300  break;
2301  }
2302 
2303  // runs
2304  fout << "runs ";
2305  fout.precision(0);
2306  for (UInt_t j=0; j<fPlots[i].fRuns.size(); ++j) {
2307  fout.width(4);
2308  fout << fPlots[i].fRuns[j];
2309  }
2310  fout << std::endl;
2311 
2312  // range and sub_ranges
2313  if ((fPlots[i].fTmin.size() == 1) && (fPlots[i].fTmax.size() == 1)) {
2314  fout << "range ";
2315  fout.precision(2);
2316  fout << fPlots[i].fTmin[0] << " " << fPlots[i].fTmax[0];
2317  } else if ((fPlots[i].fTmin.size() > 1) && (fPlots[i].fTmax.size() > 1)) {
2318  fout << "sub_ranges ";
2319  fout.precision(2);
2320  for (UInt_t j=0; j < fPlots[i].fTmin.size(); ++j) {
2321  fout << " " << fPlots[i].fTmin[j] << " " << fPlots[i].fTmax[j];
2322  }
2323  }
2324  if (!fPlots[i].fYmin.empty() && !fPlots[i].fYmax.empty()) {
2325  fout << " " << fPlots[i].fYmin[0] << " " << fPlots[i].fYmax[0];
2326  }
2327  fout << std::endl;
2328 
2329  // use_fit_ranges
2330  if (fPlots[i].fUseFitRanges) {
2331  if (!fPlots[i].fYmin.empty() && !fPlots[i].fYmax.empty())
2332  fout << "use_fit_ranges " << fPlots[i].fYmin[0] << " " << fPlots[i].fYmax[0] << std::endl;
2333  else
2334  fout << "use_fit_ranges" << std::endl;
2335  }
2336 
2337  // view_packing
2338  if (fPlots[i].fViewPacking != -1) {
2339  fout << "view_packing " << fPlots[i].fViewPacking << std::endl;
2340  }
2341 
2342  // logx
2343  if (fPlots[i].fLogX) {
2344  fout << "logx" << std::endl;
2345  }
2346 
2347  // logy
2348  if (fPlots[i].fLogY) {
2349  fout << "logy" << std::endl;
2350  }
2351 
2352  // lifetimecorrection
2353  if (fPlots[i].fLifeTimeCorrection) {
2354  fout << "lifetimecorrection" << std::endl;
2355  }
2356 
2357  // rrf_packing
2358  if (fPlots[i].fRRFPacking) {
2359  fout << "rrf_packing " << fPlots[i].fRRFPacking << std::endl;
2360  }
2361 
2362  // rrf_freq
2363  if (fPlots[i].fRRFFreq) {
2364  fout << "rrf_freq " << fPlots[i].fRRFFreq << " ";
2365  switch (fPlots[i].fRRFUnit) {
2366  case RRF_UNIT_kHz:
2367  fout << "kHz";
2368  break;
2369  case RRF_UNIT_MHz:
2370  fout << "MHz";
2371  break;
2372  case RRF_UNIT_Mcs:
2373  fout << "Mc/s";
2374  break;
2375  case RRF_UNIT_G:
2376  fout << "G";
2377  break;
2378  case RRF_UNIT_T:
2379  fout << "T";
2380  break;
2381  default:
2382  break;
2383  }
2384  fout << std::endl;
2385  }
2386 
2387  // rrf_phase
2388  if (fPlots[i].fRRFPhaseParamNo > 0) {
2389  fout << "rrf_phase par" << fPlots[i].fRRFPhaseParamNo << std::endl;
2390  } else if (fPlots[i].fRRFPhase) {
2391  fout << "rrf_phase " << fPlots[i].fRRFPhase << std::endl;
2392  }
2393 
2394  fout << std::endl;
2395  }
2396  if (!fPlots.empty()) {
2397  fout << hline.Data() << std::endl;
2398  }
2399 
2400  // write STATISTIC block
2401  TDatime dt;
2402  fout << "STATISTIC --- " << dt.AsSQLString() << std::endl;
2403  if (fStatistic.fValid) { // valid fit result
2404  if (fStatistic.fChisq) { // chisq
2405  str = " chisq = ";
2406  str += fStatistic.fMin;
2407  str += ", NDF = ";
2408  str += fStatistic.fNdf;
2409  str += ", chisq/NDF = ";
2410  str += fStatistic.fMin / fStatistic.fNdf;
2411  fout << str.Data() << std::endl;
2412  } else { // max. log. liklihood
2413  str = " maxLH = ";
2414  str += fStatistic.fMin;
2415  str += ", NDF = ";
2416  str += fStatistic.fNdf;
2417  str += ", maxLH/NDF = ";
2418  str += fStatistic.fMin / fStatistic.fNdf;
2419  fout << str.Data() << std::endl;
2420  }
2421  } else {
2422  fout << "*** FIT DID NOT CONVERGE ***" << std::endl;
2423  }
2424 
2425  // close file
2426  fout.close();
2427 
2428  str.Clear();
2429  pstr = nullptr;
2430 
2431  return PMUSR_SUCCESS;
2432 }
2433 
2434 //--------------------------------------------------------------------------
2435 // SetMsrParamValue (public)
2436 //--------------------------------------------------------------------------
2447 Bool_t PMsrHandler::SetMsrParamValue(UInt_t idx, Double_t value)
2448 {
2449  if (idx >= fParam.size()) {
2450  std::cerr << std::endl << ">> PMsrHandler::SetMsrParamValue(): **ERROR** idx = " << idx << " is >= than the number of fit parameters " << fParam.size();
2451  std::cerr << std::endl;
2452  return false;
2453  }
2454 
2455  fParam[idx].fValue = value;
2456 
2457  return true;
2458 }
2459 
2460 //--------------------------------------------------------------------------
2461 // SetMsrParamStep (public)
2462 //--------------------------------------------------------------------------
2474 Bool_t PMsrHandler::SetMsrParamStep(UInt_t idx, Double_t value)
2475 {
2476  if (idx >= fParam.size()) {
2477  std::cerr << std::endl << ">> PMsrHandler::SetMsrParamValue(): **ERROR** idx = " << idx << " is larger than the number of parameters " << fParam.size();
2478  std::cerr << std::endl;
2479  return false;
2480  }
2481 
2482  fParam[idx].fStep = value;
2483 
2484  return true;
2485 }
2486 
2487 //--------------------------------------------------------------------------
2488 // SetMsrParamPosErrorPresent (public)
2489 //--------------------------------------------------------------------------
2500 Bool_t PMsrHandler::SetMsrParamPosErrorPresent(UInt_t idx, Bool_t value)
2501 {
2502  if (idx >= fParam.size()) {
2503  std::cerr << std::endl << ">> PMsrHandler::SetMsrParamPosErrorPresent(): **ERROR** idx = " << idx << " is larger than the number of parameters " << fParam.size();
2504  std::cerr << std::endl;
2505  return false;
2506  }
2507 
2508  fParam[idx].fPosErrorPresent = value;
2509 
2510  return true;
2511 }
2512 
2513 //--------------------------------------------------------------------------
2514 // SetMsrParamPosError (public)
2515 //--------------------------------------------------------------------------
2526 Bool_t PMsrHandler::SetMsrParamPosError(UInt_t idx, Double_t value)
2527 {
2528  if (idx >= fParam.size()) {
2529  std::cerr << std::endl << ">> PMsrHandler::SetMsrParamPosError(): **ERROR** idx = " << idx << " is larger than the number of parameters " << fParam.size();
2530  std::cerr << std::endl;
2531  return false;
2532  }
2533 
2534  fParam[idx].fPosErrorPresent = true;
2535  fParam[idx].fPosError = value;
2536 
2537  return true;
2538 }
2539 
2540 //--------------------------------------------------------------------------
2541 // SetMsrT0Entry (public)
2542 //--------------------------------------------------------------------------
2550 void PMsrHandler::SetMsrT0Entry(UInt_t runNo, UInt_t idx, Double_t bin)
2551 {
2552  if (runNo >= fRuns.size()) { // error
2553  std::cerr << std::endl << ">> PMsrHandler::SetMsrT0Entry: **ERROR** runNo = " << runNo << ", is out of valid range 0.." << fRuns.size();
2554  std::cerr << std::endl;
2555  return;
2556  }
2557 
2558  if (idx >= fRuns[runNo].GetT0BinSize()) { // error
2559  std::cerr << std::endl << ">> PMsrHandler::SetMsrT0Entry: **WARNING** idx = " << idx << ", is out of valid range 0.." << fRuns[runNo].GetT0BinSize();
2560  std::cerr << std::endl << ">> Will add it anyway.";
2561  std::cerr << std::endl;
2562  }
2563 
2564  fRuns[runNo].SetT0Bin(bin, idx);
2565 }
2566 
2567 //--------------------------------------------------------------------------
2568 // SetMsrAddT0Entry (public)
2569 //--------------------------------------------------------------------------
2578 void PMsrHandler::SetMsrAddT0Entry(UInt_t runNo, UInt_t addRunIdx, UInt_t histoIdx, Double_t bin)
2579 {
2580  if (runNo >= fRuns.size()) { // error
2581  std::cerr << std::endl << ">> PMsrHandler::SetMsrAddT0Entry: **ERROR** runNo = " << runNo << ", is out of valid range 0.." << fRuns.size();
2582  std::cerr << std::endl;
2583  return;
2584  }
2585 
2586  if (addRunIdx >= fRuns[runNo].GetAddT0BinEntries()) { // error
2587  std::cerr << std::endl << ">> PMsrHandler::SetMsrAddT0Entry: **WARNING** addRunIdx = " << addRunIdx << ", is out of valid range 0.." << fRuns[runNo].GetAddT0BinEntries();
2588  std::cerr << std::endl << ">> Will add it anyway.";
2589  std::cerr << std::endl;
2590  }
2591 
2592  if (static_cast<Int_t>(histoIdx) > fRuns[runNo].GetAddT0BinSize(addRunIdx)) { // error
2593  std::cerr << std::endl << ">> PMsrHandler::SetMsrAddT0Entry: **WARNING** histoIdx = " << histoIdx << ", is out of valid range 0.." << fRuns[runNo].GetAddT0BinSize(addRunIdx);
2594  std::cerr << std::endl << ">> Will add it anyway.";
2595  std::cerr << std::endl;
2596  }
2597 
2598  fRuns[runNo].SetAddT0Bin(bin, addRunIdx, histoIdx);
2599 }
2600 
2601 //--------------------------------------------------------------------------
2602 // SetMsrDataRangeEntry (public)
2603 //--------------------------------------------------------------------------
2611 void PMsrHandler::SetMsrDataRangeEntry(UInt_t runNo, UInt_t idx, Int_t bin)
2612 {
2613  if (runNo >= fRuns.size()) { // error
2614  std::cerr << std::endl << ">> PMsrHandler::SetMsrDataRangeEntry: **ERROR** runNo = " << runNo << ", is out of valid range 0.." << fRuns.size();
2615  std::cerr << std::endl;
2616  return;
2617  }
2618 
2619  fRuns[runNo].SetDataRange(bin, idx);
2620 }
2621 
2622 //--------------------------------------------------------------------------
2623 // SetMsrBkgRangeEntry (public)
2624 //--------------------------------------------------------------------------
2632 void PMsrHandler::SetMsrBkgRangeEntry(UInt_t runNo, UInt_t idx, Int_t bin)
2633 {
2634  if (runNo >= fRuns.size()) { // error
2635  std::cerr << std::endl << ">> PMsrHandler::SetMsrBkgRangeEntry: **ERROR** runNo = " << runNo << ", is out of valid range 0.." << fRuns.size();
2636  std::cerr << std::endl;
2637  return;
2638  }
2639 
2640  fRuns[runNo].SetBkgRange(bin, idx);
2641 }
2642 
2643 //--------------------------------------------------------------------------
2644 // ParameterInUse (public)
2645 //--------------------------------------------------------------------------
2658 Int_t PMsrHandler::ParameterInUse(UInt_t paramNo)
2659 {
2660  // check that paramNo is within acceptable range
2661  if (paramNo >= fParam.size())
2662  return -1;
2663 
2664  return fParamInUse[paramNo];
2665 }
2666 
2667 //--------------------------------------------------------------------------
2668 // HandleFitParameterEntry (private)
2669 //--------------------------------------------------------------------------
2692 {
2693  PMsrParamStructure param;
2694  Bool_t error = false;
2695 
2696  PMsrLines::iterator iter;
2697 
2698  TObjArray *tokens = nullptr;
2699  TObjString *ostr = nullptr;
2700  TString str;
2701 
2702  // fill param structure
2703  iter = lines.begin();
2704  while ((iter != lines.end()) && !error) {
2705 
2706  // init param structure
2707  param.fNoOfParams = -1;
2708  param.fNo = -1;
2709  param.fName = TString("");
2710  param.fValue = 0.0;
2711  param.fStep = 0.0;
2712  param.fPosErrorPresent = false;
2713  param.fPosError = 0.0;
2714  param.fLowerBoundaryPresent = false;
2715  param.fLowerBoundary = 0.0;
2716  param.fUpperBoundaryPresent = false;
2717  param.fUpperBoundary = 0.0;
2718 
2719  tokens = iter->fLine.Tokenize(" \t");
2720  if (!tokens) {
2721  std::cerr << std::endl << ">> PMsrHandler::HandleFitParameterEntry: **SEVERE ERROR** Couldn't tokenize Parameters in line " << iter->fLineNo;
2722  std::cerr << std::endl << std::endl;
2723  return false;
2724  }
2725 
2726  // handle various input possiblities
2727  if ((tokens->GetEntries() < 4) || (tokens->GetEntries() > 7) || (tokens->GetEntries() == 6)) {
2728  error = true;
2729  } else { // handle the first 4 parameter since they are always the same
2730  // parameter number
2731  ostr = dynamic_cast<TObjString*>(tokens->At(0));
2732  str = ostr->GetString();
2733  if (str.IsDigit())
2734  param.fNo = str.Atoi();
2735  else
2736  error = true;
2737 
2738  // parameter name
2739  ostr = dynamic_cast<TObjString*>(tokens->At(1));
2740  str = ostr->GetString();
2741  param.fName = str;
2742 
2743  // parameter value
2744  ostr = dynamic_cast<TObjString*>(tokens->At(2));
2745  str = ostr->GetString();
2746  if (str.IsFloat())
2747  param.fValue = static_cast<Double_t>(str.Atof());
2748  else
2749  error = true;
2750 
2751  // parameter value
2752  ostr = dynamic_cast<TObjString*>(tokens->At(3));
2753  str = ostr->GetString();
2754  if (str.IsFloat())
2755  param.fStep = static_cast<Double_t>(str.Atof());
2756  else
2757  error = true;
2758 
2759  // 4 values, i.e. No Name Value Step
2760  if (tokens->GetEntries() == 4) {
2761  param.fNoOfParams = 4;
2762  }
2763 
2764  // 5 values, i.e. No Name Value Neg_Error Pos_Error
2765  if (tokens->GetEntries() == 5) {
2766  param.fNoOfParams = 5;
2767 
2768  // positive error
2769  ostr = dynamic_cast<TObjString*>(tokens->At(4));
2770  str = ostr->GetString();
2771  if (str.IsFloat()) {
2772  param.fPosErrorPresent = true;
2773  param.fPosError = static_cast<Double_t>(str.Atof());
2774  } else {
2775  str.ToLower();
2776  if (!str.CompareTo("none", TString::kIgnoreCase))
2777  param.fPosErrorPresent = false;
2778  else
2779  error = true;
2780  }
2781  }
2782 
2783  // 7 values, i.e. No Name Value Neg_Error Pos_Error Lower_Boundary Upper_Boundary
2784  if (tokens->GetEntries() == 7) {
2785  param.fNoOfParams = 7;
2786 
2787  // positive error
2788  ostr = dynamic_cast<TObjString*>(tokens->At(4));
2789  str = ostr->GetString();
2790  if (str.IsFloat()) {
2791  param.fPosErrorPresent = true;
2792  param.fPosError = static_cast<Double_t>(str.Atof());
2793  } else {
2794  str.ToLower();
2795  if (!str.CompareTo("none", TString::kIgnoreCase))
2796  param.fPosErrorPresent = false;
2797  else
2798  error = true;
2799  }
2800 
2801  // lower boundary
2802  ostr = dynamic_cast<TObjString*>(tokens->At(5));
2803  str = ostr->GetString();
2804  // check if lower boundary is "none", i.e. upper boundary limited only
2805  if (!str.CompareTo("none", TString::kIgnoreCase)) { // none
2806  param.fLowerBoundaryPresent = false;
2807  } else { // assuming that the lower boundary is a number
2808  if (str.IsFloat()) {
2809  param.fLowerBoundary = static_cast<Double_t>(str.Atof());
2810  param.fLowerBoundaryPresent = true;
2811  } else {
2812  error = true;
2813  }
2814  }
2815 
2816  // upper boundary
2817  ostr = dynamic_cast<TObjString*>(tokens->At(6));
2818  str = ostr->GetString();
2819  // check if upper boundary is "none", i.e. lower boundary limited only
2820  if (!str.CompareTo("none", TString::kIgnoreCase)) { // none
2821  param.fUpperBoundaryPresent = false;
2822  } else { // assuming a number
2823  if (str.IsFloat()) {
2824  param.fUpperBoundary = static_cast<Double_t>(str.Atof());
2825  param.fUpperBoundaryPresent = true;
2826  } else {
2827  error = true;
2828  }
2829  }
2830 
2831  // check for lower-/upper-boundaries = none/none
2832  if (!param.fLowerBoundaryPresent && !param.fUpperBoundaryPresent)
2833  param.fNoOfParams = 5; // since there are no real boundaries present
2834  }
2835  }
2836 
2837  // check if enough elements found
2838  if (error) {
2839  std::cerr << std::endl;
2840  std::cerr << std::endl << ">> PMsrHandler::HandleFitParameterEntry: **ERROR** in line " << iter->fLineNo << ":";
2841  std::cerr << std::endl << ">> " << iter->fLine.Data();
2842  std::cerr << std::endl << ">> A Fit Parameter line needs to have the following form: ";
2843  std::cerr << std::endl;
2844  std::cerr << std::endl << ">> No Name Value Step/Error [Lower_Boundary Upper_Boundary]";
2845  std::cerr << std::endl;
2846  std::cerr << std::endl << ">> or";
2847  std::cerr << std::endl;
2848  std::cerr << std::endl << ">> No Name Value Step/Neg_Error Pos_Error [Lower_Boundary Upper_Boundary]";
2849  std::cerr << std::endl;
2850  std::cerr << std::endl << ">> No: the parameter number (an Int_t)";
2851  std::cerr << std::endl << ">> Name: the name of the parameter (less than 256 character)";
2852  std::cerr << std::endl << ">> Value: the starting value of the parameter (a Double_t)";
2853  std::cerr << std::endl << ">> Step/Error,";
2854  std::cerr << std::endl << ">> Step/Neg_Error: the starting step value in a fit (a Double_t), or";
2855  std::cerr << std::endl << ">> the symmetric error (MIGRAD, SIMPLEX), or";
2856  std::cerr << std::endl << ">> the negative error (MINOS)";
2857  std::cerr << std::endl << ">> Pos_Error: the positive error (MINOS), (a Double_t or \"none\")";
2858  std::cerr << std::endl << ">> Lower_Boundary: the lower boundary allowed for the fit parameter (a Double_t or \"none\")";
2859  std::cerr << std::endl << ">> Upper_Boundary: the upper boundary allowed for the fit parameter (a Double_t or \"none\")";
2860  std::cerr << std::endl;
2861  } else { // everything is OK, therefore add the parameter to the parameter list
2862  fParam.push_back(param);
2863  }
2864 
2865  // clean up
2866  if (tokens) {
2867  delete tokens;
2868  tokens = nullptr;
2869  }
2870 
2871  iter++;
2872  }
2873 
2874  // check if all parameters have subsequent numbers.
2875  for (UInt_t i=0; i<fParam.size(); i++) {
2876  if (fParam[i].fNo != static_cast<Int_t>(i)+1) {
2877  error = true;
2878  std::cerr << std::endl << ">> PMsrHandler::HandleFitParameterEntry: **ERROR**";
2879  std::cerr << std::endl << ">> Sorry, you are assuming to much from this program, it cannot";
2880  std::cerr << std::endl << ">> handle none subsequent numbered parameters yet or in the near future.";
2881  std::cerr << std::endl << ">> Found parameter " << fParam[i].fName.Data() << ", with";
2882  std::cerr << std::endl << ">> parameter number " << fParam[i].fNo << ", at paramter position " << i+1 << ".";
2883  std::cerr << std::endl << ">> This needs to be fixed first.";
2884  std::cerr << std::endl;
2885  break;
2886  }
2887  }
2888 
2889  return !error;
2890 }
2891 
2892 //--------------------------------------------------------------------------
2893 // HandleTheoryEntry (private)
2894 //--------------------------------------------------------------------------
2904 {
2905  // If msr-file is used for musrFT only, nothing needs to be done here.
2906  if (fFourierOnly)
2907  return true;
2908 
2909  // store the theory lines
2910  fTheory = lines;
2911 
2912  return true;
2913 }
2914 
2915 //--------------------------------------------------------------------------
2916 // HandleFunctionsEntry (private)
2917 //--------------------------------------------------------------------------
2928 {
2929  // If msr-file is used for musrFT only, nothing needs to be done here.
2930  if (fFourierOnly)
2931  return true;
2932 
2933  // store the functions lines
2934  fFunctions = lines;
2935 
2936  // create function handler
2937  fFuncHandler = std::make_unique<PFunctionHandler>(fFunctions);
2938 
2939  // do the parsing
2940  if (!fFuncHandler->DoParse()) {
2941  return false;
2942  }
2943 
2944  // check if an empty FUNCTIONS block is present
2945  if ((fFuncHandler->GetNoOfFuncs() == 0) && !lines.empty()) {
2946  std::cerr << std::endl << ">> PMsrHandler::HandleFunctionsEntry: **WARNING** empty FUNCTIONS block found!";
2947  std::cerr << std::endl;
2948  }
2949 
2950  return true;
2951 }
2952 
2953 //--------------------------------------------------------------------------
2954 // HandleGlobalEntry (private)
2955 //--------------------------------------------------------------------------
2966 {
2967  PMsrLines::iterator iter;
2968  PMsrGlobalBlock global;
2969 
2970  Bool_t error = false;
2971 
2972  TString str;
2973  TObjArray *tokens = nullptr;
2974  TObjString *ostr = nullptr;
2975  Int_t ival = 0;
2976  Double_t dval = 0.0;
2977  UInt_t addT0Counter = 0;
2978 
2979  // since this routine is called, a GLOBAL block is present
2980  global.SetGlobalPresent(true);
2981 
2982  iter = lines.begin();
2983  while ((iter != lines.end()) && !error) {
2984  // remove potential comment at the end of lines
2985  str = iter->fLine;
2986  Ssiz_t idx = str.Index("#");
2987  if (idx != -1)
2988  str.Remove(idx);
2989 
2990  // tokenize line
2991  tokens = str.Tokenize(" \t");
2992  if (!tokens) {
2993  std::cerr << std::endl << ">> PMsrHandler::HandleGlobalEntry: **SEVERE ERROR** Couldn't tokenize line " << iter->fLineNo;
2994  std::cerr << std::endl << std::endl;
2995  return false;
2996  }
2997 
2998  if (iter->fLine.BeginsWith("fittype", TString::kIgnoreCase)) { // fittype
2999  if (tokens->GetEntries() < 2) {
3000  error = true;
3001  } else {
3002  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3003  str = ostr->GetString();
3004  if (str.IsDigit()) {
3005  Int_t fittype = str.Atoi();
3006  if ((fittype == MSR_FITTYPE_SINGLE_HISTO) ||
3007  (fittype == MSR_FITTYPE_SINGLE_HISTO_RRF) ||
3008  (fittype == MSR_FITTYPE_ASYM) ||
3009  (fittype == MSR_FITTYPE_ASYM_RRF) ||
3010  (fittype == MSR_FITTYPE_MU_MINUS) ||
3011  (fittype == MSR_FITTYPE_BNMR) ||
3012  (fittype == MSR_FITTYPE_NON_MUSR)) {
3013  global.SetFitType(fittype);
3014  } else {
3015  error = true;
3016  }
3017  } else {
3018  error = true;
3019  }
3020  }
3021  } else if (iter->fLine.BeginsWith("rrf_freq", TString::kIgnoreCase)) {
3022  if (tokens->GetEntries() < 3) {
3023  error = true;
3024  } else {
3025  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3026  str = ostr->GetString();
3027  if (str.IsFloat()) {
3028  dval = str.Atof();
3029  if (dval <= 0.0)
3030  error = true;
3031  }
3032  if (!error) {
3033  ostr = dynamic_cast<TObjString*>(tokens->At(2));
3034  str = ostr->GetString();
3035  global.SetRRFFreq(dval, str.Data());
3036  if (global.GetRRFFreq(str.Data()) == RRF_FREQ_UNDEF)
3037  error = true;
3038  }
3039  }
3040  } else if (iter->fLine.BeginsWith("rrf_packing", TString::kIgnoreCase)) {
3041  if (tokens->GetEntries() < 2) {
3042  error = true;
3043  } else {
3044  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3045  str = ostr->GetString();
3046  if (str.IsDigit()) {
3047  ival = str.Atoi();
3048  if (ival > 0) {
3049  global.SetRRFPacking(ival);
3050  } else {
3051  error = true;
3052  }
3053  } else {
3054  error = true;
3055  }
3056  }
3057  } else if (iter->fLine.BeginsWith("rrf_phase", TString::kIgnoreCase)) {
3058  if (tokens->GetEntries() < 2) {
3059  error = true;
3060  } else {
3061  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3062  str = ostr->GetString();
3063  if (str.IsFloat()) {
3064  dval = str.Atof();
3065  global.SetRRFPhase(dval);
3066  } else {
3067  error = true;
3068  }
3069  }
3070  } else if (iter->fLine.BeginsWith("data", TString::kIgnoreCase)) { // data
3071  if (tokens->GetEntries() < 3) {
3072  error = true;
3073  } else {
3074  for (Int_t i=1; i<tokens->GetEntries(); i++) {
3075  ostr = dynamic_cast<TObjString*>(tokens->At(i));
3076  str = ostr->GetString();
3077  if (str.IsDigit()) {
3078  ival = str.Atoi();
3079  if (ival >= 0) {
3080  global.SetDataRange(ival, i-1);
3081  } else {
3082  error = true;
3083  }
3084  } else {
3085  error = true;
3086  }
3087  }
3088  }
3089  } else if (iter->fLine.BeginsWith("t0", TString::kIgnoreCase)) { // t0
3090  if (tokens->GetEntries() < 2) {
3091  error = true;
3092  } else {
3093  for (Int_t i=1; i<tokens->GetEntries(); i++) {
3094  ostr = dynamic_cast<TObjString*>(tokens->At(i));
3095  str = ostr->GetString();
3096  if (str.IsFloat()) {
3097  dval = str.Atof();
3098  if (dval >= 0.0)
3099  global.SetT0Bin(dval);
3100  else
3101  error = true;
3102  } else {
3103  error = true;
3104  }
3105  }
3106  }
3107  } else if (iter->fLine.BeginsWith("addt0", TString::kIgnoreCase)) { // addt0
3108  if (tokens->GetEntries() < 2) {
3109  error = true;
3110  } else {
3111  for (Int_t i=1; i<tokens->GetEntries(); i++) {
3112  ostr = dynamic_cast<TObjString*>(tokens->At(i));
3113  str = ostr->GetString();
3114  if (str.IsFloat()) {
3115  dval = str.Atof();
3116  if (dval >= 0.0)
3117  global.SetAddT0Bin(dval, addT0Counter, i-1);
3118  else
3119  error = true;
3120  } else {
3121  error = true;
3122  }
3123  }
3124  }
3125  addT0Counter++;
3126  } else if (iter->fLine.BeginsWith("fit", TString::kIgnoreCase)) { // fit range
3127  if (tokens->GetEntries() < 3) {
3128  error = true;
3129  } else { // fit given in time, i.e. fit <start> <end>, where <start>, <end> are given as doubles
3130  if (iter->fLine.Contains("fgb", TString::kIgnoreCase)) { // fit given in bins, i.e. fit fgb+n0 lgb-n1
3131  // check 1st entry, i.e. fgb[+n0]
3132  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3133  str = ostr->GetString();
3134  Ssiz_t idx = str.First("+");
3135  TString numStr = str;
3136  if (idx > -1) { // '+' present hence extract n0
3137  numStr.Remove(0,idx+1);
3138  if (numStr.IsFloat()) {
3139  global.SetFitRangeOffset(numStr.Atoi(), 0);
3140  } else {
3141  error = true;
3142  }
3143  } else { // n0 == 0
3144  global.SetFitRangeOffset(0, 0);
3145  }
3146  // check 2nd entry, i.e. lgb[-n1]
3147  ostr = dynamic_cast<TObjString*>(tokens->At(2));
3148  str = ostr->GetString();
3149  idx = str.First("-");
3150  numStr = str;
3151  if (idx > -1) { // '-' present hence extract n1
3152  numStr.Remove(0,idx+1);
3153  if (numStr.IsFloat()) {
3154  global.SetFitRangeOffset(numStr.Atoi(), 1);
3155  } else {
3156  error = true;
3157  }
3158  } else { // n0 == 0
3159  global.SetFitRangeOffset(0, 0);
3160  }
3161  if (!error)
3162  global.SetFitRangeInBins(true);
3163  } else { // fit given in time, i.e. fit <start> <end>, where <start>, <end> are given as doubles
3164  for (Int_t i=1; i<3; i++) {
3165  ostr = dynamic_cast<TObjString*>(tokens->At(i));
3166  str = ostr->GetString();
3167  if (str.IsFloat())
3168  global.SetFitRange(str.Atof(), i-1);
3169  else
3170  error = true;
3171  }
3172  }
3173  }
3174  } else if (iter->fLine.BeginsWith("packing", TString::kIgnoreCase)) { // packing
3175  if (tokens->GetEntries() < 2) {
3176  error = true;
3177  } else {
3178  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3179  str = ostr->GetString();
3180  if (str.IsDigit()) {
3181  ival = str.Atoi();
3182  if (ival >= 0) {
3183  global.SetPacking(ival);
3184  } else {
3185  error = true;
3186  }
3187  } else {
3188  error = true;
3189  }
3190  }
3191  }
3192 
3193  // clean up
3194  if (tokens) {
3195  delete tokens;
3196  tokens = nullptr;
3197  }
3198 
3199  ++iter;
3200  }
3201 
3202  if (error) {
3203  --iter;
3204  std::cerr << std::endl << ">> PMsrHandler::HandleGlobalEntry: **ERROR** in line " << iter->fLineNo << ":";
3205  std::cerr << std::endl << ">> '" << iter->fLine.Data() << "'";
3206  std::cerr << std::endl << ">> GLOBAL block syntax is too complex to print it here. Please check the manual.";
3207  } else { // save global
3208  fGlobal = global;
3209  }
3210 
3211  return !error;
3212 }
3213 
3214 //--------------------------------------------------------------------------
3215 // HandleRunEntry (private)
3216 //--------------------------------------------------------------------------
3227 {
3228  PMsrLines::iterator iter;
3229  PMsrRunBlock param;
3230  Bool_t first = true; // first run line tag
3231  Bool_t error = false;
3232  Bool_t runLinePresent = false;
3233 
3234  TString str, line;
3235  TObjArray *tokens = nullptr;
3236  TObjString *ostr = nullptr;
3237 
3238  UInt_t addT0Counter = 0;
3239 
3240  Int_t ival;
3241  Double_t dval;
3242 
3243  iter = lines.begin();
3244  while ((iter != lines.end()) && !error) {
3245  // remove potential comment at the end of lines
3246  str = iter->fLine;
3247  Ssiz_t idx = str.Index("#");
3248  if (idx != -1)
3249  str.Remove(idx);
3250 
3251  // tokenize line
3252  tokens = str.Tokenize(" \t");
3253  if (!tokens) {
3254  std::cerr << std::endl << ">> PMsrHandler::HandleRunEntry: **SEVERE ERROR** Couldn't tokenize Parameters in line " << iter->fLineNo;
3255  std::cerr << std::endl << std::endl;
3256  return false;
3257  }
3258 
3259  // copy of the current line
3260  line = iter->fLine;
3261  // strip leading spaces from the begining
3262  line.Remove(TString::kLeading, ' ');
3263 
3264  // RUN line ----------------------------------------------
3265  if (line.BeginsWith("run", TString::kIgnoreCase)) {
3266 
3267  runLinePresent = true; // this is needed to make sure that a run line is present before and ADDRUN is following
3268 
3269  if (!first) { // not the first run in the list
3270  fRuns.push_back(param);
3271  param.CleanUp();
3272  } else {
3273  first = false;
3274  }
3275 
3276  // get run name, beamline, institute, and file-format
3277  if (tokens->GetEntries() < 5) {
3278  error = true;
3279  } else {
3280  // run name
3281  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3282  str = ostr->GetString();
3283  param.SetRunName(str);
3284  // beamline
3285  ostr = dynamic_cast<TObjString*>(tokens->At(2));
3286  str = ostr->GetString();
3287  param.SetBeamline(str);
3288  // institute
3289  ostr = dynamic_cast<TObjString*>(tokens->At(3));
3290  str = ostr->GetString();
3291  param.SetInstitute(str);
3292  // data file format
3293  ostr = dynamic_cast<TObjString*>(tokens->At(4));
3294  str = ostr->GetString();
3295  param.SetFileFormat(str);
3296  }
3297 
3298  addT0Counter = 0; // reset counter
3299  }
3300 
3301  // ADDRUN line ---------------------------------------------
3302  if (line.BeginsWith("addrun", TString::kIgnoreCase)) {
3303 
3304  if (!runLinePresent) {
3305  std::cerr << std::endl << ">> PMsrHandler::HandleRunEntry: **ERROR** Found ADDRUN without prior RUN, or";
3306  std::cerr << std::endl << ">> ADDRUN lines intercepted by other stuff. All this is not allowed!";
3307  std::cerr << std::endl << ">> error in line " << iter->fLineNo;
3308  std::cerr << std::endl;
3309  error = true;
3310  continue;
3311  }
3312 
3313  // get run name, beamline, institute, and file-format
3314  if (tokens->GetEntries() < 5) {
3315  error = true;
3316  } else {
3317  // run name
3318  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3319  str = ostr->GetString();
3320  param.SetRunName(str);
3321  // beamline
3322  ostr = dynamic_cast<TObjString*>(tokens->At(2));
3323  str = ostr->GetString();
3324  param.SetBeamline(str);
3325  // institute
3326  ostr = dynamic_cast<TObjString*>(tokens->At(3));
3327  str = ostr->GetString();
3328  param.SetInstitute(str);
3329  // data file format
3330  ostr = dynamic_cast<TObjString*>(tokens->At(4));
3331  str = ostr->GetString();
3332  param.SetFileFormat(str);
3333  }
3334  }
3335 
3336  // fittype -------------------------------------------------
3337  if (line.BeginsWith("fittype", TString::kIgnoreCase)) {
3338 
3339  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3340 
3341  if (tokens->GetEntries() < 2) {
3342  error = true;
3343  } else {
3344  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3345  str = ostr->GetString();
3346  if (str.IsDigit()) {
3347  Int_t fittype = str.Atoi();
3348  if ((fittype == MSR_FITTYPE_SINGLE_HISTO) ||
3349  (fittype == MSR_FITTYPE_SINGLE_HISTO_RRF) ||
3350  (fittype == MSR_FITTYPE_ASYM) ||
3351  (fittype == MSR_FITTYPE_ASYM_RRF) ||
3352  (fittype == MSR_FITTYPE_MU_MINUS) ||
3353  (fittype == MSR_FITTYPE_BNMR) ||
3354  (fittype == MSR_FITTYPE_NON_MUSR)) {
3355  param.SetFitType(fittype);
3356  } else {
3357  error = true;
3358  }
3359  } else {
3360  error = true;
3361  }
3362  }
3363  }
3364 
3365  // alpha -------------------------------------------------
3366  if (line.BeginsWith("alpha", TString::kIgnoreCase)) {
3367 
3368  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3369 
3370  if (tokens->GetEntries() < 2) {
3371  error = true;
3372  } else {
3373  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3374  str = ostr->GetString();
3375  if (str.IsDigit()) {
3376  ival = str.Atoi();
3377  if (ival > 0)
3378  param.SetAlphaParamNo(ival);
3379  else
3380  error = true;
3381  } else if (str.Contains("fun")) {
3382  Int_t no;
3383  if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, no))
3384  param.SetAlphaParamNo(no);
3385  else
3386  error = true;
3387  } else {
3388  error = true;
3389  }
3390  }
3391  }
3392 
3393  // beta -------------------------------------------------
3394  if (line.BeginsWith("beta", TString::kIgnoreCase)) {
3395 
3396  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3397 
3398  if (tokens->GetEntries() < 2) {
3399  error = true;
3400  } else {
3401  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3402  str = ostr->GetString();
3403  if (str.IsDigit()) {
3404  ival = str.Atoi();
3405  if (ival > 0)
3406  param.SetBetaParamNo(ival);
3407  else
3408  error = true;
3409  } else if (str.Contains("fun")) {
3410  Int_t no;
3411  if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, no))
3412  param.SetBetaParamNo(no);
3413  else
3414  error = true;
3415  } else {
3416  error = true;
3417  }
3418  }
3419  }
3420 
3421  // norm -------------------------------------------------
3422  if (line.BeginsWith("norm", TString::kIgnoreCase)) {
3423 
3424  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3425 
3426  if (tokens->GetEntries() < 2) {
3427  error = true;
3428  } else {
3429  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3430  str = ostr->GetString();
3431  if (str.IsDigit()) {
3432  param.SetNormParamNo(str.Atoi());
3433  } else if (str.Contains("fun")) {
3434  Int_t no;
3435  if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, no))
3436  param.SetNormParamNo(no);
3437  else
3438  error = true;
3439  } else {
3440  error = true;
3441  }
3442  }
3443  }
3444 
3445  // backgr.fit --------------------------------------------
3446  if (line.BeginsWith("backgr.fit", TString::kIgnoreCase)) {
3447 
3448  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3449 
3450  if (tokens->GetEntries() < 2) {
3451  error = true;
3452  } else {
3453  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3454  str = ostr->GetString();
3455  if (str.IsDigit()) {
3456  ival = str.Atoi();
3457  if (ival > 0)
3458  param.SetBkgFitParamNo(ival);
3459  else
3460  error = true;
3461  } else {
3462  error = true;
3463  }
3464  }
3465  }
3466 
3467  // lifetime ------------------------------------------------
3468  if (line.BeginsWith("lifetime ", TString::kIgnoreCase)) {
3469 
3470  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3471 
3472  if (tokens->GetEntries() < 2) {
3473  error = true;
3474  } else {
3475  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3476  str = ostr->GetString();
3477  if (str.IsDigit()) {
3478  ival = str.Atoi();
3479  if (ival > 0)
3480  param.SetLifetimeParamNo(ival);
3481  else
3482  error = true;
3483  } else {
3484  error = true;
3485  }
3486  }
3487  }
3488 
3489  // lifetimecorrection ---------------------------------------
3490  if (line.BeginsWith("lifetimecorrection", TString::kIgnoreCase)) {
3491 
3492  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3493 
3494  param.SetLifetimeCorrection(true);
3495  }
3496 
3497  // map ------------------------------------------------------
3498  if (line.BeginsWith("map", TString::kIgnoreCase)) {
3499 
3500  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3501 
3502  for (Int_t i=1; i<tokens->GetEntries(); i++) {
3503  ostr = dynamic_cast<TObjString*>(tokens->At(i));
3504  str = ostr->GetString();
3505  if (str.IsDigit()) {
3506  ival = str.Atoi();
3507  if (ival >= 0)
3508  param.SetMap(ival);
3509  else
3510  error = true;
3511  } else {
3512  error = true;
3513  }
3514  }
3515  // check map entries, i.e. if the map values are within parameter bounds
3516  if (!fFourierOnly) {
3517  for (UInt_t i=0; i<param.GetMap()->size(); i++) {
3518  if ((param.GetMap(i) < 0) || (param.GetMap(i) > static_cast<Int_t>(fParam.size()))) {
3519  std::cerr << std::endl << ">> PMsrHandler::HandleRunEntry: **SEVERE ERROR** map value " << param.GetMap(i) << " in line " << iter->fLineNo << " is out of range!";
3520  error = true;
3521  break;
3522  }
3523  }
3524  }
3525  }
3526 
3527  // forward ------------------------------------------------
3528  if (line.BeginsWith("forward", TString::kIgnoreCase)) {
3529 
3530  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3531 
3532  if (tokens->GetEntries() < 2) {
3533  error = true;
3534  } else {
3535  PUIntVector group;
3536  str = iter->fLine;
3537  std::unique_ptr<PStringNumberList> rl = std::make_unique<PStringNumberList>(str.Data());
3538  std::string errorMsg("");
3539  if (rl->Parse(errorMsg, true)) {
3540  group = rl->GetList();
3541  for (UInt_t i=0; i<group.size(); i++) {
3542  param.SetForwardHistoNo(group[i]);
3543  }
3544  } else {
3545  error = true;
3546  }
3547  group.clear();
3548  }
3549  }
3550 
3551  // backward -----------------------------------------------
3552  if (line.BeginsWith("backward", TString::kIgnoreCase)) {
3553 
3554  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3555 
3556  if (tokens->GetEntries() < 2) {
3557  error = true;
3558  } else {
3559  PUIntVector group;
3560  str = iter->fLine;
3561  std::unique_ptr<PStringNumberList> rl = std::make_unique<PStringNumberList>(str.Data());
3562  std::string errorMsg("");
3563  if (rl->Parse(errorMsg, true)) {
3564  group = rl->GetList();
3565  for (UInt_t i=0; i<group.size(); i++) {
3566  param.SetBackwardHistoNo(group[i]);
3567  }
3568  } else {
3569  error = true;
3570  }
3571  group.clear();
3572  }
3573  }
3574 
3575  // backgr.fix ----------------------------------------------
3576  if (line.BeginsWith("backgr.fix", TString::kIgnoreCase)) {
3577 
3578  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3579 
3580  if (tokens->GetEntries() < 2) {
3581  error = true;
3582  } else {
3583  for (Int_t i=1; i<tokens->GetEntries(); i++) {
3584  ostr = dynamic_cast<TObjString*>(tokens->At(i));
3585  str = ostr->GetString();
3586  if (str.IsFloat())
3587  param.SetBkgFix(str.Atof(), i-1);
3588  else
3589  error = true;
3590  }
3591  }
3592  }
3593 
3594  // background ---------------------------------------------
3595  if (line.BeginsWith("background", TString::kIgnoreCase)) {
3596 
3597  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3598 
3599  if ((tokens->GetEntries() < 3) || (tokens->GetEntries() % 2 != 1)) { // odd number (>=3) of entries needed
3600  error = true;
3601  } else {
3602  for (Int_t i=1; i<tokens->GetEntries(); i++) {
3603  ostr = dynamic_cast<TObjString*>(tokens->At(i));
3604  str = ostr->GetString();
3605  if (str.IsDigit()) {
3606  ival = str.Atoi();
3607  if (ival > 0)
3608  param.SetBkgRange(ival, i-1);
3609  else
3610  error = true;
3611  } else {
3612  error = true;
3613  }
3614  }
3615  }
3616  }
3617 
3618  // data --------------------------------------------------
3619  if (line.BeginsWith("data", TString::kIgnoreCase)) {
3620 
3621  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3622 
3623  if ((tokens->GetEntries() < 3) || (tokens->GetEntries() % 2 != 1)) { // odd number (>=3) of entries needed
3624  error = true;
3625  } else {
3626  for (Int_t i=1; i<tokens->GetEntries(); i++) {
3627  ostr = dynamic_cast<TObjString*>(tokens->At(i));
3628  str = ostr->GetString();
3629  if (str.IsDigit()) {
3630  ival = str.Atoi();
3631  if (ival > 0)
3632  param.SetDataRange(ival, i-1);
3633  else
3634  error = true;
3635  } else {
3636  error = true;
3637  }
3638  }
3639  }
3640  }
3641 
3642  // t0 -----------------------------------------------------
3643  if (line.BeginsWith("t0", TString::kIgnoreCase)) {
3644 
3645  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3646 
3647  if (tokens->GetEntries() < 2) {
3648  error = true;
3649  } else {
3650  for (Int_t i=1; i<tokens->GetEntries(); i++) {
3651  ostr = dynamic_cast<TObjString*>(tokens->At(i));
3652  str = ostr->GetString();
3653  if (str.IsFloat()) {
3654  dval = str.Atof();
3655  if (dval >= 0.0)
3656  param.SetT0Bin(dval);
3657  else
3658  error = true;
3659  } else {
3660  error = true;
3661  }
3662  }
3663  }
3664  }
3665 
3666  // addt0 -----------------------------------------------------
3667  if (line.BeginsWith("addt0", TString::kIgnoreCase)) {
3668 
3669  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3670 
3671  if (tokens->GetEntries() < 2) {
3672  error = true;
3673  } else {
3674  for (Int_t i=1; i<tokens->GetEntries(); i++) {
3675  ostr = dynamic_cast<TObjString*>(tokens->At(i));
3676  str = ostr->GetString();
3677  if (str.IsFloat()) {
3678  dval = str.Atof();
3679  if (dval >= 0.0)
3680  param.SetAddT0Bin(dval, addT0Counter, i-1);
3681  else
3682  error = true;
3683  } else {
3684  error = true;
3685  }
3686  }
3687  }
3688 
3689  addT0Counter++;
3690  }
3691 
3692  // fit -----------------------------------------------------
3693  if (line.BeginsWith("fit ", TString::kIgnoreCase)) {
3694 
3695  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3696 
3697  if (tokens->GetEntries() < 3) {
3698  error = true;
3699  } else {
3700  if (iter->fLine.Contains("fgb", TString::kIgnoreCase)) { // fit given in bins, i.e. fit fgb+n0 lgb-n1
3701  // check 1st entry, i.e. fgb[+n0]
3702  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3703  str = ostr->GetString();
3704  Ssiz_t idx = str.First("+");
3705  TString numStr = str;
3706  if (idx > -1) { // '+' present hence extract n0
3707  numStr.Remove(0,idx+1);
3708  if (numStr.IsFloat()) {
3709  param.SetFitRangeOffset(numStr.Atoi(), 0);
3710  } else {
3711  error = true;
3712  }
3713  } else { // n0 == 0
3714  param.SetFitRangeOffset(0, 0);
3715  }
3716  // check 2nd entry, i.e. lgb[-n1]
3717  ostr = dynamic_cast<TObjString*>(tokens->At(2));
3718  str = ostr->GetString();
3719  idx = str.First("-");
3720  numStr = str;
3721  if (idx > -1) { // '-' present hence extract n1
3722  numStr.Remove(0,idx+1);
3723  if (numStr.IsFloat()) {
3724  param.SetFitRangeOffset(numStr.Atoi(), 1);
3725  } else {
3726  error = true;
3727  }
3728  } else { // n0 == 0
3729  param.SetFitRangeOffset(0, 0);
3730  }
3731 
3732  if (!error)
3733  param.SetFitRangeInBins(true);
3734  } else { // fit given in time, i.e. fit <start> <end>, where <start>, <end> are given as doubles
3735  for (Int_t i=1; i<3; i++) {
3736  ostr = dynamic_cast<TObjString*>(tokens->At(i));
3737  str = ostr->GetString();
3738  if (str.IsFloat())
3739  param.SetFitRange(str.Atof(), i-1);
3740  else
3741  error = true;
3742  }
3743  }
3744  }
3745  }
3746 
3747  // packing --------------------------------------------------
3748  if (line.BeginsWith("packing", TString::kIgnoreCase)) {
3749 
3750  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3751 
3752  if (tokens->GetEntries() != 2) {
3753  error = true;
3754  } else {
3755  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3756  str = ostr->GetString();
3757  if (str.IsDigit()) {
3758  ival = str.Atoi();
3759  if (ival > 0)
3760  param.SetPacking(ival);
3761  else
3762  error = true;
3763  } else {
3764  error = true;
3765  }
3766  }
3767  }
3768 
3769  // xy-data -----------------------------------------------
3770  if (line.BeginsWith("xy-data", TString::kIgnoreCase)) {
3771 
3772  runLinePresent = false; // this is needed to make sure that a run line is present before and ADDRUN is following
3773 
3774  if (tokens->GetEntries() != 3) { // xy-data x-label y-label
3775  error = true;
3776  } else {
3777  ostr = dynamic_cast<TObjString*>(tokens->At(1));
3778  str = ostr->GetString();
3779  if (str.IsDigit()) { // xy-data indices given
3780  param.SetXDataIndex(str.Atoi()); // x-index
3781  ostr = dynamic_cast<TObjString*>(tokens->At(2));
3782  str = ostr->GetString();
3783  if (str.IsDigit()) {
3784  ival = str.Atoi();
3785  if (ival > 0)
3786  param.SetYDataIndex(ival); // y-index
3787  else
3788  error = true;
3789  } else {
3790  error = true;
3791  }
3792  } else { // xy-data labels given
3793  param.SetXDataLabel(str); // x-label
3794  ostr = dynamic_cast<TObjString*>(tokens->At(2));
3795  str = ostr->GetString();
3796  param.SetYDataLabel(str); // y-label
3797  }
3798  }
3799  }
3800 
3801  // clean up
3802  if (tokens) {
3803  delete tokens;
3804  tokens = nullptr;
3805  }
3806 
3807  ++iter;
3808  }
3809 
3810  if (error) {
3811  --iter;
3812  std::cerr << std::endl << ">> PMsrHandler::HandleRunEntry: **ERROR** in line " << iter->fLineNo << ":";
3813  std::cerr << std::endl << ">> " << iter->fLine.Data();
3814  std::cerr << std::endl << ">> RUN block syntax is too complex to print it here. Please check the manual.";
3815  } else { // save last run found
3816  fRuns.push_back(param);
3817  param.CleanUp();
3818  }
3819 
3820  return !error;
3821 }
3822 
3823 //--------------------------------------------------------------------------
3824 // FilterNumber (private)
3825 //--------------------------------------------------------------------------
3841 Bool_t PMsrHandler::FilterNumber(TString str, const Char_t *filter, Int_t offset, Int_t &no)
3842 {
3843  Int_t found, no_found=-1;
3844 
3845  // copy str to an ordinary c-like string
3846  Char_t *cstr, filterStr[32];
3847  cstr = new Char_t[str.Sizeof()];
3848  strncpy(cstr, str.Data(), str.Sizeof());
3849  snprintf(filterStr, sizeof(filterStr), "%s%%d", filter);
3850 
3851  // get number if present
3852  found = sscanf(cstr, filterStr, &no_found);
3853  if (found == 1)
3854  if (no_found < 1000)
3855  no = no_found + offset;
3856 
3857  // clean up
3858  if (cstr) {
3859  delete [] cstr;
3860  cstr = nullptr;
3861  }
3862 
3863  if ((no_found < 0) || (no_found > 1000))
3864  return false;
3865  else
3866  return true;
3867 }
3868 
3869 //--------------------------------------------------------------------------
3870 // HandleCommandsEntry (private)
3871 //--------------------------------------------------------------------------
3881 {
3882  // If msr-file is used for musrFT only, nothing needs to be done here.
3883  if (fFourierOnly)
3884  return true;
3885 
3886  PMsrLines::iterator iter;
3887 
3888  if (lines.empty()) {
3889  std::cerr << std::endl << ">> PMsrHandler::HandleCommandsEntry(): **WARNING**: There is no COMMAND block! Do you really want this?";
3890  std::cerr << std::endl;
3891  }
3892 
3893  for (iter = lines.begin(); iter != lines.end(); ++iter) {
3894  if (!iter->fLine.BeginsWith("COMMANDS"))
3895  fCommands.push_back(*iter);
3896  }
3897 
3898  return true;
3899 }
3900 
3901 //--------------------------------------------------------------------------
3902 // InitFourierParameterStructure (private)
3903 //--------------------------------------------------------------------------
3910 {
3911  fourier.fFourierBlockPresent = false; // fourier block present
3912  fourier.fUnits = FOURIER_UNIT_NOT_GIVEN; // fourier untis, default: NOT GIVEN
3913  fourier.fFourierPower = -1; // zero padding, default: -1 = NOT GIVEN
3914  fourier.fDCCorrected = false; // dc-corrected FFT, default: false
3915  fourier.fApodization = FOURIER_APOD_NOT_GIVEN; // apodization, default: NOT GIVEN
3916  fourier.fPlotTag = FOURIER_PLOT_NOT_GIVEN; // initial plot tag, default: NOT GIVEN
3917  fourier.fPhaseRef = -1; // initial phase reference -1 means: use absolute phases
3918  fourier.fPhaseParamNo.clear(); // initial phase parameter no vector is empty
3919  fourier.fPhase.clear(); // initial phase vector is empty
3920  for (UInt_t i=0; i<2; i++) {
3921  fourier.fRangeForPhaseCorrection[i] = -1.0; // frequency range for phase correction, default: {-1, -1} = NOT GIVEN
3922  fourier.fPlotRange[i] = -1.0; // fourier plot range, default: {-1, -1} = NOT GIVEN
3923  }
3924 }
3925 
3926 //--------------------------------------------------------------------------
3927 // RemoveComment (private)
3928 //--------------------------------------------------------------------------
3936 void PMsrHandler::RemoveComment(const TString &str, TString &truncStr)
3937 {
3938  truncStr = str;
3939  Ssiz_t idx = str.First('#'); // find the index of the comment character
3940 
3941  // truncate string if comment is found
3942  if (idx > 0) {
3943  truncStr.Resize(idx-1);
3944  }
3945 }
3946 
3947 //--------------------------------------------------------------------------
3948 // ParseFourierPhaseValueVector (private)
3949 //--------------------------------------------------------------------------
3961 Bool_t PMsrHandler::ParseFourierPhaseValueVector(PMsrFourierStructure &fourier, const TString &str, Bool_t &error)
3962 {
3963  Bool_t result = true;
3964 
3965  TObjArray *tok = str.Tokenize(" ,;\t");
3966  if (tok == nullptr) {
3967  std::cerr << std::endl << ">> PMsrHandler::ParseFourierPhaseValueVector: **ERROR** couldn't tokenize Fourier phase line." << std::endl << std::endl;
3968  return false;
3969  }
3970 
3971  // make sure there are enough tokens
3972  if (tok->GetEntries() < 2) {
3973  error = true;
3974  return false;
3975  }
3976 
3977  // convert all acceptable tokens
3978  TObjString *ostr = nullptr;
3979  TString sstr("");
3980  for (Int_t i=1; i<tok->GetEntries(); i++) {
3981  ostr = dynamic_cast<TObjString*>(tok->At(i));
3982  sstr = ostr->GetString();
3983  if (sstr.IsFloat()) {
3984  fourier.fPhase.push_back(sstr.Atof());
3985  } else {
3986  result = false;
3987  if (i>1) { // make sure that no 'phase val, parX' mixture is present
3988  std::cerr << std::endl << ">> PMsrHandler::ParseFourierPhaseValueVector: **ERROR** in Fourier phase line.";
3989  std::cerr << std::endl << ">> Attempt to mix val, parX? This is currently not supported." << std::endl << std::endl;
3990  error = true;
3991  }
3992  break;
3993  }
3994  }
3995 
3996  // clean up
3997  if (tok) {
3998  delete tok;
3999  }
4000 
4001  return result;
4002 }
4003 
4004 //--------------------------------------------------------------------------
4005 // ParseFourierPhaseParVector (private)
4006 //--------------------------------------------------------------------------
4020 Bool_t PMsrHandler::ParseFourierPhaseParVector(PMsrFourierStructure &fourier, const TString &str, Bool_t &error)
4021 {
4022  Bool_t result = true;
4023  Int_t refCount = 0;
4024 
4025  TObjArray *tok = str.Tokenize(" ,;\t");
4026  if (tok == nullptr) {
4027  std::cerr << std::endl << ">> PMsrHandler::ParseFourierPhaseParVector: **ERROR** couldn't tokenize Fourier phase line." << std::endl << std::endl;
4028  return false;
4029  }
4030 
4031  // make sure there are enough tokens
4032  if (tok->GetEntries() < 2) {
4033  error = true;
4034  return false;
4035  }
4036 
4037  // check that all tokens start with par
4038  TString sstr;
4039  for (Int_t i=1; i<tok->GetEntries(); i++) {
4040  TObjString *ostr = dynamic_cast<TObjString*>(tok->At(i));
4041  sstr = ostr->GetString();
4042  if (!sstr.BeginsWith("par")) {
4043  std::cerr << ">> PMsrHandler::ParseFourierPhaseParVector: **ERROR** found unhandable token '" << sstr << "'" << std::endl;
4044  error = true;
4045  result = false;
4046  break;
4047  }
4048 
4049  if (sstr.BeginsWith("parR")) {
4050  refCount++;
4051  }
4052 
4053  // rule out par(X, offset, #Param) syntax
4054  if (sstr.BeginsWith("par(")) {
4055  result = false;
4056  break;
4057  }
4058  }
4059 
4060  if (refCount > 1) {
4061  std::cerr << ">> PMsrHandler::ParseFourierPhaseParVector: **ERROR** found multiple parR's! Only one reference phase is accepted." << std::endl;
4062  result = false;
4063  }
4064 
4065  // check that token has the form parX, where X is an int
4066  Int_t rmNoOf = 3;
4067  if (result != false) {
4068  for (Int_t i=1; i<tok->GetEntries(); i++) {
4069  TObjString *ostr = dynamic_cast<TObjString*>(tok->At(i));
4070  sstr = ostr->GetString();
4071  rmNoOf = 3;
4072  if (sstr.BeginsWith("parR")) {
4073  rmNoOf++;
4074  }
4075  sstr.Remove(0, rmNoOf); // remove 'par' of 'parR' part. Rest should be an integer
4076  if (sstr.IsDigit()) {
4077  if (rmNoOf == 4) // parR
4078  fourier.fPhaseRef = sstr.Atoi();
4079  fourier.fPhaseParamNo.push_back(sstr.Atoi());
4080  } else {
4081  std::cerr << ">> PMsrHandler::ParseFourierPhaseParVector: **ERROR** found token '" << ostr->GetString() << "' which is not parX with X an integer." << std::endl;
4082  fourier.fPhaseParamNo.clear();
4083  error = true;
4084  break;
4085  }
4086  }
4087  }
4088 
4089  if (fourier.fPhaseParamNo.size() == tok->GetEntries()-1) { // everything as expected
4090  result = true;
4091  } else {
4092  result = false;
4093  }
4094 
4095  // clean up
4096  if (tok) {
4097  delete tok;
4098  }
4099 
4100  return result;
4101 }
4102 
4103 //--------------------------------------------------------------------------
4104 // ParseFourierPhaseParIterVector (private)
4105 //--------------------------------------------------------------------------
4117 Bool_t PMsrHandler::ParseFourierPhaseParIterVector(PMsrFourierStructure &fourier, const TString &str, Bool_t &error)
4118 {
4119  TString wstr = str;
4120 
4121  // remove 'phase' from string
4122  wstr.Remove(0, 5);
4123  wstr = wstr.Strip(TString::kLeading, ' ');
4124 
4125  // remove 'par(' from string if present, otherwise and error is issued
4126  if (!wstr.BeginsWith("par(") && !wstr.BeginsWith("parR(")) {
4127  std::cout << ">> PMsrHandler::ParseFourierPhaseParIterVector: **ERROR** token should start with 'par(' or 'parR(', found: '" << wstr << "' -> ERROR" << std::endl;
4128  error = true;
4129  return false;
4130  }
4131  Int_t noOf = 4; // number of characters to be removed
4132  Bool_t relativePhase = false; // relative phase handling wished
4133  if (wstr.BeginsWith("parR(")) {
4134  noOf += 1;
4135  relativePhase = true;
4136  }
4137  wstr.Remove(0, noOf);
4138 
4139  // remove trailing white spaces
4140  wstr = wstr.Strip(TString::kTrailing, ' ');
4141 
4142  // remove last ')'
4143  Ssiz_t idx=wstr.Last(')');
4144  wstr.Remove(idx, wstr.Length()-idx);
4145 
4146  // tokenize rest which should have the form 'X0, offset, #Param'
4147  TObjArray *tok = wstr.Tokenize(",;");
4148  if (tok == nullptr) {
4149  std::cerr << ">> PMsrHandler::ParseFourierPhaseParIterVector: **ERROR** tokenize failed." << std::endl;
4150  error = true;
4151  return false;
4152  }
4153 
4154  // check for proper number of expected elements
4155  if (tok->GetEntries() != 3) {
4156  std::cerr << ">> PMsrHandler::ParseFourierPhaseParIterVector: **ERROR** wrong syntax for the expected par(X0, offset, #param)." << std::endl;
4157  error = true;
4158  delete tok;
4159  return false;
4160  }
4161 
4162  Int_t x0, offset, noParam;
4163 
4164  // get X0
4165  TObjString *ostr = dynamic_cast<TObjString*>(tok->At(0));
4166  wstr = ostr->GetString();
4167  if (wstr.IsDigit()) {
4168  x0 = wstr.Atoi();
4169  } else {
4170  std::cerr << ">> PMsrHandler::ParseFourierPhaseParIterVector: **ERROR** X0='" << wstr << "' is not an integer." << std::endl;
4171  error = true;
4172  delete tok;
4173  return false;
4174  }
4175 
4176  // get offset
4177  ostr = dynamic_cast<TObjString*>(tok->At(1));
4178  wstr = ostr->GetString();
4179  if (wstr.IsDigit()) {
4180  offset = wstr.Atoi();
4181  } else {
4182  std::cerr << ">> PMsrHandler::ParseFourierPhaseParIterVector: **ERROR** offset='" << wstr << "' is not an integer." << std::endl;
4183  error = true;
4184  delete tok;
4185  return false;
4186  }
4187 
4188  // get noParam
4189  ostr = dynamic_cast<TObjString*>(tok->At(2));
4190  wstr = ostr->GetString();
4191  if (wstr.IsDigit()) {
4192  noParam = wstr.Atoi();
4193  } else {
4194  std::cerr << ">> PMsrHandler::ParseFourierPhaseParIterVector: **ERROR** #Param='" << wstr << "' is not an integer." << std::endl;
4195  error = true;
4196  delete tok;
4197  return false;
4198  }
4199 
4200  // set the reference phase parameter number for 'parR'
4201  if (relativePhase)
4202  fourier.fPhaseRef = x0;
4203  else
4204  fourier.fPhaseRef = -1;
4205 
4206  for (Int_t i=0; i<noParam; i++)
4207  fourier.fPhaseParamNo.push_back(x0 + i*offset);
4208 
4209  // clean up
4210  if (tok) {
4211  delete tok;
4212  }
4213 
4214  return true;
4215 }
4216 
4217 //--------------------------------------------------------------------------
4218 // HandleFourierEntry (private)
4219 //--------------------------------------------------------------------------
4230 {
4231  Bool_t error = false;
4232 
4233  if (lines.empty()) // no fourier block present
4234  return true;
4235 
4236  PMsrFourierStructure fourier;
4237 
4239 
4240  fourier.fFourierBlockPresent = true;
4241 
4242  PMsrLines::iterator iter;
4243 
4244  TObjArray *tokens = nullptr;
4245  TObjString *ostr = nullptr;
4246  TString str, pcStr=TString("");
4247 
4248  Int_t ival;
4249 
4250  iter = lines.begin();
4251  while ((iter != lines.end()) && !error) {
4252  // tokenize line
4253  tokens = iter->fLine.Tokenize(" \t");
4254  if (!tokens) {
4255  std::cerr << std::endl << ">> PMsrHandler::HandleFourierEntry: **SEVERE ERROR** Couldn't tokenize Parameters in line " << iter->fLineNo;
4256  std::cerr << std::endl << std::endl;
4257  return false;
4258  }
4259 
4260  if (iter->fLine.BeginsWith("units", TString::kIgnoreCase)) { // units
4261  if (tokens->GetEntries() < 2) { // units are missing
4262  error = true;
4263  continue;
4264  } else {
4265  ostr = dynamic_cast<TObjString*>(tokens->At(1));
4266  str = ostr->GetString();
4267  if (!str.CompareTo("gauss", TString::kIgnoreCase)) {
4268  fourier.fUnits = FOURIER_UNIT_GAUSS;
4269  } else if (!str.CompareTo("tesla", TString::kIgnoreCase)) {
4270  fourier.fUnits = FOURIER_UNIT_TESLA;
4271  } else if (!str.CompareTo("mhz", TString::kIgnoreCase)) {
4272  fourier.fUnits = FOURIER_UNIT_FREQ;
4273  } else if (!str.CompareTo("mc/s", TString::kIgnoreCase)) {
4274  fourier.fUnits = FOURIER_UNIT_CYCLES;
4275  } else {
4276  error = true;
4277  continue;
4278  }
4279  }
4280  } else if (iter->fLine.BeginsWith("fourier_power", TString::kIgnoreCase)) { // fourier power (zero padding)
4281  if (tokens->GetEntries() < 2) { // fourier power exponent is missing
4282  error = true;
4283  continue;
4284  } else {
4285  ostr = dynamic_cast<TObjString*>(tokens->At(1));
4286  str = ostr->GetString();
4287  if (str.IsDigit()) {
4288  ival = str.Atoi();
4289  if ((ival >= 0) && (ival <= 20)) {
4290  fourier.fFourierPower = ival;
4291  } else { // fourier power out of range
4292  error = true;
4293  continue;
4294  }
4295  } else { // fourier power not a number
4296  error = true;
4297  continue;
4298  }
4299  }
4300  } else if (iter->fLine.BeginsWith("dc-corrected", TString::kIgnoreCase)) { // dc-corrected
4301  if (tokens->GetEntries() < 2) { // dc-corrected tag is missing
4302  error = true;
4303  continue;
4304  } else {
4305  ostr = dynamic_cast<TObjString*>(tokens->At(1));
4306  str = ostr->GetString();
4307  if (!str.CompareTo("true", TString::kIgnoreCase) || !str.CompareTo("1")) {
4308  fourier.fDCCorrected = true;
4309  } else if (!str.CompareTo("false", TString::kIgnoreCase) || !str.CompareTo("0")) {
4310  fourier.fDCCorrected = false;
4311  } else { // unrecognized dc-corrected tag
4312  error = true;
4313  continue;
4314  }
4315  }
4316  } else if (iter->fLine.BeginsWith("apodization", TString::kIgnoreCase)) { // apodization
4317  if (tokens->GetEntries() < 2) { // apodization tag is missing
4318  error = true;
4319  continue;
4320  } else {
4321  ostr = dynamic_cast<TObjString*>(tokens->At(1));
4322  str = ostr->GetString();
4323  if (!str.CompareTo("none", TString::kIgnoreCase)) {
4324  fourier.fApodization = FOURIER_APOD_NONE;
4325  } else if (!str.CompareTo("weak", TString::kIgnoreCase)) {
4326  fourier.fApodization = FOURIER_APOD_WEAK;
4327  } else if (!str.CompareTo("medium", TString::kIgnoreCase)) {
4329  } else if (!str.CompareTo("strong", TString::kIgnoreCase)) {
4331  } else { // unrecognized apodization tag
4332  error = true;
4333  continue;
4334  }
4335  }
4336  } else if (iter->fLine.BeginsWith("plot", TString::kIgnoreCase)) { // plot tag
4337  if (tokens->GetEntries() < 2) { // plot tag is missing
4338  error = true;
4339  continue;
4340  } else {
4341  ostr = dynamic_cast<TObjString*>(tokens->At(1));
4342  str = ostr->GetString();
4343  if (!str.CompareTo("real", TString::kIgnoreCase)) {
4344  fourier.fPlotTag = FOURIER_PLOT_REAL;
4345  } else if (!str.CompareTo("imag", TString::kIgnoreCase)) {
4346  fourier.fPlotTag = FOURIER_PLOT_IMAG;
4347  } else if (!str.CompareTo("real_and_imag", TString::kIgnoreCase)) {
4349  } else if (!str.CompareTo("power", TString::kIgnoreCase)) {
4350  fourier.fPlotTag = FOURIER_PLOT_POWER;
4351  } else if (!str.CompareTo("phase", TString::kIgnoreCase)) {
4352  fourier.fPlotTag = FOURIER_PLOT_PHASE;
4353  } else if (!str.CompareTo("phase_opt_real", TString::kIgnoreCase)) {
4355  } else { // unrecognized plot tag
4356  error = true;
4357  continue;
4358  }
4359  }
4360  } else if (iter->fLine.BeginsWith("phase", TString::kIgnoreCase)) { // phase
4361  if (tokens->GetEntries() < 2) { // phase value(s)/par(s) is(are) missing
4362  error = true;
4363  continue;
4364  } else {
4365  // allowed phase parameter patterns:
4366  // (i) phase val [sep val sep val ...] [# comment], val=double, sep=' ,;\t'
4367  // (ii) phase parX0 [sep parX1 sep parX2 ...] [# comment], val=double, sep=' ,;\t'
4368  // (iii) phase par(X0 sep1 offset sep1 #param) [# comment], sep1= ',;'
4369 
4370  // remove potential comment
4371  TString wstr("");
4372  RemoveComment(iter->fLine, wstr);
4373 
4374  // check for 'phase val ...'
4375  Bool_t result = ParseFourierPhaseValueVector(fourier, wstr, error);
4376  if (error)
4377  continue;
4378 
4379  // check for 'phase parX0 ...' if not already val are found
4380  if (!result) {
4381  result = ParseFourierPhaseParVector(fourier, wstr, error);
4382  if (error)
4383  continue;
4384  }
4385 
4386  // check for 'phase par(X0, offset, #param)' if not already covered by the previous ones
4387  if (!result) {
4388  result = ParseFourierPhaseParIterVector(fourier, wstr, error);
4389  }
4390 
4391  if (!result || error) {
4392  continue;
4393  }
4394 
4395  // if parameter vector is given: check that all parameters are within range
4396  if (fourier.fPhaseParamNo.size() > 0) {
4397  for (UInt_t i=0; i<fourier.fPhaseParamNo.size(); i++) {
4398  if (fourier.fPhaseParamNo[i] > fParam.size()) {
4399  std::cerr << ">> PMsrHandler::HandleFourierEntry: found Fourier parameter entry par" << fourier.fPhaseParamNo[i] << " > #Param = " << fParam.size() << std::endl;
4400  error = true;
4401  --iter;
4402  continue;
4403  }
4404  }
4405  }
4406 
4407  // if parameter vector is given -> fill corresponding phase values
4408  Double_t phaseRef = 0.0;
4409  if (fourier.fPhaseParamNo.size() > 0) {
4410  // check if a relative parameter phase number is set
4411  if (fourier.fPhaseRef != -1) {
4412  phaseRef = fParam[fourier.fPhaseRef-1].fValue;
4413  }
4414  fourier.fPhase.clear();
4415  for (UInt_t i=0; i<fourier.fPhaseParamNo.size(); i++) {
4416  if (fourier.fPhaseRef == fourier.fPhaseParamNo[i]) // reference phase
4417  fourier.fPhase.push_back(fParam[fourier.fPhaseParamNo[i]-1].fValue);
4418  else
4419  fourier.fPhase.push_back(fParam[fourier.fPhaseParamNo[i]-1].fValue+phaseRef);
4420  }
4421  }
4422  }
4423  } else if (iter->fLine.BeginsWith("range_for_phase_correction", TString::kIgnoreCase)) {
4424  // keep the string. It can only be handled at the very end of the FOURIER block evaluation
4425  // since it needs potentially the range input and there is no guaranty this is already
4426  // available at this point.
4427  pcStr = iter->fLine;
4428  } else if (iter->fLine.BeginsWith("range", TString::kIgnoreCase)) { // fourier plot range
4429  if (tokens->GetEntries() < 3) { // plot range values are missing
4430  error = true;
4431  continue;
4432  } else {
4433  for (UInt_t i=0; i<2; i++) {
4434  ostr = dynamic_cast<TObjString*>(tokens->At(i+1));
4435  str = ostr->GetString();
4436  if (str.IsFloat()) {
4437  fourier.fPlotRange[i] = str.Atof();
4438  } else {
4439  error = true;
4440  continue;
4441  }
4442  }
4443  }
4444  } else if (!iter->fLine.BeginsWith("fourier", TString::kIgnoreCase) && !iter->fLine.BeginsWith("#") &&
4445  !iter->fLine.IsWhitespace() && (iter->fLine.Length() != 0)) { // make
4446  error = true;
4447  continue;
4448  }
4449 
4450  // clean up
4451  if (tokens) {
4452  delete tokens;
4453  tokens = nullptr;
4454  }
4455 
4456  ++iter;
4457  }
4458 
4459  // clean up after error
4460  if (tokens) {
4461  delete tokens;
4462  tokens = nullptr;
4463  }
4464 
4465  // handle range_for_phase_correction if present
4466  if ((pcStr.Length() != 0) && !error) {
4467  // tokenize line
4468  tokens = pcStr.Tokenize(" \t");
4469 
4470  switch (tokens->GetEntries()) {
4471  case 2:
4472  ostr = dynamic_cast<TObjString*>(tokens->At(1));
4473  str = ostr->GetString();
4474  if (!str.CompareTo("all", TString::kIgnoreCase)) {
4475  fourier.fRangeForPhaseCorrection[0] = fourier.fPlotRange[0];
4476  fourier.fRangeForPhaseCorrection[1] = fourier.fPlotRange[1];
4477  } else {
4478  error = true;
4479  }
4480  break;
4481  case 3:
4482  for (UInt_t i=0; i<2; i++) {
4483  ostr = dynamic_cast<TObjString*>(tokens->At(i+1));
4484  str = ostr->GetString();
4485  if (str.IsFloat()) {
4486  fourier.fRangeForPhaseCorrection[i] = str.Atof();
4487  } else {
4488  error = true;
4489  }
4490  }
4491  break;
4492  default:
4493  error = true;
4494  break;
4495  }
4496 
4497  // clean up
4498  if (tokens) {
4499  delete tokens;
4500  tokens = nullptr;
4501  }
4502  }
4503 
4504  if (error) {
4505  std::cerr << std::endl << ">> PMsrHandler::HandleFourierEntry: **ERROR** in line " << iter->fLineNo << ":";
4506  std::cerr << std::endl;
4507  std::cerr << std::endl << ">> " << iter->fLine.Data();
4508  std::cerr << std::endl;
4509  std::cerr << std::endl << ">> FOURIER block syntax, parameters in [] are optinal:";
4510  std::cerr << std::endl;
4511  std::cerr << std::endl << ">> FOURIER";
4512  std::cerr << std::endl << ">> [units Gauss | MHz | Mc/s]";
4513  std::cerr << std::endl << ">> [fourier_power n # n is a number such that zero padding up to 2^n will be used]";
4514  std::cerr << std::endl << ">> n=0 means no zero padding";
4515  std::cerr << std::endl << ">> 0 <= n <= 20 are allowed values";
4516  std::cerr << std::endl << ">> [dc-corrected true | false]";
4517  std::cerr << std::endl << ">> [apodization none | weak | medium | strong]";
4518  std::cerr << std::endl << ">> [plot real | imag | real_and_imag | power | phase | phase_opt_real]";
4519  std::cerr << std::endl << ">> [phase valList | parList | parIterList [# comment]]";
4520  std::cerr << std::endl << ">> valList : val [sep val ... sep val]. sep=' ,;\\t'";
4521  std::cerr << std::endl << ">> parList : parX0 [sep parX1 ... sep parX1]";
4522  std::cerr << std::endl << ">> parIterList : par(X0,offset,#param), with X0=first parameter number";
4523  std::cerr << std::endl << ">> offset=parameter offset, #param=number of phase parameters.";
4524  std::cerr << std::endl << ">> [range_for_phase_correction min max | all]";
4525  std::cerr << std::endl << ">> [range min max]";
4526  std::cerr << std::endl;
4527  } else { // save last run found
4528  fFourier = fourier;
4529  }
4530 
4531  return !error;
4532 }
4533 
4534 //--------------------------------------------------------------------------
4535 // HandlePlotEntry (private)
4536 //--------------------------------------------------------------------------
4547 {
4548  Bool_t error = false;
4549 
4550  PMsrPlotStructure param;
4551 
4552  PMsrLines::iterator iter1;
4553  PMsrLines::iterator iter2;
4554  TObjArray *tokens = nullptr;
4555  TObjString *ostr = nullptr;
4556  TString str;
4557 
4558  if (lines.empty()) {
4559  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry(): **WARNING**: There is no PLOT block! Do you really want this?";
4560  std::cerr << std::endl;
4561  }
4562 
4563  iter1 = lines.begin();
4564  while ((iter1 != lines.end()) && !error) {
4565 
4566  // initialize param structure
4567  param.fPlotType = -1;
4568  param.fLifeTimeCorrection = false;
4569  param.fUseFitRanges = false; // i.e. if not overwritten use the range info of the plot block
4570  param.fLogX = false; // i.e. if not overwritten use linear x-axis
4571  param.fLogY = false; // i.e. if not overwritten use linear y-axis
4572  param.fViewPacking = -1; // i.e. if not overwritten use the packing of the run blocks
4573  param.fRuns.clear();
4574  param.fTmin.clear();
4575  param.fTmax.clear();
4576  param.fYmin.clear();
4577  param.fYmax.clear();
4578  param.fRRFPacking = 0; // i.e. if not overwritten it will not be a valid RRF
4579  param.fRRFFreq = 0.0; // i.e. no RRF whished
4580  param.fRRFUnit = RRF_UNIT_MHz;
4581  param.fRRFPhaseParamNo = 0; // initial parameter no = 0 means not a parameter
4582  param.fRRFPhase = 0.0;
4583 
4584  // find next plot if any is present
4585  iter2 = iter1;
4586  ++iter2;
4587  for ( ; iter2 != lines.end(); ++iter2) {
4588  if (iter2->fLine.Contains("PLOT"))
4589  break;
4590  }
4591 
4592  // handle a single PLOT block
4593  while ((iter1 != iter2) && !error) {
4594  TString line = iter1->fLine;
4595  if (line.First('#') != -1) // remove trailing comment before proceed
4596  line.Resize(line.First('#'));
4597 
4598  if (line.Contains("PLOT")) { // handle plot header
4599  tokens = line.Tokenize(" \t");
4600  if (!tokens) {
4601  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize PLOT in line " << iter1->fLineNo;
4602  std::cerr << std::endl << std::endl;
4603  return false;
4604  }
4605  if (tokens->GetEntries() < 2) { // plot type missing
4606  error = true;
4607  } else {
4608  ostr = dynamic_cast<TObjString*>(tokens->At(1));
4609  str = ostr->GetString();
4610  if (str.IsDigit())
4611  param.fPlotType = str.Atoi();
4612  else
4613  error = true;
4614  }
4615  // clean up
4616  if (tokens) {
4617  delete tokens;
4618  tokens = nullptr;
4619  }
4620  } else if (line.Contains("lifetimecorrection", TString::kIgnoreCase)) {
4621  param.fLifeTimeCorrection = true;
4622  } else if (line.Contains("runs", TString::kIgnoreCase)) { // handle plot runs
4623  TComplex run;
4624  std::unique_ptr<PStringNumberList> rl;
4625  std::string errorMsg;
4626  PUIntVector runList;
4627  switch (param.fPlotType) {
4628  case -1:
4629  error = true;
4630  break;
4631  case MSR_PLOT_SINGLE_HISTO: // like: runs 1 5 13
4633  case MSR_PLOT_ASYM:
4634  case MSR_PLOT_BNMR:
4635  case MSR_PLOT_ASYM_RRF:
4636  case MSR_PLOT_NON_MUSR:
4637  case MSR_PLOT_MU_MINUS:
4638  rl = std::make_unique<PStringNumberList>(line.Data());
4639  if (!rl->Parse(errorMsg, true)) {
4640  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize PLOT in line " << iter1->fLineNo;
4641  std::cerr << std::endl << ">> Error Message: " << errorMsg;
4642  std::cerr << std::endl << std::endl;
4643  return false;
4644  }
4645  runList = rl->GetList();
4646  for (UInt_t i=0; i<runList.size(); i++) {
4647  run = TComplex(runList[i], -1.0);
4648  param.fRuns.push_back(run);
4649  }
4650  // clean up
4651  runList.clear();
4652  break;
4653  default:
4654  error = true;
4655  break;
4656  }
4657  } else if (line.Contains("range ", TString::kIgnoreCase)) { // handle plot range
4658  // remove previous entries
4659  param.fTmin.clear();
4660  param.fTmax.clear();
4661  param.fYmin.clear();
4662  param.fYmax.clear();
4663 
4664  tokens = line.Tokenize(" \t");
4665  if (!tokens) {
4666  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize PLOT in line " << iter1->fLineNo;
4667  std::cerr << std::endl << std::endl;
4668  return false;
4669  }
4670  if ((tokens->GetEntries() != 3) && (tokens->GetEntries() != 5)) {
4671  error = true;
4672  } else {
4673 
4674  // handle t_min
4675  ostr = dynamic_cast<TObjString*>(tokens->At(1));
4676  str = ostr->GetString();
4677  if (str.IsFloat())
4678  param.fTmin.push_back(static_cast<Double_t>(str.Atof()));
4679  else
4680  error = true;
4681 
4682  // handle t_max
4683  ostr = dynamic_cast<TObjString*>(tokens->At(2));
4684  str = ostr->GetString();
4685  if (str.IsFloat())
4686  param.fTmax.push_back(static_cast<Double_t>(str.Atof()));
4687  else
4688  error = true;
4689 
4690  if (tokens->GetEntries() == 5) { // y-axis interval given as well
4691 
4692  // handle y_min
4693  ostr = dynamic_cast<TObjString*>(tokens->At(3));
4694  str = ostr->GetString();
4695  if (str.IsFloat())
4696  param.fYmin.push_back(static_cast<Double_t>(str.Atof()));
4697  else
4698  error = true;
4699 
4700  // handle y_max
4701  ostr = dynamic_cast<TObjString*>(tokens->At(4));
4702  str = ostr->GetString();
4703  if (str.IsFloat())
4704  param.fYmax.push_back(static_cast<Double_t>(str.Atof()));
4705  else
4706  error = true;
4707  }
4708  }
4709  // clean up
4710  if (tokens) {
4711  delete tokens;
4712  tokens = nullptr;
4713  }
4714  } else if (line.Contains("sub_ranges", TString::kIgnoreCase)) {
4715  // remove previous entries
4716  param.fTmin.clear();
4717  param.fTmax.clear();
4718  param.fYmin.clear();
4719  param.fYmax.clear();
4720 
4721  tokens = line.Tokenize(" \t");
4722  if (!tokens) {
4723  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize PLOT in line " << iter1->fLineNo;
4724  std::cerr << std::endl << std::endl;
4725  return false;
4726  }
4727  if ((tokens->GetEntries() != static_cast<Int_t>(2*param.fRuns.size() + 1)) && (tokens->GetEntries() != static_cast<Int_t>(2*param.fRuns.size() + 3))) {
4728  error = true;
4729  } else {
4730  // get all the times
4731  for (UInt_t i=0; i<param.fRuns.size(); i++) {
4732 
4733  // handle t_min
4734  ostr = dynamic_cast<TObjString*>(tokens->At(2*i+1));
4735  str = ostr->GetString();
4736  if (str.IsFloat())
4737  param.fTmin.push_back(static_cast<Double_t>(str.Atof()));
4738  else
4739  error = true;
4740 
4741  // handle t_max
4742  ostr = dynamic_cast<TObjString*>(tokens->At(2*i+2));
4743  str = ostr->GetString();
4744  if (str.IsFloat())
4745  param.fTmax.push_back(static_cast<Double_t>(str.Atof()));
4746  else
4747  error = true;
4748  }
4749 
4750  // get y-range if present
4751  if (tokens->GetEntries() == static_cast<Int_t>(2*param.fRuns.size() + 3)) {
4752 
4753  // handle y_min
4754  ostr = dynamic_cast<TObjString*>(tokens->At(2*param.fRuns.size()+1));
4755  str = ostr->GetString();
4756  if (str.IsFloat())
4757  param.fYmin.push_back(static_cast<Double_t>(str.Atof()));
4758  else
4759  error = true;
4760 
4761  // handle y_max
4762  ostr = dynamic_cast<TObjString*>(tokens->At(2*param.fRuns.size()+2));
4763  str = ostr->GetString();
4764  if (str.IsFloat())
4765  param.fYmax.push_back(static_cast<Double_t>(str.Atof()));
4766  else
4767  error = true;
4768  }
4769  }
4770 
4771  // clean up
4772  if (tokens) {
4773  delete tokens;
4774  tokens = nullptr;
4775  }
4776  } else if (line.Contains("use_fit_ranges", TString::kIgnoreCase)) {
4777  param.fUseFitRanges = true;
4778  // check if y-ranges are given
4779 
4780  tokens = line.Tokenize(" \t");
4781  if (!tokens) {
4782  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize PLOT in line " << iter1->fLineNo;
4783  std::cerr << std::endl << std::endl;
4784  return false;
4785  }
4786 
4787  if (tokens->GetEntries() == 3) { // i.e. use_fit_ranges ymin ymax
4788  // handle y_min
4789  ostr = dynamic_cast<TObjString*>(tokens->At(1));
4790  str = ostr->GetString();
4791  if (str.IsFloat())
4792  param.fYmin.push_back(static_cast<Double_t>(str.Atof()));
4793  else
4794  error = true;
4795 
4796  // handle y_max
4797  ostr = dynamic_cast<TObjString*>(tokens->At(2));
4798  str = ostr->GetString();
4799  if (str.IsFloat())
4800  param.fYmax.push_back(static_cast<Double_t>(str.Atof()));
4801  else
4802  error = true;
4803  }
4804 
4805  if ((tokens->GetEntries() != 1) && (tokens->GetEntries() != 3)) {
4806  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **WARNING** use_fit_ranges with undefined additional parameters in line " << iter1->fLineNo;
4807  std::cerr << std::endl << ">> Will ignore this PLOT block command line, sorry.";
4808  std::cerr << std::endl << ">> Proper syntax: use_fit_ranges [ymin ymax]";
4809  std::cerr << std::endl << ">> Found: '" << iter1->fLine.Data() << "'" << std::endl;
4810  }
4811 
4812  // clean up
4813  if (tokens) {
4814  delete tokens;
4815  tokens = nullptr;
4816  }
4817  } else if (iter1->fLine.Contains("logx", TString::kIgnoreCase)) {
4818  param.fLogX = true;
4819  } else if (iter1->fLine.Contains("logy", TString::kIgnoreCase)) {
4820  param.fLogY = true;
4821  } else if (iter1->fLine.Contains("lifetimecorrection", TString::kIgnoreCase)) {
4822  param.fLifeTimeCorrection = true;
4823  } else if (iter1->fLine.Contains("view_packing", TString::kIgnoreCase)) {
4824  tokens = iter1->fLine.Tokenize(" \t");
4825  if (!tokens) {
4826  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize view_packing in line " << iter1->fLineNo;
4827  std::cerr << std::endl << std::endl;
4828  return false;
4829  }
4830  if (tokens->GetEntries() != 2) {
4831  error = true;
4832  } else {
4833  ostr = dynamic_cast<TObjString*>(tokens->At(1));
4834  str = ostr->GetString();
4835  if (str.IsDigit()) {
4836  Int_t val = str.Atoi();
4837  if (val > 0)
4838  param.fViewPacking = val;
4839  else
4840  error = true;
4841  } else {
4842  error = true;
4843  }
4844  }
4845 
4846  // clean up
4847  if (tokens) {
4848  delete tokens;
4849  tokens = nullptr;
4850  }
4851  } else if (iter1->fLine.Contains("rrf_freq", TString::kIgnoreCase)) {
4852  // expected entry: rrf_freq value unit
4853  // allowed units: kHz, MHz, Mc/s, G, T
4854  tokens = iter1->fLine.Tokenize(" \t");
4855  if (!tokens) {
4856  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize rrf_freq in line " << iter1->fLineNo;
4857  std::cerr << std::endl << std::endl;
4858  return false;
4859  }
4860  if (tokens->GetEntries() != 3) {
4861  error = true;
4862  } else {
4863  // get rrf frequency
4864  ostr = dynamic_cast<TObjString*>(tokens->At(1));
4865  str = ostr->GetString();
4866  if (str.IsFloat()) {
4867  param.fRRFFreq = str.Atof();
4868  } else {
4869  error = true;
4870  }
4871  // get unit
4872  ostr = dynamic_cast<TObjString*>(tokens->At(2));
4873  str = ostr->GetString();
4874  if (str.Contains("kHz", TString::kIgnoreCase))
4875  param.fRRFUnit = RRF_UNIT_kHz;
4876  else if (str.Contains("MHz", TString::kIgnoreCase))
4877  param.fRRFUnit = RRF_UNIT_MHz;
4878  else if (str.Contains("Mc/s", TString::kIgnoreCase))
4879  param.fRRFUnit = RRF_UNIT_Mcs;
4880  else if (str.Contains("G", TString::kIgnoreCase))
4881  param.fRRFUnit = RRF_UNIT_G;
4882  else if (str.Contains("T", TString::kIgnoreCase))
4883  param.fRRFUnit = RRF_UNIT_T;
4884  else
4885  error = true;
4886  }
4887  // clean up
4888  if (tokens) {
4889  delete tokens;
4890  tokens = nullptr;
4891  }
4892  } else if (iter1->fLine.Contains("rrf_phase", TString::kIgnoreCase)) {
4893  // expected entry: rrf_phase value. value given in units of degree. or
4894  // rrf_phase parX. where X is the parameter number, e.g. par3
4895  tokens = iter1->fLine.Tokenize(" \t");
4896  if (!tokens) {
4897  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize rrf_phase in line " << iter1->fLineNo;
4898  std::cerr << std::endl << std::endl;
4899  return false;
4900  }
4901  if (tokens->GetEntries() != 2) {
4902  error = true;
4903  } else {
4904  // get rrf phase
4905  ostr = dynamic_cast<TObjString*>(tokens->At(1));
4906  str = ostr->GetString();
4907  if (str.IsFloat()) {
4908  param.fRRFPhase = str.Atof();
4909  } else {
4910  if (str.BeginsWith("par", TString::kIgnoreCase)) { // parameter value
4911  Int_t no = 0;
4912  if (FilterNumber(str, "par", 0, no)) {
4913  // check that the parameter is in range
4914  if (static_cast<Int_t>(fParam.size()) < no) {
4915  error = true;
4916  } else {
4917  // keep the parameter number in case parX was used
4918  param.fRRFPhaseParamNo = no;
4919  // get parameter value
4920  param.fRRFPhase = fParam[no-1].fValue;
4921  }
4922  }
4923  } else {
4924  error = true;
4925  }
4926  }
4927  }
4928  // clean up
4929  if (tokens) {
4930  delete tokens;
4931  tokens = nullptr;
4932  }
4933  } else if (iter1->fLine.Contains("rrf_packing", TString::kIgnoreCase)) {
4934  // expected entry: rrf_phase value. value given in units of degree
4935  tokens = iter1->fLine.Tokenize(" \t");
4936  if (!tokens) {
4937  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **SEVERE ERROR** Couldn't tokenize rrf_packing in line " << iter1->fLineNo;
4938  std::cerr << std::endl << std::endl;
4939  return false;
4940  }
4941  if (tokens->GetEntries() != 2) {
4942  error = true;
4943  } else {
4944  // get rrf packing
4945  ostr = dynamic_cast<TObjString*>(tokens->At(1));
4946  str = ostr->GetString();
4947  if (str.IsDigit()) {
4948  param.fRRFPacking = str.Atoi();
4949  } else {
4950  error = true;
4951  }
4952  }
4953  // clean up
4954  if (tokens) {
4955  delete tokens;
4956  tokens = nullptr;
4957  }
4958  } else {
4959  error = true;
4960  }
4961 
4962  ++iter1;
4963 
4964  }
4965 
4966  // analyze if the plot block is valid
4967  Double_t keep;
4968  if (!error) {
4969  if (param.fRuns.empty()) { // there was no run tag
4970  error = true;
4971  } else { // everything ok
4972  if ((param.fTmin.size() > 0) || (param.fTmax.size() > 0)) { // if range is given, check that it is ordered properly
4973  for (UInt_t i=0; i<param.fTmin.size(); i++) {
4974  if (param.fTmin[i] > param.fTmax[i]) {
4975  keep = param.fTmin[i];
4976  param.fTmin[i] = param.fTmax[i];
4977  param.fTmax[i] = keep;
4978  }
4979  }
4980  }
4981 
4982  if ((param.fYmin.size() > 0) || (param.fYmax.size() > 0)) { // if range is given, check that it is ordered properly
4983  for (UInt_t i=0; i<param.fYmin.size(); i++) {
4984  if (param.fYmin[i] > param.fYmax[i]) {
4985  keep = param.fYmin[i];
4986  param.fYmin[i] = param.fYmax[i];
4987  param.fYmax[i] = keep;
4988  }
4989  }
4990  }
4991 
4992  // check RRF entries
4993  if (param.fRRFFreq != 0.0) {
4994  if (param.fRRFPacking == 0) {
4995  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry(): **ERROR** found RRF frequency but no required RRF packing.";
4996  std::cerr << std::endl << ">> Will ignore the RRF option.";
4997  std::cerr << std::endl;
4998  param.fRRFFreq = 0.0;
4999  }
5000  }
5001 
5002  // check if runs listed in the plot block indeed to exist
5003  for (UInt_t i=0; i<param.fRuns.size(); i++) {
5004  if (param.fRuns[i] > static_cast<Int_t>(fRuns.size())) {
5005  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry(): **WARNING** found plot run number " << param.fRuns[i] << ".";
5006  std::cerr << std::endl << ">> There are only " << fRuns.size() << " runs present, will ignore this run.";
5007  std::cerr << std::endl;
5008  param.fRuns.erase(param.fRuns.begin()+i);
5009  i--;
5010  }
5011  if (param.fRuns[i] == 0) {
5012  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry(): **WARNING** found plot run number 0.";
5013  std::cerr << std::endl << ">> Pot number needs to be > 0. Will ignore this entry.";
5014  std::cerr << std::endl;
5015  param.fRuns.erase(param.fRuns.begin()+i);
5016  i--;
5017  }
5018  }
5019 
5020  if (param.fRuns.size() > 0) {
5021  fPlots.push_back(param);
5022  } else {
5023  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **ERROR** no valid PLOT block entries, will ignore the entire PLOT block.";
5024  std::cerr << std::endl;
5025  }
5026  }
5027  }
5028 
5029  if (fPlots.size() == 0) {
5030  error = true;
5031  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **ERROR** no valid PLOT block at all present. Fix this first!";
5032  std::cerr << std::endl;
5033  }
5034 
5035  if (error) { // print error message
5036  --iter1;
5037  std::cerr << std::endl << ">> PMsrHandler::HandlePlotEntry: **ERROR** in line " << iter1->fLineNo << ": " << iter1->fLine.Data();
5038  std::cerr << std::endl << ">> A PLOT block needs to have the following structure:";
5039  std::cerr << std::endl;
5040  std::cerr << std::endl << ">> PLOT <plot_type>";
5041  std::cerr << std::endl << ">> runs <run_list>";
5042  std::cerr << std::endl << ">> [range tmin tmax [ymin ymax]]";
5043  std::cerr << std::endl << ">> [sub_ranges tmin1 tmax1 tmin2 tmax2 ... tminN tmaxN [ymin ymax]";
5044  std::cerr << std::endl << ">> [logx | logy]";
5045  std::cerr << std::endl << ">> [use_fit_ranges [ymin ymax]]";
5046  std::cerr << std::endl << ">> [view_packing n]";
5047  std::cerr << std::endl;
5048  std::cerr << std::endl << ">> where <plot_type> is: 0=single histo,";
5049  std::cerr << std::endl << ">> 1=RRF single histo,";
5050  std::cerr << std::endl << ">> 2=forward-backward asym,";
5051  std::cerr << std::endl << ">> 3=forward-backward RRF asym,";
5052  std::cerr << std::endl << ">> 4=mu minus single histo,";
5053  std::cerr << std::endl << ">> 5=forward-backward beta-NMR asym,";
5054  std::cerr << std::endl << ">> 8=non muSR.";
5055  std::cerr << std::endl << ">> <run_list> is the list of runs, e.g. runs 1 3";
5056  std::cerr << std::endl << ">> range is optional";
5057  std::cerr << std::endl << ">> sub_ranges (if present) will plot the N given runs each on its own sub-range";
5058  std::cerr << std::endl << ">> logx, logy (if present) will present the x-, y-axis in log-scale";
5059  std::cerr << std::endl << ">> use_fit_ranges (if present) will plot each run on its fit-range";
5060  std::cerr << std::endl << ">> view_packing n (if present) will bin all data by n (> 0) rather than the binning of the fit";
5061  std::cerr << std::endl;
5062  }
5063 
5064  param.fRuns.clear();
5065 
5066  }
5067 
5068  return !error;
5069 }
5070 
5071 //--------------------------------------------------------------------------
5072 // HandleStatisticEntry (private)
5073 //--------------------------------------------------------------------------
5084 {
5085  // If msr-file is used for musrFT only, nothing needs to be done here.
5086  if (fFourierOnly)
5087  return true;
5088 
5089  if (lines.empty()) {
5090  std::cerr << std::endl << ">> PMsrHandler::HandleStatisticEntry: **WARNING** There is no STATISTIC block! Do you really want this?";
5091  std::cerr << std::endl;
5092  fStatistic.fValid = false;
5093  return true;
5094  }
5095 
5096  Char_t str[128];
5097  Char_t date[128];
5098  Char_t time[128];
5099  Int_t status;
5100  Double_t dval;
5101  UInt_t ival;
5102  TString tstr;
5103  for (UInt_t i=0; i<lines.size(); i++) {
5104  // check if the statistic block line is illegal
5105  tstr = lines[i].fLine;
5106  tstr.Remove(TString::kLeading, ' ');
5107  if (tstr.Length() > 0) {
5108  if (!tstr.BeginsWith("#") && !tstr.BeginsWith("STATISTIC") && !tstr.BeginsWith("chisq") &&
5109  !tstr.BeginsWith("maxLH") && !tstr.BeginsWith("*** FIT DID NOT CONVERGE ***") &&
5110  !tstr.BeginsWith("expected chisq") && !tstr.BeginsWith("expected maxLH") &&
5111  !tstr.BeginsWith("run block")) {
5112  std::cerr << std::endl << ">> PMsrHandler::HandleStatisticEntry: **SYNTAX ERROR** in line " << lines[i].fLineNo;
5113  std::cerr << std::endl << ">> '" << lines[i].fLine.Data() << "'";
5114  std::cerr << std::endl << ">> not a valid STATISTIC block line";
5115  std::cerr << std::endl << ">> If you do not understand this, just remove the STATISTIC block, musrfit will recreate after fitting";
5116  std::cerr << std::endl << std::endl;
5117  return false;
5118  }
5119  }
5120 
5121  // filter date and chisq etc from strings
5122  // extract date and time
5123  if (lines[i].fLine.Contains("STATISTIC")) {
5124  status = sscanf(lines[i].fLine.Data(), "STATISTIC --- %s%s", date, time);
5125  if (status == 2) {
5126  fStatistic.fDate = TString(date)+TString(", ")+TString(time);
5127  } else {
5128  fStatistic.fDate = TString("????-??-??, ??:??:??");
5129  }
5130  }
5131  // extract chisq
5132  if (lines[i].fLine.Contains("chisq =")) {
5133  if (lines[i].fLine.Contains("expected")) { // expected chisq
5134  strncpy(str, lines[i].fLine.Data(), sizeof(str));
5135  status = sscanf(str+lines[i].fLine.Index("chisq = ")+8, "%lf", &dval);
5136  if (status == 1) {
5137  fStatistic.fMinExpected = dval;
5138  } else {
5139  fStatistic.fMinExpected = -1.0;
5140  }
5141  } else { // chisq
5142  fStatistic.fValid = true;
5143  strncpy(str, lines[i].fLine.Data(), sizeof(str));
5144  status = sscanf(str+lines[i].fLine.Index("chisq = ")+8, "%lf", &dval);
5145  if (status == 1) {
5146  fStatistic.fMin = dval;
5147  } else {
5148  fStatistic.fMin = -1.0;
5149  }
5150  }
5151  }
5152  // extract maxLH
5153  if (lines[i].fLine.Contains("maxLH =")) {
5154  fStatistic.fValid = true;
5155  strncpy(str, lines[i].fLine.Data(), sizeof(str));
5156  status = sscanf(str+lines[i].fLine.Index("maxLH = ")+8, "%lf", &dval);
5157  if (status == 1) {
5158  fStatistic.fMin = dval;
5159  } else {
5160  fStatistic.fMin = -1.0;
5161  }
5162  }
5163  // extract NDF
5164  if (lines[i].fLine.Contains(", NDF =")) {
5165  strncpy(str, lines[i].fLine.Data(), sizeof(str));
5166  status = sscanf(str+lines[i].fLine.Index(", NDF = ")+8, "%u", &ival);
5167  if (status == 1) {
5168  fStatistic.fNdf = ival;
5169  } else {
5170  fStatistic.fNdf = 0;
5171  }
5172  }
5173  // keep string
5174  fStatistic.fStatLines.push_back(lines[i]);
5175  }
5176 
5177  return true;
5178 }
5179 
5180 
5181 //--------------------------------------------------------------------------
5182 // GetNoOfFitParameters (public)
5183 //--------------------------------------------------------------------------
5190 {
5191  UInt_t noOfFitParameters = 0;
5192  PUIntVector paramVector;
5193  PUIntVector funVector;
5194  PUIntVector mapVector;
5195  TObjArray *tokens = nullptr;
5196  TObjString *ostr = nullptr;
5197  TString str;
5198  UInt_t k, dval;
5199  Int_t status, pos;
5200 
5201  // check that idx is valid
5202  if (idx >= fRuns.size()) {
5203  std::cerr << std::endl << ">> PMsrHandler::GetNoOfFitParameters() **ERROR** idx=" << idx << ", out of range fRuns.size()=" << fRuns.size();
5204  std::cerr << std::endl;
5205  return 0;
5206  }
5207 
5208  // get N0 parameter, possible parameter number or function (single histo fit)
5209  if (fRuns[idx].GetNormParamNo() != -1) {
5210  if (fRuns[idx].GetNormParamNo() < MSR_PARAM_FUN_OFFSET) // parameter
5211  paramVector.push_back(fRuns[idx].GetNormParamNo());
5212  else // function
5213  funVector.push_back(fRuns[idx].GetNormParamNo() - MSR_PARAM_FUN_OFFSET);
5214  }
5215 
5216  // get background parameter, for the case the background is fitted (single histo fit)
5217  if (fRuns[idx].GetBkgFitParamNo() != -1)
5218  paramVector.push_back(fRuns[idx].GetBkgFitParamNo());
5219 
5220  // get alpha parameter if present (asymmetry fit)
5221  if (fRuns[idx].GetAlphaParamNo() != -1) {
5222  if (fRuns[idx].GetAlphaParamNo() < MSR_PARAM_FUN_OFFSET) // parameter
5223  paramVector.push_back(fRuns[idx].GetAlphaParamNo());
5224  else // function
5225  funVector.push_back(fRuns[idx].GetAlphaParamNo() - MSR_PARAM_FUN_OFFSET);
5226  }
5227 
5228  // get beta parameter if present (asymmetry fit)
5229  if (fRuns[idx].GetBetaParamNo() != -1) {
5230  if (fRuns[idx].GetBetaParamNo() < MSR_PARAM_FUN_OFFSET) // parameter
5231  paramVector.push_back(fRuns[idx].GetBetaParamNo());
5232  else // function
5233  funVector.push_back(fRuns[idx].GetBetaParamNo() - MSR_PARAM_FUN_OFFSET);
5234  }
5235 
5236  // go through the theory block and collect parameters
5237  // possible entries: number -> parameter, fun<number> -> function, map<number> -> maps
5238  for (UInt_t i=0; i<fTheory.size(); i++) {
5239  // remove potential comments
5240  str = fTheory[i].fLine;
5241  pos = str.Index('#');
5242  if (pos >= 0)
5243  str.Resize(pos);
5244  // tokenize
5245  tokens = str.Tokenize(" \t");
5246  if (!tokens) {
5247  mapVector.clear();
5248  funVector.clear();
5249  paramVector.clear();
5250  return 0;
5251  }
5252 
5253  for (Int_t j=0; j<tokens->GetEntries(); j++) {
5254  ostr = dynamic_cast<TObjString*>(tokens->At(j));
5255  str = ostr->GetString();
5256  // check for parameter number
5257  if (str.IsDigit()) {
5258  dval = str.Atoi();
5259  paramVector.push_back(dval);
5260  }
5261 
5262  // check for map
5263  if (str.Contains("map")) {
5264  status = sscanf(str.Data(), "map%d", &dval);
5265  if (status == 1) {
5266  mapVector.push_back(dval);
5267  }
5268  }
5269 
5270  // check for function
5271  if (str.Contains("fun")) {
5272  status = sscanf(str.Data(), "fun%d", &dval);
5273  if (status == 1) {
5274  funVector.push_back(dval);
5275  }
5276  }
5277  }
5278 
5279  delete tokens;
5280  tokens = nullptr;
5281  }
5282 
5283  // go through the function block and collect parameters
5284  for (UInt_t i=0; i<funVector.size(); i++) {
5285  // find the proper function in the function block
5286  for (k=0; k<fFunctions.size(); k++) {
5287  status = sscanf(fFunctions[k].fLine.Data(), "fun%d", &dval);
5288  if (status == 1) {
5289  if (dval == funVector[i])
5290  break;
5291  }
5292  }
5293 
5294  // check if everything has been found at all
5295  if (k == fFunctions.size()) {
5296  std::cerr << std::endl << ">> PMsrHandler::GetNoOfFitParameters() **ERROR** couldn't find fun" << funVector[i];
5297  std::cerr << std::endl << std::endl;
5298 
5299  // clean up
5300  mapVector.clear();
5301  funVector.clear();
5302  paramVector.clear();
5303 
5304  return 0;
5305  }
5306 
5307  // remove potential comments
5308  str = fFunctions[k].fLine;
5309  pos = str.Index('#');
5310  if (pos >= 0)
5311  str.Resize(pos);
5312 
5313  // tokenize
5314  tokens = str.Tokenize(" \t");
5315  if (!tokens) {
5316  mapVector.clear();
5317  funVector.clear();
5318  paramVector.clear();
5319  return 0;
5320  }
5321 
5322  // filter out parameters and maps
5323  for (Int_t j=0; j<tokens->GetEntries(); j++) {
5324  ostr = dynamic_cast<TObjString*>(tokens->At(j));
5325  str = ostr->GetString();
5326 
5327  // check for parameter
5328  if (str.BeginsWith("par")) {
5329  status = sscanf(str.Data(), "par%d", &dval);
5330  if (status == 1)
5331  paramVector.push_back(dval);
5332  }
5333 
5334  // check for map
5335  if (str.BeginsWith("map")) {
5336  status = sscanf(str.Data(), "map%d", &dval);
5337  if (status == 1)
5338  mapVector.push_back(dval);
5339  }
5340  }
5341  }
5342 
5343  // go through the map and collect parameters
5344  for (UInt_t i=0; i<mapVector.size(); i++) {
5345  paramVector.push_back(fRuns[idx].GetMap(mapVector[i]-1));
5346  }
5347 
5348  // eliminated multiple identical entries in paramVector
5349  PUIntVector param;
5350  param.push_back(paramVector[0]);
5351  for (UInt_t i=0; i<paramVector.size(); i++) {
5352  for (k=0; k<param.size(); k++) {
5353  if (param[k] == paramVector[i])
5354  break;
5355  }
5356  if (k == param.size())
5357  param.push_back(paramVector[i]);
5358  }
5359 
5360  // calculate the number of fit parameters with step != 0
5361  for (UInt_t i=0; i<param.size(); i++) {
5362  if (fParam[param[i]-1].fStep != 0.0)
5363  noOfFitParameters++;
5364  }
5365 
5366  // cleanup
5367  param.clear();
5368  mapVector.clear();
5369  funVector.clear();
5370  paramVector.clear();
5371 
5372  return noOfFitParameters;
5373 }
5374 
5375 //--------------------------------------------------------------------------
5376 // FillParameterInUse (private)
5377 //--------------------------------------------------------------------------
5387 {
5388  PIntVector map;
5389  PIntVector fun;
5390  PMsrLines::iterator iter;
5391  TObjArray *tokens = nullptr;
5392  TObjString *ostr = nullptr;
5393  TString str;
5394  Int_t ival, funNo;
5395 
5396  // create and initialize fParamInUse vector
5397  for (UInt_t i=0; i<fParam.size(); i++)
5398  fParamInUse.push_back(0);
5399 
5400  // go through all the theory lines ------------------------------------
5401  for (iter = theory.begin(); iter != theory.end(); ++iter) {
5402  // remove potential comments
5403  str = iter->fLine;
5404  if (str.First('#') != -1)
5405  str.Resize(str.First('#'));
5406 
5407  // everything to lower case
5408  str.ToLower();
5409 
5410  // tokenize string
5411  tokens = str.Tokenize(" \t");
5412  if (!tokens)
5413  continue;
5414 
5415  // filter param no, map no, and fun no
5416  for (Int_t i=0; i<tokens->GetEntries(); i++) {
5417  ostr = dynamic_cast<TObjString*>(tokens->At(i));
5418  str = ostr->GetString();
5419  if (str.IsDigit()) { // parameter number
5420  ival = str.Atoi();
5421  if ((ival > 0) && (ival < static_cast<Int_t>(fParam.size())+1)) {
5422  fParamInUse[ival-1]++;
5423  }
5424  } else if (str.Contains("map")) { // map
5425  if (FilterNumber(str, "map", MSR_PARAM_MAP_OFFSET, ival))
5426  map.push_back(ival-MSR_PARAM_MAP_OFFSET);
5427  } else if (str.Contains("fun")) { // fun
5428  if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, ival))
5429  fun.push_back(ival-MSR_PARAM_FUN_OFFSET);
5430  }
5431  }
5432 
5433  // delete tokens
5434  if (tokens) {
5435  delete tokens;
5436  tokens = nullptr;
5437  }
5438  }
5439 
5440  // go through all the function lines: 1st time -----------------------------
5441  for (iter = funcs.begin(); iter != funcs.end(); ++iter) {
5442  // remove potential comments
5443  str = iter->fLine;
5444  if (str.First('#') != -1)
5445  str.Resize(str.First('#'));
5446 
5447  // everything to lower case
5448  str.ToLower();
5449 
5450  tokens = str.Tokenize(" /t");
5451  if (!tokens)
5452  continue;
5453 
5454  // filter fun number
5455  ostr = dynamic_cast<TObjString*>(tokens->At(0));
5456  str = ostr->GetString();
5457  if (!FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, funNo))
5458  continue;
5459  funNo -= MSR_PARAM_FUN_OFFSET;
5460 
5461  // check if fun number is used, and if yes, filter parameter numbers and maps
5462  TString sstr;
5463  for (UInt_t i=0; i<fun.size(); i++) {
5464  if (fun[i] == funNo) { // function number found
5465  // filter for parX
5466  sstr = iter->fLine;
5467  Char_t sval[128];
5468  while (sstr.Index("par") != -1) {
5469  memset(sval, 0, sizeof(sval));
5470  sstr = &sstr[sstr.Index("par")+3]; // trunc sstr
5471  for (Int_t j=0; j<sstr.Sizeof(); j++) {
5472  if (!isdigit(sstr[j]))
5473  break;
5474  sval[j] = sstr[j];
5475  }
5476  sscanf(sval, "%d", &ival);
5477  fParamInUse[ival-1]++;
5478  }
5479 
5480  // filter for mapX
5481  sstr = iter->fLine;
5482  while (sstr.Index("map") != -1) {
5483  memset(sval, 0, sizeof(sval));
5484  sstr = &sstr[sstr.Index("map")+3]; // trunc sstr
5485  for (Int_t j=0; j<sstr.Sizeof(); j++) {
5486  if (!isdigit(sstr[j]))
5487  break;
5488  sval[j] = sstr[j];
5489  }
5490  sscanf(sval, "%d", &ival);
5491  // check if map value already in map, otherwise add it
5492  if (ival > 0) {
5493  UInt_t pos;
5494  for (pos=0; pos<map.size(); pos++) {
5495  if (ival == map[pos])
5496  break;
5497  }
5498  if (pos == map.size()) { // new map value
5499  map.push_back(ival);
5500  }
5501  }
5502  }
5503  break; // since function was found, break the loop
5504  }
5505  }
5506 
5507  // delete tokens
5508  if (tokens) {
5509  delete tokens;
5510  tokens = nullptr;
5511  }
5512  }
5513 
5514  // go through all the run block lines -------------------------------------
5515  for (iter = run.begin(); iter != run.end(); ++iter) {
5516  // remove potential comments
5517  str = iter->fLine;
5518  if (str.First('#') != -1)
5519  str.Resize(str.First('#'));
5520 
5521  // everything to lower case
5522  str.ToLower();
5523 
5524  // handle everything but the maps
5525  if (str.Contains("alpha") || str.Contains("beta") ||
5526  str.Contains("alpha2") || str.Contains("beta2") ||
5527  str.Contains("norm") || str.Contains("backgr.fit") ||
5528  str.Contains("lifetime ")) {
5529  // tokenize string
5530  tokens = str.Tokenize(" \t");
5531  if (!tokens)
5532  continue;
5533  if (tokens->GetEntries()<2)
5534  continue;
5535 
5536  ostr = dynamic_cast<TObjString*>(tokens->At(1)); // parameter number or function
5537  str = ostr->GetString();
5538  // check if parameter number
5539  if (str.IsDigit()) {
5540  ival = str.Atoi();
5541  fParamInUse[ival-1]++;
5542  }
5543  // check if fun
5544  if (str.Contains("fun")) {
5545  if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, ival)) {
5546  fun.push_back(ival-MSR_PARAM_FUN_OFFSET);
5547  }
5548  }
5549 
5550  // delete tokens
5551  if (tokens) {
5552  delete tokens;
5553  tokens = nullptr;
5554  }
5555  }
5556 
5557  // handle the maps
5558  if (str.Contains("map")) {
5559  // tokenize string
5560  tokens = str.Tokenize(" \t");
5561  if (!tokens)
5562  continue;
5563 
5564  // get the parameter number via map
5565  for (UInt_t i=0; i<map.size(); i++) {
5566  if (map[i] == 0)
5567  continue;
5568  if (map[i] < tokens->GetEntries()) {
5569  ostr = dynamic_cast<TObjString*>(tokens->At(map[i]));
5570  str = ostr->GetString();
5571  if (str.IsDigit()) {
5572  ival = str.Atoi();
5573  if (ival > 0) {
5574  fParamInUse[ival-1]++; // this is OK since map is ranging from 1 ..
5575  }
5576  }
5577  }
5578  }
5579 
5580  // delete tokens
5581  if (tokens) {
5582  delete tokens;
5583  tokens = nullptr;
5584  }
5585  }
5586  }
5587 
5588  // go through all the function lines: 2nd time -----------------------------
5589  for (iter = funcs.begin(); iter != funcs.end(); ++iter) {
5590  // remove potential comments
5591  str = iter->fLine;
5592  if (str.First('#') != -1)
5593  str.Resize(str.First('#'));
5594 
5595  // everything to lower case
5596  str.ToLower();
5597 
5598  tokens = str.Tokenize(" /t");
5599  if (!tokens)
5600  continue;
5601 
5602  // filter fun number
5603  ostr = dynamic_cast<TObjString*>(tokens->At(0));
5604  str = ostr->GetString();
5605  if (!FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, funNo))
5606  continue;
5607  funNo -= MSR_PARAM_FUN_OFFSET;
5608 
5609  // check if fun number is used, and if yes, filter parameter numbers and maps
5610  TString sstr;
5611  for (UInt_t i=0; i<fun.size(); i++) {
5612  if (fun[i] == funNo) { // function number found
5613  // filter for parX
5614  sstr = iter->fLine;
5615  Char_t sval[128];
5616  while (sstr.Index("par") != -1) {
5617  memset(sval, 0, sizeof(sval));
5618  sstr = &sstr[sstr.Index("par")+3]; // trunc sstr
5619  for (Int_t j=0; j<sstr.Sizeof(); j++) {
5620  if (!isdigit(sstr[j]))
5621  break;
5622  sval[j] = sstr[j];
5623  }
5624  sscanf(sval, "%d", &ival);
5625  fParamInUse[ival-1]++;
5626  }
5627 
5628  // filter for mapX
5629  sstr = iter->fLine;
5630  while (sstr.Index("map") != -1) {
5631  memset(sval, 0, sizeof(sval));
5632  sstr = &sstr[sstr.Index("map")+3]; // trunc sstr
5633  for (Int_t j=0; j<sstr.Sizeof(); j++) {
5634  if (!isdigit(sstr[j]))
5635  break;
5636  sval[j] = sstr[j];
5637  }
5638  sscanf(sval, "%d", &ival);
5639  // check if map value already in map, otherwise add it
5640  if (ival > 0) {
5641  UInt_t pos;
5642  for (pos=0; pos<map.size(); pos++) {
5643  if (ival == map[pos])
5644  break;
5645  }
5646  if (static_cast<UInt_t>(pos) == map.size()) { // new map value
5647  map.push_back(ival);
5648  }
5649  }
5650  }
5651  }
5652  }
5653 
5654  // delete tokens
5655  if (tokens) {
5656  delete tokens;
5657  tokens = nullptr;
5658  }
5659  }
5660 
5661  // go through all the run block lines 2nd time to filter remaining maps
5662  for (iter = run.begin(); iter != run.end(); ++iter) {
5663  // remove potential comments
5664  str = iter->fLine;
5665  if (str.First('#') != -1)
5666  str.Resize(str.First('#'));
5667 
5668  // everything to lower case
5669  str.ToLower();
5670 
5671  // handle the maps
5672  if (str.Contains("map")) {
5673  // tokenize string
5674  tokens = str.Tokenize(" \t");
5675  if (!tokens)
5676  continue;
5677 
5678  // get the parameter number via map
5679  for (UInt_t i=0; i<map.size(); i++) {
5680  if (map[i] == 0)
5681  continue;
5682  if (map[i] < tokens->GetEntries()) {
5683  ostr = dynamic_cast<TObjString*>(tokens->At(map[i]));
5684  str = ostr->GetString();
5685  if (str.IsDigit()) {
5686  ival = str.Atoi();
5687  if (ival > 0) {
5688  fParamInUse[ival-1]++; // this is OK since map is ranging from 1 ..
5689  }
5690  }
5691  }
5692  }
5693 
5694  // delete tokens
5695  if (tokens) {
5696  delete tokens;
5697  tokens = nullptr;
5698  }
5699  }
5700  }
5701 
5702  // if unused parameters are present, set the step value to 0.0
5703  for (UInt_t i=0; i<fParam.size(); i++) {
5704  if (!ParameterInUse(i)) {
5705  if (fParam[i].fStep != 0.0) {
5706  std::cerr << std::endl << ">> **WARNING** : Parameter No " << i+1 << " is not used at all, will fix it" << std::endl;
5707  fParam[i].fStep = 0.0;
5708  }
5709  }
5710  }
5711 
5712  // clean up
5713  map.clear();
5714  fun.clear();
5715 }
5716 
5717 
5718 //--------------------------------------------------------------------------
5719 // CheckRunBlockIntegrity (public)
5720 //--------------------------------------------------------------------------
5730 {
5731  // go through all the present RUN blocks
5732  Int_t fitType = 0;
5733  for (UInt_t i=0; i<fRuns.size(); i++) {
5734  // check if fittype is defined
5735  fitType = fRuns[i].GetFitType();
5736  if (fitType == -1) { // fittype not given in the run block
5737  fitType = fGlobal.GetFitType();
5738  if (fitType == -1) {
5739  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** fittype is neither defined in RUN block number " << i+1 << ", nor in the GLOBAL block." << std::endl;
5740  return false;
5741  }
5742  }
5743 
5744  // check for the different fittypes differently
5745  Int_t detectorGroups = 1; // number of detectors tp be grouped
5746  switch (fitType) {
5747  case PRUN_SINGLE_HISTO:
5748  // check of norm is present
5749  if ((fRuns[i].GetNormParamNo() == -1) && !fFourierOnly) {
5750  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5751  std::cerr << std::endl << ">> Norm parameter number not defined. Necessary for single histogram fits." << std::endl;
5752  return false;
5753  }
5754  if (!fFourierOnly) { // next check NOT needed for Fourier only
5755  // check if norm parameter is given that it is either a valid function of a fit parameter present
5756  if (fRuns[i].GetNormParamNo() < MSR_PARAM_FUN_OFFSET) { // parameter number
5757  // check that norm parameter number is not larger than the number of parameters
5758  if (fRuns[i].GetNormParamNo() > static_cast<Int_t>(fParam.size())) {
5759  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5760  std::cerr << std::endl << ">> Norm parameter number " << fRuns[i].GetNormParamNo() << " is larger than the number of fit parameters (" << fParam.size() << ").";
5761  std::cerr << std::endl << ">> Consider to check the manual ;-)" << std::endl;
5762  return false;
5763  }
5764  } else { // function norm
5765  if (fRuns[i].GetNormParamNo()-MSR_PARAM_FUN_OFFSET > GetNoOfFuncs()) {
5766  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5767  std::cerr << std::endl << ">> Norm parameter function number " << fRuns[i].GetNormParamNo()-MSR_PARAM_FUN_OFFSET << " is larger than the number of functions (" << GetNoOfFuncs() << ").";
5768  std::cerr << std::endl << ">> Consider to check the manual ;-)" << std::endl;
5769  return false;
5770  }
5771  }
5772  }
5773  // check that there is a forward parameter number
5774  if (fRuns[i].GetForwardHistoNo() == -1) {
5775  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5776  std::cerr << std::endl << ">> forward parameter number not defined. Necessary for single histogram fits." << std::endl;
5777  return false;
5778  }
5779  if ((fRuns[i].GetNormParamNo() > static_cast<Int_t>(fParam.size())) && !fFourierOnly) {
5780  // check if forward histogram number is a function
5781  if (fRuns[i].GetNormParamNo() - MSR_PARAM_FUN_OFFSET > static_cast<Int_t>(fParam.size())) {
5782  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5783  std::cerr << std::endl << ">> forward histogram number " << fRuns[i].GetNormParamNo() << " is larger than the number of fit parameters (" << fParam.size() << ").";
5784  std::cerr << std::endl << ">> Consider to check the manual ;-)" << std::endl;
5785  return false;
5786  }
5787  }
5788  // check fit range
5789  if (!fRuns[i].IsFitRangeInBin() && !fFourierOnly) { // fit range given as times in usec (RUN block)
5790  if ((fRuns[i].GetFitRange(0) == PMUSR_UNDEFINED) || (fRuns[i].GetFitRange(1) == PMUSR_UNDEFINED)) { // check fit range in RUN block
5791  if (!fGlobal.IsFitRangeInBin()) { // fit range given as times in usec (GLOBAL block)
5792  if ((fGlobal.GetFitRange(0) == PMUSR_UNDEFINED) || (fGlobal.GetFitRange(1) == PMUSR_UNDEFINED)) { // check fit range in GLOBAL block
5793  std::cerr << std::endl << "PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5794  std::cerr << std::endl << " Fit range is not defined. Necessary for single histogram fits." << std::endl;
5795  return false;
5796  }
5797  }
5798  }
5799  }
5800  // check number of T0's provided
5801  detectorGroups = fRuns[i].GetForwardHistoNoSize();
5802  if ((fRuns[i].GetT0BinSize() > detectorGroups) || (fGlobal.GetT0BinSize() > detectorGroups)) {
5803  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5804  if (fRuns[i].GetT0BinSize() > detectorGroups)
5805  std::cerr << std::endl << ">> In RUN Block " << i+1 << ": found " << fRuns[i].GetT0BinSize() << " T0 entries. Expecting max. " << detectorGroups << " entries.";
5806  if (fGlobal.GetT0BinSize() > 1)
5807  std::cerr << std::endl << ">> In GLOBAL block: found " << fGlobal.GetT0BinSize() << " T0 entries. Expecting max. " << detectorGroups << " entries. Needs to be fixed.";
5808  std::cerr << std::endl << ">> In case you added runs, please use the key word 'addt0' to add the t0's of the runs to be added." << std::endl;
5809  return false;
5810  }
5811 
5812  // check packing
5813  if ((fRuns[i].GetPacking() == -1) && (fGlobal.GetPacking() == -1)) {
5814  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **WARNING** in RUN block number " << i+1;
5815  std::cerr << std::endl << ">> Packing is neither defined here, nor in the GLOBAL block, will set it to 1." << std::endl;
5816  fRuns[i].SetPacking(1);
5817  }
5818  break;
5819  case PRUN_SINGLE_HISTO_RRF:
5820  // check that there is a forward parameter number
5821  if (fRuns[i].GetForwardHistoNo() == -1) {
5822  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5823  std::cerr << std::endl << ">> forward parameter number not defined. Necessary for single histogram RRF fits." << std::endl;
5824  return false;
5825  }
5826  if ((fRuns[i].GetNormParamNo() > static_cast<Int_t>(fParam.size())) && !fFourierOnly) {
5827  // check if forward histogram number is a function
5828  if (fRuns[i].GetNormParamNo() - MSR_PARAM_FUN_OFFSET > static_cast<Int_t>(fParam.size())) {
5829  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5830  std::cerr << std::endl << ">> forward histogram number " << fRuns[i].GetNormParamNo() << " is larger than the number of fit parameters (" << fParam.size() << ").";
5831  std::cerr << std::endl << ">> Consider to check the manual ;-)" << std::endl;
5832  return false;
5833  }
5834  }
5835  // check fit range
5836  if (!fRuns[i].IsFitRangeInBin() && !fFourierOnly) { // fit range given as times in usec (RUN block)
5837  if ((fRuns[i].GetFitRange(0) == PMUSR_UNDEFINED) || (fRuns[i].GetFitRange(1) == PMUSR_UNDEFINED)) { // check fit range in RUN block
5838  if (!fGlobal.IsFitRangeInBin()) { // fit range given as times in usec (GLOBAL block)
5839  if ((fGlobal.GetFitRange(0) == PMUSR_UNDEFINED) || (fGlobal.GetFitRange(1) == PMUSR_UNDEFINED)) { // check fit range in GLOBAL block
5840  std::cerr << std::endl << "PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5841  std::cerr << std::endl << " Fit range is not defined. Necessary for single histogram fits." << std::endl;
5842  return false;
5843  }
5844  }
5845  }
5846  }
5847  // check number of T0's provided
5848  detectorGroups = fRuns[i].GetForwardHistoNoSize();
5849  if ((fRuns[i].GetT0BinSize() > detectorGroups) || (fGlobal.GetT0BinSize() > detectorGroups)) {
5850  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5851  if (fRuns[i].GetT0BinSize() > detectorGroups)
5852  std::cerr << std::endl << ">> In RUN Block " << i+1 << ": found " << fRuns[i].GetT0BinSize() << " T0 entries. Expecting max. " << detectorGroups << " entries.";
5853  if (fGlobal.GetT0BinSize() > 1)
5854  std::cerr << std::endl << ">> In GLOBAL block: found " << fGlobal.GetT0BinSize() << " T0 entries. Expecting max. " << detectorGroups << " entries. Needs to be fixed.";
5855  std::cerr << std::endl << ">> In case you added runs, please use the key word 'addt0' to add the t0's of the runs to be added." << std::endl;
5856  return false;
5857  }
5858  // check that RRF frequency is given
5860  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** no RRF frequency found in the GLOBAL block." << std::endl;
5861  return false;
5862  }
5863  // check that RRF packing is given
5864  if (fGlobal.GetRRFPacking() == -1) {
5865  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** no RRF packing found in the GLOBAL block." << std::endl;
5866  return false;
5867  }
5868  break;
5869  case PRUN_ASYMMETRY:
5870  // check alpha
5871  if ((fRuns[i].GetAlphaParamNo() == -1) && !fFourierOnly) {
5872  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5873  std::cerr << std::endl << ">> alpha parameter number missing which is needed for an asymmetry fit.";
5874  std::cerr << std::endl << ">> Consider to check the manual ;-)" << std::endl;
5875  return false;
5876  }
5877  // check that there is a forward parameter number
5878  if (fRuns[i].GetForwardHistoNo() == -1) {
5879  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5880  std::cerr << std::endl << ">> forward histogram number not defined. Necessary for asymmetry fits." << std::endl;
5881  return false;
5882  }
5883  // check that there is a backward parameter number
5884  if (fRuns[i].GetBackwardHistoNo() == -1) {
5885  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5886  std::cerr << std::endl << ">> backward histogram number not defined. Necessary for asymmetry fits." << std::endl;
5887  return false;
5888  }
5889  // check fit range
5890  if (!fRuns[i].IsFitRangeInBin()) { // fit range given as times in usec
5891  if ((fRuns[i].GetFitRange(0) == PMUSR_UNDEFINED) || (fRuns[i].GetFitRange(1) == PMUSR_UNDEFINED)) {
5893  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5894  std::cerr << std::endl << ">> Fit range is not defined, also NOT present in the GLOBAL block. Necessary for asymmetry fits." << std::endl;
5895  return false;
5896  }
5897  }
5898  }
5899  // check number of T0's provided
5900  detectorGroups = 2*fRuns[i].GetForwardHistoNoSize();
5901  if (detectorGroups < 2*fRuns[i].GetBackwardHistoNoSize())
5902  detectorGroups = 2*fRuns[i].GetBackwardHistoNoSize();
5903  if ((fRuns[i].GetT0BinSize() > detectorGroups) || (fGlobal.GetT0BinSize() > detectorGroups)) {
5904  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5905  if (fRuns[i].GetT0BinSize() > detectorGroups)
5906  std::cerr << std::endl << ">> In RUN Block " << i+1 << ": found " << fRuns[i].GetT0BinSize() << " T0 entries. Expecting max. " << detectorGroups << " entries.";
5907  if (fGlobal.GetT0BinSize() > 1)
5908  std::cerr << std::endl << ">> In GLOBAL block: found " << fGlobal.GetT0BinSize() << " T0 entries. Expecting max. " << detectorGroups << " entries. Needs to be fixed.";
5909  std::cerr << std::endl << ">> In case you added runs, please use the key word 'addt0' to add the t0's of the runs to be added." << std::endl;
5910  return false;
5911  }
5912  // check packing
5913  if ((fRuns[i].GetPacking() == -1) && (fGlobal.GetPacking() == -1)) {
5914  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **WARNING** in RUN block number " << i+1;
5915  std::cerr << std::endl << ">> Packing is neither defined here, nor in the GLOBAL block, will set it to 1." << std::endl;
5916  fRuns[i].SetPacking(1);
5917  }
5918  break;
5919  case PRUN_ASYMMETRY_BNMR:
5920  // check alpha
5921  // if ((fRuns[i].GetAlphaParamNo() == -1) && !fFourierOnly) {
5922  // std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5923  // std::cerr << std::endl << ">> alpha parameter number missing which is needed for an asymmetry fit.";
5924  // std::cerr << std::endl << ">> Consider to check the manual ;-)" << std::endl;
5925  // return false;
5926  // }
5927  // check that there is a forward parameter number
5928  if (fRuns[i].GetForwardHistoNo() == -1) {
5929  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5930  std::cerr << std::endl << ">> forward histogram number not defined. Necessary for asymmetry fits." << std::endl;
5931  return false;
5932  }
5933  // check that there is a backward parameter number
5934  if (fRuns[i].GetBackwardHistoNo() == -1) {
5935  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5936  std::cerr << std::endl << ">> backward histogram number not defined. Necessary for asymmetry fits." << std::endl;
5937  return false;
5938  }
5939  // check fit range
5940  if (!fRuns[i].IsFitRangeInBin()) { // fit range given as times in usec
5941  if ((fRuns[i].GetFitRange(0) == PMUSR_UNDEFINED) || (fRuns[i].GetFitRange(1) == PMUSR_UNDEFINED)) {
5943  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5944  std::cerr << std::endl << ">> Fit range is not defined, also NOT present in the GLOBAL block. Necessary for asymmetry fits." << std::endl;
5945  return false;
5946  }
5947  }
5948  }
5949  // check number of T0's provided
5950  if ((fRuns[i].GetT0BinSize() > 2*fRuns[i].GetForwardHistoNoSize()) &&
5951  (fGlobal.GetT0BinSize() > 2*fRuns[i].GetForwardHistoNoSize())) {
5952  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5953  std::cerr << std::endl << ">> Found " << fRuns[i].GetT0BinSize() << " T0 entries. Expecting only " << 2*fRuns[i].GetForwardHistoNoSize() << " in forward. Needs to be fixed." << std::endl;
5954  std::cerr << std::endl << ">> In GLOBAL block: " << fGlobal.GetT0BinSize() << " T0 entries. Expecting only " << 2*fRuns[i].GetForwardHistoNoSize() << ". Needs to be fixed." << std::endl;
5955  return false;
5956  }
5957  if ((fRuns[i].GetT0BinSize() > 2*fRuns[i].GetBackwardHistoNoSize()) &&
5958  (fGlobal.GetT0BinSize() > 2*fRuns[i].GetBackwardHistoNoSize())) {
5959  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5960  std::cerr << std::endl << ">> Found " << fRuns[i].GetT0BinSize() << " T0 entries. Expecting only " << 2*fRuns[i].GetBackwardHistoNoSize() << " in backward. Needs to be fixed." << std::endl;
5961  std::cerr << std::endl << ">> In GLOBAL block: " << fGlobal.GetT0BinSize() << " T0 entries. Expecting only " << 2*fRuns[i].GetBackwardHistoNoSize() << ". Needs to be fixed." << std::endl;
5962  return false;
5963  }
5964  // check packing
5965  if ((fRuns[i].GetPacking() == -1) && (fGlobal.GetPacking() == -1)) {
5966  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **WARNING** in RUN block number " << i+1;
5967  std::cerr << std::endl << ">> Packing is neither defined here, nor in the GLOBAL block, will set it to 1." << std::endl;
5968  fRuns[i].SetPacking(1);
5969  }
5970  break;
5971  case PRUN_ASYMMETRY_RRF:
5972  // check alpha
5973  if ((fRuns[i].GetAlphaParamNo() == -1) && !fFourierOnly) {
5974  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5975  std::cerr << std::endl << ">> alpha parameter number missing which is needed for an asymmetry RRF fit.";
5976  std::cerr << std::endl << ">> Consider to check the manual ;-)" << std::endl;
5977  return false;
5978  }
5979  // check that there is a forward parameter number
5980  if (fRuns[i].GetForwardHistoNo() == -1) {
5981  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5982  std::cerr << std::endl << ">> forward histogram number not defined. Necessary for asymmetry RRF fits." << std::endl;
5983  return false;
5984  }
5985  // check that there is a backward parameter number
5986  if (fRuns[i].GetBackwardHistoNo() == -1) {
5987  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5988  std::cerr << std::endl << ">> backward histogram number not defined. Necessary for asymmetry RRF fits." << std::endl;
5989  return false;
5990  }
5991  // check fit range
5992  if (!fRuns[i].IsFitRangeInBin()) { // fit range given as times in usec
5993  if ((fRuns[i].GetFitRange(0) == PMUSR_UNDEFINED) || (fRuns[i].GetFitRange(1) == PMUSR_UNDEFINED)) {
5995  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
5996  std::cerr << std::endl << ">> Fit range is not defined, also NOT present in the GLOBAL block. Necessary for asymmetry RRF fits." << std::endl;
5997  return false;
5998  }
5999  }
6000  }
6001  // check number of T0's provided
6002  detectorGroups = 2*fRuns[i].GetForwardHistoNoSize();
6003  if (detectorGroups < 2*fRuns[i].GetBackwardHistoNoSize())
6004  detectorGroups = 2*fRuns[i].GetBackwardHistoNoSize();
6005  if ((fRuns[i].GetT0BinSize() > detectorGroups) || (fGlobal.GetT0BinSize() > detectorGroups)) {
6006  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
6007  if (fRuns[i].GetT0BinSize() > detectorGroups)
6008  std::cerr << std::endl << ">> In RUN Block " << i+1 << ": found " << fRuns[i].GetT0BinSize() << " T0 entries. Expecting max. " << detectorGroups << " entries.";
6009  if (fGlobal.GetT0BinSize() > 1)
6010  std::cerr << std::endl << ">> In GLOBAL block: found " << fGlobal.GetT0BinSize() << " T0 entries. Expecting max. " << detectorGroups << " entries. Needs to be fixed.";
6011  std::cerr << std::endl << ">> In case you added runs, please use the key word 'addt0' to add the t0's of the runs to be added." << std::endl;
6012  return false;
6013  }
6014  // check that RRF frequency is given
6016  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** no RRF frequency found in the GLOBAL block." << std::endl;
6017  return false;
6018  }
6019  // check that RRF packing is given
6020  if (fGlobal.GetRRFPacking() == -1) {
6021  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** no RRF packing found in the GLOBAL block." << std::endl;
6022  return false;
6023  }
6024  break;
6025  case PRUN_MU_MINUS:
6026  // needs eventually to be implemented
6027  break;
6028  case PRUN_NON_MUSR:
6029  // check xy-data
6030  if ((fRuns[i].GetXDataIndex() == -1) && (fRuns[i].GetXDataLabel()->Length() == 0)) {
6031  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
6032  std::cerr << std::endl << ">> xy-data is missing. Necessary for non muSR fits." << std::endl;
6033  return false;
6034  }
6035  // check fit range
6036  if ((fRuns[i].GetFitRange(0) == PMUSR_UNDEFINED) || (fRuns[i].GetFitRange(1) == PMUSR_UNDEFINED)) {
6038  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** in RUN block number " << i+1;
6039  std::cerr << std::endl << ">> Fit range is not defined, neither in the RUN block, nor in the GLOBAL block.";
6040  std::cerr << std::endl << ">> Necessary for non muSR fits." << std::endl;
6041  return false;
6042  }
6043  }
6044  // check packing
6045  if (fRuns[i].GetPacking() == -1) {
6046  if (fGlobal.GetPacking() == -1) {
6047  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **WARNING** in RUN block number " << i+1;
6048  std::cerr << std::endl << ">> Packing is not defined, will set it to 1." << std::endl;
6049  fRuns[i].SetPacking(1);
6050  }
6051  }
6052  break;
6053  default:
6054  std::cerr << std::endl << ">> PMsrHandler::CheckRunBlockIntegrity(): **ERROR** fittype " << fitType << " undefined." << std::endl;
6055  return false;
6056  }
6057 
6058  }
6059 
6060  return true;
6061 }
6062 
6063 //--------------------------------------------------------------------------
6064 // CheckUniquenessOfParamNames (public)
6065 //--------------------------------------------------------------------------
6077 Bool_t PMsrHandler::CheckUniquenessOfParamNames(UInt_t &parX, UInt_t &parY)
6078 {
6079  Bool_t unique = true;
6080 
6081  for (UInt_t i=0; i<fParam.size()-1; i++) {
6082  for (UInt_t j=i+1; j<fParam.size(); j++) {
6083  if (fParam[i].fName.CompareTo(fParam[j].fName) == 0) { // equal
6084  unique = false;
6085  parX = i;
6086  parY = j;
6087  break;
6088  }
6089  }
6090  }
6091 
6092  return unique;
6093 }
6094 
6095 //--------------------------------------------------------------------------
6096 // CheckMaps (public)
6097 //--------------------------------------------------------------------------
6107 {
6108  Bool_t result = true;
6109 
6110  PIntVector mapVec;
6111  PIntVector mapBlock;
6112  PIntVector mapLineNo;
6113 
6114  TObjArray *tokens = nullptr;
6115  TObjString *ostr = nullptr;
6116  TString str;
6117 
6118  Int_t no;
6119 
6120  // check if map is present in the theory-block
6121  for (UInt_t i=0; i<fTheory.size(); i++) {
6122  if (fTheory[i].fLine.Contains("map", TString::kIgnoreCase)) {
6123  // map found hence filter out map number
6124  tokens = fTheory[i].fLine.Tokenize(" \t");
6125  for (Int_t j=0; j<tokens->GetEntries(); j++) {
6126  ostr = dynamic_cast<TObjString*>(tokens->At(j));
6127  str = ostr->GetString();
6128  if (str.Contains("map", TString::kIgnoreCase)) {
6129  if (FilterNumber(str, "map", MSR_PARAM_MAP_OFFSET, no)) {
6130  mapVec.push_back(no);
6131  mapBlock.push_back(0); // 0 = theory-block
6132  mapLineNo.push_back(fTheory[i].fLineNo);
6133  }
6134  }
6135  }
6136  // clean up tokens
6137  if (tokens) {
6138  delete tokens;
6139  tokens = nullptr;
6140  }
6141  }
6142  }
6143 
6144  // check if map is present in the function-block
6145  for (UInt_t i=0; i<fFunctions.size(); i++) {
6146  if (fFunctions[i].fLine.Contains("map", TString::kIgnoreCase)) {
6147  // map found hence filter out map number
6148  tokens = fFunctions[i].fLine.Tokenize(" \t");
6149  for (Int_t j=0; j<tokens->GetEntries(); j++) {
6150  ostr = dynamic_cast<TObjString*>(tokens->At(j));
6151  str = ostr->GetString();
6152  if (str.Contains("map", TString::kIgnoreCase)) {
6153  if (FilterNumber(str, "map", MSR_PARAM_MAP_OFFSET, no)) {
6154  mapVec.push_back(no);
6155  mapBlock.push_back(1); // 1 = theory-block
6156  mapLineNo.push_back(fFunctions[i].fLineNo);
6157  }
6158  }
6159  }
6160  // clean up tokens
6161  if (tokens) {
6162  delete tokens;
6163  tokens = nullptr;
6164  }
6165  }
6166  }
6167 
6168  // check if present maps are found in the run-block
6169  Bool_t found;
6170  for (UInt_t i=0; i<mapVec.size(); i++) { // loop over found maps in theory- and function-block
6171  found = false;
6172  for (UInt_t j=0; j<fRuns.size(); j++) { // loop over all run-blocks
6173  if ((mapVec[i]-MSR_PARAM_MAP_OFFSET-1 < static_cast<Int_t>(fRuns[j].GetMap()->size())) &&
6174  (mapVec[i]-MSR_PARAM_MAP_OFFSET-1 >= 0)) { // map value smaller than run-block map length
6175  if (fRuns[j].GetMap(mapVec[i]-MSR_PARAM_MAP_OFFSET-1) != 0) { // map value in the run-block != 0
6176  found = true;
6177  break;
6178  }
6179  }
6180  }
6181  if (!found) { // map not found
6182  result = false;
6183  std::cerr << std::endl << ">> PMsrHandler::CheckMaps: **ERROR** map" << mapVec[i]-MSR_PARAM_MAP_OFFSET << " found in the ";
6184  if (mapBlock[i] == 0)
6185  std::cerr << "theory-block ";
6186  else
6187  std::cerr << "functions-block ";
6188  std::cerr << "in line " << mapLineNo[i] << " is not present in the run-block!";
6189  std::cerr << std::endl;
6190  if (mapVec[i]-MSR_PARAM_MAP_OFFSET == 0) {
6191  std::cerr << std::endl << ">> by the way: map must be > 0 ...";
6192  std::cerr << std::endl;
6193  }
6194  }
6195  }
6196 
6197  // clean up
6198  mapVec.clear();
6199  mapBlock.clear();
6200  mapLineNo.clear();
6201 
6202  return result;
6203 }
6204 
6205 //--------------------------------------------------------------------------
6206 // CheckFuncs (public)
6207 //--------------------------------------------------------------------------
6217 {
6218  Bool_t result = true;
6219 
6220  if (fFourierOnly)
6221  return result;
6222 
6223  PIntVector funVec;
6224  PIntVector funBlock;
6225  PIntVector funLineBlockNo;
6226 
6227  TObjArray *tokens = nullptr;
6228  TObjString *ostr = nullptr;
6229  TString str;
6230 
6231  Int_t no;
6232 
6233  // check if func is present in the theory-block
6234  for (UInt_t i=0; i<fTheory.size(); i++) {
6235  if (fTheory[i].fLine.Contains("fun", TString::kIgnoreCase)) {
6236  // func found hence filter out func number
6237  tokens = fTheory[i].fLine.Tokenize(" \t");
6238  for (Int_t j=0; j<tokens->GetEntries(); j++) {
6239  ostr = dynamic_cast<TObjString*>(tokens->At(j));
6240  str = ostr->GetString();
6241  if (str.Contains("fun", TString::kIgnoreCase)) {
6242  if (FilterNumber(str, "fun", MSR_PARAM_FUN_OFFSET, no)) {
6243  funVec.push_back(no);
6244  funBlock.push_back(0); // 0 = theory-block
6245  funLineBlockNo.push_back(fTheory[i].fLineNo);
6246  }
6247  }
6248  }
6249  // clean up tokens
6250  if (tokens) {
6251  delete tokens;
6252  tokens = nullptr;
6253  }
6254  }
6255  }
6256 
6257  // check if func is present in the run-block
6258  for (UInt_t i=0; i<fRuns.size(); i++) {
6259  if (fRuns[i].GetNormParamNo() >= MSR_PARAM_FUN_OFFSET) { // function found
6260  funVec.push_back(fRuns[i].GetNormParamNo());
6261  funBlock.push_back(1); // 1 = run-block
6262  funLineBlockNo.push_back(i+1);
6263  }
6264  }
6265 
6266  // check if present funcs are found in the functions-block
6267  Bool_t found;
6268  for (UInt_t i=0; i<funVec.size(); i++) { // loop over found funcs in theory- and run-block
6269  found = false;
6270  // check if function is present in the functions-block
6271  for (UInt_t j=0; j<fFunctions.size(); j++) {
6272  if (fFunctions[j].fLine.BeginsWith("#") || fFunctions[j].fLine.IsWhitespace())
6273  continue;
6274  str = TString("fun");
6275  str += funVec[i] - MSR_PARAM_FUN_OFFSET;
6276  if (fFunctions[j].fLine.Contains(str, TString::kIgnoreCase)) {
6277  found = true;
6278  break;
6279  }
6280  }
6281  if (!found) { // func not found
6282  result = false;
6283  std::cerr << std::endl << ">> PMsrHandler::CheckFuncs: **ERROR** fun" << funVec[i]-MSR_PARAM_FUN_OFFSET << " found in the ";
6284  if (funBlock[i] == 0)
6285  std::cerr << "theory-block in line " << funLineBlockNo[i] << " is not present in the functions-block!";
6286  else
6287  std::cerr << "run-block No " << funLineBlockNo[i] << " (norm) is not present in the functions-block!";
6288  std::cerr << std::endl;
6289  }
6290  }
6291 
6292  // clean up
6293  funVec.clear();
6294  funBlock.clear();
6295  funLineBlockNo.clear();
6296 
6297  return result;
6298 }
6299 
6300 //--------------------------------------------------------------------------
6301 // CheckHistoGrouping (public)
6302 //--------------------------------------------------------------------------
6311 {
6312  Bool_t result = true;
6313 
6314  for (UInt_t i=0; i<fRuns.size(); i++) {
6315  // check grouping entries are not identical, e.g. forward 1 1 2
6316  if (fRuns[i].GetForwardHistoNoSize() > 1) {
6317  for (UInt_t j=0; j<fRuns[i].GetForwardHistoNoSize(); j++) {
6318  for (UInt_t k=j+1; k<fRuns[i].GetForwardHistoNoSize(); k++) {
6319  if (fRuns[i].GetForwardHistoNo(j) == fRuns[i].GetForwardHistoNo(k)) {
6320  std::cerr << std::endl << ">> PMsrHandler::CheckHistoGrouping: **WARNING** grouping identical histograms!!";
6321  std::cerr << std::endl << ">> run no " << i+1 << ", forward histo " << j+1 << " == forward histo " << k+1 << ".";
6322  std::cerr << std::endl << ">> this really doesn't make any sense, but you are the boss.";
6323  std::cerr << std::endl;
6324  }
6325  }
6326  }
6327  }
6328 
6329  if (fRuns[i].GetBackwardHistoNoSize() > 1) {
6330  for (UInt_t j=0; j<fRuns[i].GetBackwardHistoNoSize(); j++) {
6331  for (UInt_t k=j+1; k<fRuns[i].GetBackwardHistoNoSize(); k++) {
6332  if (fRuns[i].GetBackwardHistoNo(j) == fRuns[i].GetBackwardHistoNo(k)) {
6333  std::cerr << std::endl << ">> PMsrHandler::CheckHistoGrouping: **WARNING** grouping identical histograms!!";
6334  std::cerr << std::endl << ">> run no " << i+1 << ", backward histo " << j+1 << " == backward histo " << k+1 << ".";
6335  std::cerr << std::endl << ">> this really doesn't make any sense, but you are the boss.";
6336  std::cerr << std::endl;
6337  }
6338  }
6339  }
6340  }
6341  }
6342 
6343  return result;
6344 }
6345 
6346 //--------------------------------------------------------------------------
6347 // CheckAddRunParameters (public)
6348 //--------------------------------------------------------------------------
6357 {
6358  Bool_t result = true;
6359 
6360  for (UInt_t i=0; i<fRuns.size(); i++) {
6361  if (fRuns[i].GetRunNameSize() > 1) {
6362  // check concerning the addt0 tags
6363  if (fRuns[i].GetAddT0BinEntries() != 0) {
6364  if (fRuns[i].GetAddT0BinEntries() != fRuns[i].GetRunNameSize()-1) {
6365  std::cerr << std::endl << ">> PMsrHandler::CheckAddRunParameters: **ERROR** # of addt0 != # of addruns.";
6366  std::cerr << std::endl << ">> Run #" << i+1;
6367  std::cerr << std::endl;
6368  result = false;
6369  break;
6370  }
6371  }
6372  }
6373  }
6374 
6375  return result;
6376 }
6377 
6378 //--------------------------------------------------------------------------
6379 // CheckMaxLikelihood (public)
6380 //--------------------------------------------------------------------------
6387 {
6388  if (!fStatistic.fChisq) {
6389  for (UInt_t i=0; i<fRuns.size(); i++) {
6390  if ((fRuns[i].GetFitType() != MSR_FITTYPE_SINGLE_HISTO) && (fGlobal.GetFitType() != MSR_FITTYPE_SINGLE_HISTO) &&
6391  (fRuns[i].GetFitType() != MSR_FITTYPE_MU_MINUS) && (fGlobal.GetFitType() != MSR_FITTYPE_MU_MINUS)) {
6392  std::cerr << std::endl << ">> PMsrHandler::CheckMaxLikelihood: **WARNING**: Maximum Log Likelihood Fit is only implemented";
6393  std::cerr << std::endl << ">> for Single Histogram and Mu Minus Fits. Will fall back to Chi Square Fit.";
6394  std::cerr << std::endl << std::endl;
6395  fStatistic.fChisq = true;
6396  break;
6397  }
6398  }
6399  }
6400 }
6401 
6402 //--------------------------------------------------------------------------
6403 // CheckRRFSettings (public)
6404 //--------------------------------------------------------------------------
6410 {
6411  Bool_t result = true;
6412  Int_t fittype = fGlobal.GetFitType();
6413 
6414  // first set of tests: if RRF parameters are set, check if RRF fit is chosen.
6415  if (fGlobal.GetRRFFreq(fGlobal.GetRRFUnit().Data()) != RRF_FREQ_UNDEF) {
6416  if (fittype != -1) { // check if GLOBAL fittype is set
6417  if ((fittype != MSR_FITTYPE_SINGLE_HISTO_RRF) &&
6418  (fittype != MSR_FITTYPE_ASYM_RRF)) {
6419  std::cerr << std::endl << ">> PMsrHandler::CheckRRFSettings: **ERROR** found GLOBAL fittype " << fittype << " and";
6420  std::cerr << std::endl << ">> RRF settings in the GLOBAL section. This is NOT compatible. Fix it first.";
6421  result = false;
6422  }
6423  } else { // GLOBAL fittype is NOT set
6424  for (UInt_t i=0; i<fRuns.size(); i++) {
6425  fittype = fRuns[i].GetFitType();
6426  if ((fittype != MSR_FITTYPE_SINGLE_HISTO_RRF) &&
6427  (fittype != MSR_FITTYPE_ASYM_RRF)) {
6428  std::cerr << std::endl << ">> PMsrHandler::CheckRRFSettings: **ERROR** found RUN with fittype " << fittype << " and";
6429  std::cerr << std::endl << ">> RRF settings in the GLOBAL section. This is NOT compatible. Fix it first.";
6430  result = false;
6431  break;
6432  }
6433  }
6434  }
6435  } else {
6436  if (fGlobal.GetRRFPacking() != -1) {
6437  std::cerr << std::endl << ">> PMsrHandler::CheckRRFSettings: **WARNING** found in the GLOBAL section rrf_packing, without";
6438  std::cerr << std::endl << ">> rrf_freq. Doesn't make any sense. Will drop rrf_packing";
6439  std::cerr << std::endl << std::endl;
6440  fGlobal.SetRRFPacking(-1);
6441  }
6442  if (fGlobal.GetRRFPhase() != 0.0) {
6443  std::cerr << std::endl << ">> PMsrHandler::CheckRRFSettings: **WARNING** found in the GLOBAL section rrf_phase, without";
6444  std::cerr << std::endl << ">> rrf_freq. Doesn't make any sense. Will drop rrf_phase";
6445  std::cerr << std::endl << std::endl;
6446  fGlobal.SetRRFPhase(0.0);
6447  }
6448  }
6449 
6450  // if not a RRF fit, done at this point
6451  if ((fittype != MSR_FITTYPE_SINGLE_HISTO_RRF) &&
6452  (fittype != MSR_FITTYPE_ASYM_RRF)) {
6453  return true;
6454  }
6455 
6456  // second set of tests: if RRF fit is chosen, do I find the necessary RRF parameters?
6457  fittype = fGlobal.GetFitType();
6458  if ((fittype == MSR_FITTYPE_SINGLE_HISTO_RRF) ||
6459  (fittype == MSR_FITTYPE_ASYM_RRF)) { // make sure RRF freq and RRF packing are set
6460  if (fGlobal.GetRRFFreq(fGlobal.GetRRFUnit().Data()) == RRF_FREQ_UNDEF) {
6461  std::cerr << std::endl << ">> PMsrHandler::CheckRRFSettings: **ERROR** RRF fit chosen, but";
6462  std::cerr << std::endl << ">> no RRF frequency found in the GLOBAL section! Fix it.";
6463  return false;
6464  }
6465  if (fGlobal.GetRRFPacking() == -1) {
6466  std::cerr << std::endl << ">> PMsrHandler::CheckRRFSettings: **ERROR** RRF fit chosen, but";
6467  std::cerr << std::endl << ">> no RRF packing found in the GLOBAL section! Fix it.";
6468  return false;
6469  }
6470  } else { // check single runs for RRF
6471  UInt_t rrfFitCounter = 0;
6472  for (UInt_t i=0; i<fRuns.size(); i++) {
6473  fittype = fRuns[i].GetFitType();
6474  if ((fittype == MSR_FITTYPE_SINGLE_HISTO_RRF) ||
6475  (fittype == MSR_FITTYPE_ASYM_RRF)) { // make sure RRF freq and RRF packing are set
6476  rrfFitCounter++;
6477  }
6478  }
6479  if (rrfFitCounter != fRuns.size()) {
6480  std::cerr << std::endl << ">> PMsrHandler::CheckRRFSettings: **ERROR** #Runs (" << fRuns.size() << ") != # RRF fits found (" << rrfFitCounter << ")";
6481  std::cerr << std::endl << ">> This is currently not supported.";
6482  return false;
6483  }
6484  if (fGlobal.GetRRFFreq(fGlobal.GetRRFUnit().Data()) == RRF_FREQ_UNDEF) {
6485  std::cerr << std::endl << ">> PMsrHandler::CheckRRFSettings: **ERROR** RRF fit chosen, but";
6486  std::cerr << std::endl << ">> no RRF frequency found in the GLOBAL section! Fix it.";
6487  return false;
6488  }
6489  if (fGlobal.GetRRFPacking() == -1) {
6490  std::cerr << std::endl << ">> PMsrHandler::CheckRRFSettings: **ERROR** RRF fit chosen, but";
6491  std::cerr << std::endl << ">> no RRF packing found in the GLOBAL section! Fix it.";
6492  return false;
6493  }
6494  }
6495 
6496  return result;
6497 }
6498 
6499 //--------------------------------------------------------------------------
6500 // GetGroupingString (public)
6501 //--------------------------------------------------------------------------
6509 void PMsrHandler::GetGroupingString(Int_t runNo, TString detector, TString &groupingStr)
6510 {
6511  PIntVector grouping;
6512 
6513  if (!detector.CompareTo("forward", TString::kIgnoreCase)) {
6514  for (UInt_t i=0; i<fRuns[runNo].GetForwardHistoNoSize(); i++)
6515  grouping.push_back(fRuns[runNo].GetForwardHistoNo(i));
6516  MakeDetectorGroupingString("forward", grouping, groupingStr, false);
6517  } else if (!detector.CompareTo("backward", TString::kIgnoreCase)) {
6518  for (UInt_t i=0; i<fRuns[runNo].GetBackwardHistoNoSize(); i++)
6519  grouping.push_back(fRuns[runNo].GetBackwardHistoNo(i));
6520  MakeDetectorGroupingString("backward", grouping, groupingStr, false);
6521  } else {
6522  groupingStr = "**ERROR** unkown detector. Allow forward/backward.";
6523  }
6524 
6525  // clean up
6526  grouping.clear();
6527 }
6528 
6529 //--------------------------------------------------------------------------
6530 // EstimateN0 (public)
6531 //--------------------------------------------------------------------------
6536 {
6537  if (fStartupOptions == nullptr)
6538  return true;
6539 
6540  return fStartupOptions->estimateN0;
6541 }
6542 
6543 //--------------------------------------------------------------------------
6544 // NeededPrecision (private)
6545 //--------------------------------------------------------------------------
6555 UInt_t PMsrHandler::NeededPrecision(Double_t dval, UInt_t precLimit)
6556 {
6557  UInt_t prec=0;
6558 
6559  if (dval == 0.0)
6560  return prec;
6561 
6562  for (UInt_t i=0; i<precLimit; i++) {
6563  if (static_cast<Int_t>(dval*pow(10.0,static_cast<Double_t>(i))) != 0) {
6564  prec = i;
6565  break;
6566  }
6567  }
6568 
6569  if (prec == precLimit) {
6570  std::cerr << std::endl << ">> PMsrHandler::NeededPrecision(): **WARNING** precision limit of " << precLimit << ", requested.";
6571  }
6572 
6573  return prec;
6574 }
6575 
6576 //--------------------------------------------------------------------------
6577 // LastSignifiant (private)
6578 //--------------------------------------------------------------------------
6587 UInt_t PMsrHandler::LastSignificant(Double_t dval, UInt_t precLimit)
6588 {
6589  UInt_t lastSignificant = 2;
6590  UInt_t decimalPoint = 0;
6591 
6592  char str[128];
6593 
6594  snprintf(str, sizeof(str), "%lf", dval);
6595 
6596  // find decimal point
6597  for (UInt_t i=0; i<strlen(str); i++) {
6598  if (str[i] == '.') {
6599  decimalPoint = i;
6600  break;
6601  }
6602  }
6603 
6604  // find last significant digit
6605  for (Int_t i=strlen(str)-1; i>=0; i--) {
6606  if (str[i] != '0') {
6607  if ((static_cast<UInt_t>(i)-decimalPoint) < precLimit)
6608  lastSignificant = static_cast<UInt_t>(i)-decimalPoint;
6609  else
6610  lastSignificant = precLimit;
6611  break;
6612  }
6613  }
6614 
6615  return lastSignificant;
6616 }
6617 
6618 //--------------------------------------------------------------------------
6619 // MakeDetectorGroupingString (private)
6620 //--------------------------------------------------------------------------
6629 void PMsrHandler::MakeDetectorGroupingString(TString str, PIntVector &group, TString &result, Bool_t includeDetector)
6630 {
6631  if (includeDetector) {
6632  result = str + TString(" ");
6633  if (str == TString("forward"))
6634  result += " ";
6635  } else {
6636  str = "";
6637  }
6638 
6639  if (group.size()==0)
6640  return;
6641 
6642  UInt_t i=0, j=0;
6643  do {
6644  j = i;
6645  if (j+1 < group.size()) {
6646  while (group[j]+1 == group[j+1]) {
6647  j++;
6648  if (j == group.size()-1)
6649  break;
6650  }
6651  }
6652 
6653  if (j >= i+2) {
6654  result += group[i];
6655  result += "-";
6656  result += group[j];
6657  i = j+1;
6658  } else {
6659  result += group[i];
6660  i++;
6661  }
6662  result += " ";
6663  } while (i<group.size());
6664 }
6665 
6666 //--------------------------------------------------------------------------
6667 // BeautifyFourierPhaseParameterString (private)
6668 //--------------------------------------------------------------------------
6677 {
6678  TString str("??");
6679  TString formatStr("par%d, par%d");
6680 
6681  if (fFourier.fPhaseParamNo.size() == 0)
6682  return str;
6683 
6684  Int_t phaseRef = fFourier.fPhaseRef;
6685 
6686  if (fFourier.fPhaseParamNo.size() == 1) {
6687  str = TString::Format("par%d", fFourier.fPhaseParamNo[0]);
6688  } else if (fFourier.fPhaseParamNo.size() == 2) {
6689  if (phaseRef == fFourier.fPhaseParamNo[0])
6690  formatStr = "parR%d, par%d";
6691  if (phaseRef == fFourier.fPhaseParamNo[1])
6692  formatStr = "par%d, parR%d";
6693  str = TString::Format(formatStr, fFourier.fPhaseParamNo[0], fFourier.fPhaseParamNo[1]);
6694  } else {
6695  Bool_t phaseIter = true;
6696 
6697  // first check if fPhaseParamNo vector can be compacted into par(X0, offset, #param) form
6698  Int_t offset = fFourier.fPhaseParamNo[1] - fFourier.fPhaseParamNo[0];
6699  for (Int_t i=2; i<fFourier.fPhaseParamNo.size(); i++) {
6700  if (fFourier.fPhaseParamNo[i]-fFourier.fPhaseParamNo[i-1] != offset) {
6701  phaseIter = false;
6702  break;
6703  }
6704  }
6705 
6706  if (phaseIter) {
6707  if (phaseRef != -1) {
6708  str = TString::Format("parR(%d, %d, %lu)", fFourier.fPhaseParamNo[0], offset, fFourier.fPhaseParamNo.size());
6709  } else {
6710  str = TString::Format("par(%d, %d, %lu)", fFourier.fPhaseParamNo[0], offset, fFourier.fPhaseParamNo.size());
6711  }
6712  } else {
6713  str = TString("");
6714  for (Int_t i=0; i<fFourier.fPhaseParamNo.size()-1; i++) {
6715  if (phaseRef == fFourier.fPhaseParamNo[i]) {
6716  str += "parR";
6717  } else {
6718  str += "par";
6719  }
6720  str += fFourier.fPhaseParamNo[i];
6721  str += ", ";
6722  }
6723  if (phaseRef == fFourier.fPhaseParamNo[fFourier.fPhaseParamNo.size()-1]) {
6724  str += "parR";
6725  } else {
6726  str += "par";
6727  }
6728  str += fFourier.fPhaseParamNo[fFourier.fPhaseParamNo.size()-1];
6729  }
6730  }
6731 
6732  return str;
6733 }
6734 
6735 //--------------------------------------------------------------------------
6736 // CheckLegacyLifetimecorrection (private)
6737 //--------------------------------------------------------------------------
6745 {
6746  UInt_t idx=0;
6747  for (UInt_t i=0; i<fPlots.size(); i++) {
6748  for (UInt_t j=0; j<fPlots[i].fRuns.size(); j++) {
6749  idx = fPlots[i].fRuns[j]-1;
6750  if (fRuns[idx].IsLifetimeCorrected()) {
6751  fPlots[i].fLifeTimeCorrection = true;
6752  }
6753  }
6754  }
6755 }
6756 
6757 // end ---------------------------------------------------------------------
virtual ~PMsrHandler()
Definition: PMsrHandler.cpp:88
PMsrRunList fRuns
holds a list of run information
Definition: PMsrHandler.h:125
virtual UInt_t GetT0BinSize()
Definition: PMusr.h:583
std::unique_ptr< PFunctionHandler > fFuncHandler
needed to parse functions
Definition: PMsrHandler.h:133
virtual TString GetRRFUnit()
Definition: PMusr.cpp:834
virtual void SetDataRange(Int_t ival, Int_t idx)
Definition: PMusr.cpp:1672
#define MSR_PLOT_ASYM_RRF
Definition: PMusr.h:119
PMsrParamList fParam
holds a list of the fit parameters
Definition: PMsrHandler.h:121
#define MSR_FITTYPE_BNMR
Definition: PMusr.h:111
Bool_t fCopyStatisticsBlock
flag, if true: just copy to old statistics block (musrt0), otherwise write a new one (musrfit) ...
Definition: PMsrHandler.h:137
virtual Double_t GetAddT0Bin(UInt_t addRunIdx, UInt_t histoIdx)
Definition: PMusr.cpp:1001
PMsrLines fStatLines
statistics block in msr-file clear text
Definition: PMusr.h:810
Double_t fRRFFreq
RRF frequency.
Definition: PMusr.h:792
#define FOURIER_APOD_WEAK
Definition: PMusr.h:139
PMsrPlotList fPlots
holds a list of the plot input parameters
Definition: PMsrHandler.h:128
PStartupOptions * fStartupOptions
contains information about startup options from the musrfit_startup.xml
Definition: PMsrHandler.h:116
Bool_t writeExpectedChisq
if set to true, expected chisq and chisq per block will be written
Definition: PMusr.h:849
Bool_t fFourierBlockPresent
flag indicating if a Fourier block is present in the msr-file
Definition: PMusr.h:761
virtual Int_t GetNoOfFuncs()
Definition: PMsrHandler.h:93
virtual Int_t GetDataRange(UInt_t idx)
Definition: PMusr.cpp:895
virtual Double_t GetT0Bin(UInt_t idx=0)
Definition: PMusr.cpp:935
virtual void SetFitRangeOffset(Int_t ival, UInt_t idx)
Definition: PMusr.cpp:1865
virtual void CleanUp()
Definition: PMusr.cpp:1178
virtual Bool_t HandleTheoryEntry(PMsrLines &line)
Bool_t estimateN0
if set to true, for single histogram fits N0 will be estimated
Definition: PMusr.h:850
virtual void SetFitRangeOffset(Int_t ival, UInt_t idx)
Definition: PMusr.cpp:1105
virtual Int_t GetRRFUnitTag()
Definition: PMusr.h:578
virtual void FillParameterInUse(PMsrLines &theory, PMsrLines &funcs, PMsrLines &run)
virtual UInt_t GetAddT0BinEntries()
Definition: PMusr.h:585
Int_t fPlotTag
tag used for initial plot. 0=real, 1=imaginary, 2=real & imaginary (default), 3=power, 4=phase
Definition: PMusr.h:766
virtual void SetBackwardHistoNo(Int_t histoNo, Int_t idx=-1)
Definition: PMusr.cpp:1465
virtual Int_t GetFitRangeOffset(UInt_t idx)
Definition: PMusr.cpp:1088
virtual void SetRunName(TString &str, Int_t idx=-1)
Definition: PMusr.cpp:1249
#define MSR_FITTYPE_SINGLE_HISTO_RRF
Definition: PMusr.h:107
virtual void SetBeamline(TString &str, Int_t idx=-1)
Definition: PMusr.cpp:1291
#define FOURIER_PLOT_POWER
Definition: PMusr.h:147
TString fMsrFileDirectoryPath
msr-file directory path
Definition: PMsrHandler.h:119
PMsrFourierStructure fFourier
holds the parameters used for the Fourier transform
Definition: PMsrHandler.h:127
virtual Bool_t HandleRunEntry(PMsrLines &line)
#define MSR_TAG_FUNCTIONS
Definition: PMusr.h:96
virtual void SetRRFPhase(Double_t phase)
Definition: PMusr.h:596
PDoubleVector fMinPerHisto
chisq or max. likelihood per histo
Definition: PMusr.h:814
#define MSR_FITTYPE_SINGLE_HISTO
Definition: PMusr.h:106
#define MSR_TAG_PLOT
Definition: PMusr.h:101
virtual void SetYDataIndex(Int_t ival)
Definition: PMusr.h:703
virtual void SetYDataLabel(TString &str)
Definition: PMusr.h:705
virtual Bool_t FilterNumber(TString str, const Char_t *filter, Int_t offset, Int_t &no)
virtual void SetMsrDataRangeEntry(UInt_t runNo, UInt_t idx, Int_t bin)
Int_t fPhaseRef
phase reference for relative phase(s)
Definition: PMusr.h:767
#define RRF_FREQ_UNDEF
Definition: PMusr.h:160
UInt_t fRRFPacking
rotating reference frame (RRF) packing
Definition: PMusr.h:791
#define RRF_UNIT_MHz
Definition: PMusr.h:155
Double_t fValue
value
Definition: PMusr.h:549
virtual void SetMap(Int_t mapVal, Int_t idx=-1)
Definition: PMusr.cpp:1505
#define PRUN_MU_MINUS
Definition: PMusr.h:60
#define RRF_UNIT_kHz
Definition: PMusr.h:154
#define MSR_PLOT_BNMR
Definition: PMusr.h:121
virtual void SetXDataLabel(TString &str)
Definition: PMusr.h:704
virtual Bool_t CheckAddRunParameters()
virtual UInt_t NeededPrecision(Double_t dval, UInt_t precLimit=13)
#define MSR_PLOT_SINGLE_HISTO
Definition: PMusr.h:116
#define PMUSR_MSR_FILE_NOT_FOUND
Definition: PMusr.h:47
virtual void SetMsrT0Entry(UInt_t runNo, UInt_t idx, Double_t bin)
Double_t fMin
chisq or max. likelihood
Definition: PMusr.h:813
virtual Int_t GetRRFPacking()
Definition: PMusr.h:580
virtual void SetFitRangeInBins(Bool_t bval)
Definition: PMusr.h:602
#define MSR_PARAM_MAP_OFFSET
Definition: PMusr.h:126
#define FOURIER_PLOT_IMAG
Definition: PMusr.h:145
Bool_t fValid
flag showing if the statistics block is valid, i.e. a fit took place which converged ...
Definition: PMusr.h:809
Int_t fViewPacking
-1 -> use the run packing to generate the view, otherwise is fViewPacking for the binning of ALL runs...
Definition: PMusr.h:785
virtual void SetFileFormat(TString &str, Int_t idx=-1)
Definition: PMusr.cpp:1375
#define FOURIER_PLOT_REAL
Definition: PMusr.h:144
Bool_t fDCCorrected
if set true, the dc offset of the signal/theory will be removed before the FFT is made...
Definition: PMusr.h:763
virtual void SetFitRangeInBins(Bool_t bval)
Definition: PMusr.h:698
std::vector< Int_t > PIntVector
Definition: PMusr.h:178
virtual UInt_t GetFuncIndex(Int_t funNo)
Definition: PMsrHandler.h:95
virtual Bool_t IsFitRangeInBin()
Definition: PMusr.h:588
virtual Bool_t ParseFourierPhaseParIterVector(PMsrFourierStructure &fourier, const TString &str, Bool_t &error)
#define FOURIER_UNIT_CYCLES
Definition: PMusr.h:135
PMsrHandler(const Char_t *fileName, PStartupOptions *startupOptions=0, const Bool_t fourierOnly=false)
Definition: PMsrHandler.cpp:52
std::vector< UInt_t > PUIntVector
Definition: PMusr.h:172
PIntVector fParamInUse
array holding the information if a particular parameter is used at all, i.e. if the theory is using i...
Definition: PMsrHandler.h:135
virtual Bool_t IsPresent()
Definition: PMusr.h:575
virtual void MakeDetectorGroupingString(TString str, PIntVector &group, TString &result, Bool_t includeDetector=true)
#define FOURIER_PLOT_REAL_AND_IMAG
Definition: PMusr.h:146
virtual Bool_t ParseFourierPhaseParVector(PMsrFourierStructure &fourier, const TString &str, Bool_t &error)
virtual Double_t GetRRFFreq(const char *unit)
Definition: PMusr.cpp:762
virtual void SetAlphaParamNo(Int_t ival)
Definition: PMusr.h:682
virtual Bool_t HandlePlotEntry(PMsrLines &line)
virtual Bool_t CheckHistoGrouping()
#define PRUN_ASYMMETRY_BNMR
Definition: PMusr.h:61
Bool_t fLowerBoundaryPresent
flag showing if a lower boundary is present
Definition: PMusr.h:553
virtual Bool_t HandleFunctionsEntry(PMsrLines &line)
#define MSR_PARAM_FUN_OFFSET
Definition: PMusr.h:127
#define FOURIER_UNIT_NOT_GIVEN
Definition: PMusr.h:131
#define FOURIER_UNIT_FREQ
Definition: PMusr.h:134
virtual Int_t WriteMsrLogFile(const Bool_t messages=true)
virtual Bool_t HandleCommandsEntry(PMsrLines &line)
#define MSR_TAG_RUN
Definition: PMusr.h:98
virtual void SetBkgFitParamNo(Int_t ival)
Definition: PMusr.h:685
virtual Int_t WriteMsrFile(const Char_t *filename, std::map< UInt_t, TString > *commentsPAR=0, std::map< UInt_t, TString > *commentsTHE=0, std::map< UInt_t, TString > *commentsFUN=0, std::map< UInt_t, TString > *commentsRUN=0)
Int_t fApodization
tag indicating the kind of apodization wished, 0=no appodization (default), 1=weak, 2=medium, 3=strong (for details see the docu)
Definition: PMusr.h:765
#define MSR_TAG_COMMANDS
Definition: PMusr.h:99
PMsrStatisticStructure fStatistic
holds the statistic info
Definition: PMsrHandler.h:129
Int_t fNo
parameter number
Definition: PMusr.h:547
virtual Bool_t CheckUniquenessOfParamNames(UInt_t &parX, UInt_t &parY)
#define MSR_FITTYPE_NON_MUSR
Definition: PMusr.h:112
virtual Bool_t HandleFourierEntry(PMsrLines &line)
virtual Bool_t CheckRunBlockIntegrity()
Bool_t fUpperBoundaryPresent
flag showing if an upper boundary is present
Definition: PMusr.h:555
#define PRUN_SINGLE_HISTO_RRF
Definition: PMusr.h:57
Bool_t fLogX
yes -> x-axis in log-scale, no (default) -> x-axis in lin-scale
Definition: PMusr.h:783
#define MSR_TAG_STATISTIC
Definition: PMusr.h:102
#define MSR_PLOT_NON_MUSR
Definition: PMusr.h:122
Double_t fUpperBoundary
upper boundary for the fit parameter
Definition: PMusr.h:556
#define MSR_TAG_FOURIER
Definition: PMusr.h:100
virtual void SetT0Bin(Double_t dval, Int_t idx=-1)
Definition: PMusr.cpp:1712
#define RRF_UNIT_T
Definition: PMusr.h:158
#define PMUSR_MSR_FILE_WRITE_ERROR
Definition: PMusr.h:52
virtual Int_t ParameterInUse(UInt_t paramNo)
Int_t fLineNo
original line number of the msr-file
Definition: PMusr.h:531
#define PRUN_ASYMMETRY_RRF
Definition: PMusr.h:59
virtual void SetForwardHistoNo(Int_t histoNo, Int_t idx=-1)
Definition: PMusr.cpp:1421
Bool_t fLogY
yes -> y-axis in log-scale, no (default) -> y-axis in lin-scale
Definition: PMusr.h:784
Double_t fStep
step / error / neg_error, depending on the situation
Definition: PMusr.h:550
virtual Bool_t CheckMaps()
std::vector< PMsrLineStructure > PMsrLines
Definition: PMusr.h:539
PIntVector fPhaseParamNo
parameter number(s) if used instead of a phase value
Definition: PMusr.h:768
#define RRF_UNIT_G
Definition: PMusr.h:157
Double_t fRangeForPhaseCorrection[2]
field/frequency range for automatic phase correction
Definition: PMusr.h:770
#define RRF_UNIT_Mcs
Definition: PMusr.h:156
PMsrLines fFunctions
holds the user defined functions
Definition: PMsrHandler.h:123
TString fLine
msr-file line
Definition: PMusr.h:532
PMsrLines fCommands
holds a list of the minuit commands
Definition: PMsrHandler.h:126
PDoubleVector fMinExpectedPerHisto
expected pre histo chi2 or max. likelihood
Definition: PMusr.h:817
virtual void SetAddT0Bin(Double_t dval, UInt_t addRunIdx, UInt_t histoNoIdx)
Definition: PMusr.cpp:1788
virtual Bool_t CheckRRFSettings()
#define PRUN_NON_MUSR
Definition: PMusr.h:62
virtual void RemoveComment(const TString &str, TString &truncStr)
TString fFileName
file name of the msr-file
Definition: PMsrHandler.h:118
#define MSR_PLOT_SINGLE_HISTO_RRF
Definition: PMusr.h:117
virtual Bool_t SetMsrParamStep(UInt_t i, Double_t value)
virtual void SetMsrAddT0Entry(UInt_t runNo, UInt_t addRunIdx, UInt_t histoIdx, Double_t bin)
Int_t fMsrBlockCounter
used to select the proper msr-block
Definition: PMsrHandler.h:131
PDoubleVector fTmin
time minimum
Definition: PMusr.h:787
PDoubleVector fTmax
time maximum
Definition: PMusr.h:788
PDoubleVector fPhase
phase(s)
Definition: PMusr.h:769
virtual void SetLifetimeParamNo(Int_t ival)
Definition: PMusr.h:686
virtual void SetInstitute(TString &str, Int_t idx=-1)
Definition: PMusr.cpp:1333
virtual void SetAddT0Bin(Double_t dval, UInt_t addRunIdx, UInt_t histoNoIdx)
Definition: PMusr.cpp:1028
Int_t fUnits
flag used to indicate the units. 1=field units (G); 2=field units (T); 3=frequency units (MHz); 4=Mc/...
Definition: PMusr.h:762
virtual UInt_t LastSignificant(Double_t dval, UInt_t precLimit=6)
virtual Int_t ReadMsrFile()
#define MSR_TAG_TITLE
Definition: PMusr.h:93
Int_t fPlotType
plot type
Definition: PMusr.h:780
virtual void SetRRFPacking(Int_t pack)
Definition: PMusr.cpp:873
Int_t fRRFPhaseParamNo
parameter number if used instead of a RRF phase value
Definition: PMusr.h:794
#define MSR_FITTYPE_MU_MINUS
Definition: PMusr.h:110
#define PMUSR_UNDEFINED
Definition: PMusr.h:89
virtual void InitFourierParameterStructure(PMsrFourierStructure &fourier)
virtual void SetT0Bin(Double_t dval, Int_t idx=-1)
Definition: PMusr.cpp:952
#define PMUSR_MSR_SYNTAX_ERROR
Definition: PMusr.h:49
#define FOURIER_APOD_NONE
Definition: PMusr.h:138
virtual void SetNormParamNo(Int_t ival)
Definition: PMusr.h:684
Bool_t fFourierOnly
flag indicating if Fourier transform only is wished. If yes, some part of the msr-file blocks are not...
Definition: PMsrHandler.h:115
virtual void SetFitType(Int_t ival)
Definition: PMusr.h:598
#define MSR_PLOT_MU_MINUS
Definition: PMusr.h:120
#define FOURIER_PLOT_PHASE
Definition: PMusr.h:148
#define FOURIER_UNIT_GAUSS
Definition: PMusr.h:132
virtual Double_t GetRRFPhase()
Definition: PMusr.h:579
virtual void CheckMaxLikelihood()
virtual Int_t GetFitType()
Definition: PMusr.h:581
TString fName
name
Definition: PMusr.h:548
virtual Bool_t SetMsrParamValue(UInt_t i, Double_t value)
Bool_t fChisq
flag telling if min = chi2 or min = max.likelihood
Definition: PMusr.h:812
virtual void SetBkgRange(Int_t ival, Int_t idx)
Definition: PMusr.cpp:1630
virtual void SetFitRange(Double_t dval, UInt_t idx)
Definition: PMusr.cpp:1828
#define FOURIER_APOD_NOT_GIVEN
Definition: PMusr.h:137
virtual void SetRRFFreq(Double_t freq, const char *unit)
Definition: PMusr.cpp:806
Bool_t fUseFitRanges
yes -> use the fit ranges to plot the data, no (default) -> use range information if present ...
Definition: PMusr.h:782
PIntVector fRuns
list of runs to be plotted
Definition: PMusr.h:786
virtual void SetPacking(Int_t ival)
Definition: PMusr.h:701
#define FOURIER_UNIT_TESLA
Definition: PMusr.h:133
virtual void SetGlobalPresent(Bool_t bval)
Definition: PMusr.h:594
virtual UInt_t GetNoOfFitParameters(UInt_t idx)
Double_t fMinExpected
expected total chi2 or max. likelihood
Definition: PMusr.h:816
Double_t fLowerBoundary
lower boundary for the fit parameter
Definition: PMusr.h:554
#define FOURIER_PLOT_PHASE_OPT_REAL
Definition: PMusr.h:149
#define PMUSR_MSR_LOG_FILE_WRITE_ERROR
Definition: PMusr.h:51
virtual void SetLifetimeCorrection(Bool_t bval)
Definition: PMusr.h:687
#define FOURIER_PLOT_NOT_GIVEN
Definition: PMusr.h:143
virtual Int_t GetAddT0BinSize(UInt_t addRunIdx)
Definition: PMusr.cpp:977
if(xmlFile.is_open())
virtual void SetFitRange(Double_t dval, UInt_t idx)
Definition: PMusr.cpp:1068
virtual Bool_t HandleStatisticEntry(PMsrLines &line)
UInt_t fRRFUnit
RRF frequency unit. 0=kHz, 1=MHz, 2=Mc/s, 3=Gauss, 4=Tesla.
Definition: PMusr.h:793
virtual void GetGroupingString(Int_t runNo, TString detector, TString &groupingStr)
#define MSR_TAG_THEORY
Definition: PMusr.h:95
virtual Bool_t HandleFitParameterEntry(PMsrLines &line)
Bool_t fLifeTimeCorrection
needed for single histo. If yes, only the asymmetry is shown, otherweise the positron spectrum ...
Definition: PMusr.h:781
virtual void SetXDataIndex(Int_t ival)
Definition: PMusr.h:702
#define PRUN_ASYMMETRY
Definition: PMusr.h:58
Int_t fFourierPower
i.e. zero padding up to 2^fFourierPower, default = 0 which means NO zero padding
Definition: PMusr.h:764
virtual PIntVector * GetMap()
Definition: PMusr.h:650
#define RRF_UNIT_UNDEF
Definition: PMusr.h:153
#define MSR_FITTYPE_ASYM_RRF
Definition: PMusr.h:109
#define PMUSR_SUCCESS
Definition: PMusr.h:44
Double_t fPosError
positive error if present
Definition: PMusr.h:552
UInt_t fNdf
number of degrees of freedom
Definition: PMusr.h:815
#define MSR_FITTYPE_ASYM
Definition: PMusr.h:108
virtual void SetMsrBkgRangeEntry(UInt_t runNo, UInt_t idx, Int_t bin)
#define FOURIER_APOD_STRONG
Definition: PMusr.h:141
virtual void CheckLegacyLifetimecorrection()
virtual TString BeautifyFourierPhaseParameterString()
return status
PDoubleVector fYmin
asymmetry/counts minimum
Definition: PMusr.h:789
virtual void SetBetaParamNo(Int_t ival)
Definition: PMusr.h:683
PMsrLines fTheory
holds the theory definition
Definition: PMsrHandler.h:122
virtual Bool_t SetMsrParamPosErrorPresent(UInt_t i, Bool_t value)
Double_t fPlotRange[2]
field/frequency plot range
Definition: PMusr.h:771
PDoubleVector fYmax
asymmetry/counts maximum
Definition: PMusr.h:790
TString fTitle
holds the title string of the msr-file
Definition: PMsrHandler.h:120
Double_t fRRFPhase
RRF phase.
Definition: PMusr.h:795
virtual Bool_t EstimateN0()
Int_t fNoOfParams
how many parameters are given
Definition: PMusr.h:546
virtual void SetDataRange(Int_t ival, Int_t idx)
Definition: PMusr.cpp:912
virtual void SetPacking(Int_t ival)
Definition: PMusr.h:605
virtual Int_t GetPacking()
Definition: PMusr.h:591
virtual Double_t GetFitRange(UInt_t idx)
Definition: PMusr.cpp:1051
PMsrGlobalBlock fGlobal
holds the information of the global section
Definition: PMsrHandler.h:124
#define FOURIER_APOD_MEDIUM
Definition: PMusr.h:140
TString fDate
string holding fitting date and time
Definition: PMusr.h:811
PUIntVector fNdfPerHisto
number of degrees of freedom per histo
Definition: PMusr.h:818
#define PRUN_SINGLE_HISTO
Definition: PMusr.h:56
virtual Bool_t SetMsrParamPosError(UInt_t i, Double_t value)
virtual void SetBkgFix(Double_t dval, Int_t idx)
Definition: PMusr.cpp:1589
Bool_t fPosErrorPresent
positive error is defined (as a number)
Definition: PMusr.h:551
virtual Bool_t HandleGlobalEntry(PMsrLines &line)
virtual void SetFitType(Int_t ival)
Definition: PMusr.h:681
#define MSR_PLOT_ASYM
Definition: PMusr.h:118
#define MSR_TAG_FITPARAMETER
Definition: PMusr.h:94
virtual Bool_t CheckFuncs()
virtual Bool_t ParseFourierPhaseValueVector(PMsrFourierStructure &fourier, const TString &str, Bool_t &error)
std::vector< Bool_t > PBoolVector
Definition: PMusr.h:166
#define MSR_TAG_GLOBAL
Definition: PMusr.h:97