list<RooAbsData*> returned from RooWorkspace [RESOLVED]

Hi,

I cannot figure out how to work with the std::lists returned from RooFit objects. In particular, I have a RooWorkspace with a few datasets stored in it. I get all of them by

_file = TFile("myWS.root")
_ws = _file.Get("myWS")
_data = ws.allData()
print _data

It outputs

But now I have no idea how to iterate over it or access elements. I can access the first one with
[EDITED]

and I can create an iterator with begin() but how do I increment and dereference it? I would like an equivalent of c++ code like

for (std::list<RooAbsData *>::iterator i=_data.begin(); i != _data.end(); ++i){
   i->Print();
}

Is something like that possible with PyROOT?

Hi,

the python-equivalent of such a loop is:

for i in _data: i.Print()
Cheers,
Wim

Hi Wim,

that’s the thing: it doesn’t work like that. This was the first thing I’ve tried, and it says that the object is not iterable. As Charles Plager pointed out, it works with ROOT.list of ints but not with this ROOT.list of RooAbsData*. I will try to set up a compact test script…

Hi,

sounds odd, as it wouldn’t be iterable if there is no dictionary for this particular list. But if there isn’t then I’d expect methods like first() and begin() not to work.

Hmm, well then to answer your earlier question: dereferencing of iterators should be deref() and incrementing is postinc() and preinc() as one prefers.

Cheers,
Wim

Hi Wim,

thanks! Here’s a script that illustrates the problem that I’m having. In my case, it complains about the _data object being not iterable:

(I will try your other suggestions, they might help sidestep the problem)

#!/usr/bin/env python

from ROOT import RooWorkspace
from ROOT import RooAbsData
from ROOT import RooDataSet
from ROOT import RooFit


wspace = RooWorkspace('wspace')

# make model (taken from roostats tutorials)
wspace.factory("Poisson::on(non[0,1000], sum::splusb(s[40,0,100],b[100,0,300]))")
wspace.factory("Poisson::off(noff[0,5000], prod::taub(b,tau[5,3,7],rho[1,0,2]))")
wspace.factory("Poisson::onbar(nonbar[0,10000], bbar[1000,500,2000])")
wspace.factory("Poisson::offbar(noffbar[0,1000000], prod::lambdaoffbar(bbar, tau))")
wspace.factory("Gaussian::mcCons(rhonom[1.,0,2], rho, sigma[.2])")
wspace.factory("PROD::model(on,off,onbar,offbar,mcCons)")
wspace.defineSet("obs","non,noff,nonbar,noffbar,rhonom")

data = wspace.pdf("model").generate(wspace.set("obs"),1)
data2 = wspace.pdf("model").generate(wspace.set("obs"),1, RooFit.Name('data2'))
data3 = wspace.pdf("model").generate(wspace.set("obs"),1, RooFit.Name('data3'))
data4 = wspace.pdf("model").generate(wspace.set("obs"),1, RooFit.Name('data4'))

data.Print("v");
getattr(wspace, 'import')(data)
getattr(wspace, 'import')(data2)
getattr(wspace, 'import')(data3)
getattr(wspace, 'import')(data4)

wspace.Print()

_data = wspace.allData()
    
for ds in _data:
    print ds

[quote=“wlav”]…sounds odd, as it wouldn’t be iterable if there is no dictionary for this particular list. But if there isn’t then I’d expect methods like first() and begin() not to work

Cheers,
Wim[/quote]
Wim, my bad, it’s not _data.first() that gets me the first entry but _data.front(). I’ve edited (and marked) the original post accordingly. I guess that the dictionary is not there but I have no idea what is responsible for filling it.

Hi,

okay … I’ve also found the dictionary being requested for the list (it’s in “roofitcore/inc/LinkDef3.h”), but there is indeed no entry for the iterator. Meaning, this list can’t be iterator (also not from CINT).

Easiest workaround is to add a dict entry. Something like:[code]$ cat roofit_iterators.h
#include
#include “RooAbsData.h”

#ifdef CINT
#pragma link C++ class std::list<RooAbsData*>::iterator;
#endif[/code]
And then add to the .py file:from ROOT import gROOT gROOT.LoadMacro( "roofit_iterators.h+" )
HTH,
Wim

Thanks, Wim!

That indeed helped. Now I have another mystery but it probably belongs to a separate thread… I’ve just posted it here:

Hi,

thanks for pragma link fix, is there anyway to make the list class also indexable? e.g.

datasets = workspace.allData()
dataset0 = datasets[0]

gives me the error,

[quote]TypeError: ‘list<RooAbsData*,allocator<RooAbsData*> >’ object does not support indexing
[/quote]

Hi,

it’s possible, but can’t be done efficiently: unlike Python lists, C++ lists do not support random access (that’s what C++ vectors are for). To find the Nth element in a C++ list, you’d need to walk it until you hit element N. If you are going to do many random accesses, it’s best to copy into a python list (or tuple) first:pydatasets = list(datasets)
Cheers,
Wim

thanks Wim