Completed
Pull Request — master (#318)
by
unknown
01:23
created

Meteogram.plot_rh()   A

Complexity

Conditions 1

Size

Total Lines 22

Duplication

Lines 21
Ratio 95.45 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 1
c 4
b 0
f 0
dl 21
loc 22
rs 9.2
1
# Copyright (c) 2008-2016 MetPy Developers.
2
# Distributed under the terms of the BSD 3-Clause License.
3
# SPDX-License-Identifier: BSD-3-Clause
4
"""
5
Meteogram
6
=========
7
8
Plots time series data as a meteogram.
9
"""
10
11
import datetime as dt
12
import matplotlib.pyplot as plt
13
import matplotlib as mpl
14
import numpy as np
15
from metpy.calc import dewpoint_rh
16
from metpy.cbook import get_test_data
17
from metpy.units import units
18
19
20
def calc_mslp(t, p, h):
21
    return p * (1 - (0.0065 * h) / (t + 0.0065 * h + 273.15)) ** (-5.257)
22
23
24
# Make meteogram plot
25
class Meteogram(object):
26
    """ Plot a time series of meteorological data from a particular station as a
27
    meteogram with standard variables to visualize, including thermodynamic,
28
    kinematic, and pressure. The functions below control the plotting of each
29
    variable.
30
    TO DO: Make the subplot creation dynamic so the number of rows is not
31
    static as it is currently. """
32
33
    def __init__(self, fig, dates, probeid, time=dt.datetime.utcnow(), axis=0):
34
        """
35
        Required input:
36
            fig: figure object
37
            dates: array of dates corresponding to the data
38
            probeid: ID of the station
39
        Optional Input:
40
            time: Time the data is to be plotted
41
            axis: number that controls the new axis to be plotted (FOR FUTURE)
42
        """
43
        self.start = dates[0]
44
        self.fig = fig
45
        self.end = dates[-1]
46
        self.axis_num = 0
47
        self.dates = mpl.dates.date2num(dates)
48
        self.time = time.strftime('%Y-%m-%d %H:%M UTC')
49
        self.title = 'Latest Ob Time: {0}\nProbe ID: {1}'.format(self.time, probeid)
50
51
    def plot_winds(self, ws, wd, wsmax, plot_range=[0, 20, 1]):
52
        """
53
        Required input:
54
            ws: Wind speeds (knots)
55
            wd: Wind direction (degrees)
56
            wsmax: Wind gust (knots)
57
        Optional Input:
58
            plot_range: Data range for making figure
59
        """
60
        # PLOT WIND SPEED AND WIND DIRECTION
61
        self.ax1 = fig.add_subplot(4, 1, 1)
62
        ln1 = self.ax1.plot(self.dates, ws, label='Wind Speed')
63
        plt.fill_between(self.dates, ws, 0)
64
        self.ax1.set_xlim(self.start, self.end)
65
        plt.ylabel('Wind Speed (knots)', multialignment='center')
66
        plt.grid(b=True, which='major', axis='y', color='k', linestyle='--', linewidth=0.5)
67
        ln2 = self.ax1.plot(self.dates,
68
                            wsmax,
69
                            '.r',
70
                            label='3-sec Wind Speed Max')
71
        plt.setp(self.ax1.get_xticklabels(), visible=True)
72
        ax7 = self.ax1.twinx()
73
        ln3 = ax7.plot(self.dates,
74
                       wd,
75
                       '.k',
76
                       linewidth=0.5,
77
                       label='Wind Direction')
78
        plt.ylabel('Wind\nDirection\n(degrees)', multialignment='center')
79
        plt.ylim(0, 360)
80
        plt.yticks(np.arange(45, 405, 90), ['NE', 'SE', 'SW', 'NW'])
81
        lns = ln1 + ln2 + ln3
82
        labs = [l.get_label() for l in lns]
83
        plt.gca().xaxis.set_major_formatter(mpl.dates.DateFormatter('%d/%H UTC'))
84
        ax7.legend(lns, labs, loc='upper center',
85
                   bbox_to_anchor=(0.5, 1.2), ncol=3, prop={'size': 12})
86
87
    def plot_thermo(self, t, td, plot_range=[10, 90, 2]):
88
        """
89
        Required input:
90
            T: Temperature (deg F)
91
            TD: Dewpoint (deg F)
92
        Optional Input:
93
            plot_range: Data range for making figure
94
        """
95
        # PLOT TEMPERATURE AND DEWPOINT
96
        self.ax2 = fig.add_subplot(4, 1, 2, sharex=self.ax1)
97
        ln4 = self.ax2.plot(self.dates,
98
                            t,
99
                            'r-',
100
                            label='Temperature')
101
        plt.fill_between(self.dates,
102
                         t,
103
                         td,
104
                         color='r')
105
        plt.setp(self.ax2.get_xticklabels(), visible=True)
106
        plt.ylabel('Temperature\n(F)', multialignment='center')
107
        plt.grid(b=True, which='major', axis='y', color='k', linestyle='--', linewidth=0.5)
108
        self.ax2.set_ylim(plot_range[0], plot_range[1], plot_range[2])
109
        ln5 = self.ax2.plot(self.dates,
110
                            td,
111
                            'g-',
112
                            label='Dewpoint')
113
        plt.fill_between(self.dates,
114
                         td,
115
                         plt.ylim()[0],
116 View Code Duplication
                         color='g')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
117
        ax_twin = self.ax2.twinx()
118
        #    ax_twin.set_ylim(20,90,2)
119
        ax_twin.set_ylim(plot_range[0], plot_range[1], plot_range[2])
120
        lns = ln4 + ln5
121
        labs = [l.get_label() for l in lns]
122
        plt.gca().xaxis.set_major_formatter(mpl.dates.DateFormatter('%d/%H UTC'))
123
124
        self.ax2.legend(lns, labs, loc='upper center',
125
                        bbox_to_anchor=(0.5, 1.2), ncol=2, prop={'size': 12})
126
127
    def plot_rh(self, rh, plot_range=[0, 100, 4]):
128
        """
129
        Required input:
130
            RH: Relative humidity (%)
131
        Optional Input:
132
            plot_range: Data range for making figure
133
        """
134
        # PLOT RELATIVE HUMIDITY
135
        self.ax3 = fig.add_subplot(4, 1, 3, sharex=self.ax1)
136
        self.ax3.plot(self.dates,
137
                      rh,
138
                      'g-',
139 View Code Duplication
                      label='Relative Humidity')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
140
        self.ax3.legend(loc='upper center', bbox_to_anchor=(0.5, 1.22), prop={'size': 12})
141
        plt.setp(self.ax3.get_xticklabels(), visible=True)
142
        plt.grid(b=True, which='major', axis='y', color='k', linestyle='--', linewidth=0.5)
143
        self.ax3.set_ylim(plot_range[0], plot_range[1], plot_range[2])
144
        plt.fill_between(self.dates, rh, plt.ylim()[0], color='g')
145
        plt.ylabel('Relative Humidity\n(%)', multialignment='center')
146
        plt.gca().xaxis.set_major_formatter(mpl.dates.DateFormatter('%d/%H UTC'))
147
        axtwin = self.ax3.twinx()
148
        axtwin.set_ylim(plot_range[0], plot_range[1], plot_range[2])
149
150
    def plot_pressure(self, p, plot_range=[970, 1030, 2]):
151
        """
152
        Required input:
153
            P: Mean Sea Level Pressure (hPa)
154
        Optional Input:
155
            plot_range: Data range for making figure
156
        """
157
        # PLOT PRESSURE
158
        self.ax4 = fig.add_subplot(4, 1, 4, sharex=self.ax1)
159
        self.ax4.plot(self.dates,
160
                      p,
161
                      'm',
162
                      label='Mean Sea Level Pressure')
163
        plt.ylabel('Mean Sea\nLevel Pressure\n(mb)', multialignment='center')
164
        plt.ylim(plot_range[0], plot_range[1], plot_range[2])
165
        axtwin = self.ax4.twinx()
166
        axtwin.set_ylim(plot_range[0], plot_range[1], plot_range[2])
167
        plt.fill_between(self.dates, p, plt.ylim()[0], color='m')
168
        plt.gca().xaxis.set_major_formatter(mpl.dates.DateFormatter('%d/%H UTC'))
169
        self.ax4.legend(loc='upper center', bbox_to_anchor=(0.5, 1.2), prop={'size': 12})
170
        plt.grid(b=True, which='major', axis='y', color='k', linestyle='--', linewidth=0.5)
171
        plt.setp(self.ax4.get_xticklabels(), visible=True)
172
        # OTHER OPTIONAL AXES TO PLOT
173
        # plot_irradiance
174
        # plot_precipitation
175
176
177
# set the starttime and endtime for plotting, 24 hour range
178
endtime = dt.datetime(2016, 3, 31, 22, 0, 0, 0)
179
starttime = endtime - dt.timedelta(hours=24)
180
181
# Height of the station to calculate MSLP
182
hgt_example = 292.
183
184
185
# Parse dates from .csv file, knowing their format as a string and convert to datetime
186
def parse_date(date):
187
    return dt.datetime.strptime(date, '%Y-%m-%d %H:%M:%S')
188
189
190
testdata = np.genfromtxt(get_test_data('timeseries.csv', False), names=True, dtype=None,
191
                         usecols=list(range(1, 8)),
192
                         converters={'DATE': parse_date}, delimiter=',')
193
194
# Temporary variables for ease
195
temp = testdata['T']
196
pres = testdata['P']
197
rh = testdata['RH']
198
ws = testdata['WS']
199
wsmax = testdata['WSMAX']
200
wd = testdata['WD']
201
date = testdata['DATE']
202
203
# ID For Plotting on Meteogram
204
probe_id = '0102A'
205
206
data = dict()
207
data['wind_speed'] = (np.array(ws) * units('m/s')).to(units('knots'))
208
data['wind_speed_max'] = (np.array(wsmax) * units('m/s')).to(units('knots'))
209
data['wind_direction'] = np.array(wd) * units('degrees')
210
data['dewpoint'] = dewpoint_rh((np.array(temp) * units('degC')).to(units('K')),
211
                               np.array(rh) / 100.).to(units('degF'))
212
data['air_temperature'] = (np.array(temp) * units('degC')).to(units('degF'))
213
data['mean_slp'] = calc_mslp(np.array(temp), np.array(pres), hgt_example) * units('hPa')
214
data['relative_humidity'] = np.array(rh)
215
data['times'] = np.array(date)
216
217
fig = plt.figure(figsize=(20, 16))
218
meteogram = Meteogram(fig, data['times'], probe_id)
219
meteogram.plot_winds(data['wind_speed'], data['wind_direction'], data['wind_speed_max'])
220
meteogram.plot_thermo(data['air_temperature'], data['dewpoint'])
221
meteogram.plot_rh(data['relative_humidity'])
222
meteogram.plot_pressure(data['mean_slp'])
223
fig.subplots_adjust(hspace=0.5)
224
plt.show()
225