-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RF] Translate RooStats tutorial rs101_limitexample.C to Python #10853
[RF] Translate RooStats tutorial rs101_limitexample.C to Python #10853
Conversation
Can one of the admins verify this patch? |
## \macro_output | ||
## \macro_code | ||
## | ||
## \author Kyle Cranmer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
## \author Kyle Cranmer | |
## \date June 2022 | |
## \authors Artem Busorgin, Kyle Cranmer (C++ version) |
Please add also the date, and you can also add your name here to get some credits :)
t.Stop() | ||
t.Print() | ||
|
||
dataCanvas.SaveAs("rs101_limitexample.png") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dataCanvas.SaveAs("rs101_limitexample.png") | |
dataCanvas.SaveAs("rs101_limitexample.png") | |
# TODO: The MCMCCalculator has to be destructed first. Otherwise, we can get | |
# segmentation faults depending on the destruction order, which is random in | |
# Python. Probably the issue is that some object has a non-owning pointer to | |
# another object, which it uses in its destructor. This should be fixed either | |
# in the design of RooStats in C++, or with phythonizations. | |
del mc |
Can you please add this at the bottom please? By deleting mc
first, we are avoiding some destruction order fiasco that occasionally causes crashes in this tutorial.
# also plot the points in the markov chain | ||
chainData = mcInt.GetChainAsDataSet() | ||
|
||
assert chainData |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert chainData |
No asserts
in tutorials please (I know they were in the C++ version too, but asserts are only to check if things went well in debug builds or unit tests. For user code like these tutorials, it should never be necessary to use them)
assert chainData | ||
print("plotting the chain data - nentries = ", chainData.numEntries()) | ||
chain = ROOT.RooStats.GetAsTTree("chainTreeData", "chainTreeData", chainData) | ||
assert chain |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert chain |
No asserts in tutorials
|
||
# the points used in the profile construction | ||
parScanData = fc.GetPointsToScan() | ||
assert parScanData |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert parScanData |
No asserts in tutorials
y = evt.getRealValue("ratioSigEff") | ||
z = evt.getRealValue("s") | ||
gr.SetPoint(ievt, x, y, z) | ||
# print("{} {} {} {}".format(ievt, x, y, z)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# print("{} {} {} {}".format(ievt, x, y, z)) |
It's not good to have commented out code in tutorials.
data = ROOT.RooDataSet("exampleData", "exampleData", ROOT.RooArgSet(obs)) | ||
data.add(obs) | ||
|
||
all = ROOT.RooArgSet(s, ratioBkgEff, ratioSigEff) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all = ROOT.RooArgSet(s, ratioBkgEff, ratioSigEff) |
all
is never used. You should delete this line
modelWithConstraints = wspace.pdf("modelWithConstraints") # get the model | ||
obs = wspace.var("obs") # get the observable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modelWithConstraints = wspace.pdf("modelWithConstraints") # get the model | |
obs = wspace.var("obs") # get the observable | |
modelWithConstraints = wspace["modelWithConstraints"] # get the model | |
obs = wspace["obs"] # get the observable |
In PyRoot, you can universally get anything from a RooWorkspace with the []
-operator. You should use this everytime you see var()
, pdf()
, or function()
in C++ (there are also more occurences of var()
to replace in the lines below).
|
||
ratioSigEff = wspace.var("ratioSigEff") # get uncertain parameter to constrain | ||
ratioBkgEff = wspace.var("ratioBkgEff") # get uncertain parameter to constrain | ||
constrainedParams = ROOT.RooArgSet(ratioSigEff, ratioBkgEff) # need to constrain these in the fit (should change default behavior) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
constrainedParams = ROOT.RooArgSet(ratioSigEff, ratioBkgEff) # need to constrain these in the fit (should change default behavior) | |
constrainedParams = {ratioSigEff, ratioBkgEff} # need to constrain these in the fit (should change default behavior) |
In PyROOT, you can directly use Python sets instead of RooArgSets
|
||
# Create an example dataset with 160 observed events | ||
obs.setVal(160.) | ||
data = ROOT.RooDataSet("exampleData", "exampleData", ROOT.RooArgSet(obs)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
data = ROOT.RooDataSet("exampleData", "exampleData", ROOT.RooArgSet(obs)) | |
data = ROOT.RooDataSet("exampleData", "exampleData", {obs}) |
all = ROOT.RooArgSet(s, ratioBkgEff, ratioSigEff) | ||
|
||
# not necessary | ||
modelWithConstraints.fitTo(data, ROOT.RooFit.Constrain(ROOT.RooArgSet(ratioSigEff, ratioBkgEff))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modelWithConstraints.fitTo(data, ROOT.RooFit.Constrain(ROOT.RooArgSet(ratioSigEff, ratioBkgEff))) | |
modelWithConstraints.fitTo(data, Constrain=constrainedParams) |
There was already a set defined for them before. You should reuse that here.
modelConfig.SetParametersOfInterest(paramOfInterest) | ||
modelConfig.SetNuisanceParameters(constrainedParams) | ||
modelConfig.SetObservables(obs) | ||
modelConfig.SetGlobalObservables(ROOT.RooArgSet(gSigEff, gSigBkg)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modelConfig.SetGlobalObservables(ROOT.RooArgSet(gSigEff, gSigBkg)) | |
modelConfig.SetGlobalObservables({gSigEff, gSigBkg}) |
|
||
modelConfig = ROOT.RooStats.ModelConfig(wspace) | ||
modelConfig.SetPdf(modelWithConstraints) | ||
modelConfig.SetParametersOfInterest(paramOfInterest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modelConfig.SetParametersOfInterest(paramOfInterest) | |
modelConfig.SetParametersOfInterest({s}) |
The paramOfInterest
variable above is used nowhere else. You should better delete it, and directly use {s}
here to be more explicit.
wspace.writeToFile("rs101_ws.root") | ||
|
||
# First, let's use a Calculator based on the Profile Likelihood Ratio | ||
# plc = ROOT.RooStats.ProfileLikelihoodCalculator(data, modelWithConstraints, paramOfInterest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# plc = ROOT.RooStats.ProfileLikelihoodCalculator(data, modelWithConstraints, paramOfInterest) |
You should remove this commented out code, as there is not good reason to have it here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @busorgin thank you so much for this contribution, which is really appreciated 👍 I which context are you doing this? Are you a RooFit user who wants to contribute, or you were just browsing GitHub for issues you could address?
Please address the requests I have (mostly about Pythonic code, and one fix for the destruction order fiasco).
Also, after applying all these suggestions, could you please format the new tutorial with black?
black --line-length=120 rs101_limitexample.py
Hi @guitargeek, thanks for the review. I addressed the suggestions and formatted the code. I was looking for an open source project to contribute to that would be interesting to me, settled on root |
@phsft-bot build |
Starting build on |
Alright, thank you very much! That's very nice you chose ROOT to contribute to! If you need any guidance on what you could help with, just ask me. Sometimes it's not easy to find the issues that are actually easy to work on, as the code is quite complex. Are you looking only Python-related issues, or would you also be interested in doing some C++ contributions to beef up your C++ skills and experience? As for this PR, I'll merge it if the CI bot tests pass. |
Thanks, I'll keep that in mind. I was looking for both C++ and Python. I found #9859, seemed like a good starter item on the C++ side. Open to suggestions if there are other good issues to look into. |
Hi @busorgin, okay sounds great! The issue you linked is indeed a very good one to get started with RooFit C++ development. If you have any questions about it, we can follow up in the issue thread there. Of course, it would also be of great help if you continue doing these RooStats tutorial translations! People use more Python than C++ now, and a better coverage of the Python tutorials is something requested by many users, in particular for RooStats. So among all the "easier" RooFit issues, the RooStats tutorial translations have the highest priority. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you for this contribution!
- new tutorial translation runs on my local machine and on the CI
- the output of the tutorial is the same as for the C++ version
This Pull request:
Changes or fixes:
Add rs101_limitexample.py - Converted from rs101_limitexample.C
Checklist:
This PR fixes # Part of 8758