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