Issue with Using IntegralAndError() with pyroot

_ROOT Version:_root_v6.24.08
python 3.10

Hi everyone,

I have a quick question. I am trying to use the function IntegralAndError() but I am running into a problem with the variable type for the error.

Here is my code:
h is a TH1F and bg_bin_left, and num_bins are the area of the TH1F I am interested in integrating.

  import ROOT
import ctypes
import math, json
import numpy as np
import os
import sys
import datetime 

  b_err_left = ctypes.c_double()
  b_err_right = ctypes.c_double()

  b = h.IntegralAndError(bg_bin_left-num_bins, bg_bin_left,b_err_left)+h.IntegralAndError(bg_bin_right, bg_bin_right+num_bins,b_err_right)
  b_err = math.sqrt(b_err_left*b_err_left + b_err_right*b_err_right)

but I get this error

    b_err = math.sqrt(b_err_left*b_err_left + b_err_right*b_err_right)
TypeError: unsupported operand type(s) for *: 'c_double' and 'c_double' 

any advice on how to fix this? Since I have to use ctypes?

Thanks in advance!

Hi @IP25 ,
This is really not a ROOT issue, ctypes do not support arythmetic operators:

>>> from ctypes import c_double
>>> a = c_double(2.0)
>>> b = c_double(2.0)
>>> a + b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'c_double' and 'c_double'
>>> b - a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'c_double' and 'c_double'
>>> a * b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for *: 'c_double' and 'c_double'

I guess if you really need to use these wrappers, you could access their value attribute. But this is really not the way you should be using ctypes. See their docs for more info.
Cheers,
Vincenzo

Hi, so in the previous version of this code, it used ROOT.Double() and it worked fine.

  b_err_left = ROOT.Double()
  b_err_right = ROOT.Double()

But this has since been deprecated. IntegralAndError doesn’t work unless I use the c++ double class.

But you are right if I do

>>> from ctypes import c_double
>>> a = c_double(2.0)
>>> b = c_double(2.0)
>>> a.value+b.value
4.0

That works! Thanks :slight_smile:

ROOT.Double_t()

that is a lot better than what I was doing! How did you find the new way to do it?