'Matplotlib issue between MacOS and Raspberry Pi

I have a raspberry pi running some hardware, and continuously generating data. Each day, I collect the data in a pandas dataframe, and it shoots off a summary email. That email needs to contain a pretty chart showing the data over time. Testing on my main machine (latest MacOS) works beautifully. The pi, however, outputs blank charts. Axes, labels, colors, and everything but the plots themselves. Just an empty chart. Both machines are running matplotlib 3.5.1. Please help me figure out why the plots are not rendering on the one machine, but just fine on the other.

#!/usr/bin/env python

import dill
import pandas
import datetime
from datetime import timedelta
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import subprocess

class Report():
  def __init__(self, datafile):
    # Saved dataframes
    self.file = datafile

  def runReport(self):
    # Open data
    saveIn = open(self.file, 'rb')
    data = dill.load(saveIn)
    # Close file
    saveIn.close()
    # Alias dataframe
    systemData = data['systemReadings']

    # Declare chart, set output size
    fig = plt.figure(figsize = (14, 8.75))

    ## Plot1
    # Create plot1 plot sharing an X-axis with Plot5
    plot1 = fig.add_subplot()
    # Display y-axis labels alongside Plot5
    plot1.yaxis.tick_left()
    # Display tick labels to left of tick line
    rspine = plot1.spines['left']
    # Display y-axis label to the left of the chart
    plot1.yaxis.set_label_position("left")
    # Y-axis range
    plt.ylim((7.0, 8.5))
    # Divide y-axis into 10 ticks
    plt.locator_params(axis = 'y', nbins = 10)
    # Limit x-axis to 00:00 - 23:59 range
    plot1.set_xlim([datetime.date(2022,3,6), datetime.date(2022,3,7)])
    # Link data and color line
    plot1.plot(systemData['Plot1'], color = 'k', label = 'Plot1')
    # Shares scale and label with Plot5

    ## Plot2
    # Create Plot2 plot on X-axis with plot1
    plot2 = plot1.twinx()
    # Display y-axis labels to the right of scale line
    rspine = plot2.spines['right']
    # Adjust location of axis/labels so they're not on top of the other dataset sharing that side of the chart
    rspine.set_position(('axes', 1.05))
    # Y-axis range
    plt.ylim((-0.05, 1))
    # Divide y-axis into 10 tickmarks
    plt.locator_params(axis = 'y', nbins = 10)
    # Link data and line color
    plot2.plot(systemData['Plot2'], color = 'orange', label = 'Plot2')
    # Label and label color
    plot2.set_ylabel('Plot2', color = 'orange')

    ## Plo3
    # Create Estimated Plot3 plot on same X-axis with plot1
    plot3 = plot1.twinx()
    # Display ticks on left side of chart
    plot3.yaxis.tick_left()
    # Display tick labels to left of tick line
    rspine = plot3.spines['left']
    # Display y-axis label to the left of the chart
    plot3.yaxis.set_label_position("left")
    # Adjust location of axis/labels so they're not on top of the other dataset sharing that side of the chart
    rspine.set_position(('axes', -0.05))
    # Y-axis range
    plt.ylim((-2, 2))
    # Divide y-axis into 20 tick marks
    plt.locator_params(axis = 'y', nbins = 20)
    # Link data and color line
    plot3.plot(systemData['Plot3'], color = 'limegreen', label = 'Plot3')
    # Label and label color
    plot3.set_ylabel('Plot3', color = 'limegreen')

    ## Plot4
    # Create Plot4 sharing an X-axis with plot1 plot
    plot4 = plot1.twinx()
    # Display y-axis labels to the right of scale line
    rspine = plot4.spines['right']
    # Y-axis range
    plt.ylim((-0.05, 0.5))
    # Divide y-axis in to 10 ticks
    plt.locator_params(axis = 'y', nbins = 10)
    # Link data and color line
    plot4.plot(systemData['Plot4'], color = 'r', label = 'Plot4')
    # Label and label color
    plot4.set_ylabel('Plot4', color = 'b')

    ## plot5
    # Create Plot5 sharing an X-axis with plot1 plot
    plot5 = plot1.twinx()
    # Display ticks on left side of chart
    plot5.yaxis.tick_left()
    # Display tick labels to left of tick line
    rspine = plot3.spines['left']
    # Display y-axis label to the left of the chart
    plot5.yaxis.set_label_position("left")
    # Adjust location of axis/labels so they're not on top of the other dataset sharing that side of the chart
    rspine.set_position(('axes', -0.05))
    # Y-axis range
    plt.ylim((7.0, 8.5))
    # Display y-axis grid lines
    plot5.yaxis.grid()
    # Divide y-axis into 10 ticks
    plt.locator_params(axis = 'y', nbins = 10)
    # Link data and color line
    # Raw
    plot5.plot(systemData['Plot5'], color = 'r', label = 'Plot5')
    # Label and label color
    plot5.set_ylabel('Plot5', color = 'r')

    ## Overall chart formatting
    # Format x-axis hour labels
    plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%I:%M %p'))
    # Only tick on each hour
    plt.gca().xaxis.set_major_locator(mdates.HourLocator(interval = 1))
    # Display labels at an angle for space
    fig.autofmt_xdate()
    # Place legend below chart
    fig.legend(loc = 'lower center', ncol = 5)

    # Display final chart
    plt.show()


report = Report()
report.runReport()


Solution 1:[1]

This line:

    # Limit x-axis to 00:00 - 23:59 range
    plot1.set_xlim([datetime.date(2022,3,6), datetime.date(2022,3,7)])

Worked due to prototyping with a sample dataset with data from that date, and then partially failed due to failure to fully integrate. Self-flagellation will be brief.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1