Exemple #1
0
    def plot(self, axis=None, **kwargs):
        """Plot centroids scatter points over earth.

        Parameters
        ----------
        axis : matplotlib.axes._subplots.AxesSubplot, optional
            axis to use
        kwargs : optional
            arguments for scatter matplotlib function

        Returns
        -------
        axis : matplotlib.axes._subplots.AxesSubplot
        """
        if self.meta and not self.coord.size:
            self.set_meta_to_lat_lon()
        pad = np.abs(u_coord.get_resolution(self.lat, self.lon)).min()

        proj_data, _ = u_plot.get_transformation(self.crs)
        proj_plot = proj_data
        if isinstance(proj_data, ccrs.PlateCarree):
            # use different projections for plot and data to shift the central lon in the plot
            xmin, ymin, xmax, ymax = u_coord.latlon_bounds(self.lat, self.lon, buffer=pad)
            proj_plot = ccrs.PlateCarree(central_longitude=0.5 * (xmin + xmax))
        else:
            xmin, ymin, xmax, ymax = (self.lon.min() - pad, self.lat.min() - pad,
                                      self.lon.max() + pad, self.lat.max() + pad)

        if not axis:
            _, axis = u_plot.make_map(proj=proj_plot)

        axis.set_extent((xmin, xmax, ymin, ymax), crs=proj_data)
        u_plot.add_shapes(axis)
        axis.scatter(self.lon, self.lat, transform=proj_data, **kwargs)
        return axis
Exemple #2
0
    def plot_raster(self, res=None, raster_res=None, save_tiff=None,
                    raster_f=lambda x: np.log10((np.fmax(x+1, 1))),
                    label='value (log10)', scheduler=None, axis=None, **kwargs):
        """ Generate raster from points geometry and plot it using log10 scale:
        np.log10((np.fmax(raster+1, 1))).

        Parameters:
            res (float, optional): resolution of current data in units of latitude
                and longitude, approximated if not provided.
            raster_res (float, optional): desired resolution of the raster
            save_tiff (str, optional): file name to save the raster in tiff
                format, if provided
            raster_f (lambda function): transformation to use to data. Default:
                log10 adding 1.
            label (str): colorbar label
            scheduler (str): used for dask map_partitions. “threads”,
                “synchronous” or “processes”
            axis (matplotlib.axes._subplots.AxesSubplot, optional): axis to use
            kwargs (optional): arguments for imshow matplotlib function

         Returns:
            matplotlib.figure.Figure, cartopy.mpl.geoaxes.GeoAxesSubplot
        """
        if self.meta and self.meta['height']*self.meta['width'] == len(self):
            raster = self.value.values.reshape((self.meta['height'],
                                                self.meta['width']))
            # check raster starts by upper left corner
            if self.latitude.values[0] < self.latitude.values[-1]:
                raster = np.flip(raster, axis=0)
            if self.longitude.values[0] > self.longitude.values[-1]:
                LOGGER.error('Points are not ordered according to meta raster.')
                raise ValueError
        else:
            raster, meta = co.points_to_raster(self, ['value'], res, raster_res,
                                               scheduler)
            raster = raster.reshape((meta['height'], meta['width']))
        # save tiff
        if save_tiff is not None:
            ras_tiff = rasterio.open(save_tiff, 'w', driver='GTiff', \
                height=meta['height'], width=meta['width'], count=1, \
                dtype=np.float32, crs=self.crs, transform=meta['transform'])
            ras_tiff.write(raster.astype(np.float32), 1)
            ras_tiff.close()
        # make plot
        crs_epsg, _ = u_plot.get_transformation(self.crs)
        xmin, ymin, xmax, ymax = self.longitude.min(), self.latitude.min(), \
        self.longitude.max(), self.latitude.max()
        if not axis:
            _, axis = u_plot.make_map(proj=crs_epsg)
        cbar_ax = make_axes_locatable(axis).append_axes('right', size="6.5%", \
            pad=0.1, axes_class=plt.Axes)
        axis.set_extent([max(xmin, crs_epsg.x_limits[0]), \
            min(xmax, crs_epsg.x_limits[1]), max(ymin, crs_epsg.y_limits[0]), \
            min(ymax, crs_epsg.y_limits[1])], crs_epsg)
        u_plot.add_shapes(axis)
        imag = axis.imshow(raster_f(raster), **kwargs, origin='upper',
                           extent=[xmin, xmax, ymin, ymax], transform=crs_epsg)
        plt.colorbar(imag, cax=cbar_ax, label=label)
        plt.draw()
        return axis
    def plot_raster(self, res=None, raster_res=None, save_tiff=None,
                    raster_f=lambda x: np.log10((np.fmax(x+1, 1))),
                    label='value (log10)', **kwargs):
        """ Generate raster from points geometry and plot it using log10 scale:
        np.log10((np.fmax(raster+1, 1))).

        Parameters:
            res (float, optional): resolution of current data in units of latitude
                and longitude, approximated if not provided.
            raster_res (float, optional): desired resolution of the raster
            save_tiff (str, optional): file name to save the raster in tiff
                format, if provided
            raster_f (lambda function): transformation to use to data. Default:
                log10 adding 1.
            label (str): colorbar label
            kwargs (optional): arguments for imshow matplotlib function

         Returns:
            matplotlib.figure.Figure, cartopy.mpl.geoaxes.GeoAxesSubplot
        """
        if not 'geometry' in self.columns:
            self.set_geometry_points()
        crs_epsg, crs_unit = self._get_transformation()
        if not res:
            res= min(get_resolution(self.latitude.values, self.longitude.values))
        if not raster_res:
            raster_res = res
        LOGGER.info('Raster from resolution %s%s to %s%s.', res, crs_unit,
                    raster_res, crs_unit)
        exp_poly = self[['value']].set_geometry(self.buffer(res/2).envelope)
        # construct raster
        xmin, ymin, xmax, ymax = self.total_bounds
        rows, cols, ras_trans = points_to_raster((xmin, ymin, xmax, ymax), raster_res)
        raster = rasterize([(x, val) for (x, val) in zip(exp_poly.geometry, exp_poly.value)],
                           out_shape=(rows, cols), transform=ras_trans, fill=0,
                           all_touched=True, dtype=rasterio.float32, )
        # save tiff
        if save_tiff is not None:
            ras_tiff = rasterio.open(save_tiff, 'w', driver='GTiff', \
                height=raster.shape[0], width=raster.shape[1], count=1, \
                dtype=np.float32, crs=self.crs, transform=ras_trans)
            ras_tiff.write(raster.astype(np.float32), 1)
            ras_tiff.close()
        # make plot
        fig, axis = u_plot.make_map(proj=crs_epsg)
        cbar_ax = fig.add_axes([0.99, 0.238, 0.03, 0.525])
        fig.subplots_adjust(hspace=0, wspace=0)
        axis[0, 0].set_extent([max(xmin, crs_epsg.x_limits[0]),
                               min(xmax, crs_epsg.x_limits[1]),
                               max(ymin, crs_epsg.y_limits[0]),
                               min(ymax, crs_epsg.y_limits[1])], crs_epsg)
        u_plot.add_shapes(axis[0, 0])
        imag = axis[0, 0].imshow(raster_f(raster), **kwargs, origin='upper',
                                 extent=[xmin, xmax, ymin, ymax], transform=crs_epsg)
        plt.colorbar(imag, cax=cbar_ax, label=label)
        plt.draw()
        posn = axis[0, 0].get_position()
        cbar_ax.set_position([posn.x0 + posn.width + 0.01, posn.y0, 0.04, posn.height])

        return fig, axis
