Exemplo n.º 1
0
def main():
    parser = get_parser()
    args = parser.parse_args()

    grid_name = args.grid_name
    clon = args.center_longitude
    clat = args.center_latitude
    pixel_size_x = args.pixel_size_x
    pixel_size_y = args.pixel_size_y
    if pixel_size_y > 0 and not args.dont_touch_ysize: pixel_size_y *= -1
    grid_width = args.grid_width
    grid_height = args.grid_height

    if clon < -180 or clon > 180:
        print "ERROR: Center longitude must be between -180 and 180 degrees"
        return -1
    if clat < -90 or clat > 90:
        print "ERROR: Center latitude must be between -90 and 90 degrees"
        return -1

    proj_str = determine_projection(clon, clat, args.proj_str)
    p = Proj(proj_str)
    origin_x = p(clon, clat)[0] + (grid_width / 2.0 * pixel_size_x * -1)
    origin_y = p(clon, clat)[1] + (grid_height / 2.0 * pixel_size_y * -1)
    if p.is_latlong():
        # Origin is in degrees so we need to add a unit string to it
        origin_x = "%0.3fdeg" % origin_x
        origin_y = "%0.3fdeg" % origin_y
    else:
        origin_lon, origin_lat = p(origin_x, origin_y, inverse=True)
        origin_x = "%0.3fdeg" % origin_lon
        origin_y = "%0.3fdeg" % origin_lat

    valid_config_line = CONFIG_LINE_FORMAT % {
        "grid_name": grid_name,
        "proj4_str": proj_str,
        "origin_x": origin_x,
        "origin_y": origin_y,
        "pixel_size_x": pixel_size_x,
        "pixel_size_y": pixel_size_y,
        "width": grid_width,
        "height": grid_height,
    }
    print valid_config_line
Exemplo n.º 2
0
def main():
    parser = get_parser()
    args = parser.parse_args()

    grid_name = args.grid_name
    clon = args.center_longitude
    clat = args.center_latitude
    pixel_size_x = args.pixel_size_x
    pixel_size_y = args.pixel_size_y
    if pixel_size_y > 0 and not args.dont_touch_ysize: pixel_size_y *= -1
    grid_width = args.grid_width
    grid_height = args.grid_height

    if clon < -180 or clon > 180:
        print("ERROR: Center longitude must be between -180 and 180 degrees")
        return -1
    if clat < -90 or clat > 90:
        print("ERROR: Center latitude must be between -90 and 90 degrees")
        return -1

    proj_str = determine_projection(clon, clat, args.proj_str)
    p = Proj(proj_str)
    origin_x = p(clon, clat)[0] + (grid_width / 2.0 * pixel_size_x * -1)
    origin_y = p(clon, clat)[1] + (grid_height / 2.0 * pixel_size_y * -1)
    if p.is_latlong():
        # Origin is in degrees so we need to add a unit string to it
        origin_x = "%0.5fdeg" % origin_x
        origin_y = "%0.5fdeg" % origin_y
    else:
        origin_lon, origin_lat = p(origin_x, origin_y, inverse=True)
        origin_x = "%0.5fdeg" % origin_lon
        origin_y = "%0.5fdeg" % origin_lat

    valid_config_line = CONFIG_LINE_FORMAT % {
            "grid_name": grid_name,
            "proj4_str": proj_str,
            "origin_x": origin_x,
            "origin_y": origin_y,
            "pixel_size_x": pixel_size_x,
            "pixel_size_y": pixel_size_y,
            "width": grid_width,
            "height": grid_height,
            }
    print(valid_config_line)
Exemplo n.º 3
0
 def cell_width_meters(self):
     """Estimation of what a latlong cell width would be in meters.
     """
     proj4_dict = self.proj4_dict
     lon0 = proj4_dict.get("lon0", 0.0)
     lat0 = proj4_dict.get("lat0", 0.0)
     p = Proj("+proj=eqc +lon0=%f +lat0=%f" % (lon0, lat0))
     x0, y0 = p(lon0, lat0)
     x1, y1 = p(lon0 + self["cell_width"], lat0)
     return abs(x1 - x0)
Exemplo n.º 4
0
def create_nav_binaries(lon_fn,
                        lat_fn,
                        proj4_str,
                        width,
                        height,
                        origin_x,
                        origin_y,
                        x_psize,
                        y_psize,
                        psize_radians=False):
    """Create longitude and latitude binaries from the projection definition
    provided.
    """
    p = Proj(proj4_str)

    # Open the files and a memory mapped array
    lon_file = numpy.memmap(lon_fn,
                            dtype=numpy.float32,
                            mode="w+",
                            shape=(abs(height), abs(width)))
    lat_file = numpy.memmap(lat_fn,
                            dtype=numpy.float32,
                            mode="w+",
                            shape=(abs(height), abs(width)))

    cols = numpy.arange(width)
    for row in range(height):
        grid_x = cols * x_psize + origin_x
        grid_y = numpy.repeat(row * y_psize + origin_y, width)
        if "longlat" in proj4_str and not psize_radians:
            lon_file[row] = grid_x[:]
            lat_file[row] = grid_y[:]
        else:
            lons, lats = p(grid_x, grid_y, inverse=True)
            lon_file[row] = lons[:]
            lat_file[row] = lats[:]
