Ejemplo n.º 1
0
def flip_quadkey(q, flip):
    lng, lat = quadkey_to_centroid(q)
    z = len(q)
    if flip[0]: lng = -lng
    if flip[1]: lat = -lat
    tile = mercantile.tile(lng, lat, z)
    return mercantile.quadkey(tile)
Ejemplo n.º 2
0
def quadkey(ctx, input):
    """Takes [x, y, z] tiles or quadkeys as input and writes
    quadkeys or a [x, y, z] tiles to stdout, respectively.

    Input may be a compact newline-delimited sequences of JSON or
    a pretty-printed ASCII RS-delimited sequence of JSON (like
    https://tools.ietf.org/html/rfc8142 and
    https://tools.ietf.org/html/rfc7159).

    $ echo "[486, 332, 10]" | mercantile quadkey

    Output:

    0313102310

    $ echo "0313102310" | mercantile quadkey

    Output:

    [486, 332, 10]
    """
    src = normalize_input(input)
    try:
        for line in iter_lines(src):
            if line[0] == '[':
                tile = json.loads(line)[:3]
                output = mercantile.quadkey(tile)
            else:
                tile = mercantile.quadkey_to_tile(line)
                output = json.dumps(tile)
            click.echo(output)
    except ValueError:
        raise click.BadParameter(
            "{0}".format(input), param=input, param_hint='input')
Ejemplo n.º 3
0
    def cl_post_prediction(self, payload: Dict[str, Any], chips: List[dict], prediction_id: str, inferences: List[str]) -> Dict[str, Any]:
        payload = json.dumps(payload)
        r = requests.post(self.prediction_endpoint + ":predict", data=payload)
        r.raise_for_status()

        preds = r.json()["predictions"]
        pred_list = [];

        for i in range(len(chips)):
            pred_dict = {}

            for j in range(len(preds[i])):
                pred_dict[inferences[j]] = preds[i][j]

            body = {
                "geom": shapely.geometry.mapping(box(*chips[i].get('bounds'))),
                "predictions": pred_dict,
                "prediction_id": prediction_id
            }

            if chips[i].get('x') is not None and chips[i].get('y') is not None and chips[i].get('z') is not None:
                body['quadkey'] = mercantile.quadkey(chips[i].get('x'), chips[i].get('y'), chips[i].get('z'))

            pred_list.append(body)

        return {
            "predictionId": prediction_id,
            "predictions": pred_list
        }
Ejemplo n.º 4
0
def quadkey(ctx, input):
    """Takes a [x, y, z] tile or a quadkey as input and writes a
    quadkey or a [x, y, z] tile to stdout, respectively.

    $ echo "[486, 332, 10]" | mercantile quadkey

    Output:

    0313102310

    $ echo "0313102310" | mercantile quadkey

    Output:

    [486, 332, 10]
    """
    src = normalize_input(input)
    try:
        for line in iter_lines(src):
            if line[0] == '[':
                tile = json.loads(line)[:3]
                output = mercantile.quadkey(tile)
            else:
                tile = mercantile.quadkey_to_tile(line)
                output = json.dumps(tile)
            click.echo(output)
    except ValueError:
        raise click.BadParameter("{0}".format(input),
                                 param=input,
                                 param_hint='input')
Ejemplo n.º 5
0
    def polyfill(self, input_gdf, zoom_level):
        check_package('mercantile', is_optional=True)
        import mercantile

        if not hasattr(input_gdf, 'geometry'):
            raise ValueError('This dataframe has no valid geometry.')

        geometry_name = input_gdf.geometry.name

        dfs = []
        for _, row in input_gdf.iterrows():
            input_geometry = row[geometry_name]
            bounds = input_geometry.bounds
            tiles = mercantile.tiles(bounds[0], bounds[1], bounds[2],
                                     bounds[3], zoom_level)
            new_rows = []
            for tile in tiles:
                new_row = row.copy()
                new_geometry = box(*mercantile.bounds(tile))
                if new_geometry.intersects(input_geometry):
                    new_row[geometry_name] = new_geometry
                    new_row['quadkey'] = mercantile.quadkey(tile)
                    new_rows.append(new_row)
            dfs.append(DataFrame(new_rows))

        df = concat(dfs).reset_index(drop=True)

        return GeoDataFrame(df, geometry=geometry_name, crs='epsg:4326')
Ejemplo n.º 6
0
    def cl_post_prediction(self, payload: Dict[str, Any], tiles: List[Tile],
                           prediction_id: str,
                           inferences: List[str]) -> Dict[str, Any]:
        payload = json.dumps(payload)
        r = requests.post(self.prediction_endpoint + ":predict", data=payload)
        r.raise_for_status()

        preds = r.json()["predictions"]
        pred_list = []

        for i in range(len(tiles)):
            pred_dict = {}

            for j in range(len(preds[i])):
                pred_dict[inferences[j]] = preds[i][j]

            pred_list.append({
                "quadkey":
                mercantile.quadkey(tiles[i].x, tiles[i].y, tiles[i].z),
                "predictions":
                pred_dict,
                "prediction_id":
                prediction_id
            })

        return {"predictionId": prediction_id, "predictions": pred_list}
