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( 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_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(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: 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(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, 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 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(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 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 = [] # First analyse the data entry if "id" not in node.arguments: raise Exception("Process %s requires parameter <id>" % PROCESS_NAME) input_object = DataObject.from_string(node.arguments["id"]) spatial_extent = None if "spatial_extent" in node.arguments: spatial_extent = node.arguments["spatial_extent"] temporal_extent = None if "temporal_extent" in node.arguments: temporal_extent = node.arguments["temporal_extent"] bands = None if "bands" in node.arguments: bands = node.arguments["bands"] if input_object.is_strds() and \ (temporal_extent is not None or bands is not None): output_object = DataObject( name=create_output_name(input_object.name, node), datatype=input_object.datatype) elif input_object.is_stac(): output_object = DataObject( name=create_output_name(input_object.name, node), datatype=input_object.datatype) else: output_object = input_object output_objects.append(output_object) node.add_output(output_object) pc = create_process_chain_entry(input_object, spatial_extent, temporal_extent, bands, output_object) process_list.extend(pc) return output_objects, process_list
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 get_process_list(node: Node): """Analyse the process description and return the Actinia process chain and the name of the processing result layer which is a single raster layer :param node: The process node :return: (output_objects, actinia_process_list) """ input_objects, process_list = check_node_parents(node=node) output_objects = [] if "method" not in node.arguments: raise Exception("Parameter method is required.") for input_object in node.get_parent_by_name("data").output_objects: output_object = DataObject( name=create_output_name(input_object.name, PROCESS_NAME), datatype=GrassDataType.RASTER) output_objects.append(output_object) node.add_output(output_object=output_object) pc = create_process_chain_entry( input_object, node.arguments["method"], output_object) process_list.append(pc) return output_objects, process_list
def get_process_list(node: Node): """Analyse the process node 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 "data" not in node.arguments: raise Exception("Process %s requires parameter data" % PROCESS_NAME) input_objects = node.get_parent_by_name(parent_name="data").output_objects if not input_objects: raise Exception("Process %s requires an input strds" % PROCESS_NAME) input_object = list(input_objects)[-1] output_object = DataObject(name=create_output_name(input_object.name, PROCESS_NAME), datatype=GrassDataType.STRDS) output_objects.append(output_object) # pc = create_process_chain_entry(input_object, vector_object, output_object) # process_list.append(pc) return output_objects, process_list
def get_process_list(node: Node) -> Tuple[list, list]: """Analyse the process node 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 "data" not in node.arguments or \ "min" not in node.arguments or \ "max" not in node.arguments: raise Exception("Process %s requires parameter data, min, max" % PROCESS_NAME) newmin = node.arguments["min"] newmax = node.arguments["max"] # for each raster separately for input_object in node.get_parent_by_name("data").output_objects: output_object = DataObject(name=create_output_name( input_object.name, PROCESS_NAME), datatype=GrassDataType.RASTER) output_objects.append(output_object) node.add_output(output_object=output_object) pc = create_process_chain_entry(input_object, newmin, newmax, output_object) process_list.append(pc) # TODO: create strds from output raster maps return output_objects, process_list
def get_process_list(node: Node): """Analyse the process description and return the Actinia process chain and the name of the processing result layer which is a single raster layer :param node: The process node :return: (output_objects, actinia_process_list) """ input_objects, process_list = check_node_parents(node=node) output_objects = [] if "percentile" not in node.arguments: raise Exception("Parameter percentile is required.") for data_object in node.get_parent_by_name("data").output_objects: # multiple strds as input ? # multiple raster layers as output ! output_object = DataObject(name=create_output_name( data_object.name, node), datatype=GrassDataType.STRDS) output_objects.append(output_object) node.add_output(output_object=output_object) pc = create_process_chain_entry(data_object, node.arguments["percentile"], output_object) process_list.append(pc) return output_objects, process_list
def get_process_list(node: Node): """Analyse the process description and return the Actinia process chain and the name of the processing result layer which is a single raster layer :param node: The process node :return: (output_objects, actinia_process_list) """ tree, operators = construct_tree( node.as_dict()['arguments']['process']['process_graph']) # print (operators) formula = None output_datatype = GrassDataType.RASTER formula = serialize_tree(tree) # print(formula) output_datatype = GrassDataType.STRDS input_objects, process_list = check_node_parents(node=node) output_objects = [] for input_object in node.get_parent_by_name("data").output_objects: output_object = DataObject(name=create_output_name( input_object.name, PROCESS_NAME), datatype=output_datatype) output_objects.append(output_object) node.add_output(output_object=output_object) pc = create_process_chain_entry(input_object, formula, operators, output_object) process_list.append(pc) return output_objects, process_list
def get_process_list(node: Node) -> Tuple[list, list]: """Analyse the process node 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 "data" not in node.arguments or \ "min" not in node.arguments or \ "max" not in node.arguments: raise Exception("Process %s requires parameter data, min, max" % PROCESS_NAME) vmin = node.arguments["min"] vmax = node.arguments["max"] for data_object in input_objects: output_object = DataObject(name=create_output_name( data_object.name, node), datatype=GrassDataType.STRDS) output_objects.append(output_object) node.add_output(output_object=output_object) pc = create_process_chain_entry(data_object, vmin, vmax, output_object) process_list.append(pc) return output_objects, process_list
def get_process_list(node: Node): """Analyse the process description and return the Actinia process chain and the name of the processing result layer which is a single raster layer :param args: The process description :return: (output_names, actinia_process_list) """ # Get the input description and the process chain to attach this process input_objects, process_list = check_node_parents(node=node) output_objects = [] input_objects = node.get_parent_by_name(parent_name="data").output_objects python_file_url = node.arguments["udf"] udf_runtime = None if "runtime" in node.arguments: udf_runtime = node.arguments["runtime"] udf_version = None if "version" in node.arguments: udf_version = node.arguments["version"] for input_object in input_objects: output_object = DataObject(name=create_output_name( input_object.name, PROCESS_NAME), datatype=GrassDataType.STRDS) output_objects.append(output_object) pc = create_process_chain_entry(input_object, python_file_url, udf_runtime, udf_version, output_object) process_list.append(pc) return output_objects, process_list
def get_process_list(node: Node): """Analyse the process description and return the Actinia process chain and the name of the processing result strds that was filtered by start and end date :param node: The process node :return: (output_names, actinia_process_list) """ input_objects, process_list = check_node_parents(node=node) output_objects = [] for data_object in node.get_parent_by_name( parent_name="data").output_objects: # Skip if the datatype is not a strds and put the input into the output if data_object.is_strds() is False: output_objects.append(data_object) continue if "dimension" not in node.arguments or \ node.arguments["dimension"] != "bands": raise Exception( "Process %s requires dimension to be set to bands" % PROCESS_NAME) output_object = DataObject(name=create_output_name( data_object.name, node), datatype=GrassDataType.STRDS) output_objects.append(output_object) node.add_output(output_object=output_object) if not isinstance(node.arguments["target"], list): raise Exception("Process %s requires target to be a list" % PROCESS_NAME) target = node.arguments["target"] source = None if "source" in node.arguments: if not isinstance(node.arguments["source"], list): raise Exception("Process %s requires source to be a list" % PROCESS_NAME) source = node.arguments["source"] if len(source) != len(target): raise Exception( "Process %s requires source and target to have the same number of items" % PROCESS_NAME) else: if len(target) != 1: raise Exception( "Process %s requires one item in target if source is not given" % PROCESS_NAME) pc = create__process_chain_entry(input_object=data_object, target=target, source=source, output_object=output_object) process_list.extend(pc) return output_objects, process_list
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 get_process_list(node: Node): """Analyse the process description and return the Actinia process chain and the name of the processing result layer which is a single raster layer :param node: The process node :return: (output_objects, actinia_process_list) """ input_objects, process_list = check_node_parents(node=node) output_objects = [] if "nf" not in node.arguments: raise Exception("Parameter nf is required.") nf = int(node.arguments["nf"]) dod = 0 if "dod" in node.arguments: dod = int(node.arguments["dod"]) fet = 1.7977e308 if "fet" in node.arguments: fet = float(node.arguments["fet"]) range_low = -1.7977e308 if "range_low" in node.arguments: range_low = float(node.arguments["range_low"]) range_high = 1.7977e308 if "range_high" in node.arguments: range_high = float(node.arguments["range_high"]) reject_low = False if "reject_low" in node.arguments: reject_low = bool(node.arguments["reject_low"]) reject_high = False if "reject_high" in node.arguments: reject_high = bool(node.arguments["reject_high"]) for data_object in node.get_parent_by_name("data").output_objects: # Skip if the datatype is not a strds and put the input into the output if data_object.is_strds() is False: output_objects.append(data_object) continue # multiple strds as input ? output_object = DataObject(name=create_output_name( data_object.name, PROCESS_NAME), datatype=GrassDataType.STRDS) output_objects.append(output_object) node.add_output(output_object=output_object) pc = create_process_chain_entry(data_object, nf, dod, fet, range_low, range_high, reject_low, reject_high, output_object) process_list.append(pc) return output_objects, process_list
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(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( 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 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 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 = [] # Get the input data input_objects = node.get_parent_by_name(parent_name="data").output_objects input_strds = list(input_objects)[-1] nir_band = "nir" red_band = "red" if "nir" in node.arguments and \ node.arguments["nir"] is not None and \ node.arguments["nir"] != "null": nir_band = node.arguments["nir"] if "red" in node.arguments and \ node.arguments["red"] is not None and \ node.arguments["red"] != "null": red_band = node.arguments["red"] target_band = None if "target_band" in node.arguments and \ node.arguments["target_band"] is not None and \ node.arguments["target_band"] != "null": target_band = node.arguments["target_band"] output_objects.extend(list(input_objects)) output_object = DataObject( name=create_output_name(input_strds.name, node), datatype=GrassDataType.STRDS) if target_band is None: output_objects.append(output_object) node.add_output(output_object=output_object) else: # if target band is given, extend the input strds output_objects.append(input_strds) node.add_output(output_object=input_strds) pc = create_process_chain_entry( input_strds, nir_band, red_band, target_band, output_object) process_list.extend(pc) return output_objects, process_list
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 = [] # First analyse the data entries if "band1" not in node.arguments: raise Exception("Process %s requires parameter <band1>" % PROCESS_NAME) if "band2" not in node.arguments: raise Exception("Process %s requires parameter <band2>" % PROCESS_NAME) # Get the red and nir data separately band1_input_objects = node.get_parent_by_name( parent_name="band1").output_objects band2_input_objects = node.get_parent_by_name( parent_name="band2").output_objects if not band1_input_objects: raise Exception( "Process %s requires an input strds for band 1" % PROCESS_NAME) if not band2_input_objects: raise Exception( "Process %s requires an input strds for band 2" % PROCESS_NAME) band1_strds = list(band1_input_objects)[-1] band2_strds = list(band2_input_objects)[-1] output_objects.extend(list(band1_input_objects)) output_objects.extend(list(band2_input_objects)) output_object = DataObject( name=create_output_name(band1_strds.name, node), datatype=GrassDataType.STRDS) output_objects.append(output_object) node.add_output(output_object=output_object) pc = create_process_chain_entry(band1_strds, band2_strds, output_object) process_list.extend(pc) return output_objects, process_list
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 get_process_list(node: Node): """Analyse the process description and return the Actinia process chain and the name of the processing result layer which is a single raster layer :param node: The process node :return: (output_objects, actinia_process_list) """ # get dimension type dimtype = get_dimension_type(node.arguments["dimension"]) if dimtype is None: raise Exception( 'Unable to determine dimension type for dimension <%s>.' % (node.arguments["dimension"])) tree, operators = construct_tree( node.as_dict()['arguments']['reducer']['process_graph']) # print (operators) formula = None output_datatype = GrassDataType.STRDS if dimtype == 'bands': formula = serialize_tree(tree) # print (formula) output_datatype = GrassDataType.STRDS elif dimtype == 'temporal': if len(operators) != 1: raise Exception( 'Only one method is supported by reduce process on the temporal dimension.' ) input_objects, process_list = check_node_parents(node=node) output_objects = [] for input_object in node.get_parent_by_name("data").output_objects: output_object = DataObject(name=create_output_name( input_object.name, node), datatype=output_datatype) output_objects.append(output_object) node.add_output(output_object=output_object) pc = create_process_chain_entry(input_object, dimtype, formula, operators, output_object) process_list.extend(pc) return output_objects, process_list
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