2

I have a lot of scatter functions to plot using matplotlib, either on one y axis or two y axis. To ease this, I create my own scatter function: draw_scatter. I indicate in argument on which y axis I want the data to be plotted.

I also indicate fig_param which specifies fig, ax1, ax2 and the function returns a tuple (fig, ax1, ax2) to use the same elements for the next set of data.

I don't like having in argument ax1, ax2 but I don't find how to avoid it. Is there any built function giving ax1 and ax2 if available ? I could call it in my function

I will have then a function to specify the x_label, legend ... of the fig.

Thank you

import numpy as np
import matplotlib.pyplot as plt

def draw_scatter(fig_param, ax_selec, X, Y, **kwargs):
    """Draw a figure, scatter type, on one or two axis, with selection in argument 
       Input: fig_param(fig,ax1,ax2), ax2 is None if only one axis wanted, 
              simple array X, simple array Y, parameters dict 
       Output: (fig,ax1,ax2), in order to be used again for next elements to be drawn on the same figure""" 

    fig, ax1, ax2 = fig_param

    if kwargs.get('marker_color'):  
        marker_color = kwargs['marker_color']
    else:
        marker_color='k'        
    if kwargs.get('marker_size'): 
        marker_size = kwargs['marker_size']
    else:
        marker_size = 4    

    if ax_selec == 1:
        ax1.scatter(X, Y, color=marker_color, s=marker_size)     
    else:
       ax2.scatter(X, Y, color=marker_color, s=marker_size)       
    return (fig, ax1, ax2)  

x = np.arange(0, 10.0, 1)
y1 = 2*x
y2 = np.sin(x)

fig, ax1 = plt.subplots()
ax2 = ax1.twinx()  # -Set to None if only one y axis is needed 

param = {'marker_color':'blue',
         'marker_size' : 20} 
result_fig = draw_scatter((fig,ax1,ax2), 1, x, y1,**param)

param = {'marker_color':'red'} 
result_fig = draw_scatter(result_fig, 2, x, y2, **param)
Kerdiorp
  • 43
  • 4

2 Answers2

0

Well, unless you declare some ax1 and ax2 and fig as some local variables inside the function scope, the changes and updates will be applied to the global variables.

That being said, in your present example, you don't need to pass the ax1, ax2, fig to your function. Read this to get more insights into the global variables.

def draw_scatter(ax_selec, X, Y, **kwargs):
    if kwargs.get('marker_color'):  # Il faudrait pouvoir supprimer ou activé tickle sur le x. prevoir un else 
        marker_color = kwargs['marker_color']
    else:
        marker_color='k'        
    if kwargs.get('marker_size'):  # Il faudrait pouvoir supprimer ou activé tickle sur le x. prevoir un else 
        marker_size = kwargs['marker_size']
    else:
        marker_size = 4    

    if ax_selec == 1:
        ax1.scatter(X, Y, color=marker_color, s=marker_size)     
    else:
        ax2.scatter(X, Y, color=marker_color, s=marker_size)       
    return (fig, ax1, ax2)  

x = np.arange(0, 10.0, 1)
y1 = 2*x
y2 = np.sin(x)

fig, ax1 = plt.subplots()
ax2 = ax1.twinx()  # -Set to None if only one y axis is needed 

param = {'marker_color':'blue',
         'marker_size' : 20} 
result_fig = draw_scatter( 1, x, y1,**param)

param = {'marker_color':'red'} 
result_fig = draw_scatter(2, x, y2, **param)

enter image description here

Sheldore
  • 37,862
  • 7
  • 57
  • 71
  • ok, Python will look 'above' if the variable ax1 or ax2 is not found in the local variables of the considered function. In case I deal with several figures at the same time, will I not have a problem ? There will be only one ax1 and ax2 – Kerdiorp Jun 12 '19 at 15:19
  • @Kerdiorp : For one figure, as you have used in your example, my answer would work. If you want to know a general answer, with many `fig` objects, you should include such an example **(complete and runnable)** in your question – Sheldore Jun 12 '19 at 15:23
  • @Kerdiorp : You can also write `global fig, ax1, ax2` as the first line inside your function so that inside the function, the global variables are used. However, for the current example, this is not needed – Sheldore Jun 12 '19 at 15:25
0

Alternatively of going global, I think I can use inside my function plt.gcf().axes

import numpy as np
import matplotlib.pyplot as plt

def draw_scatter(fig, ax_selec, X, Y, **kwargs):

    axes_list = plt.gcf().axes

    if kwargs.get('marker_color'): 
        marker_color = kwargs['marker_color']
    else:
        marker_color='k'        
    if kwargs.get('marker_size'):  
        marker_size = kwargs['marker_size']
    else:
        marker_size = 4    

    if ax_selec == 1:
        axes_list[0].scatter(X, Y, color=marker_color, s=marker_size)     
    else:
       axes_list[1].scatter(X, Y, color=marker_color, s=marker_size)       

x = np.arange(0, 10.0, 1)
y1 = 2*x
y2 = np.sin(x)

fig, ax1 = plt.subplots()
ax2 = ax1.twinx()  # -Set to None if only one y axis is needed 

param = {'marker_color':'blue',
         'marker_size' : 20} 
draw_scatter(fig, 1, x, y1,**param)

param = {'marker_color':'red'} 
draw_scatter(fig, 2, x, y2, **param)
Kerdiorp
  • 43
  • 4