Exemple #1
0
def get_process_list(process):
    """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 arguments
    :return: (output_names, actinia_process_list)
    """
    input_names, process_list = analyse_process_graph(process)
    output_names = []

    if "method" not in process:
        raise Exception("Parameter method is required.")

    for input_name in input_names:
        location, mapset, datatype, layer_name = ActiniaInterface.layer_def_to_components(
            input_name)
        output_name = "%s_%s" % (layer_name, PROCESS_NAME)
        output_names.append(output_name)

        pc = create_process_chain_entry(input_name, process["method"],
                                        output_name)
        process_list.append(pc)

    return output_names, process_list
Exemple #2
0
def get_process_list(args):
    """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_names, process_list = process_node_to_actinia_process_chain(args)
    output_names = []

    for input_name in input_names:

        location, mapset, datatype, layer_name = ActiniaInterface.layer_def_to_components(
            input_name)
        output_name = create_output_name(layer_name, PROCESS_NAME)
        output_names.append(output_name)

        if "python_file_url" in args:
            python_file_url = args["python_file_url"]
        else:
            raise Exception(
                "Python file is missing in the process description")

        pc = create_process_chain_entry(input_name=input_name,
                                        python_file_url=python_file_url,
                                        output_name=output_name)
        process_list.append(pc)

    return output_names, process_list
def create_process_chain_entry(input_name, python_file_url, output_name):
    """Create a Actinia command of the process chain that uses g.region to create a valid computational region
    for the provide input strds

    :param strds_name: The name of the strds
    :param python_file_url: The URL to the python file that defines the UDF
    :param output_name: The name of the output raster layer
    :return: A Actinia process chain description
    """

    location, mapset, datatype, layer_name = ActiniaInterface.layer_def_to_components(input_name)
    input_name = layer_name
    if mapset is not None:
        input_name = layer_name + "@" + mapset

    pc = {"id": "t_rast_aggr_func",
          "module": "t.rast.aggr_func",
          "inputs": [{"import_descr": {"source": python_file_url,
                                       "type": "file"},
                      "param": "pyfile",
                      "value": "$file::my_py_func"},
                     {"param": "input",
                      "value": input_name},
                     {"param": "output",
                      "value": output_name}]}

    return pc
Exemple #4
0
def get_process_list(process):
    """Analyse the process description and return the Actinia process chain and the name of the processing result

    :param args: The process description arguments
    :return: (output_names, actinia_process_list)
    """
    output_names = []
    process_list = []

    # First analyse the data entries
    if "red" not in process:
        raise Exception("Process %s requires parameter <red>" % PROCESS_NAME)

    if "nir" not in process:
        raise Exception("Process %s requires parameter <nir>" % PROCESS_NAME)

    # Get the red and ir data separately
    red_process = dict(myproc="myproc", red=process["red"])
    nir_process = dict(myproc="myproc", red=process["nir"])

    red_input_names, red_process_list = analyse_process_graph(red_process)
    process_list.extend(red_process_list)
    nir_input_names, nir_process_list = analyse_process_graph(nir_process)
    process_list.extend(nir_process_list)

    if not red_input_names:
        raise Exception("Process %s requires an input strds for band <red>" %
                        PROCESS_NAME)

    if not nir_input_names:
        raise Exception("Process %s requires an input strds for band <nir>" %
                        PROCESS_NAME)

    red_stds = red_input_names[-1]
    nir_strds = nir_input_names[-1]

    # Take the last entry from the
    if len(red_input_names) > 1:
        output_names.extend(red_input_names[0:-1])

    # Take the last entry from the
    if len(nir_input_names) > 1:
        output_names.extend(nir_input_names[0:-1])

    location, mapset, datatype, layer_name = ActiniaInterface.layer_def_to_components(
        red_stds)
    output_name = "%s_%s" % (layer_name, PROCESS_NAME)
    output_names.append(output_name)

    pc = create_process_chain_entry(nir_strds, red_stds, output_name)
    process_list.extend(pc)

    return output_names, process_list
def create__process_chain_entry(input_name, start_time, end_time, output_name):
    """Create a Actinia command of the process chain that uses t.rast.extract to create a subset of a strds

    :param strds_name: The name of the strds
    :param start_time:
    :param end_time:
    :return: A Actinia process chain description
    """
    location, mapset, datatype, layer_name = ActiniaInterface.layer_def_to_components(
        input_name)
    input_name = layer_name
    if mapset is not None:
        input_name = layer_name + "@" + mapset
    base_name = "%s_extract" % layer_name

    # Get info about the time series to extract its resolution settings and bbox
    rn = randint(0, 1000000)

    pc = {
        "id":
        "t_rast_extract_%i" % rn,
        "module":
        "t.rast.extract",
        "inputs": [{
            "param": "input",
            "value": input_name
        }, {
            "param": "where",
            "value": "start_time >= '%(start)s' "
            "AND end_time <= '%(end)s'" % {
                "start": start_time,
                "end": end_time
            }
        }, {
            "param": "output",
            "value": output_name
        }, {
            "param": "expression",
            "value": "1.0 * %s" % input_name
        }, {
            "param": "basename",
            "value": base_name
        }, {
            "param": "suffix",
            "value": "num"
        }]
    }

    return pc
Exemple #6
0
def get_process_list(process):
    """Analyse the process description and return the Actinia process chain and the name of the processing result

    :param args: The process description arguments
    :return: (output_names, actinia_process_list)
    """
    output_names = []

    # First analyse the data entries
    if "red" not in process:
        raise Exception("Process %s requires parameter <red>" % PROCESS_NAME)

    if "nir" not in process:
        raise Exception("Process %s requires parameter <nir>" % PROCESS_NAME)

    red_strds = None
    nir_strds = None
    input_names, process_list = analyse_process_graph(process)

    # Find the red and nir datasets in the input
    for input_name in input_names:
        if process["red"] in input_name:
            red_strds = input_name
        elif process["nir"] in input_name:
            nir_strds = input_name
        else:
            # Pipe other inputs to the output
            output_names.append(input_name)

    if not red_strds:
        raise Exception("Process %s requires an input strds for band <red>" %
                        PROCESS_NAME)

    if not nir_strds:
        raise Exception("Process %s requires an input strds for band <nir>" %
                        PROCESS_NAME)

    location, mapset, datatype, layer_name = ActiniaInterface.layer_def_to_components(
        red_strds)
    output_name = "%s_%s" % (layer_name, PROCESS_NAME)
    output_names.append(output_name)

    pc = create_process_chain_entry(nir_strds, red_strds, output_name)
    process_list.extend(pc)

    return output_names, process_list
def get_process_list(process):
    """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 process: The process description
    :return: (output_names, actinia_process_list)
    """

    # Get the input description and the process chain to attach this process
    input_names, process_list = analyse_process_graph(process)
    output_names = []

    for input_name in input_names:

        location, mapset, datatype, layer_name = ActiniaInterface.layer_def_to_components(
            input_name)

        # Skip if the datatype is not a strds and put the input into the output
        if datatype and datatype != "strds":
            output_names.append(input_name)
            continue

        output_name = "%s_%s" % (layer_name, PROCESS_NAME)
        output_names.append(output_name)

        start_time = None
        end_time = None

        if "from" in process:
            start_time = process["from"]
        if "to" in process:
            end_time = process["to"]

        pc = create__process_chain_entry(input_name=input_name,
                                         start_time=start_time,
                                         end_time=end_time,
                                         output_name=output_name)
        process_list.append(pc)

    return output_names, process_list
def create_process_chain_entry(input_name):
    """Create a Actinia process description that uses t.rast.series to create the minimum
    value of the time series.

    :param input_time_series: The input time series name
    :param output_map: The name of the output map
    :return: A Actinia process chain description
    """

    location, mapset, datatype, layer_name = ActiniaInterface.layer_def_to_components(input_name)
    input_name = layer_name
    if mapset is not None:
        input_name = layer_name + "@" + mapset

    rn = randint(0, 1000000)

    pc = {}

    if datatype == "raster":
        pc = {"id": "r_info_%i" % rn,
              "module": "r.info",
              "inputs": [{"param": "map", "value": input_name}, ],
              "flags": "g"}
    elif datatype == "vector":
        pc = {"id": "v_info_%i" % rn,
              "module": "v.info",
              "inputs": [{"param": "map", "value": input_name}, ],
              "flags": "g"}
    elif datatype == "strds":
        pc = {"id": "t_info_%i" % rn,
              "module": "t.info",
              "inputs": [{"param": "input", "value": input_name}, ],
              "flags": "g"}
    else:
        raise Exception("Unsupported datatype")

    return pc
Exemple #9
0
class CollectionInformationResource(Resource):

    def __init__(self):
        self.iface = ActiniaInterface()

    def get(self, name):

        # List strds maps from the GRASS location
        location, mapset, datatype, layer = self.iface.layer_def_to_components(
            name)

        if location == "stac":
            status_code, collection = self.iface.get_stac_collection(name=name)
            if status_code != 200:
                return make_response(
                    jsonify(
                        {
                            "id": "12345678",
                            "code": "Internal",
                            "message": "Server error: %s" %
                            (name),
                            "links": {}}),
                    500)

            # Not using CollectionInformation model here for now
            # as valid STAC collections comply.
            # Using it here might omit some properties
            # which are not modelled in this backend (e.g. assets)
            return make_response(collection, 200)

        status_code, layer_data = self.iface.layer_info(layer_name=name)
        if status_code != 200:
            return make_response(
                jsonify(
                    {
                        "id": "12345678",
                        "code": "CollectionNotFound",
                        "message": "Collection '%s' does not exist." %
                        (name),
                        "links": {}}),
                404)

        # Get the projection from the GRASS mapset
        status_code, mapset_info = self.iface.mapset_info(
            location=location, mapset=mapset)
        if status_code != 200:
            return make_response(
                jsonify(
                    {
                        "id": "12345678",
                        "code": "Internal",
                        "message": "Server error: %s" %
                        (mapset_info),
                        "links": {}}),
                500)

        extent = CollectionExtent(
            spatial=(
                float(
                    layer_data["west"]), float(
                    layer_data["south"]), float(
                    layer_data["east"]), float(
                        layer_data["north"])), temporal=(
                            "1900-01-01T00:00:00", "2100-01-01T00:00:00"))

        title = "Raster dataset"
        bands = []
        dimensions = {"x": {
            "type": "spatial",
            "axis": "x",
            "extent": [layer_data["west"], layer_data["east"]],
            "reference_system": mapset_info["projection"]
        },
            "y": {
            "type": "spatial",
            "axis": "y",
            "extent": [layer_data["south"], layer_data["north"]],
            "reference_system": mapset_info["projection"]
        },
        }
        platform = "unknown"
        instrument = "unknown"
        if datatype.lower() == "strds":
            title = "Space time raster dataset"

            start_time = layer_data["start_time"]
            end_time = layer_data["end_time"]

            if start_time:
                start_time = start_time.replace(
                    " ",
                    "T").replace(
                    "'",
                    "").replace(
                    '"',
                    '')

            if end_time:
                end_time = end_time.replace(
                    " ",
                    "T").replace(
                    "'",
                    "").replace(
                    '"',
                    '')

            dimensions['t'] = {"type": "temporal",
                               "extent": [start_time, end_time]
                               }

            extent = CollectionExtent(
                spatial=(
                    float(
                        layer_data["west"]), float(
                        layer_data["south"]), float(
                        layer_data["east"]), float(
                        layer_data["north"])), temporal=(
                            start_time, end_time))

            if "semantic_labels" in layer_data:
                bandlist = layer_data["semantic_labels"].split(',')
                dimensions['bands'] = {"type": "bands",
                                       "values": bandlist
                                       }
                for bandname in bandlist:
                    # not so nice, better use different name and common_name
                    # waiting for GRASS GIS
                    bands.append(EOBands(name=bandname, common_name=bandname))

                # get platform and sensor
                # see
                # https://github.com/radiantearth/stac-spec/blob/master/item-spec/common-metadata.md#platform
                # https://github.com/radiantearth/stac-spec/blob/master/item-spec/common-metadata.md#instruments
                if "_" in bandlist[0]:
                    sensor_abbr = bandlist[0].split('_')[0]
                    if sensor_abbr == "L5":
                        platform = "landsat-5"
                        instrument = "tm, mss"
                    elif sensor_abbr == "L7":
                        platform = "landsat-7"
                        instrument = "etm+"
                    elif sensor_abbr == "L8":
                        platform = "landsat-8"
                        instrument = "oli, trs"
                    elif sensor_abbr == "S1":
                        platform = "sentinel-1"
                        instrument = "c-sar"
                    elif sensor_abbr == "S2":
                        platform = "sentinel-2"
                        instrument = "msi"

        if datatype.lower() == "vector":
            title = "Vector dataset"

        description = "GRASS GIS location/mapset path: /%s/%s" % (
            location, mapset)
        crs = mapset_info["projection"]

        coordinate_transform_extent_to_EPSG_4326(crs=crs, extent=extent)

        # GRASS / actinia do not yet report platform and instrument
        properties = (CollectionProperties(eo_platform=platform,
                                           eo_instrument=instrument,
                                           eo_bands=bands))

        ci = CollectionInformation(id=name, title=title,
                                   description=description,
                                   extent=extent,
                                   properties=properties,
                                   dimensions=dimensions)

        return ci.as_response(http_status=200)
Exemple #10
0
class CollectionInformationResource(Resource):
    def __init__(self):
        self.iface = ActiniaInterface()

    def get(self, name):

        # List strds maps from the GRASS location
        location, mapset, datatype, layer = self.iface.layer_def_to_components(
            name)

        status_code, layer_data = self.iface.layer_info(layer_name=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"
                        "" % (name, str(layer_data))
                    }, 400))

        # Get the projection from the GRASS mapset
        status_code, mapset_info = self.iface.mapset_info(location=location,
                                                          mapset=mapset)
        if status_code != 200:
            return make_response(
                jsonify(
                    {
                        "description":
                        "An internal error occurred "
                        "while catching mapset info "
                        "for mapset <%s>!" % mapset
                    }, 400))

        extent = Extent(spatial=(float(layer_data["west"]),
                                 float(layer_data["south"]),
                                 float(layer_data["east"]),
                                 float(layer_data["north"])))

        title = "Raster dataset"
        if datatype.lower() == "strds":
            title = "Space time raster dataset"
            extent = Extent(spatial=(float(layer_data["west"]),
                                     float(layer_data["south"]),
                                     float(layer_data["east"]),
                                     float(layer_data["north"])),
                            temporal=(layer_data["start_time"],
                                      layer_data["end_time"]))
        if datatype.lower() == "vector":
            title = "Vector dataset"

        description = "GRASS GIS location/mapset path: /%s/%s" % (location,
                                                                  mapset)
        crs = mapset_info["projection"]

        coorindate_transform_extent_to_EPSG_4326(crs=crs, extent=extent)

        ci = CollectionInformation(name=name,
                                   title=title,
                                   description=description,
                                   extent=extent)

        return make_response(ci.to_json(), 200)