0

I am trying to plot some data with corresponding timestamps in python with matplotlib. The 'dates' are actually datetime.time objects (so no corresponding dates and I don't care about the dates) which look like this:

In[6]: dates[1]
Out[6]: datetime.time(12, 3, 1) 

I have created a simple code which shows what I would like to do (and am doing with the actual data but isn't working for some reason):

Working Code

import matplotlib.pyplot as plt
import matplotlib.dates as pltdt
import datetime as dt

dates = [dt.time(12,3,i) for i in range(6)]
time_to_datetime = []
for i in dates:
    time_to_datetime.append(dt.datetime.combine(dt.date.min, i))
dates_as_num = pltdt.date2num(time_to_datetime)
values = range(len(dates))

plt.plot_date(dates_as_num, values)
plt.show()

print ('Done!')

Which produces the following plot:

Example of what I want

However, when I do this EXACT process with my data (of course instead of 6 points I have ~300,000 and there is some extra processing happening) I get the following error:

Traceback (most recent call last):
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\backends\backend_qt5agg.py", line 197, in __draw_idle_agg
    FigureCanvasAgg.draw(self)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\backends\backend_agg.py", line 464, in draw
    self.figure.draw(self.renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\figure.py", line 1143, in draw
    renderer, self, dsu, self.suppressComposite)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\image.py", line 139, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axes\_base.py", line 2409, in draw
    mimage._draw_list_compositing_images(renderer, self, dsu)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\image.py", line 139, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 1136, in draw
    ticks_to_draw = self._update_ticks(renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 969, in _update_ticks
    tick_tups = [t for t in self.iter_ticks()]
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 969, in <listcomp>
    tick_tups = [t for t in self.iter_ticks()]
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 912, in iter_ticks
    majorLocs = self.major.locator()
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 983, in __call__
    self.refresh()
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 1003, in refresh
    dmin, dmax = self.viewlim_to_dt()
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 760, in viewlim_to_dt
    return num2date(vmin, self.tz), num2date(vmax, self.tz)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 401, in num2date
    return _from_ordinalf(x, tz)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 254, in _from_ordinalf
    dt = datetime.datetime.fromordinal(ix).replace(tzinfo=UTC)
ValueError: ordinal must be >= 1
Traceback (most recent call last):
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\backends\backend_qt5agg.py", line 197, in __draw_idle_agg
    FigureCanvasAgg.draw(self)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\backends\backend_agg.py", line 464, in draw
    self.figure.draw(self.renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\figure.py", line 1143, in draw
    renderer, self, dsu, self.suppressComposite)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\image.py", line 139, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axes\_base.py", line 2409, in draw
    mimage._draw_list_compositing_images(renderer, self, dsu)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\image.py", line 139, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 1136, in draw
    ticks_to_draw = self._update_ticks(renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 969, in _update_ticks
    tick_tups = [t for t in self.iter_ticks()]
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 969, in <listcomp>
    tick_tups = [t for t in self.iter_ticks()]
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 912, in iter_ticks
    majorLocs = self.major.locator()
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 983, in __call__
    self.refresh()
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 1003, in refresh
    dmin, dmax = self.viewlim_to_dt()
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 760, in viewlim_to_dt
    return num2date(vmin, self.tz), num2date(vmax, self.tz)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 401, in num2date
    return _from_ordinalf(x, tz)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 254, in _from_ordinalf
    dt = datetime.datetime.fromordinal(ix).replace(tzinfo=UTC)
ValueError: ordinal must be >= 1
%run "c:\users\willev~1\appdata\local\temp\tmpjkubsr.py"

I have tried everything I can to get this thing to work with no success. I tried even converting the times to strings and just manually setting the tick labels for the x-axis but ran into a problem where what showed up on the x-axis wasn't representing the actual dates accurately (where there should have been 200 minutes in minute intervals displayed, there was a total of 3 minutes displayed even though the y values spanned the whole 200 point range). Thanks for any help!

My trimmed code is below (sorry it is messy):

import matplotlib.pyplot as plt
import matplotlib.dates as pltdt
import numpy as np
import datetime as dt
import math

def plot_two_orbit(times, values):
    fig2 = plt.figure(figsize = (14,8))
    ax2=plt.subplot(111)
    ax2.plot_date(times, values, linewidth=4)
    ax2.set_xticklabels([i.strftime('%H:%M') for i in two_orbit_times])
    ax2.yaxis.set_ticks_position("left")
    ax2.xaxis.set_ticks_position("bottom")
    ax2.spines['top'].set_color('None')
    ax2.spines['right'].set_color('None')
    ax2.spines['bottom'].set_color('black')
    ax2.spines['left'].set_color('black')
    ax2.tick_params(axis='x', colors='black', labelsize=20, pad=10)
    ax2.tick_params(axis='y', colors='black', labelsize=20, pad=10)
    ax2.yaxis.label.set_color('black')
    ax2.xaxis.label.set_color('black')
    ax2.set_ylabel(r'Ion Temp (K)', size=23)
    ax2.set_xlabel(r'Local Time', size=23)
    plt.show()
    return None

#model parameters
modalt = np.arange(90, 1005, 5) #90km to 1000km in 5km increiments,
modlat = np.arange(-90, 92, 2) #latitude from 0 to 355 in 5 degree incriments
modlon = np.arange(0,356, 4) #longitude from -87.5 to 87.5 in 5 degree incriments
modtime = np.arange(.25,24.25,.25) # time in 15 minute incriments

#making the modtime array into a python datetime.time object
times = []
for i in modtime:
    strip = [math.modf(i)[1],math.modf(i)[0]*60 ]
    if strip[0]==24:
        times.append(dt.time(0, int(strip[1]),0))
    else:
        times.append(dt.time(int(strip[0]), int(strip[1]),0))

#loading in the Model data
mdatas =np.load('C:/Users/Will Evonosky/Dropbox/SOARS/SOARS 2017/Data/GIP_Feb5_ti.npy')

#Function to find the index of the neasrest array point to a given value
def find_nearest(array,value):
    idx = (np.abs(array-value)).argmin()
    return idx

#load in the ephemeris data retrieved from STK 
ephem = np.genfromtxt('C:/Users/Will Evonosky/Dropbox/SOARS/SOARS 2017/Data/STK Data/Location for count and science/Times_Loc_Fix_7mon_500km.csv', skip_header=1, dtype=None, delimiter=',')

#Pulling out the indivdual parameters from the STK data
sattime = [dt.datetime.strptime(i[1].decode('ascii'), '%H:%M').time() for i in ephem]
satlat = np.round([i[2] for i in ephem], decimals=2)
satlon = np.round([i[3] for i in ephem], decimals=2)
satalt = np.round([i[4] for i in ephem], decimals=2)

#making the modeled satellite longitude match GIP (-180 to 180) to (0 to 360)
satloncor = []
for i in satlon:
    if i<0:
        satloncor.append(round(i+360,2))
    else:
        satloncor.append(round(i,2))

#Converting UT times for satellite data into local solar time

localtimes = []
for (i,j) in zip(sattime, satloncor):
    td = dt.datetime.combine(dt.datetime.min, i) - dt.datetime.min
    seconds = td  // dt.timedelta(seconds=1)
    local = (seconds + (j/(360/86400)))/3600
    if local>24:
        local-=24
    strip = [math.modf(local)[1],math.modf(local)[0]*60 ]
    if strip[0]==24:
        localtimes.append(dt.time(0, int(strip[1]),0))
    else:
        localtimes.append(dt.time(int(strip[0]), int(strip[1]),0))

#Creating empty arrays to hold the resulting values
grid_night_hour = np.zeros((24,len(modlat),len(modlon)))
two_orbit_line = []
two_orbit_times=[]

#Count determines how many orbits to sample. 1 orbit is ~ 90 data points
count = 200
night_hours = [20,21,22,23,0,1,2,3,4,5]
#plucking out the model data which most closely match the lat, lon, time, and alt of STK sat data
for (i,j,k,l,m) in zip(satlat, satloncor, sattime, satalt, localtimes):
    mlat = find_nearest(modlat, i)
    mlon = find_nearest(modlon, j)
    malt = find_nearest(modalt, l)
    mtime = times.index(min(times, key=lambda d: abs(dt.datetime.combine(dt.date.min,d) - dt.datetime.combine(dt.date.min,k))))
    if m.hour in night_hours:
        grid_night_hour[m.hour, mlat, mlon] = mdatas[malt, mlat, mlon, mtime]
    if count > 0:
        two_orbit_line.append(mdatas[malt, mlat, mlon, mtime])
        two_orbit_times.append(pltdt.date2num(dt.datetime.combine(dt.date.min,m)))
        count-=1

#masking zero values so they wont plot
grid_night_hour[grid_night_hour == 0.0] = np.nan

grid_night_hour = grid_night_hour - np.nanmean(grid_night_hour)

#Plotting the data

plot_two_orbit(two_orbit_times, two_orbit_line)

print ('Done!')

1 Answer 1

1

I figured it out. Y.Luo was on the right track even though their formulation was incorrect. I think that the minimum year supported by pythons datetime library is too low for the dates recognized by matploltib and the same goes for the max years. I manually inserted a date (changed code below) and the plot suddenly worked. Now I am running into another issue but that will have to be for another question.

if count > 0:
        two_orbit_line.append(mdatas[malt, mlat, mlon, mtime])
        two_orbit_times.append(pltdt.date2num(dt.datetime.combine(dt.date(2019,1,1),m)))
        count-=1
Sign up to request clarification or add additional context in comments.

1 Comment

Happy to hear you've figured it out. Will delete my answer to avoid confusion.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.