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

calc_mslp()   A

Complexity

Conditions 1

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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