Ejemplo n.º 7
0
def quadkey(ctx, input):
    """Takes a [x, y, z] tile or a quadkey as input and writes a
    quadkey or a [x, y, z] tile to stdout, respectively.

    $ echo "[486, 332, 10]" | mercantile quadkey

    Output:

    0313102310

    $ echo "0313102310" | mercantile quadkey

    Output:

    [486, 332, 10]
    """
    src = normalize_input(input)
    try:
        for line in iter_lines(src):
            if line[0] == '[':
                tile = json.loads(line)[:3]
                output = mercantile.quadkey(tile)
            else:
                tile = mercantile.quadkey_to_tile(line)
                output = json.dumps(tile)
            click.echo(output)
    except ValueError:
        raise click.BadParameter(
            "{0}".format(input), param=input, param_hint='input')
Ejemplo n.º 8
0
def quadkey(ctx, input):
    """Takes [x, y, z] tiles or quadkeys as input and writes
    quadkeys or a [x, y, z] tiles to stdout, respectively.

    Input may be a compact newline-delimited sequences of JSON or
    a pretty-printed ASCII RS-delimited sequence of JSON (like
    https://tools.ietf.org/html/rfc8142 and
    https://tools.ietf.org/html/rfc7159).

    Examples:

    \b
    echo "[486, 332, 10]" | mercantile quadkey
    0313102310

    \b
    echo "0313102310" | mercantile quadkey
    [486, 332, 10]

    """
    src = normalize_input(input)
    try:
        for line in iter_lines(src):
            if line[0] == "[":
                tile = json.loads(line)[:3]
                output = mercantile.quadkey(tile)
            else:
                tile = mercantile.quadkey_to_tile(line)
                output = json.dumps(tile)
            click.echo(output)
    except mercantile.QuadKeyError:
        raise click.BadParameter("{0}".format(input),
                                 param=input,
                                 param_hint="input")
Ejemplo n.º 9
0
def get_assets(url: str, x: int, y: int, z: int) -> Tuple[str]:
    """Get assets."""
    mosaic_def = fetch_mosaic_definition(url)
    min_zoom = mosaic_def["minzoom"]
    max_zoom = mosaic_def["maxzoom"]
    if z > max_zoom or z < min_zoom:
        return []  # return empty asset

    mercator_tile = mercantile.Tile(x=x, y=y, z=z)
    quadkey_zoom = mosaic_def.get("quadkey_zoom", min_zoom)  # 0.0.2

    # get parent
    if mercator_tile.z > quadkey_zoom:
        depth = mercator_tile.z - quadkey_zoom
        for i in range(depth):
            mercator_tile = mercantile.parent(mercator_tile)
        quadkey = [mercantile.quadkey(*mercator_tile)]

    # get child
    elif mercator_tile.z < quadkey_zoom:
        depth = quadkey_zoom - mercator_tile.z
        mercator_tiles = [mercator_tile]
        for i in range(depth):
            mercator_tiles = sum([mercantile.children(t) for t in mercator_tiles], [])

        mercator_tiles = list(filter(lambda t: t.z == quadkey_zoom, mercator_tiles))
        quadkey = [mercantile.quadkey(*tile) for tile in mercator_tiles]
    else:
        quadkey = [mercantile.quadkey(*mercator_tile)]

    assets = list(
        itertools.chain.from_iterable(
            [mosaic_def["tiles"].get(qk, []) for qk in quadkey]
        )
    )

    # check if we have a mosaic in the url (.json/.gz)
    return list(
        itertools.chain.from_iterable(
            [
                get_assets(asset, x, y, z)
                if os.path.splitext(asset)[1] in [".json", ".gz"]
                else [asset]
                for asset in assets
            ]
        )
    )
Ejemplo n.º 10
0
def quadkeys_to_poly(quadkeys):
    quadkeys = sorted(set(quadkeys))
    tiles = [mercantile.quadkey_to_tile(qk) for qk in quadkeys]
    tiles = mercantile.simplify(tiles)
    quadkeys = [mercantile.quadkey(t) for t in tiles]
    polys = quadkeys_to_polys(quadkeys)
    poly = shapely.ops.unary_union(polys)
    return poly
Ejemplo n.º 11
0
def bbox_to_quadkeys(bbox: list, zoom: int):
    """ Find all quadkeys in a bbox """
    tiles = mercantile.tiles(bbox[0], bbox[1], bbox[2], bbox[3], int(zoom))
    quadkeys = []
    for tile in tiles:
        quadkeys.append(mercantile.quadkey(tile))

    return quadkeys
Ejemplo n.º 12
0
def create_tiles_gdf(bounds: List[float],
                     quadkey_zoom: int) -> gpd.GeoDataFrame:
    """Create GeoDataFrame of all tiles within bounds at quadkey_zoom
    """
    features = [
        mercantile.feature(tile, props={'quadkey': mercantile.quadkey(tile)})
        for tile in mercantile.tiles(*bounds, quadkey_zoom)
    ]
    return gpd.GeoDataFrame.from_features(features, crs='EPSG:4326')
Ejemplo n.º 13
0
    def __init__(self, *tile):

        if len(tile) == 1:
            tile = tile[0]
        else:
            tile = Tile(*tile)

        quadkey = mercantile.quadkey(tile)
        self.url_fmt = f'http://t0.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=854&mkt=en-US&token='
Ejemplo n.º 14
0
    def get_tile(self, tile):
    #========================
        surface = skia.Surface(*self.__tile_size)  ## In pixels...
        canvas = surface.getCanvas()
        canvas.clear(skia.Color4f(0xFFFFFFFF))
        canvas.translate(self.__pixel_offset[0] + (self.__tile_origin[0] - tile.x)*self.__tile_size[0],
                         self.__pixel_offset[1] + (self.__tile_origin[1] - tile.y)*self.__tile_size[1])
        quadkey = mercantile.quadkey(tile)
        self.__svg_drawing.draw_element(canvas, self.__tile_bboxes.get(quadkey))

        image = surface.makeImageSnapshot()
        return image.toarray(colorType=skia.kBGRA_8888_ColorType)
Ejemplo n.º 15
0
def find_quadkeys(mercator_tile: mercantile.Tile,
                  quadkey_zoom: int) -> List[str]:
    """
    Find quadkeys at desired zoom for tile

    Attributes
    ----------
    mercator_tile: mercantile.Tile
        Input tile to use when searching for quadkeys
    quadkey_zoom: int
        Zoom level

    Returns
    -------
    list
        List[str] of quadkeys

    """
    # get parent
    if mercator_tile.z > quadkey_zoom:
        depth = mercator_tile.z - quadkey_zoom
        for i in range(depth):
            mercator_tile = mercantile.parent(mercator_tile)
        return [mercantile.quadkey(*mercator_tile)]

    # get child
    elif mercator_tile.z < quadkey_zoom:
        depth = quadkey_zoom - mercator_tile.z
        mercator_tiles = [mercator_tile]
        for i in range(depth):
            mercator_tiles = sum(
                [mercantile.children(t) for t in mercator_tiles], [])

        mercator_tiles = list(
            filter(lambda t: t.z == quadkey_zoom, mercator_tiles))
        return [mercantile.quadkey(*tile) for tile in mercator_tiles]
    else:
        return [mercantile.quadkey(*mercator_tile)]
Ejemplo n.º 16
0
    def __init__(self, raster_layer, tile_set):
        self.__svg = etree.parse(raster_layer.source_data).getroot()
        if 'viewBox' in self.__svg.attrib:
            self.__size = tuple(
                float(x) for x in self.__svg.attrib['viewBox'].split()[2:])
        else:
            self.__size = (length_as_pixels(self.__svg.attrib['width']),
                           length_as_pixels(self.__svg.attrib['height']))
        self.__scaling = (tile_set.pixel_rect.width / self.__size[0],
                          tile_set.pixel_rect.height / self.__size[1])
        self.__definitions = DefinitionStore()
        defs = self.__svg.find(SVG_NS('defs'))
        if defs is not None:
            self.__definitions.add_definitions(defs)
        self.__style_matcher = StyleMatcher(self.__svg.find(SVG_NS('style')))
        self.__first_scan = True

        # Transform from SVG pixels to tile pixels
        transform = Transform([[self.__scaling[0], 0.0, 0.0],
                               [0.0, self.__scaling[1], 0.0], [0.0, 0.0, 1.0]])
        self.__path_list = []
        self.__draw_svg(transform, self.__path_list)

        # Transform from SVG pixels to world coordinates
        self.__image_to_world = (Transform([
            [WORLD_METRES_PER_PIXEL / self.__scaling[0], 0, 0],
            [0, WORLD_METRES_PER_PIXEL / self.__scaling[1], 0], [0, 0, 1]
        ]) @ np.array([[1, 0, -self.__scaling[0] * self.__size[0] / 2.0],
                       [0, -1, self.__scaling[1] * self.__size[1] / 2.0],
                       [0, 0, 1.0]]))

        self.__tile_size = tile_set.tile_size
        self.__tile_origin = tile_set.start_coords
        self.__pixel_offset = tuple(tile_set.pixel_rect)[0:2]
        path_bounding_boxes = [(path, paint,
                                shapely.geometry.box(*tuple(path.getBounds())))
                               for (path, paint) in self.__path_list]
        self.__tile_paths = {}
        for tile in tile_set:
            tile_set.tile_coords_to_pixels.transform_point((tile.x, tile.y))
            x0 = (tile.x - self.__tile_origin[0]
                  ) * self.__tile_size[0] - self.__pixel_offset[0]
            y0 = (tile.y - self.__tile_origin[1]
                  ) * self.__tile_size[1] - self.__pixel_offset[1]
            tile_bbox = shapely.prepared.prep(
                shapely.geometry.box(x0, y0, x0 + self.__tile_size[0],
                                     y0 + self.__tile_size[0]))
            self.__tile_paths[mercantile.quadkey(tile)] = list(
                filter(lambda ppb: tile_bbox.intersects(ppb[2]),
                       path_bounding_boxes))
Ejemplo n.º 17
0
def children(quadkeys, levels=1):
    if not type(quadkeys) is list:
        quadkeys = [
            quadkeys,
        ]
    for level in range(levels):
        childrenKeys = []
        for qk in quadkeys:
            childrenKeys.extend([
                mercantile.quadkey(t) \
                    for t in mercantile.children(mercantile.quadkey_to_tile(qk))
                ])
        quadkeys = childrenKeys
    return quadkeys
