Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add maidr as a matplotlib backend #93

Open
5 tasks done
jooyoungseo opened this issue Aug 23, 2024 · 0 comments
Open
5 tasks done

feat: add maidr as a matplotlib backend #93

jooyoungseo opened this issue Aug 23, 2024 · 0 comments
Assignees

Comments

@jooyoungseo
Copy link
Member

Feature Request

Description

This feature request describes a new rendering behavior of maidr.show() method.

Motivation

Currently, maidr users have to use maidr.show() method to display an accessible plot instead of plt.show().

matplotlib supports multiple backends to render plots, and the selected backend is registered to plot.show().

If we can automatically register maidr as a matplotlib backend, users can use plt.show() to display maidr plots.

Additional Context

Background Knowledge

Try the following code to learn more about this concept:

import matplotlib
import matplotlib.pyplot as plt

# Step 1: Create a test empty plot
plt.plot()
plt.show()

# Step 2: Check the Current Backend:
print(matplotlib.get_backend())

# Step 3: List All Available Backends:
print(matplotlib.rcsetup.all_backends)

# Step 4: Change backend
matplotlib.use("WebAgg")

# Step 5: Check the Current Backend:
print(matplotlib.get_backend())

# Step 6: Print the empty plot again: see whether it is displayed
plt.show()

How to Start?

You need to copy the template backend provided by matplotlib and modify it to suit our custom needs. This involves creating custom classes for rendering figures, managing figure windows, and displaying the figures. You can then register our maidr custom backend with matplotlib and test it by creating and displaying plots.

Read the following instruction by ChatGPT:

When I mentioned "copying the template backend," I referred to using the provided template backend as a starting point or blueprint for developing a custom Matplotlib backend. Here's how you can approach this:

Steps to Create a Custom Backend Using the Template Backend:

  1. Locate the Template Backend Source Code:

    • The template backend is part of Matplotlib's source code. You can find it in the Matplotlib repository on GitHub or in your local installation of Matplotlib.
    • In your local installation, it’s typically located in:
      <path_to_python_site_packages>/matplotlib/backends/backend_template.py
      
    • Alternatively, you can view it online on the Matplotlib GitHub repository.
  2. Copy the Template Backend:

    • Start by copying the backend_template.py file to a new file. You can name this new file based on the backend you are developing, for example, backend_mycustom.py.
    • Place this file in a directory where Python can find it (e.g., in your project directory or as part of a custom package).
  3. Modify the Template:

    • FigureCanvas Class: This is where you define how the figures are rendered. You'll replace the placeholder methods with your custom rendering logic. For example, if you are targeting a custom display, you’ll implement drawing commands that output to that device.
    • FigureManager Class: This class handles the management of the figure window. Depending on your needs, you might need to implement methods that control how the figure is displayed, resized, or interacted with.
    • show Function: Implement the logic to display the figure. This could involve opening a window, exporting a file, or sending the rendered figure to a web service.
  4. Register Your Custom Backend:

    • Matplotlib allows you to use custom backends by referencing them with the matplotlib.use() function. To use your custom backend, you need to specify its module path:
      import matplotlib
      matplotlib.use('module://your_project.backend_mycustom')
    • You would replace 'your_project.backend_mycustom' with the actual module path to your custom backend file.
  5. Test Your Custom Backend:

    • After implementing your backend, test it by creating and displaying plots. Ensure that your custom rendering logic is working as expected.
    • You can use standard Matplotlib plotting commands, and your backend should handle the rendering as per your implementation.

Example Structure:

Here's a simplified structure of what your custom backend might look like:

# backend_mycustom.py

from matplotlib.backend_bases import FigureCanvasBase, FigureManagerBase, RendererBase
from matplotlib.figure import Figure

class MyRenderer(RendererBase):
    def draw_path(self, gc, path, transform, rgbFace=None):
        # Implement custom drawing logic here
        pass

class FigureCanvasMyCustom(FigureCanvasBase):
    def draw(self):
        renderer = MyRenderer()
        self.figure.draw(renderer)

class FigureManagerMyCustom(FigureManagerBase):
    pass

def new_figure_manager(num, *args, **kwargs):
    figure = Figure(*args, **kwargs)
    canvas = FigureCanvasMyCustom(figure)
    manager = FigureManagerMyCustom(canvas, num)
    return manager

def show():
    # Implement custom show logic here
    pass

Summary:

  • Copying the Template Backend: Involves duplicating the backend_template.py file and modifying it to suit your custom needs.
  • Custom Implementation: Replace the placeholders in the template with your custom logic to create a new backend that suits your specific use case.
  • Testing and Usage: Register and test your custom backend by using it in Matplotlib to see how it performs with your custom rendering logic.

This approach allows you to extend Matplotlib to handle specialized rendering tasks that are not supported by the built-in backends.

Checklist

  • I have searched for similar feature requests and confirmed that this is a new request.
  • I have provided a clear and concise description of the feature.
  • I have explained the motivation behind this feature request.
  • I have outlined a proposed solution or ideas for implementing this feature.
  • I have provided any additional context or screenshots if applicable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants