Esempio n. 1
0
 def __init__(self, product, band_cfg, dc):
     self.product = product
     self.product_name = product.name
     self.native_bands = dc.list_measurements().loc[self.product_name]
     if band_cfg is None:
         self.band_cfg = {}
         for b in self.native_bands.index:
             self.band_cfg[b] = []
     else:
         self.band_cfg = band_cfg
     self._idx = {}
     self._nodata_vals = {}
     for b, aliases in self.band_cfg.items():
         if b not in self.native_bands.index:
             raise ConfigException(f"Unknown band: {b} in layer {product}")
         if b in self._idx:
             raise ConfigException(
                 f"Duplicate band name/alias: {b} in layer {product}")
         self._idx[b] = b
         for a in aliases:
             if a != b and a in self._idx:
                 raise ConfigException(
                     f"Duplicate band name/alias: {a} in layer {product}")
             self._idx[a] = b
         self._nodata_vals[b] = self.native_bands['nodata'][b]
         if isinstance(self._nodata_vals[b],
                       str) and self._nodata_vals[b].lower() == "nan":
             self._nodata_vals[b] = float("nan")
    def parse_pq_names(self, cfg):
        if "datasets" in cfg:
            raise ConfigException(
                f"The 'datasets' entry in the flags section is no longer supported. Please refer to the documentation for the correct format (layer {self.name})"
            )
        if "products" in cfg:
            pq_names = tuple(cfg["products"])
        else:
            pq_names = self.product_names

        if "low_res_products" in cfg:
            pq_low_res_names = tuple(cfg["low_res_products"])
        else:
            pq_low_res_names = self.low_res_product_names
        if "product" in cfg:
            raise ConfigException(
                f"'product' entry in flags section of multi-product layer {self.name} - use 'products' only"
            )
        if "low_res_product" in cfg:
            raise ConfigException(
                f"'low_res_product' entry in flags section of multi-product layer {self.name} - use 'low_res_products' only"
            )
        return {
            "pq_names": pq_names,
            "pq_low_res_names": pq_low_res_names,
        }
    def __init__(self, identifier, cfg, global_cfg):
        super().__init__(cfg)
        self.global_cfg = global_cfg
        self.identifier = identifier

        self.crs_name = cfg["crs"]
        if self.crs_name not in self.global_cfg.published_CRSs:
            raise ConfigException(
                f"Tile matrix set {identifier} has unpublished CRS: {self.crs_name}"
            )
        self.matrix_origin = cfg["matrix_origin"]
        validate_2d_array(self.matrix_origin, identifier, "Matrix origin",
                          float)
        self.tile_size = cfg["tile_size"]
        validate_2d_array(self.tile_size, identifier, "Tile size", int)
        self.scale_set = cfg["scale_set"]
        try:
            validate_array_typ(self.scale_set, identifier, "Scale set", float)
        except TypeError:
            raise ConfigException(
                f"In tile matrix set {identifier}, scale_set is not a list")
        if len(self.scale_set) < 1:
            raise ConfigException(
                f"Tile matrix set {identifier} has no scale denominators in scale_set"
            )
        self.force_raw_crs_name = bool(cfg.get("force_raw_crs_name", False))
        self.wkss = cfg.get("wkss")
        self.initial_matrix_exponents = cfg.get(
            "matrix_exponent_initial_offsets", (0, 0))
        validate_2d_array(self.initial_matrix_exponents, identifier,
                          "Initial matrix exponents", int)
        self.unit_coefficients = cfg.get("unit_coefficients", (1.0, -1.0))
        validate_2d_array(self.unit_coefficients, identifier,
                          "Unit coefficients", float)
    def parse_pq_names(self, cfg):
        # pylint: disable=attribute-defined-outside-init
        if "datasets" in cfg:
            self.pq_names = cfg["datasets"]
            print("CFG WARNING:",
                  "The preferred name for the 'datasets' entry",
                  "in the flags section is now 'products'.",
                  "Please update the configuration for layer", self.name)
        elif "products" in cfg:
            self.pq_names = cfg["products"]
        else:
            self.pq_names = list(self.product_names)
        self.pq_name = self.pq_names[0]

        if "low_res_products" in cfg:
            self.pq_low_res_names = cfg["low_res_products"]
            self.pq_low_res_name = self.pq_names[0]
        else:
            self.pq_low_res_names = list(self.low_res_product_names)
            self.pq_low_res_name = self.low_res_product_name
        if "product" in cfg:
            raise ConfigException(
                f"'product' entry in flags section of multi-product layer {self.name} - use 'products' only"
            )
        if "low_res_product" in cfg:
            raise ConfigException(
                f"'low_res_product' entry in flags section of multi-product layer {self.name} - use 'low_res_products' only"
            )
