8000 [Bug]: parasite_axes does not properly handle units · Issue #22714 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content
[Bug]: parasite_axes does not properly handle units #22714
Closed
@quentinmit

Description

@quentinmit

Bug summary

When plotting on a parasite axis using axes_grid1.parasite_axes, units are not automatically applied to the parasite axis.

Code for reproduction

#!/usr/bin/env python3

from mpl_toolkits.axes_grid1 import host_subplot
from mpl_toolkits import axisartist
import matplotlib.pyplot as plt
import matplotlib.units as units
import matplotlib.ticker as ticker

class Unit:
    def __init__(self, val):
        self._val = val

class Volt(Unit):
    fmt = "%0.1f V"
class Amp(Unit):
    fmt = "%0.1f A"

class UnitConverter(units.ConversionInterface):
    @staticmethod
    def convert(value, unit, axis):
        return [x._val for x in value]

    @staticmethod
    def axisinfo(unit, axis):
        return units.AxisInfo(majfmt=ticker.FormatStrFormatter(unit.fmt))

    @staticmethod
    def default_units(x, axis):
        return x[0].__class__

units.registry[Volt] = UnitConverter()
units.registry[Amp] = UnitConverter()

host = host_subplot(111, axes_class=axisartist.Axes)

p1, = host.plot([0, 1, 2], [Volt(x) for x in (0, 1, 2)])

par1 = host.twinx()
par1.axis["right"].major_ticklabels.set_visible(True)
p2, = par1.plot([0, 1, 2], [Amp(x) for x in (0, 3, 2)])

plt.show()

Actual outcome

image

Expected outcome

image

Additional information

As far as I can tell, this is because ParasiteAxesBase.cla contains this line:

self._get_lines = self._parent_axes._get_lines

Since _get_lines contains a reference to its axes instance, this causes ax2.plot to attempt to call update_units on the host axes instead of the parasite axes. Removing this line appears to fix unit behavior for me, but I don't know why the line was there in the first place because it has been there since the very first commit of parasite_axes. Perhaps the goal was to make the axes share a color cycler?

I was able to preserve that behavior while fixing unit support by changing the line to

self._get_lines = functools.partial(self._parent_axes._get_lines, axes=self)

and then changing _process_plot_var_args.__call__, _process_plot_var_args._makefill, and _process_plot_var_args._plot_args to use kwargs.get("axes", self.axes) instead of self.axes.

Operating system

OS X

Matplotlib Version

3.5.1

Matplotlib Backend

MacOSX

Python version

Python 3.10.1

Jupyter version

n/a

Installation

Linux package manager

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0