Fitting IV curve with a combination of pol1 and pol2

Hi ROOTers,

I acquired some IV curve and im trying to fit them using a combination of linear and parabola fit. The macro used

bool reject = false;

double splitline(const double *x, const double *p) {
  // y = a + b * (x - x0) + c * (x - x0) * (x - x0)
  double x0 = p[0]; // "point of split"
  double a = p[1]; // "left" and "right" (linear and parabolic)
  double b_left = p[2]; // "left" (linear)
  double b_right = p[3]; // "right" (parabolic)
  double c_right = p[4]; // "right" (parabolic)
  double dx = x[0] - x0;
  // when fitting, exclude points which are close to the "point of split"
  if (reject && (dx > -1.075) && (dx < 0.3)) // note: asymmetric range, change it in order to obtain the best chi squared
  return (a + ((dx < 0.) ? b_left : b_right + c_right * dx) * dx);

void hamamatsu(const char *fname = "1_inversa.txt") {
  if (!(fname && fname[0])) return; // just a precaution
  TGraphErrors *g = new TGraphErrors(fname);
  if (!(g->GetN())) return; // just a precaution
  g->Sort(); // just a precaution
  g->SetTitle("Curve I-V;Reverse-bias [V];Current [nA]");
  TCanvas *c = new TCanvas("c", "Curve I-V");
  c->SetGrid(1, 1);
  c->SetTicks(1, 1);
  gStyle->SetOptFit(000); // 111 per vedere i parametri di fit
  TF1 *f = new TF1("f_splitline", splitline, g->GetX()[0], g->GetX()[(g->GetN() - 1)], 5);
  f->SetParNames("x0", "a", "b_left", "b_right", "c_right");
  // note: one should always set "reasonable" initial values for all parameters
  f->SetParameters((g->GetX()[0] + g->GetX()[(g->GetN() - 1)]) / 2., g->GetY()[0], 0., 0., 0.);
  // f->SetParameters(50., 0.1, 0., 10., 10.);
#if 0 /* 0 or 1 */
  // try to make the fit more "robust" (when initial parameters are not good)
  // f->SetParLimits(0, g->GetX()[0], g->GetX()[(g->GetN() - 1)]); // x0
  // f->SetParLimits(1, 0., 1000.); // a >= 0
  f->SetParLimits(2, 0., 1000.); // b_left >= 0
  f->SetParLimits(3, 0., 1000.); // b_right >= 0
  f->SetParLimits(4, 0., 1000.); // c_right >= 0
#endif /* 0 or 1 */
  reject = true;
  g->Fit(f, "QN"); // first "initial pre-fit"
  g->Fit(f, "QN"); // second "initial pre-fit"
  g->Fit(f, "QN"); // third "initial pre-fit"
  g->Fit(f, "QN"); // fourth "initial pre-fit"
  g->Fit(f, ""); // "final fit"
  reject = false;

works perfectly for some kind of curve like HPK_S13_anode10_25C_inv.txt (6,5 KB):

but not the same for another kind of IV curve like Ch1_inv.txt (3,2 KB):

Someone can help me please?

Hi Samuele,

Interesting use case, thanks for sharing.

By looking at your second plot, my first question would be whether you tried to reduce the range in which you perform the fit. For example, your functional form seems to reproduce your data but after 2 or so, judging by some qualitative by-eye analysis…

I hope this helps.


1 Like

I tried but doesn’t work:

@Danilo do you tried to run locally the macro and second file?

I don’t understand why doesn’t work…


maybe setting the initial value of the parameters could help?


No… maybe I’m doing wrong something…

This code was written thanks the help of @Wile_E_Coyote some times ago…maybe He can give some suggestion.

I think the main issue is the fit of the split parameter, I set the parameter p0 manually to 39.5 and the fit is slightly better as you can see from the figure. Look for a sharp change of the first derivative could be a good way to estimate the split point.


On the other hand I am not sure the same parameter a is good both the linear part and parabolic one.


Looking at the graph with linear y scale, the left part doesn’t seem completely linear.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.