Esempio n. 5
0
    def __init__(self, refresh=False):
        if not self.initialised or refresh:
            self.initialised = True
            cfg = read_config()
            try:
                self.parse_global(cfg["global"])
            except KeyError as e:
                raise ConfigException(
                    "Missing required config entry in 'global' section: %s" %
                    str(e))

            if self.wms:
                self.parse_wms(cfg.get("wms", {}))
            else:
                self.parse_wms({})

            if self.wcs:
                try:
                    self.parse_wcs(cfg["wcs"])
                except KeyError as e:
                    raise ConfigException(
                        "Missing required config entry in 'wcs' section (with WCS enabled): %s"
                        % str(e))
            else:
                self.parse_wcs(None)
            try:
                self.parse_layers(cfg["layers"])
            except KeyError as e:
                raise ConfigException(
                    "Missing required config entry in 'layers' section")
        super().__init__({})
    def ready_flags(self, dc):
        if self.pq_names:
            for pqn in self.pq_names:
                if pqn is not None:
                    pq_product = dc.index.products.get_by_name(pqn)
                    if pq_product is None:
                        raise ConfigException(
                            f"Could not find flags product {pqn} for layer {self.name} in datacube"
                        )
                    self.pq_products.append(pq_product)
        if self.pq_low_res_names:
            for pqn in self.pq_low_res_names:
                if pqn is not None:
                    pq_product = dc.index.products.get_by_name(pqn)
                    if pq_product is None:
                        raise ConfigException(
                            f"Could not find flags low_res product {pqn} for layer {self.name} in datacube"
                        )
                    self.pq_low_res_products.append(pq_product)

        self.info_mask = ~0
        if self.pq_products:
            self.pq_product = self.pq_products[0]
            meas = self.pq_product.lookup_measurements([self.pq_band])
            self.flags_def = meas[self.pq_band]["flags_definition"]
            for bitname in self.ignore_info_flags:
                bit = self.flags_def[bitname]["bits"]
                if not isinstance(bit, int):
                    continue
                flag = 1 << bit
                self.info_mask &= ~flag
        else:
            self.flags_def = None
            self.pq_product = None
    def parse_wcs(self, cfg):
        if self.wcs:
            if not isinstance(cfg, Mapping):
                raise ConfigException(
                    "WCS section missing (and WCS is enabled)")
            self.wcs_formats = WCSFormat.from_cfg(cfg["formats"])
            self.wcs_formats_by_name = {
                fmt.name: fmt
                for fmt in self.wcs_formats
            }
            self.wcs_formats_by_mime = {
                fmt.mime: fmt
                for fmt in self.wcs_formats
            }
            if not self.wcs_formats:
                raise ConfigException(
                    "Must configure at least one wcs format to support WCS.")

            self.native_wcs_format = cfg["native_format"]
            if self.native_wcs_format not in self.wcs_formats_by_name:
                raise ConfigException(
                    f"Configured native WCS format ({self.native_wcs_format}) not a supported format."
                )
        else:
            self.default_geographic_CRS = None
            self.default_geographic_CRS_def = None
            self.wcs_formats = []
            self.wcs_formats_by_name = {}
            self.wcs_formats_by_mime = {}
            self.native_wcs_format = None