Ejemplo n.º 18
0
 def get_tile(self, tile):
     #========================
     surface = skia.Surface(*self.__tile_size)
     canvas = surface.getCanvas()
     canvas.translate(
         self.__pixel_offset[0] +
         (self.__tile_origin[0] - tile.x) * self.__tile_size[0],
         self.__pixel_offset[1] +
         (self.__tile_origin[1] - tile.y) * self.__tile_size[1])
     quadkey = mercantile.quadkey(tile)
     for path, paint, bbox in self.__tile_paths.get(quadkey, []):
         canvas.drawPath(path, paint)
     image = surface.makeImageSnapshot()
     return image.toarray(colorType=skia.kBGRA_8888_ColorType)
Ejemplo n.º 19
0
    def od_post_prediction(self, payload: str, chips: List[dict], prediction_id: str) -> Dict[str, Any]:
        pred_list = [];

        for i in range(len(chips)):
            r = requests.post(self.prediction_endpoint + ":predict", data=json.dumps({
                "instances": [ payload["instances"][i] ]
            }))

            r.raise_for_status()

            # We only post a single chip for od detection
            preds = r.json()["predictions"][0]

            if preds["num_detections"] == 0.0:
                continue

            # Create lists of num_detections length
            scores = preds['detection_scores'][:int(preds["num_detections"])]
            bboxes = preds['detection_boxes'][:int(preds["num_detections"])]

            bboxes_256 = []
            for bbox in bboxes:
                bboxes_256.append([c * 256 for c in bbox])

            for j in range(len(bboxes_256)):
                bbox = geojson.Feature(
                    geometry=self.tf_bbox_geo(bboxes_256[j], chips[i].get('bounds')),
                    properties={}
                ).geometry

                score = preds["detection_scores"][j]

                body = {
                    "geom": bbox,
                    "predictions": {
                        "default": score
                    },
                    "prediction_id": prediction_id
                }

                if chips[i].get('x') is not None and chips[i].get('y') is not None and chips[i].get('z') is not None:
                    body['quadkey'] = mercantile.quadkey(chips[i].get('x'), chips[i].get('y'), chips[i].get('z'))

                pred_list.append(body)

        return {
            "predictionId": prediction_id,
            "predictions": pred_list
        }
Ejemplo n.º 20
0
    def od_post_prediction(self, payload: str, tiles: List[Tile],
                           prediction_id: str) -> Dict[str, Any]:
        pred_list = []

        for i in range(len(tiles)):
            r = requests.post(self.prediction_endpoint + ":predict",
                              data=json.dumps(
                                  {"instances": [payload["instances"][i]]}))

            r.raise_for_status()

            # We only post a single chip for od detection
            preds = r.json()["predictions"][0]

            if preds["num_detections"] == 0.0:
                continue

            # Create lists of num_detections length
            scores = preds['detection_scores'][:int(preds["num_detections"])]
            bboxes = preds['detection_boxes'][:int(preds["num_detections"])]

            bboxes_256 = []
            for bbox in bboxes:
                bboxes_256.append([c * 256 for c in bbox])

            print("BOUND: " + str(len(bboxes_256)) + " for " +
                  str(tiles[i].x) + "/" + str(tiles[i].y) + "/" +
                  str(tiles[i].z))

            for j in range(len(bboxes_256)):
                bbox = geojson.Feature(geometry=self.tf_bbox_geo(
                    bboxes_256[j], tiles[i]),
                                       properties={}).geometry

                score = preds["detection_scores"][j]

                pred_list.append({
                    "quadkey":
                    mercantile.quadkey(tiles[i].x, tiles[i].y, tiles[i].z),
                    "quadkey_geom":
                    bbox,
                    "predictions": {
                        "default": score
                    },
                    "prediction_id":
                    prediction_id
                })

        return {"predictionId": prediction_id, "predictions": pred_list}
Ejemplo n.º 21
0
    def __init__(self, xtile, ytile, zoom, uri=None):
        super(Syncher, self).__init__()
        self.uri = uri or get_uri(xtile, ytile, zoom)
        self.tile = {'x': xtile, 'y': ytile, 'z': zoom}
        tile_bounds = mc.bounds(mc.quadkey_to_tile(mc.quadkey(xtile, ytile, zoom)))
        keys = ('w', 's', 'e', 'n',)
        self.bbox = dict(zip(keys, map(str, (
            tile_bounds.west,
            tile_bounds.south,
            tile_bounds.east,
            tile_bounds.north,
        )))) # minx, miny, maxx, maxy

        self.base_query = {
            'query': [[{"k": "qwertyuiop", "modv": "not", "regv": "."}]],
            'bbox': self.bbox,
            'gtypes': ['node', 'way', 'relation'],
        }