Exemple #4
0
    def plot(self, axis=None, **kwargs):
        """Plot centroids scatter points over earth.

        Parameters:
            axis (matplotlib.axes._subplots.AxesSubplot, optional): axis to use
            kwargs (optional): arguments for scatter matplotlib function

        Returns:
            matplotlib.axes._subplots.AxesSubplot
        """
        if not axis:
            _, axis = u_plot.make_map()
        u_plot.add_shapes(axis)
        if self.meta and not self.coord.size:
            self.set_meta_to_lat_lon()
        axis.scatter(self.lon, self.lat, **kwargs)
        return axis
Exemple #5
0
    def plot(self, **kwargs):
        """ Plot centroids scatter points over earth.

        Parameters:
            kwargs (optional): arguments for scatter matplotlib function

        Returns:
            matplotlib.figure.Figure, matplotlib.axes._subplots.AxesSubplot
        """
        if 's' not in kwargs:
            kwargs['s'] = 1
        fig, axis = u_plot.make_map()
        axis = axis[0][0]
        u_plot.add_shapes(axis)
        if self.meta and not self.coord.size:
            self.set_meta_to_lat_lon()
        axis.scatter(self.lon, self.lat, **kwargs)
        return fig, axis
Exemple #6
0
    def plot(self, **kwargs):
        """ Plot centroids points over earth.

        Parameters:
            kwargs (optional): arguments for scatter matplotlib function

        Returns:
            matplotlib.figure.Figure, matplotlib.axes._subplots.AxesSubplot
        """
        if 's' not in kwargs:
            kwargs['s'] = 1
        fig, axis = u_plot.make_map()
        axis = axis[0][0]
        u_plot.add_shapes(axis)
        axis.set_title(self.tag.join_file_names())
        axis.scatter(self.lon, self.lat, **kwargs)

        return fig, axis
Exemple #7
0
    def plot_raster(self,
                    res=None,
                    raster_res=None,
                    save_tiff=None,
                    raster_f=lambda x: np.log10((np.fmax(x + 1, 1))),
                    label='value (log10)',
                    scheduler=None,
                    axis=None,
                    figsize=(9, 13),
                    **kwargs):
        """Generate raster from points geometry and plot it using log10 scale:
        np.log10((np.fmax(raster+1, 1))).

        Parameters:
            res (float, optional): resolution of current data in units of latitude
                and longitude, approximated if not provided.
            raster_res (float, optional): desired resolution of the raster
            save_tiff (str, optional): file name to save the raster in tiff
                format, if provided
            raster_f (lambda function): transformation to use to data. Default:
                log10 adding 1.
            label (str): colorbar label
            scheduler (str): used for dask map_partitions. “threads”,
                “synchronous” or “processes”
            axis (matplotlib.axes._subplots.AxesSubplot, optional): axis to use
            figsize (tuple, optional): figure size for plt.subplots
            kwargs (optional): arguments for imshow matplotlib function

        Returns:
            matplotlib.figure.Figure, cartopy.mpl.geoaxes.GeoAxesSubplot
        """
        if self.meta and self.meta.get('height', 0) * self.meta.get(
                'height', 0) == len(self.gdf):
            raster = self.gdf.value.values.reshape(
                (self.meta['height'], self.meta['width']))
            # check raster starts by upper left corner
            if self.gdf.latitude.values[0] < self.gdf.latitude.values[-1]:
                raster = np.flip(raster, axis=0)
            if self.gdf.longitude.values[0] > self.gdf.longitude.values[-1]:
                LOGGER.error(
                    'Points are not ordered according to meta raster.')
                raise ValueError
        else:
            raster, meta = u_coord.points_to_raster(self.gdf, ['value'], res,
                                                    raster_res, scheduler)
            raster = raster.reshape((meta['height'], meta['width']))
        # save tiff
        if save_tiff is not None:
            with rasterio.open(save_tiff,
                               'w',
                               driver='GTiff',
                               height=meta['height'],
                               width=meta['width'],
                               count=1,
                               dtype=np.float32,
                               crs=self.crs,
                               transform=meta['transform']) as ras_tiff:
                ras_tiff.write(raster.astype(np.float32), 1)
        # make plot
        proj_data, _ = u_plot.get_transformation(self.crs)
        proj_plot = proj_data
        if isinstance(proj_data, ccrs.PlateCarree):
            # use different projections for plot and data to shift the central lon in the plot
            xmin, ymin, xmax, ymax = u_coord.latlon_bounds(
                self.gdf.latitude.values, self.gdf.longitude.values)
            proj_plot = ccrs.PlateCarree(central_longitude=0.5 * (xmin + xmax))
        else:
            xmin, ymin, xmax, ymax = (self.gdf.longitude.min(),
                                      self.gdf.latitude.min(),
                                      self.gdf.longitude.max(),
                                      self.gdf.latitude.max())

        if not axis:
            _, axis = u_plot.make_map(proj=proj_plot, figsize=figsize)

        cbar_ax = make_axes_locatable(axis).append_axes('right',
                                                        size="6.5%",
                                                        pad=0.1,
                                                        axes_class=plt.Axes)
        axis.set_extent((xmin, xmax, ymin, ymax), crs=proj_data)
        u_plot.add_shapes(axis)
        imag = axis.imshow(raster_f(raster),
                           **kwargs,
                           origin='upper',
                           extent=(xmin, xmax, ymin, ymax),
                           transform=proj_data)
        plt.colorbar(imag, cax=cbar_ax, label=label)
        plt.draw()
        return axis
