@@ -228,37 +228,33 @@ def _read_one_nc(cls, file_name, centroids, intensity_thres):
228228 new_haz : StormEurope
229229 Hazard instance for one single storm.
230230 """
231- ncdf = xr .open_dataset (file_name )
232-
233- if centroids .size != (ncdf .sizes ['latitude' ] * ncdf .sizes ['longitude' ]):
234- ncdf .close ()
235- LOGGER .warning (('Centroids size doesn\' t match NCDF dimensions. '
236- 'Omitting file %s.' ), file_name )
237- return None
238-
239- # xarray does not penalise repeated assignments, see
240- # http://xarray.pydata.org/en/stable/data-structures.html
241- stacked = ncdf ['max_wind_gust' ].stack (
242- intensity = ('latitude' , 'longitude' , 'time' )
243- )
244- stacked = stacked .where (stacked > intensity_thres )
245- stacked = stacked .fillna (0 )
246-
247- # fill in values from netCDF
248- ssi_wisc = np .array ([float (ncdf .attrs ['ssi' ])])
249- intensity = sparse .csr_matrix (stacked )
250- new_haz = cls (ssi_wisc = ssi_wisc ,
251- intensity = intensity ,
252- event_name = [ncdf .attrs ['storm_name' ]],
253- date = np .array ([datetime64_to_ordinal (ncdf ['time' ].data [0 ])]),
254- # fill in default values
255- centroids = centroids ,
256- event_id = np .array ([1 ]),
257- frequency = np .array ([1 ]),
258- orig = np .array ([True ]),)
259-
260- ncdf .close ()
261- return new_haz
231+ with xr .open_dataset (file_name ) as ncdf :
232+ if centroids .size != (ncdf .sizes ['latitude' ] * ncdf .sizes ['longitude' ]):
233+ LOGGER .warning (('Centroids size doesn\' t match NCDF dimensions. '
234+ 'Omitting file %s.' ), file_name )
235+ return None
236+
237+ # xarray does not penalise repeated assignments, see
238+ # http://xarray.pydata.org/en/stable/data-structures.html
239+ stacked = ncdf ['max_wind_gust' ].stack (
240+ intensity = ('latitude' , 'longitude' , 'time' )
241+ )
242+ stacked = stacked .where (stacked > intensity_thres )
243+ stacked = stacked .fillna (0 )
244+
245+ # fill in values from netCDF
246+ ssi_wisc = np .array ([float (ncdf .attrs ['ssi' ])])
247+ intensity = sparse .csr_matrix (stacked )
248+ new_haz = cls (ssi_wisc = ssi_wisc ,
249+ intensity = intensity ,
250+ event_name = [ncdf .attrs ['storm_name' ]],
251+ date = np .array ([datetime64_to_ordinal (ncdf ['time' ].data [0 ])]),
252+ # fill in default values
253+ centroids = centroids ,
254+ event_id = np .array ([1 ]),
255+ frequency = np .array ([1 ]),
256+ orig = np .array ([True ]),)
257+ return new_haz
262258
263259 def read_cosmoe_file (self , * args , ** kwargs ):
264260 """This function is deprecated, use StormEurope.from_cosmoe_file instead."""
@@ -309,69 +305,66 @@ def from_cosmoe_file(cls, fp_file, run_datetime, event_date=None,
309305 intensity_thres = cls .intensity_thres if intensity_thres is None else intensity_thres
310306
311307 # read intensity from file
312- ncdf = xr .open_dataset (fp_file )
313- ncdf = ncdf .assign_coords (date = ('time' ,ncdf ["time" ].dt .floor ("D" ).values ))
314-
315- if event_date :
316- try :
317- stacked = ncdf .sel (
318- time = event_date .strftime ('%Y-%m-%d' )
319- ).groupby ('date' ).max ().stack (intensity = ('y_1' , 'x_1' ))
320- except KeyError as ker :
321- raise ValueError ('Extraction of date and coordinates failed. This is most likely '
322- 'because the selected event_date '
323- f'{ event_date .strftime ("%Y-%m-%d" )} is not contained in the '
324- 'weather forecast selected by fp_file {fp_file}. Please adjust '
325- f'event_date or fp_file.' ) from ker
326- considered_dates = np .datetime64 (event_date )
327- else :
328- time_covered_step = ncdf ['time' ].diff ('time' )
329- time_covered_day = time_covered_step .groupby ('date' ).sum ()
330- # forecast run should cover at least 18 hours of a day
331- considered_dates_bool = time_covered_day >= np .timedelta64 (18 ,'h' )
332- stacked = ncdf .groupby ('date' ).max ()\
333- .sel (date = considered_dates_bool )\
334- .stack (intensity = ('y_1' , 'x_1' ))
335- considered_dates = stacked ['date' ].values
336- stacked = stacked .stack (date_ensemble = ('date' , 'epsd_1' ))
337- stacked = stacked .where (stacked ['VMAX_10M' ] > intensity_thres )
338- stacked = stacked .fillna (0 )
339-
340- # fill in values from netCDF
341- intensity = sparse .csr_matrix (stacked ['VMAX_10M' ].T )
342- event_id = np .arange (stacked ['date_ensemble' ].size ) + 1
343- date = np .repeat (
344- np .array (datetime64_to_ordinal (considered_dates )),
345- np .unique (ncdf ['epsd_1' ]).size
346- )
347- orig = np .full_like (event_id , False )
348- orig [(stacked ['epsd_1' ] == 0 ).values ] = True
349- if description is None :
350- description = (model_name +
351- ' weather forecast windfield ' +
352- 'for run startet at ' +
353- run_datetime .strftime ('%Y%m%d%H' ))
354-
355- # Create Hazard
356- haz = cls (
357- intensity = intensity ,
358- event_id = event_id ,
359- centroids = cls ._centroids_from_nc (fp_file ),
360- # fill in default values
361- orig = orig ,
362- date = date ,
363- event_name = [date_i + '_ens' + str (ens_i )
364- for date_i , ens_i
365- in zip (date_to_str (date ), stacked ['epsd_1' ].values + 1 )],
366- frequency = np .divide (
367- np .ones_like (event_id ),
368- np .unique (ncdf ['epsd_1' ]).size ),
369- )
308+ with xr .open_dataset (fp_file ) as ncdf :
309+ ncdf = ncdf .assign_coords (date = ('time' ,ncdf ["time" ].dt .floor ("D" ).values ))
310+ if event_date :
311+ try :
312+ stacked = ncdf .sel (
313+ time = event_date .strftime ('%Y-%m-%d' )
314+ ).groupby ('date' ).max ().stack (intensity = ('y_1' , 'x_1' ))
315+ except KeyError as ker :
316+ raise ValueError ('Extraction of date and coordinates failed. This is most likely '
317+ 'because the selected event_date '
318+ f'{ event_date .strftime ("%Y-%m-%d" )} is not contained in the '
319+ 'weather forecast selected by fp_file {fp_file}. Please adjust '
320+ f'event_date or fp_file.' ) from ker
321+ considered_dates = np .datetime64 (event_date )
322+ else :
323+ time_covered_step = ncdf ['time' ].diff ('time' )
324+ time_covered_day = time_covered_step .groupby ('date' ).sum ()
325+ # forecast run should cover at least 18 hours of a day
326+ considered_dates_bool = time_covered_day >= np .timedelta64 (18 ,'h' )
327+ stacked = ncdf .groupby ('date' ).max ()\
328+ .sel (date = considered_dates_bool )\
329+ .stack (intensity = ('y_1' , 'x_1' ))
330+ considered_dates = stacked ['date' ].values
331+ stacked = stacked .stack (date_ensemble = ('date' , 'epsd_1' ))
332+ stacked = stacked .where (stacked ['VMAX_10M' ] > intensity_thres )
333+ stacked = stacked .fillna (0 )
334+
335+ # fill in values from netCDF
336+ intensity = sparse .csr_matrix (stacked ['VMAX_10M' ].T )
337+ event_id = np .arange (stacked ['date_ensemble' ].size ) + 1
338+ date = np .repeat (
339+ np .array (datetime64_to_ordinal (considered_dates )),
340+ np .unique (ncdf ['epsd_1' ]).size
341+ )
342+ orig = np .full_like (event_id , False )
343+ orig [(stacked ['epsd_1' ] == 0 ).values ] = True
344+ if description is None :
345+ description = (model_name +
346+ ' weather forecast windfield ' +
347+ 'for run startet at ' +
348+ run_datetime .strftime ('%Y%m%d%H' ))
349+
350+ # Create Hazard
351+ haz = cls (
352+ intensity = intensity ,
353+ event_id = event_id ,
354+ centroids = cls ._centroids_from_nc (fp_file ),
355+ # fill in default values
356+ orig = orig ,
357+ date = date ,
358+ event_name = [date_i + '_ens' + str (ens_i )
359+ for date_i , ens_i
360+ in zip (date_to_str (date ), stacked ['epsd_1' ].values + 1 )],
361+ frequency = np .divide (
362+ np .ones_like (event_id ),
363+ np .unique (ncdf ['epsd_1' ]).size ),
364+ )
370365
371- # close netcdf file
372- ncdf .close ()
373- haz .check ()
374- return haz
366+ haz .check ()
367+ return haz
375368
376369 def read_icon_grib (self , * args , ** kwargs ):
377370 """This function is deprecated, use StormEurope.from_icon_grib instead."""
@@ -444,11 +437,12 @@ def from_icon_grib(cls, run_datetime, event_date=None, model_name='icon-eu-eps',
444437 gripfile_path_i = Path (file_i [:- 4 ])
445438 with open (file_i , 'rb' ) as source , open (gripfile_path_i , 'wb' ) as dest :
446439 dest .write (bz2 .decompress (source .read ()))
447- ds_i = xr .open_dataset (gripfile_path_i , engine = 'cfgrib' )
448- if ind_i == 0 :
449- stacked = ds_i
450- else :
451- stacked = xr .concat ([stacked ,ds_i ], 'valid_time' )
440+
441+ with xr .open_dataset (gripfile_path_i , engine = 'cfgrib' ) as ds_i :
442+ if ind_i == 0 :
443+ stacked = ds_i
444+ else :
445+ stacked = xr .concat ([stacked ,ds_i ], 'valid_time' )
452446
453447 # create intensity matrix with max for each full day
454448 stacked = stacked .assign_coords (
@@ -524,35 +518,34 @@ def _centroids_from_nc(file_name):
524518 'longitude' variables in a netCDF file.
525519 """
526520 LOGGER .info ('Constructing centroids from %s' , file_name )
527- ncdf = xr .open_dataset (file_name )
528- create_meshgrid = True
529- if hasattr (ncdf , 'latitude' ):
530- lats = ncdf ['latitude' ].data
531- lons = ncdf ['longitude' ].data
532- elif hasattr (ncdf , 'lat' ):
533- lats = ncdf ['lat' ].data
534- lons = ncdf ['lon' ].data
535- elif hasattr (ncdf , 'lat_1' ):
536- if len (ncdf ['lon_1' ].shape )> 1 & \
537- (ncdf ['lon_1' ].shape == ncdf ['lat_1' ].shape ) \
538- :
539- lats = ncdf ['lat_1' ].data .flatten ()
540- lons = ncdf ['lon_1' ].data .flatten ()
521+ with xr .open_dataset (file_name ) as ncdf :
522+ create_meshgrid = True
523+ if hasattr (ncdf , 'latitude' ):
524+ lats = ncdf ['latitude' ].data
525+ lons = ncdf ['longitude' ].data
526+ elif hasattr (ncdf , 'lat' ):
527+ lats = ncdf ['lat' ].data
528+ lons = ncdf ['lon' ].data
529+ elif hasattr (ncdf , 'lat_1' ):
530+ if len (ncdf ['lon_1' ].shape )> 1 & \
531+ (ncdf ['lon_1' ].shape == ncdf ['lat_1' ].shape ) \
532+ :
533+ lats = ncdf ['lat_1' ].data .flatten ()
534+ lons = ncdf ['lon_1' ].data .flatten ()
535+ create_meshgrid = False
536+ else :
537+ lats = ncdf ['lat_1' ].data
538+ lons = ncdf ['lon_1' ].data
539+ elif hasattr (ncdf , 'clat' ):
540+ lats = ncdf ['clat' ].data
541+ lons = ncdf ['clon' ].data
542+ if ncdf ['clat' ].attrs ['units' ]== 'radian' :
543+ lats = np .rad2deg (lats )
544+ lons = np .rad2deg (lons )
541545 create_meshgrid = False
542546 else :
543- lats = ncdf ['lat_1' ].data
544- lons = ncdf ['lon_1' ].data
545- elif hasattr (ncdf , 'clat' ):
546- lats = ncdf ['clat' ].data
547- lons = ncdf ['clon' ].data
548- if ncdf ['clat' ].attrs ['units' ]== 'radian' :
549- lats = np .rad2deg (lats )
550- lons = np .rad2deg (lons )
551- create_meshgrid = False
552- else :
553- raise AttributeError ('netcdf file has no field named latitude or '
554- 'other know abrivation for coordinates.' )
555- ncdf .close ()
547+ raise AttributeError ('netcdf file has no field named latitude or '
548+ 'other know abrivation for coordinates.' )
556549
557550 if create_meshgrid :
558551 lats , lons = np .array ([np .repeat (lats , len (lons )),
0 commit comments