Esempio n. 1
0
    def getGeoElementFromData(self, data,vdims=None):

        arrayGeomType = data.geom_type.unique()

        for geomType in arrayGeomType:

            data = data[data['geometry'].apply(lambda x: x.geom_type == geomType)]

            if geomType in POINT:
                geomNdOverlay = gv.Points(data, vdims=vdims,crs=ccrs.GOOGLE_MERCATOR,  group=POINT[0])


            elif geomType in LINESTRING:
                data['geometry'] = data.simplify(SOFT_SIMPLIFY, True)
                geomNdOverlay = gv.Path(data, vdims=vdims,crs=ccrs.GOOGLE_MERCATOR, group=LINESTRING[0])

            elif geomType in MULTILINESTRING:
                data['geometry'] = data.simplify(SOFT_SIMPLIFY, True)
                geomNdOverlay = gv.Path(data, vdims=vdims, crs=ccrs.GOOGLE_MERCATOR,
                                        group=MULTILINESTRING[0])
            elif geomType in POLYGONE:
                data['geometry'] = data.simplify(STRONG_SIMPLIFY, True)
                geomNdOverlay = gv.Polygons(data, vdims=vdims, crs=ccrs.GOOGLE_MERCATOR,  group=POLYGONE[0])

            elif geomType in MULTIPOLYGONE:
                data['geometry'] = data.simplify(STRONG_SIMPLIFY, True)
                geomNdOverlay = gv.Polygons(data, vdims=vdims, crs=ccrs.GOOGLE_MERCATOR,
                                            group=MULTIPOLYGONE[0])
            elif geomType in GEOMETRYCOLLECTION:
                data = data.explode()
                geomNdOverlay = GeomUtil.getGeoElementFromData(self,data=data)
            else:
                return None

        return geomNdOverlay.opts(tools=['hover', 'tap'])
    def generate(self, bounds_polygon: sg.Polygon, raster_shape: Tuple[int, int], from_cache: bool = False, **kwargs) -> \
            Tuple[Geometry, np.ndarray, gpd.GeoDataFrame]:
        import colorcet
        import datashader as ds
        from holoviews.operation.datashader import rasterize
        import geoviews as gv
        from copy import deepcopy

        bounds = bounds_polygon.bounds
        polys_df = self.query_osm_polygons(bounds_polygon)
        bounded_census_wards = self._census_wards.cx[bounds[1]:bounds[3],
                                                     bounds[0]:bounds[2]]

        # Find landuse polygons intersecting/within census wards and merge left
        census_df = gpd.overlay(polys_df,
                                bounded_census_wards,
                                how='intersection')
        # Estimate the population of landuse polygons from the density of the census ward they are within
        # EPSG:4326 is *not* an equal area projection so would give gibberish areas
        # Project geometries to an equidistant/equal areq projection
        census_df['population'] = census_df['density'] * census_df[
            'geometry'].to_crs('EPSG:3395').area
        census_df['ln_density'] = np.log(census_df['density'])

        # Construct the GeoViews Polygons
        gv_polys = gv.Polygons(census_df, kdims=['Longitude', 'Latitude'],
                               vdims=['population', 'ln_density', 'density']) \
            .opts(color='ln_density',
                  cmap=colorcet.CET_L18, alpha=0.8,
                  colorbar=True, colorbar_opts={'title': 'Log Population Density [ln(people/km^2)]'}, show_legend=False,
                  line_color='ln_density')

        if self.buffer_dist > 0:
            buffered_df = deepcopy(census_df)
            buffered_df.geometry = buffered_df.to_crs('EPSG:27700') \
                .buffer(self.buffer_dist).to_crs('EPSG:4326')
            buffered_polys = gv.Polygons(buffered_df,
                                         kdims=['Longitude', 'Latitude'],
                                         vdims=['name', 'density'])
            raster = rasterize(buffered_polys,
                               aggregator=ds.max('density'),
                               width=raster_shape[0],
                               height=raster_shape[1],
                               x_range=(bounds[1], bounds[3]),
                               y_range=(bounds[0], bounds[2]),
                               dynamic=False)
        else:
            raster = rasterize(gv_polys,
                               aggregator=ds.max('density'),
                               width=raster_shape[0],
                               height=raster_shape[1],
                               x_range=(bounds[1], bounds[3]),
                               y_range=(bounds[0], bounds[2]),
                               dynamic=False)

        raster_grid = np.copy(
            list(raster.data.data_vars.items())[0][1].data.astype(np.float))

        return gv_polys, raster_grid, gpd.GeoDataFrame(census_df)
    def createOverlay(self,**kwargs):

        traceP = kwargs.get("traceParam")
        data = traceP.data
        label  = kwargs.get("label")
        self.param.variable_taille_point.objects = traceP.listeEntier
        self.param.variable_couleur.objects = data.columns

        if not self.variable_taille_point:
            self.silently = True
            self.variable_taille_point = traceP.listeEntier[0]

        if not self.variable_couleur:
            self.silently = True
            self.variable_couleur = traceP.listeEntier[0]


        vdims = traceP.listeEntier
        kdims = list(data.columns)[5:-1]

        size = self.variable_taille_point

        arrayGeomType = data.geom_type.unique()

        for geomType in arrayGeomType:

            data = data[data['geometry'].apply(lambda x: x.geom_type == geomType)]

            if geomType in POINT:
                geomNdOverlay = gv.Points(data, vdims=vdims, crs=crs.GOOGLE_MERCATOR, label=label, group=POINT[0], id=traceP.trace.id).options(size=dim(size).norm()*45)

            ## Convertir les autres géometry en barycentre
            elif geomType in POLYGONE:
                data['geometry'] = data.simplify(STRONG_SIMPLIFY,True)
                geomNdOverlay =  gv.Polygons(data,vdims=vdims, crs=crs.GOOGLE_MERCATOR,label=label, group=POLYGONE[0])

            elif geomType in LINESTRING:
                data['geometry'] = data.simplify(SOFT_SIMPLIFY, True)
                geomNdOverlay = gv.Path(data, crs=crs.GOOGLE_MERCATOR,label=label, group=LINESTRING[0])

            elif geomType in MULTILINESTRING:
                data['geometry'] = data.simplify(SOFT_SIMPLIFY, True)
                geomNdOverlay = gv.Path(data, crs=crs.GOOGLE_MERCATOR, label=label, group=MULTILINESTRING[0])

            elif geomType in MULTIPOLYGONE:
                data['geometry'] = data.simplify(STRONG_SIMPLIFY,True)
                geomNdOverlay =  gv.Polygons(data, vdims=vdims, crs=crs.GOOGLE_MERCATOR,label=label, group=MULTIPOLYGONE[0])
            else:
                geomNdOverlay = None


        overlay = hv.Overlay([geomNdOverlay.opts(tools=['hover', 'tap'],color=self.variable_couleur, cmap='Category20')])

        return overlay
