## From \$ROOTSYS/tutorials/spectrum/peaks.C

```// Illustrates how to find peaks in histograms.
// This script generates a random number of gaussian peaks
// on top of a linear background.
// The position of the peaks is found via TSpectrum and injected
// as initial values of parameters to make a global fit.
// The background is computed and drawn on top of the original histogram.
//
// To execute this example, do
//  root > .x peaks.C  (generate 10 peaks by default)
//  root > .x peaks.C++ (use the compiler)
//  root > .x peaks.C++(30) (generates 30 peaks)
//
// To execute only the first part of the script (without fitting)
// specify a negative value for the number of peaks, eg
//  root > .x peaks.C(-20)
//
//Author: Rene Brun

#include "TCanvas.h"
#include "TMath.h"
#include "TH1.h"
#include "TF1.h"
#include "TRandom.h"
#include "TSpectrum.h"
#include "TVirtualFitter.h"

Int_t npeaks = 30;
Double_t fpeaks(Double_t *x, Double_t *par) {
Double_t result = par[0] + par[1]*x[0];
for (Int_t p=0;p<npeaks;p++) {
Double_t norm  = par[3*p+2];
Double_t mean  = par[3*p+3];
Double_t sigma = par[3*p+4];
result += norm*TMath::Gaus(x[0],mean,sigma);
}
return result;
}
void peaks(Int_t np=10) {
npeaks = TMath::Abs(np);
TH1F *h = new TH1F("h","test",500,0,1000);
//generate n peaks at random
Double_t par[3000];
par[0] = 0.8;
par[1] = -0.6/1000;
Int_t p;
for (p=0;p<npeaks;p++) {
par[3*p+2] = 1;
par[3*p+3] = 10+gRandom->Rndm()*980;
par[3*p+4] = 3+2*gRandom->Rndm();
}
TF1 *f = new TF1("f",fpeaks,0,1000,2+3*npeaks);
f->SetNpx(1000);
f->SetParameters(par);
TCanvas *c1 = new TCanvas("c1","c1",10,10,1000,900);
c1->Divide(1,2);
c1->cd(1);
h->FillRandom("f",200000);
h->Draw();
TH1F *h2 = (TH1F*)h->Clone("h2");
//Use TSpectrum to find the peak candidates
TSpectrum *s = new TSpectrum(2*npeaks);
Int_t nfound = s->Search(h,2,"",0.10);
printf("Found %d candidate peaks to fit\n",nfound);
//Estimate background using TSpectrum::Background
TH1 *hb = s->Background(h,20,"same");
if (hb) c1->Update();
if (np <0) return;

//estimate linear background using a fitting method
c1->cd(2);
TF1 *fline = new TF1("fline","pol1",0,1000);
h->Fit("fline","qn");
//Loop on all found peaks. Eliminate peaks at the background level
par[0] = fline->GetParameter(0);
par[1] = fline->GetParameter(1);
npeaks = 0;
Float_t *xpeaks = s->GetPositionX();
for (p=0;p<nfound;p++) {
Float_t xp = xpeaks[p];
Int_t bin = h->GetXaxis()->FindBin(xp);
Float_t yp = h->GetBinContent(bin);
if (yp-TMath::Sqrt(yp) < fline->Eval(xp)) continue;
par[3*npeaks+2] = yp;
par[3*npeaks+3] = xp;
par[3*npeaks+4] = 3;
npeaks++;
}
printf("Found %d useful peaks to fit\n",npeaks);
printf("Now fitting: Be patient\n");
TF1 *fit = new TF1("fit",fpeaks,0,1000,2+3*npeaks);
//we may have more than the default 25 parameters
TVirtualFitter::Fitter(h2,10+3*npeaks);
fit->SetParameters(par);
fit->SetNpx(1000);
h2->Fit("fit");
}
```
peaks.C:1
peaks.C:2
peaks.C:3
peaks.C:4
peaks.C:5
peaks.C:6
peaks.C:7
peaks.C:8
peaks.C:9
peaks.C:10
peaks.C:11
peaks.C:12
peaks.C:13
peaks.C:14
peaks.C:15
peaks.C:16
peaks.C:17
peaks.C:18
peaks.C:19
peaks.C:20
peaks.C:21
peaks.C:22
peaks.C:23
peaks.C:24
peaks.C:25
peaks.C:26
peaks.C:27
peaks.C:28
peaks.C:29
peaks.C:30
peaks.C:31
peaks.C:32
peaks.C:33
peaks.C:34
peaks.C:35
peaks.C:36
peaks.C:37
peaks.C:38
peaks.C:39
peaks.C:40
peaks.C:41
peaks.C:42
peaks.C:43
peaks.C:44
peaks.C:45
peaks.C:46
peaks.C:47
peaks.C:48
peaks.C:49
peaks.C:50
peaks.C:51
peaks.C:52
peaks.C:53
peaks.C:54
peaks.C:55
peaks.C:56
peaks.C:57
peaks.C:58
peaks.C:59
peaks.C:60
peaks.C:61
peaks.C:62
peaks.C:63
peaks.C:64
peaks.C:65
peaks.C:66
peaks.C:67
peaks.C:68
peaks.C:69
peaks.C:70
peaks.C:71
peaks.C:72
peaks.C:73
peaks.C:74
peaks.C:75
peaks.C:76
peaks.C:77
peaks.C:78
peaks.C:79
peaks.C:80
peaks.C:81
peaks.C:82
peaks.C:83
peaks.C:84
peaks.C:85
peaks.C:86
peaks.C:87
peaks.C:88
peaks.C:89
peaks.C:90
peaks.C:91
peaks.C:92
peaks.C:93
peaks.C:94
peaks.C:95
peaks.C:96
peaks.C:97