Skip to content

[RF] RooDataSet.from_numpy gives wrong result when the input arrays are not c-contiguous #13605

Description

@AlkaidCheng

Check duplicate issues.

  • Checked for duplicates

Description

If the input numpy arrays to RooDataSet.from_numpy are not c-contiguous, then the resulting dataset will have messed up values.

Reproducer

import itertools
import numpy as np

import ROOT

obs_1 = ROOT.RooRealVar('obs_1' , 'obs_1', 70, 70, 190)
obs_1.setBins(30)
obs_2 = ROOT.RooRealVar('obs_2' , 'obs_2', 100, 100, 180)
obs_2.setBins(80)

val_obs_1 = []
val_obs_2 = []
for i in range(obs_1.numBins()):
    obs_1.setBin(i)
    val_obs_1.append(obs_1.getVal())
for i in range(obs_2.numBins()):
    obs_2.setBin(i)
    val_obs_2.append(obs_2.getVal())    

# so that all combination of values are in the dataset
val_cart_product = np.array(list(itertools.product(val_obs_1, val_obs_2)))
data = {
    'obs_1': val_cart_product[:, 0],
    'obs_2': val_cart_product[:, 1]
}

dataset = ROOT.RooDataSet.from_numpy(data, ROOT.RooArgSet(obs_1, obs_2))

This gives (memory dependent):

>>> dataset.to_numpy()
{'obs_1': array([ 72. , 100.5,  72. , ..., 178.5, 128. , 179.5]),
 'obs_2': array([100.5,  72. , 101.5, ..., 128. , 179.5, 132. ])}

The expected output should be

>>> dataset.to_numpy()
{'obs_1': array([ 72.,  72.,  72., ..., 188., 188., 188.]),
 'obs_2': array([100.5, 101.5, 102.5, ..., 177.5, 178.5, 179.5])}

This happens because the arrays data['obs_1'] and data['obs_2'] are not c-contiguous:

>>> data['obs_1'].flags
  C_CONTIGUOUS : False
  F_CONTIGUOUS : False
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False

If we make the arrays c-contiguous, the resulting dataset is correct:

for key, arr in data.items():
    if not arr.flags.c_contiguous:
        data[key] = np.ascontiguousarray(arr)
dataset = ROOT.RooDataSet.from_numpy(data, ROOT.RooArgSet(obs_1, obs_2))

this gives

>>> dataset.to_numpy()
{'obs_1': array([ 72.,  72.,  72., ..., 188., 188., 188.]),
 'obs_2': array([100.5, 101.5, 102.5, ..., 177.5, 178.5, 179.5])}

This issue arises because the copying of numpy data to std::vector assumes the numpy array to be c-contiguous:
https://github.com/root-project/root/blob/master/bindings/pyroot/pythonizations/python/ROOT/_pythonization/_roofit/_roodataset.py#L129-L132

ROOT version

ROOT 6.26/08+

Installation method

lxplus

Operating system

Linux

Additional context

No response

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions