diff --git a/coloc_sat/generate_coloc.py b/coloc_sat/generate_coloc.py index 25531b7..8683d10 100644 --- a/coloc_sat/generate_coloc.py +++ b/coloc_sat/generate_coloc.py @@ -1,11 +1,14 @@ import os.path - +import logging from .tools import call_meta_class, get_all_comparison_files, extract_name_from_meta_class, set_config from .intersection import ProductIntersection from .sar_meta import GetSarMeta import numpy as np +logger = logging.getLogger(__name__) + + class GenerateColoc: """ Class that generates co-locations. It can create listings of co-located products and/or generate co-location products. @@ -82,6 +85,7 @@ def __init__(self, product1_id, destination_folder='/tmp', delta_time=60, minima self.product2 = None self.delta_time = delta_time self._minimal_area = minimal_area + self.resampling_method = kwargs.get('resampling_method', None) self.delta_time_np = np.timedelta64(delta_time, 'm') self.destination_folder = destination_folder self._listing_filename = kwargs.get('listing_filename', None) @@ -269,6 +273,7 @@ def fill_intersections(self): opened_file = call_meta_class(file, product_generation=self._product_generation) intersecter = ProductIntersection(self.product1, opened_file, delta_time=self.delta_time, minimal_area=self.minimal_area, + resampling_method=self.resampling_method, product_generation=self._product_generation) _intersections[file] = intersecter except FileNotFoundError: @@ -338,10 +343,10 @@ def save_results(self): if (line not in existing_lines) and (reversed_line not in existing_lines): with open(listing_path, 'a') as listing_file: listing_file.write(line) - print(f"A co-located product have been added in the listing file " + + logger.info(f"A co-located product have been added in the listing file " + f"{listing_path}") else: - print("A co-located product already exists in the listing file " + + logger.info("A co-located product already exists in the listing file " + f"{listing_path}") if self.product_generation(intersection): @@ -351,6 +356,9 @@ def save_results(self): os.makedirs(self.destination_folder) coloc_ds = intersection.coloc_product_datasets coloc_ds.to_netcdf(colocation_product_path) - print(f"A co-located products have been created: {colocation_product_path}") + logger.info(f"A co-located product have been created: {colocation_product_path}") else: - print("No coloc file has been produced, probably because no coloc has been found.") + logger.info("No coloc file has been produced, probably because no coloc has been found.") + return 1 + return 0 + diff --git a/coloc_sat/intersection.py b/coloc_sat/intersection.py index 64d3a0f..88b099d 100644 --- a/coloc_sat/intersection.py +++ b/coloc_sat/intersection.py @@ -8,7 +8,7 @@ import logging import shapely import rasterio - +import rasterio.enums from .intersection_tools import extract_times_dataset, are_dimensions_empty, get_footprint_from_ll_ds, \ get_polygon_area_in_km_squared, get_transform, get_common_points, get_nearest_time_datasets, remove_nat from .tools import mean_time_diff, reformat_meta, convert_str_to_polygon @@ -19,13 +19,16 @@ class ProductIntersection: - def __init__(self, meta1, meta2, delta_time=60, minimal_area=1600, product_generation=True): + def __init__(self, meta1, meta2, delta_time=60, minimal_area=1600, resampling_method="nearest", + product_generation=True): + resampling_mapping = {method.name: method for method in rasterio.enums.Resampling} # Store the meta and rename longitude/latitude by reference ones self._meta1 = reformat_meta(meta1) self._meta2 = reformat_meta(meta2) self.product_generation = product_generation self.delta_time = delta_time self.minimal_area = minimal_area + self.resampling_method = resampling_mapping[resampling_method] self.delta_time_np = np.timedelta64(delta_time, 'm') self.start_date = None self.stop_date = None @@ -463,12 +466,12 @@ def coloc_resample(self): logger.info("Reprojecting dataset with higher resolution to make it match with the lower resolution one.") if pixel_spacing_lon1 * pixel_spacing_lat1 <= pixel_spacing_lon2 * pixel_spacing_lat2: # some product don't have the same resolution, so we apply the same resolution by specifying a resampling - dataset1 = dataset1.rio.reproject_match(dataset2, resampling=rasterio.enums.Resampling.bilinear) + dataset1 = dataset1.rio.reproject_match(dataset2, resampling=self.resampling_method) reprojected_dataset = "dataset1" logger.info("dataset1 reprojected") else: # some product don't have the same resolution, so we apply the same resolution by specifying a resampling - dataset2 = dataset2.rio.reproject_match(dataset1, resampling=rasterio.enums.Resampling.bilinear) + dataset2 = dataset2.rio.reproject_match(dataset1, resampling=self.resampling_method) reprojected_dataset = "dataset2" logger.info("dataset2 reprojected.") logger.info("Done reprojecting dataset.") diff --git a/coloc_sat/scripts/coloc_2_products.py b/coloc_sat/scripts/coloc_2_products.py index 28d3c30..b2e0402 100644 --- a/coloc_sat/scripts/coloc_2_products.py +++ b/coloc_sat/scripts/coloc_2_products.py @@ -1,11 +1,11 @@ import argparse -import coloc_sat -from coloc_sat.generate_coloc import GenerateColoc -from coloc_sat.intersection import __version__ import sys +import rasterio.enums def main(): + resampling_methods = [method.name for method in rasterio.enums.Resampling] + parser = argparse.ArgumentParser(description="Generate co-locations between two products.") parser.add_argument("--product1-id", type=str, help="Path of the first product.") @@ -26,8 +26,11 @@ def main(): help="Name of the listing file to be created.") parser.add_argument("--colocation-filename", nargs='?', type=str, help="Name of the co-location product to be created.") + parser.add_argument("--resampling-method", type=str, default="nearest", + choices=resampling_methods) parser.add_argument("--config", type=str, help="Configuration file to use instead of the " "default one.") + parser.add_argument("--debug", action="store_true", default=False) parser.add_argument("-v", "--version", action="store_true", help="Print version") args = parser.parse_args() @@ -36,7 +39,32 @@ def main(): print(__version__) sys.exit(0) - print(f"The script is executed from {__file__}") + if args.debug: + logging.basicConfig( + level=logging.DEBUG, # Set the logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) + format="%(asctime)s [%(levelname)s]: %(message)s", # Define the log message format + datefmt="%Y-%m-%d %H:%M:%S", # Define the date/time format + ) + logger = logging.getLogger(__name__) + logger.setLevel(logging.DEBUG) + coloc_logger = logging.getLogger("coloc_sat") + coloc_logger.setLevel(logging.DEBUG) + else: + logging.basicConfig( + level=logging.INFO, # Set the logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) + format="%(asctime)s [%(levelname)s]: %(message)s", # Define the log message format + datefmt="%Y-%m-%d %H:%M:%S", # Define the date/time format + ) + logger = logging.getLogger(__name__) + logger.setLevel(logging.INFO) + coloc_logger = logging.getLogger("coloc_sat") + coloc_logger.setLevel(logging.INFO) + + import coloc_sat + from coloc_sat.generate_coloc import GenerateColoc + from coloc_sat.intersection import __version__ + + logger.info(f"The script is executed from {__file__}") # Check for missing required arguments if not args.product1_id or not args.product2_id: @@ -44,14 +72,16 @@ def main(): # Information for the user about listing / co-location product creation if args.listing is True: - print("A listing of the co-located products will be created. To disable, use --no-listing.") + logger.info("A listing of the co-located products will be created. To disable, use --no-listing.") if args.product_generation is True: - print("Co-location products will be created. To disable, use --no-product-generation.") + logger.info("Co-location products will be created. To disable, use --no-product-generation.") - print("WARNING : product colocation has only been tested on _ll_gd SAR products.") + logger.warning("WARNING : product colocation has only been tested on _ll_gd SAR products.") generator = GenerateColoc(**vars(args)) - generator.save_results() + status = generator.save_results() + + logger.info("Coloc python program successfully ended") + sys.exit(status) - print("Coloc python program successfully ended") \ No newline at end of file diff --git a/coloc_sat/scripts/coloc_between_product_and_mission.py b/coloc_sat/scripts/coloc_between_product_and_mission.py index 6ee6fab..540ea32 100644 --- a/coloc_sat/scripts/coloc_between_product_and_mission.py +++ b/coloc_sat/scripts/coloc_between_product_and_mission.py @@ -1,11 +1,12 @@ +import logging import argparse -import coloc_sat -from coloc_sat.generate_coloc import GenerateColoc -from coloc_sat.intersection import __version__ import sys +import rasterio.enums def main(): + resampling_methods = [method.name for method in rasterio.enums.Resampling] + parser = argparse.ArgumentParser(description="Generate co-locations between a specified product and a mission.") parser.add_argument("--product1-id", type=str, help="Path of the first product.") @@ -32,8 +33,11 @@ def main(): help="Name of the listing file to be created.") parser.add_argument("--colocation-filename", nargs='?', type=str, help="Name of the co-location product to be created.") + parser.add_argument("--resampling-method", type=str, default="nearest", + choices=resampling_methods) parser.add_argument("--config", type=str, help="Configuration file to use instead of the " "default one.") + parser.add_argument("--debug", action="store_true", default=False) parser.add_argument("-v", "--version", action="store_true", help="Print version") args = parser.parse_args() @@ -42,11 +46,35 @@ def main(): print(__version__) sys.exit(0) - print(f"The script is executed from {__file__}") + if args.debug: + logging.basicConfig( + level=logging.DEBUG, # Set the logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) + format="%(asctime)s [%(levelname)s]: %(message)s", # Define the log message format + datefmt="%Y-%m-%d %H:%M:%S", # Define the date/time format + ) + logger = logging.getLogger(__name__) + logger.setLevel(logging.DEBUG) + coloc_logger = logging.getLogger("coloc_sat") + coloc_logger.setLevel(logging.DEBUG) + else: + logging.basicConfig( + level=logging.INFO, # Set the logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) + format="%(asctime)s [%(levelname)s]: %(message)s", # Define the log message format + datefmt="%Y-%m-%d %H:%M:%S", # Define the date/time format + ) + logger = logging.getLogger(__name__) + logger.setLevel(logging.INFO) + coloc_logger = logging.getLogger("coloc_sat") + coloc_logger.setLevel(logging.INFO) + + import coloc_sat + from coloc_sat.generate_coloc import GenerateColoc + from coloc_sat.intersection import __version__ + logger.info(f"The script is executed from {__file__}") # Check for missing required arguments if not args.product1_id or not args.mission_name: - parser.error("product1-id and mission-name are required arguments.") + parser.error("product1-id and mission-name are required aprguments.") # rename mission_name by ds_name in the args because it is the argument used in GenerateColoc args.ds_name = args.mission_name @@ -54,13 +82,14 @@ def main(): # Information for the user about listing / co-location product creation if args.listing is True: - print("A listing of the co-located products will be created. To disable, use --no-listing.") + logger.info("A listing of the co-located products will be created. To disable, use --no-listing.") if args.product_generation is True: - print("Co-location products will be created. To disable, use --no-product-generation.") + logger.info("Co-location products will be created. To disable, use --no-product-generation.") - print("WARNING : product colocation has only been tested on _ll_gd SAR products.") + logger.warning("WARNING : product colocation has only been tested on _ll_gd SAR products.") generator = GenerateColoc(**vars(args)) - generator.save_results() + status = generator.save_results() - print("Coloc python program successfully ended") + logger.info("Coloc python program successfully ended") + sys.exit(status)