FitAwmi

This macro fits the source spectrum using the AWMI algorithm from the "TSpectrumFit" class ("TSpectrum" class is used to find peaks).

To try this macro, in a ROOT (5 or 6) prompt, do:

root > .x FitAwmi.C

or:

root > .x FitAwmi.C++
 root > FitAwmi(); // re-run with another random set of peaks

Author:
This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Tuesday, August 09, 2022 at 09:43 AM.

Definition of a helper function:

In [1]:
%%cpp -d

#include "TROOT.h"
#include "TMath.h"
#include "TRandom.h"
#include "TH1.h"
#include "TF1.h"
#include "TCanvas.h"
#include "TSpectrum.h"
#include "TSpectrumFit.h"
#include "TPolyMarker.h"
#include "TList.h"

#include <iostream>

TH1F *FitAwmi_Create_Spectrum(void) {
   Int_t nbins = 1000;
   Double_t xmin = -10., xmax = 10.;
   delete gROOT->FindObject("h"); // prevent "memory leak"
   TH1F *h = new TH1F("h", "simulated spectrum", nbins, xmin, xmax);
   h->SetStats(kFALSE);
   TF1 f("f", "TMath::Gaus(x, [0], [1], 1)", xmin, xmax);
   // f.SetParNames("mean", "sigma");
   gRandom->SetSeed(0); // make it really random
   // create well separated peaks with exactly known means and areas
   // note: TSpectrumFit assumes that all peaks have the same sigma
   Double_t sigma = (xmax - xmin) / Double_t(nbins) * Int_t(gRandom->Uniform(2., 6.));
   Int_t npeaks = 0;
   while (xmax > (xmin + 6. * sigma)) {
      npeaks++;
      xmin += 3. * sigma; // "mean"
      f.SetParameters(xmin, sigma);
      Double_t area = 1. * Int_t(gRandom->Uniform(1., 11.));
      h->Add(&f, area, ""); // "" ... or ... "I"
      std::cout << "created "
                << xmin << " "
                << (area / sigma / TMath::Sqrt(TMath::TwoPi())) << " "
                << area << std::endl;
      xmin += 3. * sigma;
   }
   std::cout << "the total number of created peaks = " << npeaks
             << " with sigma = " << sigma << std::endl;
   return h;
}

Arguments are defined.

In [2]:
TH1F *h = FitAwmi_Create_Spectrum();

TCanvas *cFit = ((TCanvas *)(gROOT->GetListOfCanvases()->FindObject("cFit")));
if (!cFit) cFit = new TCanvas("cFit", "cFit", 10, 10, 1000, 700);
else cFit->Clear();
h->Draw("L");
Int_t i, nfound, bin;
Int_t nbins = h->GetNbinsX();

Double_t *source = new Double_t[nbins];
Double_t *dest = new Double_t[nbins];

for (i = 0; i < nbins; i++) source[i] = h->GetBinContent(i + 1);
TSpectrum *s = new TSpectrum(); // note: default maxpositions = 100
created -9.7 35.9048 9
created -9.1 7.97885 2
created -8.5 7.97885 2
created -7.9 35.9048 9
created -7.3 3.98942 1
created -6.7 27.926 7
created -6.1 23.9365 6
created -5.5 31.9154 8
created -4.9 23.9365 6
created -4.3 31.9154 8
created -3.7 39.8942 10
created -3.1 7.97885 2
created -2.5 7.97885 2
created -1.9 35.9048 9
created -1.3 3.98942 1
created -0.7 19.9471 5
created -0.1 39.8942 10
created 0.5 11.9683 3
created 1.1 27.926 7
created 1.7 7.97885 2
created 2.3 15.9577 4
created 2.9 19.9471 5
created 3.5 19.9471 5
created 4.1 35.9048 9
created 4.7 23.9365 6
created 5.3 39.8942 10
created 5.9 15.9577 4
created 6.5 11.9683 3
created 7.1 39.8942 10
created 7.7 31.9154 8
created 8.3 15.9577 4
created 8.9 31.9154 8
created 9.5 31.9154 8
the total number of created peaks = 33 with sigma = 0.1