Ejemplo n.º 22
0
    def __init__(self, raster_layer, tile_set):
        self.__bbox = shapely.geometry.box(*extent_to_bounds(raster_layer.extent))
        self.__svg = etree.parse(raster_layer.source_data).getroot()
        self.__source = raster_layer.source_params.get('source')
        if 'viewBox' in self.__svg.attrib:
            self.__size = tuple(float(x)
                for x in self.__svg.attrib['viewBox'].split()[2:])
        else:
            self.__size = (length_as_pixels(self.__svg.attrib['width']),
                           length_as_pixels(self.__svg.attrib['height']))
        self.__scaling = (tile_set.pixel_rect.width/self.__size[0],
                          tile_set.pixel_rect.height/self.__size[1])
        self.__definitions = DefinitionStore()
        self.__style_matcher = StyleMatcher(self.__svg.find(SVG_NS('style')))
        self.__clip_paths = ObjectStore()

        # Transform from SVG pixels to tile pixels
        svg_to_tile_transform = Transform([[self.__scaling[0],               0.0, 0.0],
                                           [              0.0, self.__scaling[1], 0.0],
                                           [              0.0,               0.0, 1.0]])
        self.__svg_drawing = self.__draw_svg(svg_to_tile_transform)

        # Transform from SVG pixels to world coordinates
        self.__image_to_world = (Transform([
            [WORLD_METRES_PER_PIXEL/self.__scaling[0],                                        0, 0],
            [                                       0, WORLD_METRES_PER_PIXEL/self.__scaling[1], 0],
            [                                       0,                                        0, 1]])
           @np.array([[1,  0, -self.__scaling[0]*self.__size[0]/2.0],
                      [0, -1,  self.__scaling[1]*self.__size[1]/2.0],
                      [0,  0,                                               1.0]]))

        self.__tile_size = tile_set.tile_size
        self.__tile_origin = tile_set.start_coords
        self.__pixel_offset = tuple(tile_set.pixel_rect)[0:2]

        self.__tile_bboxes = {}
        for tile in tile_set:
            tile_set.tile_coords_to_pixels.transform_point((tile.x, tile.y))
            x0 = (tile.x - self.__tile_origin[0])*self.__tile_size[0] - self.__pixel_offset[0]
            y0 = (tile.y - self.__tile_origin[1])*self.__tile_size[1] - self.__pixel_offset[1]
            tile_bbox = shapely.geometry.box(x0, y0,
                                                                   x0 + self.__tile_size[0],
                                                                   y0 + self.__tile_size[0])
            self.__tile_bboxes[mercantile.quadkey(tile)] = tile_bbox
    def save_to_db(self, tiles:List[Tile], results:List[Any], result_wrapper:Optional[Callable]=None) -> None:
        db = urlparse(self.db)

        conn = pg8000.connect(
          user=db.username,
          password=db.password,
          host=db.hostname,
          database=db.path[1:],
          port=db.port
        )
        cursor = conn.cursor()

        for i, output in enumerate(results):
            quadkey = quadkey(tiles[i])
            # centroid = db.Column(Geometry('POINT', srid=4326))
            predictions = pg8000.PGJsonb(output)
            cursor.execute("INSERT INTO mlenabler VALUES (null, %s, %s, %s) ON CONFLICT (id) DO UPDATE SET output = %s", (self.prediction_id, quadkey, predictions, predictions))

        conn.commit()
        conn.close()
Ejemplo n.º 24
0
def soil_hi():
    with open('E:/project_use/geodata/soil_liq_hi.txt', 'r',
              encoding='utf-8') as f:
        t = json.load(f)
    '''把所有的物件只挑要的撈出來,另存成item'''
    item1 = []
    for iii, it in enumerate(t['features']):
        area = it['properties']['area']
        grade = it['properties']['分級']
        codi = []
        for jjj, it1 in enumerate(it['geometry']['coordinates']):
            for kkk, it2 in enumerate(it1):
                long = it2[0]
                lat = it2[1]
                codi.append((long, lat))
        js = {'area': area, 'grade': grade, 'coodinates': codi}
        item1.append(js)
    # print(item)
    '''將經緯度轉換成quadkey值並存進原本的dict'''
    for mmm, each in enumerate(item1):
        each_tiles = []
        for nnn, each_pt in enumerate(each['coodinates']):
            zoom_num = 16
            aaa = mercantile.tile(each_pt[0], each_pt[1], zoom_num)
            each_tiles.append(aaa)
    #     print(list(set(each_tiles)))
        each_tile = list(set(each_tiles))
        each_quad = []
        for o in range(len(each_tile)):
            b = mercantile.quadkey(each_tile[o])
            each_quad.append(b)
        each['quad'] = each_quad
    '''把最終高潛勢的quadkey值append成一個list'''
    level_hi_quad = []
    for ppp in range(len(item1)):
        each_quads = item1[ppp]['quad']
        for rrr in range(len(each_quads)):
            ccc = each_quads[rrr]
            level_hi_quad.append(ccc)
    set(level_hi_quad)
    return list(set(level_hi_quad))
