Skip to content

Use of matplotlib's OOP API #113

Open
@mocquin

Description

@mocquin

Most use of matplotlib througout the package rely on the implicit pyplot API.

I'd advocate for using the more explicit OOP-oriented API since it is considered cleaner, more pythonic, and allows for more control over plots.

The difference between the 2 APIs is described here : https://matplotlib.org/stable/users/explain/figure/api_interfaces.html

Example for distributions

For example, in the base class for distributions, the view method :

def view(self):

uses plt for accessing matplotlib. This code could be replace with, for example :

Before

    def view(self):
        """Visualize the distribution.

        This method plots the distribution points and a unit circle for
            reference.
        """
        plt.plot(self.x, self.y, "k*")
        t = np.linspace(0, 2 * np.pi, 256)
        x, y = np.cos(t), np.sin(t)
        plt.plot(x, y, "r")
        plt.xlabel("Normalized Pupil Coordinate X")
        plt.ylabel("Normalized Pupil Coordinate Y")
        plt.axis("equal")
        plt.show()

After

    def view(self, ax=None):
        """Visualize the distribution.
    
        This method plots the distribution points and a unit circle for
            reference.
        """
        if ax is None:
            fig, ax = plt.subplots()
        
        ax.plot(self.x, self.y, "k*")
        t = np.linspace(0, 2 * np.pi, 256)
        x, y = np.cos(t), np.sin(t)
        ax.plot(x, y, "r")
        ax.set_xlabel("Normalized Pupil Coordinate X")
        ax.set_ylabel("Normalized Pupil Coordinate Y")
        ax.set_aspect("equal")
        return ax

This way :

  • the user can either provide the Axes or let the method just create a new one with signature (self, ax=None):
  • and return the Axes for further customization with return ax
  • and delay the actual displaying by removing plt.show()

Generalization

This approach could (and should?) be applied throughout all plottings with matplotlib in the package:

Note on circles

I believe using

circle = plt.Circle((xc, yc), R, fill=False)
ax.add_patch(circle)

is considered a cleaner approach to plot a circle on an ax (removes the need for sampling `t = np.linspace(0, 2 * np.pi, 256)' )

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions