1

I'm making a reference to the question on Plotting labeled intervals in matplotlib/gnuplot, the problem with the solution exposed there, is that doesn't work with only one line of data in the files. This is the code I'm trying:

#!/usr/bin/env python
#

import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter, MinuteLocator, SecondLocator
import numpy as np
from StringIO import StringIO
import datetime as dt

a=StringIO("""MMEX 2016-01-29T12:38:22 2016-01-29T12:39:03 SUCCESS 
""")

#Converts str into a datetime object.
conv = lambda s: dt.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S')

#Use numpy to read the data in. 
data = np.genfromtxt(a, converters={1: conv, 2: conv},
                 names=['caption', 'start', 'stop', 'state'], dtype=None)
cap, start, stop = data['caption'], data['start'], data['stop']

#Check the status, because we paint all lines with the same color 
#together
is_ok = (data['state'] == 'SUCCESS')
not_ok = np.logical_not(is_ok)

#Get unique captions and there indices and the inverse mapping    
captions, unique_idx, caption_inv = np.unique(cap, 1, 1)

#Build y values from the number of unique captions.
y = (caption_inv + 1) / float(len(captions) + 1)

#Plot function
def timelines(y, xstart, xstop, color='b'):
    """Plot timelines at y from xstart to xstop with given color."""   
    plt.hlines(y, xstart, xstop, color, lw=4)
    plt.vlines(xstart, y+0.005, y-0.005, color, lw=2)
    plt.vlines(xstop, y+0.005, y-0.005, color, lw=2)

#Plot ok tl black    
timelines(y[is_ok], start[is_ok], stop[is_ok], 'k')
#Plot fail tl red
timelines(y[not_ok], start[not_ok], stop[not_ok], 'r')

#Setup the plot
ax = plt.gca()
ax.xaxis_date()
myFmt = DateFormatter('%Y-%m-%dT%H:%M:%S')
ax.xaxis.set_major_formatter(myFmt)
ax.xaxis.set_major_locator(SecondLocator(interval=3600)) # used to be         SecondLocator(0, interval=20)

#To adjust the xlimits a timedelta is needed.
delta = (stop.max() - start.min())/10

plt.yticks(y[unique_idx], captions)
plt.ylim(0,1)
plt.xlim(start.min()-delta, stop.max()+delta)
plt.xlabel('Time')
plt.xticks(rotation=70)
plt.show(block=True)

When I try this code, I get the following error:

Traceback (most recent call last):
  File "./testPlot.py", line 49, in <module>
    timelines(y[is_ok], start[is_ok], stop[is_ok], 'k')
ValueError: boolean index array should have 1 dimension

Also, when I try to add a dummy line on the data, let's said "MMEX 2016-01-01T00:00:00 2016-01-01T00:00:00 SUCCESS", the plot works but doesn't look good.

Any suggestions? I tried to put this question on the same post when I found the solution, but I don't have enough reputation...

Thanks in advance

Community
  • 1
  • 1
  • Can you give the outputs of `shape(y)`, `shape(start)`, `shape(stop)` and `shape(is_ok)`? I suppose your data arrays don't have the same dimension. – wsj May 12 '16 at 08:46

1 Answers1

0

The issue is that when you only read 1 item with np.genfromtxt, it is producing scalars (0-dimensions). We need them to be at least 1D.

You can add these lines just above where you define your timelines function, and then everything works ok.

This makes use of the numpy function np.atleast_1d(), to turn the scalars into 1D numpy arrays.

#Check the dimensions are at least 1D (for 1-item data input)
if start.ndim < 1:
    start = np.atleast_1d(start)
if stop.ndim < 1::
    stop = np.atleast_1d(stop)    
if is_ok.ndim < 1:
    is_ok = np.atleast_1d(is_ok)    
if not_ok.ndim < 1:
    not_ok = np.atleast_1d(is_ok)  

The output:

enter image description here

tmdavison
  • 64,360
  • 12
  • 187
  • 165