Build Weather Plot - BitKnitting/should_I_water GitHub Wiki

The Python script is located at this GitHub location.

Create a plot based on the chance of rain

Use matplotlib to make the plot. Use the darknet weather APIs to get the chance of rain.

The Python script I used is avaialable at this GitHub location.


NOTE: Initially, I used Jupyter to try this stuff out.

Then it was on to getting this stuff to run on the Raspberry Pi....

After finally installing matplotlib on the Raspberry Pi, it wanted the GTK namespace. I googled and installed it. Then I got:

Gdk-CRITICAL **: gdk_cursor_new_for_display: assertion 'GDK_IS_DISPLAY (display)' failed

adding:

import matplotlib
matplotlib.use('Agg')

before adding:

import matplotlib.pyplot as plt

fixed this. I got this advice from https://github.com/BVLC/caffe/issues/861: If you want to run totally headless....


Import the external libraries we'll be using.

# I had to use this directive to show the matplot lib plots within Jupyter.
%matplotlib inline 
import certifi
from datetime import datetime,timedelta
import json
import matplotlib.pyplot as plt
import numpy as np
import urllib3

Get today's weather forecast.

# Use the darksky weather service to get today's forecast.  
# The 24 hour clock is used.  We pull out the probability of rain, the intensity of
# rain that will fall if it does rain, the cloud cover, and the temperature into a prediction_list.
def get_weather_forecast():
    _NUMBER_OF_HOURS = 15
    '''
    Use the darksky weather service to get today's forecast.  
    The 24 hour clock is used.  We pull out the probability of rain, the intensity of
    rain that will fall if it does rain, the cloud cover, and the temperature into a prediction_list.
    '''
    http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED',ca_certs=certifi.where())
    url = "https://api.darksky.net/forecast/<your info here>"
    request = http.request('GET',url)
    # Try a five times in case there is a failure to connect
    for i in range(5):
        try:
            weather_prediction = json.loads(request.data.decode('utf8'))
        except HTTPError as e:
            weather_prediction = None
        else:
            prediction_data = weather_prediction['hourly']['data']
            first_hour = prediction_data[0]['time']
            # Just predict for _NUMBER_OF_HOURS
            last_hour = datetime.fromtimestamp(first_hour) + timedelta(hours=_NUMBER_OF_HOURS)
            prediction_list = []
            for hour_data in prediction_data:
                hour_as_datetime = datetime.fromtimestamp(hour_data['time'])
                int_hour = int(hour_as_datetime.strftime('%H'))
                if hour_as_datetime >= last_hour or int_hour == 0:
                    return prediction_list
                prediction_list.append([int_hour,hour_data['precipIntensity'],hour_data['precipProbability'],
                                       hour_data['cloudCover'],hour_data['temperature']])
           
    

Plot

def plot_weather(prediction_list):
    '''
    Make a four plots: hour of the day (x-axis) vs probability of rain, intensity of rain,
    cloud cover, and temperature.  Each reading will be in it's own graph.
    
    store in PNG file.
    '''
    # Set up the numpy array.
    array = np.array(prediction_list)
    # Set up the x-axis. The array's columns = hour, intensity, probability, cloud_cover, temperature.
    # The first hour is at location [0,0] and the last hour with readings is at the end of the first
    # column at [-1,0]
    start_hour = array[0,0].astype(int)
    end_hour = array[-1,0].astype(int)
    x = np.linspace(start_hour,end_hour,num=len(array))
    # set up the x-axis and y-axis data.
    hour = array[:,0].astype('int')
    intensity = array[:,1]
    probability = array[:,2]
    cloud_cover = array[:,3]
    temperature = array[:,4]
    # make room for 4 subplots.  We picked a size that looks good when the plot is saved as a png.
    fig, (ax1,ax2,ax3,ax4) = plt.subplots(nrows=4,figsize=(6,7))
    # The first plot will be the probability of rain.
    ax1.set_ylim([0,1])
    ax1.plot(hour,probability)
    ax1.set_ylabel('probability')
    ax1.set_title('Probability of rain',fontsize = 14)
    # The second plot will be the expected intensity of rain (assuming it rains at all).
    ax2.set_ylim([0,1])
    ax2.set_title('Rain Intensity',fontsize = 14)
    ax2.set_ylabel('intensity')
    ax2.plot(hour,intensity)
    # Plot the cloud cover
    ax3.set_ylim([0,1])
    ax3.set_title('Cloud Cover',fontsize = 14)
    ax3.set_ylabel('cloud cover')
    ax3.plot(hour,cloud_cover)
    # Plot the temperature
    ax4.set_xlabel('Hour (24 hour clock)',fontsize = 16)
    ax4.set_title('Temperature',fontsize = 14)
    ax4.set_ylabel('temperature')
    # Set the y - axis to fit the data within 10's.
    y_min = np.amin(temperature)
    rem = y_min % 10
    y_min -= rem
    y_max = np.amax(temperature)
    rem = y_max % 10
    y_max += (10-rem)
    ax4.set_ylim(y_min,y_max)
    ax4.plot(hour,temperature)
    # plt.tight_layout()
    # Adjust the layout
    fig.subplots_adjust(hspace=1)
    # Save as a png
    fig.savefig('/<your path>/weather.png')
    # Fun to see...just checking...
    plt.show()
    plt.close(fig)
