Пример #1
0
    def _generate_initial_gml_db(self):
        """
        Generates the initial slice in gml for importing using the database method and returns the gml for it
        :rtype: File
        """
        # Transform the axes domains such that only a point is defined.
        # For the first slice we need to import a single point, which will then be updated with the real data
        axes_map = OrderedDict()
        for axis, grid_axis in self.coverage.get_insert_axes().items():
            if axis.coefficient is not None:
                assert type(axis.coefficient) == list, "Axis coefficients not of type list."
                assert len(axis.coefficient) > 0, "The list of coefficients is empty."
                # Get the first coefficient in irregular coverage  to create a initial slice
                axis = IrregularAxis(axis.label, axis.uomLabel, axis.low, axis.high, axis.origin, [axis.coefficient[0]],
                                     axis.crs_axis)
            axes_map[axis] = GridAxis(grid_axis.order, grid_axis.label, grid_axis.resolution, 0, 0)
        metadata_provider = MetadataProvider(self.coverage.coverage_id, axes_map,
                                             self.coverage.range_fields, self.coverage.crs, self.coverage.metadata,
                                             self.grid_coverage)
        tuple_list = []

        # Tuple list for InsertCoverage request should be created from null values if they exist
        for range_field in self.coverage.range_fields:
            # If band doesn't have null value, default insert value is 0
            insert_value = self.DEFAULT_INSERT_VALUE
            if (range_field.nilValues is not None) and (len(range_field.nilValues) > 0):
                insert_value = strip_trailing_zeros(range_field.nilValues[0].value.split(":")[0])
                if insert_value == "":
                    insert_value = self.DEFAULT_INSERT_VALUE

            tuple_list.append(insert_value)

        data_provider = TupleListDataProvider(",".join(tuple_list))
        mediator = Mediator(metadata_provider, data_provider)
        return mediator.get_gml_file() if ConfigManager.mock else mediator.get_gml_str()
Пример #2
0
    def _fill_grid_axis(self):
        grid_axis_x = GridAxis(0, "", self.gdal_dataset.get_resolution_x(), 0,
                               self.gdal_dataset.get_raster_x_size() - 1)
        grid_axis_y = GridAxis(1, "", self.gdal_dataset.get_resolution_y(), 0,
                               self.gdal_dataset.get_raster_y_size() - 1)
        for i in range(0, len(self.subsets)):
            if self.subsets[i].coverage_axis.axis.crs_axis.is_easting():
                grid_axis_x.label = self.subsets[i].coverage_axis.axis.label
                self.subsets[i].coverage_axis.grid_axis = grid_axis_x
            elif self.subsets[i].coverage_axis.axis.crs_axis.is_northing():
                grid_axis_y.label = self.subsets[i].coverage_axis.axis.label
                self.subsets[i].coverage_axis.grid_axis = grid_axis_y
            else:
                self.subsets[i].coverage_axis.grid_axis = GridAxis(i, self.subsets[i].coverage_axis.axis.label, 1, 0, 0)

        return self.subsets
Пример #3
0
 def _generate_initial_gml_db(self):
     """
     Generates the initial slice in gml for importing using the database method and returns the gml for it
     :rtype: File
     """
     # Transform the axes domains such that only a point is defined.
     # For the first slice we need to import a single point, which will then be updated with the real data
     axes_map = OrderedDict()
     for axis, grid_axis in self.coverage.get_insert_axes().iteritems():
         if axis.coefficient is not None:
             assert type(axis.coefficient
                         ) == list, "Axis coefficients not of type list."
             assert len(
                 axis.coefficient) > 0, "The list of coefficients is empty."
             # Get the first coefficient in irregular coverage  to create a initial slice
             axis = IrregularAxis(axis.label, axis.uomLabel, axis.low,
                                  axis.high, axis.origin,
                                  [axis.coefficient[0]], axis.crs_axis)
         axes_map[axis] = GridAxis(grid_axis.order, grid_axis.label,
                                   grid_axis.resolution, 0, 0)
     metadata_provider = MetadataProvider(
         self.coverage.coverage_id, axes_map, self.coverage.range_fields,
         self.coverage.crs, self.coverage.metadata, self.grid_coverage)
     tuple_list = ",".join(['0'] * len(self.coverage.range_fields))
     data_provider = TupleListDataProvider(tuple_list)
     file = Mediator(metadata_provider, data_provider).get_gml_file()
     return file
