diff --git a/gts2_client/gts2_client.py b/gts2_client/gts2_client.py index 7fbbc2aa8600d56d072865704ed6e99ba8c203e6..88efb7e26b0e67f136a75dd8217227842f2a69e9 100755 --- a/gts2_client/gts2_client.py +++ b/gts2_client/gts2_client.py @@ -64,9 +64,12 @@ class Gts2Request(dict): assert opts["sensor"] in ["S2A", "S2B", "S2all"] assert opts["level"] in ["L1C", "L2A"] + # onlytime=False seems to act as onlytime=True, therefore it has to be omitted completelly if false + onlytime = "&onlytime=True" if opts["onlytime"] else "" + self.api_fmt = "{address}/{bands}/{date_from}_{date_to}/{ll_lon:.5f}_{ur_lon:.5f}_{ll_lat:.5f}_{ur_lat:.5f}" \ "?minimum_fill={minimum_fill}&sensor={sensor}&level={level}&version={version}&suffix={suffix}" \ - "&max_cloudy={max_cloudy}&utm_zone={utm_zone}" + "&max_cloudy={max_cloudy}&utm_zone={utm_zone}" + onlytime # construct api call self.api_call = self.api_fmt.format(address=address, bands=opts["bands"], date_from=opts["date_from"], @@ -711,7 +714,7 @@ def __get_auth(logger=None): def client(outpath="", out_prefix="", out_mode="json", geo_ll=(), geo_ur=(), sensor="S2A", bands="", max_cloudy="0.5", level="L2A", start_date="", end_date="", version="0.13", suffix="", minimum_fill="", only_tile="", stack_resolution="10", quiet=False, rgb_extension="jpg", rgb_bands_selection="realistic", - merge_tifs=False, merge_tile=None): + merge_tifs=False, merge_tile=None, onlytime=False): """ Downloads data via API and saves it in a wanted file format (.json, .tiff or .nc) or alternatively returns a python dictionary. @@ -765,6 +768,9 @@ def client(outpath="", out_prefix="", out_mode="json", geo_ll=(), geo_ur=(), sen if out_mode != "rgb" and bands == "": raise AssertionError("Please provide at least one band.") + if onlytime and out_mode not in ["json", "python"]: + raise AssertionError("Invalid output mode. If onlytime==True, choose either 'python' or 'json'") + valid_out_modes = ["json", "nc", "single", "stack", "python", "rgb"] try: assert out_mode in valid_out_modes @@ -782,7 +788,8 @@ def client(outpath="", out_prefix="", out_mode="json", geo_ll=(), geo_ur=(), sen # options opts = {"ll": geo_ll, "ur": geo_ur, "sensor": sensor, "bands": bands, "max_cloudy": max_cloudy, "auth": auth, "level": level, "date_from": start_date, "date_to": end_date, - "version": version, "suffix": suffix, "minimum_fill": minimum_fill, "utm_zone": only_tile, "logger": logger} + "version": version, "suffix": suffix, "minimum_fill": minimum_fill, "utm_zone": only_tile, "logger": logger, + "onlytime": onlytime} # actual API request logger.info("Requesting data from the GTS2 server ...", ) @@ -808,9 +815,9 @@ def client(outpath="", out_prefix="", out_mode="json", geo_ll=(), geo_ur=(), sen if out_mode == "json": logger.info("Saving data to json file ...", ) - json_outfile = "{path}/S2_{level}_{pref}_{lla}_{llo}_{ura}_{uro}_{sdate}_{edate}_{band}.json".format( + json_outfile = "{path}/S2_{level}_{pref}_{lla}_{llo}_{ura}_{uro}_{sdate}_{edate}_{band}{onlytime}.json".format( path=outpath, pref=out_prefix, sdate=start_date, edate=end_date, band=bands, level=level, - lla=geo_ll[0], llo=geo_ll[1], ura=geo_ur[0], uro=geo_ur[1]) + lla=geo_ll[0], llo=geo_ll[1], ura=geo_ur[0], uro=geo_ur[1], onlytime="_onlytime" if onlytime else "") with open(json_outfile, 'w') as f: json.dump(api_result, f, indent=4) @@ -910,6 +917,8 @@ if __name__ == "__main__": help="Merge tifs and RGBs if area in two or more MGRS tiles per time step (True or False).") parser.add_argument("-x", "--merge_tile", action="store", required=False, type=str, default=None, help="Choose MGRS tile into which the merge of files is performed (e.g. 33UUV).") + parser.add_argument("-p", "--onlytime", action="store", required=False, type=str2bool, default=False, + help="get the available timestamps for a specific request without downloading any rasterdata") args = parser.parse_args() @@ -934,4 +943,5 @@ if __name__ == "__main__": rgb_extension=args.rgb_extension, rgb_bands_selection=args.rgb_bands_selection, merge_tifs=args.merge_tifs, - merge_tile=args.merge_tile) + merge_tile=args.merge_tile, + onlytime=args.onlytime) diff --git a/tests/test_gts2_client.py b/tests/test_gts2_client.py index 0ef545c4e43d8c75e1cec7ccad719db52a2e546e..63f01f3223d588b3ee774d7d8811f8f89f58eb0f 100644 --- a/tests/test_gts2_client.py +++ b/tests/test_gts2_client.py @@ -40,13 +40,14 @@ class TestGts2Client(unittest.TestCase): :return: """ - out_modes = ["json", "single", "stack", "stack", "nc", "nc", "rgb", "rgb"] - out_formats = ["json", "tif", "tif", "tif", "nc", "nc", "jpg", "jpg"] - levels = ["L2A", "L2A", "L2A", "L1C", "L2A", "L1C", "L2A", "L1C"] + out_modes = ["json", "single", "stack", "stack", "nc", "nc", "rgb", "rgb", "json"] + out_formats = ["json", "tif", "tif", "tif", "nc", "nc", "jpg", "jpg", "json"] + levels = ["L2A", "L2A", "L2A", "L1C", "L2A", "L1C", "L2A", "L1C", "L2A"] + onlytime = [False] * (len(levels) - 1) + [True] for ii, out_mode in enumerate(out_modes): with tempfile.TemporaryDirectory() as tmpdir: - print("#### Testing {om}".format(om=out_mode)) + print("#### Testing {om}".format(om=out_mode) + " - onlytime" if onlytime[ii] else "") gts2_client.client( outpath=tmpdir, out_prefix=out_mode, @@ -60,7 +61,8 @@ class TestGts2Client(unittest.TestCase): level=levels[ii], max_cloudy=max_cloudy, minimum_fill=minimum_fill, - stack_resolution=stack_res) + stack_resolution=stack_res, + onlytime=onlytime[ii]) list_of_files = glob(os.path.join(tmpdir, "*.{form}".format(form=out_formats[ii]))) if len(list_of_files) == 0: @@ -168,24 +170,36 @@ class TestGts2Client(unittest.TestCase): necessary_keys = ["Acknowledgement", "ControlValues", "Metadata", "Request", "RequestGeoInfo", "Results"] out_mode = "python" - print("#### Testing {om}".format(om=out_mode)) - res = gts2_client.client( - out_mode=out_mode, - geo_ll=geo_ll, - geo_ur=geo_ur, - bands=bands, - start_date=start_date, - end_date=end_date, - version=version, - level=level, - max_cloudy=max_cloudy, - minimum_fill=minimum_fill, - stack_resolution=stack_res, - quiet=True) - - for ki in necessary_keys: - if not (ki in res.keys()): - raise KeyError("{key} is not in returned results.".format(key=ki)) + + for onlytime in [False, True]: + print("#### Testing {om} - onlytime={onlytime}".format(om=out_mode,onlytime=onlytime)) + res = gts2_client.client( + out_mode=out_mode, + geo_ll=geo_ll, + geo_ur=geo_ur, + bands=bands, + start_date=start_date, + end_date=end_date, + version=version, + level=level, + max_cloudy=max_cloudy, + minimum_fill=minimum_fill, + stack_resolution=stack_res, + quiet=True, + onlytime=onlytime) + + for ki in necessary_keys: + if not (ki in res.keys()): + raise KeyError("{key} is not in returned results.".format(key=ki)) + else: + print("Test OK.") + + any_band_downloaded = any([band in list(res["Results"].values())[0].keys() + for band in ['B02_10m', 'B05_20m']]) + if onlytime and any_band_downloaded: + raise AssertionError("onlytime=True but data retrieved anyway") + elif (not onlytime) and (not any_band_downloaded): + raise AssertionError("onlytime=False but not any data downloaded") else: print("Test OK.") @@ -383,7 +397,7 @@ class TestGts2Client(unittest.TestCase): print_run(subprocess.run( ["{python} {script} -o {outpath} -r test -l {lat_ll} -k {lon_ll} -i {lat_ur} -j {lon_ur} " "-b {bands} -s {start_date} -e {end_date} -m {out_mode} -a {sensor} -t {level} -v {version} " - "-c {coreg} -z {max_cloudy} -f {minimum_fill} -d {utm_zone} -g {stack_res}".format( + "-c {coreg} -z {max_cloudy} -f {minimum_fill} -d {utm_zone} -g {stack_res} -h {onlytime}".format( python=sys.executable, script=fn_bin, outpath=tmpdir, @@ -402,7 +416,8 @@ class TestGts2Client(unittest.TestCase): max_cloudy=max_cloudy, minimum_fill=minimum_fill, stack_res=stack_res, - utm_zone="33UUV")], + utm_zone="33UUV", + onlytime=False)], shell=True, check=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env))