2828 - kml_build_colorbar - create a colorbar to display on GE
2929 - topo2kmz - create kmz file showing onshore and offshore topography
3030 - transect2kml - create kml file showing a set of points on a transect
31+ - dtopo_contours2kmz - create a kmz file containing contour plots of dtopo(s)
3132 - kml_header - used internally
3233 - kml_footer - used internally
3334 - kml_region - used internally
4142except :
4243 pass # assume python2, already has reload
4344
45+ import numpy as np
46+ from numpy import ma
47+ from matplotlib import pyplot as plt
48+ import os
49+
4450def f2s (x , num_digits = 6 ):
4551 r"""
4652 Convert float to string in fixed point notation with at most
@@ -954,6 +960,11 @@ def fgmax2kml(rundata=None,fname='fgmax_grids.kml',verbose=True,combined=False):
954960 xy = ([fg .x1 ,fg .x2 ,fg .x3 ,fg .x4 ],
955961 [fg .y1 ,fg .y2 ,fg .y3 ,fg .y4 ])
956962 poly2kml (xy , kml_file , fname_root , color = '8888FF' )
963+ elif fg .point_style == 4 :
964+ # points specified by mask in a topo-like file, so plot its extent:
965+ topo_file_name = fg .xy_fname
966+ topo_type = 3
967+ topo2kml (topo_file_name , topo_type , color = '8888FF' )
957968 else :
958969 print ('fgmax2kml not yet implemented for point_style = %i' \
959970 % fg .point_style )
@@ -1006,7 +1017,7 @@ def fgout2kml(rundata=None,fname='fgout_grids.kml',verbose=True,combined=False):
10061017 box2kml (xy , kml_file , fname_root , color = '8888FF' )
10071018
10081019
1009- def make_input_data_kmls (rundata = None , combined = False ):
1020+ def make_input_data_kmls (rundata = None , combined = False , dtopo_contours = False ):
10101021 """
10111022 Produce kml files for the computational domain, all gauges and regions
10121023 specified, and all topo and dtopo files specified in rundata.
@@ -1050,6 +1061,13 @@ def make_input_data_kmls(rundata=None, combined=False):
10501061 dtopo_file_name = f [- 1 ]
10511062 dtopo_type = f [0 ]
10521063 dtopo2kml (dtopo_file_name , dtopo_type )
1064+ if dtopo_contours :
1065+ # also make a kmz file showing dtopo contours (takes a bit longer)
1066+ fname_kmz = os .path .split (dtopo_file_name )[- 1 ]
1067+ fname_kmz = os .path .splitext (fname_kmz )[0 ] # w/o path or extension
1068+ fname_kmz = fname_kmz + '_contours.kmz'
1069+ dtopo_contours2kmz (dtopo_file_name , dtopo_type = dtopo_type ,
1070+ dZ_interval = 1 , fname_kmz = fname_kmz ,verbose = False )
10531071
10541072
10551073def pcolorcells_for_kml (X , Y , Z , png_filename = None , dpc = 2 , max_inches = 15. ,
@@ -1090,25 +1108,27 @@ def pcolorcells_for_kml(X, Y, Z, png_filename=None, dpc=2, max_inches=15.,
10901108 png file, as described below.
10911109
10921110 Internally the value `dpi` (dots per inch) for the png file is
1093- determined so that it is at least 16 and so that:
1111+ determined so that it is at least 16 and so that::
1112+
10941113 dpi * x_inches = dcp * x_cells
10951114 dpi * y_inches = dcp * y_cells
1115+
10961116 where `x_cells`, `y_cells` are the number of cells in each direction.
10971117
10981118 `kwargs` are passed to `pcolormesh`, e.g. `cmap` and `norm` are
10991119 generally specified.
11001120
11011121 This function returns `fig, ax, png_extent, kml_dpi` so the user can further
11021122 annotate the figure befor saving it as a png file, which should then
1103- be done with:
1123+ be done with::
1124+
11041125 plt.savefig(png_filename, transparent=True, dpi=kml_dpi)
1126+
11051127 The `png_extent` is needed in construcing a kml file to display the
11061128 png file on Google Earth, e.g. using the function `png2kml` in this
11071129 module.
11081130 """
11091131
1110- from matplotlib import pyplot as plt
1111- import numpy as np
11121132
11131133 # If X is 2d extract proper 1d slice:
11141134 if X .ndim == 1 :
@@ -1160,8 +1180,8 @@ def pcolorcells_for_kml(X, Y, Z, png_filename=None, dpc=2, max_inches=15.,
11601180 dots_per_cell = dpc
11611181 max_dots = dots_per_cell * max_cells
11621182
1163- # determine dots per inch for png file, minimum 16 :
1164- kml_dpi = max (int (round (max_dots / max_inches )), 16 )
1183+ # determine dots per inch for png file, minimum 64 :
1184+ kml_dpi = max (int (round (max_dots / max_inches )), 64 )
11651185 dots_x = x_cells * dots_per_cell
11661186 dots_y = y_cells * dots_per_cell
11671187
@@ -1347,9 +1367,7 @@ def kml_build_colorbar(cb_filename, cmap, cmin=None, cmax=None,
13471367 cmin, cmax are used only if nrm is not provided.
13481368 """
13491369
1350- import matplotlib .pyplot as plt
13511370 import matplotlib as mpl
1352- import numpy
13531371
13541372 fig = plt .figure (figsize = (1.2 ,3 ))
13551373 ax1 = fig .add_axes ([0.3 , 0.075 , 0.20 , 0.80 ])
@@ -1366,12 +1384,12 @@ def kml_build_colorbar(cb_filename, cmap, cmin=None, cmax=None,
13661384
13671385 # make sure ticks appear at lower and upper limits of scale:
13681386 cbticks = cb1 .get_ticks ()
1369- cbticks = numpy .hstack ([norm .vmin , cbticks , norm .vmax ])
1387+ cbticks = np .hstack ([norm .vmin , cbticks , norm .vmax ])
13701388 # remove 2nd and/or next-to-last tick if they are cramped:
13711389 if cbticks [1 ]- cbticks [0 ] < 0.25 * (cbticks [2 ]- cbticks [1 ]):
1372- cbticks = numpy .hstack ((cbticks [:1 ], cbticks [2 :]))
1390+ cbticks = np .hstack ((cbticks [:1 ], cbticks [2 :]))
13731391 if cbticks [- 1 ]- cbticks [- 2 ] < 0.25 * (cbticks [- 2 ]- cbticks [- 3 ]):
1374- cbticks = numpy .hstack ((cbticks [:- 2 ], cbticks [- 1 :]))
1392+ cbticks = np .hstack ((cbticks [:- 2 ], cbticks [- 1 :]))
13751393 cb1 .set_ticks (cbticks )
13761394
13771395 if label :
@@ -1408,18 +1426,15 @@ def topo2kmz(topo, zlim=(-20,20), mask_outside_zlim=True, sea_level=0.,
14081426 - *close_figs* to close the pyplot figures after making png files
14091427
14101428 :Future:
1411- If `force_dry` is an array of the same shape as `topo.Z` then another png
1412- and kml file are created for land that is below `sea_level` but where
1413- `force_dry = True`.
1429+ - If `force_dry` is an array of the same shape as `topo.Z` then another png
1430+ and kml file are created for land that is below `sea_level` but where
1431+ `force_dry = True`.
14141432
14151433 """
14161434
14171435 import os , glob
1418- import numpy
1419- from numpy import ma
14201436 from clawpack .visclaw import colormaps
14211437 import zipfile
1422- import matplotlib .pyplot as plt
14231438
14241439 assert force_dry is None , 'force_dry not yet implemented'
14251440
@@ -1440,7 +1455,7 @@ def topo2kmz(topo, zlim=(-20,20), mask_outside_zlim=True, sea_level=0.,
14401455 data_break = sea_level )
14411456
14421457 if mask_outside_zlim :
1443- Z = ma .masked_where (numpy .logical_or (topo .Z < zlim [0 ], topo .Z > zlim [1 ]), topo .Z )
1458+ Z = ma .masked_where (np .logical_or (topo .Z < zlim [0 ], topo .Z > zlim [1 ]), topo .Z )
14441459 cbar_extend = 'neither'
14451460 else :
14461461 Z = topo .Z
@@ -1549,3 +1564,125 @@ def transect2kml(xtrans, ytrans, fname='transect.kml'):
15491564 kml_file .write ("\n </Document>\n </kml>" )
15501565
15511566 print ('Created ' , fname )
1567+
1568+ def dtopo_contours2kmz (dtopofiles , dtopo_type = 3 , dZ_interval = 1 , dZmax = 40 ,
1569+ text_label = True , text_x = None , text_y = None ,
1570+ fname_kmz = None , verbose = True ):
1571+
1572+ """
1573+ Create dtopo_contours.kmz file containing contour plots of the dtopo
1574+ deformations with radio buttons to select which one to show.
1575+ (Or dtopofiles can be a string for a single dtopofile.)
1576+
1577+ To show multiple dtopofiles, they must all have the same extent.
1578+
1579+ :Inputs:
1580+
1581+ - *dtopofiles* (str or list of str): single or list of dtopofile paths
1582+ - *dZ_interval* (float) the interval in meters between contours.
1583+ - *dZmax* (float) max for contour levels shown (and -dZmax is the min)
1584+ - *text_label* Text label to add to plots,
1585+ If text_label is a string this will be added as a text label,
1586+ If text_label == True a standard label will be added with the
1587+ dopofile name, dZ_interval, and the max, min values of dZ.
1588+ - *text_x, text_y* are the location of the text,
1589+ or if None then the mean of dtopofile.X and dtopofile.Y are used.
1590+
1591+ :Future:
1592+ - Could also add pcolor plot of deformation to kmz file.
1593+ """
1594+ from clawpack .geoclaw import dtopotools
1595+
1596+ import os ,sys , zipfile , shutil
1597+
1598+ kml_dir = 'temp_dtopos_kml'
1599+ os .system ('mkdir -p %s' % kml_dir )
1600+ events = []
1601+ png_files = []
1602+
1603+ if type (dtopofiles ) == str :
1604+ dtopofiles = [dtopofiles ] # if only one passed in
1605+
1606+ previous_png_extent = None
1607+
1608+ for dtopofile in dtopofiles :
1609+ dtopofile = os .path .abspath (dtopofile )
1610+ event = os .path .splitext (os .path .split (dtopofile )[- 1 ])[0 ]
1611+ events .append (event )
1612+ if verbose :
1613+ print ('Making contours for event = ' ,event )
1614+ print (' contour interval = %gm' % dZ_interval )
1615+
1616+ dtopo = dtopotools .DTopography (dtopofile , dtopo_type = dtopo_type )
1617+
1618+ # first make empty plot of right dimensions:
1619+ Zm = ma .masked_where (dtopo .Y < 90 , dtopo .Y ) # all masked
1620+ fig ,ax ,png_extent ,kml_dpi = pcolorcells_for_kml (dtopo .X , dtopo .Y , Zm ,
1621+ png_filename = None , dpc = 4 ,
1622+ verbose = verbose )
1623+
1624+ if previous_png_extent is not None :
1625+ assert png_extent == previous_png_extent , \
1626+ '*** dtopofiles have different extents\n ' \
1627+ + '*** cannot make a single kmz file displaying them'
1628+ previous_png_extent = png_extent
1629+
1630+ # now add contour plot:
1631+ clines = np .arange (dZ_interval ,dZmax ,dZ_interval )
1632+ lw = 2.
1633+ ax .contour (dtopo .X , dtopo .Y , dtopo .dZ [- 1 ,:,:], clines , colors = 'r' ,
1634+ linestyles = '-' , linewidths = lw )
1635+ clines = np .arange (- dZmax ,0 ,dZ_interval )
1636+ ax .contour (dtopo .X , dtopo .Y , dtopo .dZ [- 1 ,:,:], clines , colors = 'c' ,
1637+ linestyles = '-' , linewidths = lw )
1638+
1639+ if text_label :
1640+ if text_x is None :
1641+ text_x = dtopo .x .mean ()
1642+ if text_y is None :
1643+ text_y = dtopo .y .mean ()
1644+
1645+ dZ_min = dtopo .dZ [- 1 ,:,:].min ()
1646+ dZ_max = dtopo .dZ [- 1 ,:,:].max ()
1647+ if type (text_label ) == str :
1648+ plt .text (text_x , text_y , text_label , fontsize = 15 ,color = 'yellow' )
1649+ else :
1650+ plt .text (text_x , text_y ,'%s\n dZ_min = %.1fm, dZ_max = %.1fm' \
1651+ % (event ,dZ_min ,dZ_max ) \
1652+ + '\n dZ_interval = %.1f m' % dZ_interval , \
1653+ fontsize = 15 ,color = 'yellow' )
1654+
1655+ png_filename = '%s_contours.png' % event
1656+ png_files .append (png_filename )
1657+ png_filename = os .path .join (kml_dir , png_filename )
1658+ plt .savefig (png_filename , transparent = True , dpi = kml_dpi )
1659+ plt .close (fig )
1660+
1661+ if fname_kmz is None :
1662+ fname_kmz = 'dtopo_contours.kmz'
1663+ path_kmz = os .path .abspath ('./%s' % fname_kmz ) # path in this directory
1664+
1665+ # move to kml_dir for making kml files:
1666+ savedir = os .getcwd ()
1667+ os .chdir (kml_dir )
1668+ png_names = events
1669+ fname = 'dtopo_contours.kml'
1670+ name = 'dtopo_contours'
1671+ png2kml (png_extent , png_files = png_files , png_names = png_names ,
1672+ radio_style = True , name = name , fname = fname , verbose = verbose )
1673+
1674+ files = [fname ] + ['%s_contours.png' % event for event in events ]
1675+ if 0 :
1676+ print ('kmz file will include:' )
1677+ for file in files :
1678+ print (' ' , file )
1679+
1680+ with zipfile .ZipFile (path_kmz , 'w' ) as zip :
1681+ for file in files :
1682+ zip .write (file )
1683+ print ('Created %s' % fname_kmz )
1684+ os .chdir (savedir )
1685+
1686+ if verbose :
1687+ print ('Removing ' ,kml_dir )
1688+ shutil .rmtree (kml_dir )
0 commit comments