Esempio n. 4
0
def geodframe_to_geoviews(obj, geo_type, crs):
    """Converts the geometry in a GeoPandas GeoDataFrame into a list formatted for Geoviews
        only accepts one data type per object

        Parameters
        ----------
        obj - geopandas geodataframe with geometry column of shapely objects
        geo_type - string - type of geometry to extract from gdf 'point' or 'polygon'.
            Only one geometry type can be extracted from a gdf
        crs - cartopy.crs projection
        """

    if geo_type is 'point':
        data = [item.coords for item in obj.geometry]
        element = gv.Points(data, crs=crs)
        for col in obj.columns:
            if col is not 'geometry':
                element = element.add_dimension(col, 0, obj[col], True)

    elif geo_type is 'polygon':
        data = [item.coords for item in obj.geometry.boundary]
        element = gv.Polygons(data, crs=crs)
        for col in obj.columns:
            if col is not 'geometry':
                element = element.add_dimension(col, 0, obj[col], True)
    else:
        raise IOError('Shapely geometry type {} not supported'.format(
            obj.geometryType()))

    return element
Esempio n. 5
0
def compare_sp_and_osm_for_tile(rgb_fn, gdf_sp, gdf_osm):
    """
    Creates an interactive gui to explore each tile resulting
    rgb_fn: a uncropped rgb file or cropped tile
    gdf_sp and gdf_osm: ideally covers equal or larger bounds than the bounds of rgb_fn
    """
    ds = rio.open(rgb_fn)
    img = reshape_as_image(ds.read())
    bounds = ds.bounds
    polys_sp = filter_gdf_to_polys_within_bounds(gdf_sp, bounds)
    polys_osm = filter_gdf_to_polys_within_bounds(gdf_osm, bounds)

    overlay = (gv.Image(img, bounds=bounds) *
               gv.Polygons(polys_sp, group='sp', datatype=['list']) *
               gv.Polygons(polys_osm, group='osm'))
    return overlay
Esempio n. 6
0
def warning(color="orange"):
    warning = gv.Polygons([]).opts(line_color=color, line_width=3, 
                                      fill_color=color, fill_alpha=0.2)
    pen = FreehandDraw(source=warning)

    return pen, warning
    
class Mapview(param.Parameterized):

    opts = dict(width=1200,
                height=750,
                xaxis=None,
                yaxis=None,
                show_grid=False)
    tiles = gv.tile_sources.CartoEco().apply.opts(**opts)
    extents = param.Parameter(default=(-168, -60, 168, 83), precedence=-1)
    tiles.extents = extents.default
    box_polygons = gv.Polygons([]).opts(fill_alpha=0.1)
    box_colours = ["red", "blue", "green", "orange", "purple"]
    box_stream = hv.streams.BoxEdit(source=box_polygons,
                                    num_objects=5,
                                    styles={"fill_color": box_colours})
    template_df = pd.DataFrame({
        "x_meters": [],
        "y_meters": []
    },
                               columns=["x_meters", "y_meters"])
    dfstream = hv.streams.Buffer(template_df, index=False, length=10000)
    points = hv.DynamicMap(hv.Points, streams=[dfstream]).opts(size=5,
                                                               color="green",
                                                               fill_alpha=0.3,
                                                               line_alpha=0.4)

    def show_map(self):
        return self.tiles * self.box_polygons * self.points
Esempio n. 8
0
    def grid(self, tiles=False, **kwargs):

        x = kwargs.get("x", self._obj.SCHISM_hgrid_node_x[:].values)
        y = kwargs.get("y", self._obj.SCHISM_hgrid_node_y[:].values)
        tes = kwargs.get("tri3", self._obj.SCHISM_hgrid_face_nodes.values)

        width = kwargs.get("width", 800)
        height = kwargs.get("height", 600)
        opts.defaults(opts.WMTS(width=width, height=height))

        tile = gv.WMTS("https://b.tile.openstreetmap.org/{Z}/{X}/{Y}.png")

        nodes = pd.DataFrame({"longitude": x, "latitude": y})

        points = gv.operation.project_points(gv.Points(nodes))

        if tes.shape[1] == 3:

            elems = pd.DataFrame(tes, columns=["a", "b", "c"])

            trimesh = gv.TriMesh((elems, points)).edgepaths

            if tiles:
                return tile * datashade(
                    trimesh, precompute=True, cmap=["black"])
            else:
                return datashade(trimesh, precompute=True,
                                 cmap=["green"]).opts(width=width,
                                                      height=height)

        else:  # there are quads

            elems = pd.DataFrame(tes, columns=["a", "b", "c", "d"])

            quads = elems.loc[~elems.d.isna()].copy()
            quads = quads.reset_index(drop=True)
            ap = nodes.loc[quads.a, ["longitude", "latitude"]]
            bp = nodes.loc[quads.b, ["longitude", "latitude"]]
            cp = nodes.loc[quads.c, ["longitude", "latitude"]]
            dp = nodes.loc[quads.d, ["longitude", "latitude"]]
            quads["ap"] = ap.values.tolist()
            quads["bp"] = bp.values.tolist()
            quads["cp"] = cp.values.tolist()
            quads["dp"] = dp.values.tolist()

            q = gv.Polygons([
                quads.loc[i, ["ap", "bp", "cp", "dp"]].tolist()
                for i in range(quads.shape[0])
            ]).options(fill_alpha=0, line_color="black")

            triangles = elems.loc[elems.d.isna()]

            trimesh = gv.TriMesh((triangles, points)).edgepaths

            g1 = datashade(trimesh, precompute=True, cmap=["black"])

            if tiles:
                return tile * g1 * q
            else:
                return g1 * q
    def generate(self, bounds_polygon: sg.Polygon, raster_shape: Tuple[int, int], from_cache: bool = False, **kwargs) -> \
            Tuple[Geometry, np.ndarray, gpd.GeoDataFrame]:
        import geoviews as gv
        from holoviews.operation.datashader import rasterize

        bounds = bounds_polygon.bounds

        bounded_df = self.dataframe.cx[bounds[1]:bounds[3],
                                       bounds[0]:bounds[2]]

        polys = gv.Polygons(bounded_df).opts(style={
            'alpha': 0.8,
            'color': self._colour
        })
        raster = rasterize(polys,
                           width=raster_shape[0],
                           height=raster_shape[1],
                           x_range=(bounds[1], bounds[3]),
                           y_range=(bounds[0], bounds[2]),
                           dynamic=False)
        raster_grid = np.copy(
            list(raster.data.data_vars.items())[0][1].data.astype(np.float))
        if self.blocking:
            raster_grid[raster_grid != 0] = -1

        return polys, raster_grid, gpd.GeoDataFrame(self.dataframe)
Esempio n. 10
0
    def plot(self):

        commune_plot = gv.Polygons(
            ifrag_cont_df_merged[ifrag_cont_df_merged.nom_com ==
                                 self.localisation],
            vdims=vdims,
        )
        return self.tiles * commune_plot.opts(
            color=indice, width=600, height=600, fill_alpha=0.5)
Esempio n. 11
0
 def __init__(self, poly_data=[], **params):
     super(SelectRegionPanel, self).__init__(**params)
     self.boxes = gv.Polygons(poly_data).options(
         fill_alpha=0.5, color='grey', line_color='white',
         line_width=2, width=self.width, height=self.height
     )
     if not self.boxes:
         self.boxes = self.boxes.options(global_extent=True)
     self.box_stream = BoxEdit(source=self.boxes, num_objects=1)
Esempio n. 12
0
    def _plot_shapes_one(self, data_gpd: GeoDataFrame, timestamp: dt.datetime,
                         crs: CRS):
        """Plots shapes for one timestamp from geopandas GeoDataFrame

        :param data_gpd: data to plot
        :param timestamp: timestamp to plot data for
        :param crs: in which crs is the data to plot
        """
        out = data_gpd.loc[data_gpd[self.config.timestamp_column] == timestamp]
        return gv.Polygons(out, crs=ccrs.epsg(int(crs.value)))
Esempio n. 13
0
    def grid(self, tiles=False, **kwargs):

        x = kwargs.get('x',self._obj.SCHISM_hgrid_node_x[:].values)
        y = kwargs.get('y',self._obj.SCHISM_hgrid_node_y[:].values)
        tes = kwargs.get('tri3',self._obj.SCHISM_hgrid_face_nodes.values)

        width = kwargs.get('width', 800)
        height = kwargs.get('height', 600)
        opts.defaults(opts.WMTS(width=width, height=height))

        tile = gv.WMTS('https://b.tile.openstreetmap.org/{Z}/{X}/{Y}.png')

        nodes = pd.DataFrame({'longitude':x,'latitude':y})

        points = gv.operation.project_points(gv.Points(nodes))

        if tes.shape[1] == 3 :

            elems  = pd.DataFrame(tes, columns=['a', 'b', 'c'])

            trimesh=gv.TriMesh((elems, points)).edgepaths

            if tiles:
                return tile * datashade(trimesh, precompute=True, cmap=['black'])
            else:
                return datashade(trimesh, precompute=True, cmap=['green']).opts(width=width,height=height)


        else: # there are quads

            elems  = pd.DataFrame(tes, columns=['a', 'b', 'c', 'd'])

            quads = elems.loc[~elems.d.isna()].copy()
            quads = quads.reset_index(drop=True)
            ap = nodes.loc[quads.a,['longitude','latitude']]
            bp = nodes.loc[quads.b,['longitude','latitude']]
            cp = nodes.loc[quads.c,['longitude','latitude']]
            dp = nodes.loc[quads.d,['longitude','latitude']]
            quads['ap'] = ap.values.tolist()
            quads['bp'] = bp.values.tolist()
            quads['cp'] = cp.values.tolist()
            quads['dp'] = dp.values.tolist()

            q = gv.Polygons([quads.loc[i,['ap','bp','cp','dp']].tolist() for i in range(quads.shape[0])]).options(fill_alpha=0, line_color='black')

            triangles = elems.loc[elems.d.isna()]

            trimesh=gv.TriMesh((triangles, points)).edgepaths

            g1 = datashade(trimesh, precompute=True, cmap=['black'])

            if tiles : 
                return tile * g1 * q
            else:
                return g1 * q
