DEV Community

Cover image for Custom Grid and Polar Projection in Matplotlib
Labby for LabEx

Posted on

Custom Grid and Polar Projection in Matplotlib

Introduction

MindMap

In this lab, we will learn how to use GridHelperCurveLinear to create custom grid and tick lines in Matplotlib. We will also learn how to create a polar projection in a rectangular box.

VM Tips

After the VM startup is done, click the top left corner to switch to the Notebook tab to access Jupyter Notebook for practice.

Sometimes, you may need to wait a few seconds for Jupyter Notebook to finish loading. The validation of operations cannot be automated because of limitations in Jupyter Notebook.

If you face issues during learning, feel free to ask Labby. Provide feedback after the session, and we will promptly resolve the problem for you.

Grid for Custom Transform

First, we will create a custom grid and tick lines using GridHelperCurveLinear. The custom transform will be applied to the grid and tick lines. The following code demonstrates this process:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.projections import PolarAxes
from matplotlib.transforms import Affine2D
from mpl_toolkits.axisartist import Axes, HostAxes, angle_helper
from mpl_toolkits.axisartist.grid_helper_curvelinear import GridHelperCurveLinear

def curvelinear_test1(fig):
    # Define custom transform
    def tr(x, y):
        return x, y - x
    def inv_tr(x, y):
        return x, y + x

    # Create GridHelperCurveLinear object
    grid_helper = GridHelperCurveLinear((tr, inv_tr))

    # Create a subplot with the custom grid and tick lines
    ax1 = fig.add_subplot(1, 2, 1, axes_class=Axes, grid_helper=grid_helper)

    # Plot some points on the subplot
    xx, yy = tr(np.array([3, 6]), np.array([5, 10]))
    ax1.plot(xx, yy)

    # Set the aspect ratio and limits of the subplot
    ax1.set_aspect(1)
    ax1.set_xlim(0, 10)
    ax1.set_ylim(0, 10)

    # Add floating axes and grid lines
    ax1.axis["t"] = ax1.new_floating_axis(0, 3)
    ax1.axis["t2"] = ax1.new_floating_axis(1, 7)
    ax1.grid(True, zorder=0)

fig = plt.figure(figsize=(7, 4))
curvelinear_test1(fig)
plt.show()
Enter fullscreen mode Exit fullscreen mode

Polar Projection in a Rectangular Box

Next, we will create a polar projection in a rectangular box using GridHelperCurveLinear. We will use an Affine2D transform to scale the degree coordinates to radians, and PolarAxes.PolarTransform to create the polar projection. We will also use angle_helper.ExtremeFinderCycle to find the extremes of the polar projection, and angle_helper.LocatorDMS and angle_helper.FormatterDMS to format the tick labels. The following code demonstrates this process:

def curvelinear_test2(fig):
    # Define the custom transform
    tr = Affine2D().scale(np.pi/180, 1) + PolarAxes.PolarTransform()

    # Define the extreme finder, grid locator, and tick formatter
    extreme_finder = angle_helper.ExtremeFinderCycle(
        nx=20, ny=20,
        lon_cycle=360, lat_cycle=None,
        lon_minmax=None, lat_minmax=(0, np.inf),
    )
    grid_locator1 = angle_helper.LocatorDMS(12)
    tick_formatter1 = angle_helper.FormatterDMS()

    # Create GridHelperCurveLinear object
    grid_helper = GridHelperCurveLinear(
        tr, extreme_finder=extreme_finder,
        grid_locator1=grid_locator1, tick_formatter1=tick_formatter1)
    ax1 = fig.add_subplot(
        1, 2, 2, axes_class=HostAxes, grid_helper=grid_helper)

    # Make ticklabels of right and top axis visible
    ax1.axis["right"].major_ticklabels.set_visible(True)
    ax1.axis["top"].major_ticklabels.set_visible(True)

    # Let right axis show ticklabels for 1st coordinate (angle)
    ax1.axis["right"].get_helper().nth_coord_ticks = 0

    # Let bottom axis show ticklabels for 2nd coordinate (radius)
    ax1.axis["bottom"].get_helper().nth_coord_ticks = 1

    # Set the aspect ratio and limits of the subplot
    ax1.set_aspect(1)
    ax1.set_xlim(-5, 12)
    ax1.set_ylim(-5, 10)

    # Add grid lines to the subplot
    ax1.grid(True, zorder=0)

    # Create a parasite axes with the given transform
    ax2 = ax1.get_aux_axes(tr)

    # Anything you draw in ax2 will match the ticks and grids of ax1.
    ax2.plot(np.linspace(0, 30, 51), np.linspace(10, 10, 51), linewidth=2)

    ax2.pcolor(np.linspace(0, 90, 4), np.linspace(0, 10, 4),
               np.arange(9).reshape((3, 3)))
    ax2.contour(np.linspace(0, 90, 4), np.linspace(0, 10, 4),
                np.arange(16).reshape((4, 4)), colors="k")