Ejemplo n.º 25
0
def missing_quadkeys(mosaic: Dict,
                     shp_path: str,
                     bounds: List[float] = None,
                     simplify: bool = True) -> Dict:
    """Find quadkeys over land missing from mosaic

    Args:
        - mosaic: mosaic definition
        - shp_path: path to Natural Earth shapefile of land boundaries
        - bounds: force given bounds
        - simplify: reduce size of the tileset as much as possible by merging leaves into parents

    Returns:
        - GeoJSON FeatureCollection of missing tiles
    """
    bounds = bounds or mosaic['bounds']
    top_tile = mercantile.bounding_tile(*bounds)
    gdf = gpd.read_file(shp_path)
    quadkey_zoom = mosaic.get('quadkey_zoom', mosaic['minzoom'])

    # Remove null island
    # Keep the landmasses that are visible at given zoom
    gdf = gdf[gdf['max_zoom'] <= quadkey_zoom]

    land_tiles = find_child_land_tiles(top_tile, gdf, quadkey_zoom)
    quadkeys = {mercantile.quadkey(tile) for tile in land_tiles}

    mosaic_quadkeys = set(mosaic['tiles'].keys())
    not_in_mosaic = quadkeys.difference(mosaic_quadkeys)
    not_in_mosaic = [mercantile.quadkey_to_tile(qk) for qk in not_in_mosaic]

    if simplify:
        not_in_mosaic = mercantile.simplify(not_in_mosaic)

    features = [mercantile.feature(tile) for tile in not_in_mosaic]

    return {'type': 'FeatureCollection', 'features': features}
