def create_process_chain_entry(input_object: DataObject, output_object: DataObject): """Create a Actinia command of the process chain :param input_object: :param vector_object: :return: A Actinia process chain description """ rn = randint(0, 1000000) pc = { "id": "t_rast_algebra_%i" % rn, "module": "t.rast.algebra", "inputs": [ { "param": "expression", "value": "%(result)s = 1 * %(input)s" % { "result": output_object.grass_name(), "input": input_object.grass_name() } }, { "param": "basename", "value": "trim" }, ] } return pc
def create_process_chain_entry(cube1_object: DataObject, cube2_object: DataObject, output_object: DataObject): """Create a Actinia command of the process chain :param cube1_object: :param cube2_object: :return: A Actinia process chain description """ rn = randint(0, 1000000) # t.merge does not have a method to resolve overlaps pc = { "id": "t_merge_%i" % rn, "module": "t.merge", "inputs": [{ "param": "inputs", "value": "%(cube1)s,%(cube2)s" % { "cube1": cube1_object.grass_name(), "cube2": cube2_object.grass_name() } }, { "param": "output", "value": output_object.grass_name() }] } return pc
def create_process_chain_entry(input: DataObject, mask: DataObject, output: DataObject): """Create a Actinia process description that uses r.mapcalc to apply a mask. NOTE: according to multilayer_mask, 0 means not masked, 1 means masked this is the other way around compared to GRASS :param input: The input map name :param mask: The mask map name :param output: The name of the output map :return: A Actinia process chain description """ rn = randint(0, 1000000) pc = { "id": "r_mapcalc_%i" % rn, "module": "r.mapcalc", "inputs": [{ "param": "expression", "value": "%(result)s = if(isnull(%(mask)s) || %(mask)s == 0, " "null(), %(raw)s)" % { "result": output.grass_name(), "raw": input.grass_name(), "mask": mask.grass_name() } }] } return pc
def create_process_chain_entry( output_object: DataObject, red_object: DataObject, green_object: DataObject, blue_object: DataObject) -> list: """Actinia process to export an RGB composite GeoTiff :param output_object: :param red_name: :param green_name: :param blue_name: :return: The process chain """ rn = randint(0, 1000000) pc = [] composite = { "id": "composite_%i" % rn, "module": "r.composite", "inputs": [{"param": "red", "value": red_object.grass_name()}, {"param": "green", "value": green_object.grass_name()}, {"param": "blue", "value": blue_object.grass_name()}], "outputs": [{"export": {"type": "raster", "format": "GTiff"}, "param": "output", "value": output_object.grass_name()}]} pc.append(composite) return pc
def create_process_chain_entry(input_time_series: DataObject, nir_band, red_band, output_time_series: DataObject): """Create a Actinia process description that uses t.rast.ndvi to create the NDVI time series :param input_time_series: The input time series object with red and nir bands :param output_time_series: The object of the output time series :return: A list of Actinia process chain descriptions """ rn = randint(0, 1000000) # TODO: adjust t.rast.ndvi to accept nir band and red band names # pass nir_band and red_band to t.rast.ndvi pc = [ {"id": "t_rast_ndvi_%i" % rn, "module": "t.rast.ndvi", "inputs": [{"param": "input", "value": "%(input)s" % {"input": input_time_series.grass_name()}}, {"param": "basename", "value": "ndvi"}, {"param": "output", "value": output_time_series.grass_name()}]}, {"id": "t_rast_color_%i" % rn, "module": "t.rast.colors", "inputs": [{"param": "input", "value": output_time_series.grass_name()}, {"param": "color", "value": "ndvi"}]}] return pc
def create__process_chain_entry(input_object: DataObject, target, source, output_object: DataObject): """Create a Actinia command of the process chain that uses t.rast.renamebands to rename band names. :param input_object: The input strds object :param dimension: :param target: :param source: :param output_object: The output strds object :return: A Actinia process chain description """ # Get info about the time series to extract its resolution settings and # bbox rn = randint(0, 1000000) # source can be null if source: pc = { "id": "t_rast_renamebands_%i" % rn, "module": "t.rast.renamebands", "inputs": [{ "param": "input", "value": input_object.grass_name() }, { "param": "target", "value": (',').join(target) }, { "param": "source", "value": (',').join(source) }, { "param": "output", "value": output_object.grass_name() }] } else: pc = { "id": "t_rast_renamebands_%i" % rn, "module": "t.rast.renamebands", "inputs": [{ "param": "input", "value": input_object.grass_name() }, { "param": "target", "value": (',').join(target) }, { "param": "output", "value": output_object.grass_name() }] } return pc
def create__process_chain_entry(input_object: DataObject, start_time: str, end_time: str, output_object: DataObject): """Create a Actinia command of the process chain that uses t.rast.extract to create a subset of a strds The filter checks whether the temporal dimension value is greater than or equal to the lower boundary (start date/time) and the temporal dimension value is less than the value of the upper boundary (end date/time). This corresponds to a left-closed interval, which contains the lower boundary but not the upper boundary. :param input_object: The input strds object :param start_time: :param end_time: :param output_object: The output strds object :return: A Actinia process chain description """ start_time = start_time.replace('T', ' ') end_time = end_time.replace('T', ' ') # Get info about the time series to extract its resolution settings and # bbox rn = randint(0, 1000000) # end_time can be null, and we can not find out if end_time is set because # the input does not exist yet pc = { "id": "t_rast_extract_%i" % rn, "module": "t.rast.extract", "inputs": [{ "param": "input", "value": input_object.grass_name() }, { "param": "where", "value": "start_time >= '%(start)s' " "AND start_time <= '%(end)s'" % { "start": start_time, "end": end_time } }, { "param": "output", "value": output_object.grass_name() }, { "param": "expression", "value": "1.0 * %s" % input_object.grass_name() }, { "param": "basename", "value": f"{input_object.name}_extract" }, { "param": "suffix", "value": "num" }] } return pc
def create_process_chain_entry(input_object: DataObject, method, output_object: DataObject): """Create a Actinia process description. :param input_object: The input time series name :param method: The method for time reduction :param output_map: The name of the output raster map :return: A Actinia process chain description """ rn = randint(0, 1000000) # TODO: a new GRASS addon that # 1. fetches a list of raster maps in a strds # 2. resamples each raster map with the selected method # translate openeo method to GRASS method if method == "near": method = "nearest" if method == "cubic": method = "bicubic" if method == "max": method = "maximum" if method == "min": method = "minimum" if method == "med": method = "median" if method == "q1": method = "quart1" if method == "q3": method = "quart3" pc = [{ "id": "t_rast_resample_%i" % rn, "module": "t.rast.resample", "inputs": [{ "param": "input", "value": input_object.grass_name() }, { "param": "method", "value": method }, { "param": "output", "value": output_object.grass_name() }], }] return pc
def create_process_chain_entry(input_object: DataObject, formula, operators, output_object: DataObject): """Create a Actinia process description. :param input_object: The input time series object :param output_object: The output time series or raster object :return: A Actinia process chain description """ rn = randint(0, 1000000) # t.rast.mapcalc formula = formula.replace('data', input_object.grass_name()) pc = { "id": "t_rast_mapcalc_%i" % rn, "module": "t.rast.mapcalc", "inputs": [ { "param": "expression", "value": "%(formula)s" % { "formula": formula } }, { "param": "input", "value": "%(input)s" % { "input": input_object.grass_name() } }, { "param": "output", "value": output_object.grass_name() }, # the basename will always replace any individual # raster map names from the input STRDS, # but some basename is required. { "param": "basename", "value": output_object.grass_name() } ] } return pc
def create_process_chain_entry(input_object: DataObject, vmin: float, vmax: float, output_object: DataObject): """Create a Actinia command of the process chain that uses t.rast.mapcalc to filter raster values by the specified interval :param input_object: The input time series object :param min: smallest allowed value :param max: largest allowed value :param output_object: The output time series object :return: A Actinia process chain description """ rn = randint(0, 1000000) pc = { "id": "t_rast_mapcalc_%i" % rn, "module": "t.rast.mapcalc", "inputs": [ { "param": "expression", "value": "%(result)s = if(%(raw)s < %(min)s || " "%(raw)s > %(max)s), null(), %(raw)s)" % { "result": output_object.grass_name(), "raw": input_object.grass_name(), "min": str(vmin), "max": str(vmax) } }, { "param": "basename", "value": output_object.name }, { "param": "output", "value": output_object.grass_name() }, ] } return pc
def create_process_chain_entry( input_object: DataObject, method, output_object: DataObject): """Create a Actinia process description that uses t.rast.series to reduce a time series. :param input_object: The input time series object :param method: The method for time reduction :param output_map: The name of the output raster object :return: A Actinia process chain description """ rn = randint(0, 1000000) pc = {"id": "t_rast_series_%i" % rn, "module": "t.rast.series", "inputs": [{"param": "input", "value": input_object.grass_name()}, {"param": "method", "value": method}, {"param": "output", "value": output_object.grass_name()}], "flags": "t"} return pc
def create_process_chain_entry( nir_time_series: DataObject, red_time_series: DataObject, blue_time_series: DataObject, scale: float, output_time_series: DataObject): """Create a Actinia process description that uses t.rast.mapcalc to create the EVI time series :param nir_time_series: The NIR band time series name :param red_time_series: The RED band time series name :param blue_time_series: The BLUE band time series name :param scale: scale factor :param output_time_series: The name of the output time series :return: A list of Actinia process chain descriptions """ rn = randint(0, 1000000) pc = [ {"id": "t_rast_mapcalc_%i" % rn, "module": "t.rast.mapcalc", "inputs": [{"param": "expression", "value": "%(result)s = float(2.5 * %(scale)s * (%(nir)s - %(red)s)/" "(%(nir)s * %(scale)s + 6.0 * %(red)s * %(scale)s -7.5 * %(blue)s * %(scale)s + 1.0))" % { "result": output_time_series.grass_name(), "nir": nir_time_series.grass_name(), "red": red_time_series.grass_name(), "blue": blue_time_series.grass_name(), "scale": scale}}, {"param": "inputs", "value": "%(nir)s,%(red)s,%(blue)s" % {"nir": nir_time_series.grass_name(), "red": red_time_series.grass_name(), "blue": blue_time_series.grass_name()}}, {"param": "basename", "value": output_time_series.name}, {"param": "output", "value": output_time_series.grass_name()}]}, {"id": "t_rast_color_%i" % rn, "module": "t.rast.colors", "inputs": [{"param": "input", "value": output_time_series.grass_name()}, {"param": "color", "value": "ndvi"}]}] return pc
def get_process_list(node: Node): """Analyse the process description and return the Actinia process chain and the name of the processing result :param node: The process node :return: (output_objects, actinia_process_list) """ input_objects, process_list = check_node_parents(node=node) output_objects = [] if "result" not in node.arguments: raise Exception("The result name must be specified as parameter") if "expression" not in node.arguments: raise Exception("The expression must be specified as parameter") if "basename" not in node.arguments: raise Exception("The basename must be specified as parameter") result = DataObject( name=node.arguments["result"], datatype=GrassDataType.STRDS) expression = node.arguments["expression"] basename = node.arguments["basename"] if "a" in node.arguments: a = list(node.get_parent_by_name(parent_name="a").output_objects)[-1] expression = expression.replace("$a", a.grass_name()) if "b" in node.arguments: b = list(node.get_parent_by_name(parent_name="b").output_objects)[-1] expression = expression.replace("$b", b.grass_name()) if "c" in node.arguments: c = list(node.get_parent_by_name(parent_name="c").output_objects)[-1] expression = expression.replace("$c", c.grass_name()) if "d" in node.arguments: d = list(node.get_parent_by_name(parent_name="d").output_objects)[-1] expression = expression.replace("$d", d.grass_name()) if "e" in node.arguments: e = list(node.get_parent_by_name(parent_name="e").output_objects)[-1] expression = expression.replace("$e", e.grass_name()) if "f" in node.arguments: f = list(node.get_parent_by_name(parent_name="f").output_objects)[-1] expression = expression.replace("$f", f.grass_name()) expression = expression.replace("$result", result.grass_name()) output_objects.append(result) node.add_output(output_object=result) pc = create_process_chain_entry(expression=expression, basename=basename) process_list.extend(pc) return output_objects, process_list
def create_process_chain_entry(band1_time_series: DataObject, band2_time_series: DataObject, output_time_series: DataObject): """Create a Actinia process description that uses t.rast.mapcalc to create the normalized difference time series :param band1_time_series: The first band time series object :param band2_time_series: The second band time series object :param output_time_series: The object of the output time series :return: A list of Actinia process chain descriptions """ rn = randint(0, 1000000) pc = [{ "id": "t_rast_mapcalc_%i" % rn, "module": "t.rast.mapcalc", "inputs": [{ "param": "expression", "value": "%(result)s = float((%(band1)s - %(band2)s)/" "(%(band1)s + %(band2)s))" % { "result": output_time_series.grass_name(), "band1": band1_time_series.grass_name(), "band2": band2_time_series.grass_name() } }, { "param": "inputs", "value": "%(band1)s,%(band2)s" % { "band1": band1_time_series.grass_name(), "band2": band2_time_series.grass_name() } }, { "param": "basename", "value": "nd" }, { "param": "output", "value": output_time_series.grass_name() }] }, { "id": "t_rast_color_%i" % rn, "module": "t.rast.colors", "inputs": [{ "param": "input", "value": output_time_series.grass_name() }, { "param": "color", "value": "ndvi" }] }] return pc
def create_process_chain_entry(input_object: DataObject, percentile, output_object: DataObject): """Create a Actinia process description that uses t.rast.series to reduce a time series. :param input_time_series: The input time series object :param percentile: The percentile to use for time reduction :param output_map: The object of the output raster map :return: A Actinia process chain description """ rn = randint(0, 1000000) quantile = float(percentile) / 100.0 pc = { "id": "t_rast_series_%i" % rn, "module": "t.rast.series", "inputs": [{ "param": "input", "value": input_object.grass_name() }, { "param": "method", "value": "quantile" }, { "param": "quantile", "value": quantile }, { "param": "output", "value": output_object.grass_name() }], "flags": "t" } return pc
def create_process_chain_entry(input_time_series: DataObject, bands, wavelengths, output_time_series: DataObject): """Create a Actinia command of the process chain that uses g.region to create a valid computational region for the provide input strds :param north: :param south: :param east: :param west: :param crs: :return: A Actinia process chain description """ rn = randint(0, 1000000) # convert wavelengths to a string wvstring = None pc = None if wavelengths and bands: wvstring = (',').join(wavelengths) pc = {"id": "t_rast_filterbands_%i" % rn, "module": "t.rast.filterbands", "inputs": [{"param": "input", "value": "%(input)s" % {"input": input_time_series.grass_name()}}, {"param": "bands", "value": "%(bands)s" % {"bands": (',').join(bands)}}, {"param": "wavelengths", "value": "%(wavelengths)s" % {"wavelengths": wvstring}}, {"param": "output", "value": output_time_series.grass_name()}]} elif bands: pc = {"id": "t_rast_filterbands_%i" % rn, "module": "t.rast.filterbands", "inputs": [{"param": "input", "value": "%(input)s" % {"input": input_time_series.grass_name()}}, {"param": "bands", "value": "%(bands)s" % {"bands": (',').join(bands)}}, {"param": "output", "value": output_time_series.grass_name()}]} elif wavelengths: wvstring = (',').join(wavelengths) pc = {"id": "t_rast_filterbands_%i" % rn, "module": "t.rast.filterbands", "inputs": [{"param": "input", "value": "%(input)s" % {"input": input_time_series.grass_name()}}, {"param": "bands", "value": "%(bands)s" % {"bands": (',').join(bands)}}, {"param": "output", "value": output_time_series.grass_name()}]} return pc
def create_process_chain_entry(data_object: DataObject) -> dict: """Create a Actinia command of the process chain that uses g.region to create a valid computational region for the provide input strds :param data_object: Input raster map data object :return: A Actinia process chain description """ rn = randint(0, 1000000) pc = { "id": "g_region_%i" % rn, "module": "g.region", "inputs": [{ "param": "raster", "value": str(data_object.grass_name()) }], "flags": "p" } return pc
def create_process_chain_entry(data_object: DataObject): """Create a Actinia command of the process chain that computes the regional statistics based on a strds and a polygon. :param data_object: The name of the raster layer :return: A Actinia process chain description """ rn = randint(0, 1000000) pc = [] exporter = { "id": "exporter_%i" % rn, "module": "exporter", "outputs": [{"export": {"type": "raster", "format": "GTiff"}, "param": "map", "value": data_object.grass_name()}]} pc.append(exporter) return pc
def create_process_chain_entry(input_object: DataObject, options: dict): """Create a Actinia command of the process chain that computes the regional statistics based on a strds and a polygon. :param input_object: The name of the raster layer :return: A Actinia process chain description """ rn = randint(0, 1000000) pc = [] output_format = "GTiff" if input_object.is_vector(): output_format = "GML" # the actinia exporter currently does not support GDAL creation options # parameter options is ignored options_list = list() for key in options: optstr = ("%s=%s" % (key, options[key])) options_list.append(optstr) exporter = { "id": "save_result_%i" % rn, "module": "exporter", "outputs": [{ "export": { "type": input_object.datatype.value, "format": output_format }, "param": "map", "value": input_object.grass_name() }] } pc.append(exporter) return pc
def create_process_chain_entry(input_object: DataObject, spatial_extent, temporal_extent, bands, output_object: DataObject): """Create a Actinia process description that r.info, v.info, or t.info. :param input_object: The input object name :param spatial_extent: spatial filter :param temporal_extent: temporal filter :param bands: bands to extract :return: A Actinia process chain description """ rn = randint(0, 1000000) pc = [] if input_object.is_raster(): importer = {"id": "r_info_%i" % rn, "module": "r.info", "inputs": [ {"param": "map", "value": input_object.grass_name()}, ], "flags": "g"} elif input_object.is_vector(): importer = {"id": "v_info_%i" % rn, "module": "v.info", "inputs": [ {"param": "map", "value": input_object.grass_name()}, ], "flags": "g"} elif input_object.is_strds(): importer = {"id": "t_info_%i" % rn, "module": "t.info", "inputs": [ {"param": "input", "value": input_object.grass_name()}, ], "flags": "g"} elif input_object.is_stac(): instance_id = input_object.mapset collection_id = f"stac.{instance_id}.rastercube.{input_object.name}" strds_name = (output_object.grass_name()).replace('@', '_') # Define the import process of the STAC collection stac_input_importer = { "import_descr": { "source": collection_id, "type": "stac" }, "param": "map", "value": strds_name } param_import = _get_stac_importer(stac_input_importer, spatial_extent, temporal_extent, bands, rn) stac_importchain = { "id": "importer_1", "module": "importer", "inputs": [param_import] } pc.append(stac_importchain) importer = {"id": "t_info_%i" % rn, "module": "t.info", "inputs": [ {"param": "input", "value": strds_name}, ], "flags": "g"} else: raise Exception("Unsupported datatype") pc.append(importer) # TODO: spatial extent can also be a GeoJSON object if spatial_extent is not None: north = spatial_extent["north"] south = spatial_extent["south"] west = spatial_extent["west"] east = spatial_extent["east"] if "crs" in spatial_extent: crs = str(spatial_extent["crs"]) else: crs = "4326" if crs.isnumeric(): crs = "EPSG:" + crs if input_object.is_raster(): region_bbox = { "id": "g_region_bbox_%i" % rn, "module": "g.region.bbox", "inputs": [ { "param": "n", "value": str(north)}, { "param": "s", "value": str(south)}, { "param": "e", "value": str(east)}, { "param": "w", "value": str(west)}, { "param": "crs", "value": str(crs)}, { "param": "raster", "value": input_object.grass_name()}, ]} elif input_object.is_strds() or input_object.is_stac(): region_bbox = { "id": "g_region_bbox_%i" % rn, "module": "g.region.bbox", "inputs": [ { "param": "n", "value": str(north)}, { "param": "s", "value": str(south)}, { "param": "e", "value": str(east)}, { "param": "w", "value": str(west)}, { "param": "crs", "value": str(crs)}, { "param": "strds", "value": input_object.grass_name()}, ] } else: region_bbox = {"id": "g_region_bbox_%i" % rn, "module": "g.region.bbox", "inputs": [{"param": "n", "value": str(north)}, {"param": "s", "value": str(south)}, {"param": "e", "value": str(east)}, {"param": "w", "value": str(west)}, {"param": "crs", "value": str(crs)}, ]} pc.append(region_bbox) if input_object.is_strds() and \ (temporal_extent is not None or bands is not None): wherestring = "" if temporal_extent: start_time = temporal_extent[0].replace('T', ' ') if len(temporal_extent) > 1: end_time = temporal_extent[1].replace('T', ' ') wherestring = "start_time >= '%(start)s' AND start_time < '%(end)s'" % { "start": start_time, "end": end_time} # end_time can be null, use only start_time for filtering else: wherestring = "start_time >= '%(start)s'" % {"start": start_time} if bands: wherestring = wherestring + " AND " if bands: wherestring = wherestring + \ "semantic_label in ('%(band_names)s')" % {"band_names": ("', '").join(bands)} pc_strdsfilter = { "id": "t_rast_extract_%i" % rn, "module": "t.rast.extract", "inputs": [{"param": "input", "value": input_object.grass_name()}, {"param": "where", "value": wherestring}, {"param": "output", "value": output_object.grass_name()}, {"param": "expression", "value": "1.0 * %s" % input_object.name}, {"param": "basename", "value": output_object.name}, {"param": "suffix", "value": "num"}]} pc.append(pc_strdsfilter) return pc
def create_process_chain_entry(data_object: DataObject, output_object: DataObject): """Create a Actinia process description that uses t.rast.series and r.mapcalc to create a multilayer mask. :param data_object: The input time series object :param output_object: The name of the output raster map :return: A Actinia process chain description """ output_temp_object = DataObject(name=f"{output_object.name}_temp", datatype=GrassDataType.RASTER) # get number of maps in input_time_series iface = ActiniaInterface() # this is not working because the input object might not yet exist status_code, layer_data = iface.layer_info( layer_name=data_object.grass_name()) if status_code != 200: return make_response( jsonify( { "description": "An internal error occurred " "while catching GRASS GIS layer information " "for layer <%s>!\n Error: %s" "" % (data_object, str(layer_data)) }, 400)) nmaps = layer_data['number_of_maps'] rn = randint(0, 1000000) pc = [{ "id": "t_rast_series_%i" % rn, "module": "t.rast.series", "inputs": [{ "param": "input", "value": data_object.grass_name() }, { "param": "method", "value": "count" }, { "param": "output", "value": output_temp_object.grass_name() }], "flags": "t" }, { "id": "r_mapcalc_%i" % rn, "module": "r.mapcalc", "inputs": [{ "param": "expression", "value": "%(result)s = int(if(%(raw)s < %(nmaps)s, 1, 0))" % { "result": output_object.grass_name(), "raw": output_temp_object.grass_name(), "nmaps": str(nmaps) } }], }] # g.remove raster name=output_name_tmp -f ? return pc
def create_process_chain_entry(input_object: DataObject, polygons: str): """Create a Actinia command of the process chain that computes the regional statistics based on a strds and a polygon. The computational region will be set to the vector map, the previous region will be saved and after processing restored. A mask will be set that uses the vector file as input. This mask will be removed in the end. :param input_object: The name of the strds :param polygons: The URL to the vector file that defines the regions of interest :return: A Actinia process chain description """ rn = randint(0, 1000000) pc = [] importer = { "id": "importer_%i" % rn, "module": "importer", "inputs": [{ "import_descr": { "source": polygons, "type": "vector" }, "param": "map", "value": "polygon" }] } g_region_1 = { "id": "g_region_1_%i" % rn, "module": "g.region", "inputs": [{ "param": "save", "value": "previous_region" }], "flags": "g" } g_region_2 = { "id": "g_region_2_%i" % rn, "module": "g.region", "inputs": [{ "param": "vector", "value": "polygon" }], "flags": "g" } r_mask_1 = { "id": "r_mask_1_%i" % rn, "module": "r.mask", "inputs": [{ "param": "vector", "value": "polygon" }] } t_rast_univar = { "id": "t_rast_univar_%i" % rn, "module": "t.rast.univar", "inputs": [{ "param": "input", "value": input_object.grass_name() }] } r_mask_2 = {"id": "r_mask_2_%i" % rn, "module": "r.mask", "flags": "r"} g_region_3 = { "id": "g_region_3_%i" % rn, "module": "g.region", "inputs": [{ "param": "region", "value": "previous_region" }], "flags": "g" } pc.append(importer) pc.append(g_region_1) pc.append(g_region_2) pc.append(r_mask_1) pc.append(t_rast_univar) pc.append(r_mask_2) pc.append(g_region_3) return pc
def create_process_chain_entry(input_object: DataObject, vector_object, output_object: DataObject): """Create a Actinia command of the process chain :param input_object: :param vector_object: :return: A Actinia process chain description """ rn = randint(0, 1000000) pc = [{ "id": "v_in_geojson_%i" % rn, "module": "v.in.geojson", "inputs": [ { "param": "input", "value": vector_object }, { "param": "output", "value": "geojson_mask" }, ] }, { "id": "v_to_rast_%i" % rn, "module": "v.to.rast", "inputs": [ { "param": "input", "value": "geojson_mask" }, { "param": "output", "value": "MASK" }, { "param": "type", "value": "point,line,area" }, { "param": "use", "value": "val" }, ] }, { "id": "t_rast_algebra_%i" % rn, "module": "t.rast.algebra", "inputs": [ { "param": "expression", "value": "%(result)s = 1 * %(input)s" % { "result": output_object.grass_name(), "input": input_object.grass_name() } }, { "param": "basename", "value": output_object.name }, ] }, { "id": "r_mask_%i" % rn, "module": "r_mask", "inputs": { "flags": "r" } }] return pc
def create__process_chain_entry(input_object: DataObject, target, source, output_object: DataObject): """Create a Actinia command of the process chain that uses t.rast.renamebands to rename band names. :param input_object: The input strds object :param dimension: :param target: :param source: :param output_object: The output strds object :return: A Actinia process chain description """ # Get info about the time series to extract its resolution settings and # bbox rn = randint(0, 1000000) # TODO: do not create a new STRDS # only update labels in the input STRDS ? pc = [] # source can be null if source: p = { "id": "t_rast_renamelabels_%i" % rn, "module": "t.rast.renamelabels", "inputs": [{ "param": "input", "value": input_object.grass_name() }, { "param": "new", "value": (',').join(target) }, { "param": "old", "value": (',').join(source) }, { "param": "output", "value": output_object.grass_name() }] } else: p = { "id": "t_rast_renamelabels_%i" % rn, "module": "t.rast.renamelabels", "inputs": [{ "param": "input", "value": input_object.grass_name() }, { "param": "new", "value": (',').join(target) }, { "param": "output", "value": output_object.grass_name() }] } pc.append(p) p = { "id": "t_info_%i" % rn, "module": "t.info", "inputs": [{ "param": "input", "value": output_object.grass_name() }, { "param": "type", "value": "strds" }], "flags": 'g' } pc.append(p) return pc
def create_process_chain_entry(input_object: DataObject, mask_object: DataObject, mask_value, output_object: DataObject): """Create a Actinia command of the process chain that uses t.rast.mapcalc to mask raster values based on a mask dataset and a replacement value :param input_object: The input time series name :param mask_object: time series to use as mask :param mask_value: values in input are replaced with this value if mask is not null :param output_object: The output time series name :return: A Actinia process chain description """ rn = randint(0, 1000000) if mask_value == "null": pc = { "id": "t_rast_mapcalc_%i" % rn, "module": "t.rast.mapcalc", "inputs": [ { "param": "expression", "value": "if(isnull(%(mask_name)s), " "%(raw)s, null())" % { "mask_name": mask_object.grass_name(), "raw": input_object.grass_name() } }, { "param": "input", "value": "%(input)s" % { "input": input_object.grass_name() } }, { "param": "basename", "value": output_object.grass_name() }, { "param": "output", "value": output_object.grass_name() }, ] } else: pc = { "id": "t_rast_mapcalc_%i" % rn, "module": "t.rast.mapcalc", "inputs": [ { "param": "expression", "value": "if(isnull(%(mask_name)s), " "%(raw)s, %(mask_value)s)" % { "mask_name": mask_object.grass_name(), "raw": input_object.grass_name(), "mask_value": mask_value } }, { "param": "input", "value": "%(input)s" % { "input": input_object.grass_name() } }, { "param": "basename", "value": output_object.grass_name() }, { "param": "output", "value": output_object.grass_name() }, ] } return pc
def create_process_chain_entry(input_time_series: DataObject, nir_band, red_band, target_band, output_time_series: DataObject): """Create a Actinia process description that uses t.rast.ndvi to create the NDVI time series :param input_time_series: The input time series object with red and nir bands :param output_time_series: The object of the output time series :return: A list of Actinia process chain descriptions """ rn = randint(0, 1000000) if target_band is not None: pc = [ {"id": "t_rast_ndvi_%i" % rn, "module": "t.rast.ndvi", "inputs": [{"param": "input", "value": "%(input)s" % {"input": input_time_series.grass_name()}}, {"param": "red", "value": red_band}, {"param": "nir", "value": nir_band}, {"param": "target", "value": target_band}, {"param": "basename", "value": output_time_series.name}, {"param": "output", "value": output_time_series.grass_name()}]}] else: pc = [ {"id": "t_rast_ndvi_%i" % rn, "module": "t.rast.ndvi", "inputs": [{"param": "input", "value": "%(input)s" % {"input": input_time_series.grass_name()}}, {"param": "red", "value": red_band}, {"param": "nir", "value": nir_band}, {"param": "basename", "value": output_time_series.name}, {"param": "output", "value": output_time_series.grass_name()}]}, {"id": "t_rast_color_%i" % rn, "module": "t.rast.colors", "inputs": [{"param": "input", "value": output_time_series.grass_name()}, {"param": "color", "value": "ndvi"}]}] if target_band is not None: p = {"id": "t_info_%i" % rn, "module": "t.info", "inputs": [{"param": "input", "value": input_time_series.grass_name()}, {"param": "type", "value": "strds"}], "flags": 'g'} else: p = {"id": "t_info_%i" % rn, "module": "t.info", "inputs": [{"param": "input", "value": output_time_series.grass_name()}, {"param": "type", "value": "strds"}], "flags": 'g'} pc.append(p) return pc
def create_process_chain_entry(input_object: DataObject, vector_object, mask_value, inside, output_object: DataObject): """Create a Actinia command of the process chain :param input_object: :param vector_object: :return: A Actinia process chain description """ # TODO: support geojson as input rn = randint(0, 1000000) pc = [] importer = { "id": "v_in_geojson_%i" % rn, "module": "v.in.geojson", "inputs": [ { "param": "input", "value": vector_object }, { "param": "output", "value": "geojson_mask" }, ] } if inside is False: create_mask = { "id": "v_to_rast_%i" % rn, "module": "v.to.rast", "inputs": [ { "param": "input", "value": "geojson_mask" }, { "param": "output", "value": "polymask" }, { "param": "type", "value": "area" }, { "param": "use", "value": "val" }, ] } else: create_mask = [{ "id": "v_to_rast_%i" % rn, "module": "v.to.rast", "inputs": [ { "param": "input", "value": "geojson_mask" }, { "param": "output", "value": "polymask_inv" }, { "param": "type", "value": "area" }, { "param": "use", "value": "val" }, ] }, { "id": "r:mapcalc_%i" % rn, "module": "r.mapcalc", "inputs": [{ "param": "expression", "value": "polymask = if(isnull(polymask_inv), 1, null())" }] }] # replace all pixels where mask is null if mask_value == "null": do_mask = { "id": "t_rast_mapcalc_%i" % rn, "module": "t.rast.mapcalc", "inputs": [ { "param": "expression", "value": "%(result)s = if(isnull(%(mask_name)s), " "%(raw)s, null())" % { "result": output_object.grass_name(), "mask_name": "polymask", "raw": input_object.grass_name() } }, { "param": "basename", "value": "masked" }, { "param": "output", "value": output_object.grass_name() }, ] } else: do_mask = { "id": "t_rast_mapcalc_%i" % rn, "module": "t.rast.mapcalc", "inputs": [ { "param": "expression", "value": "%(result)s = if(isnull(%(mask_name)s), " "%(raw)s, %(mask_value)s)" % { "result": output_object.grass_name(), "mask_name": "polymask", "raw": input_object.grass_name(), "mask_value": mask_value } }, { "param": "basename", "value": "masked" }, { "param": "output", "value": output_object.grass_name() }, ] } pc.append(importer) pc.append(create_mask) pc.append(do_mask) return pc
def create_process_chain_entry(input_object: DataObject, dimtype, formula, operators, output_object: DataObject): """Create a Actinia process description. :param input_object: The input time series object :param dimension: dimension to reduce :param output_object: The output time series or raster object :return: A Actinia process chain description """ # dimension is the name of the dimension. The name is arbitrary. # Need to check the dimension name and get its type. # Supported dimension types are "temporal" and "bands". # Dimension type "spatial" should also be supported. # We can not check dimension names of the input object here # because the input object does not exist yet. # Use a new GRASS addon t.rast.reduce ? # There are no dimension names in GRASS, only dimension types # -> deadlock: dimension names are openeo specific # we need the openeo object to get the dimension type # from the dimension name # BUT the openeo object does not exist yet # implement openeo / STAC like dimensions in GRASS ? rn = randint(0, 1000000) pc = [] if dimtype == 'temporal': # t.rast.series # exactly one function: map openeo function to r.series method method = operators[0] if method == "mean": method = "average" elif method == "count": method = "count" elif method == "median": method = "median" elif method == "min": method = "minimum" elif method == "max": method = "maximum" elif method == "sd": method = "stddev" elif method == "sum": method = "sum" elif "variance" in formula: method = "variance" else: raise Exception('Unsupported method <%s> for temporal reduction.' % (method)) # TODO: quantiles with openeo options probabilites # (list of values between 0 and 1) # q as number of intervals to calculate quantiles for series = { "id": "t_rast_series_%i" % rn, "module": "t.rast.series", "inputs": [{ "param": "input", "value": input_object.grass_name() }, { "param": "method", "value": method }, { "param": "output", "value": output_object.grass_name() }], "flags": "t" } pc.append(series) r2strds = { "id": "t_rast2strds_%i" % rn, "module": "t.rast2strds", "inputs": [{ "param": "strds", "value": input_object.grass_name() }, { "param": "raster", "value": output_object.grass_name() }, { "param": "bandname", "value": method }, { "param": "output", "value": output_object.grass_name() }] } pc.append(r2strds) elif dimtype == 'bands': # t.rast.mapcalc # t.rast.bandcalc needs the formula and translates # "data[<index>]" to appropriate band references # with <index> being a number, 0 for first band # the order of bands is obtained from g.bands pc = [{ "id": "t_rast_bandcalc_%i" % rn, "module": "t.rast.bandcalc", "inputs": [{ "param": "expression", "value": "%(formula)s" % { "formula": formula } }, { "param": "input", "value": "%(input)s" % { "input": input_object.grass_name() } }, { "param": "basename", "value": output_object.name }, { "param": "output", "value": output_object.grass_name() }] }] return pc
def create_process_chain_entry(input_object: DataObject, mask_object: DataObject, mask_value: str, output_object: DataObject): """Create a Actinia command of the process chain that uses t.rast.mapcalc to mask raster values based on a mask dataset and a replacement value :param input_object: The input time series name :param mask_object: time series to use as mask :param mask_value: values in input are replaced with this value if mask is not null :param output_object: The output time series name :return: A Actinia process chain description """ rn = randint(0, 1000000) if mask_value == "null": mask_value = "null()" pc = [] p = { "id": "t_rast_mask_%i" % rn, "module": "t.rast.mask", "inputs": [{ "param": "input", "value": input_object.grass_name() }, { "param": "mask", "value": mask_object.grass_name() }, { "param": "basename", "value": output_object.name }, { "param": "output", "value": output_object.grass_name() }, { "param": "value", "value": mask_value }], "flags": "i" } pc.append(p) p = { "id": "t_info_%i" % rn, "module": "t.info", "inputs": [{ "param": "input", "value": output_object.grass_name() }, { "param": "type", "value": "strds" }], "flags": 'g' } pc.append(p) return pc