Esempio n. 8
0
    def parse_legend_ticks(self, cfg):
        # Ticks
        ticks = []
        if "ticks_every" in cfg:
            if "tick_count" in cfg:
                raise ConfigException(
                    "Cannot use tick count and ticks_every in the same legend")
            if "ticks" in cfg:
                raise ConfigException(
                    "Cannot use ticks and ticks_every in the same legend")
            delta = Decimal(cfg["ticks_every"])
            tickval = self.legend_begin
            while tickval < self.legend_end:
                ticks.append(tickval)
                tickval += delta
            ticks.append(tickval)
        if "ticks" in cfg:
            if "tick_count" in cfg:
                raise ConfigException(
                    "Cannot use tick count and ticks in the same legend")
            ticks = [Decimal(t) for t in cfg["ticks"]]
        if not ticks:
            count = int(cfg.get("tick_count", 1))
            if count < 0:
                raise ConfigException("tick_count cannot be negative")
            delta = self.legend_end - self.legend_begin
            dcount = Decimal(count)

            for i in range(0, count + 1):
                tickval = self.legend_begin + (Decimal(i) / dcount) * delta
                ticks.append(
                    tickval.quantize(self.rounder, rounding=ROUND_HALF_UP))
        # pylint: disable=attribute-defined-outside-init
        self.ticks = ticks
Esempio n. 9
0
    def make_ready(self, dc, *args, **kwargs):
        self.pq_products = []
        self.pq_low_res_products = []
        for pqn in self.pq_names:
            if pqn is not None:
                pq_product = dc.index.products.get_by_name(pqn)
                if pq_product is None:
                    raise ConfigException(
                        f"Could not find flags product {pqn} for layer {self.product.name} in datacube"
                    )
                self.pq_products.append(pq_product)
        for pqn in self.pq_low_res_names:
            if pqn is not None:
                pq_product = dc.index.products.get_by_name(pqn)
                if pq_product is None:
                    raise ConfigException(
                        f"Could not find flags low_res product {pqn} for layer {self.product.name} in datacube"
                    )
                self.pq_low_res_products.append(pq_product)

        self.info_mask = ~0
        # A (hopefully) representative product
        product = self.pq_products[0]
        meas = product.lookup_measurements([self.pq_band])
        self.flags_def = meas[self.pq_band]["flags_definition"]
        for bitname in self.ignore_info_flags:
            bit = self.flags_def[bitname]["bits"]
            if not isinstance(bit, int):
                continue
            flag = 1 << bit
            self.info_mask &= ~flag
        super().make_ready(dc)
    def __init__(self, cfg, parent_layer=None, **kwargs):
        super().__init__(cfg, **kwargs)
        self.global_cfg = kwargs["global_cfg"]
        self.parent_layer = parent_layer

        if "title" not in cfg:
            raise ConfigException(
                "Layer without title found under parent layer %s" %
                str(parent_layer))
        self.title = cfg["title"]
        if "abstract" in cfg:
            self.abstract = cfg["abstract"]
        elif parent_layer:
            self.abstract = parent_layer.abstract
        else:
            raise ConfigException(
                "No abstract supplied for top-level layer %s" % self.title)
        # Accumulate keywords
        self.keywords = set()
        if self.parent_layer:
            for word in self.parent_layer.keywords:
                self.keywords.add(word)
        else:
            for word in self.global_cfg.keywords:
                self.keywords.add(word)
        for word in cfg.get("keywords", []):
            self.keywords.add(word)
        # Inherit or override attribution
        if "attribution" in cfg:
            self.attribution = AttributionCfg.parse(cfg.get("attribution"))
        elif parent_layer:
            self.attribution = self.parent_layer.attribution
        else:
            self.attribution = self.global_cfg.attribution
