Ejemplo n.º 1
0
    def plot(self,
             flush_cache=True,
             norm=True,
             clip_percentage=(0.02, 0.98),
             clip_min_max=None,
             log=False,
             rescale_percentage=None,
             bands=None,
             ax=None,
             title=None,
             cmap=None,
             figsize=None):
        """Plot the raster object.

        Parameters
        ----------
        flush_cache: bool. 
            Flush the cached processed result for quick plotting.
        norm: bool, optional, default: True
            Normalize the image for showing.
        clip_percentage: tuple of float, optional, default: (0.02, 0.98)
            The percentage to cut the data in head and tail e.g. (0.02, 0.98)
        log: bool, optional, default: False
            Get the log value of data to show the image.
        rescale_percentage: float, optional
            The percentage to recale (resize) the image for efficient showing.
        bands: list, optional
            Which bands to plot. Length of bands should be 1, 3 or 4.
            If 3 bands is used, each of them will be defined as rgb bands. 
            If the forth band is used, it will be the opacity value.
        ax: matplotlib.axes._subplots.AxesSubplot, optional
            On which ax the raster will be plot.
        title: str, optional
            The title of the histgram.
        cmap: str, optional
            See Colormaps in Matplotlib https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html.
        figsize: tuple, optional
            Width and height of the histgram e.g.(10, 10).
        """
        if bands is None:
            bands = [0, 1, 2] if self.bands >= 3 else [0]

        assert type(bands) is list, "type of bands should be list"
        assert len(bands) in [1, 3, 4], "length of bands should be 1, 3 or 4"

        if (self.cache_data_for_plot is None) or flush_cache:
            # reshape to valid shape for matplotlib
            if len(bands) == 1:
                data = self.data[:, :, bands[0]]
            else:
                data = self.data[:, :, bands]

            # deal with no data
            data = data.astype(np.float)
            data[data == self.no_data_value] = np.nan

            # detect single value
            if len(np.unique(data[~np.isnan(data)])) == 1:
                norm = False
                log = False
                clip_percentage = None

            # clip_percentage & clip_min_max
            if clip_percentage is not None:
                assert not (
                    clip_percentage is not None and clip_min_max is not None
                ), "should not set clip_percentage and clip_min_max at the same time!"
                assert len(
                    clip_percentage) == 2, "clip_percentage two element tuple"
                data = tgp.Normalizer().clip_by_percentage(
                    data, clip_percentage=clip_percentage)
            elif clip_min_max is not None:
                assert len(clip_min_max) == 2, "clip_min_max two element tuple"
                data = tgp.Normalizer().clip_by_min_max(data,
                                                        min_max=clip_min_max)

            # log
            if log:
                if data[~np.isnan(data)].min() < 0:
                    data -= data[~np.isnan(data)].min()
                data[~np.isnan(data)] = np.log(data[~np.isnan(data)] + 10**-6)

            # normalize
            if norm:
                data = tgp.Normalizer().fit_transform(data)

            if rescale_percentage is not None:
                import cv2
                data = cv2.resize(data, (int(self.cols * rescale_percentage),
                                         int(self.rows * rescale_percentage)))

            self.cache_data_for_plot = data
        else:
            data = self.cache_data_for_plot

        # flip xy
        c, a, b, f, d, e = self.geo_transform
        # lng = a * col + b * row + c
        # lat = d * col + e * row + f
        # a = d(lng) / d(col)
        # b = d(lng) / d(row)
        # d = d(lat) / d(col)
        # e = d(lat) / d(row)
        if (np.abs(a) > np.abs(d)) and (np.abs(e) > np.abs(b)):
            lng_res, lat_res = a, e
        elif (np.abs(d) > np.abs(a)) and (
                np.abs(b) > np.abs(e)
        ):  # if d > a, 1 col move contribute more on lat, less on lng
            data = np.flipud(np.rot90(data))
            lng_res, lat_res = d, b
        else:
            assert False, "not acceptable geotransform"
        if lng_res < 0:  # general lng_res > 0
            data = np.fliplr(data)
        if lat_res > 0:  # general lat_res < 0
            data = np.flipud(data)

        # plotting
        if ax is not None:
            img = ax.imshow(data, extent=self.extent_for_plot, cmap=cmap)
            ax.set_title(title)
        else:
            if figsize is not None:
                plt.figure(figsize=figsize)
            img = plt.imshow(data, extent=self.extent_for_plot, cmap=cmap)
            plt.title(title)
            plt.show()
        return img
Ejemplo n.º 2
0
    def hist(self,
             norm=False,
             clip_percentage=None,
             log=False,
             bands=None,
             ax=None,
             title=None,
             figsize=None):
        """plot digital value histgram (distribution) of raster object.

        Parameters
        ----------
        norm: bool, optional, default: False
            Normalize the image for showing.
        clip_percentage: tuple of float, optional
            The percentage to cut the data in head and tail e.g. (0.02, 0.98)
        log: bool, optional, default: False
            Use the log value to plot the histgram.
        bands: list, optional
            Which bands to plot. if bands==None, use values from all bands.
        ax: matplotlib.axes._subplots.AxesSubplot, optional
            On which ax the raster will be plot.
        title: str, optional
            The title of the histgram.
        figsize: tuple, optional
            Width and height of the histgram e.g.(10, 10).
        """
        if bands is None:
            data = self.data[self.data != self.no_data_value].flatten()
        else:
            data = self.data[:, :, bands]
            data = data[data != self.no_data_value].flatten()

        # clip_percentage
        if clip_percentage is not None:
            assert len(
                clip_percentage) == 2, "clip_percentage two element tuple"
            idx_st = int(len(data.flatten()) * clip_percentage[0])
            idx_end = int(len(data.flatten()) * clip_percentage[1])
            X_sorted = np.sort(data.flatten())
            data_min = X_sorted[idx_st]
            data_max = X_sorted[idx_end]
            data[data < data_min] = data_min
            data[data > data_max] = data_max

        # log
        if log:
            data = np.log(data)

        # normalize
        if norm:
            data = tgp.Normalizer().fit_transform(
                data, clip_percentage=clip_percentage)

        if ax is not None:
            ax.hist(data)
            ax.set_title(title)
        else:
            if figsize is not None:
                plt.figure(figsize=figsize)
            plt.hist(data)
            plt.title(title)
            plt.show()