Example #1
0
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
Example #2
0
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