Пример #4
0
    def _fill_grid_axis(self, timeseries_recipe=False):
        x_order = self.GRID_AXIS_X_ORDER
        y_order = self.GRID_AXIS_Y_ORDER

        if timeseries_recipe:
            x_order = self.GRID_AXIS_X_ORDER_SHIFTED
            y_order = self.GRID_AXIS_Y_ORDER_SHIFTED

        grid_axis_x = GridAxis(x_order, "",
                               self.gdal_dataset.get_resolution_x(), 0,
                               self.gdal_dataset.get_raster_x_size() - 1)
        grid_axis_y = GridAxis(y_order, "",
                               self.gdal_dataset.get_resolution_y(), 0,
                               self.gdal_dataset.get_raster_y_size() - 1)
        for i in range(0, len(self.subsets)):
            if self.subsets[i].coverage_axis.axis.crs_axis.is_x_axis():
                grid_axis_x.label = self.subsets[i].coverage_axis.axis.label
                self.subsets[i].coverage_axis.grid_axis = grid_axis_x
            elif self.subsets[i].coverage_axis.axis.crs_axis.is_y_axis():
                grid_axis_y.label = self.subsets[i].coverage_axis.axis.label
                self.subsets[i].coverage_axis.grid_axis = grid_axis_y
            else:
                self.subsets[i].coverage_axis.grid_axis = GridAxis(
                    i, self.subsets[i].coverage_axis.axis.label, 1, 0, 0)

        return self.subsets
Пример #5
0
    def _axis_subset(self, crs_axis, nc_file):
        """
        Returns an axis subset using the given crs axis in the context of the nc file
        :param CRSAxis crs_axis: the crs definition of the axis
        :param File nc_file: the netcdf file
        :rtype AxisSubset
        """
        user_axis = self._user_axis(self._get_user_axis_by_crs_axis_name(crs_axis.label), NetcdfEvaluatorSlice(nc_file))

        # Normally, without pixelIsPoint:true, in the ingredient needs to +/- 0.5 * resolution for each regular axis
        # e.g: resolution for axis E is 10000, then
        # "min": "${netcdf:variable:E:min} - 10000 / 2",
        # "max": "${netcdf:variable:E:max} + 10000 / 2",
        # with pixelIsPoint: true, no need to add these values as the service will do it automatically
        if self.pixel_is_point:
            PointPixelAdjuster.adjust_axis_bounds_to_continuous_space(user_axis, crs_axis)
        else:
            # No adjustment for all regular axes but still need to translate time in datetime to decimal to calculate
            if user_axis.type == UserAxisType.DATE:
                user_axis.interval.low = decimal.Decimal(str(arrow.get(user_axis.interval.low).float_timestamp))
                if user_axis.interval.high:
                    user_axis.interval.high = decimal.Decimal(str(arrow.get(user_axis.interval.high).float_timestamp))
            # if low < high, adjust it
            if user_axis.interval.high is not None and user_axis.interval.low > user_axis.interval.high:
                user_axis.interval.low, user_axis.interval.high = user_axis.interval.high, user_axis.interval.low

        high = user_axis.interval.high if user_axis.interval.high else user_axis.interval.low
        origin = PointPixelAdjuster.get_origin(user_axis, crs_axis)

        if isinstance(user_axis, RegularUserAxis):
            geo_axis = RegularAxis(crs_axis.label, crs_axis.uom, user_axis.interval.low, high, origin, crs_axis)
        else:
            if user_axis.type == UserAxisType.DATE:
                if crs_axis.is_uom_day():
                    coefficients = self._translate_day_date_direct_position_to_coefficients(user_axis.interval.low,
                                                                                            user_axis.directPositions)
                else:
                    coefficients = self._translate_seconds_date_direct_position_to_coefficients(user_axis.interval.low,
                                                                                                user_axis.directPositions)
            else:
                coefficients = self._translate_number_direct_position_to_coefficients(user_axis.interval.low,
                                                                                      user_axis.directPositions)
            geo_axis = IrregularAxis(crs_axis.label, crs_axis.uom, user_axis.interval.low, high, origin, coefficients, crs_axis)

        grid_low = 0
        grid_high = PointPixelAdjuster.get_grid_points(user_axis, crs_axis)

        # NOTE: Grid Coverage uses the direct intervals as in Rasdaman
        if self.grid_coverage is False and grid_high > grid_low:
            grid_high -= 1

        grid_axis = GridAxis(user_axis.order, crs_axis.label, user_axis.resolution, grid_low, grid_high)
        if user_axis.type == UserAxisType.DATE:
            self._translate_decimal_to_datetime(user_axis, geo_axis)

        return AxisSubset(CoverageAxis(geo_axis, grid_axis, user_axis.dataBound),
                          Interval(user_axis.interval.low, user_axis.interval.high))
