def geogrid_simulator(fpath, do_maps=True, map_kwargs=None): """Emulates geogrid.exe, which is useful when defining new WRF domains. Parameters ---------- fpath: str path to a namelist.wps file do_maps: bool if you want the simulator to return you maps of the grids as well map_kwargs: dict kwargs to pass to salem.Map() Returns ------- (grids, maps) with: - grids: a list of Grids corresponding to the domains defined in the namelist - maps: a list of maps corresponding to the grids (if do_maps==True) """ with open(fpath) as f: lines = f.readlines() pargs = dict() for l in lines: s = l.split('=') if len(s) < 2: continue s0 = s[0].strip().upper() s1 = list(filter(None, s[1].strip().replace('\n', '').split(','))) if s0 == 'PARENT_ID': parent_id = [int(s) for s in s1] if s0 == 'PARENT_GRID_RATIO': parent_ratio = [int(s) for s in s1] if s0 == 'I_PARENT_START': i_parent_start = [int(s) for s in s1] if s0 == 'J_PARENT_START': j_parent_start = [int(s) for s in s1] if s0 == 'E_WE': e_we = [int(s) for s in s1] if s0 == 'E_SN': e_sn = [int(s) for s in s1] if s0 == 'DX': dx = float(s1[0]) if s0 == 'DY': dy = float(s1[0]) if s0 == 'MAP_PROJ': map_proj = s1[0].replace("'", '').strip().upper() if s0 == 'REF_LAT': pargs['lat_0'] = float(s1[0]) if s0 == 'REF_LON': pargs['ref_lon'] = float(s1[0]) if s0 == 'TRUELAT1': pargs['lat_1'] = float(s1[0]) if s0 == 'TRUELAT2': pargs['lat_2'] = float(s1[0]) if s0 == 'STAND_LON': pargs['lon_0'] = float(s1[0]) # Sometimes files are not complete pargs.setdefault('lon_0', pargs['ref_lon']) # define projection if map_proj == 'LAMBERT': pwrf = '+proj=lcc +lat_1={lat_1} +lat_2={lat_2} ' \ '+lat_0={lat_0} +lon_0={lon_0} ' \ '+x_0=0 +y_0=0 +a=6370000 +b=6370000' pwrf = pwrf.format(**pargs) elif map_proj == 'MERCATOR': pwrf = '+proj=merc +lat_ts={lat_1} +lon_0={lon_0} ' \ '+x_0=0 +y_0=0 +a=6370000 +b=6370000' pwrf = pwrf.format(**pargs) elif map_proj == 'POLAR': pwrf = '+proj=stere +lat_ts={lat_1} +lat_0=90.0 +lon_0={lon_0} ' \ '+x_0=0 +y_0=0 +a=6370000 +b=6370000' pwrf = pwrf.format(**pargs) else: raise NotImplementedError('WRF proj not implemented yet: ' '{}'.format(map_proj)) pwrf = gis.check_crs(pwrf) # get easting and northings from dom center (probably unnecessary here) e, n = pyproj.transform(wgs84, pwrf, pargs['ref_lon'], pargs['lat_0']) # LL corner nx, ny = e_we[0] - 1, e_sn[0] - 1 x0 = -(nx - 1) / 2. * dx + e # -2 because of staggered grid y0 = -(ny - 1) / 2. * dy + n # parent grid grid = gis.Grid(nxny=(nx, ny), x0y0=(x0, y0), dxdy=(dx, dy), proj=pwrf) # child grids out = [grid] for ips, jps, pid, ratio, we, sn in zip(i_parent_start, j_parent_start, parent_id, parent_ratio, e_we, e_sn): if ips == 1: continue ips -= 1 jps -= 1 we -= 1 sn -= 1 nx = we / ratio ny = sn / ratio if nx != (we / ratio): raise RuntimeError('e_we and ratios are incompatible: ' '(e_we - 1) / ratio must be integer!') if ny != (sn / ratio): raise RuntimeError('e_sn and ratios are incompatible: ' '(e_sn - 1) / ratio must be integer!') prevgrid = out[pid - 1] xx, yy = prevgrid.corner_grid.x_coord, prevgrid.corner_grid.y_coord dx = prevgrid.dx / ratio dy = prevgrid.dy / ratio grid = gis.Grid(nxny=(we, sn), x0y0=(xx[ips], yy[jps]), dxdy=(dx, dy), pixel_ref='corner', proj=pwrf) out.append(grid.center_grid) maps = None if do_maps: from salem import Map import shapely.geometry as shpg if map_kwargs is None: map_kwargs = {} maps = [] for i, g in enumerate(out): m = Map(g, **map_kwargs) for j in range(i + 1, len(out)): cg = out[j] left, right, bottom, top = cg.extent s = np.array([(left, bottom), (right, bottom), (right, top), (left, top)]) l1 = shpg.LinearRing(s) m.set_geometry(l1, crs=cg.proj, linewidth=(len(out) - j), zorder=5) maps.append(m) return out, maps
def geogrid_simulator(fpath, do_maps=True): """Emulates geogrid.exe, which is useful when defining new WRF domains. Parameters ---------- fpath: str path to a namelist.wps file do_maps: bool if you want the simulator to return you maps of the grids as well Returns ------- (grids, maps) with: - grids: a list of Grids corresponding to the domains defined in the namelist - maps: a list of maps corresponding to the grids (if do_maps==True) """ with open(fpath) as f: lines = f.readlines() pargs = dict() for l in lines: s = l.split('=') if len(s) < 2: continue s0 = s[0].strip().upper() s1 = list(filter(None, s[1].strip().replace('\n', '').split(','))) if s0 == 'PARENT_ID': parent_id = [int(s) for s in s1] if s0 == 'PARENT_GRID_RATIO': parent_ratio = [int(s) for s in s1] if s0 == 'I_PARENT_START': i_parent_start = [int(s) for s in s1] if s0 == 'J_PARENT_START': j_parent_start = [int(s) for s in s1] if s0 == 'E_WE': e_we = [int(s) for s in s1] if s0 == 'E_SN': e_sn = [int(s) for s in s1] if s0 == 'DX': dx = float(s1[0]) if s0 == 'DY': dy = float(s1[0]) if s0 == 'MAP_PROJ': map_proj = s1[0].replace("'", '').strip().upper() if s0 == 'REF_LAT': pargs['lat_0'] = float(s1[0]) if s0 == 'REF_LON': pargs['lon_0'] = float(s1[0]) if s0 == 'TRUELAT1': pargs['lat_1'] = float(s1[0]) if s0 == 'TRUELAT2': pargs['lat_2'] = float(s1[0]) # define projection if map_proj == 'LAMBERT': pwrf = '+proj=lcc +lat_1={lat_1} +lat_2={lat_2} ' \ '+lat_0={lat_0} +lon_0={lon_0} ' \ '+x_0=0 +y_0=0 +a=6370000 +b=6370000' pwrf = pwrf.format(**pargs) elif map_proj == 'MERCATOR': pwrf = '+proj=merc +lat_ts={lat_1} ' \ '+lon_0={lon_0} ' \ '+x_0=0 +y_0=0 +a=6370000 +b=6370000' pwrf = pwrf.format(**pargs) else: raise NotImplementedError('WRF proj not implemented yet: ' '{}'.format(map_proj)) pwrf = gis.check_crs(pwrf) # get easting and northings from dom center (probably unnecessary here) e, n = pyproj.transform(wgs84, pwrf, pargs['lon_0'], pargs['lat_0']) # LL corner nx, ny = e_we[0]-1, e_sn[0]-1 x0 = -(nx-1) / 2. * dx + e # -2 because of staggered grid y0 = -(ny-1) / 2. * dy + n # parent grid grid = gis.Grid(nxny=(nx, ny), ll_corner=(x0, y0), dxdy=(dx, dy), proj=pwrf) # child grids out = [grid] for ips, jps, pid, ratio, we, sn in zip(i_parent_start, j_parent_start, parent_id, parent_ratio, e_we, e_sn): if ips == 1: continue ips -= 1 jps -= 1 we -= 1 sn -= 1 nx = we / ratio ny = sn / ratio if nx != (we / ratio): raise RuntimeError('e_we and ratios are incompatible: ' '(e_we - 1) / ratio must be integer!') if ny != (sn / ratio): raise RuntimeError('e_sn and ratios are incompatible: ' '(e_sn - 1) / ratio must be integer!') prevgrid = out[pid - 1] xx, yy = prevgrid.corner_grid.x_coord, prevgrid.corner_grid.y_coord dx = prevgrid.dx / ratio dy = prevgrid.dy / ratio grid = gis.Grid(nxny=(we, sn), ll_corner=(xx[ips], yy[jps]), dxdy=(dx, dy), pixel_ref='corner', proj=pwrf) out.append(grid.center_grid) maps = None if do_maps: from salem import Map import shapely.geometry as shpg maps = [] for i, g in enumerate(out): m = Map(g) for j in range(i+1, len(out)): cg = out[j] left, right, bottom, top = cg.extent s = np.array([(left, bottom), (right, bottom), (right, top), (left, top)]) l1 = shpg.LinearRing(s) m.set_geometry(l1, crs=cg.proj, linewidth=(len(out)-j)) maps.append(m) return out, maps