searching for candidate peaks positions

In [3]:
nfound = s->SearchHighRes(source, dest, nbins, 2., 2., kFALSE, 10000, kFALSE, 0);

filling in the initial estimates of the input parameters

In [4]:
Bool_t *FixPos = new Bool_t[nfound];
Bool_t *FixAmp = new Bool_t[nfound];
for(i = 0; i < nfound; i++) FixAmp[i] = FixPos[i] = kFALSE;

Double_t *Pos, *Amp = new Double_t[nfound]; // ROOT 6

Pos = s->GetPositionX(); // 0 ... (nbins - 1)
for (i = 0; i < nfound; i++) {
   bin = 1 + Int_t(Pos[i] + 0.5); // the "nearest" bin
   Amp[i] = h->GetBinContent(bin);
}
TSpectrumFit *pfit = new TSpectrumFit(nfound);
pfit->SetFitParameters(0, (nbins - 1), 1000, 0.1, pfit->kFitOptimChiCounts,
                       pfit->kFitAlphaHalving, pfit->kFitPower2,
                       pfit->kFitTaylorOrderFirst);
pfit->SetPeakParameters(2., kFALSE, Pos, FixPos, Amp, FixAmp);

pfit->SetBackgroundParameters(source[0], kFALSE, 0., kFALSE, 0., kFALSE);

In [5]:
pfit->FitAwmi(source);
Double_t *Positions = pfit->GetPositions();
Double_t *PositionsErrors = pfit->GetPositionsErrors();
Double_t *Amplitudes = pfit->GetAmplitudes();
Double_t *AmplitudesErrors = pfit->GetAmplitudesErrors();
Double_t *Areas = pfit->GetAreas();
Double_t *AreasErrors = pfit->GetAreasErrors();
delete gROOT->FindObject("d"); // prevent "memory leak"
TH1F *d = new TH1F(*h); d->SetNameTitle("d", ""); d->Reset("M");
for (i = 0; i < nbins; i++) d->SetBinContent(i + 1, source[i]);
Double_t x1 = d->GetBinCenter(1), dx = d->GetBinWidth(1);
Double_t sigma, sigmaErr;
pfit->GetSigma(sigma, sigmaErr);

current TSpectrumFit needs a sqrt(2) correction factor for sigma

In [6]:
sigma /= TMath::Sqrt2(); sigmaErr /= TMath::Sqrt2();

convert "bin numbers" into "x-axis values"

In [7]:
sigma *= dx; sigmaErr *= dx;

std::cout << "the total number of found peaks = " << nfound
          << " with sigma = " << sigma << " (+-" << sigmaErr << ")"
          << std::endl;