Esempio n. 14
0
    def _plot_vector_timeless(self, eopatch: EOPatch):
        """Plot vector timeless data"""
        crs = eopatch.bbox.crs
        data_gpd = eopatch[self.feature]
        if crs is CRS.WGS84:
            crs = CRS.POP_WEB
            data_gpd = data_gpd.to_crs(crs.pyproj_crs())

        return gv.Polygons(data_gpd,
                           crs=ccrs.epsg(crs.epsg),
                           vdims=self.config.vdims)
Esempio n. 15
0
    def plot_shapes_one(self, data_gpd, timestamp, crs):
        """ Plots shapes for one timestamp from geopandas GeoDataFrame

        :param data_gpd: data to plot
        :type data_gpd: geopandas.GeoDataFrame
        :param timestamp: timestamp to plot data for
        :type timestamp: datetime
        :param crs: in which crs is the data to plot
        :type crs: sentinelhub.crs
        :return: visualization
        :rtype: geoviews
        """
        out = data_gpd.loc[data_gpd[self.timestamp_column] == timestamp]
        return gv.Polygons(out, crs=ccrs.epsg(int(crs.value)))
Esempio n. 16
0
    def plot_vector_timeless(self, feature_name):
        """ Plot FeatureType.VECTOR_TIMELESS data

        :param feature_name: name of the eopatch featrue
        :type feature_name: str
        :return: visalization
        :rtype: geoviews
        """
        crs = self.eopatch.bbox.crs
        data_gpd = self.eopatch[FeatureType.VECTOR_TIMELESS][feature_name]
        if crs is CRS.WGS84:
            crs = CRS.POP_WEB
            data_gpd = data_gpd.to_crs(crs.pyproj_crs())

        return gv.Polygons(data_gpd, crs=ccrs.epsg(crs.epsg), vdims=self.vdims)
Esempio n. 17
0
def bbox_selector(metadata_csv=None,
                  metadata_csv_lon_column='Longitude',
                  metadata_csv_lat_column='Latitude',
                  bounds=(-124.5, 40, -108, 50),
                  basemap_url=None):
    '''
    Draw bounding box (hold shift) on basemap and return vertices.
    Select bounding box to delete.
    '''
    OpenTopoMap = 'https://tile.opentopomap.org/{Z}/{X}/{Y}.png'
    OpenStreetMap = 'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png'
    GoogleHybrid = 'https://mt1.google.com/vt/lyrs=y&x={X}&y={Y}&z={Z}'
    GoogleSatellite = 'https://mt1.google.com/vt/lyrs=s&x={X}&y={Y}&z={Z}'
    GoogleRoad = 'https://mt1.google.com/vt/lyrs=m&x={X}&y={Y}&z={Z}'
    GoogleTerrain = 'http://mt0.google.com/vt/lyrs=p&hl=en&x={X}&y={Y}&z={Z}'
    GoogleTerrainOnly = 'http://mt0.google.com/vt/lyrs=t&hl=en&x={X}&y={Y}&z={Z}'
    ESRIImagery = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{Z}/{Y}/{X}.jpg'
    Wikimedia = 'https://maps.wikimedia.org/osm-intl/{Z}/{X}/{Y}@2x.png'

    print('Toggle Box Edit Tool  and hold shift to draw bounding box.')

    if not basemap_url:
        url = GoogleSatellite

    basemap = gv.WMTS(url, extents=bounds).opts(aspect=1, frame_height=500)

    if metadata_csv:
        df = pd.read_csv(metadata_csv)
        df = df.loc[(df[metadata_csv_lat_column] < bounds[3])
                    & (df[metadata_csv_lat_column] > bounds[1]) &
                    (df[metadata_csv_lon_column] > bounds[0]) &
                    (df[metadata_csv_lon_column] < bounds[2])].reset_index(
                        drop=True)
        coords = list(
            zip(df[metadata_csv_lon_column].values,
                df[metadata_csv_lat_column].values))
        points = gv.Points(coords).opts(size=10, frame_height=500)
    else:
        points = gv.Points({}).opts(size=10, frame_height=500)

    box_poly = gv.Polygons([{}]).opts(
        opts.Polygons(fill_alpha=0,
                      line_color='yellow',
                      line_width=3,
                      selection_fill_color='red'))
    box_stream = BoxEdit(source=box_poly)

    return basemap * points * box_poly, box_stream
    def update_poly(self):
        poly = polygons.copy()
        poly = poly[poly.nom_com == self.localisation]

        poly.loc[:, "value"] = np.random.rand(len(poly)) * self.some_value
        vdims = ["value", "value2"]

        poly.loc[:, "value2"] = np.random.rand(len(poly)) * self.some_value

        # Hovertool
        # https://docs.bokeh.org/en/latest/docs/user_guide/tools.html#hovertool

        # gv.Polygons(d1, vdims=[('pop_est','Population'), ('name', 'Country')]).options(
        #     tools=['hover'], width=800, height=500, projection=crs.Robinson()
        # )

        tooltips = [("value", "@value"), ("value2", "-")]

        if self.some_value > 50:
            tooltips = [("value", "@value"), ("value2", "@value2")]

        TOOLTIPS_HTML = """
        <div>
        """
        for val in ["value", "value2"]:
            TOOLTIPS_HTML += """<div>
                <span style="font-size: 17px; font-weight: bold;">{parameter} :</span> <span style="red"> @{parameter}</span>
            </div>""".format(parameter=val)

        TOOLTIPS_HTML += """
        </div>
        """

        hover_custom = HoverTool(tooltips=TOOLTIPS_HTML)

        maps = gv.Polygons(poly, vdims=vdims).opts(
            # tools=[hover_custom],
            tools=[hover_custom],
            color="value",
            colorbar=True,
            toolbar="above",
            fill_alpha=0.5,
            width=800,
            height=800,
        )
        return maps
