Eomys/pyleecan

setting ax parameter to plot_multi does not work.

Closed this issue · 4 comments

The docstring of the method plot_multi implies that passing an matplotlib axis instance as ax will put the plot on that specific axis.

Signature:
Xout.plot_multi(
    x_symbol,
    y_symbol,
    c_symbol=None,
    cmap=None,
    plot_type='point',
    idx=None,
    ax=None,
    title=None,
    is_show_fig=True,
    save_path=None,
    win_title=None,
)
Docstring:
Plot data from a DataKeeper for a given parameter from a ParamExplorer

x_symbol: str
    ParamExplorer or DataKeeper symbol
y_symbol: str
    ParamExplorer or DataKeeper symbol
c_symbol: str
    optional symbol to set the plot colors
cmap: colormap
    optional colormap
plot_type: str
    scatter or plot to chose plot type
idx: slice
    To plot only some data
ax: matplotlib.pyplot.Axe
    To put the plot in a specific ax
title: str
    Figure or subfigure title according to ax
is_show_fig : bool
    True to show figure after plot
save_path : str
    full path of the png file where the figure is saved if save_path is not None

Returns
-------
fig or ax

Raises
------

The following code should plot on two subplots ax1 and ax2, it ignores the ax parameter. Reading the code shows there is a call to plot_2D, but without passing ax. Also, It is also not going to return an ax or a fig as

fig, (ax1, ax2) = plt.subplots(1, 2)

fig_or_ax1 = Xout.plot_multi("Phi0", "Tem_av", ax=ax1, is_show_fig=False)
fig_or_ax2 = Xout.plot_multi("Id", "Iq", ax=ax2, is_show_fig=False)
#Has the Xout.plot_multi returned anything?
print(fig_or_ax1 != None)
#Has Xout.plot_multi added any artist to the axis?
print(ax1.has_data() != False)

Hello,
PR #527 should solve that. Thank you for spotting it.
I have removed the return fig, ax docstring as it didn't exist in the code. Do you need this return ? Then we can investigate adding it to most pyleecan plot commands

Best regards,
Pierre

I think to allow full control over the plotting, taking an ax as a parameter, and returning an ax is essential.
I'll check around in matplotlib to see how it is most consistently done.

This article has a good overview of writing modular matplotlib plotting functions, and deals with a few issues I had not thought about.

TLDR: Define your own functions that involve plotting onto a specific axes with the following syntax:

def custom_plot(x, y, ax=None, **plt_kwargs):
    if ax is None:
        ax = plt.gca()
    ax.plot(x, y, **plt_kwargs) ## example plot here
    return(ax)
def multiple_custom_plots(x, y, ax=None, plt_kwargs={}, sct_kwargs={}):
    if ax is None:
        ax = plt.gca()
    ax.plot(x, y, **plt_kwargs) #example plot1
    ax.scatter(x, y, **sct_kwargs) #example plot2
    return(ax)

I think if adopted consistently, this would solve #531 and many other issues as well.

In #536 I have added fig/ax as input/output of most plot methods to be more consistent. I took the opportunity to remove calls to plt.legend, plt.axis and plt.close() to more explicit call the the corresponding axis method.
I may have missed some, you can open another issue if you find other inconsistency.
Thank you for reporting this

Best regards,
Pierre