# Make a plot of the weather and save into png.
prediction_list = get_weather_forecast()
plot_weather(prediction_list)

weather plots

Jumping Point

I found these plots and thought they might work for the visual. I ended up using line charts for now. Line charts are a faster way to see if I can get the results into a visual that our family finds useful.

# Evenly spaced ticks on x axis labeled 0 to 24 for 24 hour clock.
x = np.linspace(0,24)
# Chance of precipitation for each hour.
# We have the intensity and the probability
y = np.cumsum(np.random.randn(50))+6

fig, (ax,ax2) = plt.subplots(nrows=2, sharex=True)

extent = [x[0]-(x[1]-x[0])/2., x[-1]+(x[1]-x[0])/2.,0,1]
ax.imshow(y[np.newaxis,:], cmap="plasma", aspect="auto", extent=extent)
ax.set_yticks([])
ax.set_xlim(extent[0], extent[1])

ax2.plot(x,y)

plt.tight_layout()
plt.show()

jumping off point

import numpy as np; np.random.seed(1)
a = np.array([[1,2,3], [4,5,6]])
print(a)
print(np.cumsum(a))
random = np.random.randn(50)
print(random)
y = np.cumsum(random) + 6
print(y)
[[1 2 3]
 [4 5 6]]
[ 1  3  6 10 15 21]
[ 1.62434536 -0.61175641 -0.52817175 -1.07296862  0.86540763 -2.3015387
  1.74481176 -0.7612069   0.3190391  -0.24937038  1.46210794 -2.06014071
 -0.3224172  -0.38405435  1.13376944 -1.09989127 -0.17242821 -0.87785842
  0.04221375  0.58281521 -1.10061918  1.14472371  0.90159072  0.50249434
  0.90085595 -0.68372786 -0.12289023 -0.93576943 -0.26788808  0.53035547
 -0.69166075 -0.39675353 -0.6871727  -0.84520564 -0.67124613 -0.0126646
 -1.11731035  0.2344157   1.65980218  0.74204416 -0.19183555 -0.88762896
 -0.74715829  1.6924546   0.05080775 -0.63699565  0.19091548  2.10025514
  0.12015895  0.61720311]
[ 7.62434536  7.01258895  6.4844172   5.41144858  6.2768562   3.97531751
  5.72012927  4.95892237  5.27796147  5.02859109  6.49069903  4.43055832
  4.10814112  3.72408676  4.8578562   3.75796494  3.58553673  2.70767831
  2.74989206  3.33270727  2.23208809  3.3768118   4.27840252  4.78089686
  5.68175281  4.99802495  4.87513473  3.93936529  3.67147721  4.20183268
  3.51017193  3.1134184   2.4262457   1.58104006  0.90979393  0.89712933
 -0.22018102  0.01423468  1.67403686  2.41608102  2.22424546  1.3366165
  0.58945821  2.28191281  2.33272056  1.69572492  1.8866404   3.98689554
  4.10705449  4.7242576 ]
⚠️ **GitHub.com Fallback** ⚠️