Exemplo n.º 5
0
 def proj(self):
     if self.p is None:
         self.p = Proj(self["proj4_definition"])
     return self.p
Exemplo n.º 6
0
def parse_proj4_config_line(grid_name, parts):
    """Return a dictionary of information for a specific PROJ.4 grid from
    a grid configuration line. ``parts`` should be every comma-separated
    part of the line including the ``grid_name``.
    """
    info = {}

    proj4_str = parts[2]
    # Test to make sure the proj4_str is valid in pyproj's eyes
    try:
        p = Proj(proj4_str)
        del p
    except StandardError:
        LOG.error("Invalid proj4 string in '%s' : '%s'" % (grid_name, proj4_str))
        raise

    # Some parts can be None, but not all
    try:
        static = True
        if parts[3] == "None" or parts[3] == "":
            static = False
            grid_width = None
        else:
            grid_width = int(parts[3])

        if parts[4] == "None" or parts[4] == "":
            static = False
            grid_height = None
        else:
            grid_height = int(parts[4])

        if parts[5] == "None" or parts[5] == "":
            LOG.warning("Grid '%s' may not process properly due to unspecified pixel size", grid_name)
            static = False
            pixel_size_x = None
        else:
            pixel_size_x = float(parts[5])

        if parts[6] == "None" or parts[6] == "":
            LOG.warning("Grid '%s' may not process properly due to unspecified pixel size", grid_name)
            static = False
            pixel_size_y = None
        else:
            pixel_size_y = float(parts[6])

        convert_xorigin_to_meters = False
        if parts[7] == "None" or parts[7] == "":
            static = False
            grid_origin_x = None
        else:
            grid_origin_x, convert_xorigin_to_meters = _parse_meter_degree_param(parts[7])

        convert_yorigin_to_meters = False
        if parts[8] == "None" or parts[8] == "":
            static = False
            grid_origin_y = None
        else:
            grid_origin_y, convert_yorigin_to_meters = _parse_meter_degree_param(parts[8])
    except StandardError:
        LOG.error("Could not parse proj4 grid configuration: '%s'" % (grid_name,))
        raise

    if (pixel_size_x is None and pixel_size_y is not None) or (pixel_size_x is not None and pixel_size_y is None):
        LOG.error("Both or neither pixel sizes must be specified for '%s'" % grid_name)
        raise ValueError("Both or neither pixel sizes must be specified for '%s'" % grid_name)
    if (grid_width is None and grid_height is not None) or (grid_width is not None and grid_height is None):
        LOG.error("Both or neither grid sizes must be specified for '%s'" % grid_name)
        raise ValueError("Both or neither grid sizes must be specified for '%s'" % grid_name)
    if (grid_origin_x is None and grid_origin_y is not None) or (grid_origin_x is not None and grid_origin_y is None):
        LOG.error("Both or neither grid origins must be specified for '%s'" % grid_name)
        raise ValueError("Both or neither grid origins must be specified for '%s'" % grid_name)
    if grid_width is None and pixel_size_x is None:
        LOG.error("Either grid size or pixel size must be specified for '%s'" % grid_name)
        raise ValueError("Either grid size or pixel size must be specified for '%s'" % grid_name)
    if convert_xorigin_to_meters != convert_yorigin_to_meters:
        LOG.error("Grid origin parameters must be in the same units (meters vs degrees)")
        raise ValueError("Grid origin parameters must be in the same units (meters vs degrees)")

    # Convert any parameters from degrees to meters (we already made sure both need to be converted above)
    p = Proj(proj4_str)
    if convert_xorigin_to_meters and not p.is_latlong():
        meters_x, meters_y = p(grid_origin_x, grid_origin_y)
        LOG.debug(
            "Converted grid '%s' origin from (lon: %f, lat: %f) to (x: %f, y: %f)",
            grid_name,
            grid_origin_x,
            grid_origin_y,
            meters_x,
            meters_y,
        )
        grid_origin_x, grid_origin_y = meters_x, meters_y
    elif not convert_xorigin_to_meters and (grid_origin_x is not None and p.is_latlong()):
        LOG.error("Lat/Lon grid '%s' must have its origin in degrees", grid_name)
        raise ValueError("Lat/Lon grid '%s' must have its origin in degrees" % (grid_name,))

    proj4_dict = get_proj4_info(proj4_str)

    info.update(**proj4_dict)
    info["grid_kind"] = "proj4"
    info["static"] = static
    info["proj4_str"] = proj4_str
    info["pixel_size_x"] = pixel_size_x
    info["pixel_size_y"] = pixel_size_y
    info["grid_origin_x"] = grid_origin_x
    info["grid_origin_y"] = grid_origin_y
    info["grid_width"] = grid_width
    info["grid_height"] = grid_height

    return info