Exemple #8
0
    def video_direct_impact(exp, if_set, haz_list, file_name='',
                            writer=animation.PillowWriter(bitrate=500),
                            imp_thresh=0, args_exp=dict(), args_imp=dict()):
        """
        Computes and generates video of accumulated impact per input events
        over exposure.

        Parameters:
            exp (Exposures): exposures instance, constant during all video
            if_set (ImpactFuncSet): impact functions
            haz_list (list(Hazard)): every Hazard contains an event; all hazards
                use the same centroids
            file_name (str, optional): file name to save video, if provided
            writer = (matplotlib.animation.*, optional): video writer. Default:
                pillow with bitrate=500
            imp_thresh (float): represent damages greater than threshold
            args_exp (optional): arguments for scatter (points) or hexbin (raster)
                matplotlib function used in exposures
            args_imp (optional): arguments for scatter (points) or hexbin (raster)
                matplotlib function used in impact

        Returns:
            list(Impact)
        """
        imp_list = []
        exp_list = []
        imp_arr = np.zeros(len(exp))
        for i_time, _ in enumerate(haz_list):
            imp_tmp = Impact()
            imp_tmp.calc(exp, if_set, haz_list[i_time])
            imp_arr = np.maximum(imp_arr, imp_tmp.eai_exp)
            # remove not impacted exposures
            save_exp = imp_arr > imp_thresh
            imp_tmp.coord_exp = imp_tmp.coord_exp[save_exp, :]
            imp_tmp.eai_exp = imp_arr[save_exp]
            imp_list.append(imp_tmp)
            exp_list.append(~save_exp)

        v_lim = [np.array([haz.intensity.min() for haz in haz_list]).min(),
                 np.array([haz.intensity.max() for haz in haz_list]).max()]

        if 'vmin' not in args_exp:
            args_exp['vmin'] = exp.value.values.min()

        if 'vmin' not in args_imp:
            args_imp['vmin'] = np.array([imp.eai_exp.min() for imp in imp_list
                                         if imp.eai_exp.size]).min()

        if 'vmax' not in args_exp:
            args_exp['vmax'] = exp.value.values.max()

        if 'vmax' not in args_imp:
            args_imp['vmax'] = np.array([imp.eai_exp.max() for imp in imp_list
                                         if imp.eai_exp.size]).max()

        if 'cmap' not in args_exp:
            args_exp['cmap'] = 'winter_r'

        if 'cmap' not in args_imp:
            args_imp['cmap'] = 'autumn_r'


        plot_raster = False
        if exp.meta:
            plot_raster = True

        def run(i_time):
            haz_list[i_time].plot_intensity(1, axis=axis, cmap='Greys', vmin=v_lim[0],
                                            vmax=v_lim[1], alpha=0.8)
            if plot_raster:
                exp.plot_hexbin(axis=axis, mask=exp_list[i_time], ignore_zero=True,
                                pop_name=False, **args_exp)
                if imp_list[i_time].coord_exp.size:
                    imp_list[i_time].plot_hexbin_eai_exposure(axis=axis, pop_name=False,
                                                              **args_imp)
                    fig.delaxes(fig.axes[1])
            else:
                exp.plot_scatter(axis=axis, mask=exp_list[i_time], ignore_zero=True,
                                 pop_name=False, **args_exp)
                if imp_list[i_time].coord_exp.size:
                    imp_list[i_time].plot_scatter_eai_exposure(axis=axis, pop_name=False,
                                                               **args_imp)
                    fig.delaxes(fig.axes[1])
            fig.delaxes(fig.axes[1])
            fig.delaxes(fig.axes[1])
            axis.set_xlim(haz_list[-1].centroids.lon.min(), haz_list[-1].centroids.lon.max())
            axis.set_ylim(haz_list[-1].centroids.lat.min(), haz_list[-1].centroids.lat.max())
            axis.set_title(haz_list[i_time].event_name[0])
            pbar.update()

        if file_name:
            LOGGER.info('Generating video %s', file_name)
            fig, axis = u_plot.make_map()
            ani = animation.FuncAnimation(fig, run, frames=len(haz_list),
                                          interval=500, blit=False)
            pbar = tqdm(total=len(haz_list))
            ani.save(file_name, writer=writer)
            pbar.close()

        return imp_list
