Search code examples
pythonmatplotlibrectangles

Plot a rectangle of time (yAxis) from start to end of an event


First, new to matplotlib and have never tried plotting a rectangle. My yAxis will show time (24 hour period) with the xAxis showing each event. I need to show when in time the event started (HH:MM) and when it concluded (HH:MM). I've seen some horizontal rectangles and a few candlestick charts (not sure if that will work for me). Each xAxis rectangle is not related to the other. I can generate the canvas and create an elapse time by subtracting the end time from begin time to generate the points on the rectangle but I cannot get the object to show on the chart. Ideas? Code below:

from datetime import datetime, timedelta
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import matplotlib.dates as mdates
from matplotlib.dates import HourLocator
from matplotlib.dates import DateFormatter

fig, ax = plt.subplots()


data = ["20180101T09:28:52.442130", "20180101T09:32:04.672891"]

endTime = datetime.strptime(data[1], "%Y%m%dT%H:%M:%S.%f")
beginTime = datetime.strptime(data[0], "%Y%m%dT%H:%M:%S.%f")

timeDiff = endTime - beginTime
elapseTime = timedelta(days=0, seconds=timeDiff.seconds,\
microseconds=timeDiff.microseconds)
print("elapseTime:", elapseTime)
theStartTime = endTime
theEndTime = theStartTime + elapseTime

# convert to matplotlib date representation
eventStart = mdates.date2num(theStartTime)
eventEnd = mdates.date2num(theEndTime)
eventTime = eventEnd - eventStart

# plot it as a Rectangle
nextEvent = Rectangle((1, eventStart), 1, eventTime, color="blue")
print("nextEvent:", nextEvent)

# locator = mdates.AutoDateLocator()
# locator.intervald[“MINUTELY”] = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45,\   
#  50, 55]
# formatter = mdates.AutoDateFormatter[locator]
# formatter.scale[1/(24.*60.)] = “%M:%S”

timeFormat = mdates.DateFormatter("%H:%M")
ax.set_xlim([1, 5])
ax.yaxis_date()
ax.yaxis.set_major_formatter(timeFormat)
ax.set_ylim([datetime.strptime("23:59:59", "%H:%M:%S"),\ 
   datetime.strptime("00:00:00", "%H:%M:%S")])
ax.set_ylabel("Time(HH:MM)")
ax.set_xlabel("Events")
ax.add_patch(nextEvent)

plt.show()

enter image description here

I'm not able to see the data but it appears based upon print of the rectangle object it doesn't fit the canvas.

What I'm trying to achieve is the image below (candlestick presentation) enter image description here


Solution

  • Indeed, your datetime axis is completely off. It ranges from midnight of the first of January 1900 to one minute to midnight of the second of January 1900. Yet your rectangle is somewhen in the year 2018.

    So the solution is simple, include the complete datetime when setting the limits.

    ax.set_ylim([datetime.strptime("20180101 23:59:59", "%Y%m%d %H:%M:%S"), 
                 datetime.strptime("20180101 00:00:00", "%Y%m%d %H:%M:%S")])
    

    Alternatively define your data to have taken place in 1900.