3 import matplotlib
as mpl
4 import matplotlib
.pyplot
as plt
5 from matplotlib
.patches
import Rectangle
6 from matplotlib
.collections
import PatchCollection
7 from matplotlib
.transforms
import Affine2D
8 from mpl_toolkits
.mplot3d
import Axes3D
9 from matplotlib
.colors
import LinearSegmentedColormap
10 from mpl_toolkits
.basemap
import Basemap
12 from interpolation
import sort_dates
17 def create_pixels(lons
,lats
,widths
,heights
,alphas
,color
,label
):
19 Plot of pixels using centers (lons,lats), with sizes (widhts,heights), angle alphas, and color color.
21 :param lons: array of longitude coordinates at the center of the pixels
22 :param lats: array of latitude coordinates at the center of the pixels
23 :param widths: array of widhts of the pixels
24 :param heights: array of heights of the pixels
25 :param alphas: array of angles of the pixels
26 :param color: tuple with RGB color values
27 :return col: collection of rectangles with the pixels
29 Developed in Python 2.7.15 :: Anaconda 4.5.10, on MACINTOSH.
30 Angel Farguell (angel.farguell@gmail.com) 2018-12-28
35 for x
, y
, h
, w
, a
in zip(lons
, lats
, heights
, widths
, alphas
):
36 xpos
= x
- w
/2 # The x position will be half the width from the center
37 ypos
= y
- h
/2 # same for the y position, but with height
38 rect
= Rectangle( (xpos
, ypos
), w
, h
, a
) # Create a rectangle
39 pixels
.append(rect
) # Add the rectangle patch to our list
41 # Create a collection from the rectangles
42 col
= PatchCollection(pixels
)
43 # set the alpha for all rectangles
45 # Set the colors using the colormap
46 col
.set_facecolor( [color
]*len(lons
) )
48 col
.set_linewidth( 0 )
53 def basemap_scatter_mercator(g
,bounds
,map):
55 Scatter plot of fire and ground pixels in a png file using a basemap with mercator projection
57 :param g: granule dictionary from read_*_files functions in JPSSD.py
58 :param bounds: array with the coordinates of the bounding box of the case
59 :param map: basemap mercator map where to plot the center of the pixels
60 :return png: string with png plot
61 :return float_bounds: coordinates of the borders of the png file
63 Developed in Python 2.7.15 :: Anaconda 4.5.10, on MACINTOSH.
64 Angel Farguell (angel.farguell@gmail.com) 2018-04-05
73 fil
= np
.logical_and(np
.logical_and(np
.logical_and(flon
>bounds
[0],flon
<bounds
[1]),flat
>bounds
[2]),flat
<bounds
[3])
75 categories
= (np
.array(mask
[fil
] == 3), np
.array(mask
[fil
] == 5),
76 np
.array(mask
[fil
] == 7), np
.array(mask
[fil
] == 8),
77 np
.array(mask
[fil
] == 9))
78 alphas
= (.2,.2,.4,.5,.6)
79 labels
= ('Water','Ground','Fire low','Fire nominal','Fire high')
84 for i
,cat
in enumerate(categories
):
85 lon
.append(flon
[fil
][cat
])
86 lat
.append(flat
[fil
][cat
])
87 val
.append(np
.ones(lon
[i
].shape
)*i
)
90 fig
= plt
.figure(frameon
=False,figsize
=(12,8),dpi
=72*2)
92 colors
= [(0,0,.5),(0,.5,0),(1,1,0),(1,.65,0),(.5,0,0)]
93 cmap
= LinearSegmentedColormap
.from_list('fire_detections', colors
, N
=N
)
95 m
.scatter(lon
[i
],lat
[i
],size
,c
=val
[i
],latlon
=True,marker
='.',cmap
=cmap
,vmin
=-.5,vmax
=N
-.5,alpha
=alphas
[i
],linewidths
=0)
97 str_io
= StringIO
.StringIO()
98 plt
.savefig(str_io
,bbox_inches
='tight',format
='png',pad_inches
=0,transparent
=True)
101 orientation
= 'vertical'
105 kwargs
= { 'norm': mpl
.colors
.Normalize(-.5,N
-.5),
106 'orientation': orientation
,
107 'spacing': 'proportional',
111 # build figure according to requested orientation
112 hsize
, wsize
= (size_in
,size_in
*0.5) if orientation
== 'vertical' else (size_in
*0.5,size_in
)
113 fig
= plt
.figure(figsize
=(wsize
,hsize
))
115 # proportions that work with axis title (horizontal not tested)
116 ax
= fig
.add_axes([.5,.03,.12,.8]) if orientation
=='vertical' else fig
.add_axes([0.03,.4,.8,.12])
118 # construct the colorbar and modify properties
119 cb
= mpl
.colorbar
.ColorbarBase(ax
,**kwargs
)
120 cb
.ax
.tick_params(length
=0)
121 cb
.ax
.set_yticklabels(labels
)
122 cb
.set_label(cb_label
,color
='0',fontsize
=8,labelpad
=-50)
124 # move ticks to left side
125 ax
.yaxis
.set_ticks_position('left')
126 for tick_lbl
in ax
.get_yticklabels():
127 tick_lbl
.set_color('0')
128 tick_lbl
.set_fontsize(5)
133 png
= str_io
.getvalue()
135 numpy_bounds
= [ (bounds
[0],bounds
[2]),(bounds
[1],bounds
[2]),(bounds
[1],bounds
[3]),(bounds
[0],bounds
[3]) ]
136 float_bounds
= [ (float(x
), float(y
)) for x
,y
in numpy_bounds
]
137 return png
, float_bounds
140 def center_pixels_plot(g
,bounds
):
142 Center pixels plot: generates a plot of the center of the pixels.
144 :param g: granule dictionary from read_*_files functions in JPSSD.py
145 :param bounds: array with the coordinates of the bounding box of the case
146 :return: 2D plot of the center of the pixels
148 Developed in Python 2.7.15 :: Anaconda 4.5.10, on MACINTOSH.
149 Angel Farguell (angel.farguell@gmail.com) 2018-12-28
153 ax
=fig
.add_subplot(111)
155 # Size of the center of the pixels
159 lons
=np
.array(g
.lon_nofire
)
160 lats
=np
.array(g
.lat_nofire
)
161 color
=(0,0.59765625,0)
162 plt
.scatter(lons
,lats
,size
,marker
='.',color
=color
,edgecolors
='k')
165 lons
=np
.array(g
.lon_fire
)
166 lats
=np
.array(g
.lat_fire
)
167 color
=(0.59765625,0,0)
168 plt
.scatter(lons
,lats
,size
,marker
='.',color
=color
,edgecolors
='k')
170 ax
.set_xlim(bounds
[0],bounds
[1])
171 ax
.set_ylim(bounds
[2],bounds
[3])
174 def pixels_plot(g
,bounds
):
176 Regular pixels plot: generates a plot of the pixels using a regular grid by distances.
178 :param g: granule dictionary from read_*_files functions in JPSSD.py
179 :param bounds: array with the coordinates of the bounding box of the case
180 :return: 2D plot of the pixels
182 Developed in Python 2.7.15 :: Anaconda 4.5.10, on MACINTOSH.
183 Angel Farguell (angel.farguell@gmail.com) 2018-12-28
195 dlonh
=np
.hstack((dlonh
,dlonh
[:,[-1]]))
197 dlonv
=np
.vstack((dlonv
,dlonv
[-1]))
204 dlath
=np
.hstack((dlath
,dlath
[:,[-1]]))
206 dlatv
=np
.vstack((dlatv
,dlatv
[-1]))
208 dh
=np
.sqrt(dlonh
**2+dlath
**2)
209 dv
=np
.sqrt(dlonv
**2+dlatv
**2)
211 # Mean between the distances
213 w
[:,1:-1]=np
.hstack([(dh
[:,[k
]]+dh
[:,[k
+1]])/2 for k
in range(dh
.shape
[1]-2)])
215 h
[1:-1,:]=np
.vstack([(dv
[k
]+dv
[k
+1])/2 for k
in range(dv
.shape
[0]-2)])
218 # Maximum between the distances
220 w[:,1:-1]=np.hstack([np.maximum(dh[:,[k]],dh[:,[k+1]]) for k in range(dh.shape[1]-2)])
222 h[1:-1,:]=np.vstack([np.maximum(dv[k],dv[k+1]) for k in range(dv.shape[0]-2)])
225 angle
=np
.arctan(dlath
/dlonh
)*180/np
.pi
230 ax
= fig
.gca(projection
='3d')
231 surf
= ax
.plot_surface(lon
,lat
,w
)
233 ax
= fig
.gca(projection
='3d')
234 surf
= ax
.plot_surface(lon
,lat
,h
)
236 ax
= fig
.gca(projection
='3d')
237 surf
= ax
.plot_surface(lon
,lat
,angle
)
239 flon
=np
.reshape(lon
,np
.prod(lon
.shape
))
240 flat
=np
.reshape(lat
,np
.prod(lat
.shape
))
241 fil
=np
.logical_and(np
.logical_and(np
.logical_and(flon
>bounds
[0],flon
<bounds
[1]),flat
>bounds
[2]),flat
<bounds
[3])
245 ff
=np
.reshape(fire
,np
.prod(fire
.shape
))
247 nofi
=np
.logical_or(ffg
== 3, ffg
== 5)
250 width
=np
.reshape(w
,np
.prod(w
.shape
))[fil
]
251 height
=np
.reshape(h
,np
.prod(h
.shape
))[fil
]
252 alpha
=np
.reshape(angle
,np
.prod(angle
.shape
))[fil
]
255 ax
= fig
.add_subplot(111)
263 color
=(0,0.59765625,0)
264 col_nofire
=create_pixels(lons
,lats
,widths
,heights
,alphas
,color
,'Ground')
265 ax
.add_collection(col_nofire
)
273 color
=(0.59765625,0,0)
274 col_fire
=create_pixels(lons
,lats
,widths
,heights
,alphas
,color
,'Fire')
275 ax
.add_collection(col_fire
)
278 ax
.set_xlim(bounds
[0],bounds
[1])
279 ax
.set_ylim(bounds
[2],bounds
[3])
282 def create_kml(kml_data
,kml_path
):
284 Creation of KML file with png files from basemap_scatter_mercator function
286 :param kml_data: dictionary with granules to plot information: name, png_file, bounds, time
287 :param kml_path: path to kml to generate
289 Developed in Python 2.7.15 :: Anaconda 4.5.10, on MACINTOSH.
290 Angel Farguell (angel.farguell@gmail.com) 2018-04-05
293 with
open(kml_path
,'w') as kml
:
294 kml
.write("""<?xml version="1.0" encoding="UTF-8"?>\n""")
295 kml
.write("""<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">\n""")
296 kml
.write("""<Document><name>Satellite Data</name>""")
299 <name>granules</name>""")
300 for idx
,data
in enumerate(kml_data
):
303 png
= data
['png_file']
304 bounds
= data
['bounds']
305 coord
= (str(bounds
[0]),str(bounds
[2]),
306 str(bounds
[1]),str(bounds
[2]),
307 str(bounds
[1]),str(bounds
[3]),
308 str(bounds
[0]),str(bounds
[3]),
309 str(bounds
[0]),str(bounds
[2]))
313 <Icon><href>%s</href></Icon>
314 <gx:TimeStamp><when>%s</when></gx:TimeStamp>""" % (
325 </gx:LatLonQuad>""" % coord
)
330 kml
.write("""</Document>\n</kml>\n""")
332 print 'Created file %s' % kml_path
336 print "Error: python %s pixel_plot_type" % sys
.argv
[0]
337 print " - Center pixels in basemap: 0"
338 print " - Center pixels plot: 1"
339 print " - Regular pixels plot: 2"
341 if __name__
== "__main__":
346 if sys
.argv
[1] not in ['0','1','2']:
348 print "Invalid value given: %s" % sys
.argv
[1]
353 print 'Loading data...'
354 data
,fxlon
,fxlat
,time_num
=sl
.load('data')
356 print "Error: No data file in the directory. First run a case using case.py."
359 granules
=sort_dates(data
)
360 bounds
=[fxlon
.min(),fxlon
.max(),fxlat
.min(),fxlat
.max()]
362 print 'Plotting data...'
364 if sys
.argv
[1] is '0':
365 m
= Basemap(projection
='merc',llcrnrlat
=bounds
[2], urcrnrlat
=bounds
[3], llcrnrlon
=bounds
[0], urcrnrlon
=bounds
[1])
367 for idx
, g
in enumerate(granules
):
368 raster_png_data
,corner_coords
= basemap_scatter_mercator(g
[1],bounds
,m
)
369 bounds
= (corner_coords
[0][0],corner_coords
[1][0],corner_coords
[0][1],corner_coords
[2][1])
370 pngfile
= g
[0]+'.png'
371 timestamp
= g
[1].acq_date
+ 'T' + g
[1].acq_time
[0:2] + ':' + g
[1].acq_time
[2:4] + 'Z'
372 with
open(pngfile
, 'w') as f
:
373 f
.write(raster_png_data
)
374 print '> File %s saved.' % g
[0]
375 kmld
.append(Dict({'name': g
[0], 'png_file': pngfile
, 'bounds': bounds
, 'time': timestamp
}))
376 create_kml(kmld
,'./doc.kml')
377 os
.system('zip -r granules.kmz doc.kml *.png')
378 print 'Created file granules.kmz'
379 elif sys
.argv
[1] is '1':
381 center_pixels_plot(g
[1],bounds
)
382 plt
.title('Granule %s' % g
[0])
386 pixels_plot(g
[1],bounds
)
387 plt
.title('Granule %s' % g
[0])