1 from netCDF4
import Dataset
2 from datetime
import datetime
, timedelta
4 import matplotlib
.pyplot
as plt
5 from mpl_toolkits
.basemap
import Basemap
6 from pyproj
import Proj
12 # Seconds since 2000-01-01 12:00:00
13 add_seconds
=ncf
.variables
['t'][0]
14 # Datetime of image scan
15 dt
=datetime(2000, 1, 1, 12)+timedelta(seconds
=float(add_seconds
.data
))
19 # Detections in RGB array
21 R
=ncf
.variables
['CMI_C07'][:].data
22 G
=ncf
.variables
['CMI_C06'][:].data
23 B
=ncf
.variables
['CMI_C05'][:].data
24 # Turn empty values into nans
28 # Apply range limits for each channel (mostly important for Red channel)
35 # Normalize each channel by the appropriate range of values (again, mostly important for Red channel)
39 # Apply the gamma correction to Red channel.
40 # I was told gamma=0.4, but I get the right answer with gamma=2.5 (the reciprocal of 0.4)
42 # The final RGB array :)
43 RGB
=np
.dstack([R
, G
, B
])
49 sat_h
=ncf
.variables
['goes_imager_projection'].perspective_point_height
53 sat_lon
=ncf
.variables
['goes_imager_projection'].longitude_of_projection_origin
57 sat_sweep
=ncf
.variables
['goes_imager_projection'].sweep_angle_axis
60 # The projection x and y coordinates equals
61 # the scanning angle (in radians) multiplied by the satellite height (http://proj4.org/projections/geos.html)
62 X
=ncf
.variables
['x'][:] * sat_h
63 Y
=ncf
.variables
['y'][:] * sat_h
69 # Visualize the way Brian Blaylock does
70 p
=Proj(proj
='geos', h
=sat_h
, lon_0
=sat_lon
, sweep
=sat_sweep
)
71 # Convert map points to latitude and longitude with the magic provided by Pyproj
72 XX
, YY
=np
.meshgrid(X
, Y
)
73 lons
, lats
=p(XX
, YY
, inverse
=True)
74 lats
[np
.isnan(R
)]=np
.nan
75 lons
[np
.isnan(R
)]=np
.nan
76 # Make a new map object for the HRRR model domain map projection
77 mH
= Basemap(resolution
='l', projection
='lcc', area_thresh
=5000, \
78 width
=1800*3000, height
=1060*3000, \
79 lat_1
=38.5, lat_2
=38.5, \
80 lat_0
=38.5, lon_0
=-97.5)
81 # Create a color tuple for pcolormesh
82 rgb
= RGB
[:,:-1,:] # Using one less column is very important, else your image will be scrambled! (This is the stange nature of pcolormesh)
83 colorTuple
= rgb
.reshape((rgb
.shape
[0] * rgb
.shape
[1]), 3) # flatten array, becuase that's what pcolormesh wants.
84 colorTuple
= np
.insert(colorTuple
, 3, 1.0, axis
=1) # adding an alpha channel will plot faster, according to stackoverflow. Not sure why.
85 # Now we can plot the GOES data on the HRRR map domain and projection
86 plt
.figure(figsize
=[10,8])
87 # The values of R are ignored becuase we plot the color in colorTuple, but pcolormesh still needs its shape.
88 newmap
= mH
.pcolormesh(lons
, lats
, R
, color
=colorTuple
, linewidth
=0, latlon
=True)
89 newmap
.set_array(None) # without this line the linewidth is set to zero, but the RGB colorTuple is ignored. I don't know why.
90 mH
.drawcoastlines(color
='w')
91 mH
.drawcountries(color
='w')
92 mH
.drawstates(color
='w')
93 plt
.title('GOES-16 Fire Temperature', fontweight
='semibold', fontsize
=15)
94 plt
.title('%s' % dt
.strftime('%H:%M UTC %d %B %Y'), loc
='right')
97 # location of South Sugarloaf fire
98 l
= {'latitude': 41.812,
99 'longitude': -116.324}
101 #l = {'latitude': 39.2827513,
102 # 'longitude':-76.6214623}
104 #l = {'latitude': 33.724,
105 # 'longitude': -108.538}
107 mZ
= Basemap(projection
='lcc', resolution
='i',
108 width
=3E5
, height
=3E5
,
109 lat_0
=l
['latitude'], lon_0
=l
['longitude'],)
111 # Now we can plot the GOES data on a zoomed in map centered on the Sugarloaf wildfire
112 plt
.figure(figsize
=[10, 10])
113 newmap
= mZ
.pcolormesh(lons
, lats
, R
, color
=colorTuple
, linewidth
=0, latlon
=True)
114 newmap
.set_array(None)
116 #mZ.scatter(l['longitude'], l['latitude'], marker='o', s=1000, facecolor='none', edgecolor='greenyellow') # circle fire area
117 mZ
.drawcoastlines(color
='w')
118 mZ
.drawcountries(color
='w')
119 mZ
.drawstates(color
='w')
121 plt
.title('GOES-16 Fire Temperature\n', fontweight
='semibold', fontsize
=15)
122 plt
.title('%s' % dt
.strftime('%H:%M UTC %d %B %Y'), loc
='right')
123 plt
.title('South Sugarloaf Fire', loc
='left')