Exemple #9
0
    def video_intensity(track_name,
                        tracks,
                        centroids,
                        file_name=None,
                        writer=animation.PillowWriter(bitrate=500),
                        figsize=(9, 13),
                        adapt_fontsize=True,
                        **kwargs):
        """
        Generate video of TC wind fields node by node and returns its
        corresponding TropCyclone instances and track pieces.

        Parameters
        ----------
        track_name : str
            name of the track contained in tracks to record
        tracks : climada.hazard.TCTracks
            tropical cyclone tracks
        centroids : climada.hazard.Centroids
            centroids where wind fields are mapped
        file_name : str, optional
            file name to save video (including full path and file extension)
        writer : matplotlib.animation.*, optional
            video writer. Default is pillow with bitrate=500
        figsize : tuple, optional
            figure size for plt.subplots
        adapt_fontsize : bool, optional
            If set to true, the size of the fonts will be adapted to the size of the figure. Otherwise
            the default matplotlib font size is used. Default is True.
        kwargs : optional
            arguments for pcolormesh matplotlib function used in event plots

        Returns
        -------
        tc_list, tc_coord : list(TropCyclone), list(np.array)

        Raises
        ------
        ValueError

        """
        # initialization
        track = tracks.get_track(track_name)
        if not track:
            raise ValueError('%s not found in track data.' % track_name)
        idx_plt = np.argwhere(
            (track.lon.values < centroids.total_bounds[2] + 1)
            & (centroids.total_bounds[0] - 1 < track.lon.values)
            & (track.lat.values < centroids.total_bounds[3] + 1)
            & (centroids.total_bounds[1] - 1 < track.lat.values)).reshape(-1)

        tc_list = []
        tr_coord = {'lat': [], 'lon': []}
        for node in range(idx_plt.size - 2):
            tr_piece = track.sel(
                time=slice(track.time.values[idx_plt[node]], track.time.values[
                    idx_plt[node + 2]]))
            tr_piece.attrs['n_nodes'] = 2  # plot only one node
            tr_sel = TCTracks()
            tr_sel.append(tr_piece)
            tr_coord['lat'].append(tr_sel.data[0].lat.values[:-1])
            tr_coord['lon'].append(tr_sel.data[0].lon.values[:-1])

            tc_tmp = TropCyclone()
            tc_tmp.set_from_tracks(tr_sel, centroids)
            tc_tmp.event_name = [
                track.name + ' ' + time.strftime(
                    "%d %h %Y %H:%M",
                    time.gmtime(tr_sel.data[0].time[1].values.astype(int) /
                                1000000000))
            ]
            tc_list.append(tc_tmp)

        if 'cmap' not in kwargs:
            kwargs['cmap'] = 'Greys'
        if 'vmin' not in kwargs:
            kwargs['vmin'] = np.array([tc_.intensity.min()
                                       for tc_ in tc_list]).min()
        if 'vmax' not in kwargs:
            kwargs['vmax'] = np.array([tc_.intensity.max()
                                       for tc_ in tc_list]).max()

        def run(node):
            tc_list[node].plot_intensity(1, axis=axis, **kwargs)
            axis.plot(tr_coord['lon'][node], tr_coord['lat'][node], 'k')
            axis.set_title(tc_list[node].event_name[0])
            pbar.update()

        if file_name:
            LOGGER.info('Generating video %s', file_name)
            fig, axis, fontsize = u_plot.make_map(
                figsize=figsize, adapt_fontsize=adapt_fontsize)
            pbar = tqdm(total=idx_plt.size - 2)
            ani = animation.FuncAnimation(fig,
                                          run,
                                          frames=idx_plt.size - 2,
                                          interval=500,
                                          blit=False)
            fig.tight_layout()
            ani.save(file_name, writer=writer)
            pbar.close()
        return tc_list, tr_coord
Exemple #10
0
    def video_intensity(track_name,
                        tracks,
                        centroids,
                        file_name=None,
                        writer=animation.PillowWriter(bitrate=500),
                        **kwargs):
        """Generate video of TC wind fields node by node and returns its
        corresponding TropCyclone instances and track pieces.

        Parameters:
            track_name (str): name of the track contained in tracks to record
            tracks (TCTracks): tracks
            centroids (Centroids): centroids where wind fields are mapped
            file_name (str, optional): file name to save video, if provided
            writer = (matplotlib.animation.*, optional): video writer. Default:
                pillow with bitrate=500
            kwargs (optional): arguments for pcolormesh matplotlib function
                used in event plots

        Returns:
            list(TropCyclone), list(np.array)

        Raises:
            ValueError
        """
        # initialization
        track = tracks.get_track(track_name)
        if not track:
            LOGGER.error('%s not found in track data.', track_name)
            raise ValueError
        idx_plt = np.argwhere(
            (track.lon.values < centroids.total_bounds[2] + 1)
            & (centroids.total_bounds[0] - 1 < track.lon.values)
            & (track.lat.values < centroids.total_bounds[3] + 1)
            & (centroids.total_bounds[1] - 1 < track.lat.values)).reshape(-1)

        tc_list = []
        tr_coord = {'lat': [], 'lon': []}
        for node in range(idx_plt.size - 2):
            tr_piece = track.sel(
                time=slice(track.time.values[idx_plt[node]], track.time.values[
                    idx_plt[node + 2]]))
            tr_piece.attrs['n_nodes'] = 2  # plot only one node
            tr_sel = TCTracks()
            tr_sel.append(tr_piece)
            tr_coord['lat'].append(tr_sel.data[0].lat.values[:-1])
            tr_coord['lon'].append(tr_sel.data[0].lon.values[:-1])

            tc_tmp = TropCyclone()
            tc_tmp.set_from_tracks(tr_sel, centroids)
            tc_tmp.event_name = [
                track.name + ' ' + time.strftime(
                    "%d %h %Y %H:%M",
                    time.gmtime(tr_sel.data[0].time[1].values.astype(int) /
                                1000000000))
            ]
            tc_list.append(tc_tmp)

        if 'cmap' not in kwargs:
            kwargs['cmap'] = 'Greys'
        if 'vmin' not in kwargs:
            kwargs['vmin'] = np.array([tc_.intensity.min()
                                       for tc_ in tc_list]).min()
        if 'vmax' not in kwargs:
            kwargs['vmax'] = np.array([tc_.intensity.max()
                                       for tc_ in tc_list]).max()

        def run(node):
            tc_list[node].plot_intensity(1, axis=axis, **kwargs)
            axis.plot(tr_coord['lon'][node], tr_coord['lat'][node], 'k')
            axis.set_title(tc_list[node].event_name[0])
            pbar.update()

        if file_name:
            LOGGER.info('Generating video %s', file_name)
            fig, axis = u_plot.make_map()
            pbar = tqdm(total=idx_plt.size - 2)
            ani = animation.FuncAnimation(fig,
                                          run,
                                          frames=idx_plt.size - 2,
                                          interval=500,
                                          blit=False)
            ani.save(file_name, writer=writer)
            pbar.close()
        return tc_list, tr_coord
