Matt
Matt

Reputation: 392

Matplotlib: datetime-based linecollection in interactive jupyter plot

I am trying to plot a collection of tens of thousands of line segments in a matplotlib interactive plot in a Jupyter notebook. The problem I have is that

Example:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import collections  as mc
import matplotlib.dates as mdates

%matplotlib nbagg # interactive plot in jupyter notebook

x = np.array([['2018-03-19T07:01:00.000073810', '2018-03-19T07:01:00.632164618'],
       ['2018-03-19T07:01:00.000073811', '2018-03-19T07:01:00.742295898'],
       ['2018-03-19T07:01:00.218747698', '2018-03-19T07:01:00.260067814'],
      ['2018-03-19T07:01:01.218747698', '2018-03-19T07:01:02.260067814'],
      ['2018-03-19T07:01:02.218747698', '2018-03-19T07:01:02.260067814'],
      ['2018-03-19T07:01:02.218747698', '2018-03-19T07:01:02.260067814']],
      dtype='datetime64[ns]')
y = np.array([[12355.5, 12355.5],
       [12363. , 12363. ],
       [12362.5, 12362.5],
       [12355.5, 12355.5],
       [12363. , 12363. ],
       [12362.5, 12362.5]])

fig, ax = plt.subplots()
segs = np.zeros((x.shape[0], x.shape[1], 2))
segs[:, :, 1] = y
segs[:, :, 0] = mdates.date2num(x)
lc = mc.LineCollection(segs)
ax.set_xlim(segs[:,:,0].min(), segs[:,:,0].max())
ax.set_ylim(segs[:,:,1].min()-1, segs[:,:,1].max()+1)
ax.add_collection(lc)

Now, zooming works fine -- the x-axis scale adjusts with the zoom -- but the x-axis values don't tell me anything useful, i.e. the precise time I'm currently looking at. To remedy this I tried to e.g. do:

ax.xaxis.set_major_locator(mdates.SecondLocator())
#ax.xaxis.set_minor_locator(mdates.MicrosecondLocator()) # this causes the plot not to display
Fmt = mdates.DateFormatter("%S")
ax.xaxis.set_major_formatter(Fmt)

Now clearly zooming doesn't work fine since matplotlib doesn't know how format the finer ticks. So if I zoom sufficiently -- which I need to do -- I basically have no ticks on the x-axis.

Is there a way to address this? One way I could think of is to be able to setup a callback that gets called when the plot zooms, and adjust the format of the x-axis. But as far as I could find, this is not possible.

Upvotes: 0

Views: 751

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339775

It appears that the main problem is currently to get just any useful ticks and labels on your plot. The default way to do this would be

loc = mdates.AutoDateLocator()
fmt = mdates.AutoDateFormatter(loc)
ax.xaxis.set_major_locator(loc)
ax.xaxis.set_major_formatter(fmt)

This would automatically choose useful tick locations for you and is correct down to some microseconds; below that, ticking may become inaccurate due to floating point restrictions.

Meaning, if you need customized or more accurate tick locations you will need to write your own locator and/or change the units of your data (e.g. to "seconds since midnight").

Upvotes: 1

Related Questions