musrfit 1.10.0
PPrepFourier.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 PPrepFourier.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 <cmath>
31
32#include "PPrepFourier.h"
33
34//--------------------------------------------------------------------------
35// Constructor
36//--------------------------------------------------------------------------
44{
45 fBkgRange[0] = -1;
46 fBkgRange[1] = -1;
47 fPacking = 1;
48}
49
50//--------------------------------------------------------------------------
51// Constructor
52//--------------------------------------------------------------------------
64PPrepFourier::PPrepFourier(const Int_t packing, const Int_t *bkgRange, PDoubleVector bkg) :
65 fPacking(packing)
66{
67 SetBkgRange(bkgRange);
68 SetBkg(bkg);
69}
70
71//--------------------------------------------------------------------------
72// Destructor
73//--------------------------------------------------------------------------
81{
82 fRawData.clear();
83 fData.clear();
84}
85
86//--------------------------------------------------------------------------
87// SetBkgRange
88//--------------------------------------------------------------------------
99void PPrepFourier::SetBkgRange(const Int_t *bkgRange)
100{
101 Int_t err=0;
102 if (bkgRange[0] >= -1) {
103 fBkgRange[0] = bkgRange[0];
104 } else {
105 err = 1;
106 }
107 if (bkgRange[1] >= -1) {
108 fBkgRange[1] = bkgRange[1];
109 } else {
110 if (err == 0)
111 err = 2;
112 else
113 err = 3;
114 }
115
116 TString errMsg("");
117 switch (err) {
118 case 1:
119 errMsg = TString::Format("start bkg range < 0 (given: %d), will ignore it.", bkgRange[0]);
120 break;
121 case 2:
122 errMsg = TString::Format("end bkg range < 0 (given: %d), will ignore it.", bkgRange[1]);
123 break;
124 case 3:
125 errMsg = TString::Format("start/end bkg range < 0 (given: %d/%d), will ignore it.", bkgRange[0], bkgRange[1]);
126 break;
127 default:
128 errMsg = TString("??");
129 break;
130 }
131
132 if (err != 0) {
133 std::cerr << std::endl << ">> PPrepFourier::SetBkgRange: **WARNING** " << errMsg << std::endl;
134 }
135}
136
137//--------------------------------------------------------------------------
138// SetBkg
139//--------------------------------------------------------------------------
150{
151 for (UInt_t i=0; i<bkg.size(); i++)
152 fBkg.push_back(bkg[i]);
153}
154
155//--------------------------------------------------------------------------
156// SetPacking
157//--------------------------------------------------------------------------
167void PPrepFourier::SetPacking(const Int_t packing)
168{
169 if (packing > 0) {
170 fPacking = packing;
171 } else {
172 std::cerr << std::endl << ">> PPrepFourier::SetPacking: **WARNING** found packing=" << packing << " < 0, will ignore it." << std::endl;
173 }
174}
175
176//--------------------------------------------------------------------------
177// AddData
178//--------------------------------------------------------------------------
189{
190 fRawData.push_back(data);
191}
192
193//--------------------------------------------------------------------------
194// DoBkgCorrection
195//--------------------------------------------------------------------------
210{
211 // make sure fData are already present, and if not create the necessary data sets
212 if (fData.size() != fRawData.size()) {
213 InitData();
214 }
215
216 // if no bkg-range is given, nothing needs to be done
217 if ((fBkgRange[0] == -1) && (fBkgRange[1] == -1) && (fBkg.size() == 0)) {
218 return;
219 }
220
221 if ((fBkgRange[0] != -1) && (fBkgRange[1] != -1)) { // background range is given
222 // make sure that the bkg range is ok
223 for (UInt_t i=0; i<fRawData.size(); i++) {
224 if ((fBkgRange[0] >= static_cast<Int_t>(fRawData[i].rawData.size())) || (fBkgRange[1] >= static_cast<Int_t>(fRawData[i].rawData.size()))) {
225 std::cerr << std::endl << "PPrepFourier::DoBkgCorrection() **ERROR** bkg-range out of data-range!";
226 return;
227 }
228 }
229
230 Double_t bkg=0.0;
231 for (UInt_t i=0; i<fRawData.size(); i++) {
232 // calculate the bkg for the given range
233 for (Int_t j=fBkgRange[0]; j<=fBkgRange[1]; j++) {
234 bkg += fRawData[i].rawData[j];
235 }
236 bkg /= (fBkgRange[1]-fBkgRange[0]+1);
237 std::cout << "info> background " << i << ": " << bkg << std::endl;
238
239 // correct data
240 for (UInt_t j=0; j<fData[i].size(); j++)
241 fData[i][j] -= bkg;
242 }
243 } else { // there might be an explicit background list
244 // check if there is a background list
245 if (fBkg.size() == 0)
246 return;
247
248 // check if there are as many background values than data values
249 if (fBkg.size() != fData.size()) {
250 std::cerr << std::endl << "PPrepFourier::DoBkgCorrection() **ERROR** #bkg values != #histos. Will do nothing here." << std::endl;
251 return;
252 }
253
254 for (UInt_t i=0; i<fData.size(); i++)
255 for (UInt_t j=0; j<fData[i].size(); j++)
256 fData[i][j] -= fBkg[i];
257 }
258}
259
260//--------------------------------------------------------------------------
261// DoPacking
262//--------------------------------------------------------------------------
274{
275 // make sure fData are already present, and if not create the necessary data sets
276 if (fData.size() != fRawData.size()) {
277 InitData();
278 }
279
280 if (fPacking == 1) // nothing to be done
281 return;
282
283 PDoubleVector tmpData;
284 Double_t dval = 0.0;
285 for (UInt_t i=0; i<fData.size(); i++) {
286 tmpData.clear();
287 dval = 0.0;
288 for (UInt_t j=0; j<fData[i].size(); j++) {
289 if ((j % fPacking == 0) && (j != 0)) {
290 tmpData.push_back(dval);
291 dval = 0.0;
292 } else {
293 dval += fData[i][j];
294 }
295 }
296 // change the original data set with the packed one
297 fData[i].clear();
298 fData[i] = tmpData;
299 }
300}
301
302//--------------------------------------------------------------------------
303// DoLifeTimeCorrection
304//--------------------------------------------------------------------------
323{
324 // make sure fData are already present, and if not create the necessary data sets
325 if (fData.size() != fRawData.size()) {
326 InitData();
327 }
328
329 // calc exp(+t/tau)*N(t), where N(t) is already background corrected
330 Double_t scale;
331 for (UInt_t i=0; i<fData.size(); i++) {
332 scale = fRawData[i].timeResolution / PMUON_LIFETIME;
333 for (UInt_t j=0; j<fData[i].size(); j++) {
334 fData[i][j] *= exp(j*scale);
335 }
336 }
337
338 // calc N0
339 Double_t dval;
340 Double_t N0;
341 for (UInt_t i=0; i<fData.size(); i++) {
342 dval = 0.0;
343 for (UInt_t j=0; j<fData[i].size(); j++) {
344 dval += fData[i][j];
345 }
346 N0 = dval/fData[i].size();
347 N0 *= fudge;
348 for (UInt_t j=0; j<fData[i].size(); j++) {
349 fData[i][j] -= N0;
350 fData[i][j] /= N0;
351 }
352 }
353}
354
355//--------------------------------------------------------------------------
356// GetInfo
357//--------------------------------------------------------------------------
364TString PPrepFourier::GetInfo(const UInt_t idx)
365{
366 TString info("");
367
368 if (idx < fRawData.size())
369 info = fRawData[idx].info;
370
371 return info;
372}
373
374//--------------------------------------------------------------------------
375// GetDataSetTag
376//--------------------------------------------------------------------------
386Int_t PPrepFourier::GetDataSetTag(const UInt_t idx)
387{
388 Int_t result = -1;
389
390 if (idx < fRawData.size())
391 result = fRawData[idx].dataSetTag;
392
393 return result;
394}
395
396//--------------------------------------------------------------------------
397// GetData
398//--------------------------------------------------------------------------
411std::vector<TH1F*> PPrepFourier::GetData()
412{
413 std::vector<TH1F*> data;
414 data.resize(fData.size());
415
416 // if not data are present, just return an empty vector
417 if (fData.size() == 0)
418 return data;
419
420 TString name("");
421 Double_t dt=0.0;
422 Double_t start=0.0;
423 Double_t end=0.0;
424 UInt_t size;
425 UInt_t startIdx;
426 UInt_t endIdx;
427
428 for (UInt_t i=0; i<fData.size(); i++) {
429 name = TString::Format("histo%2d", i);
430 dt = fRawData[i].timeResolution*fPacking;
431 start = fRawData[i].timeRange[0];
432 end = fRawData[i].timeRange[1];
433
434 // init size and start/end indices
435 size = fData[i].size();
436 startIdx = 1;
437 endIdx = size;
438
439 // time range given, hence calculate the proper size
440 if (start != -1.0) {
441 size = static_cast<UInt_t>((end-start)/dt);
442 if (start >= 0.0) {
443 startIdx = static_cast<UInt_t>(start/dt)+1;
444 endIdx = static_cast<UInt_t>(end/dt)+1;
445 } else {
446 std::cerr << std::endl << ">> PPrepFourier::GetData **WARNING** found start time < 0.0, will set it to 0.0" << std::endl;
447 endIdx = static_cast<UInt_t>(end/dt)+1;
448 }
449 }
450
451 if (start == -1.0) { // no time range given, hence start == 0.0 - dt/2
452 start = -dt/2.0;
453 } else { // time range given
454 start -= dt/2.0;
455 }
456
457 if (end == -1.0) { // no time range given, hence end == (fData[idx].size()-1)*dt + dt/2
458 end = (fData[i].size()-1)*dt+dt/2.0;
459 } else { // time range given
460 end += dt/2.0;
461 }
462
463 data[i] = new TH1F(name.Data(), fRawData[i].info.Data(), size, start, end);
464 for (UInt_t j=startIdx; j<endIdx; j++)
465 data[i]->SetBinContent(j-startIdx+1, fData[i][j]);
466 }
467
468 return data;
469}
470
471//--------------------------------------------------------------------------
472// GetData
473//--------------------------------------------------------------------------
488TH1F *PPrepFourier::GetData(const UInt_t idx)
489{
490 if (fData.size() == 0) // no data present
491 return nullptr;
492
493 if (idx > fData.size()) // requested index out of range
494 return nullptr;
495
496 TString name = TString::Format("histo%2d", idx);
497 Double_t dt = fRawData[idx].timeResolution*fPacking;
498 Double_t start = fRawData[idx].timeRange[0];
499 Double_t end = fRawData[idx].timeRange[1];
500 UInt_t size = fData[idx].size();
501 UInt_t startIdx = 1;
502 UInt_t endIdx = size;
503
504 // time range given, hence calculate the proper size
505 if (start != -1.0) {
506 size = static_cast<UInt_t>((end-start)/dt);
507 if (start >= 0.0) {
508 startIdx = static_cast<UInt_t>(start/dt)+1;
509 endIdx = static_cast<UInt_t>(end/dt)+1;
510 } else {
511 std::cerr << std::endl << ">> PPrepFourier::GetData **WARNING** found start time < 0.0, will set it to 0.0" << std::endl;
512 endIdx = static_cast<UInt_t>(end/dt)+1;
513 }
514 }
515
516 if (start == -1.0) { // no time range given, hence start == 0.0 - dt/2
517 start = -dt/2.0;
518 } else { // time range given
519 start -= dt/2.0;
520 }
521
522 if (end == -1.0) { // no time range given, hence end == (fData[idx].size()-1)*dt + dt/2
523 end = (fData[idx].size()-1)*dt+dt/2.0;
524 } else { // time range given
525 end += dt/2.0;
526 }
527
528 TH1F *data = new TH1F(name.Data(), fRawData[idx].info.Data(), size, start, end);
529 for (UInt_t i=startIdx; i<endIdx; i++)
530 data->SetBinContent(i-startIdx+1, fData[idx][i]);
531
532 return data;
533}
534
535//--------------------------------------------------------------------------
536// InitData (private)
537//--------------------------------------------------------------------------
549{
550 fData.resize(fRawData.size());
551 UInt_t t0;
552 for (UInt_t i=0; i<fRawData.size(); i++) {
553 if (fRawData[i].t0 >= 0)
554 t0 = fRawData[i].t0;
555 else
556 t0 = 0;
557 for (UInt_t j=t0; j<fRawData[i].rawData.size(); j++) {
558 fData[i].push_back(fRawData[i].rawData[j]);
559 }
560 }
561}
#define PMUON_LIFETIME
Definition PMusr.h:119
std::vector< Double_t > PDoubleVector
Definition PMusr.h:385
virtual void InitData()
Initializes processed data from raw data.
Int_t fBkgRange[2]
Background range: [0]=start bin, [1]=end bin (-1=unused)
std::vector< PDoubleVector > fData
Processed data (after t0, corrections, packing)
PPrepFourier()
Default constructor (requires separate configuration)
virtual void DoLifeTimeCorrection(Double_t fudge)
Applies muon lifetime correction for theory-free analysis.
Int_t fPacking
Rebinning factor (1=no rebinning, N=combine N bins)
virtual void SetPacking(const Int_t packing)
Sets rebinning/packing factor for data reduction.
std::vector< musrFT_data > fRawData
Raw input data sets with metadata.
PDoubleVector fBkg
Explicit background values (one per data set)
virtual void SetBkg(PDoubleVector bkg)
Sets explicit background values for each data set.
Int_t GetDataSetTag(const UInt_t idx)
Returns data set tag identifier.
virtual void AddData(musrFT_data &data)
Adds a time-domain data set for processing.
std::vector< TH1F * > GetData()
Creates ROOT histograms for all processed data sets.
virtual ~PPrepFourier()
Destructor.
virtual void DoBkgCorrection()
Applies background correction to all data sets.
virtual void SetBkgRange(const Int_t *bkgRange)
Sets background range for automatic background calculation.
TString GetInfo(const UInt_t idx)
Returns metadata string for a specific data set.
virtual void DoPacking()
Applies rebinning/packing to reduce data points.
Data structure holding raw time-domain μSR data with metadata.