Ejemplo n.º 26
0
def lnglat_to_Num(lon, lat, zoom):
    try:
        lat_deg = float(lat)
        lon_deg = float(lon)

        lat_rad = math.radians(lat_deg)
        n = 2.0**zoom
        xtile = int((lon_deg + 180.0) / 360.0 * n)
        ytile = int(
            (1.0 - math.log(math.tan(lat_rad) +
                            (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
        qk = mercantile.quadkey(xtile, ytile, zoom)

        number = 0
        for i, digit in enumerate(qk):
            number |= int(digit)
            if i != len(qk) - 1:
                number = number << 2

        return number

    except ValueError, e:
        print "error", e
        return None
Ejemplo n.º 27
0
    def _create_mosaic(
        cls,
        features: Sequence[Dict],
        minzoom: int,
        maxzoom: int,
        quadkey_zoom: Optional[int] = None,
        accessor: Callable[[Dict], str] = default_accessor,
        asset_filter: Callable = default_filter,
        version: str = "0.0.2",
        quiet: bool = True,
        **kwargs,
    ):
        """Create mosaic definition content.

        Attributes:
            features (list): List of GeoJSON features.
            minzoom (int): Force mosaic min-zoom.
            maxzoom (int): Force mosaic max-zoom.
            quadkey_zoom (int): Force mosaic quadkey zoom (optional).
            accessor (callable): Function called on each feature to get its identifier (default is feature["properties"]["path"]).
            asset_filter (callable):  Function to filter features.
            version (str): mosaicJSON definition version (default: 0.0.2).
            quiet (bool): Mask processing steps (default is True).
            kwargs (any): Options forwarded to `asset_filter`

        Returns:
            mosaic_definition (MosaicJSON): Mosaic definition.

        Examples:
            >>> MosaicJSON._create_mosaic([], 12, 14)

        """
        quadkey_zoom = quadkey_zoom or minzoom

        if not quiet:
            click.echo(f"Get quadkey list for zoom: {quadkey_zoom}", err=True)

        # If Pygeos throws an error, fall back to non-vectorized operation
        # Ref: https://github.com/developmentseed/cogeo-mosaic/issues/81
        try:
            dataset_geoms = polygons(
                [feat["geometry"]["coordinates"][0] for feat in features]
            )
        except TypeError:
            dataset_geoms = [
                polygons(feat["geometry"]["coordinates"][0]) for feat in features
            ]

        bounds = tuple(total_bounds(dataset_geoms))

        tiles = burntiles.burn(features, quadkey_zoom)
        tiles = [mercantile.Tile(*tile) for tile in tiles]

        mosaic_definition: Dict[str, Any] = dict(
            mosaicjson=version,
            minzoom=minzoom,
            maxzoom=maxzoom,
            quadkey_zoom=quadkey_zoom,
            bounds=bounds,
            center=((bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2, minzoom),
            tiles={},
            version="1.0.0",
        )

        if not quiet:
            click.echo("Feed Quadkey index", err=True)

        # Create tree and find assets that overlap each tile
        tree = STRtree(dataset_geoms)

        fout = os.devnull if quiet else sys.stderr
        with click.progressbar(  # type: ignore
            tiles, file=fout, show_percent=True, label="Iterate over quadkeys"
        ) as bar:
            for tile in bar:
                quadkey = mercantile.quadkey(tile)
                tile_geom = polygons(
                    mercantile.feature(tile)["geometry"]["coordinates"][0]
                )

                # Find intersections from rtree
                intersections_idx = sorted(
                    tree.query(tile_geom, predicate="intersects")
                )
                if len(intersections_idx) == 0:
                    continue

                intersect_dataset, intersect_geoms = zip(
                    *[(features[idx], dataset_geoms[idx]) for idx in intersections_idx]
                )

                dataset = asset_filter(
                    tile, intersect_dataset, intersect_geoms, **kwargs
                )

                if dataset:
                    mosaic_definition["tiles"][quadkey] = [accessor(f) for f in dataset]

        return cls(**mosaic_definition)
Ejemplo n.º 28
0
def stac_to_mosaicJSON(
    query: Dict,
    minzoom: int = 7,
    maxzoom: int = 12,
    optimized_selection: bool = True,
    maximum_items_per_tile: int = 20,
    stac_collection_limit: int = 500,
    seasons: Tuple = ["spring", "summer", "autumn", "winter"],
    stac_url: str = os.environ.get("SATAPI_URL",
                                   "https://sat-api.developmentseed.org"),
) -> Dict:
    """
    Create a mosaicJSON from a stac request.

    Attributes
    ----------
    query : str
        sat-api query.
    minzoom : int, optional, (default: 7)
        Mosaic Min Zoom.
    maxzoom : int, optional (default: 12)
        Mosaic Max Zoom.
    optimized_selection : bool, optional (default: true)
        Limit one Path-Row scene per quadkey.
    maximum_items_per_tile : int, optional (default: 20)
        Limit number of scene per quadkey. Use 0 to use all items.
    stac_collection_limit : int, optional (default: None)
        Limits the number of items returned by sat-api
    stac_url : str, optional (default: from ENV)

    Returns
    -------
    out : dict
        MosaicJSON definition.

    """
    if stac_collection_limit:
        query.update(limit=stac_collection_limit)

    logger.debug(json.dumps(query))

    def fetch_sat_api(query):
        headers = {
            "Content-Type": "application/json",
            "Accept-Encoding": "gzip",
            "Accept": "application/geo+json",
        }

        url = f"{stac_url}/stac/search"
        data = requests.post(url, headers=headers, json=query).json()
        error = data.get("message", "")
        if error:
            raise Exception(f"SAT-API failed and returned: {error}")

        meta = data.get("meta", {})
        if not meta.get("found"):
            return []

        logger.debug(json.dumps(meta))

        features = data["features"]
        if data["links"]:
            curr_page = int(meta["page"])
            query["page"] = curr_page + 1
            query["limit"] = meta["limit"]

            features = list(itertools.chain(features, fetch_sat_api(query)))

        return features

    features = fetch_sat_api(query)
    if not features:
        raise Exception(f"No asset found for query '{json.dumps(query)}'")

    logger.debug(f"Found: {len(features)} scenes")

    features = list(
        filter(
            lambda x: _get_season(x["properties"]["datetime"],
                                  max(x["bbox"][1], x["bbox"][3])) in seasons,
            features,
        ))

    if optimized_selection:
        dataset = []
        prs = []
        for item in features:
            pr = item["properties"]["eo:column"] + "-" + item["properties"][
                "eo:row"]
            if pr not in prs:
                prs.append(pr)
                dataset.append(item)
    else:
        dataset = features

    if query.get("bbox"):
        bounds = query["bbox"]
    else:
        bounds = burntiles.find_extrema(dataset)

    for i in range(len(dataset)):
        dataset[i]["geometry"] = shape(dataset[i]["geometry"])

    tiles = burntiles.burn([bbox_to_geojson(bounds)], minzoom)
    tiles = list(set(["{2}-{0}-{1}".format(*tile.tolist()) for tile in tiles]))

    logger.debug(f"Number tiles: {len(tiles)}")

    mosaic_definition = dict(
        mosaicjson="0.0.1",
        minzoom=minzoom,
        maxzoom=maxzoom,
        bounds=bounds,
        center=[(bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2,
                minzoom],
        tiles={},
    )

    for tile in tiles:
        z, x, y = list(map(int, tile.split("-")))
        tile = mercantile.Tile(x=x, y=y, z=z)
        quadkey = mercantile.quadkey(*tile)
        geometry = box(*mercantile.bounds(tile))
        intersect_dataset = list(
            filter(lambda x: geometry.intersects(x["geometry"]), dataset))
        if len(intersect_dataset):
            # We limit the item per quadkey to 20
            if maximum_items_per_tile:
                intersect_dataset = intersect_dataset[0:maximum_items_per_tile]

            mosaic_definition["tiles"][quadkey] = [
                scene["properties"]["landsat:product_id"]
                for scene in intersect_dataset
            ]

    return mosaic_definition
Ejemplo n.º 29
0
def point_to_polygon(point, zoom):
    tile = mercantile.tile(*np.array(point), zoom)
    quadkey = mercantile.quadkey(tile)
    poly = quadkey_to_poly(quadkey)
    return poly
Ejemplo n.º 30
0
def get_quadkeys(totalBounds, zoom):
    allTiles = mercantile.tiles(*totalBounds, zoom)
    for tile in allTiles:
        yield mercantile.quadkey(tile)
Ejemplo n.º 31
0
def test_quadkey():
    tile = mercantile.Tile(486, 332, 10)
    expected = "0313102310"
    assert mercantile.quadkey(tile) == expected
Ejemplo n.º 32
0
    def do_GET(self):
        url = urlparse(self.path)

        if url.path == '/tile':

            query_components = parse_qs(urlparse(self.path).query)
            dataset = query_components["dataset"][0]
            level = query_components["level"][0]
            x = query_components["x"][0]
            y = query_components["y"][0]

            time_from = transToStamp(query_components["time_from"][0])
            time_to = transToStamp(query_components["time_to"][0])

            # start = time.time()

            tile_quadkey = mercantile.quadkey(int(x), int(y), int(level))
            tile_id = quadkey_to_num(tile_quadkey)
            print tile_id, str(time_from), str(time_to)
            jpype.attachThreadToJVM()
            hbase_response = cp.spatialSum("nycTaxi", tile_id, str(time_from),
                                           str(time_to))

            print hbase_response
            # end = time.time()
            # print "query_time" + ": " + str(end - start)
            #
            #
            # q_time1.append(end - start)

            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.send_header('Access-Control-Allow-Origin', '*')
            self.end_headers()

            self.wfile.write(hbase_response)

            # if len(q_time1) == 20:
            #     print "hundred"
            #     plt.plot(range(len(q_time1)), q_time1)
            #     plt.ylabel('tile query time')
            #     plt.axis([1, 20, 0, 2])
            #     print float(sum(q_time1)) / len(q_time1)
            #     plt.show()

            return

        if url.path == '/time_series':
            query_components = parse_qs(urlparse(self.path).query)

            dataset = query_components["dataset"][0]
            level = query_components["level"][0]
            bounds = query_components["bounds"][0]
            bounds = bounds.split(",")
            time_from = transToStamp(query_components["time_from"][0])
            time_to = transToStamp(query_components["time_to"][0])

            start = time.time()

            new_bounds = check_bounds(bounds)
            tiles = mercantile.tiles(new_bounds[0],new_bounds[1],new_bounds[2], \
                                     new_bounds[3], [int(level), ])

            tile_numbers = []
            for tile in list(tiles):
                t_quadkey = mercantile.quadkey(tile)
                t_num = quadkey_to_num(t_quadkey)
                tile_numbers.append(t_num)

            tile_numbers = ' '.join(str(x) for x in tile_numbers)
            jpype.attachThreadToJVM()
            res = cp.timeSeriesCount(dataset, tile_numbers, str(time_from),
                                     str(time_to))

            end = time.time()
            print "query_time" + ": " + str(end - start)

            # q_time2.append(end - start)

            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.send_header('Access-Control-Allow-Origin', '*')
            self.end_headers()
            self.wfile.write(res)

            # if len(q_time2) == 20:
            #     print "hundred"
            #     plt.plot(range(len(q_time2)), q_time2)
            #     plt.ylabel('timeseries query time')
            #     plt.axis([1, 20, 0, 1])
            #     print float(sum(q_time2)) / len(q_time2)
            #     plt.show()

            return
Ejemplo n.º 33
0
    def _create_mosaic(
        cls,
        features: Sequence[Dict],
        minzoom: int,
        maxzoom: int,
        quadkey_zoom: Optional[int] = None,
        accessor: Callable[[Dict], str] = default_accessor,
        asset_filter: Callable = default_filter,
        version: str = "0.0.2",
        quiet: bool = True,
        **kwargs,
    ):
        """
        Create mosaic definition content.

        Attributes
        ----------
        features : List, required
            List of GeoJSON features.
        minzoom: int, required
            Force mosaic min-zoom.
        maxzoom: int, required
            Force mosaic max-zoom.
        quadkey_zoom: int, optional
            Force mosaic quadkey zoom.
        accessor: callable, required
            Function called on each feature to get its identifier (default is feature["properties"]["path"]).
        asset_filter: callable, required
            Function to filter features.
        version: str, optional
            mosaicJSON definition version (default: 0.0.2).
        quiet: bool, optional (default: True)
            Mask processing steps.
        kwargs: any
            Options forwarded to `asset_filter`

        Returns
        -------
        mosaic_definition : MosaicJSON
            Mosaic definition.

        """
        quadkey_zoom = quadkey_zoom or minzoom

        if not quiet:
            click.echo(f"Get quadkey list for zoom: {quadkey_zoom}", err=True)

        # Find dataset geometries
        dataset_geoms = polygons(
            [feat["geometry"]["coordinates"][0] for feat in features])
        bounds = list(total_bounds(dataset_geoms))

        tiles = burntiles.burn(features, quadkey_zoom)
        tiles = [mercantile.Tile(*tile) for tile in tiles]

        mosaic_definition: Dict[str, Any] = dict(
            mosaicjson=version,
            minzoom=minzoom,
            maxzoom=maxzoom,
            quadkey_zoom=quadkey_zoom,
            bounds=bounds,
            center=((bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2,
                    minzoom),
            tiles={},
            version="1.0.0",
        )

        if not quiet:
            click.echo(f"Feed Quadkey index", err=True)

        # Create tree and find assets that overlap each tile
        tree = STRtree(dataset_geoms)

        for tile in tiles:
            quadkey = mercantile.quadkey(tile)
            tile_geom = polygons(
                mercantile.feature(tile)["geometry"]["coordinates"][0])

            # Find intersections from rtree
            intersections_idx = sorted(
                tree.query(tile_geom, predicate="intersects"))
            if len(intersections_idx) == 0:
                continue

            intersect_dataset, intersect_geoms = zip(
                *[(features[idx], dataset_geoms[idx])
                  for idx in intersections_idx])

            dataset = asset_filter(tile, intersect_dataset, intersect_geoms,
                                   **kwargs)

            if dataset:
                mosaic_definition["tiles"][quadkey] = [
                    accessor(f) for f in dataset
                ]

        return cls(**mosaic_definition)