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