From eac26731183acbfe9bf887f3588f52ddc22cb790 Mon Sep 17 00:00:00 2001 From: Suter Andreas Date: Sat, 6 Dec 2014 10:26:35 +0100 Subject: [PATCH] added proper data alignment for averaging. --- ChangeLog | 2 + src/classes/PMusrCanvas.cpp | 199 +++++++++++++++++++++++++++++++++++- src/include/PMusrCanvas.h | 7 +- 3 files changed, 202 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index acd31761..2c98d854 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,8 @@ NEW 2014-12-04 Fourier: added the unit 'Tesla' needed e.g. for HAL-9500 NEW 2014-12-04 Added the possibility to show the average of currently viewed data. This is useful e.g. when looking at the Fourier of lots of histogram channels (detectors). +FIXED 2014-12-04 added proper alignment for averaging. Still missing: error propagation + for averaging in time based data. changes since 0.11.0 =================================== diff --git a/src/classes/PMusrCanvas.cpp b/src/classes/PMusrCanvas.cpp index b1b07f53..d8ebeba3 100644 --- a/src/classes/PMusrCanvas.cpp +++ b/src/classes/PMusrCanvas.cpp @@ -2842,10 +2842,15 @@ void PMusrCanvas::HandleAverage() // calculate all the average data sets double dval; if (fDataAvg.data != 0) { + if (!CalcAlignment(eTime)) { + cerr << endl << ">> PMusrCanvas::HandleAverage: data: **WARNING** only approx. alignment possible." << endl; + } for (Int_t i=0; iGetNbinsX(); i++) { dval = 0.0; for (UInt_t j=0; jGetBinContent(i); + if ((i-fAlignmentOffset[j]) > 0) { + dval += fData[j].data->GetBinContent(i-fAlignmentOffset[j]); + } } fDataAvg.data->SetBinContent(i, dval/fData.size()); } @@ -2856,10 +2861,15 @@ void PMusrCanvas::HandleAverage() fDataAvg.data->SetMarkerStyle(fData[0].data->GetMarkerStyle()); } if (fDataAvg.dataFourierRe != 0) { + if (!CalcAlignment(eFreq)) { + cerr << endl << ">> PMusrCanvas::HandleAverage: Fourier Re: **WARNING** only approx. alignment possible." << endl; + } for (Int_t i=0; iGetNbinsX(); i++) { dval = 0.0; for (UInt_t j=0; jGetBinContent(i); + if ((i-fAlignmentOffset[j]) > 0) { + dval += fData[j].dataFourierRe->GetBinContent(i-fAlignmentOffset[j]); + } } fDataAvg.dataFourierRe->SetBinContent(i, dval/fData.size()); } @@ -2870,10 +2880,15 @@ void PMusrCanvas::HandleAverage() fDataAvg.dataFourierRe->SetMarkerStyle(fData[0].dataFourierRe->GetMarkerStyle()); } if (fDataAvg.dataFourierIm != 0) { + if (!CalcAlignment(eFreq)) { + cerr << endl << ">> PMusrCanvas::HandleAverage: Fourier Im: **WARNING** only approx. alignment possible." << endl; + } for (Int_t i=0; iGetNbinsX(); i++) { dval = 0.0; for (UInt_t j=0; jGetBinContent(i); + if ((i-fAlignmentOffset[j]) > 0) { + dval += fData[j].dataFourierIm->GetBinContent(i-fAlignmentOffset[j]); + } } fDataAvg.dataFourierIm->SetBinContent(i, dval/fData.size()); } @@ -2884,10 +2899,15 @@ void PMusrCanvas::HandleAverage() fDataAvg.dataFourierIm->SetMarkerStyle(fData[0].dataFourierIm->GetMarkerStyle()); } if (fDataAvg.dataFourierPwr != 0) { + if (!CalcAlignment(eFreq)) { + cerr << endl << ">> PMusrCanvas::HandleAverage: Fourier Pwr: **WARNING** only approx. alignment possible." << endl; + } for (Int_t i=0; iGetNbinsX(); i++) { dval = 0.0; for (UInt_t j=0; jGetBinContent(i); + if ((i-fAlignmentOffset[j]) > 0) { + dval += fData[j].dataFourierPwr->GetBinContent(i-fAlignmentOffset[j]); + } } fDataAvg.dataFourierPwr->SetBinContent(i, dval/fData.size()); } @@ -2898,10 +2918,15 @@ void PMusrCanvas::HandleAverage() fDataAvg.dataFourierPwr->SetMarkerStyle(fData[0].dataFourierPwr->GetMarkerStyle()); } if (fDataAvg.dataFourierPhase != 0) { + if (!CalcAlignment(eFreq)) { + cerr << endl << ">> PMusrCanvas::HandleAverage: Fourier Phase: **WARNING** only approx. alignment possible." << endl; + } for (Int_t i=0; iGetNbinsX(); i++) { dval = 0.0; for (UInt_t j=0; jGetBinContent(i); + if ((i-fAlignmentOffset[j]) > 0) { + dval += fData[j].dataFourierPhase->GetBinContent(i-fAlignmentOffset[j]); + } } fDataAvg.dataFourierPhase->SetBinContent(i, dval/fData.size()); } @@ -2911,6 +2936,21 @@ void PMusrCanvas::HandleAverage() fDataAvg.dataFourierPhase->SetMarkerSize(fData[0].dataFourierPhase->GetMarkerSize()); fDataAvg.dataFourierPhase->SetMarkerStyle(fData[0].dataFourierPhase->GetMarkerStyle()); } + if (fDataAvg.theory != 0) { + if (!CalcAlignment(eTheoTime)) { + cerr << endl << ">> PMusrCanvas::HandleAverage: theory: **WARNING** only approx. alignment possible." << endl; + } + for (Int_t i=0; iGetNbinsX(); i++) { + dval = 0.0; + for (UInt_t j=0; j 0) { + dval += fData[j].theory->GetBinContent(i-fAlignmentOffset[j]); + } + } + fDataAvg.theory->SetBinContent(i, dval/fData.size()); + } + fDataAvg.theory->SetLineColor(fData[0].theory->GetLineColor()); + } if (fDataAvg.theoryFourierRe != 0) { for (Int_t i=0; iGetNbinsX(); i++) { dval = 0.0; @@ -2967,6 +3007,25 @@ void PMusrCanvas::HandleAverage() fDataAvg.theoryFourierPhase->SetMarkerSize(fData[0].theoryFourierPhase->GetMarkerSize()); fDataAvg.theoryFourierPhase->SetMarkerStyle(fData[0].theoryFourierPhase->GetMarkerStyle()); } + if (fDataAvg.diff != 0) { + if (!CalcAlignment(eTime)) { + cerr << endl << ">> PMusrCanvas::HandleAverage: diff: **WARNING** only approx. alignment possible." << endl; + } + for (Int_t i=0; iGetNbinsX(); i++) { + dval = 0.0; + for (UInt_t j=0; j 0) { + dval += fData[j].diff->GetBinContent(i-fAlignmentOffset[j]); + } + } + fDataAvg.diff->SetBinContent(i, dval/fData.size()); + } + // set marker color, line color, maker size, marker type + fDataAvg.diff->SetMarkerColor(fData[0].diff->GetMarkerColor()); + fDataAvg.diff->SetLineColor(fData[0].diff->GetLineColor()); + fDataAvg.diff->SetMarkerSize(fData[0].diff->GetMarkerSize()); + fDataAvg.diff->SetMarkerStyle(fData[0].diff->GetMarkerStyle()); + } if (fDataAvg.diffFourierRe != 0) { for (Int_t i=0; iGetNbinsX(); i++) { dval = 0.0; @@ -6209,3 +6268,133 @@ UInt_t PMusrCanvas::GetNeededAccuracy(PMsrParamStructure param) return accuracy; } + + +//-------------------------------------------------------------------------- +// CalcAlignment (private) +//-------------------------------------------------------------------------- +/** + *