Esempio n. 19
0
def save_shapefile(cdsdata, path, template):
    """
    Accepts bokeh ColumnDataSource data and saves it as a shapefile,
    using an existing template to determine the required schema.
    """
    collection = fiona.open(template)
    arrays = [
        np.column_stack([xs, ys])
        for xs, ys in zip(cdsdata['xs'], cdsdata['ys'])
    ]
    polys = gv.Polygons(arrays, crs=ccrs.GOOGLE_MERCATOR)
    projected = gv.operation.project_path(polys, projection=ccrs.PlateCarree())
    data = [list(map(tuple, arr)) for arr in projected.split(datatype='array')]
    shape_data = list(collection.items())[0][1]
    shape_data['geometry']['coordinates'] = data
    with fiona.open(path, 'w', collection.driver, collection.schema,
                    collection.crs) as c:
        c.write(shape_data)
Esempio n. 20
0
    def plot_vector_timeless(self, feature_name):
        """ Plot FeatureType.VECTOR_TIMELESS data

        :param feature_name: name of the eopatch featrue
        :type feature_name: str
        :return: visalization
        :rtype: geoviews
        """
        crs = self.eopatch.bbox.crs
        if crs is CRS.WGS84:
            crs = CRS.POP_WEB
            data_gpd = self.eopatch[
                FeatureType.VECTOR_TIMELESS][feature_name].to_crs(
                    {'init': 'epsg:{}'.format(crs.value)})
        else:
            data_gpd = self.eopatch[FeatureType.VECTOR_TIMELESS][feature_name]
        return gv.Polygons(data_gpd,
                           crs=ccrs.epsg(int(crs.value)),
                           vdims=self.vdims)
Esempio n. 21
0
    def generate(self, bounds_polygon: sg.Polygon, raster_shape: Tuple[int, int], from_cache: bool = False,
                 hour: int = 8, resolution: float = 20, **kwargs) -> \
            Tuple[Geometry, np.ndarray, gpd.GeoDataFrame]:
        from holoviews.operation.datashader import rasterize
        import geoviews as gv
        import datashader as ds
        import colorcet

        relative_variation = self.relative_variations_flat[hour]

        roads_gdf = self._interpolate_traffic_counts(bounds_polygon)
        roads_gdf['population_per_hour'] = roads_gdf[
            'population_per_hour'] * relative_variation
        roads_gdf['population'] = roads_gdf['population_per_hour'] / 3600
        roads_gdf['density'] = roads_gdf['population'] / (
            roads_gdf.geometry.area * 1e-6)  # km^2
        ln_mask = roads_gdf['density'] > 0
        roads_gdf.loc[ln_mask, 'ln_density'] = np.log(roads_gdf.loc[ln_mask,
                                                                    'density'])
        roads_gdf['ln_density'].fillna(0, inplace=True)
        roads_gdf = roads_gdf.set_crs('EPSG:27700').to_crs('EPSG:4326')

        points = gv.Polygons(
            roads_gdf,
            kdims=['Longitude', 'Latitude'],
            vdims=['population_per_hour', 'ln_density', 'density']).opts(
                # colorbar=True,
                cmap=colorcet.CET_L18,
                color='ln_density',
                line_color='ln_density')
        bounds = bounds_polygon.bounds
        raster = rasterize(points,
                           aggregator=ds.mean('density'),
                           width=raster_shape[0],
                           height=raster_shape[1],
                           x_range=(bounds[1], bounds[3]),
                           y_range=(bounds[0], bounds[2]),
                           dynamic=False)
        raster_grid = np.copy(
            list(raster.data.data_vars.items())[0][1].data.astype(np.float))
        return points, raster_grid, gpd.GeoDataFrame(roads_gdf)
Esempio n. 22
0
    def generate(self, bounds_polygon: sg.Polygon, raster_shape: Tuple[int, int], from_cache: bool = False, **kwargs) -> \
            Tuple[Geometry, np.ndarray, gpd.GeoDataFrame]:
        import geoviews as gv
        from holoviews.operation.datashader import rasterize

        bounds = bounds_polygon.bounds
        polys_df = self.query_osm_polygons(bounds_polygon)
        if polys_df.empty:
            return None
        if self.buffer_dist > 0:
            polys_df.geometry = polys_df.to_crs('EPSG:27700').buffer(self.buffer_dist).to_crs('EPSG:4326')
        polys = gv.Polygons(polys_df).opts(alpha=0.8, color=self._colour, line_color=self._colour)
        raster = rasterize(polys, width=raster_shape[0], height=raster_shape[1],
                           x_range=(bounds[1], bounds[3]), y_range=(bounds[0], bounds[2]), dynamic=False)
        raster_grid = np.copy(list(raster.data.data_vars.items())[0][1].data.astype(np.float))
        if self.blocking:
            raster_grid[raster_grid != 0] = -1
        else:
            raster_grid = None

        return polys, raster_grid, polys_df