Esempio n. 11
0
    def parse_wcs(self, cfg):
        if self.wcs:
            if not isinstance(cfg, Mapping):
                raise ConfigException("WCS section missing (and WCS is enabled)")
            self.default_geographic_CRS = cfg.get("default_geographic_CRS")
            if self.default_geographic_CRS not in self.published_CRSs:
                raise ConfigException("Configured default geographic CRS not listed in published CRSs.")
            if not self.published_CRSs[self.default_geographic_CRS]["geographic"]:
                raise ConfigException("Configured default geographic CRS not listed in published CRSs as geographic.")
            self.default_geographic_CRS_def = self.published_CRSs[self.default_geographic_CRS]
            self.wcs_formats = {}
            for fmt_name, fmt in cfg["formats"].items():
                self.wcs_formats[fmt_name] = {
                    "mime": fmt["mime"],
                    "extension": fmt["extension"],
                    "multi-time": fmt["multi-time"],
                    "name": fmt_name,
                }
                self.wcs_formats[fmt_name]["renderer"] = get_function(fmt["renderer"])
            if not self.wcs_formats:
                raise ConfigException("Must configure at least one wcs format to support WCS.")

            self.native_wcs_format = cfg["native_format"]
            if self.native_wcs_format not in self.wcs_formats:
                raise Exception("Configured native WCS format not a supported format.")
        else:
            self.default_geographic_CRS = None
            self.default_geographic_CRS_def = None
            self.wcs_formats = {}
            self.native_wcs_format = None
Esempio n. 12
0
    def __init__(self, cfg, global_cfg, dc, parent_layer=None):
        self.global_cfg = global_cfg
        self.parent_layer = parent_layer

        if "title" not in cfg:
            raise ConfigException("Layer without title found under parent layer %s" % str(parent_layer))
        self.title = cfg["title"]
        try:
            if "abstract" in cfg:
                self.abstract = cfg["abstract"]
            elif parent_layer:
                self.abstract = parent_layer.abstract
            else:
                raise ConfigException("No abstract supplied for top-level layer %s" % self.title)
            # Accumulate keywords
            self.keywords = set()
            if self.parent_layer:
                for word in self.parent_layer.keywords:
                    self.keywords.add(word)
            else:
                for word in self.global_cfg.keywords:
                    self.keywords.add(word)
            for word in cfg.get("keywords", []):
                self.keywords.add(word)
            # Inherit or override attribution
            if "attribution" in cfg:
                self.attribution = AttributionCfg.parse(cfg.get("attribution"))
            elif parent_layer:
                self.attribution = self.parent_layer.attribution
            else:
                self.attribution = self.global_cfg.attribution

        except KeyError:
            raise ConfigException("Required entry missing in layer %s" % self.title)
        super().__init__({})
def validate_2d_array(array, ident, label, typ):
    try:
        if len(array) != 2:
            raise ConfigException(
                f"In tile matrix set {ident}, {label} must have two values: f{array}"
            )
        validate_array_typ(array, ident, label, typ)
    except TypeError:
        raise ConfigException(
            f"In tile matrix set {ident}, {label} must be a list of two values: f{array}"
        )
 def add_aliases(self, cfg):
     for b, aliases in cfg.items():
         if b in self._idx:
             raise ConfigException(
                 f"Duplicate band name/alias: {b} in layer {self.product_name}"
             )
         self._idx[b] = b
         for a in aliases:
             if a != b and a in self._idx:
                 raise ConfigException(
                     f"Duplicate band name/alias: {a} in layer {self.product_name}"
                 )
             self._idx[a] = b
 def parse_wmts(self, cfg):
     tms_cfgs = TileMatrixSet.default_tm_sets.copy()
     if "tile_matrix_sets" in cfg:
         for identifier, tms in cfg["tile_matrix_sets"].items():
             tms_cfgs[identifier] = tms
     self.tile_matrix_sets = {}
     for identifier, tms in tms_cfgs.items():
         if len(identifier.split()) != 1:
             raise ConfigException(f"Invalid identifier: {identifier}")
         if identifier in self.tile_matrix_sets:
             raise ConfigException(
                 f"Tile matrix set identifiers must be unique: {identifier}"
             )
         self.tile_matrix_sets[identifier] = TileMatrixSet(
             identifier, tms, self)
