Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

More flexible plotting #80

Open
alexpearce opened this issue Mar 20, 2017 · 0 comments
Open

More flexible plotting #80

alexpearce opened this issue Mar 20, 2017 · 0 comments

Comments

@alexpearce
Copy link
Contributor

Plotting fits is very nice right now, as long as you're happy using something like BinnedLH.draw. If you want to go beyond that, things start to become painful.

This begins when you want want to modify the .draw methods in any way, like changing line colours, as you need to copy-paste to format of the returned tuple:

likelihood = minuit.fcn
(
    (data_edges, data_y),
    (errorp,errorm),
    (total_pdf_x, total_pdf_y),
    parts
) = likelihood.draw(minuit, parts=True, no_plot=True)

Things get considerably worse when you have components PDFs which themselves have components. Consider:

import matplotlib.pyplot as plt
import probfit

bounds = (0, 10)

sig_pdf1 = probfit.rename(probfit.pdf.gaussian, ('x', 'mu', 'sigma1'))
sig_pdf2 = probfit.rename(probfit.pdf.gaussian, ('x', 'mu', 'sigma2'))
sig_pdf = probfit.AddPdfNorm(sig_pdf1, sig_pdf2, facname=['f0'])
sig_pdf = probfit.Extended(probfit.Normalized(sig_pdf, bounds), extname='Nsig')

bkg_pdf = probfit.rename(probfit.pdf.linear, ('x', 'm', 'c'))
bkg_pdf = probfit.Extended(probfit.Normalized(bkg_pdf, bounds), extname='Nbkg')

tot_pdf = probfit.AddPdf(sig_pdf, bkg_pdf)

# In the order of probfit.describe(tot_pdf)
# Would normally get these values from Minuit after the fit
initial_values = (5, 1, 0.3, 0.5, 10, 0.5, 1, 10)
probfit.plotting.draw_pdf(tot_pdf, initial_values, bounds, label='Total PDF')
probfit.plotting.draw_pdf(tot_pdf.parts()[0], initial_values, bounds, label='Signal PDF')
probfit.plotting.draw_pdf(tot_pdf.parts()[1], initial_values, bounds, label='Background PDF')
plt.legend();

Gives you this:

Pretty.

But what if I also want to visualise the components of sig_pdf, i.e. the two Gaussians? I think this is a common requirement. (Bonus: this is without data; things get more complicated then.)

Right now, I don't think there's a way to access either of the two components of sig_pdf from the total PDF object. This is because AddPdf turns its components into MinimalFuncCode object and FakeFunc objects (which admittedly I don't really understand), and these don't expose any sub-PDFs.

>>> type(tot_pdf.func_code)
probfit.funcutil.MinimalFuncCode
>>> tot_pdf.parts()
[<probfit.funcutil.FakeFunc at 0x7f371c159b40>,
 <probfit.funcutil.FakeFunc at 0x7f371c159a68>]
>>> tot_pdf.parts()[0].parts()
...
AttributeError: 'probfit.funcutil.FakeFunc' object has no attribute 'parts'

Similar issues exist with the residual plotting methods, but there I'd argue it's actually harder to customise those.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

1 participant