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

Meteogram.__init__()   A

Complexity

Conditions 1

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

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