Esempio n. 16
0
    def __init__(self,
                 product,
                 style_cfg,
                 stand_alone=False,
                 defer_multi_date=False):
        super(ColorRampDef, self).__init__(product,
                                           style_cfg,
                                           stand_alone=stand_alone,
                                           defer_multi_date=defer_multi_date)
        style_cfg = self._raw_cfg
        self.color_ramp = ColorRamp(self, style_cfg)

        for band in style_cfg["needed_bands"]:
            self.raw_needed_bands.add(band)

        self.include_in_feature_info = style_cfg.get("include_in_feature_info",
                                                     True)

        if "index_function" in style_cfg:
            self.index_function = FunctionWrapper(self,
                                                  style_cfg["index_function"],
                                                  stand_alone=self.stand_alone)
        else:
            raise ConfigException(
                "Index function is required for index and hybrid styles. Style %s in layer %s"
                % (self.name, self.product.name))
        if not defer_multi_date:
            self.parse_multi_date(style_cfg)
    def parse_wcs(self, cfg):
        if cfg is None:
            self.wcs = False
            return
        else:
            self.wcs = True
        # Native CRS
        self.cfg_native_crs = cfg.get("native_crs")
        self.declare_unready("native_CRS")
        self.declare_unready("native_CRS_def")

        # Rectified Grids
        self.declare_unready("origin_x")
        self.declare_unready("origin_y")
        self.cfg_native_resolution = cfg.get("native_resolution")
        self.declare_unready("resolution_x")
        self.declare_unready("resolution_y")
        self.declare_unready("grid_high_x")
        self.declare_unready("grid_high_y")
        self.declare_unready("grids")
        # Band management
        self.wcs_raw_default_bands = cfg["default_bands"]
        self.declare_unready("wcs_default_bands")

        # Native format
        if "native_format" in cfg:
            self.native_format = cfg["native_format"]
            if self.native_format not in self.global_cfg.wcs_formats_by_name:
                raise ConfigException(
                    f"WCS native format {self.native_format} for layer {self.name} is not in supported formats list"
                )
        else:
            self.native_format = self.global_cfg.native_wcs_format
 def parse_flags(self, cfg):
     self.flag_bands = {}
     if cfg:
         if isinstance(cfg, dict):
             fb = OWSFlagBand(cfg, self)
             self.flag_bands[fb.pq_band] = fb
             _LOG.warning(
                 "Single flag bands not in a list is deprecated. Please refer to the documentation for the new format (layer %s)",
                 self.name)
         else:
             for fb_cfg in cfg:
                 fb = OWSFlagBand(fb_cfg, self)
                 self.flag_bands[fb.pq_band] = fb
     pq_names_to_lowres_names = {}
     for fb in self.flag_bands.values():
         pns = fb.pq_names
         lrpns = fb.pq_low_res_names
         if pns in pq_names_to_lowres_names and pq_names_to_lowres_names[
                 pns] != lrpns:
             raise ConfigException(
                 f"Product name mismatch in flags section for layer {self.name}: product_names {pns} has multiple distinct low-res product names"
             )
         pq_names_to_lowres_names[pns] = lrpns
     # pylint: disable=dict-values-not-iterating
     self.allflag_productbands = FlagProductBands.build_list_from_flagbands(
         self.flag_bands.values())
 def parse_product_names(self, cfg):
     self.product_names = cfg["product_names"]
     self.product_name = self.product_names[0]
     self.low_res_product_names = cfg.get("low_res_product_names", [])
     if self.low_res_product_names:
         self.low_res_product_name = self.low_res_product_names[0]
     else:
         self.low_res_product_name = None
     if "product_name" in cfg:
         raise ConfigException(
             f"'product_name' entry in multi-product layer {self.name} - use 'product_names' only"
         )
     if "low_res_product_name" in cfg:
         raise ConfigException(
             f"'low_res_product_name' entry in multi-product layer {self.name} - use 'low_res_product_names' only"
         )
