anesthetic
anesthetic copied to clipboard
Setting each diagonal block with different plotting types
Currently for all the diagonal blocks of a triangle plot, we could set types={'diagonal': 'hist'} or {'diagonal': 'kde'} . But sometimes one may want to have different type settings for each diagonal blocks. Could we add a feature that enable users to set the type of each diagonal block separately?
I think this should be achievable. The main thing to discuss is what the interface should be (@lukashergt may want to weigh in here).
Given that types
is already provided as a dictionary, we could simply allow extra keys in this dictionary that would override the 'diagonal' 'upper' and 'lower' choices, for example
types={'diagonal':'hist',
'lower':'kde',
('x0','x1'):'fastkde',
'x0':'kde'}
would set the x0
on the diagonal to be kde, and the rest of the diagonals to be hist
, whilst the lower triangle would be filled with kde
s, except the ('x0','x1')
block, which would be a fastkde
That sort of addition to the dictionary would be possible, I guess.
Another option that possibly already works (haven't tried it though) could be to set up the axes
with make_2d_axes
(say e.g. with lower and diagonal set to true), then call plot_2d
first on all axes
with types={'lower': 'kde'}
(this will leave the diagonal axes empty for now) and then call plot_2d
with types={'diagonal': 'hist'}
on the desired subset of axes (e.g. axes.iloc[:1, :1]
) and analogously for types={'diagonal': 'kde'}
.
Here an example of how to make it work with the current set-up. The colours will need manual tweaking. This might seem complicated, but extending the dictionary as proposed above would mean also the handling of kwargs would have to be extended and I fear that might complicate things a lot more.
What do you think, @williamjameshandley, @xichenamoy?
ns1 = NestedSamples(root="./tests/example_data/pc")
ns2 = NestedSamples(root="./tests/example_data/pc")
fig = plt.figure(figsize=(10, 10))
fig, axes = make_2d_axes(['x0', 'x1', 'x2', 'x3'], fig=fig, upper=False)
ns1.plot_2d(axes=axes, types={'lower': 'kde'}, label='2D kde')
ns1.plot_2d(axes=axes.iloc[1:, 1:], types={'diagonal': 'kde'}, label='kde')
ns1.plot_2d(axes=axes.iloc[:1, :1], types={'diagonal': 'hist'}, label='hist',
diagonal_kwargs={'histtype': 'step', 'ls': '--'})
axes['x0']['x0'].legend()
axes['x0']['x1'].legend()
axes['x1']['x1'].legend(bbox_to_anchor=(1, 1), loc='lower left')
axes['x1']['x2'].legend(bbox_to_anchor=(1, 1), loc='lower left')
That looks good to me, very nice fix! I think this could fully solve the issue in my plot. Thank you!
That is a good solution for @xichenamoy for now, although I think this kind of fine-grained control should be incorporated into a full interface.
This might seem complicated, but extending the dictionary as proposed above would mean also the handling of kwargs would have to be extended and I fear that might complicate things a lot more.
A dict-of-dict approach for the additional kwargs, whilst ghastly would certainly accommodate this extension. diagonal_kwargs
etc were only introduced last release, I would be amenable to changing it if it allows us to implement the extension
Alternatively, if we'd rather stick with a similar interface, it would be entirely possible to add auto-generated kwargs like x0_x1_kwargs
, where x0
and x1
are the user-specified parameter names, since the kwargs.pop
functionality would allow this.
Resolved by lukas