Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Inconsistency between axes.set_xlim and axes.xaxis.set_view_interval #6863

Closed
@syrte

Description

@syrte

Problem

For an Axes object axes, axes.viewLim.intervalx defines the view interval for x-axis.
In current version, there are two functions/methods change axes.viewLim.intervalx directly.

One is axes.set_xlim (code), another is axes.xaxis.set_view_interval (code).

Generally we use axes.set_xlim or its wrapper plt.xlim, note the callback mechanism and sharex mechanism are reduced in this method (when emit is True).
However, when we call plt.xticks, axes.set_xticks or axes.xaxis.set_ticks, it uses axes.xaxis.set_view_interval, thus changes axes.viewLim.intervalx directly without callback and sharex. This may cause some unexpected behaviers.

Same situation for y-axis.

Example

from matplotlib import pyplot as plt
a = plt.gca()
a.plot([0,1], [0,1])
b = plt.twinx()
b.plot([0,1], [0,1])
b.set_xticks([1,2,3])
plt.draw()

Example
The two lines in figure should be the same in this figure, as they share x-axis and have the same y-axis limits. It goes wrong becasue that b.set_xticks changes the range of itself but didn't inform its twin axes a.

Solution

Make a new method for axes named _set_view_intervalx or something similar, it aims at change viewLim.intervalx and reduce the callback and sharex.
And let axes.set_xlim and axes.xaxis.set_view_interval call this function to change interval.
We shall make sure this method is the only one who can modify viewLim.intervalx directly.

class _AxesBase(martist.Artist):
    ...
    def _set_view_intervalx(self, left, right, emit=False):
        """
        Set the data limits for the xaxis
        *emit*: [ *True* | *False* ]
            Notify observers of limit change
        """
        self.viewLim.intervalx = (left, right)
        if emit:
            self.callbacks.process('xlim_changed', self)
            # Call all of the other x-axes that are shared with this one
            for other in self._shared_x_axes.get_siblings(self):
                if other is not self:
                    other.set_xlim(self.viewLim.intervalx,
                                   emit=False, auto=auto)
                    if (other.figure != self.figure and
                            other.figure.canvas is not None):
                        other.figure.canvas.draw_idle()

Sorry if I missed anything obvious or misunderstand the mechanism behind.
I'm new here, any comments are welcome. Feel free to add proper flag and modify the post title, thanks.


Related post
#5560
#6860

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions