5
5
Wrapper to handle importing MPAS files into xarray.
6
6
7
7
Module:
8
- 1. converts MPAS "xtime" to xarray time. Time dimension is assigned via
9
- `preprocess_mpas(..., timeSeriestats=False, ...)`.
10
- 2. converts MPAS "timeSinceStartOfSim" to xarray time for MPAS fields coming
11
- from the timeSeriesStatsAM. Time dimension is assigned via
12
- `preprocess_mpas(..., timeSeriesStats=True, ...)`.
13
- 3. provides capability to remove redundant time entries from reading of
8
+ 1. converts MPAS time in various formats to xarray time. The MPAS time
9
+ variable is provided via
10
+ `preprocess_mpas(..., timestr='xtime', ...)`.
11
+ `timestr` can either be a single variable name or a pair of variable
12
+ names. In the latter case, each time variable is converted to an
13
+ xarray time and the mean of the two times is used as the final xarray
14
+ time. Each variable name in `timestr` can refer either to a float
15
+ array containing the the number of days since the start of the
16
+ simulation (e.g. `daysSinceStartOfSim`) or a string variable with the
17
+ date and time (e.g. `xtime`) in the usual MPAS format:
18
+ YYYY-MM-DD_hh:mm:ss
19
+ 2. provides capability to remove redundant time entries from reading of
14
20
multiple netCDF datasets via `remove_repeated_time_index`.
15
21
16
22
Example Usage:
21
27
>>> ds = remove_repeated_time_index(ds)
22
28
23
29
Phillip J. Wolfram, Xylar Asay-Davis
24
- Last modified: 11/25 /2016
30
+ Last modified: 12/01 /2016
25
31
"""
26
32
27
33
import datetime
@@ -110,26 +116,44 @@ def ensure_list(alist): # {{{
110
116
return alist # }}}
111
117
112
118
113
- def time_series_stat_time ( timestr , daysSinceStart ): # {{{
119
+ def get_datetimes ( time_var , yearoffset ): # {{{
114
120
"""
115
- Modifies daysSinceStart for uniformity based on between differences
116
- between MPAS-O and MPAS-Seaice.
121
+ time_var is an xarray DataArray that contains time information as a date
122
+ string, a floating-point number of days or a number of days represented
123
+ as a pandas timedelta (in ns). The result is a list of datetimes
124
+ corresponding to the input dates offset as appropriate by the yearoffset.
117
125
118
- Phillip J. Wolfram
119
- 09/09 /2016
126
+ Xylar Asay-Davis
127
+ Last modified: 11/25 /2016
120
128
"""
121
129
122
- if (timestr == 'timeSeriesStatsMonthly_avg_daysSinceStartOfSim_1' ):
123
- return [datetime .timedelta (x ) for x in daysSinceStart .values ]
130
+ if time_var .dtype == '|S64' :
131
+ # this is a variable like date strings like 'xtime'
132
+ time = ['' .join (atime ).strip () for atime in time_var .values ]
133
+ datetimes = [datetime .datetime (yearoffset + int (x [:4 ]), int (x [5 :7 ]),
134
+ int (x [8 :10 ]), int (x [11 :13 ]),
135
+ int (x [14 :16 ]), int (x [17 :19 ]))
136
+ for x in time ]
137
+ elif time_var .dtype == 'float64' :
138
+ # this array contains floating-point days like 'daysSinceStartOfSim'
139
+ start = datetime .datetime (year = yearoffset + 1 , month = 1 , day = 1 )
140
+ datetimes = [start + datetime .timedelta (x )
141
+ for x in time_var .values ]
142
+ elif time_var .dtype == 'timedelta64[ns]' :
143
+ # this array contains a variable like 'daysSinceStartOfSim' as a
144
+ # timedelta64
145
+ start = datetime .datetime (year = yearoffset + 1 , month = 1 , day = 1 )
146
+ datetimes = [start + x for x in
147
+ pd .to_timedelta (time_var .values , unit = 'ns' )]
124
148
else :
125
- return pd .to_timedelta (daysSinceStart .values , unit = 'ns' )
149
+ raise TypeError ("time_var of unsupported type {}" .format (
150
+ time_var .dtype ))
126
151
127
- # }}}
152
+ return datetimes # }}}
128
153
129
154
130
155
def preprocess_mpas (ds , onlyvars = None , selvals = None , iselvals = None ,
131
- timeSeriesStats = False , timestr = None ,
132
- yearoffset = 1849 ): # {{{
156
+ timestr = 'xtime' , yearoffset = 1849 ): # {{{
133
157
"""
134
158
Builds correct time specification for MPAS, allowing a date offset because
135
159
the time must be between 1678 and 2262 based on the xarray library.
@@ -141,50 +165,36 @@ def preprocess_mpas(ds, onlyvars=None, selvals=None, iselvals=None,
141
165
conditions. Hence, a default date offset is chosen to be yearoffset=1849,
142
166
(year 0001 of an 1850 run will correspond with Jan 1st, 1850).
143
167
144
- Note, for use with the timeSeriesStats analysis member fields set
145
- timeSeriesStats=True and assign timestr.
146
-
147
- The timestr variable designates the appropriate variable to be used as the
148
- unlimited dimension for xarray concatenation. For MPAS-O
149
- timestr='time_avg_daysSinceStartOfSim' and for MPAS-Seaice
150
- timestr='timeSeriesStatsMonthly_avg_daysSinceStartOfSim_1'.
168
+ The data set is assumed to have an array of date strings with variable
169
+ name given by timestr, typically either 'xtime', or 'xtime_start'.
151
170
152
171
The onlyvars option reduces the dataset to only include variables in the
153
172
onlyvars list. If onlyvars=None, include all dataset variables.
154
173
155
174
iselvals and selvals provide index and value-based slicing operations for
156
175
individual datasets prior to their merge via xarray.
157
- iselvals is a dictionary, e.g., iselvals = {'nVertLevels': slice(0,3),
158
- 'nCells': cellIDs}
159
- selvals is a dictionary, e.g., selvals = {'cellLon': 180.0}
176
+ iselvals is a dictionary, e.g. iselvals = {'nVertLevels': slice(0, 3),
177
+ 'nCells': cellIDs}
178
+ selvals is a dictionary, e.g. selvals = {'cellLon': 180.0}
160
179
161
180
Phillip J. Wolfram, Milena Veneziani, Luke van Roekel and Xylar Asay-Davis
162
- 11/25/2016
181
+ Last modified: 11/25/2016
163
182
"""
164
183
165
- # ensure timestr is specified used when timeSeriesStats=True
166
- if timeSeriesStats :
167
- if timestr is None :
168
- assert False , 'A value for timestr is required, e.g., ' + \
169
- 'for MPAS-O: time_avg_daysSinceStartOfSim, and ' + \
170
- 'for MPAS-Seaice: ' + \
171
- 'timeSeriesStatsMonthly_avg_daysSinceStartOfSim_1'
172
-
173
- # compute shifted datetimes
174
- daysSinceStart = ds [timestr ]
175
- datetimes = [datetime .datetime (yearoffset + 1 , 1 , 1 ) + x
176
- for x in time_series_stat_time (timestr , daysSinceStart )]
184
+ if isinstance (timestr , (tuple , list )):
185
+ # we want to average the two
186
+ assert (len (timestr ) == 2 )
187
+ starts = get_datetimes (ds [timestr [0 ]], yearoffset )
188
+ ends = get_datetimes (ds [timestr [1 ]], yearoffset )
189
+ datetimes = [starts [i ] + (ends [i ] - starts [i ])/ 2
190
+ for i in range (len (starts ))]
177
191
else :
178
- time = np .array (['' .join (atime ).strip () for atime in ds .xtime .values ])
179
- datetimes = [datetime .datetime (yearoffset + int (x [:4 ]), int (x [5 :7 ]),
180
- int (x [8 :10 ]), int (x [11 :13 ]),
181
- int (x [14 :16 ]), int (x [17 :19 ]))
182
- for x in time ]
192
+ datetimes = get_datetimes (ds [timestr ], yearoffset )
183
193
184
194
assert_valid_datetimes (datetimes , yearoffset )
185
195
186
196
# append the corret time information
187
- ds .coords ['Time' ] = pd . to_datetime ( datetimes )
197
+ ds .coords ['Time' ] = datetimes
188
198
# record the yroffset
189
199
ds .attrs .__setitem__ ('time_yearoffset' , str (yearoffset ))
190
200
0 commit comments