Esempio n. 23
0
    def update_all(pn_date_value):
        if isinstance(pn_date_value, datetime.date):
            # si on a choisi le widget DatePicker
            pn_date_value = (pn_date_value - datetime.date(1950, 1, 1)).days

        hv_polygons = []
        hv_exterieur = []

        for (d, color), d_unique in zip(datasets, datasets_unique):

            mask = d.time == pn_date_value
            sub_lon = ((d.contour_lon_s[mask] + 180) % 360) - 180
            sub_lat = d.contour_lat_s[mask]

            sub_data = np.moveaxis(np.array([sub_lon, sub_lat]), [0], [2])
            polygons = [Polygon(poly) for poly in sub_data]

            dct_data = {name: d[name][mask] for name in hover_info}
            dct_data["geometry"] = polygons
            gpd = geopandas.GeoDataFrame(dct_data)

            opts_common = dict(responsive=True)
            hv_polygons.append(
                gv.Polygons(gpd, vdims=hover_info).opts(line_color=color,
                                                        **opts_common))

            sub_lon = ((d.contour_lon_e[mask] + 180) % 360) - 180
            sub_lat = d.contour_lat_e[mask]

            _lon = flatten_line_matrix(sub_lon)
            _lat = flatten_line_matrix(sub_lat)
            hv_exterieur.append(
                gv.Path([np.array([_lon, _lat]).T]).opts(color=color,
                                                         alpha=0.70,
                                                         line_dash="dashed",
                                                         **opts_common))

        return gv.Overlay([*hv_polygons, *hv_exterieur]).opts(responsive=True,
                                                              tools=["hover"])
Esempio n. 24
0
def add_obstacles(bounds, obstacles, raster_shape):
    import geoviews as gv
    from holoviews.operation.datashader import rasterize
    import geopandas as gpd

    if type(obstacles) is gpd.GeoDataFrame:
        df = obstacles
    else:
        df = gpd.GeoDataFrame({'geometry': obstacles}).set_crs('EPSG:4326')
    bounded_df = df.cx[bounds[1]:bounds[3], bounds[0]:bounds[2]]
    bounded_df['z'] = np.inf

    polys = gv.Polygons(bounded_df, vdims=['z'])
    raster = rasterize(polys,
                       width=raster_shape[1],
                       height=raster_shape[0],
                       x_range=(bounds[1], bounds[3]),
                       y_range=(bounds[0], bounds[2]),
                       dynamic=False)
    raster_grid = np.flipud(
        np.copy(
            list(raster.data.data_vars.items())[0][1].data.astype(np.float)))
    return remove_raster_nans(raster_grid)
Esempio n. 25
0
def get_data(path):
    """
    :return:
    """
    redwood_np = gp.GeoDataFrame.from_file('data/RedwoodNP.geojson')
    gedi_files = [
        g for g in os.listdir(path)
        if g.startswith('GEDI02_A') and g.endswith('.h5')
    ]

    for item in gedi_files:
        path_to_file = os.path.join(path, item)
        gedi_l2a = h5py.File(path_to_file, 'r')
        beam_names = [g for g in gedi_l2a.keys() if g.startswith('BEAM')]
        latslons = open_sds(gedi_l2a, beam_names[0])

        vdims = []
        for f in latslons:
            if f not in ['geometry']:
                vdims.append(f)

        gv.Polygons(redwood_np).opts(
            tools=['hover'], line_color='red', color=None) * point_visual(
                latslons, vdims=vdims)
