Example #1
0
def get_coordinates(eopatch, feature, crs):
    """ Creates coordinates for xarray DataArray

    :param eopatch: eopatch
    :type eopatch: EOPatch
    :param feature: feature of eopatch
    :type feature: (FeatureType, str)
    :param crs: convert spatial coordinates to crs
    :type crs: sentinelhub.crs
    :return: coordinates for xarry DataArray/Dataset
    :rtype: dict
    """

    features = list(FeatureParser(feature))
    feature_type, feature_name = features[0]
    original_crs = eopatch.bbox.crs
    if crs and original_crs != crs:
        bbox = eopatch.bbox.transform(crs)
    else:
        bbox = eopatch.bbox
    data = eopatch[feature_type][feature_name]
    timestamps = eopatch.timestamp

    if feature_type in FeatureTypeSet.RASTER_TYPES_4D:
        return {**_get_temporal_coordinates(timestamps),
                **_get_spatial_coordinates(bbox, data, feature_type),
                **_get_depth_coordinates(data=data, feature_name=feature_name)}
    if feature_type in FeatureTypeSet.RASTER_TYPES_2D:
        return {**_get_temporal_coordinates(timestamps),
                **_get_depth_coordinates(data=data, feature_name=feature_name)}
    if feature_type in FeatureTypeSet.RASTER_TYPES_3D:
        return {**_get_spatial_coordinates(bbox, data, feature_type),
                **_get_depth_coordinates(data=data, feature_name=feature_name)}
    return _get_depth_coordinates(data=data, feature_name=feature_name)
Example #2
0
def array_to_dataframe(eopatch, feature, remove_depth=True, crs=None):
    """ Converts one feature of eopatch to xarray DataArray

    :param eopatch: eopatch
    :type eopatch: EOPatch
    :param feature: feature of eopatch
    :type feature: (FeatureType, str)
    :param remove_depth: removes last dimension if it is one
    :type remove_depth: bool
    :param crs: converts dimensions to crs
    :type crs: sentinelhub.crs
    :return: dataarray
    :rtype: xarray DataArray
    """
    features = list(FeatureParser(feature))
    feature_type, feature_name = features[0]
    bbox = eopatch.bbox
    data = eopatch[feature_type][feature_name]
    if isinstance(data, xr.DataArray):
        data = data.values
    dimensions = get_dimensions(feature)
    coordinates = get_coordinates(eopatch, feature, crs=crs)
    dataframe = xr.DataArray(data=data,
                             coords=coordinates,
                             dims=dimensions,
                             attrs={'crs': str(bbox.crs),
                                    'feature_type': feature_type,
                                    'feature_name': feature_name},
                             name=string_to_variable(feature_name))

    if remove_depth and dataframe.values.shape[-1] == 1:
        dataframe = dataframe.squeeze()
        dataframe = dataframe.drop(feature_name + '_dim')

    return dataframe
Example #3
0
def get_dimensions(feature):
    """ Returns list of dimensions for xarray DataArray/Dataset

    :param feature: eopatch feature
    :type feature: (FeatureType, str)
    :return: dimensions for xarray DataArray/Dataset
    :rtype: list(str)
    """
    features = list(FeatureParser(feature))
    feature_type, feature_name = features[0]
    depth = string_to_variable(feature_name, '_dim')
    if feature_type in FeatureTypeSet.RASTER_TYPES_4D:
        return ['time', 'y', 'x', depth]
    if feature_type in FeatureTypeSet.RASTER_TYPES_2D:
        return ['time', depth]
    if feature_type in FeatureTypeSet.RASTER_TYPES_3D:
        return ['y', 'x', depth]
    return [depth]
    def plot(self):
        """ Plots eopatch

        :return: plot
        :rtype: holovies/bokeh
        """

        features = list(FeatureParser(self.feature))
        feature_type, feature_name = features[0]
        if self.pixel and feature_type in FeatureTypeSet.RASTER_TYPES_4D:
            vis = self.plot_pixel(feature_type, feature_name)
        elif feature_type in (FeatureType.MASK,
                              *FeatureTypeSet.RASTER_TYPES_3D):
            vis = self.plot_raster(feature_type, feature_name)
        elif feature_type is FeatureType.DATA:
            vis = self.plot_data(feature_name)
        elif feature_type is FeatureType.VECTOR:
            vis = self.plot_vector(feature_name)
        elif feature_type is FeatureType.VECTOR_TIMELESS:
            vis = self.plot_vector_timeless(feature_name)
        else:  # elif feature_type in (FeatureType.SCALAR, FeatureType.LABEL):
            vis = self.plot_scalar_label(feature_type, feature_name)

        return vis.opts(plot=dict(width=PLOT_WIDTH, height=PLOT_HEIGHT))
Example #5
0
    def __init__(self,
                 class_feature,
                 samples_amount=0.1,
                 valid_mask=None,
                 ignore_labels=None,
                 features=None,
                 weak_classes=None,
                 search_radius=3,
                 samples_per_class=None,
                 seed=None):
        """
        :param class_feature: Feature that contains class labels
        :type class_feature: (FeatureType, string) or string
        :param samples_amount: Number of samples taken per patch. If the number is on the interval of [0...1] then that
            percentage of all points is taken. If the value is 1 all eligible points are taken.
        :type samples_amount: float
        :param valid_mask: Feature that defines the area from where samples are
            taken, if None the whole image is used
        :type valid_mask: (FeatureType, string), string or None
        :param ignore_labels: A single item or a list of values that should not be sampled.
        :type ignore_labels: list of integers or int
        :param features: Temporal features to include in dataset for each pixel sampled
        :type features: Input that the FeatureParser class can parse
        :param samples_per_class: Number of samples per class returned after
            balancing. If the number is higher than total amount of some classes, then those classes have their
            points duplicated to reach the desired amount. If the argument is None then limit is set to the size of
            the number of samples of the smallest class
        :type samples_per_class: int or None
        :param seed: Seed for random generator
        :type seed: int
        :param weak_classes: Classes that upon finding, also the neighbouring regions
            will be checked and added if they contain one of the weak classes. Used to enrich the samples
        :type weak_classes: list of integers or int
        :param search_radius: How many points in each direction to check for additional weak classes
        :type search_radius: int
        """
        self.class_feature = next(
            FeatureParser(class_feature,
                          default_feature_type=FeatureType.MASK_TIMELESS)())
        self.samples_amount = samples_amount
        self.valid_mask = next(
            FeatureParser(valid_mask,
                          default_feature_type=FeatureType.MASK_TIMELESS)
            ()) if valid_mask else None
        self.ignore_labels = ignore_labels if isinstance(
            ignore_labels, list) else [ignore_labels]
        self.features = FeatureParser(features,
                                      default_feature_type=FeatureType.
                                      DATA_TIMELESS) if features else None
        self.columns = [self.class_feature[1]] + ['patch_identifier', 'x', 'y']
        if features:
            self.columns += [x[1] for x in self.features]

        self.samples_per_class = samples_per_class
        self.seed = seed
        if seed is not None:
            random.seed(self.seed)
        self.weak_classes = weak_classes if isinstance(
            weak_classes, list) else [weak_classes]
        self.search_radius = search_radius
        self.sampled_data = []
        self.balanced_data = None
        self.class_distribution = None