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