Exemplo n.º 7
0
def parse_proj4_config_line(grid_name, parts):
    """Return a dictionary of information for a specific PROJ.4 grid from
    a grid configuration line. ``parts`` should be every comma-separated
    part of the line including the ``grid_name``.
    """
    info = {}

    proj4_str = parts[2]
    # Test to make sure the proj4_str is valid in pyproj's eyes
    try:
        p = Proj(proj4_str)
        del p
    except ValueError:
        LOG.error("Invalid proj4 string in '%s' : '%s'" % (grid_name, proj4_str))
        raise

    # Some parts can be None, but not all
    try:
        static = True
        if parts[3] == "None" or parts[3] == '':
            static = False
            grid_width = None
        else:
            grid_width = int(parts[3])

        if parts[4] == "None" or parts[4] == '':
            static = False
            grid_height = None
        else:
            grid_height = int(parts[4])

        if parts[5] == "None" or parts[5] == '':
            LOG.warning("Grid '%s' may not process properly due to unspecified pixel size", grid_name)
            static = False
            pixel_size_x = None
        else:
            pixel_size_x = float(parts[5])

        if parts[6] == "None" or parts[6] == '':
            LOG.warning("Grid '%s' may not process properly due to unspecified pixel size", grid_name)
            static = False
            pixel_size_y = None
        else:
            pixel_size_y = float(parts[6])

        convert_xorigin_to_meters = False
        if parts[7] == "None" or parts[7] == '':
            static = False
            grid_origin_x = None
        else:
            grid_origin_x, convert_xorigin_to_meters = _parse_meter_degree_param(parts[7])

        convert_yorigin_to_meters = False
        if parts[8] == "None" or parts[8] == '':
            static = False
            grid_origin_y = None
        else:
            grid_origin_y, convert_yorigin_to_meters = _parse_meter_degree_param(parts[8])
    except ValueError:
        LOG.error("Could not parse proj4 grid configuration: '%s'" % (grid_name,))
        raise

    if (pixel_size_x is None and pixel_size_y is not None) or \
            (pixel_size_x is not None and pixel_size_y is None):
        LOG.error("Both or neither pixel sizes must be specified for '%s'" % grid_name)
        raise ValueError("Both or neither pixel sizes must be specified for '%s'" % grid_name)
    if (grid_width is None and grid_height is not None) or \
            (grid_width is not None and grid_height is None):
        LOG.error("Both or neither grid sizes must be specified for '%s'" % grid_name)
        raise ValueError("Both or neither grid sizes must be specified for '%s'" % grid_name)
    if (grid_origin_x is None and grid_origin_y is not None) or \
            (grid_origin_x is not None and grid_origin_y is None):
        LOG.error("Both or neither grid origins must be specified for '%s'" % grid_name)
        raise ValueError("Both or neither grid origins must be specified for '%s'" % grid_name)
    if grid_width is None and pixel_size_x is None:
        LOG.error("Either grid size or pixel size must be specified for '%s'" % grid_name)
        raise ValueError("Either grid size or pixel size must be specified for '%s'" % grid_name)
    if convert_xorigin_to_meters != convert_yorigin_to_meters:
        LOG.error("Grid origin parameters must be in the same units (meters vs degrees)")
        raise ValueError("Grid origin parameters must be in the same units (meters vs degrees)")

    # Convert any parameters from degrees to meters (we already made sure both need to be converted above)
    p = Proj(proj4_str)
    if convert_xorigin_to_meters and not p.is_latlong():
        meters_x, meters_y = p(grid_origin_x, grid_origin_y)
        LOG.debug("Converted grid '%s' origin from (lon: %f, lat: %f) to (x: %f, y: %f)",
                  grid_name, grid_origin_x, grid_origin_y, meters_x, meters_y)
        grid_origin_x, grid_origin_y = meters_x, meters_y
    elif not convert_xorigin_to_meters and (grid_origin_x is not None and p.is_latlong()):
        LOG.error("Lat/Lon grid '%s' must have its origin in degrees", grid_name)
        raise ValueError("Lat/Lon grid '%s' must have its origin in degrees" % (grid_name,))

    proj4_dict = get_proj4_info(proj4_str)

    info.update(**proj4_dict)
    info["grid_kind"] = "proj4"
    info["static"] = static
    info["proj4_str"] = proj4_str
    info["pixel_size_x"] = pixel_size_x
    info["pixel_size_y"] = pixel_size_y
    info["grid_origin_x"] = grid_origin_x
    info["grid_origin_y"] = grid_origin_y
    info["grid_width"] = grid_width
    info["grid_height"] = grid_height

    return info
