Preventing plot joining when values "wrap" in matplotlib plots

list, matplotlib, plot, python

Solution

Here is a generator function that finds the contiguous regions of 'wrapped' data:

import numpy as np

def unlink_wrap(dat, lims=[-np.pi, np.pi], thresh = 0.95):
    """
    Iterate over contiguous regions of `dat` (i.e. where it does not
    jump from near one limit to the other).

    This function returns an iterator object that yields slice
    objects, which index the contiguous portions of `dat`.

    This function implicitly assumes that all points in `dat` fall
    within `lims`.

    """
    jump = np.nonzero(np.abs(np.diff(dat)) > ((lims[1] - lims[0]) * thresh))[0]
    lasti = 0
    for ind in jump:
        yield slice(lasti, ind + 1)
        lasti = ind + 1
    yield slice(lasti, len(dat))

An example usage would be,

x = np.arange(0, 100, .1)
y = x.copy()

lims = [0, 24]

x = (x % lims[1])

fig, ax = matplotlib.pyplot.subplots()

for slc in unlink_wrap(x, lims):
    ax.plot(x[slc], y[slc], 'b-', linewidth=2)

ax.plot(x, y, 'r-', zorder=-10)
ax.set_xlim(lims)

Which gives the figure below. Note that the blue lines (which utilize `unlink_wrap`) are broken and the standard-plotted red lines are shown for reference.

Problem

I'm plotting right ascension ephemerides for planets, which have the property that they are cyclical: they hit a maximum value, 24, and then start again at 0. When I plot these using matplotlib, the "jump" from 24 to zero is joined so that I get horizontal lines running across my figure: How can I eliminate these lines? Is there an approach in matplotlib, or perhaps a way to split the lists at between the points where the jump occurs. Code to generate above figure: ``` from __future__ import division import ephem import matplotlib import matplotlib.pyplot import math fig, ax = matplotlib.pyplot.subplots() ax.set(xlim=[0, 24]) ax.set(ylim=[min(date_range), max(date_range)]) ax.plot([12*ep.ra/math.pi for ep in [ephem.Jupiter(base_date + d) for d in date_range]], date_range, ls='-', color='g', lw=2) ax.plot([12*ep.ra/math.pi for ep in [ephem.Venus(base_date + d) for d in date_range]], date_range, ls='-', color='r', lw=1) ax.plot([12*ep.ra/math.pi for ep in [ephem.Sun(base_date + d) for d in date_range]], date_range, ls='-', color='y', lw=3) ```

Original source

Related problems