Esempio n. 26
0
def facet_map_interactive(
        df,
        cols_to_plot,
        target,
        predicted=None,
        dissolve_on=None,
        alpha=0.5,
        autobin=False,
        n_bins=7,
        geoid="nis",
        weight="exp_yr",
        shp_file=None,
        figsize=(12, 12),
        ncols=2,
        cmap=None,
        normalize=True,
        tiles_src=None,
):
    """
    Prepare the geodata to map. Take the dataframe df,
    which should have a geoid column, and join it to
    the zipcode mapper and the geometries.
    The result is illustrated on a (facet) chart.

    An aggregation step by geoid is performed in order to have a
    value per unique geoid.

    If weight is provided, then weighted average, at the geoid level,
    of the target is computed. The uncertainty (on the weighted average)
    is computed accordingly to the distribution (gaussian, Poisson or Gamma)
    and can be illustrated in another panel and the sample weights as well.

    If dissolve it set to True, the geometries are "dissolved"
    to go at the upper level, e.g. dissolve counties to go at the state level
    (a state being larger and containing several counties).



    :param df: dataframe
        the data set, predictors + dependent variable
    :param cols_to_plot: list of str of None
        the columns to plot with the target (e.g. predicted values
        or any other columns than target)
    :param target: str
        the target name (main column to plot, e.g. observed values/truth)
    :param predicted: str or pandas data frame or None, default: None
        if dataframe, should be the same length of df.
        It could be predicted values, not joined to df
    :param dissolve_on: str
        the column name you want to dissolve on. Dissolve means going to
        an upper geographical level, e.g. from commune to district or to state.
        (e.g. moving from counties to states)
    :param alpha: float between 0 and 1, default=0.5
        the transparency of the choropleth
    :param autobin: Bool, default=False
        autobin (discretized) the illustrated values.
        If True, the values are binned using percentiles before to be plotted
    :param n_bins: int, default: 7
        number of bin for auto-binning (discretizing the values)
    :param geoid: str, default: 'INS'
        the name of the geoid columns, INS refers to the Belgian french name
    :param weight: None or str
        column (if any) of sample weights
    :param shp_file: geopandas frame
        the shapefile. E.G: load_be_shp()
    :param figsize: 2-uple, default: (12, 12)
        figure size, (width, heihgt)
    :param ncols: int, default: 2
        the number of columns in the facet plot, if there are several columns to plot
    :param cmap: matplotlib cmap or None
        Please, use ONLY scientific color maps. No jet, no rainbow!
        If you have any doubt, keep the default
        e.g. http://www.fabiocrameri.ch/colourmaps.php
    :param normalize: bool
        should the other illustrated columns normalized to the target?
        If True, the vmin and vmax will be the same for all the panels
        and computed w.r.t the target colum,
    :param tiles_src: str or None
        the tile source, should be a string, compatible with one of the geoview tile sources

    :return: matplotlib figure
    """

    if not isinstance(ncols, int):
        raise ValueError("'ncols' should be an integer")

    # load the data to illustrate
    geo_df = prepare_geo_data(
        df=df,
        cols_to_plot=cols_to_plot,
        target=target,
        predicted=predicted,
        dissolve_on=dissolve_on,
        n_bins=n_bins,
        geoid=geoid,
        weight=weight,
        shp_file=shp_file,
        autobin=False,
    )

    # if more than 1 column to illustrate, fillna and set
    # the number of rows in the panel plot
    if cols_to_plot is not None:
        geo_df[cols_to_plot] = geo_df[cols_to_plot].fillna(0)
    else:
        cols_to_plot = []

    if (tiles_src is not None) and (tiles_src not in list(
            hv.element.tiles.tile_sources.keys())):
        raise ValueError("`tiles_src` should be a string and one "
                         "of {}".format(
                             list(hv.element.tiles.tile_sources.keys())))
    elif (tiles_src is not None) and (tiles_src in list(
            hv.element.tiles.tile_sources.keys())):
        tiles = hv.element.tiles.tile_sources[tiles_src]()
    else:
        tiles = hv.element.tiles.tile_sources["CartoLight"]()

    # define colour_map
    if (cmap is None) and (autobin is False):
        colour_map = cmr.tropical  # Thermal_20.mpl_colormap
    elif (cmap is None) and (autobin is True):
        colour_map = cmr.tropical
    else:
        colour_map = cmap

    hv_plot_list = []
    # loop over the columns to illustrate
    for i, col in enumerate([target] + cols_to_plot):

        plot_opts = dict(
            tools=["hover"],
            width=550,
            height=450,
            color_index=col,
            cmap=colour_map,
            colorbar=True,
            toolbar="above",
            xaxis=None,
            yaxis=None,
            alpha=alpha,
            title=col,
            clipping_colors={"NaN": "white"},
        )

        if autobin:
            if normalize:
                ser, bins = pd.qcut(geo_df[target].fillna(0),
                                    q=n_bins,
                                    retbins=True,
                                    labels=None,
                                    precision=2)
                geo_df[col] = (pd.cut(
                    geo_df[col].fillna(0),
                    bins=bins,
                    labels=np.unique(ser),
                    include_lowest=True,
                ).apply(lambda x: x.mid).astype(float))
                # pd.cut(geo_df[col], q=n_bins, duplicates='drop').
                # apply(lambda x: x.mid).astype(float)
            else:
                geo_df[col] = (pd.qcut(
                    geo_df[col], q=n_bins, duplicates="drop",
                    precision=2).apply(lambda x: x.mid).astype(float))
                # .apply(lambda x: x.mid).astype(float)

            hv_plot_list.append(tiles * gv.Polygons(
                geo_df, vdims=[hv.Dimension(col)
                               ], crs=ccrs.GOOGLE_MERCATOR).opts(**plot_opts))
        else:
            if normalize:
                vmax = np.nanpercentile(geo_df[target].fillna(0), 99)
                vmin = np.nanpercentile(geo_df[target].fillna(0), 1)
            else:
                vmax = np.nanpercentile(geo_df[col].fillna(0), 99)
                vmin = np.nanpercentile(geo_df[col].fillna(0), 1)

            hv_plot_list.append(tiles * gv.Polygons(
                geo_df,
                vdims=[hv.Dimension(col, range=(vmin, vmax))],
                crs=ccrs.GOOGLE_MERCATOR,
            ).opts(**plot_opts))

    # Display the figure
    hvl = (hv.Layout(hv_plot_list).opts(
        opts.Tiles(width=figsize[0], height=figsize[1])).cols(2))
    return hvl
Esempio n. 27
0
import quest
import geoviews as gv
import holoviews as hv
import panel as pp

hv.extension('bokeh')

quest_service = 'svc://wmts:seamless_imagery'
tile_service_options = quest.api.get_download_options(
    quest_service, fmt='param')[quest_service]

boxes = gv.Polygons([]).options(fill_alpha=0.4, line_width=2)
box_stream = hv.streams.BoxEdit(source=boxes, num_objects=1)

import param


class MyParam(param.Parameterized):
    alpha = param.Number(0.5, bounds=(0, 1), doc="alpha")


myparam = MyParam()