Exemple #11
0
    def _plot_warn(
            self,
            run_datetime,
            thresholds,
            decision_level,
            decision_dict,
            polygon_file,
            polygon_file_crs,
            title,
            proj=ccrs.PlateCarree(),
            figsize=(9, 13),
            adapt_fontsize=True,
    ):
        """plotting the warning level of each warning region based on thresholds"""
        # select hazard with run_datetime
        # pylint: disable=protected-access
        if run_datetime is None:
            run_datetime = self.run_datetime[0]
        haz_ind = np.argwhere(np.isin(self.run_datetime, run_datetime))[0][0]

        kwargs = dict()
        kwargs["cmap"] = CMAP_WARNPROB
        kwargs["s"] = 5
        kwargs["marker"] = ","
        kwargs["norm"] = BoundaryNorm(np.linspace(0, 1, 11),
                                      CMAP_WARNPROB.N,
                                      clip=True)

        # Generate each subplot
        fig, axis, _fontsize = u_plot.make_map(1,
                                               proj=proj,
                                               figsize=figsize,
                                               adapt_fontsize=adapt_fontsize)
        if isinstance(axis, np.ndarray):
            axis = axis[0]
        tit = title
        fig.set_size_inches(9, 8)

        # add warning regions
        shp = shapereader.Reader(polygon_file)
        transformer = pyproj.Transformer.from_crs(polygon_file_crs,
                                                  self._impact[haz_ind].crs,
                                                  always_xy=True)
        # checking the decision dict and define the corresponding functions
        if not (isinstance(decision_dict["probability_aggregation"], float)
                & isinstance(decision_dict["area_aggregation"], float)):
            ValueError(" If decision_level is 'exposure_point'," +
                       "parameters probability_aggregation and " +
                       "area_aggregation of " +
                       "Forecast.plot_warn_map() must both be " +
                       "floats between [0..1]. Which each " +
                       "specify quantiles.")
        decision_dict_functions = decision_dict.copy()
        for aggregation in decision_dict:
            if isinstance(decision_dict[aggregation], float):
                decision_dict_functions[aggregation] = np.percentile
            elif decision_dict[aggregation] == "sum":
                decision_dict_functions[aggregation] = np.sum
            elif decision_dict[aggregation] == "mean":
                decision_dict_functions[aggregation] = np.mean
            else:
                raise ValueError("Parameter area_aggregation of " +
                                 "Forecast.plot_warn_map() must eiter be " +
                                 "a float between [0..1], which " +
                                 "specifys a quantile. or 'sum' or 'mean'.")

        for geometry, _ in zip(shp.geometries(), shp.records()):
            geom2 = shapely.ops.transform(transformer.transform, geometry)
            in_geom = u_coord.coord_on_land(
                lat=self._impact[haz_ind].coord_exp[:, 0],
                lon=self._impact[haz_ind].coord_exp[:, 1],
                land_geom=geom2,
            )
            if not in_geom.any():
                continue
            # decide warning level
            warn_level = 0
            for ind_i, warn_thres_i in enumerate(thresholds):
                if decision_level == "exposure_point":
                    # decision at each grid_point
                    probabilities = np.squeeze(
                        np.asarray((self._impact[haz_ind].imp_mat >=
                                    warn_thres_i).sum(axis=0) /
                                   self._impact[haz_ind].event_id.size))
                    # quantiles over probability
                    area = (probabilities[in_geom] >=
                            decision_dict["probability_aggregation"]).sum()
                    # quantiles over area
                    if area >= (in_geom.sum() *
                                decision_dict["area_aggregation"]):
                        warn_level = ind_i + 1
                elif decision_level == "polygon":
                    # aggregation over area
                    if isinstance(decision_dict["area_aggregation"], float):
                        value_per_member = decision_dict_functions[
                            "area_aggregation"](
                                self._impact[haz_ind].imp_mat[:,
                                                              in_geom].todense(
                                                              ),
                                decision_dict["area_aggregation"],
                                axis=1,
                            )
                    else:
                        value_per_member = decision_dict_functions[
                            "area_aggregation"](self._impact[haz_ind].
                                                imp_mat[:, in_geom].todense(),
                                                axis=1)
                    # aggregation over members/probability
                    if isinstance(decision_dict["probability_aggregation"],
                                  float):
                        value_per_region = decision_dict_functions[
                            "probability_aggregation"](
                                value_per_member,
                                decision_dict["probability_aggregation"])
                    else:
                        value_per_region = decision_dict_functions[
                            "probability_aggregation"](value_per_member)
                    # warn level decision
                    if value_per_region >= warn_thres_i:
                        warn_level = ind_i + 1
                else:
                    raise ValueError(
                        "Parameter decision_level of " +
                        "Forecast.plot_warn_map() must eiter be " +
                        "'exposure_point' or 'polygon'.")
            # plot warn_region with specific color (dependent on warning level)
            axis.add_geometries(
                [geom2],
                crs=ccrs.PlateCarree(),
                facecolor=COLORS_WARN[warn_level, :],
                edgecolor="gray",
            )

        # Create legend in this axis
        hazard_levels = [
            "1: Minimal or no hazard",
            "2: Moderate hazard",
            "3: Significant hazard",
            "4: Severe hazard",
            "5: Very severe hazard",
        ]
        legend_elements = [
            Patch(facecolor=COLORS_WARN[n, :],
                  edgecolor="gray",
                  label=hazard_level)
            for n, hazard_level in enumerate(hazard_levels)
        ]

        axis.legend(
            handles=legend_elements,
            loc="upper center",
            framealpha=0.5,
            bbox_to_anchor=(0.5, -0.02),
            ncol=3,
        )
        title_position = {
            "model_text": [0.02, 0.91],
            "explain_text": [0.02, 0.87],
            "event_day": [0.98, 0.91],
            "run_start": [0.98, 0.87],
        }
        left_right = {
            "model_text": "left",
            "explain_text": "left",
            "event_day": "right",
            "run_start": "right",
        }
        color = {
            "model_text": "k",
            "explain_text": "k",
            "event_day": "r",
            "run_start": "k",
        }
        for t_i in tit:
            plt.figtext(
                title_position[t_i][0],
                title_position[t_i][1],
                tit[t_i],
                fontsize="xx-large",
                color=color[t_i],
                ha=left_right[t_i],
            )

        extent = u_plot._get_borders(self._impact[haz_ind].coord_exp)
        axis.set_extent((extent), ccrs.PlateCarree())
        fig.tight_layout()
        return fig, axis