fig = plt.figure(figsize=(7, 4))
curvelinear_test2(fig)
plt.show()
Enter fullscreen mode Exit fullscreen mode

Final Code

The final code combines the code from Step 1 and Step 2:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.projections import PolarAxes
from matplotlib.transforms import Affine2D
from mpl_toolkits.axisartist import Axes, HostAxes, angle_helper
from mpl_toolkits.axisartist.grid_helper_curvelinear import GridHelperCurveLinear

def curvelinear_test1(fig):
    # Define custom transform
    def tr(x, y):
        return x, y - x
    def inv_tr(x, y):
        return x, y + x

    # Create GridHelperCurveLinear object
    grid_helper = GridHelperCurveLinear((tr, inv_tr))

    # Create a subplot with the custom grid and tick lines
    ax1 = fig.add_subplot(1, 2, 1, axes_class=Axes, grid_helper=grid_helper)

    # Plot some points on the subplot
    xx, yy = tr(np.array([3, 6]), np.array([5, 10]))
    ax1.plot(xx, yy)

    # Set the aspect ratio and limits of the subplot
    ax1.set_aspect(1)
    ax1.set_xlim(0, 10)
    ax1.set_ylim(0, 10)

    # Add floating axes and grid lines
    ax1.axis["t"] = ax1.new_floating_axis(0, 3)
    ax1.axis["t2"] = ax1.new_floating_axis(1, 7)
    ax1.grid(True, zorder=0)

def curvelinear_test2(fig):
    # Define the custom transform
    tr = Affine2D().scale(np.pi/180, 1) + PolarAxes.PolarTransform()

    # Define the extreme finder, grid locator, and tick formatter
    extreme_finder = angle_helper.ExtremeFinderCycle(
        nx=20, ny=20,
        lon_cycle=360, lat_cycle=None,
        lon_minmax=None, lat_minmax=(0, np.inf),
    )
    grid_locator1 = angle_helper.LocatorDMS(12)
    tick_formatter1 = angle_helper.FormatterDMS()

    # Create GridHelperCurveLinear object
    grid_helper = GridHelperCurveLinear(
        tr, extreme_finder=extreme_finder,
        grid_locator1=grid_locator1, tick_formatter1=tick_formatter1)
    ax1 = fig.add_subplot(
        1, 2, 2, axes_class=HostAxes, grid_helper=grid_helper)

    # Make ticklabels of right and top axis visible
    ax1.axis["right"].major_ticklabels.set_visible(True)
    ax1.axis["top"].major_ticklabels.set_visible(True)

    # Let right axis show ticklabels for 1st coordinate (angle)
    ax1.axis["right"].get_helper().nth_coord_ticks = 0

    # Let bottom axis show ticklabels for 2nd coordinate (radius)
    ax1.axis["bottom"].get_helper().nth_coord_ticks = 1

    # Set the aspect ratio and limits of the subplot
    ax1.set_aspect(1)
    ax1.set_xlim(-5, 12)
    ax1.set_ylim(-5, 10)

    # Add grid lines to the subplot
    ax1.grid(True, zorder=0)

    # Create a parasite axes with the given transform
    ax2 = ax1.get_aux_axes(tr)

    # Anything you draw in ax2 will match the ticks and grids of ax1.
    ax2.plot(np.linspace(0, 30, 51), np.linspace(10, 10, 51), linewidth=2)

    ax2.pcolor(np.linspace(0, 90, 4), np.linspace(0, 10, 4),
               np.arange(9).reshape((3, 3)))
    ax2.contour(np.linspace(0, 90, 4), np.linspace(0, 10, 4),
                np.arange(16).reshape((4, 4)), colors="k")

fig = plt.figure(figsize=(7, 4))
curvelinear_test1(fig)
curvelinear_test2(fig)
plt.show()
Enter fullscreen mode Exit fullscreen mode

Summary

In this lab, we learned how to create custom grid and tick lines using GridHelperCurveLinear. We also learned how to create a polar projection in a rectangular box using Affine2D, PolarAxes.PolarTransform, and GridHelperCurveLinear.


🚀 Practice Now: Matplotlib Curvilinear Grid


Want to Learn More?

Top comments (0)