def change_basemap(**kw):
    print("change_basemap: " + str(kw))
    url = kw['url']
    alpha = kw["alpha"]
    tiles = gv.WMTS(url).options(global_extent=True,
                                 height=400,
                                 width=700,
Esempio n. 28
0
def dmp_callback(*args, **kw):
    global stream_extract_options
    global elevation_filled
    global tiles
    global points
    global box_poly
    global streams
    global fill_dataset
    global st_dataset

    if box_stream.element:
        xs, ys = box_stream.element.array().T
        bbox = [xs[0], ys[1], xs[2], ys[0]]
    else:
        bbox = [
            -90.88870324076336, 32.245105881134, -90.78133198716839,
            32.37688211930573
        ]
    print('BOUNDS:', bbox)
    tiles.extents = tuple(bbox)

    if box_stream._triggering:
        print("Box stream is triggering")
        elements = tiles * box_poly * points

    elif btn_download_stream._triggering:

        # import pdb
        # pdb.set_trace()
        print("btn_download_stream is triggering")

        elevation_raster = quest.api.get_seamless_data(
            service_uri=elevation_service.service,
            bbox=bbox,
            collection_name='examples',
            use_cache=False,  # in standalone Bokeh app this should be set False
            as_open_dataset=False,
        )
        fill_dataset = quest.tools.wbt_fill_depressions(
            dataset=elevation_raster, )['datasets'][0]
        fill = quest.api.open_dataset(fill_dataset,
                                      with_nodata=True,
                                      isel_band=0)

        elevation_filled = gv.Image(fill, ['x', 'y']).options(alpha=0.8)

        stream_extract_options = quest.tools.wbt_extract_streams_workflow
        stream_extract_options.params()['dataset'].precedence = -1
        stream_extract_options.dataset = fill_dataset
        stream_extract_options.set_threshold_bounds()

        print("Bounds" +
              str(stream_extract_options.params()["stream_threshold"].bounds))
        start, end = stream_extract_options.params()["stream_threshold"].bounds
        slider_extract.start = start
        slider_extract.end = end
        slider_extract.value = stream_extract_options.stream_threshold

        elements = tiles * elevation_filled * box_poly * points

    elif btn_run_stream._triggering:
        print("btn_run_stream is triggering")

        stream_extract_options.stream_threshold = slider_extract.value
        st_dataset = stream_extract_options()['datasets'][0]
        st = quest.api.open_dataset(st_dataset, with_nodata=True, isel_band=0)
        streams = gv.Image(st, ['x', 'y']).options(cmap='Greens')

        elements = tiles * box_poly * elevation_filled * streams * points

    elif btn_delin_stream._triggering:
        print("btn_delin_stream is triggering")

        if point_stream.element:
            original_outlets = [
                (x, y) for x, y in zip(*point_stream.element.array().T)
            ]
        else:
            original_outlets = (-90.883981967599979, 32.291221825861946)
        result = quest.tools.wbt_watershed_delineation_workflow(
            elevation_dataset=fill_dataset,
            streams_dataset=st_dataset,
            snap_distance=0.1,
            outlets=original_outlets,
        )
        watersheds, snapped_outlets, catalog_entry = result['catalog_entries']

        outline = gv.Polygons(watersheds).options(alpha=0.5, color="yellow")
        original_points = gv.Points(original_outlets).options(color='blue',
                                                              size=12)
        snapped_points = gv.Points(snapped_outlets).options(color='green',
                                                            size=12)
        elements = tiles * box_poly * original_points * outline * snapped_points * streams * points

    else:
        print("someone is triggering")
        elements = tiles * box_poly * points

    return elements
Esempio n. 29
0
# Subject to Bokeh Bug: Tool Bar disappears https://github.com/ioam/holoviews/issues/2784
import quest
import geoviews as gv
import holoviews as hv
from holoviews.streams import (Params, PolyEdit, BoxEdit, PointDraw)
# from holoviews.operation.datashader import regrid
import panel as pp
# import param

hv.extension('bokeh')
# pp.extension()

tiles = gv.tile_sources.StamenTerrain().options(width=950, height=600)
tiles.extents = (-125, 25, -65, 50)
box_poly = gv.Polygons([]).options(fill_alpha=.2)
box_stream = BoxEdit(source=box_poly, num_objects=1, name="boxedit")
points = gv.Points([])
point_stream = PointDraw(source=points)

elevation_service = quest.util.ServiceSelector(
    parameter='elevation', default='svc://usgs-ned:1-arc-second')

# Explicitly create a panel widget
btn_download = pp.widgets.Button(name='Download & Fill', button_type='danger')
btn_download_stream = Params(btn_download, ['clicks'],
                             rename={'clicks': 'download_clicks'})

btn_run = pp.widgets.Button(name='Extract', button_type='danger')
btn_run_stream = Params(btn_run, ['clicks'], rename={'clicks': 'run_clicks'})

btn_delin = pp.widgets.Button(name='Delinate', button_type='danger')
Esempio n. 30
0
    def update_map_values(self):
        try:
            # Selection par localisation
            #  http://holoviews.org/user_guide/Plotting_with_Bokeh.html
            # https://docs.bokeh.org/en/latest/docs/user_guide/tools.html#custom-tooltip
            map_info = ["tout_axes", "nom_com"]

            vdims = (
                map_info
                + [k + "_SCORE" for k in self.selected_indices_level_0]
                + list(AXES_INDICES.keys())
            )

            TOOLTIPS_HTML = """<span style="font-size: 22px; font-weight: bold;"> @nom_com</span>
            <div>
            """
            for k, indicators in AXES_INDICES.items():
                display_name = indicators["nom"]
                vdim_name = k
                if vdim_name in vdims:
                    TOOLTIPS_HTML += """<div>
                    <span style="font-size: 18px; font-weight: bold;">  {display_name} :</span> <span style="red"> @{vdim_name}</span>
                </div>""".format(
                        display_name=display_name, vdim_name=vdim_name
                    )

                else:
                    TOOLTIPS_HTML += """<div>
                    <span style="font-size: 18px; font-weight: bold;">  {display_name} :</span> <span style="red"> N/A </span>
                </div>""".format(
                        display_name=display_name, vdim_name=vdim_name
                    )

                for indic in indicators:
                    if indic not in ["desc", "nom"]:
                        display_name = CATEGORIES_INDICES[indic]
                        vdim_name = indic + "_SCORE"
                        if vdim_name in vdims:

                            TOOLTIPS_HTML += """<div>
                            <span style="font-size: 12px; ">  {display_name} :</span> <span style="red">@{vdim_name}</span>
                            </div>""".format(
                                display_name=display_name, vdim_name=vdim_name
                            )
                        else:
                            TOOLTIPS_HTML += """<div>
                            <span style="font-size: 12px;">  {display_name} :</span> <span style="red">N/A</span>
                            </div>""".format(
                                display_name=display_name
                            )

                TOOLTIPS_HTML += """
                </div>
                """

            hover_custom = HoverTool(tooltips=TOOLTIPS_HTML)

            self.maps = gv.Polygons(self.df_score, vdims=vdims)
            return self.maps.opts(
                tools=[hover_custom],
                color="tout_axes",
                colorbar=True,
                toolbar="above",
                # xaxis=None,
                # yaxis=None,
                fill_alpha=0.5,
            )

        except Exception as e:
            print(e)
            pass