Exemple #12
0
    def _plot_exc_prob(
            self,
            run_datetime,
            threshold,
            title,
            cbar_label,
            proj=ccrs.PlateCarree(),
            polygon_file=None,
            polygon_file_crs="epsg:4326",
            mask=None,
            figsize=(9, 13),
            adapt_fontsize=True,
    ):
        """plot the probability of reaching a threshold"""
        # select hazard with run_datetime
        # pylint: disable=protected-access
        if run_datetime is None:
            run_datetime = self.run_datetime[0]
        haz_ind = np.argwhere(np.isin(self.run_datetime, run_datetime))[0][0]
        extend = "neither"
        value = np.squeeze(
            np.asarray(
                (self._impact[haz_ind].imp_mat > threshold).sum(axis=0) /
                self._impact[haz_ind].event_id.size))
        if mask is not None:
            value[np.invert(mask)] = np.nan
        coord = self._impact[haz_ind].coord_exp
        # Generate array of values used in each subplot
        array_sub = value
        shapes = True
        if not polygon_file:
            shapes = False
        var_name = cbar_label
        geo_coord = coord
        num_im, list_arr = u_plot._get_collection_arrays(array_sub)
        list_tit = to_list(num_im, title, "title")
        list_name = to_list(num_im, var_name, "var_name")
        list_coord = to_list(num_im, geo_coord, "geo_coord")

        kwargs = dict()
        kwargs["cmap"] = CMAP_WARNPROB
        kwargs["s"] = 5
        kwargs["marker"] = ","
        kwargs["norm"] = BoundaryNorm(np.linspace(0, 1, 11),
                                      CMAP_WARNPROB.N,
                                      clip=True)

        # Generate each subplot
        fig, axis_sub, _fontsize = u_plot.make_map(
            num_im, proj=proj, figsize=figsize, adapt_fontsize=adapt_fontsize)
        if not isinstance(axis_sub, np.ndarray):
            axis_sub = np.array([[axis_sub]])
        fig.set_size_inches(9, 8)
        for array_im, axis, tit, name, coord in zip(list_arr,
                                                    axis_sub.flatten(),
                                                    list_tit, list_name,
                                                    list_coord):
            if coord.shape[0] != array_im.size:
                raise ValueError("Size mismatch in input array: %s != %s." %
                                 (coord.shape[0], array_im.size))

            hex_bin = axis.scatter(coord[:, 1],
                                   coord[:, 0],
                                   c=array_im,
                                   transform=ccrs.PlateCarree(),
                                   **kwargs)
            if shapes:
                # add warning regions
                shp = shapereader.Reader(polygon_file)
                transformer = pyproj.Transformer.from_crs(
                    polygon_file_crs,
                    self._impact[haz_ind].crs,
                    always_xy=True)
                for geometry, _ in zip(shp.geometries(), shp.records()):
                    geom2 = shapely.ops.transform(transformer.transform,
                                                  geometry)
                    axis.add_geometries(
                        [geom2],
                        crs=ccrs.PlateCarree(),
                        facecolor="none",
                        edgecolor="gray",
                    )

            # Create colorbar in this axis
            cbax = make_axes_locatable(axis).append_axes("bottom",
                                                         size="6.5%",
                                                         pad=0.3,
                                                         axes_class=plt.Axes)
            cbar = plt.colorbar(hex_bin,
                                cax=cbax,
                                orientation="horizontal",
                                extend=extend)
            cbar.set_label(name)
            title_position = {
                "model_text": [0.02, 0.94],
                "explain_text": [0.02, 0.9],
                "event_day": [0.98, 0.94],
                "run_start": [0.98, 0.9],
            }
            left_right = {
                "model_text": "left",
                "explain_text": "left",
                "event_day": "right",
                "run_start": "right",
            }
            color = {
                "model_text": "k",
                "explain_text": "k",
                "event_day": "r",
                "run_start": "k",
            }
            for t_i in tit:
                plt.figtext(
                    title_position[t_i][0],
                    title_position[t_i][1],
                    tit[t_i],
                    fontsize="xx-large",
                    color=color[t_i],
                    ha=left_right[t_i],
                )
            extent = u_plot._get_borders(coord)
            axis.set_extent((extent), ccrs.PlateCarree())
        fig.tight_layout()
        return fig, axis_sub
