1 import matplotlib
.pyplot
as plt
5 from datetime
import timedelta
6 from JPSSD
import time_iso2num
, time_iso2datetime
, time_datetime2iso
9 import re
, glob
, sys
, os
12 def process_forecast(wrfout_file
,bounds
,plot
=False):
14 Process infrared perimeters the same way than satellite data.
16 :param dst: path to kml perimeter files
17 :param bounds: coordinate bounding box filtering to
19 Developed in Python 2.7.15 :: Anaconda 4.5.10, on MACINTOSH.
20 Angel Farguell (angel.farguell@gmail.com), 2019-06-05
23 # prefix of the elements in the dictionary
30 # initializing dictionary
35 data
= nc
.Dataset(wrfout_file
)
36 except Exception as e
:
37 print 'Warning: No netcdf file %s in the path' % wrfout_file
40 ctime
= ''.join(data
['Times'][-1])
41 ctime_iso
= ctime
.replace('_','T')
42 ctime_datetime
= time_iso2datetime(ctime_iso
)
43 # getting rid of strip
44 atmlenx
= len(data
.dimensions
['west_east'])
45 atmleny
= len(data
.dimensions
['south_north'])
46 staglenx
= len(data
.dimensions
['west_east_stag'])
47 stagleny
= len(data
.dimensions
['south_north_stag'])
48 dimlenx
= len(data
.dimensions
['west_east_subgrid'])
49 dimleny
= len(data
.dimensions
['south_north_subgrid'])
50 ratiox
= dimlenx
/max(staglenx
,atmlenx
+1)
51 ratioy
= dimleny
/max(stagleny
,atmleny
+1)
55 lon
= data
['FXLONG'][0][0:lenx
,0:leny
]
56 lat
= data
['FXLAT'][0][0:lenx
,0:leny
]
57 # mask coordinates to bounding box
58 mask
= np
.logical_and(np
.logical_and(np
.logical_and(lon
>bounds
[0],lon
<bounds
[1]),lat
>bounds
[2]),lat
<bounds
[3])
60 tign_g
= data
['TIGN_G'][0][0:lenx
,0:leny
]
61 # create a square subset of fire arrival time less than the maximum
62 mtign
= np
.logical_and(mask
,tign_g
< tign_g
.max())
65 mlen
= margin
*(mlon
.max()-mlon
.min())
66 sbounds
= (mlon
.min()-mlen
, mlon
.max()+mlen
, mlat
.min()-mlen
, mlat
.max()+mlen
)
67 smask
= np
.logical_and(np
.logical_and(np
.logical_and(lon
>sbounds
[0],lon
<sbounds
[1]),lat
>sbounds
[2]),lat
<sbounds
[3])
69 dx
= data
.getncattr('DX')
70 dy
= data
.getncattr('DY')
71 # scan and track dimensions of the observation (in km)
77 # times to get fire arrival time from
78 dt_forecast
= 1800 # in seconds
79 TT
= np
.arange(tign_g
.min(),tign_g
.max(),dt_forecast
)[0:-1]
81 # fire arrival time to datetime
82 time_datetime
= ctime_datetime
-timedelta(seconds
=float(tign_g
.max()-T
)) # there is an error of about 10 seconds (wrfout not ending at exact time of simulation)
83 # create ISO time of the date
84 time_iso
= time_datetime2iso(time_datetime
)
85 # create numerical time from the ISO time
86 time_num
= time_iso2num(time_iso
)
88 time_data
= '_A%04d%03d_%02d%02d' % (time_datetime
.year
, time_datetime
.timetuple().tm_yday
,
89 time_datetime
.hour
, time_datetime
.minute
)
90 # create acquisition date
91 acq_date
= '%04d-%02d-%02d' % (time_datetime
.year
, time_datetime
.month
, time_datetime
.day
)
92 # create acquisition time
93 acq_time
= '%02d%02d' % (time_datetime
.hour
, time_datetime
.minute
)
95 print 'Retrieving forecast from %s' % time_iso
99 nofire
= np
.logical_and(tign_g
> T
, np
.logical_or(tign_g
!= tign_g
.max(), smask
))
101 lon_fire
= lon
[np
.logical_and(mask
,fire
)]
102 lat_fire
= lat
[np
.logical_and(mask
,fire
)]
103 lon_nofire
= lon
[np
.logical_and(mask
,nofire
)]
104 lat_nofire
= lat
[np
.logical_and(mask
,nofire
)]
105 # create general arrays
106 lons
= np
.concatenate((lon_nofire
,lon_fire
))
107 lats
= np
.concatenate((lat_nofire
,lat_fire
))
108 fires
= np
.concatenate((5*np
.ones(lon_nofire
.shape
),9*np
.ones(lon_fire
.shape
)))
113 plt
.plot(lons
[fires
==5],lats
[fires
==5],'g.')
114 plt
.plot(lons
[fires
==9],lats
[fires
==9],'r.')
119 # update perimeters dictionary
120 forecast
.update({prefix
+ time_data
: Dict({'file': wrfout_file
, 'time_tign_g': T
, 'lon': lons
, 'lat': lats
,
121 'fire': fires
, 'conf_fire': np
.array(conf_fire
*np
.ones(lons
[fires
==9].shape
)),
122 'lon_fire': lons
[fires
==9], 'lat_fire': lats
[fires
==9], 'lon_nofire': lons
[fires
==5], 'lat_nofire': lats
[fires
==5],
123 'scan_fire': scan
*np
.ones(lons
[fires
==9].shape
), 'track_fire': track
*np
.ones(lons
[fires
==9].shape
),
124 'scan_nofire': scan
*np
.ones(lons
[fires
==5].shape
), 'track_nofire': track
*np
.ones(lons
[fires
==9].shape
),
125 'time_iso': time_iso
, 'time_num': time_num
, 'acq_date': acq_date
, 'acq_time': acq_time
})})
130 if __name__
== "__main__":
132 bounds
= (-113.85068, -111.89413, 39.677563, 41.156837)
133 dst
= './patch/wrfout_patch'
135 f
= process_forecast(dst
,bounds
,plot
=plot
)
136 sl
.save(f
,'forecast')