Linear fit residuals

Hello! I am trying to plot the residuals for a simple linear fit but the results I get are different from what I would expect. I can’t understand what I’m doing wrong, any help is very much appreciated

#include "TCanvas.h"
#include "TFile.h"
#include "TH1.h"
#include "TF1.h"
#include "TAxis.h"
#include "TStyle.h"
#include <cmath>
#include <string>
#include <iostream>
using namespace std;

void risoluzione() {

    gStyle->SetOptFit(0011);
    TCanvas *canvas=new TCanvas("canvas", "canvas", 800, 800);


    double energy[4]={525.325,1310.73, 1169.89, 1328.57}; //ch0, no Cs
    double ee[4]={0.05, 0.16, 0.343, 0.38};
    double sigma[4]={18.3131, 29.0482, 28.6102, 28.269};
    double esigma[4]={0.06, 0.202, 0.49, 0.53};
    double FWHM[4]={}; 

    double x[4] = {}; //ch0
    double y[4] ={};
    double ex[4]={0,0,0,0};
    double ey[4]={}; //ch0

    for(int i=0; i<4; i++){
        FWHM[i]=2.355*sigma[i];
        y[i]=FWHM[i]/energy[i];
        x[i]=1/sqrt(energy[i]);
        ey[i]=y[i]*sqrt(pow(esigma[i]/sigma[i],2)+pow(ee[i]/energy[i],2));
        cout << y[i] << endl;
        cout << x[i] << endl;
    };

    TGraphErrors *gr = new TGraphErrors(4,x,y,ex,ey);
    gr->SetMarkerStyle(24);
    gr->SetMarkerSize(0.5); 
    gr->Draw("AP");

    gr->Fit("pol1");

    gr->SetTitle("Risoluzione (ch0);1/#sqrt{E} [keV^{-1/2}];R");

    canvas->Draw();
    
    TCanvas *canvas1=new TCanvas("canvas1", "canvas", 800, 800);
    TGraph *residual= new TGraph;

    TF1 *fitFunc = new TF1("fitFunc", "pol1");
    for (int i=0; i<4; i++){
        Double_t y0 = fitFunc->Eval(x[i]);
        Double_t yr = (gr->GetY()[i] - y0);
        residual->SetPoint(i , x[i], yr);

    }

    residual->Draw("ape");

    


    return;
}



Hi @Liz,
you fitted your data with a pol1 and after the fit you declare the TF1 to compute the residual. But in this way the parameters of your fitFunc are 0s. So your residual plot is the same of your graph.

I changed your code just a little bit,
I moved the fitFunc declaration before the fit of the TGraph and I used the function for the fit.
This is enough to create the residual plot.

In addition:

  • in the for cycle I have removed the declaration of y0 and yr and compute everything in one line.
    but if you prefer to use y0 and yr for the readability of your code is completely fine.
  • I added the SetMarkerStyle to see the data immediately (just aesthetic)

Best,
Stefano

#include "TCanvas.h"
#include "TFile.h"
#include "TH1.h"
#include "TF1.h"
#include "TAxis.h"
#include "TStyle.h"
#include <cmath>
#include <string>
#include <iostream>
using namespace std;

void risoluzione() {

    gStyle->SetOptFit(0011);
    TCanvas *canvas=new TCanvas("canvas", "canvas", 800, 800);


    double energy[4]={525.325,1310.73, 1169.89, 1328.57}; //ch0, no Cs
    double ee[4]={0.05, 0.16, 0.343, 0.38};
    double sigma[4]={18.3131, 29.0482, 28.6102, 28.269};
    double esigma[4]={0.06, 0.202, 0.49, 0.53};
    double FWHM[4]={}; 

    double x[4] = {}; //ch0
    double y[4] ={};
    double ex[4]={0,0,0,0};
    double ey[4]={}; //ch0

    for(int i=0; i<4; i++){
        FWHM[i]=2.355*sigma[i];
        y[i]=FWHM[i]/energy[i];
        x[i]=1/sqrt(energy[i]);
        ey[i]=y[i]*sqrt(pow(esigma[i]/sigma[i],2)+pow(ee[i]/energy[i],2));
        cout << y[i] << endl;
        cout << x[i] << endl;
    };

    TGraphErrors *gr = new TGraphErrors(4,x,y,ex,ey);
    gr->SetMarkerStyle(24);
    gr->SetMarkerSize(0.5); 
    gr->Draw("AP");
    TF1 *fitFunc = new TF1("fitFunc", "pol1");
    gr->Fit("fitFunc");

    gr->SetTitle("Risoluzione (ch0);1/#sqrt{E} [keV^{-1/2}];R");

    canvas->Draw();
    
    TCanvas *canvas1=new TCanvas("canvas1", "canvas", 800, 800);
    TGraph *residual= new TGraph;

   
    for (int i=0; i<4; i++){
        residual->SetPoint(i , x[i], y[i]-fitFunc->Eval(x[i]));

    }
    residual->SetMarkerStyle(21);
    residual->Draw("ape");

    


    return;
}

1 Like

Thank you so so much! :blush:

1 Like