Exemple #13
0
    def _plot_imp_map(
            self,
            run_datetime,
            title,
            cbar_label,
            polygon_file=None,
            polygon_file_crs="epsg:4326",
            proj=ccrs.PlateCarree(),
            figsize=(9, 13),
            adapt_fontsize=True,
    ):
        # select hazard with run_datetime
        # pylint: disable=protected-access
        if run_datetime is None:
            run_datetime = self.run_datetime[0]
        haz_ind = np.argwhere(np.isin(self.run_datetime, run_datetime))[0][0]
        # tryout new plot with right projection
        extend = "neither"
        value = self._impact[haz_ind].eai_exp
        #    value[np.invert(mask)] = np.nan
        coord = self._impact[haz_ind].coord_exp

        # Generate array of values used in each subplot
        array_sub = value
        shapes = True
        if not polygon_file:
            shapes = False
        var_name = cbar_label
        geo_coord = coord
        num_im, list_arr = u_plot._get_collection_arrays(array_sub)
        list_tit = to_list(num_im, title, "title")
        list_name = to_list(num_im, var_name, "var_name")
        list_coord = to_list(num_im, geo_coord, "geo_coord")

        kwargs = dict()
        kwargs["cmap"] = CMAP_IMPACT
        kwargs["s"] = 5
        kwargs["marker"] = ","
        kwargs["norm"] = BoundaryNorm(
            np.append(
                np.append([0], [10**x for x in np.arange(0, 2.9, 2.9 / 9)]),
                [10**x for x in np.arange(3, 7, 4 / 90)],
            ),
            CMAP_IMPACT.N,
            clip=True,
        )

        # Generate each subplot
        fig, axis_sub, _fontsize = u_plot.make_map(
            num_im, proj=proj, figsize=figsize, adapt_fontsize=adapt_fontsize)
        if not isinstance(axis_sub, np.ndarray):
            axis_sub = np.array([[axis_sub]])
        fig.set_size_inches(9, 8)
        for array_im, axis, tit, name, coord in zip(list_arr,
                                                    axis_sub.flatten(),
                                                    list_tit, list_name,
                                                    list_coord):
            if coord.shape[0] != array_im.size:
                raise ValueError("Size mismatch in input array: %s != %s." %
                                 (coord.shape[0], array_im.size))
            # Binned image with coastlines
            extent = u_plot._get_borders(coord)
            axis.set_extent((extent), ccrs.PlateCarree())
            hex_bin = axis.scatter(coord[:, 1],
                                   coord[:, 0],
                                   c=array_im,
                                   transform=ccrs.PlateCarree(),
                                   **kwargs)
            if shapes:
                # add warning regions
                shp = shapereader.Reader(polygon_file)
                transformer = pyproj.Transformer.from_crs(
                    polygon_file_crs,
                    self._impact[haz_ind].crs,
                    always_xy=True)
                for geometry, _ in zip(shp.geometries(), shp.records()):
                    geom2 = shapely.ops.transform(transformer.transform,
                                                  geometry)
                    axis.add_geometries(
                        [geom2],
                        crs=ccrs.PlateCarree(),
                        facecolor="none",
                        edgecolor="gray",
                    )
            else:  # add country boundaries
                u_plot.add_shapes(axis)
            # Create colorbar in this axis
            cbax = make_axes_locatable(axis).append_axes("bottom",
                                                         size="6.5%",
                                                         pad=0.3,
                                                         axes_class=plt.Axes)
            cbar = plt.colorbar(hex_bin,
                                cax=cbax,
                                orientation="horizontal",
                                extend=extend)
            cbar.set_label(name)
            cbar.formatter.set_scientific(False)
            cbar.set_ticks([0, 1000, 10000, 100000, 1000000])
            cbar.set_ticklabels(
                ["0", "1 000", "10 000", "100 000", "1 000 000"])
            title_position = {
                "model_text": [0.02, 0.85],
                "explain_text": [0.02, 0.81],
                "event_day": [0.98, 0.85],
                "run_start": [0.98, 0.81],
            }
            left_right = {
                "model_text": "left",
                "explain_text": "left",
                "event_day": "right",
                "run_start": "right",
            }
            color = {
                "model_text": "k",
                "explain_text": "k",
                "event_day": "r",
                "run_start": "k",
            }
            for t_i in tit:
                plt.figtext(
                    title_position[t_i][0],
                    title_position[t_i][1],
                    tit[t_i],
                    fontsize="xx-large",
                    color=color[t_i],
                    ha=left_right[t_i],
                )

        fig.tight_layout()
        fig.subplots_adjust(top=0.8)
        return fig, axis_sub
Exemple #14
0
    def _plot_exc_prob(self,
                       run_datetime,
                       threshold,
                       title,
                       cbar_label,
                       proj=ccrs.PlateCarree(),
                       polygon_file=None,
                       polygon_file_crs='epsg:4326',
                       mask=None,
                       figsize=(9, 13)):
        """  plot the probability of reaching a threshold """
        # select hazard with run_datetime
        if run_datetime is None:
            run_datetime = self.run_datetime[0]
        haz_ind = np.argwhere(np.isin(self.run_datetime, run_datetime))[0][0]
        extend = 'neither'
        value = np.squeeze(
            np.asarray(
                (self._impact[haz_ind].imp_mat > threshold).sum(axis=0) /
                self._impact[haz_ind].event_id.size))
        if mask is not None:
            value[np.invert(mask)] = np.nan
        coord = self._impact[haz_ind].coord_exp
        # Generate array of values used in each subplot
        array_sub = value
        shapes = True
        if not polygon_file:
            shapes = False
        var_name = cbar_label
        geo_coord = coord
        num_im, list_arr = u_plot._get_collection_arrays(array_sub)
        list_tit = to_list(num_im, title, 'title')
        list_name = to_list(num_im, var_name, 'var_name')
        list_coord = to_list(num_im, geo_coord, 'geo_coord')

        kwargs = dict()
        kwargs['cmap'] = CMAP_WARNPROB
        kwargs['s'] = 5
        kwargs['marker'] = ','
        kwargs['norm'] = BoundaryNorm(np.linspace(0, 1, 11),
                                      CMAP_WARNPROB.N,
                                      clip=True)

        # Generate each subplot
        fig, axis_sub = u_plot.make_map(num_im, proj=proj, figsize=figsize)
        if not isinstance(axis_sub, np.ndarray):
            axis_sub = np.array([[axis_sub]])
        fig.set_size_inches(9, 8)
        for array_im, axis, tit, name, coord in zip(list_arr,
                                                    axis_sub.flatten(),
                                                    list_tit, list_name,
                                                    list_coord):
            if coord.shape[0] != array_im.size:
                raise ValueError("Size mismatch in input array: %s != %s." % \
                                 (coord.shape[0], array_im.size))

            hex_bin = axis.scatter(coord[:, 1], coord[:, 0], c=array_im, \
                                   transform=ccrs.PlateCarree(), **kwargs)
            if shapes:
                # add warning regions
                shp = shapereader.Reader(polygon_file)
                transformer = pyproj.Transformer.from_crs(
                    polygon_file_crs,
                    self._impact[haz_ind].crs,
                    always_xy=True)
                for geometry, _ in zip(shp.geometries(), shp.records()):
                    geom2 = shapely.ops.transform(transformer.transform,
                                                  geometry)
                    axis.add_geometries([geom2], crs=ccrs.PlateCarree(), facecolor='', \
                                        edgecolor='gray')

            # Create colorbar in this axis
            cbax = make_axes_locatable(axis).append_axes('bottom', size="6.5%", \
                                                         pad=0.3, axes_class=plt.Axes)
            cbar = plt.colorbar(hex_bin,
                                cax=cbax,
                                orientation='horizontal',
                                extend=extend)
            cbar.set_label(name)
            title_position = {
                'model_text': [0.02, 0.94],
                'explain_text': [0.02, 0.9],
                'event_day': [0.98, 0.94],
                'run_start': [0.98, 0.9]
            }
            left_right = {
                'model_text': 'left',
                'explain_text': 'left',
                'event_day': 'right',
                'run_start': 'right'
            }
            color = {
                'model_text': 'k',
                'explain_text': 'k',
                'event_day': 'r',
                'run_start': 'k'
            }
            for t_i in tit:
                plt.figtext(title_position[t_i][0],
                            title_position[t_i][1],
                            tit[t_i],
                            fontsize='xx-large',
                            color=color[t_i],
                            ha=left_right[t_i])
            extent = u_plot._get_borders(coord)
            axis.set_extent((extent), ccrs.PlateCarree())

        return fig, axis_sub