Esempio n. 20
0
def cfg_expand(cfg_unexpanded, cwd=None, inclusions=[]):
    # inclusions defaulting to an empty list is dangerous, but note that it is never modified.
    # If modification of inclusions is a required, a copy (ninclusions) is made and modified instead.
    if cwd is None:
        cwd = os.getcwd()
    if isinstance(cfg_unexpanded, Mapping):
        if "include" in cfg_unexpanded:
            if cfg_unexpanded["include"] in inclusions:
                raise ConfigException("Cyclic inclusion: %s" % cfg_unexpanded["include"])
            ninclusions = inclusions.copy()
            ninclusions.append(cfg_unexpanded["include"])
            # Perform expansion
            if "type" not in cfg_unexpanded or cfg_unexpanded["type"] == "json":
                # JSON Expansion
                raw_path = cfg_unexpanded["include"]
                try:
                    # Try in actual working directory
                    json_obj = load_json_obj(raw_path)
                    abs_path = os.path.abspath(cfg_unexpanded["include"])
                    cwd = os.path.dirname(abs_path)
                # pylint: disable=broad-except
                except Exception:
                    json_obj = None
                if json_obj is None:
                    path = os.path.join(cwd, raw_path)
                    try:
                        # Try in inherited working directory
                        json_obj = load_json_obj(path)
                        abs_path = os.path.abspath(path)
                        cwd = os.path.dirname(abs_path)
                    # pylint: disable=broad-except
                    except Exception:
                        json_obj = None
                if json_obj is None:
                    raise ConfigException("Could not find json file %s" % raw_path)
                return cfg_expand(load_json_obj(abs_path), cwd=cwd, inclusions=ninclusions)
            elif cfg_unexpanded["type"] == "python":
                # Python Expansion
                return cfg_expand(import_python_obj(cfg_unexpanded["include"]), cwd=cwd, inclusions=ninclusions)
            else:
                raise ConfigException("Unsupported inclusion type: %s" % str(cfg_unexpanded["type"]))
        else:
            return { k: cfg_expand(v, cwd=cwd, inclusions=inclusions) for k,v in cfg_unexpanded.items()  }
    elif isinstance(cfg_unexpanded, Sequence) and not isinstance(cfg_unexpanded, str):
        return list([cfg_expand(elem, cwd=cwd, inclusions=inclusions) for elem in cfg_unexpanded ])
    else:
        return cfg_unexpanded
Esempio n. 21
0
 def add_flag_band(self, fb):
     self.flag_bands[fb.pq_band] = fb
     self.bands.add(fb.pq_band)
     if fb.pq_manual_merge:
         fb.pq_manual_merge = True
     if fb.pq_fuse_func and self.fuse_func and fb.pq_fuse_func != self.fuse_func:
         raise ConfigException(
             f"Fuse functions for flag bands in product set {self.product_names} do not match"
         )
     if fb.pq_ignore_time != self.ignore_time:
         raise ConfigException(
             f"ignore_time option for flag bands in product set {self.product_names} do not match"
         )
     elif fb.pq_fuse_func and not self.fuse_func:
         self.fuse_func = fb.pq_fuse_func
     self.declare_unready("products")
     self.declare_unready("low_res_products")
Esempio n. 22
0
    def __init__(self, cfg, keyvals, *args, **kwargs):
        super().__init__(cfg, *args, **kwargs)

        for k in self.INDEX_KEYS:
            if k not in keyvals:
                raise ConfigException(
                    f"Key value {k} missing from keyvals: {keyvals!r}")
        self.keyvals = keyvals