Exemplo n.º 8
0
def python_ll2cr(lon_arr,
                 lat_arr,
                 grid_info,
                 fill_in=numpy.nan,
                 fill_out=None,
                 cols_out=None,
                 rows_out=None):
    """Project longitude and latitude points to column rows in the specified grid.

    :param lon_arr: Numpy array of longitude floats
    :param lat_arr: Numpy array of latitude floats
    :param grid_info: dictionary of grid information (see below)
    :param fill_in: (optional) Fill value for input longitude and latitude arrays (default: NaN)
    :param fill_out: (optional) Fill value for output column and row array (default: `fill_in`)
    :returns: tuple(points_in_grid, cols_out, rows_out)

    The provided grid info must have the following parameters (optional grids mean dynamic):

        - proj4_definition
        - cell_width
        - cell_height
        - width (optional/None)
        - height (optional/None)
        - origin_x (optional/None)
        - origin_y (optional/None)

    Steps taken in this function:

        1. Convert (lon, lat) points to (X, Y) points in the projection space
        2. If grid is missing some parameters (dynamic grid), then fill them in
        3. Convert (X, Y) points to (column, row) points in the grid space
    """
    p = Proj(grid_info["proj4_definition"])
    cw = grid_info["cell_width"]
    ch = grid_info["cell_height"]
    w = grid_info.get("width", None)
    h = grid_info.get("height", None)
    ox = grid_info.get("origin_x", None)
    oy = grid_info.get("origin_y", None)
    is_static = None not in [w, h, ox, oy]
    proj_circum = projection_circumference(p)

    if rows_out is None:
        rows_out = numpy.empty_like(lat_arr)
    if cols_out is None:
        cols_out = numpy.empty_like(lon_arr)
    if fill_out is None:
        fill_out = fill_in

    mask = ~(mask_helper(lon_arr, fill_in) | mask_helper(lat_arr, fill_in))
    x, y = p(lon_arr, lat_arr)
    mask = mask & (x < 1e30) & (y < 1e30)
    # need temporary storage because x and y are might NOT be copies (latlong projections)
    cols_out[:] = numpy.where(mask, x, fill_out)
    rows_out[:] = numpy.where(mask, y, fill_out)
    # we only need the good Xs and Ys from here on out
    x = cols_out[mask]
    y = rows_out[mask]

    if not is_static:
        # fill in grid parameters
        xmin = numpy.nanmin(x)
        xmax = numpy.nanmax(x)
        ymin = numpy.nanmin(y)
        ymax = numpy.nanmax(y)
        # if the data seems to be covering more than 75% of the projection space then the antimeridian is being crossed
        # if proj_circum is None then we can't simply wrap the data around projection, the grid will probably be large
        LOG.debug("Projection circumference: %f", proj_circum)
        if proj_circum is not None and xmax - xmin >= proj_circum * .75:
            old_xmin = xmin
            old_xmax = xmax
            x[x < 0] += proj_circum
            xmin = numpy.nanmin(x)
            xmax = numpy.nanmax(x)
            LOG.debug(
                "Data seems to cross the antimeridian: old_xmin=%f; old_xmax=%f; xmin=%f; xmax=%f",
                old_xmin, old_xmax, xmin, xmax)
        LOG.debug("Xmin=%f; Xmax=%f; Ymin=%f; Ymax=%f", xmin, xmax, ymin, ymax)

        if ox is None:
            # upper-left corner
            ox = grid_info["origin_x"] = float(xmin)
            oy = grid_info["origin_y"] = float(ymax)
            LOG.debug("Dynamic grid origin (%f, %f)", xmin, ymax)
        if w is None:
            w = grid_info["width"] = int(abs((xmax - xmin) / cw))
            h = grid_info["height"] = int(abs((ymax - ymin) / ch))
            LOG.debug(
                "Dynamic grid width and height (%d x %d) with cell width and height (%f x %f)",
                w, h, cw, ch)

    good_cols = (x - ox) / cw
    good_rows = (y - oy) / ch
    cols_out[mask] = good_cols
    rows_out[mask] = good_rows

    points_in_grid = numpy.count_nonzero((good_cols >= -1)
                                         & (good_cols <= w + 1)
                                         & (good_rows >= -1)
                                         & (good_rows <= h + 1))

    return points_in_grid, cols_out, rows_out