Exemple #15
0
    def plot_raster(self,
                    res=None,
                    raster_res=None,
                    save_tiff=None,
                    raster_f=lambda x: np.log10((np.fmax(x + 1, 1))),
                    label='value (log10)',
                    scheduler=None,
                    axis=None,
                    figsize=(9, 13),
                    fill=True,
                    adapt_fontsize=True,
                    **kwargs):
        """Generate raster from points geometry and plot it using log10 scale:
        np.log10((np.fmax(raster+1, 1))).

        Parameters
        ----------
        res : float, optional
            resolution of current data in units of latitude
            and longitude, approximated if not provided.
        raster_res : float, optional
            desired resolution of the raster
        save_tiff : str, optional
            file name to save the raster in tiff
            format, if provided
        raster_f : lambda function
            transformation to use to data. Default:
            log10 adding 1.
        label : str
            colorbar label
        scheduler : str
            used for dask map_partitions. “threads”,
            “synchronous” or “processes”
        axis : matplotlib.axes._subplots.AxesSubplot, optional
            axis to use
        figsize : tuple, optional
            figure size for plt.subplots
        fill : bool, optional
            If false, the areas with no data will be plotted
            in white. If True, the areas with missing values are filled as 0s.
            The default is True.
        adapt_fontsize : bool, optional
            If set to true, the size of the fonts will be adapted to the size of the figure.
            Otherwise the default matplotlib font size is used. Default is True.
        kwargs : optional
            arguments for imshow matplotlib function

        Returns
        -------
        matplotlib.figure.Figure, cartopy.mpl.geoaxes.GeoAxesSubplot
        """
        if self.meta and self.meta.get('height', 0) * self.meta.get(
                'height', 0) == len(self.gdf):
            raster = self.gdf.value.values.reshape(
                (self.meta['height'], self.meta['width']))
            # check raster starts by upper left corner
            if self.gdf.latitude.values[0] < self.gdf.latitude.values[-1]:
                raster = np.flip(raster, axis=0)
            if self.gdf.longitude.values[0] > self.gdf.longitude.values[-1]:
                raise ValueError(
                    'Points are not ordered according to meta raster.')
        else:
            raster, meta = u_coord.points_to_raster(self.gdf, ['value'], res,
                                                    raster_res, scheduler)
            raster = raster.reshape((meta['height'], meta['width']))
        # save tiff
        if save_tiff is not None:
            with rasterio.open(save_tiff,
                               'w',
                               driver='GTiff',
                               height=meta['height'],
                               width=meta['width'],
                               count=1,
                               dtype=np.float32,
                               crs=self.crs,
                               transform=meta['transform']) as ras_tiff:
                ras_tiff.write(raster.astype(np.float32), 1)
        # make plot
        proj_data, _ = u_plot.get_transformation(self.crs)
        proj_plot = proj_data
        if isinstance(proj_data, ccrs.PlateCarree):
            # use different projections for plot and data to shift the central lon in the plot
            xmin, ymin, xmax, ymax = u_coord.latlon_bounds(
                self.gdf.latitude.values, self.gdf.longitude.values)
            proj_plot = ccrs.PlateCarree(central_longitude=0.5 * (xmin + xmax))
        else:
            xmin, ymin, xmax, ymax = (self.gdf.longitude.min(),
                                      self.gdf.latitude.min(),
                                      self.gdf.longitude.max(),
                                      self.gdf.latitude.max())

        if not axis:
            _, axis, fontsize = u_plot.make_map(proj=proj_plot,
                                                figsize=figsize,
                                                adapt_fontsize=adapt_fontsize)
        else:
            fontsize = None
        cbar_ax = make_axes_locatable(axis).append_axes('right',
                                                        size="6.5%",
                                                        pad=0.1,
                                                        axes_class=plt.Axes)
        axis.set_extent((xmin, xmax, ymin, ymax), crs=proj_data)
        u_plot.add_shapes(axis)
        if not fill:
            raster = np.where(raster == 0, np.nan, raster)
            raster_f = lambda x: np.log10((np.maximum(x + 1, 1)))
        if 'cmap' not in kwargs:
            kwargs['cmap'] = CMAP_RASTER
        imag = axis.imshow(raster_f(raster),
                           **kwargs,
                           origin='upper',
                           extent=(xmin, xmax, ymin, ymax),
                           transform=proj_data)
        cbar = plt.colorbar(imag, cax=cbar_ax, label=label)
        plt.colorbar(imag, cax=cbar_ax, label=label)
        plt.tight_layout()
        plt.draw()
        if fontsize:
            cbar.ax.tick_params(labelsize=fontsize)
            cbar.ax.yaxis.get_offset_text().set_fontsize(fontsize)
            for item in [axis.title, cbar.ax.xaxis.label, cbar.ax.yaxis.label]:
                item.set_fontsize(fontsize)
        return axis