Esempio n. 23
0
 def lookup(self, cfg, keyvals, subs=None):
     if subs is None:
         subs = {}
     for k in self.INDEX_KEYS:
         if k not in keyvals:
             raise ConfigException(
                 f"Key value {k} missing from keyvals: {keyvals!r}")
     return self.lookup_impl(cfg, keyvals, subs)
    def parse_product_names(self, cfg):
        self.product_name = cfg["product_name"]
        self.product_names = (self.product_name, )

        self.low_res_product_name = cfg.get("low_res_product_name")
        if self.low_res_product_name:
            self.low_res_product_names = (self.low_res_product_name, )
        else:
            self.low_res_product_names = tuple()
        if "product_names" in cfg:
            raise ConfigException(
                f"'product_names' entry in non-multi-product layer {self.name} - use 'product_name' only"
            )
        if "low_res_product_names" in cfg:
            raise ConfigException(
                f"'low_res_product_names' entry in non-multi-product layer {self.name} - use 'low_res_product_name' only"
            )
 def __init__(self, cfg, layer_cfg, max_datasets):
     super().__init__(cfg)
     self.rules = cfg
     self.use_caching = self.rules is not None
     self.max_datasets = max_datasets
     if not self.use_caching:
         return
     min_so_far = 0
     max_max_age_so_far = 0
     for rule in self.rules:
         if "min_datasets" not in rule:
             raise ConfigException(
                 f"Dataset cache rule does not contain a 'min_datasets' element in layer {layer_cfg.name}"
             )
         if "max_age" not in rule:
             raise ConfigException(
                 f"Dataset cache rule does not contain a 'max_age' element in layer {layer_cfg.name}"
             )
         min_datasets = rule["min_datasets"]
         max_age = rule["max_age"]
         if not isinstance(min_datasets, int):
             raise ConfigException(
                 f"Dataset cache rule has non-integer 'min_datasets' element in layer {layer_cfg.name}"
             )
         if not isinstance(max_age, int):
             raise ConfigException(
                 f"Dataset cache rule has non-integer 'max_age' element in layer {layer_cfg.name}"
             )
         if min_datasets <= 0:
             raise ConfigException(
                 f"Invalid dataset cache rule in layer {layer_cfg.name}: min_datasets must be greater than zero."
             )
         if min_datasets <= min_so_far:
             raise ConfigException(
                 f"Dataset cache rules must be sorted by ascending min_datasets values.  In layer {layer_cfg.name}."
             )
         if max_datasets > 0 and min_datasets > max_datasets:
             raise ConfigException(
                 f"Dataset cache rule min_datasets value exceeds the max_datasets limit in layer {layer_cfg.name}."
             )
         min_so_far = min_datasets
         if max_age <= 0:
             raise ConfigException(
                 f"Dataset cache rule max_age value must be greater than zero in layer {layer_cfg.name}."
             )
         if max_age <= max_max_age_so_far:
             raise ConfigException(
                 f"max_age values in dataset cache rules must increase monotonically in layer {layer_cfg.name}."
             )
         max_max_age_so_far = max_age
    def make_ready(self, dc, *args, **kwargs):
        self.products = []
        self.low_res_products = []
        for i, prod_name in enumerate(self.product_names):
            if self.low_res_product_names:
                low_res_prod_name = self.low_res_product_names[i]
            else:
                low_res_prod_name = None
            product = dc.index.products.get_by_name(prod_name)
            if not product:
                raise ConfigException(
                    f"Could not find product {prod_name} in datacube for layer {self.name}"
                )
            self.products.append(product)
            if low_res_prod_name:
                product = dc.index.products.get_by_name(low_res_prod_name)
                if not product:
                    raise ConfigException(
                        f"Could not find product {low_res_prod_name} in datacube for layer {self.name}"
                    )
                self.low_res_products.append(product)
        self.product = self.products[0]
        self.definition = self.product.definition
        self.force_range_update(dc)
        self.band_idx.make_ready(dc)
        self.all_flag_band_names = set()
        for fb in self.flag_bands.values():
            fb.make_ready(dc)
            if fb.pq_band in self.all_flag_band_names:
                raise ConfigException(
                    f"Duplicate flag band name: {fb.pq_band}")
            self.all_flag_band_names.add(fb.pq_band)
        self.ready_image_processing(dc)
        if self.global_cfg.wcs:
            self.ready_wcs(dc)
        for style in self.styles:
            style.make_ready(dc, *args, **kwargs)
        for fpb in self.allflag_productbands:
            fpb.make_ready(dc, *args, **kwargs)
        if not self.multi_product:
            self.global_cfg.native_product_index[self.product_name] = self

        if not self.hide:
            super().make_ready(dc, *args, **kwargs)
 def crs(self, crsid):
     if crsid not in self.published_CRSs:
         raise ConfigException(f"CRS {crsid} is not published")
     crs_def = self.published_CRSs[crsid]
     crs_alias = crs_def["alias_of"]
     if crs_alias:
         use_crs = crs_alias
     else:
         use_crs = crsid
     return geometry.CRS(use_crs)
