Error with sPlot constructor

Hello,
I am facing a problem when trying to build a sPlot for my fit.
I am trying to create a sPlot with the following constructor:

SPlot (const char *name, const char *title, RooDataSet &data, RooAbsPdf *pdf, const RooArgList &yieldsList, const RooArgSet &projDeps=RooArgSet(), bool includeWeights=kTRUE, bool copyDataSet=kFALSE, const char *newName="")

but I am using a RooDataHist instead of RooDataSet and I can’t compile my program, I guess this is the reason. Does anyone have a solution to this?

Here’s bits of my code:

filename = ROOT.TFile("BDT_Xib0.root")
    tree = filename.Get("mytree")
    hist = ROOT.TH1F("hist","hist title",100,lowRange,highRange)
    data = ROOT.RooDataHist("data","my dataset",x,hist)
    tree.Project("hist","lab0_M")

 sData = ROOT.RooStats.SPlot("sData", "An SPlot", data, model, ROOT.RooArgList(sYield, bYield))

Thanks
Andrea

Hi @sala,
can you provide a self-contained reproducer and the full error message?

@StephanH can probably advise further.

Cheers,
Enrico

Sure. Here’s the full error message:

 Traceback (most recent call last):
  File "mySPLOT.py", line 172, in <module>
    rs301_splot()
  File "mySPLOT.py", line 75, in rs301_splot
    sData = ROOT.RooStats.SPlot("sData", "An SPlot", data, model, ROOT.RooArgList(sYield, bYield))
TypeError: none of the 5 overloaded methods succeeded. Full details:
  SPlot::SPlot(const char* name, const char* title, RooDataSet& data, RooAbsPdf* pdf, const RooArgList& yieldsList, const RooArgSet& projDeps = RooArgSet(), bool useWeights = kTRUE, bool copyDataSet = kFALSE, const char* newName = "", const RooCmdArg& fitToarg5 = RooCmdArg::none(), const RooCmdArg& fitToarg6 = RooCmdArg::none(), const RooCmdArg& fitToarg7 = RooCmdArg::none(), const RooCmdArg& fitToarg8 = RooCmdArg::none()) =>
    TypeError: could not convert argument 3
  SPlot::SPlot(const char* name, const char* title, const RooDataSet& data) =>
    TypeError: takes at most 3 arguments (5 given)
  SPlot::SPlot(const RooStats::SPlot& other) =>
    TypeError: takes at most 1 arguments (5 given)
  SPlot::SPlot() =>
    TypeError: takes at most 0 arguments (5 given)
  SPlot::SPlot(const char* name, const char* title) =>
    TypeError: takes at most 2 arguments (5 given)

I am currently having some troubles with providing a self-contained reproducer because I am using a 2GB data file, but I’m working on that.

Thanks Enrico and Stephan!
Andrea

Try with this one:
mySPLOT.py (3.1 KB)

I’ve replaced my data with random gaussian.

I kinda solved it by switching back to C++ and using unbinned data.
Python3 and ROOT do not interact very well…

Hi Andrea,

SPlots can only work with unbinned data, because they have to reweight each entry in the dataset. It is therefore correct that the constructor only takes a RooDataSet, and no RooDataHist.
This should not have anything to do with python. If you had unbinned data on the python side, I would expect that you could call the constructor.
(And if you cannot, let us know please :wink: )

1 Like

Hi Stephan,
thank you for your answer.
Yes, you are right, this has actually nothing to do with python :rofl: The thing is, with python3 I could not build a RooDataSet from TTree using the constructor… I don’t know why but it kept failing
Anyway, I was just complaining because I am experiencing a lot of problems with PyRoot. Sorry if I bothered you!

Old or new pyroot? In 6.22, pyroot got a big update. A lot of things got a lot better, and for the rest we have a pyroot expert. :smiley:

Yes. I am using 6.22.
For example

x = RooRealVar(...)
data = RooDataSet("data","data",tree,RooArgSet(x))

does not work

Oh yes. It’s a lifetime problem that’s notoriously difficult to solve between those two languages, but there’s an easy workaround:

x = RooRealVar(...)
xSet = ROOT.RooArgSet(x)
data = RooDataSet("data","data",tree,xSet)

What happens:
Python creates a temporary RooArgSet, and calls the function. RooDataSet uses the (C++) RooArgSet to define which variables should be in use. Python thinks that nobody uses the ArgSet, and deletes it --> the C++ object vanishes --> dangling pointer --> Crash.
Give it a name, and python lets it survive.
We are thinking about how to solve it, but this requires to smartly find out when python should release ownership of an object. Alternatively, we need to teach python’s garbage collector that C++ still needs the thing.
It’s a work in progress …

Details:

Thanks for telling me this!
I will try to go back to my code and fix it.
Cheers,
Andrea

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