Пример #6
0
    def _fill_grid_axis(self):
        grid_axis_x = GridAxis(0, "", self.gdal_dataset.get_resolution_x(), 0,
                               self.gdal_dataset.get_raster_x_size() - 1)
        grid_axis_y = GridAxis(1, "", self.gdal_dataset.get_resolution_y(), 0,
                               self.gdal_dataset.get_raster_y_size() - 1)
        for i in range(0, len(self.subsets)):
            if self.subsets[i].coverage_axis.axis.crs_axis.is_easting():
                grid_axis_x.label = self.subsets[i].coverage_axis.axis.label
                self.subsets[i].coverage_axis.grid_axis = grid_axis_x
            elif self.subsets[i].coverage_axis.axis.crs_axis.is_northing():
                grid_axis_y.label = self.subsets[i].coverage_axis.axis.label
                self.subsets[i].coverage_axis.grid_axis = grid_axis_y
            else:
                self.subsets[i].coverage_axis.grid_axis = GridAxis(
                    i, self.subsets[i].coverage_axis.axis.label, 1, 0, 0)

        return self.subsets
Пример #7
0
    def _get_coverage_axes(self, geo_coords, raster_coords, origin, crs_axes,
                           resolutions):
        """
        Generates the coverage axes for this coverage
        :param list[Interval] geo_coords: the geographical coords in the order of the gml
        :param list[Interval] raster_coords: the grid coords in the order of the grid (not necessarily the order of the geo axes)
        :param list[str] origin: the origin of the coverage
        :param list[CRSAxis] crs_axes: a list of the crs axes
        :param list[dict] resolutions: a list of triples containing the resolution, coefficient list and position in grid
        :rtype: list[CoverageAxis]
        """

        axis_index = 0
        coverage_axes = []
        for crs_axis in crs_axes:
            resolution = resolutions[axis_index]
            order = resolution['position']
            grid_axis = GridAxis(order, crs_axis.label,
                                 resolution['resolution'],
                                 raster_coords[order].low,
                                 raster_coords[order].high)
            if resolution['coefficient'] is not None:
                geo_axis = IrregularAxis(crs_axis.label, crs_axis.uom,
                                         geo_coords[axis_index].low,
                                         geo_coords[axis_index].high,
                                         origin[axis_index],
                                         resolution['coefficient'], crs_axis)
            else:
                geo_axis = RegularAxis(crs_axis.label, crs_axis.uom,
                                       geo_coords[axis_index].low,
                                       geo_coords[axis_index].high,
                                       origin[axis_index], crs_axis)
            data_bound = crs_axis.is_easting() or crs_axis.is_northing()
            coverage_axis = CoverageAxis(geo_axis, grid_axis, data_bound)
            coverage_axes.append(coverage_axis)
            axis_index += 1
        return coverage_axes