Calculates the alignment index for each data set needed to average the data. + * + * return: + * - true for perfect alignment + * - false for approximate alignment + * + * \param tag to distinguish time data sets from Fourier data sets. + */ +Bool_t PMusrCanvas::CalcAlignment(const EAlignTag tag) +{ + Bool_t result = true; + + fAlignmentOffset.clear(); + + UInt_t idx=0; + Double_t dval; + if (tag == eTime) { + // first find the data vector with the lowest initial time + dval = fData[0].data->GetXaxis()->GetBinCenter(1); + for (UInt_t i=1; iGetXaxis()->GetBinCenter(1) < dval) { + idx = i; + dval = fData[i].data->GetXaxis()->GetBinCenter(1); + } + } + + // next setp: find all the alignment indices + fAlignmentOffset.resize(fData.size()); + for (UInt_t i=0; iGetXaxis()->GetBinCenter(1); + Int_t j=1; + Bool_t found = false; + do { + if (fData[idx].data->GetXaxis()->GetBinCenter(j) >= dval) { + fAlignmentOffset[i] = (UInt_t)(j-1); + if (fData[idx].data->GetXaxis()->GetBinCenter(j) != dval) { + result = false; + } + found = true; + } + } while (!found && (++jGetNbinsX())); + } + } else if (tag == eTheoTime) { + // first find the data vector with the lowest initial time + dval = fData[0].theory->GetXaxis()->GetBinCenter(1); + for (UInt_t i=1; iGetXaxis()->GetBinCenter(1) < dval) { + idx = i; + dval = fData[i].theory->GetXaxis()->GetBinCenter(1); + } + } + + // next setp: find all the alignment indices + fAlignmentOffset.resize(fData.size()); + for (UInt_t i=0; iGetXaxis()->GetBinCenter(1); + Int_t j=1; + Bool_t found = false; + do { + if (fData[idx].theory->GetXaxis()->GetBinCenter(j) >= dval) { + fAlignmentOffset[i] = (UInt_t)(j-1); + if (fData[idx].theory->GetXaxis()->GetBinCenter(j) != dval) { + result = false; + } + found = true; + } + } while (!found && (++jGetNbinsX())); + } + } else if (tag == eFreq) { + // first find the data vector with the lowest initial time + dval = fData[0].dataFourierRe->GetXaxis()->GetBinCenter(1); + for (UInt_t i=1; iGetXaxis()->GetBinCenter(1) < dval) { + idx = i; + dval = fData[i].dataFourierRe->GetXaxis()->GetBinCenter(1); + } + } + + // next setp: find all the alignment indices + fAlignmentOffset.resize(fData.size()); + for (UInt_t i=0; iGetXaxis()->GetBinCenter(1); + Int_t j=1; + Bool_t found = false; + do { + if (fData[idx].dataFourierRe->GetXaxis()->GetBinCenter(j) >= dval) { + fAlignmentOffset[i] = (UInt_t)(j-1); + if (fData[idx].dataFourierRe->GetXaxis()->GetBinCenter(j) != dval) { + result = false; + } + found = true; + } + } while (!found && (++jGetNbinsX())); + } + } else if (tag == eTheoFreq) { + // first find the data vector with the lowest initial time + dval = fData[0].theoryFourierRe->GetXaxis()->GetBinCenter(1); + for (UInt_t i=1; iGetXaxis()->GetBinCenter(1) < dval) { + idx = i; + dval = fData[i].theoryFourierRe->GetXaxis()->GetBinCenter(1); + } + } + + // next setp: find all the alignment indices + fAlignmentOffset.resize(fData.size()); + for (UInt_t i=0; iGetXaxis()->GetBinCenter(1); + Int_t j=1; + Bool_t found = false; + do { + if (fData[idx].theoryFourierRe->GetXaxis()->GetBinCenter(j) >= dval) { + fAlignmentOffset[i] = (UInt_t)(j-1); + if (fData[idx].theoryFourierRe->GetXaxis()->GetBinCenter(j) != dval) { + result = false; + } + found = true; + } + } while (!found && (++jGetNbinsX())); + } + } + + return result; +} diff --git a/src/include/PMusrCanvas.h b/src/include/PMusrCanvas.h index a9af4d76..eaf0b5ac 100644 --- a/src/include/PMusrCanvas.h +++ b/src/include/PMusrCanvas.h @@ -277,8 +277,11 @@ class PMusrCanvas : public TObject, public TQObject PRunListCollection *fRunList; ///< data handler #endif // __MAKECINT__ - PMusrCanvasDataList fData; ///< list of all histogram data to be plotted (asymmetry/single histogram) + enum EAlignTag {eTime, eTheoTime, eFreq, eTheoFreq}; PMusrCanvasDataSet fDataAvg; ///< set of all averaged data to be plotted (asymmetry/single histogram) + PIntVector fAlignmentOffset; ///< holds the vector with the time/freq alignment offsets + + PMusrCanvasDataList fData; ///< list of all histogram data to be plotted (asymmetry/single histogram) PMusrCanvasNonMusrDataList fNonMusrData; ///< list of all error graphs to be plotted (non-muSR) TMultiGraph *fMultiGraphData; ///< fMultiGraphData is a 'global' graph needed in order to plot error graphs (data) with (potentially) different x-frames TMultiGraph *fMultiGraphDiff; ///< fMultiGraphDiff is a 'global' graph needed in order to plot error graphs (data-theory) with (potentially) different x-frames @@ -331,6 +334,8 @@ class PMusrCanvas : public TObject, public TQObject virtual Bool_t IsScaleN0AndBkg(); virtual UInt_t GetNeededAccuracy(PMsrParamStructure param); + virtual Bool_t CalcAlignment(const EAlignTag tag); + ClassDef(PMusrCanvas, 1) };