std::cout << "fit chi^2 = " << pfit->GetChi() << std::endl;
for (i = 0; i < nfound; i++) {
   bin = 1 + Int_t(Positions[i] + 0.5); // the "nearest" bin
   Pos[i] = d->GetBinCenter(bin);
   Amp[i] = d->GetBinContent(bin);

   // convert "bin numbers" into "x-axis values"
   Positions[i] = x1 + Positions[i] * dx;
   PositionsErrors[i] *= dx;
   Areas[i] *= dx;
   AreasErrors[i] *= dx;

   std::cout << "found "
             << Positions[i] << " (+-" << PositionsErrors[i] << ") "
             << Amplitudes[i] << " (+-" << AmplitudesErrors[i] << ") "
             << Areas[i] << " (+-" << AreasErrors[i] << ")"
             << std::endl;
}
d->SetLineColor(kRed); d->SetLineWidth(1);
d->Draw("SAME L");
TPolyMarker *pm = ((TPolyMarker*)(h->GetListOfFunctions()->FindObject("TPolyMarker")));
if (pm) {
   h->GetListOfFunctions()->Remove(pm);
   delete pm;
}
pm = new TPolyMarker(nfound, Pos, Amp);
h->GetListOfFunctions()->Add(pm);
pm->SetMarkerStyle(23);
pm->SetMarkerColor(kRed);
pm->SetMarkerSize(1);
the total number of found peaks = 33 with sigma = 0.100002 (+-4.27897e-05)
fit chi^2 = 5.56458e-06
found -3.7 (+-0.000326653) 39.894 (+-0.128728) 10.0001 (+-0.00105641)
found -0.1 (+-0.000326446) 39.8939 (+-0.128717) 10.0001 (+-0.00105631)
found 5.3 (+-0.000326896) 39.894 (+-0.128738) 10.0001 (+-0.00105648)
found 7.1 (+-0.000326971) 39.894 (+-0.128742) 10.0001 (+-0.00105652)
found -9.7 (+-0.000343897) 35.9042 (+-0.122093) 9.00003 (+-0.00100196)
found -7.9 (+-0.000342627) 35.9043 (+-0.122052) 9.00004 (+-0.00100162)
found -1.9 (+-0.000342627) 35.9043 (+-0.122052) 9.00003 (+-0.00100162)
found 4.1 (+-0.000345053) 35.9047 (+-0.122151) 9.00014 (+-0.00100243)
found 7.7 (+-0.000366763) 31.9155 (+-0.115197) 8.00018 (+-0.000945363)
found -5.5 (+-0.000366519) 31.9154 (+-0.115186) 8.00015 (+-0.000945274)
found -4.3 (+-0.000367272) 31.9156 (+-0.115216) 8.00021 (+-0.000945522)
found 8.9 (+-0.000366419) 31.9154 (+-0.115183) 8.00016 (+-0.000945247)
found 9.5 (+-0.000363746) 31.9156 (+-0.115099) 8.0002 (+-0.000944555)
found -6.7 (+-0.000390255) 27.9258 (+-0.107697) 7.00009 (+-0.000883815)
found 1.1 (+-0.000389945) 27.9257 (+-0.107684) 7.00006 (+-0.000883711)
found 4.7 (+-0.000425884) 23.9371 (+-0.0998353) 6.00025 (+-0.000819297)
found -6.1 (+-0.000424958) 23.9369 (+-0.0998065) 6.00019 (+-0.000819061)
found -4.9 (+-0.000425208) 23.9369 (+-0.0998142) 6.00021 (+-0.000819124)
found -0.699996 (+-0.000463818) 19.9473 (+-0.0910732) 5.00014 (+-0.000747391)
found 2.9 (+-0.00046424) 19.9472 (+-0.0910782) 5.00012 (+-0.000747432)
found 3.5 (+-0.000465879) 19.9475 (+-0.0911202) 5.00018 (+-0.000747777)
found 5.9 (+-0.000521185) 15.9581 (+-0.0815085) 4.00017 (+-0.000668898)
found 8.3 (+-0.00052282) 15.9582 (+-0.081541) 4.00021 (+-0.000669165)
found 2.3 (+-0.000518682) 15.9578 (+-0.0814566) 4.00009 (+-0.000668473)
found 0.499998 (+-0.000605947) 11.9689 (+-0.0706533) 3.00022 (+-0.000579815)
found 6.5 (+-0.00060425) 11.9688 (+-0.0706266) 3.00018 (+-0.000579597)
found -9.10001 (+-0.00074055) 7.97927 (+-0.0576735) 2.00014 (+-0.000473297)
found -3.10001 (+-0.000741081) 7.97933 (+-0.0576798) 2.00016 (+-0.000473348)
found 1.7 (+-0.000741742) 7.97927 (+-0.0576842) 2.00014 (+-0.000473384)
found -8.49999 (+-0.00074055) 7.97927 (+-0.0576735) 2.00014 (+-0.000473297)
found -2.49999 (+-0.00074055) 7.97927 (+-0.0576735) 2.00014 (+-0.000473297)
found -7.3 (+-0.00106482) 3.99018 (+-0.04088) 1.00021 (+-0.000335481)
found -1.30001 (+-0.00106214) 3.99008 (+-0.0408644) 1.00018 (+-0.000335354)

cleanup

In [8]:
delete pfit;
delete [] Amp;
delete [] FixAmp;
delete [] FixPos;
delete s;
delete [] dest;
delete [] source;
return;

Draw all canvases

In [9]:
gROOT->GetListOfCanvases()->Draw()