Пример #8
0
    def _axis_subset(self, crs_axis, evaluator_slice, resolution=None):
        """
        Returns an axis subset using the given crs axis in the context of the gdal file
        :param CRSAxis crs_axis: the crs definition of the axis
        :param GDALEvaluatorSlice evaluator_slice: the evaluator for GDAL file
        :param resolution: Known axis resolution, no need to evaluate sentence expression from ingredient file (e.g: Sentinel2 recipe)
        :rtype AxisSubset
        """
        user_axis = self._user_axis(
            self._get_user_axis_by_crs_axis_name(crs_axis.label),
            evaluator_slice)
        if resolution is not None:
            user_axis.resolution = resolution

        high = user_axis.interval.high if user_axis.interval.high is not None else user_axis.interval.low

        if user_axis.type == UserAxisType.DATE:
            # it must translate datetime string to float by arrow for calculating later
            user_axis.interval.low = arrow.get(
                user_axis.interval.low).float_timestamp
            if user_axis.interval.high is not None:
                user_axis.interval.high = arrow.get(
                    user_axis.interval.high).float_timestamp

        if isinstance(user_axis, RegularUserAxis):
            geo_axis = RegularAxis(crs_axis.label, crs_axis.uom,
                                   user_axis.interval.low, high,
                                   user_axis.interval.low, crs_axis)
        else:
            # Irregular axis (coefficients must be number, not datetime string)
            if user_axis.type == UserAxisType.DATE:
                if crs_axis.is_time_day_axis():
                    coefficients = self._translate_day_date_direct_position_to_coefficients(
                        user_axis.interval.low, user_axis.directPositions)
                else:
                    coefficients = self._translate_seconds_date_direct_position_to_coefficients(
                        user_axis.interval.low, user_axis.directPositions)
            else:
                coefficients = self._translate_number_direct_position_to_coefficients(
                    user_axis.interval.low, user_axis.directPositions)

            self._update_for_slice_group_size(self.coverage_id, user_axis,
                                              crs_axis, coefficients)

            geo_axis = IrregularAxis(crs_axis.label, crs_axis.uom,
                                     user_axis.interval.low, high,
                                     user_axis.interval.low, coefficients,
                                     crs_axis)

        if not crs_axis.is_x_axis() and not crs_axis.is_y_axis():
            # GDAL model is 2D so on any axis except x/y we expect to have only one value
            grid_low = 0
            grid_high = None
            if user_axis.interval.high is not None:
                grid_high = 0
        else:
            grid_low = 0
            number_of_grid_points = decimal.Decimal(str(user_axis.interval.high)) \
                                  - decimal.Decimal(str(user_axis.interval.low))
            # number_of_grid_points = (geo_max - geo_min) / resolution
            grid_high = grid_low + number_of_grid_points / decimal.Decimal(
                user_axis.resolution)
            grid_high = HighPixelAjuster.adjust_high(grid_high)

            # Negative axis, e.g: Latitude (min <--- max)
            if user_axis.resolution < 0:
                grid_high = int(abs(math.floor(grid_high)))
            else:
                # Positive axis, e.g: Longitude (min --> max)
                grid_high = int(abs(math.ceil(grid_high)))

        # NOTE: Grid Coverage uses the direct intervals as in Rasdaman
        if self.grid_coverage is False and grid_high is not None:
            if grid_high > grid_low:
                grid_high -= 1

        grid_axis = GridAxis(user_axis.order, crs_axis.label,
                             user_axis.resolution, grid_low, grid_high)
        geo_axis.origin = PointPixelAdjuster.get_origin(user_axis, crs_axis)
        if user_axis.type == UserAxisType.DATE:
            self._translate_decimal_to_datetime(user_axis, geo_axis)
        # NOTE: current, gdal recipe supports only has 2 axes which are "bounded" (i.e: they exist as 2D axes in file)
        # and 1 or more another axes gotten (i.e: from fileName) which are not "bounded" to create 3D+ coverage.
        data_bound = crs_axis.is_y_axis() or crs_axis.is_x_axis()

        return AxisSubset(
            CoverageAxis(geo_axis, grid_axis, data_bound),
            Interval(user_axis.interval.low, user_axis.interval.high))
    def _axis_subset(self, grib_file, evaluated_messages, crs_axis):
        """
        Returns an axis subset using the given crs axis in the context of the grib file
        :param File grib_file: the current grib file (slice) is evaluated
        :param List[GirbMessages] evaluated_messages: all Grib messages was evaluated
        :param CRSAxis crs_axis: the crs definition of the axis
        :rtype AxisSubset
        """
        # first grib message from grib file, used to extract grib variables only
        first_grib_message = self.dataset.message(1)

        # As all the messages contain same axes (but different intervals), so first message is ok to get user_axis
        first_user_axis = self._get_user_axis_in_evaluated_message(
            evaluated_messages[0], crs_axis.label)
        # NOTE: we don't want to change this user_axis belongs to messages, so clone it
        user_axis = copy.deepcopy(first_user_axis)
        # Then, we calculate the geo, grid bounds, origin, resolution of this axis for the slice
        self._set_low_high(evaluated_messages, user_axis)

        high = user_axis.interval.high if user_axis.interval.high is not None else user_axis.interval.low
        origin = PointPixelAdjuster.get_origin(user_axis, crs_axis)

        if isinstance(user_axis, RegularUserAxis):
            geo_axis = RegularAxis(crs_axis.label, crs_axis.uom,
                                   user_axis.interval.low, high, origin,
                                   crs_axis)
        else:
            # after all messages was evaluated, we could get the direct_positions of the axis as in netcdf
            # then, it can evaluate the grib sentence normally, e.g: ${grib:axis:level} + 5
            evaluating_sentence = user_axis.directPositions
            direct_positions = self._get_axis_values(evaluated_messages,
                                                     user_axis)
            # convert all of values in the list to string then it can be evaluated
            direct_positions = list_util.to_list_string(direct_positions)
            evaluator_slice = GribMessageEvaluatorSlice(
                first_grib_message, grib_file, direct_positions)
            user_axis.directPositions = self.sentence_evaluator.evaluate(
                evaluating_sentence, evaluator_slice, user_axis.statements)

            # axis is datetime
            if user_axis.type == UserAxisType.DATE:
                if crs_axis.is_time_day_axis():
                    coefficients = self._translate_day_date_direct_position_to_coefficients(
                        user_axis.interval.low, user_axis.directPositions)
                else:
                    coefficients = self._translate_seconds_date_direct_position_to_coefficients(
                        user_axis.interval.low, user_axis.directPositions)
            else:
                # number axis like Index1D
                coefficients = self._translate_number_direct_position_to_coefficients(
                    user_axis.interval.low, user_axis.directPositions)

            self._update_for_slice_group_size(self.coverage_id, user_axis,
                                              crs_axis, coefficients)

            geo_axis = IrregularAxis(crs_axis.label, crs_axis.uom,
                                     user_axis.interval.low, high, origin,
                                     coefficients, crs_axis)
        grid_low = 0
        grid_high = PointPixelAdjuster.get_grid_points(user_axis, crs_axis)
        # NOTE: Grid Coverage uses the direct intervals as in Rasdaman
        if self.grid_coverage is False and grid_high > grid_low:
            grid_high -= 1
        grid_axis = GridAxis(user_axis.order, crs_axis.label,
                             user_axis.resolution, grid_low, grid_high)
        if user_axis.type == UserAxisType.DATE:
            self._translate_decimal_to_datetime(user_axis, geo_axis)

        return AxisSubset(
            CoverageAxis(geo_axis, grid_axis, user_axis.dataBound),
            Interval(user_axis.interval.low, user_axis.interval.high))
