musrfit 1.10.0
PRunSingleHistoRRF.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 PRunSingleHistoRRF.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#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
34#ifdef HAVE_GOMP
35#include <omp.h>
36#endif
37
38#include <cmath>
39#include <iostream>
40#include <fstream>
41#include <memory>
42#include <string>
43#include <vector>
44
45#include <TString.h>
46#include <TH1F.h>
47
48#include "PMusr.h"
49#include "PStringUtils.h"
50#include "PFourier.h"
51#include "PRunSingleHistoRRF.h"
52
53//--------------------------------------------------------------------------
54// Constructor
55//--------------------------------------------------------------------------
75{
76 fNoOfFitBins = 0;
77 fBackground = 0.0;
78 fBkgErr = 1.0;
79 fRRFPacking = -1;
80 fTheoAsData = false;
81
82 // the 2 following variables are need in case fit range is given in bins, and since
83 // the fit range can be changed in the command block, these variables need to be accessible
84 fGoodBins[0] = -1;
85 fGoodBins[1] = -1;
86
87 fN0EstimateEndTime = 1.0; // end time in (us) over which N0 is estimated.
88}
89
90//--------------------------------------------------------------------------
91// Constructor
92//--------------------------------------------------------------------------
133PRunSingleHistoRRF::PRunSingleHistoRRF(PMsrHandler *msrInfo, PRunDataHandler *rawData, UInt_t runNo, EPMusrHandleTag tag, Bool_t theoAsData) :
134 PRunBase(msrInfo, rawData, runNo, tag), fTheoAsData(theoAsData)
135{
136 fNoOfFitBins = 0;
137
138 PMsrGlobalBlock *global = msrInfo->GetMsrGlobal();
139
140 if (!global->IsPresent()) {
141 std::cerr << std::endl << ">> PRunSingleHistoRRF::PRunSingleHistoRRF(): **SEVERE ERROR**: no GLOBAL-block present!";
142 std::cerr << std::endl << ">> For Single Histo RRF the GLOBAL-block is mandatory! Please fix this first.";
143 std::cerr << std::endl;
144 fValid = false;
145 return;
146 }
147
148 if (!global->GetRRFUnit().CompareTo("??")) {
149 std::cerr << std::endl << ">> PRunSingleHistoRRF::PRunSingleHistoRRF(): **SEVERE ERROR**: no RRF-Frequency found!";
150 std::cerr << std::endl;
151 fValid = false;
152 return;
153 }
154
155 fRRFPacking = global->GetRRFPacking();
156 if (fRRFPacking == -1) {
157 std::cerr << std::endl << ">> PRunSingleHistoRRF::PRunSingleHistoRRF(): **SEVERE ERROR**: no RRF-Packing found!";
158 std::cerr << std::endl;
159 fValid = false;
160 return;
161 }
162
163 // the 2 following variables are need in case fit range is given in bins, and since
164 // the fit range can be changed in the command block, these variables need to be accessible
165 fGoodBins[0] = -1;
166 fGoodBins[1] = -1;
167
168 fN0EstimateEndTime = 1.0; // end time in (us) over which N0 is estimated.
169
170 if (!PrepareData()) {
171 std::cerr << std::endl << ">> PRunSingleHistoRRF::PRunSingleHistoRRF(): **SEVERE ERROR**: Couldn't prepare data for fitting!";
172 std::cerr << std::endl << ">> This is very bad :-(, will quit ...";
173 std::cerr << std::endl;
174 fValid = false;
175 }
176}
177
178//--------------------------------------------------------------------------
179// Destructor
180//--------------------------------------------------------------------------
198
199//--------------------------------------------------------------------------
200// CalcChiSquare (public)
201//--------------------------------------------------------------------------
240Double_t PRunSingleHistoRRF::CalcChiSquare(const std::vector<Double_t>& par)
241{
242 Double_t chisq = 0.0;
243 Double_t diff = 0.0;
244
245 // calculate functions
246 for (Int_t i=0; i<fMsrInfo->GetNoOfFuncs(); i++) {
247 UInt_t funcNo = fMsrInfo->GetFuncNo(i);
248 fFuncValues[i] = fMsrInfo->EvalFunc(funcNo, *fRunInfo->GetMap(), par, fMetaData);
249 }
250
251 // calculate chi square
252 Double_t time(1.0);
253 Int_t i;
254
255 // Calculate the theory function once to ensure one function evaluation for the current set of parameters.
256 // This is needed for the LF and user functions where some non-thread-save calculations only need to be calculated once
257 // for a given set of parameters---which should be done outside of the parallelized loop.
258 // For all other functions it means a tiny and acceptable overhead.
259 time = fTheory->Func(time, par, fFuncValues);
260
261 #ifdef HAVE_GOMP
262 Int_t chunk = (fEndTimeBin - fStartTimeBin)/omp_get_num_procs();
263 if (chunk < 10)
264 chunk = 10;
265 #pragma omp parallel for default(shared) private(i,time,diff) schedule(dynamic,chunk) reduction(+:chisq)
266 #endif
267 for (i=fStartTimeBin; i<fEndTimeBin; ++i) {
268 time = fData.GetDataTimeStart() + static_cast<Double_t>(i)*fData.GetDataTimeStep();
269 diff = fData.GetValue()->at(i) - fTheory->Func(time, par, fFuncValues);
270 chisq += diff*diff / (fData.GetError()->at(i)*fData.GetError()->at(i));
271 }
272
273 return chisq;
274}
275
276//--------------------------------------------------------------------------
277// CalcChiSquareExpected (public)
278//--------------------------------------------------------------------------
307Double_t PRunSingleHistoRRF::CalcChiSquareExpected(const std::vector<Double_t>& par)
308{
309 Double_t chisq = 0.0;
310 Double_t diff = 0.0;
311 Double_t theo = 0.0;
312
313 // calculate functions
314 for (Int_t i=0; i<fMsrInfo->GetNoOfFuncs(); i++) {
315 UInt_t funcNo = fMsrInfo->GetFuncNo(i);
316 fFuncValues[i] = fMsrInfo->EvalFunc(funcNo, *fRunInfo->GetMap(), par, fMetaData);
317 }
318
319 // calculate chi square
320 Double_t time(1.0);
321 Int_t i;
322
323 // Calculate the theory function once to ensure one function evaluation for the current set of parameters.
324 // This is needed for the LF and user functions where some non-thread-save calculations only need to be calculated once
325 // for a given set of parameters---which should be done outside of the parallelized loop.
326 // For all other functions it means a tiny and acceptable overhead.
327 time = fTheory->Func(time, par, fFuncValues);
328
329 #ifdef HAVE_GOMP
330 Int_t chunk = (fEndTimeBin - fStartTimeBin)/omp_get_num_procs();
331 if (chunk < 10)
332 chunk = 10;
333 #pragma omp parallel for default(shared) private(i,time,diff) schedule(dynamic,chunk) reduction(+:chisq)
334 #endif
335 for (i=fStartTimeBin; i < fEndTimeBin; ++i) {
336 time = fData.GetDataTimeStart() + static_cast<Double_t>(i)*fData.GetDataTimeStep();
337 theo = fTheory->Func(time, par, fFuncValues);
338 diff = fData.GetValue()->at(i) - theo;
339 chisq += diff*diff / theo;
340 }
341
342 return chisq;
343}
344
345//--------------------------------------------------------------------------
346// CalcMaxLikelihood (public)
347//--------------------------------------------------------------------------
379Double_t PRunSingleHistoRRF::CalcMaxLikelihood(const std::vector<Double_t>& par)
380{
381 // not yet implemented
382
383 return 0.0;
384}
385
386//--------------------------------------------------------------------------
387// CalcTheory (public)
388//--------------------------------------------------------------------------
425{
426 // feed the parameter vector
427 std::vector<Double_t> par;
428 PMsrParamList *paramList = fMsrInfo->GetMsrParamList();
429 for (UInt_t i=0; i<paramList->size(); i++)
430 par.push_back((*paramList)[i].fValue);
431
432 // calculate functions
433 for (Int_t i=0; i<fMsrInfo->GetNoOfFuncs(); i++) {
434 fFuncValues[i] = fMsrInfo->EvalFunc(fMsrInfo->GetFuncNo(i), *fRunInfo->GetMap(), par, fMetaData);
435 }
436
437 // calculate theory
438 UInt_t size = fData.GetValue()->size();
439 Double_t start = fData.GetDataTimeStart();
440 Double_t resolution = fData.GetDataTimeStep();
441 Double_t time;
442 for (UInt_t i=0; i<size; i++) {
443 time = start + static_cast<Double_t>(i)*resolution;
444 fData.AppendTheoryValue(fTheory->Func(time, par, fFuncValues));
445 }
446
447 // clean up
448 par.clear();
449}
450
451//--------------------------------------------------------------------------
452// GetNoOfFitBins (public)
453//--------------------------------------------------------------------------
474{
476
477 return fNoOfFitBins;
478}
479
480//--------------------------------------------------------------------------
481// SetFitRangeBin (public)
482//--------------------------------------------------------------------------
530void PRunSingleHistoRRF::SetFitRangeBin(const TString fitRange)
531{
532 TString str;
533 Ssiz_t idx = -1;
534 Int_t offset = 0;
535
536 std::vector<std::string> tok = PStringUtils::Split(fitRange.Data(), " \t");
537
538 if (tok.size() == 3) { // structure FIT_RANGE fgb+n0 lgb-n1
539 // handle fgb+n0 entry
540 str = tok[1];
541 // check if there is an offset present
542 idx = str.First("+");
543 if (idx != -1) { // offset present
544 str.Remove(0, idx+1);
545 if (str.IsFloat()) // if str is a valid number, convert is to an integer
546 offset = str.Atoi();
547 }
548 fFitStartTime = (fGoodBins[0] + offset - fT0s[0]) * fTimeResolution;
549
550 // handle lgb-n1 entry
551 str = tok[2];
552 // check if there is an offset present
553 idx = str.First("-");
554 if (idx != -1) { // offset present
555 str.Remove(0, idx+1);
556 if (str.IsFloat()) // if str is a valid number, convert is to an integer
557 offset = str.Atoi();
558 }
559 fFitEndTime = (fGoodBins[1] - offset - fT0s[0]) * fTimeResolution;
560 } else if ((tok.size() > 3) && (tok.size() % 2 == 1)) { // structure FIT_RANGE fgb[+n00] lgb[-n01] [fgb[+n10] lgb[-n11] ... fgb[+nN0] lgb[-nN1]]
561 UInt_t pos = 2*(fRunNo+1)-1;
562
563 if (pos + 1 >= tok.size()) {
564 std::cerr << std::endl << ">> PRunSingleHistoRRF::SetFitRangeBin(): **ERROR** invalid FIT_RANGE command found: '" << fitRange << "'";
565 std::cerr << std::endl << ">> will ignore it. Sorry ..." << std::endl;
566 } else {
567 // handle fgb+n0 entry
568 str = tok[pos];
569 // check if there is an offset present
570 idx = str.First("+");
571 if (idx != -1) { // offset present
572 str.Remove(0, idx+1);
573 if (str.IsFloat()) // if str is a valid number, convert is to an integer
574 offset = str.Atoi();
575 }
576 fFitStartTime = (fGoodBins[0] + offset - fT0s[0]) * fTimeResolution;
577
578 // handle lgb-n1 entry
579 str = tok[pos+1];
580 // check if there is an offset present
581 idx = str.First("-");
582 if (idx != -1) { // offset present
583 str.Remove(0, idx+1);
584 if (str.IsFloat()) // if str is a valid number, convert is to an integer
585 offset = str.Atoi();
586 }
587 fFitEndTime = (fGoodBins[1] - offset - fT0s[0]) * fTimeResolution;
588 }
589 } else { // error
590 std::cerr << std::endl << ">> PRunSingleHistoRRF::SetFitRangeBin(): **ERROR** invalid FIT_RANGE command found: '" << fitRange << "'";
591 std::cerr << std::endl << ">> will ignore it. Sorry ..." << std::endl;
592 }
593}
594
595//--------------------------------------------------------------------------
596// CalcNoOfFitBins (public)
597//--------------------------------------------------------------------------
632{
633 // In order not having to loop over all bins and to stay consistent with the chisq method, calculate the start and end bins explicitly
634 fStartTimeBin = static_cast<Int_t>(ceil((fFitStartTime - fData.GetDataTimeStart())/fData.GetDataTimeStep()));
635 if (fStartTimeBin < 0)
636 fStartTimeBin = 0;
637 fEndTimeBin = static_cast<Int_t>(floor((fFitEndTime - fData.GetDataTimeStart())/fData.GetDataTimeStep())) + 1;
638 if (fEndTimeBin > static_cast<Int_t>(fData.GetValue()->size()))
639 fEndTimeBin = fData.GetValue()->size();
640
643 else
644 fNoOfFitBins = 0;
645}
646
647//--------------------------------------------------------------------------
648// PrepareData (protected)
649//--------------------------------------------------------------------------
697{
698 Bool_t success = true;
699
700 if (!fValid)
701 return false;
702
703 // keep the Global block info
704 PMsrGlobalBlock *globalBlock = fMsrInfo->GetMsrGlobal();
705
706 // get the proper run
707 PRawRunData* runData = fRawData->GetRunData(*fRunInfo->GetRunName());
708 if (!runData) { // couldn't get run
709 std::cerr << std::endl << ">> PRunSingleHistoRRF::PrepareData(): **ERROR** Couldn't get run " << fRunInfo->GetRunName()->Data() << "!";
710 std::cerr << std::endl;
711 return false;
712 }
713
714 // keep the field from the meta-data from the data-file
715 fMetaData.fField = runData->GetField();
716
717 // keep the energy from the meta-data from the data-file
718 fMetaData.fEnergy = runData->GetEnergy();
719
720 // keep the temperature(s) from the meta-data from the data-file
721 for (unsigned int i=0; i<runData->GetNoOfTemperatures(); i++)
722 fMetaData.fTemp.push_back(runData->GetTemperature(i));
723
724 // collect histogram numbers
725 PUIntVector histoNo; // histoNo = msr-file forward + redGreen_offset - 1
726 for (UInt_t i=0; i<fRunInfo->GetForwardHistoNoSize(); i++) {
727 histoNo.push_back(fRunInfo->GetForwardHistoNo(i));
728
729 if (!runData->IsPresent(histoNo[i])) {
730 std::cerr << std::endl << ">> PRunSingleHistoRRF::PrepareData(): **PANIC ERROR**:";
731 std::cerr << std::endl << ">> histoNo found = " << histoNo[i] << ", which is NOT present in the data file!?!?";
732 std::cerr << std::endl << ">> Will quit :-(";
733 std::cerr << std::endl;
734 histoNo.clear();
735 return false;
736 }
737 }
738
739 // keep the time resolution in (us)
740 fTimeResolution = runData->GetTimeResolution()/1.0e3;
741 std::cout.precision(10);
742 std::cout << std::endl << ">> PRunSingleHisto::PrepareData(): time resolution=" << std::fixed << runData->GetTimeResolution() << "(ns)" << std::endl;
743
744 // get all the proper t0's and addt0's for the current RUN block
745 if (!GetProperT0(runData, globalBlock, histoNo)) {
746 return false;
747 }
748
749 // keep the histo of each group at this point (addruns handled below)
750 std::vector<PDoubleVector> forward;
751 forward.resize(histoNo.size()); // resize to number of groups
752 for (UInt_t i=0; i<histoNo.size(); i++) {
753 forward[i].resize(runData->GetDataBin(histoNo[i])->size());
754 forward[i] = *runData->GetDataBin(histoNo[i]);
755 }
756
757 // check if there are runs to be added to the current one
758 if (fRunInfo->GetRunNameSize() > 1) { // runs to be added present
759 PRawRunData *addRunData;
760 std::vector<PDoubleVector> addForward;
761 for (UInt_t i=1; i<fRunInfo->GetRunNameSize(); i++) {
762
763 // get run to be added to the main one
764 addRunData = fRawData->GetRunData(*fRunInfo->GetRunName(i));
765 if (addRunData == nullptr) { // couldn't get run
766 std::cerr << std::endl << ">> PRunSingleHistoRRF::PrepareData(): **ERROR** Couldn't get addrun " << fRunInfo->GetRunName(i)->Data() << "!";
767 std::cerr << std::endl;
768 return false;
769 }
770
771 addForward.clear();
772 addForward.resize(histoNo.size()); // resize to number of groups
773 for (UInt_t j=0; j<histoNo.size(); j++) {
774 addForward[j].resize(addRunData->GetDataBin(histoNo[j])->size());
775 addForward[j] = *addRunData->GetDataBin(histoNo[j]);
776 }
777 DeadTimeCorrection(addForward, histoNo);
778
779 // add forward run
780 UInt_t addRunSize;
781 for (UInt_t k=0; k<histoNo.size(); k++) { // fill each group
782 addRunSize = addForward[k].size();
783 for (UInt_t j=0; j<addRunSize; j++) { // loop over the bin indices
784 // make sure that the index stays in the proper range
785 if ((static_cast<Int_t>(j)+static_cast<Int_t>(fAddT0s[i-1][k])-static_cast<Int_t>(fT0s[k]) >= 0) &&
786 (j+static_cast<Int_t>(fAddT0s[i-1][k])-static_cast<Int_t>(fT0s[k]) < addRunSize)) {
787 forward[k][j] += addForward[k][j+static_cast<Int_t>(fAddT0s[i-1][k])-static_cast<Int_t>(fT0s[k])];
788 }
789 }
790 }
791 }
792 }
793
794 // set forward histo data of the first group
795 fForward.resize(forward[0].size());
796 for (UInt_t i=0; i<fForward.size(); i++) {
797 fForward[i] = forward[0][i];
798 }
799
800 // group histograms, add all the remaining forward histograms of the group
801 for (UInt_t i=1; i<histoNo.size(); i++) { // loop over the groupings
802 for (UInt_t j=0; j<runData->GetDataBin(histoNo[i])->size(); j++) { // loop over the bin indices
803 // make sure that the index stays within proper range
804 if ((static_cast<Int_t>(j)+static_cast<Int_t>(fT0s[i])-static_cast<Int_t>(fT0s[0]) >= 0) &&
805 (j+static_cast<Int_t>(fT0s[i])-static_cast<Int_t>(fT0s[0]) < runData->GetDataBin(histoNo[i])->size())) {
806 fForward[j] += forward[i][j+static_cast<Int_t>(fT0s[i])-static_cast<Int_t>(fT0s[0])];
807 }
808 }
809 }
810
811 // get the data range (fgb/lgb) for the current RUN block
812 if (!GetProperDataRange()) {
813 return false;
814 }
815
816 // get the fit range for the current RUN block
817 GetProperFitRange(globalBlock);
818
819 // do the more fit/view specific stuff
820 if (fHandleTag == kFit)
821 success = PrepareFitData(runData, histoNo[0]);
822 else if (fHandleTag == kView)
823 success = PrepareViewData(runData, histoNo[0]);
824 else
825 success = false;
826
827 // cleanup
828 histoNo.clear();
829
830 return success;
831}
832
833//--------------------------------------------------------------------------
834// PrepareFitData (protected)
835//--------------------------------------------------------------------------
905Bool_t PRunSingleHistoRRF::PrepareFitData(PRawRunData* runData, const UInt_t histoNo)
906{
907 // keep the raw data for the RRF asymmetry error estimate for later
908 PDoubleVector rawNt;
909 for (UInt_t i=0; i<fForward.size(); i++) {
910 rawNt.push_back(fForward[i]); // N(t) without any corrections
911 }
912 Double_t freqMax = GetMainFrequency(rawNt);
913 std::cout << "info> freqMax=" << freqMax << " (MHz)" << std::endl;
914
915 // "optimal packing"
916 Double_t optNoPoints = 8;
917 if (freqMax < 271.0) // < 271 MHz, i.e ~ 2T
918 optNoPoints = 5;
919 std::cout << "info> optimal packing: " << static_cast<Int_t>(1.0 / (fTimeResolution*(freqMax - fMsrInfo->GetMsrGlobal()->GetRRFFreq("MHz"))) / optNoPoints);
920
921 // initially fForward is the "raw data set" (i.e. grouped histo and raw runs already added) to be fitted. This means fForward = N(t) at this point.
922
923 // 1) check how the background shall be handled
924 // subtract background from histogramms ------------------------------------------
925 if (fRunInfo->GetBkgFix(0) == PMUSR_UNDEFINED) { // no fixed background given
926 if (fRunInfo->GetBkgRange(0) >= 0) {
927 if (!EstimateBkg(histoNo))
928 return false;
929 } else { // no background given to do the job, try estimate
930 fRunInfo->SetBkgRange(static_cast<Int_t>(fT0s[0]*0.1), 0);
931 fRunInfo->SetBkgRange(static_cast<Int_t>(fT0s[0]*0.6), 1);
932 std::cerr << std::endl << ">> PRunSingleHistoRRF::PrepareFitData(): **WARNING** Neither fix background nor background bins are given!";
933 std::cerr << std::endl << ">> Will try the following: bkg start = " << fRunInfo->GetBkgRange(0) << ", bkg end = " << fRunInfo->GetBkgRange(1);
934 std::cerr << std::endl << ">> NO WARRANTY THAT THIS MAKES ANY SENSE! Better check ...";
935 std::cerr << std::endl;
936 if (!EstimateBkg(histoNo))
937 return false;
938 }
939 // subtract background from fForward
940 for (UInt_t i=0; i<fForward.size(); i++)
941 fForward[i] -= fBackground;
942 } else { // fixed background given
943 for (UInt_t i=0; i<fForward.size(); i++) {
944 fForward[i] -= fRunInfo->GetBkgFix(0);
945 }
946 fBackground = fRunInfo->GetBkgFix(0);
947 }
948 // here fForward = N(t) - Nbkg
949
950 Int_t t0 = static_cast<Int_t>(fT0s[0]);
951
952 // 2) N(t) - Nbkg -> exp(+t/tau) [N(t)-Nbkg]
953 Double_t startTime = fTimeResolution * (static_cast<Double_t>(fGoodBins[0]) - static_cast<Double_t>(t0));
954
955 Double_t time_tau=0.0;
956 Double_t exp_t_tau=0.0;
957 for (Int_t i=fGoodBins[0]; i<fGoodBins[1]; i++) {
958 time_tau = (startTime + fTimeResolution * (i - fGoodBins[0])) / PMUON_LIFETIME;
959 exp_t_tau = exp(time_tau);
960 fForward[i] *= exp_t_tau;
961 fM.push_back(fForward[i]); // i.e. M(t) = [N(t)-Nbkg] exp(+t/tau); needed to estimate N0 later on
962 fMerr.push_back(exp_t_tau*sqrt(rawNt[i]+fBkgErr*fBkgErr));
963 }
964
965 // calculate weights
966 for (UInt_t i=0; i<fMerr.size(); i++) {
967 if (fMerr[i] > 0.0)
968 fW.push_back(1.0/(fMerr[i]*fMerr[i]));
969 else
970 fW.push_back(1.0);
971 }
972 // now fForward = exp(+t/tau) [N(t)-Nbkg] = M(t)
973
974 // 3) estimate N0
975 Double_t errN0 = 0.0;
976 Double_t n0 = EstimateN0(errN0, freqMax);
977
978 // 4a) A(t) = exp(+t/tau) [N(t)-Nbkg] / N0 - 1.0
979 for (Int_t i=fGoodBins[0]; i<=fGoodBins[1]; i++) {
980 fForward[i] = fForward[i] / n0 - 1.0;
981 }
982
983 // 4b) error estimate of A(t): errA(t) = exp(+t/tau)/N0 sqrt( N(t) + ([N(t)-N_bkg]/N0)^2 errN0^2 )
984 for (Int_t i=fGoodBins[0]; i<=fGoodBins[1]; i++) {
985 time_tau = (startTime + fTimeResolution * (i - fGoodBins[0])) / PMUON_LIFETIME;
986 exp_t_tau = exp(time_tau);
987 fAerr.push_back(exp_t_tau/n0*sqrt(rawNt[i]+pow(((rawNt[i]-fBackground)/n0)*errN0,2.0)));
988 }
989
990 // 5) rotate A(t): A(t) -> 2* A(t) * cos(wRRF t + phiRRF), the factor 2.0 is needed since the high frequency part is suppressed.
991 PMsrGlobalBlock *globalBlock = fMsrInfo->GetMsrGlobal();
992 Double_t wRRF = globalBlock->GetRRFFreq("Mc");
993 Double_t phaseRRF = globalBlock->GetRRFPhase()*TMath::TwoPi()/180.0;
994 Double_t time = 0.0;
995 for (Int_t i=fGoodBins[0]; i<=fGoodBins[1]; i++) {
996 time = startTime + fTimeResolution * (static_cast<Double_t>(i) - static_cast<Double_t>(fGoodBins[0]));
997 fForward[i] *= 2.0*cos(wRRF * time + phaseRRF);
998 }
999
1000 // 6) RRF packing
1001 Double_t dval=0.0;
1002 for (Int_t i=fGoodBins[0]; i<=fGoodBins[1]; i++) {
1003 if (fRRFPacking == 1) {
1004 fData.AppendValue(fForward[i]);
1005 } else { // RRF packing > 1
1006 if (((i-fGoodBins[0]) % fRRFPacking == 0) && (i != fGoodBins[0])) { // fill data
1007 dval /= fRRFPacking;
1008 fData.AppendValue(dval);
1009 // reset dval
1010 dval = 0.0;
1011 }
1012 dval += fForward[i];
1013 }
1014 }
1015
1016 // 7) estimate packed RRF errors (see log-book p.204)
1017 // the error estimate of the unpacked RRF asymmetry is: errA_RRF(t) \simeq exp(t/tau)/N0 sqrt( [N(t) + ((N(t)-N_bkg)/N0)^2 errN0^2] )
1018 dval = 0.0;
1019 // the packed RRF asymmetry error
1020 for (Int_t i=fGoodBins[0]; i<=fGoodBins[1]; i++) {
1021 if (((i-fGoodBins[0]) % fRRFPacking == 0) && (i != fGoodBins[0])) { // fill data
1022 fData.AppendErrorValue(sqrt(2.0*dval)/fRRFPacking); // the factor 2.0 is needed since the high frequency part is suppressed.
1023 dval = 0.0;
1024 }
1025 dval += fAerr[i-fGoodBins[0]]*fAerr[i-fGoodBins[0]];
1026 }
1027
1028 // set start time and time step
1029 fData.SetDataTimeStart(fTimeResolution*(static_cast<Double_t>(fGoodBins[0])-static_cast<Double_t>(t0)+static_cast<Double_t>(fRRFPacking-1)/2.0));
1030 fData.SetDataTimeStep(fTimeResolution*fRRFPacking);
1031
1033
1034 return true;
1035}
1036
1037//--------------------------------------------------------------------------
1038// PrepareViewData (protected)
1039//--------------------------------------------------------------------------
1091Bool_t PRunSingleHistoRRF::PrepareViewData(PRawRunData* runData, const UInt_t histoNo)
1092{
1093 // --------------
1094 // prepare data
1095 // --------------
1096
1097 // prepare RRF single histo
1098 PrepareFitData(runData, histoNo);
1099
1100 // check for view packing
1101 Int_t viewPacking = fMsrInfo->GetMsrPlotList()->at(0).fViewPacking;
1102 if (viewPacking > 0) {
1103 if (viewPacking < fRRFPacking) {
1104 std::cerr << ">> PRunSingleHistoRRF::PrepareViewData(): **WARNING** Found View Packing (" << viewPacking << ") < RRF Packing (" << fRRFPacking << ").";
1105 std::cerr << ">> Will ignore View Packing." << std::endl;
1106 } else {
1107 // STILL MISSING
1108 }
1109 }
1110
1111 // --------------
1112 // prepare theory
1113 // --------------
1114
1115 // feed the parameter vector
1116 std::vector<Double_t> par;
1117 PMsrParamList *paramList = fMsrInfo->GetMsrParamList();
1118 for (UInt_t i=0; i<paramList->size(); i++)
1119 par.push_back((*paramList)[i].fValue);
1120
1121 // calculate functions
1122 for (Int_t i=0; i<fMsrInfo->GetNoOfFuncs(); i++) {
1123 fFuncValues[i] = fMsrInfo->EvalFunc(fMsrInfo->GetFuncNo(i), *fRunInfo->GetMap(), par, fMetaData);
1124 }
1125
1126 // check if a finer binning for the theory is needed
1127 UInt_t size = fForward.size();
1128 Int_t factor = 8; // 8 times more points for the theory (if fTheoAsData == false)
1129 fData.SetTheoryTimeStart(fData.GetDataTimeStart());
1130 if (fTheoAsData) { // calculate theory only at the data points
1131 fData.SetTheoryTimeStep(fData.GetDataTimeStep());
1132 } else {
1133 // finer binning for the theory (8 times as many points = factor)
1134 size *= factor;
1135 fData.SetTheoryTimeStep(fData.GetDataTimeStep()/(Double_t)factor);
1136 }
1137
1138 // calculate theory
1139 Double_t time = 0.0;
1140 Double_t theoryValue = 0.0;
1141 for (UInt_t i=0; i<size; i++) {
1142 time = fData.GetTheoryTimeStart() + static_cast<Double_t>(i)*fData.GetTheoryTimeStep();
1143 theoryValue = fTheory->Func(time, par, fFuncValues);
1144 if (fabs(theoryValue) > 10.0) { // dirty hack needs to be fixed!!
1145 theoryValue = 0.0;
1146 }
1147 fData.AppendTheoryValue(theoryValue);
1148 }
1149
1150 return true;
1151}
1152
1153//--------------------------------------------------------------------------
1154// GetProperT0 (private)
1155//--------------------------------------------------------------------------
1205{
1206 // feed all T0's
1207 // first init T0's, T0's are stored as (forward T0, backward T0, etc.)
1208 fT0s.clear();
1209 fT0s.resize(histoNo.size());
1210 for (UInt_t i=0; i<fT0s.size(); i++) {
1211 fT0s[i] = -1.0;
1212 }
1213
1214 // fill in the T0's from the msr-file (if present)
1215 for (UInt_t i=0; i<fRunInfo->GetT0BinSize(); i++) {
1216 fT0s[i] = fRunInfo->GetT0Bin(i);
1217 }
1218
1219 // fill in the T0's from the GLOBAL block section (if present)
1220 for (UInt_t i=0; i<globalBlock->GetT0BinSize(); i++) {
1221 if (fT0s[i] == -1.0) { // i.e. not given in the RUN block section
1222 fT0s[i] = globalBlock->GetT0Bin(i);
1223 }
1224 }
1225
1226 // fill in the T0's from the data file, if not already present in the msr-file
1227 for (UInt_t i=0; i<histoNo.size(); i++) {
1228 if (fT0s[i] == -1.0) { // i.e. not present in the msr-file, try the data file
1229 if (runData->GetT0Bin(histoNo[i]) > 0.0) {
1230 fT0s[i] = runData->GetT0Bin(histoNo[i]);
1231 fRunInfo->SetT0Bin(fT0s[i], i); // keep value for the msr-file
1232 }
1233 }
1234 }
1235
1236 // fill in the T0's gaps, i.e. in case the T0's are NOT in the msr-file and NOT in the data file
1237 for (UInt_t i=0; i<histoNo.size(); i++) {
1238 if (fT0s[i] == -1.0) { // i.e. not present in the msr-file and data file, use the estimated T0
1239 fT0s[i] = runData->GetT0BinEstimated(histoNo[i]);
1240 fRunInfo->SetT0Bin(fT0s[i], i); // keep value for the msr-file
1241
1242 std::cerr << std::endl << ">> PRunSingleHistoRRF::GetProperT0(): **WARRNING** NO t0's found, neither in the run data nor in the msr-file!";
1243 std::cerr << std::endl << ">> run: " << fRunInfo->GetRunName()->Data();
1244 std::cerr << std::endl << ">> will try the estimated one: forward t0 = " << runData->GetT0BinEstimated(histoNo[i]);
1245 std::cerr << std::endl << ">> NO WARRANTY THAT THIS OK!! For instance for LEM this is almost for sure rubbish!";
1246 std::cerr << std::endl;
1247 }
1248 }
1249
1250 // check if t0 is within proper bounds
1251 for (UInt_t i=0; i<fRunInfo->GetForwardHistoNoSize(); i++) {
1252 if ((fT0s[i] < 0.0) || (fT0s[i] > static_cast<Int_t>(runData->GetDataBin(histoNo[i])->size()))) {
1253 std::cerr << std::endl << ">> PRunSingleHistoRRF::GetProperT0(): **ERROR** t0 data bin (" << fT0s[i] << ") doesn't make any sense!";
1254 std::cerr << std::endl;
1255 return false;
1256 }
1257 }
1258
1259 // check if there are runs to be added to the current one. If yes keep the needed t0's
1260 if (fRunInfo->GetRunNameSize() > 1) { // runs to be added present
1261 PRawRunData *addRunData;
1262 fAddT0s.resize(fRunInfo->GetRunNameSize()-1); // resize to the number of addruns
1263 for (UInt_t i=1; i<fRunInfo->GetRunNameSize(); i++) {
1264
1265 // get run to be added to the main one
1266 addRunData = fRawData->GetRunData(*fRunInfo->GetRunName(i));
1267 if (addRunData == nullptr) { // couldn't get run
1268 std::cerr << std::endl << ">> PRunSingleHistoRRF::GetProperT0(): **ERROR** Couldn't get addrun " << fRunInfo->GetRunName(i)->Data() << "!";
1269 std::cerr << std::endl;
1270 return false;
1271 }
1272
1273 // feed all T0's
1274 // first init T0's, T0's are stored as (forward T0, backward T0, etc.)
1275 fAddT0s[i-1].resize(histoNo.size());
1276 for (UInt_t j=0; j<fAddT0s[i-1].size(); j++) {
1277 fAddT0s[i-1][j] = -1.0;
1278 }
1279
1280 // fill in the T0's from the msr-file (if present)
1281 for (UInt_t j=0; j<fRunInfo->GetT0BinSize(); j++) {
1282 fAddT0s[i-1][j] = fRunInfo->GetAddT0Bin(i-1,j); // addRunIdx starts at 0
1283 }
1284
1285 // fill in the T0's from the data file, if not already present in the msr-file
1286 for (UInt_t j=0; j<histoNo.size(); j++) {
1287 if (fAddT0s[i-1][j] == -1.0) // i.e. not present in the msr-file, try the data file
1288 if (addRunData->GetT0Bin(histoNo[j]) > 0.0) {
1289 fAddT0s[i-1][j] = addRunData->GetT0Bin(histoNo[j]);
1290 fRunInfo->SetAddT0Bin(fAddT0s[i-1][j], i-1, j); // keep value for the msr-file
1291 }
1292 }
1293
1294 // fill in the T0's gaps, i.e. in case the T0's are NOT in the msr-file and NOT in the data file
1295 for (UInt_t j=0; j<histoNo.size(); j++) {
1296 if (fAddT0s[i-1][j] == -1.0) { // i.e. not present in the msr-file and data file, use the estimated T0
1297 fAddT0s[i-1][j] = addRunData->GetT0BinEstimated(histoNo[j]);
1298 fRunInfo->SetAddT0Bin(fAddT0s[i-1][j], i-1, j); // keep value for the msr-file
1299
1300 std::cerr << std::endl << ">> PRunSingleHistoRRF::GetProperT0(): **WARRNING** NO t0's found, neither in the run data nor in the msr-file!";
1301 std::cerr << std::endl << ">> run: " << fRunInfo->GetRunName(i)->Data();
1302 std::cerr << std::endl << ">> will try the estimated one: forward t0 = " << addRunData->GetT0BinEstimated(histoNo[j]);
1303 std::cerr << std::endl << ">> NO WARRANTY THAT THIS OK!! For instance for LEM this is almost for sure rubbish!";
1304 std::cerr << std::endl;
1305 }
1306 }
1307
1308 // check if t0 is within proper bounds
1309 for (UInt_t j=0; j<fRunInfo->GetForwardHistoNoSize(); j++) {
1310 if ((fAddT0s[i-1][j] < 0) || (fAddT0s[i-1][j] > static_cast<Int_t>(addRunData->GetDataBin(histoNo[j])->size()))) {
1311 std::cerr << std::endl << ">> PRunSingleHistoRRF::GetProperT0(): **ERROR** addt0 data bin (" << fAddT0s[i-1][j] << ") doesn't make any sense!";
1312 std::cerr << std::endl;
1313 return false;
1314 }
1315 }
1316 }
1317 }
1318
1319 return true;
1320}
1321
1322//--------------------------------------------------------------------------
1323// GetProperDataRange (private)
1324//--------------------------------------------------------------------------
1362{
1363 // get start/end data
1364 Int_t start;
1365 Int_t end;
1366 start = fRunInfo->GetDataRange(0);
1367 end = fRunInfo->GetDataRange(1);
1368
1369 // check if data range has been given in the RUN block, if not try to get it from the GLOBAL block
1370 if (start < 0) {
1371 start = fMsrInfo->GetMsrGlobal()->GetDataRange(0);
1372 }
1373 if (end < 0) {
1374 end = fMsrInfo->GetMsrGlobal()->GetDataRange(1);
1375 }
1376
1377 // check if data range has been provided, and if not try to estimate them
1378 if (start < 0) {
1379 Int_t offset = static_cast<Int_t>(10.0e-3/fTimeResolution);
1380 start = static_cast<Int_t>(fT0s[0])+offset;
1381 fRunInfo->SetDataRange(start, 0);
1382 std::cerr << std::endl << ">> PRunSingleHistoRRF::GetProperDataRange(): **WARNING** data range was not provided, will try data range start = t0+" << offset << "(=10ns) = " << start << ".";
1383 std::cerr << std::endl << ">> NO WARRANTY THAT THIS DOES MAKE ANY SENSE.";
1384 std::cerr << std::endl;
1385 }
1386 if (end < 0) {
1387 end = fForward.size();
1388 fRunInfo->SetDataRange(end, 1);
1389 std::cerr << std::endl << ">> PRunSingleHistoRRF::GetProperDataRange(): **WARNING** data range was not provided, will try data range end = " << end << ".";
1390 std::cerr << std::endl << ">> NO WARRANTY THAT THIS DOES MAKE ANY SENSE.";
1391 std::cerr << std::endl;
1392 }
1393
1394 // check if start and end make any sense
1395 // 1st check if start and end are in proper order
1396 if (end < start) { // need to swap them
1397 Int_t keep = end;
1398 end = start;
1399 start = keep;
1400 }
1401 // 2nd check if start is within proper bounds
1402 if ((start < 0) || (start > static_cast<Int_t>(fForward.size()))) {
1403 std::cerr << std::endl << ">> PRunSingleHistoRRF::GetProperDataRange(): **ERROR** start data bin (" << start << ") doesn't make any sense!";
1404 std::cerr << std::endl;
1405 return false;
1406 }
1407 // 3rd check if end is within proper bounds
1408 if (end < 0) {
1409 std::cerr << std::endl << ">> PRunSingleHistoRRF::GetProperDataRange(): **ERROR** end data bin (" << end << ") doesn't make any sense!";
1410 std::cerr << std::endl;
1411 return false;
1412 }
1413 if (end > static_cast<Int_t>(fForward.size())) {
1414 std::cerr << std::endl << ">> PRunSingleHistoRRF::GetProperDataRange(): **WARNING** end data bin (" << end << ") > histo length (" << fForward.size() << ").";
1415 std::cerr << std::endl << ">> Will set end = (histo length - 1). Consider to change it in the msr-file." << std::endl;
1416 std::cerr << std::endl;
1417 end = static_cast<Int_t>(fForward.size()-1);
1418 }
1419
1420 // keep good bins for potential later use
1421 fGoodBins[0] = start;
1422 fGoodBins[1] = end;
1423
1424 // make sure that fGoodBins are in proper range for fForward
1425 if (fGoodBins[0] < 0)
1426 fGoodBins[0]=0;
1427 if (fGoodBins[1] > fForward.size()) {
1428 std::cerr << std::endl << ">> PRunSingleHisto::GetProperDataRange **WARNING** needed to shift forward lgb,";
1429 std::cerr << std::endl << ">> from " << fGoodBins[1] << " to " << fForward.size()-1 << std::endl;
1430 fGoodBins[1]=fForward.size()-1;
1431 }
1432
1433 return true;
1434}
1435
1436//--------------------------------------------------------------------------
1437// GetProperFitRange (private)
1438//--------------------------------------------------------------------------
1481{
1482 // set fit start/end time; first check RUN Block
1483 fFitStartTime = fRunInfo->GetFitRange(0);
1484 fFitEndTime = fRunInfo->GetFitRange(1);
1485 // if fit range is given in bins (and not time), the fit start/end time can be calculated at this point now
1486 if (fRunInfo->IsFitRangeInBin()) {
1487 fFitStartTime = (fGoodBins[0] + fRunInfo->GetFitRangeOffset(0) - fT0s[0]) * fTimeResolution; // (fgb+n0-t0)*dt
1488 fFitEndTime = (fGoodBins[1] - fRunInfo->GetFitRangeOffset(1) - fT0s[0]) * fTimeResolution; // (lgb-n1-t0)*dt
1489 // write these times back into the data structure. This way it is available when writting the log-file
1490 fRunInfo->SetFitRange(fFitStartTime, 0);
1491 fRunInfo->SetFitRange(fFitEndTime, 1);
1492 }
1493 if (fFitStartTime == PMUSR_UNDEFINED) { // fit start/end NOT found in the RUN block, check GLOBAL block
1494 fFitStartTime = globalBlock->GetFitRange(0);
1495 fFitEndTime = globalBlock->GetFitRange(1);
1496 // if fit range is given in bins (and not time), the fit start/end time can be calculated at this point now
1497 if (globalBlock->IsFitRangeInBin()) {
1498 fFitStartTime = (fGoodBins[0] + globalBlock->GetFitRangeOffset(0) - fT0s[0]) * fTimeResolution; // (fgb+n0-t0)*dt
1499 fFitEndTime = (fGoodBins[1] - globalBlock->GetFitRangeOffset(1) - fT0s[0]) * fTimeResolution; // (lgb-n1-t0)*dt
1500 // write these times back into the data structure. This way it is available when writting the log-file
1501 globalBlock->SetFitRange(fFitStartTime, 0);
1502 globalBlock->SetFitRange(fFitEndTime, 1);
1503 }
1504 }
1506 fFitStartTime = (fGoodBins[0] - fT0s[0]) * fTimeResolution; // (fgb-t0)*dt
1507 fFitEndTime = (fGoodBins[1] - fT0s[0]) * fTimeResolution; // (lgb-t0)*dt
1508 std::cerr << ">> PRunSingleHistoRRF::GetProperFitRange(): **WARNING** Couldn't get fit start/end time!" << std::endl;
1509 std::cerr << ">> Will set it to fgb/lgb which given in time is: " << fFitStartTime << "..." << fFitEndTime << " (usec)" << std::endl;
1510 }
1511}
1512
1513//--------------------------------------------------------------------------
1514// GetMainFrequency (private)
1515//--------------------------------------------------------------------------
1554{
1555 Double_t freqMax = 0.0;
1556
1557 // create histo
1558 Double_t startTime = (fGoodBins[0]-fT0s[0]) * fTimeResolution;
1559 Int_t noOfBins = fGoodBins[1]-fGoodBins[0]+1;
1560 std::unique_ptr<TH1F> histo = std::make_unique<TH1F>("data", "data", noOfBins, startTime-fTimeResolution/2.0, startTime+fTimeResolution/2.0+noOfBins*fTimeResolution);
1561 for (Int_t i=fGoodBins[0]; i<=fGoodBins[1]; i++) {
1562 histo->SetBinContent(i-fGoodBins[0]+1, data[i]);
1563 }
1564
1565 // Fourier transform
1566 std::unique_ptr<PFourier> ft = std::make_unique<PFourier>(histo.get(), FOURIER_UNIT_FREQ);
1567 ft->Transform(F_APODIZATION_STRONG);
1568
1569 // find frequency maximum
1570 TH1F *power = ft->GetPowerFourier();
1571 Double_t maxFreqVal = 0.0;
1572 for (Int_t i=1; i<power->GetNbinsX(); i++) {
1573 // ignore dc part at 0 frequency
1574 if (i<power->GetNbinsX()-1) {
1575 if (power->GetBinContent(i)>power->GetBinContent(i+1))
1576 continue;
1577 }
1578 // ignore everything below 10 MHz
1579 if (power->GetBinCenter(i) < 10.0)
1580 continue;
1581 // check for maximum
1582 if (power->GetBinContent(i) > maxFreqVal) {
1583 maxFreqVal = power->GetBinContent(i);
1584 freqMax = power->GetBinCenter(i);
1585 }
1586 }
1587
1588 // clean up
1589 if (power)
1590 delete power;
1591
1592 return freqMax;
1593}
1594
1595//--------------------------------------------------------------------------
1596// EstimateN0 (private)
1597//--------------------------------------------------------------------------
1644Double_t PRunSingleHistoRRF::EstimateN0(Double_t &errN0, Double_t freqMax)
1645{
1646 // endBin is estimated such that the number of full cycles (according to the maximum frequency of the data)
1647 // is approximately the time fN0EstimateEndTime.
1648 Int_t endBin = static_cast<Int_t>(round(ceil(fN0EstimateEndTime*freqMax/TMath::TwoPi()) * (TMath::TwoPi()/freqMax) / fTimeResolution));
1649
1650 Double_t n0 = 0.0;
1651 Double_t wN = 0.0;
1652 for (Int_t i=0; i<endBin; i++) {
1653// n0 += fW[i]*fM[i];
1654 n0 += fM[i];
1655 wN += fW[i];
1656 }
1657// n0 /= wN;
1658 n0 /= endBin;
1659
1660 errN0 = 0.0;
1661 for (Int_t i=0; i<endBin; i++) {
1662 errN0 += fW[i]*fW[i]*fMerr[i]*fMerr[i];
1663 }
1664 errN0 = sqrt(errN0)/wN;
1665
1666 std::cout << "info> PRunSingleHistoRRF::EstimateN0(): N0=" << n0 << "(" << errN0 << ")" << std::endl;
1667
1668 return n0;
1669}
1670
1671//--------------------------------------------------------------------------
1672// EstimatBkg (private)
1673//--------------------------------------------------------------------------
1718{
1719 Double_t beamPeriod = 0.0;
1720
1721 // check if data are from PSI, RAL, or TRIUMF
1722 if (fRunInfo->GetInstitute()->Contains("psi"))
1723 beamPeriod = ACCEL_PERIOD_PSI;
1724 else if (fRunInfo->GetInstitute()->Contains("ral"))
1725 beamPeriod = ACCEL_PERIOD_RAL;
1726 else if (fRunInfo->GetInstitute()->Contains("triumf"))
1727 beamPeriod = ACCEL_PERIOD_TRIUMF;
1728 else
1729 beamPeriod = 0.0;
1730
1731 // check if start and end are in proper order
1732 UInt_t start = fRunInfo->GetBkgRange(0);
1733 UInt_t end = fRunInfo->GetBkgRange(1);
1734 if (end < start) {
1735 std::cout << std::endl << "PRunSingleHistoRRF::EstimatBkg(): end = " << end << " > start = " << start << "! Will swap them!";
1736 UInt_t keep = end;
1737 end = start;
1738 start = keep;
1739 }
1740
1741 // calculate proper background range
1742 if (beamPeriod != 0.0) {
1743 Double_t timeBkg = static_cast<Double_t>(end-start)*fTimeResolution; // length of the background intervall in time
1744 UInt_t fullCycles = static_cast<UInt_t>(timeBkg/beamPeriod); // how many proton beam cylces can be placed within the proposed background intervall
1745 // correct the end of the background intervall such that the background is as close as possible to a multiple of the proton cylce
1746 end = start + static_cast<UInt_t>((fullCycles*beamPeriod)/fTimeResolution);
1747 std::cout << std::endl << "PRunSingleHistoRRF::EstimatBkg(): Background " << start << ", " << end;
1748 if (end == start)
1749 end = fRunInfo->GetBkgRange(1);
1750 }
1751
1752 // check if start is within histogram bounds
1753 if (start >= fForward.size()) {
1754 std::cerr << std::endl << ">> PRunSingleHistoRRF::EstimatBkg(): **ERROR** background bin values out of bound!";
1755 std::cerr << std::endl << ">> histo lengths = " << fForward.size();
1756 std::cerr << std::endl << ">> background start = " << start;
1757 std::cerr << std::endl;
1758 return false;
1759 }
1760
1761 // check if end is within histogram bounds
1762 if (end >= fForward.size()) {
1763 std::cerr << std::endl << ">> PRunSingleHistoRRF::EstimatBkg(): **ERROR** background bin values out of bound!";
1764 std::cerr << std::endl << ">> histo lengths = " << fForward.size();
1765 std::cerr << std::endl << ">> background end = " << end;
1766 std::cerr << std::endl;
1767 return false;
1768 }
1769
1770 // calculate background
1771 Double_t bkg = 0.0;
1772
1773 // forward
1774 for (UInt_t i=start; i<end; i++)
1775 bkg += fForward[i];
1776 bkg /= static_cast<Double_t>(end - start + 1);
1777
1778 fBackground = bkg; // keep background (per bin)
1779
1780 bkg = 0.0;
1781 for (UInt_t i=start; i<end; i++)
1782 bkg += pow(fForward[i]-fBackground, 2.0);
1783 fBkgErr = sqrt(bkg/(static_cast<Double_t>(end - start)));
1784
1785 std::cout << std::endl << "info> fBackground=" << fBackground << "(" << fBkgErr << ")" << std::endl;
1786
1787 fRunInfo->SetBkgEstimated(fBackground, 0);
1788
1789 return true;
1790}
#define F_APODIZATION_STRONG
Strong apodization (heavy roll-off for best frequency resolution)
Definition PFourier.h:59
std::vector< UInt_t > PUIntVector
Definition PMusr.h:375
#define ACCEL_PERIOD_TRIUMF
TRIUMF accelerator cycle: 43.37 ns.
Definition PMusr.h:156
EPMusrHandleTag
Definition PMusr.h:427
@ kFit
Fitting mode - perform least-squares fit to data.
Definition PMusr.h:429
@ kView
Viewing mode - display data and theory without fitting.
Definition PMusr.h:430
#define FOURIER_UNIT_FREQ
Frequency in MHz.
Definition PMusr.h:290
#define PMUSR_UNDEFINED
Definition PMusr.h:177
#define PMUON_LIFETIME
Definition PMusr.h:124
std::vector< PMsrParamStructure > PMsrParamList
Definition PMusr.h:1040
#define ACCEL_PERIOD_PSI
PSI (Paul Scherrer Institute) accelerator cycle: 19.75 ns.
Definition PMusr.h:154
std::vector< Double_t > PDoubleVector
Definition PMusr.h:399
#define ACCEL_PERIOD_RAL
RAL (Rutherford Appleton Lab) - pulsed beam.
Definition PMusr.h:158
if(xmlFile.is_open())
virtual Bool_t IsPresent()
Definition PMusr.h:1060
virtual void SetFitRange(Double_t dval, UInt_t idx)
Definition PMusr.cpp:1171
virtual Double_t GetFitRange(UInt_t idx)
Definition PMusr.cpp:1154
virtual UInt_t GetT0BinSize()
Definition PMusr.h:1068
virtual Bool_t IsFitRangeInBin()
Definition PMusr.h:1073
virtual Int_t GetRRFPacking()
Definition PMusr.h:1065
virtual TString GetRRFUnit()
Definition PMusr.cpp:937
virtual Int_t GetFitRangeOffset(UInt_t idx)
Definition PMusr.cpp:1191
virtual Double_t GetT0Bin(UInt_t idx=0)
Definition PMusr.cpp:1038
virtual Double_t GetRRFPhase()
Definition PMusr.h:1064
virtual Double_t GetRRFFreq(const char *unit)
Definition PMusr.cpp:865
MSR file parser and manager for the musrfit framework.
virtual PMsrGlobalBlock * GetMsrGlobal()
Returns pointer to GLOBAL block settings.
virtual const PDoubleVector * GetDataBin(const UInt_t histoNo)
Definition PMusr.h:896
virtual const Double_t GetT0Bin(const UInt_t histoNo)
Definition PMusr.h:884
virtual const Double_t GetTimeResolution()
Definition PMusr.h:882
virtual const Bool_t IsPresent(UInt_t histoNo)
Definition PMusr.h:883
virtual const UInt_t GetNoOfTemperatures()
Definition PMusr.h:874
virtual const Double_t GetField()
Definition PMusr.h:873
virtual const Double_t GetEnergy()
Definition PMusr.h:878
virtual const Double_t GetT0BinEstimated(const UInt_t histoNo)
Definition PMusr.h:885
virtual const PDoublePairVector * GetTemperature() const
Definition PMusr.h:875
Double_t fTimeResolution
Time resolution of raw histogram data in microseconds (μs), e.g., 0.01953125 μs for PSI GPS.
Definition PRunBase.h:276
Bool_t fValid
Flag indicating if run object initialized successfully; false if any error occurred.
Definition PRunBase.h:266
Double_t fFitEndTime
Fit range end time in microseconds (μs) relative to t0.
Definition PRunBase.h:282
PDoubleVector fFuncValues
Cached values of user-defined functions from FUNCTIONS block, evaluated at current parameters.
Definition PRunBase.h:284
PMsrHandler * fMsrInfo
Pointer to MSR file handler (owned externally, not deleted here)
Definition PRunBase.h:271
virtual void DeadTimeCorrection(std::vector< PDoubleVector > &histos, PUIntVector &histoNo)
carry out dead time correction
Definition PRunBase.cpp:169
PMetaData fMetaData
Experimental metadata extracted from data file header (magnetic field, temperature,...
Definition PRunBase.h:277
std::unique_ptr< PTheory > fTheory
Theory function evaluator (smart pointer, automatically deleted)
Definition PRunBase.h:285
std::vector< PDoubleVector > fAddT0s
Time-zero bin values for additional runs to be added to main run.
Definition PRunBase.h:279
EPMusrHandleTag fHandleTag
Operation mode: kFit (fitting), kView (display only), kEmpty (uninitialized)
Definition PRunBase.h:268
PRunData fData
Processed data container: background-corrected, packed, with theory values.
Definition PRunBase.h:275
PRunDataHandler * fRawData
Pointer to raw data handler (owned externally, not deleted here)
Definition PRunBase.h:273
PDoubleVector fT0s
Time-zero bin values for all histograms in this run (forward, backward, etc.)
Definition PRunBase.h:278
PRunBase()
Default constructor.
Definition PRunBase.cpp:52
Int_t fRunNo
Run number (0-based index in MSR file RUN blocks)
Definition PRunBase.h:270
PMsrRunBlock * fRunInfo
Pointer to this run's RUN block settings within fMsrInfo.
Definition PRunBase.h:272
Double_t fFitStartTime
Fit range start time in microseconds (μs) relative to t0.
Definition PRunBase.h:281
Raw data file reader and format converter for μSR data.
PDoubleVector fForward
Forward detector histogram data (progressively transformed during preparation)
Int_t fEndTimeBin
Last bin index in fit range (exclusive: loop as i < fEndTimeBin)
virtual Double_t CalcChiSquare(const std::vector< Double_t > &par)
Calculates χ² between RRF-transformed data and theory.
PDoubleVector fAerr
Asymmetry errors before RRF packing. Used for packed error calculation.
virtual Double_t GetMainFrequency(PDoubleVector &data)
Finds the dominant precession frequency in raw data.
PRunSingleHistoRRF()
Default constructor creating an empty, invalid RRF single histogram run object.
virtual Double_t EstimateN0(Double_t &errN0, Double_t freqMax)
Estimates initial normalization N₀ from lifetime-corrected data.
virtual Bool_t PrepareFitData(PRawRunData *runData, const UInt_t histoNo)
Performs full RRF transformation for fitting.
Double_t fBackground
Estimated or fixed background level in counts/bin (before packing)
virtual Double_t CalcChiSquareExpected(const std::vector< Double_t > &par)
Calculates expected χ² using theory variance instead of data variance.
virtual ~PRunSingleHistoRRF()
Virtual destructor releasing allocated resources.
virtual Bool_t PrepareData()
Main data preparation orchestrator for RRF single histogram analysis.
Int_t fStartTimeBin
First bin index in fit range (inclusive, 0-based in RRF-packed data)
virtual void GetProperFitRange(PMsrGlobalBlock *globalBlock)
Determines fit time range from MSR file settings.
Bool_t fTheoAsData
Theory resolution mode: true = at data points only, false = 8× finer grid for smooth Fourier transfor...
virtual Bool_t PrepareViewData(PRawRunData *runData, const UInt_t histoNo)
Prepares RRF data for viewing/plotting.
PDoubleVector fM
Lifetime-corrected histogram: M(t) = [N(t) - B] × exp(+t/τ_μ). Used for N₀ estimation.
virtual Bool_t EstimateBkg(UInt_t histoNo)
Estimates background from pre-t0 bins.
Int_t fGoodBins[2]
Good bin range: [0] = first good bin (fgb), [1] = last good bin (lgb). Used for COMMANDS block fit ra...
Double_t fN0EstimateEndTime
End time (μs) for N₀ estimation window. Rounded to integer number of oscillation cycles based on main...
Double_t fBkgErr
Statistical error on background estimate (std dev of background region)
PDoubleVector fMerr
Error on M(t): σ_M = exp(+t/τ_μ) × √(N(t) + σ_B²). Includes background error.
Int_t fRRFPacking
RRF packing factor from GLOBAL block (number of raw bins averaged together)
UInt_t fNoOfFitBins
Number of RRF-packed bins within fit range [fStartTimeBin, fEndTimeBin)
virtual Bool_t GetProperT0(PRawRunData *runData, PMsrGlobalBlock *globalBlock, PUIntVector &histoNo)
Determines and validates t0 values for all histograms.
virtual Double_t CalcMaxLikelihood(const std::vector< Double_t > &par)
Calculates maximum likelihood (not yet implemented for RRF).
virtual Bool_t GetProperDataRange()
Determines valid data range (first/last good bins).
PDoubleVector fW
Weights for N₀ estimation: W(t) = 1/σ_M². Used in weighted average.
virtual void SetFitRangeBin(const TString fitRange)
Sets fit range using bin-offset syntax from COMMANDS block.
virtual UInt_t GetNoOfFitBins()
Returns the number of bins included in the current fit range.
virtual void CalcTheory()
Evaluates theory function at all data points for viewing/plotting.
virtual void CalcNoOfFitBins()
Calculates start/end bin indices from fit time range.