From 523c99f3c8e74c84ef73ec97685ff8898017b2b7 Mon Sep 17 00:00:00 2001 From: HamedElgizery Date: Mon, 24 Jun 2024 23:36:23 +0300 Subject: [PATCH] Add footprints option to save the search results footprints after downloading them --- src/imagery/i.eodag/i.eodag.py | 95 ++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/src/imagery/i.eodag/i.eodag.py b/src/imagery/i.eodag/i.eodag.py index df43a40ce2..c506677d27 100755 --- a/src/imagery/i.eodag/i.eodag.py +++ b/src/imagery/i.eodag/i.eodag.py @@ -91,6 +91,13 @@ # % guisection: Region # %end +# %option G_OPT_V_OUTPUT +# % key: footprints +# % description: Name for output vector map with footprints +# % required: no +# % guisection: Output +# %end + # %option # % key: minimum_overlap # % type: integer @@ -168,6 +175,7 @@ from subprocess import PIPE from datetime import datetime, timedelta from functools import cmp_to_key +from collections import OrderedDict import grass.script as gs from grass.pygrass.modules import Module @@ -591,6 +599,91 @@ def products_compare(first, second): return search_result +def save_footprints(search_result, map_name): + """Save products footprints as a vector map in the current mapset. + + Reprojection is done on the fly. + + :param search_result: EO products to be sorted + :type search_result: class'eodag.api.search_result.SearchResult' + + :param map_name: Footprint name to be used. + :type map_name: str + """ + try: + from osgeo import ogr, osr + except ImportError as e: + gs.fatal(_("Option requires GDAL library: {}").format(e)) + + gs.message(_("Writing footprints into <{}>...").format(map_name)) + driver = ogr.GetDriverByName("GPKG") + tmp_name = gs.tempfile() + ".gpkg" + data_source = driver.CreateDataSource(tmp_name) + + srs = osr.SpatialReference() + srs.ImportFromEPSG(4326) + + # features can be polygons or multi-polygons + layer = data_source.CreateLayer(str(map_name), srs, ogr.wkbMultiPolygon) + + # attributes + attrs = OrderedDict( + [ + ("uuid", ogr.OFTString), + ("ingestiondate", ogr.OFTString), + ("cloudcoverpercentage", ogr.OFTInteger), + ("producttype", ogr.OFTString), + ("identifier", ogr.OFTString), + ] + ) + + for key, val in attrs.items(): + field = ogr.FieldDefn(key, val) + layer.CreateField(field) + + # features + for idx in range(len(search_result)): + wkt = search_result[idx].properties["gmlgeometry"] + feature = ogr.Feature(layer.GetLayerDefn()) + newgeom = ogr.CreateGeometryFromGML(wkt) + # convert polygons to multi-polygons + newgeomtype = ogr.GT_Flatten(newgeom.GetGeometryType()) + if newgeomtype == ogr.wkbPolygon: + multigeom = ogr.Geometry(ogr.wkbMultiPolygon) + multigeom.AddGeometryDirectly(newgeom) + feature.SetGeometry(multigeom) + else: + feature.SetGeometry(newgeom) + for key in attrs.keys(): + if key == "ingestiondate": + value = search_result[idx].properties["startTimeFromAscendingNode"] + elif key == "uuid": + value = search_result[idx].properties["uid"] + elif key == "cloudcoverpercentage": + value = search_result[idx].properties["cloudCover"] + elif key == "producttype": + value = search_result[idx].properties["productType"] + elif key == "identifier": + # Not sure if that is what is meant by identifier + value = search_result[idx].properties["platformSerialIdentifier"] + feature.SetField(key, value) + layer.CreateFeature(feature) + feature = None + + data_source = None + + # coordinates of footprints are in WKT -> fp precision issues + # -> snap + gs.run_command( + "v.import", + input=tmp_name, + output=map_name, + layer=map_name, + snap=1e-10, + quiet=True, + ) + + def main(): # Products: https://github.com/CS-SI/eodag/blob/develop/eodag/resources/product_types.yml @@ -667,6 +760,8 @@ def main(): # TODO: Add timeout and wait parameters for downloading offline products... # https://eodag.readthedocs.io/en/stable/getting_started_guide/product_storage_status.html dag.download_all(search_result) + if options["footprints"]: + save_footprints(search_result, options["footprints"]) if __name__ == "__main__":