Esempio n. 28
0
    def __init__(self,
                 product,
                 style_cfg,
                 local_band_map=None,
                 stand_alone=False,
                 defer_multi_date=False):
        super().__init__(product,
                         style_cfg,
                         stand_alone=stand_alone,
                         defer_multi_date=defer_multi_date)
        style_cfg = self._raw_cfg
        self.raw_rgb_components = {}
        for imgband in ["red", "green", "blue", "alpha"]:
            components = style_cfg["components"].get(imgband)
            if components is None:
                if imgband == "alpha":
                    continue
                else:
                    raise ConfigException(
                        f"No components defined for {imgband} band in style {self.name}, layer {product.name}"
                    )
            if "function" in components:
                self.raw_rgb_components[imgband] = FunctionWrapper(
                    self.product, components, stand_alone=self.stand_alone)
                for b in style_cfg["additional_bands"]:
                    self.raw_needed_bands.add(b)
            else:
                self.raw_rgb_components[imgband] = components
                for k in components.keys():
                    if k != "scale_range":
                        self.raw_needed_bands.add(k)
        self.declare_unready("rgb_components")

        self.scale_factor = style_cfg.get("scale_factor")
        if "scale_range" in style_cfg:
            self.scale_min, self.scale_max = style_cfg["scale_range"]
        elif self.scale_factor:
            self.scale_min = 0.0
            self.scale_max = 255.0 * self.scale_factor
        else:
            self.scale_min = None
            self.scale_max = None

        self.component_scale_ranges = {}
        for cn, cd in style_cfg["components"].items():
            if "scale_range" in cd:
                self.component_scale_ranges[cn] = {
                    "min": cd["scale_range"][0],
                    "max": cd["scale_range"][1],
                }
            else:
                self.component_scale_ranges[cn] = {
                    "min": self.scale_min,
                    "max": self.scale_max,
                }
Esempio n. 29
0
    def parse_wcs(self, cfg, dc):
        if cfg is None:
            self.wcs = False
            return
        else:
            self.wcs = True
        # Native CRS
        try:
            self.native_CRS = self.product.definition["storage"]["crs"]
        except KeyError:
            self.native_CRS = None
        if not self.native_CRS:
            self.native_CRS = cfg.get("native_crs")
        if not self.native_CRS:
            raise ConfigException("No native CRS could be found for layer %s" % self.name)
        if self.native_CRS not in self.global_cfg.published_CRSs:
            raise ConfigException("Native CRS for product %s (%s) not in published CRSs" % (
                            self.product_name,
                            self.native_CRS))
        self.native_CRS_def = self.global_cfg.published_CRSs[self.native_CRS]
        # Prepare Rectified Grid
        native_bounding_box = self.bboxes[self.native_CRS]
        self.origin_x = native_bounding_box["left"]
        self.origin_y = native_bounding_box["bottom"]
        try:
            self.resolution_x, self.resolution_y = cfg["native_resolution"]
        except KeyError:
            raise ConfigException("No native resolution supplied for WCS enabled layer %s" % self.name)
        except ValueError:
            raise ConfigException("Invalid native resolution supplied for WCS enabled layer %s" % self.name)
        except TypeError:
            raise ConfigException("Invalid native resolution supplied for WCS enabled layer %s" % self.name)
        self.grid_high_x = int((native_bounding_box["right"] - native_bounding_box["left"]) / self.resolution_x)
        self.grid_high_y = int((native_bounding_box["top"] - native_bounding_box["bottom"]) / self.resolution_y)

        # Band management
        self.wcs_default_bands = [self.band_idx.band(b) for b in cfg["default_bands"]]
        # Cache some metadata from the datacube
        bands = dc.list_measurements().loc[self.product_name]
        self.bands = bands.index.values
        self.nodata_values = bands['nodata'].values
        self.nodata_dict = {a: b for a, b in zip(self.bands, self.nodata_values)}
Esempio n. 30
0
 def parse_styling(self, cfg):
     self.styles = list([StyleDef(self, s) for s in cfg["styles"]])
     self.style_index = {s.name: s for s in self.styles}
     if "default_style" in cfg:
         if cfg["default_style"] not in self.style_index:
             raise ConfigException(
                 "Default style %s is not in the 'styles' for layer %s" %
                 (cfg["default_style"], self.name))
         self.default_style = self.style_index[cfg["default_style"]]
     else:
         self.default_style = self.styles[0]