Пример #10
0
    def _axis_subset(self, crs_axis, gdal_file):
        """
        Returns an axis subset using the given crs axis in the context of the gdal file
        :param CRSAxis crs_axis: the crs definition of the axis
        :param File gdal_file: the gdal file
        :rtype AxisSubset
        """
        user_axis = self._user_axis(
            self._get_user_axis_by_crs_axis_name(crs_axis.label),
            GDALEvaluatorSlice(GDALGmlUtil(gdal_file.get_filepath())))
        high = user_axis.interval.high if user_axis.interval.high else user_axis.interval.low

        if isinstance(user_axis, RegularUserAxis):
            geo_axis = RegularAxis(crs_axis.label, crs_axis.uom,
                                   user_axis.interval.low, high,
                                   user_axis.interval.low, crs_axis)
        else:
            # if irregular axis value is fetched from fileName so the coefficient is [0] as slicing
            if user_axis.directPositions == AbstractToCoverageConverter.DIRECT_POSITIONS_SLICING:
                user_axis.directPositions = AbstractToCoverageConverter.COEFFICIENT_SLICING
            geo_axis = IrregularAxis(crs_axis.label, crs_axis.uom,
                                     user_axis.interval.low, high,
                                     user_axis.interval.low,
                                     user_axis.directPositions, crs_axis)

        if not crs_axis.is_easting() and not crs_axis.is_northing():
            # GDAL model is 2D so on any axis except x/y we expect to have only one value
            grid_low = 0
            grid_high = 0
        else:
            grid_low = 0
            number_of_grid_points = decimal.Decimal(str(user_axis.interval.high)) \
                                  - decimal.Decimal(str(user_axis.interval.low))
            # number_of_grid_points = (geo_max - geo_min) / resolution
            grid_high = grid_low + number_of_grid_points / decimal.Decimal(
                user_axis.resolution)
            grid_high = HighPixelAjuster.adjust_high(grid_high)

            # Negative axis, e.g: Latitude (min <--- max)
            if user_axis.resolution < 0:
                grid_high = int(abs(math.floor(grid_high)))
            else:
                # Positive axis, e.g: Longitude (min --> max)
                grid_high = int(abs(math.ceil(grid_high)))

        # NOTE: Grid Coverage uses the direct intervals as in Rasdaman
        if self.grid_coverage is False:
            if grid_high > grid_low:
                grid_high -= 1

        grid_axis = GridAxis(user_axis.order, crs_axis.label,
                             user_axis.resolution, grid_low, grid_high)
        geo_axis.origin = PointPixelAdjuster.get_origin(user_axis, crs_axis)
        if user_axis.type == UserAxisType.DATE:
            self._translate_decimal_to_datetime(user_axis, geo_axis)
        # NOTE: current, gdal recipe supports only has 2 axes which are "bounded" (i.e: they exist as 2D axes in file)
        # and 1 or more another axes gotten (i.e: from fileName) which are not "bounded" to create 3D+ coverage.
        data_bound = crs_axis.is_northing() or crs_axis.is_easting()

        return AxisSubset(
            CoverageAxis(geo_axis, grid_axis, data_bound),
            Interval(user_axis.interval.low, user_axis.interval.high))