From 795fef00cfb2f3cf3b8ff739e84bdf484f563d07 Mon Sep 17 00:00:00 2001 From: Lea Vauchier Date: Thu, 4 Sep 2025 10:52:16 +0200 Subject: [PATCH] Add synthetic flag criterium on donor points --- CHANGELOG.md | 2 + configs/configs_patchwork.yaml | 2 + patchwork/patchwork.py | 77 ++++++++++--- test/configs/config_test_mount_points.yaml | 2 + test/data/recipient_with_synthetic_points.laz | Bin 0 -> 63510 bytes test/test_patchwork.py | 106 ++++++++++++++---- 6 files changed, 148 insertions(+), 41 deletions(-) create mode 100644 test/data/recipient_with_synthetic_points.laz diff --git a/CHANGELOG.md b/CHANGELOG.md index 904864c..37ca684 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # CHANGELOG +- Possibilité d'ignorer les points synthétiques du fichier donneur (paramètre DONOR_USE_SYNTHETIC_POINTS dans le fichier de config) + ## 1.2.1 - Ajout de gdal dans l'image docker (fichiers manquant pour l'utiliser en ligne de commande) diff --git a/configs/configs_patchwork.yaml b/configs/configs_patchwork.yaml index 688f7b0..2082851 100644 --- a/configs/configs_patchwork.yaml +++ b/configs/configs_patchwork.yaml @@ -48,6 +48,8 @@ mount_points: CRS: 2154 DONOR_CLASS_LIST: [2, 22] +DONOR_USE_SYNTHETIC_POINTS: false + RECIPIENT_CLASS_LIST: [2, 6, 9, 17] TILE_SIZE: 1000 diff --git a/patchwork/patchwork.py b/patchwork/patchwork.py index bc850d4..51a41ad 100644 --- a/patchwork/patchwork.py +++ b/patchwork/patchwork.py @@ -16,41 +16,68 @@ def get_selected_classes_points( - config: DictConfig, tile_origin: Tuple[int, int], points_list: ScaleAwarePointRecord, class_list: list[int], + use_synthetic_points: bool, fields_to_keep: list[str], + patch_size: int, + tile_size: int, ) -> pd.DataFrame: - """get a list of points from a las, and return a ndarray of those point with the selected classification""" - + """Get a list of points from a las, filter them based on classification an d synthetic flag + and return them as a pandas dataframe + + Args: + tile_origin (Tuple[int, int]): Origin point of the tile (in meters) + points_list (ScaleAwarePointRecord): Points list in laspy format + class_list (list[int]): List of classes to keep + use_synthetic_points (bool): if false, filter out points with flag "synthetic" = True + fields_to_keep (list[str]): Las file attribute to keep in the output dataframe + patch_size (int): Size of the patches (for discretization) + tile_size (int): Size of the tile + + Raises: + NotImplementedError: Filtering out synthetic points is implemented only + if the synthetic field is in fields_to_keep + + Returns: + pd.DataFrame: Filtered points list as a pd.DataFrame + """ # we add automatically classification, so we remove it if it's in field_to_keep if c.CLASSIFICATION_STR in fields_to_keep: fields_to_keep.remove(c.CLASSIFICATION_STR) table_fields_to_keep = [points_list[field] for field in fields_to_keep] table_field_necessary = [ - np.int32(points_list.x / config.PATCH_SIZE), # convert x into the coordinate of the patch - np.int32(points_list.y / config.PATCH_SIZE), # convert y into the coordinate of the patch + np.int32(points_list.x / patch_size), # convert x into the coordinate of the patch + np.int32(points_list.y / patch_size), # convert y into the coordinate of the patch points_list.classification, ] + all_fields_list = [*fields_to_keep, c.PATCH_X_STR, c.PATCH_Y_STR, c.CLASSIFICATION_STR] all_classes_points = np.array(table_fields_to_keep + table_field_necessary).transpose() + df_points = pd.DataFrame(all_classes_points, columns=all_fields_list) - mask = np.zeros(len(all_classes_points), dtype=bool) - for classification in class_list: - mask = mask | (all_classes_points[:, -1] == classification) - wanted_classes_points = all_classes_points[mask] - all_fields_list = [*fields_to_keep, c.PATCH_X_STR, c.PATCH_Y_STR, c.CLASSIFICATION_STR] - df_wanted_classes_points = pd.DataFrame(wanted_classes_points, columns=all_fields_list) + # Filter points based on classification + df_points = df_points[df_points.classification.isin(class_list)] + + # Filter based on if the point is synthetic + if not use_synthetic_points: + if "synthetic" in fields_to_keep: + df_points = df_points[np.logical_not(df_points.synthetic)] + else: + raise NotImplementedError( + "'get_selected_classes_points' is asked to filter on synthetic flag, " + "but this flag is not in fields to keep." + ) # "push" the points on the limit of the tile to the closest patch - mask_points_on_max_x = df_wanted_classes_points[c.PATCH_X_STR] == tile_origin[0] + config.TILE_SIZE - df_wanted_classes_points.loc[mask_points_on_max_x, c.PATCH_X_STR] = tile_origin[0] + config.TILE_SIZE - 1 - mask_points_on_max_y = df_wanted_classes_points[c.PATCH_Y_STR] == tile_origin[1] - df_wanted_classes_points.loc[mask_points_on_max_y, c.PATCH_Y_STR] = tile_origin[1] - 1 + mask_points_on_max_x = df_points[c.PATCH_X_STR] == tile_origin[0] + tile_size + df_points.loc[mask_points_on_max_x, c.PATCH_X_STR] = tile_origin[0] + tile_size - 1 + mask_points_on_max_y = df_points[c.PATCH_Y_STR] == tile_origin[1] + df_points.loc[mask_points_on_max_y, c.PATCH_Y_STR] = tile_origin[1] - 1 - return df_wanted_classes_points + return df_points def get_type(new_column_size: int): @@ -75,7 +102,13 @@ def get_complementary_points( recipient_points = recipient_file.read().points df_recipient_points = get_selected_classes_points( - config, tile_origin, recipient_points, config.RECIPIENT_CLASS_LIST, [] + tile_origin, + recipient_points, + config.RECIPIENT_CLASS_LIST, + use_synthetic_points=True, + fields_to_keep=[], + patch_size=config.PATCH_SIZE, + tile_size=config.TILE_SIZE, ) # set, for each patch of coordinate (patch_x, patch_y), the number of recipient point @@ -100,7 +133,15 @@ def get_complementary_points( donor_columns = get_field_from_header(donor_file) dfs_donor_points.append( - get_selected_classes_points(config, tile_origin, donor_points, config.DONOR_CLASS_LIST, donor_columns) + get_selected_classes_points( + tile_origin, + donor_points, + config.DONOR_CLASS_LIST, + config.DONOR_USE_SYNTHETIC_POINTS, + donor_columns, + patch_size=config.PATCH_SIZE, + tile_size=config.TILE_SIZE, + ) ) if len(df_donor_info.index): diff --git a/test/configs/config_test_mount_points.yaml b/test/configs/config_test_mount_points.yaml index a2581e2..ea17550 100644 --- a/test/configs/config_test_mount_points.yaml +++ b/test/configs/config_test_mount_points.yaml @@ -50,6 +50,8 @@ mount_points: CRS: 2154 +DONOR_USE_SYNTHETIC_POINTS: true + DONOR_CLASS_LIST: [2, 22] RECIPIENT_CLASS_LIST: [2, 6, 9, 17] diff --git a/test/data/recipient_with_synthetic_points.laz b/test/data/recipient_with_synthetic_points.laz new file mode 100644 index 0000000000000000000000000000000000000000..17ea7840dd5b60484053b410f8360be8268d162b GIT binary patch literal 63510 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∨vvw-eX7TL>9Pfsau{nM?I22ys6dAFQoA#7 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 +1HAJI_3uk5X{9aJMT^kk0r&6zCZ~n4uL2-VeS& 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 A`v3p{ literal 0 HcmV?d00001 diff --git a/test/test_patchwork.py b/test/test_patchwork.py index 4c5d66e..63b5f3f 100644 --- a/test/test_patchwork.py +++ b/test/test_patchwork.py @@ -18,7 +18,7 @@ patchwork, ) -RECIPIENT_TEST_DIR = "test/data/" +TEST_DATA_DIR = "test/data/" RECIPIENT_TEST_NAME = "recipient_test.laz" DONOR_CLASS_LIST = [2, 9] @@ -29,37 +29,79 @@ NEW_COLUMN = "virtual_column" NEW_COLUMN_SIZE = 8 VALUE_ADDED_POINTS = 1 +TILE_SIZE = 1000 +PATCH_SIZE = 1 SHP_X_Y_TO_METER_FACTOR = 1000 def test_get_field_from_header(): - with laspy.open(os.path.join(RECIPIENT_TEST_DIR, RECIPIENT_TEST_NAME)) as recipient_file: + with laspy.open(os.path.join(TEST_DATA_DIR, RECIPIENT_TEST_NAME)) as recipient_file: recipient_fields_list = get_field_from_header(recipient_file) assert len(recipient_fields_list) == 18 # check if all fields are lower case assert [field for field in recipient_fields_list if field != field.lower()] == [] -def test_get_selected_classes_points(): - with initialize(version_base="1.2", config_path="../configs"): - config = compose( - config_name="configs_patchwork.yaml", - overrides=[ - f"filepath.RECIPIENT_DIRECTORY={RECIPIENT_TEST_DIR}", - f"filepath.RECIPIENT_NAME={RECIPIENT_TEST_NAME}", - f"RECIPIENT_CLASS_LIST={RECIPIENT_CLASS_LIST}", - ], +@pytest.mark.parametrize( + "las_path, class_list, fields_to_keep, use_synthetic", + [ + # Keep all points + (os.path.join(TEST_DATA_DIR, RECIPIENT_TEST_NAME), [1, 2, 3, 4, 5], ["synthetic", "intensity"], True), + # Filter on class only + (os.path.join(TEST_DATA_DIR, RECIPIENT_TEST_NAME), [2, 3], ["synthetic", "intensity"], True), + # Filter out synthetic points + (os.path.join(TEST_DATA_DIR, RECIPIENT_TEST_NAME), [2, 3], ["synthetic", "x"], False), + ], +) +def test_get_selected_classes_points(las_path, class_list, fields_to_keep, use_synthetic): + tile_origin = get_tile_origin_using_header_info(las_path, TILE_SIZE) + with laspy.open(las_path) as recipient_file: + input_points = recipient_file.read().points + df_output_points = get_selected_classes_points( + tile_origin, + input_points, + class_list, + fields_to_keep=fields_to_keep, + use_synthetic_points=use_synthetic, + patch_size=PATCH_SIZE, + tile_size=TILE_SIZE, ) - recipient_path = os.path.join(config.filepath.RECIPIENT_DIRECTORY, config.filepath.RECIPIENT_NAME) - tile_origin_recipient = get_tile_origin_using_header_info(recipient_path, config.TILE_SIZE) - with laspy.open(recipient_path) as recipient_file: - recipient_points = recipient_file.read().points - df_recipient_points = get_selected_classes_points( - config, tile_origin_recipient, recipient_points, config.RECIPIENT_CLASS_LIST, [] + assert len(df_output_points.index), "No points in output dataframe" + classification = set(df_output_points[c.CLASSIFICATION_STR]) + assert classification.issubset(class_list) + assert set(df_output_points.columns.values) == { + *fields_to_keep, + c.PATCH_X_STR, + c.PATCH_Y_STR, + c.CLASSIFICATION_STR, + } + if use_synthetic: + assert len(df_output_points.index) == np.count_nonzero( + np.isin(np.array(input_points.classification), class_list) + ) + else: + assert not np.any(df_output_points.synthetic) + + +def test_get_selected_classes_points_raise_error(): + las_path = os.path.join(TEST_DATA_DIR, "recipient_with_synthetic_points.laz") + class_list = [2, 3] + fields_to_keep = [] + use_synthetic = False + tile_origin = get_tile_origin_using_header_info(las_path, TILE_SIZE) + with pytest.raises(NotImplementedError): + with laspy.open(las_path) as las_path: + input_points = las_path.read().points + get_selected_classes_points( + tile_origin, + input_points, + class_list, + fields_to_keep=fields_to_keep, + use_synthetic_points=use_synthetic, + patch_size=PATCH_SIZE, + tile_size=TILE_SIZE, ) - for classification in np.unique(df_recipient_points[c.CLASSIFICATION_STR]): - assert classification in RECIPIENT_CLASS_LIST @pytest.mark.parametrize( @@ -104,6 +146,7 @@ def test_get_complementary_points(donor_info_path, recipient_path, x, y, expecte f"DONOR_CLASS_LIST={DONOR_CLASS_LIST}", f"RECIPIENT_CLASS_LIST={RECIPIENT_CLASS_LIST}", f"+VIRTUAL_CLASS_TRANSLATION={VIRTUAL_CLASS_TRANSLATION}", + "DONOR_USE_SYNTHETIC_POINTS=true", ], ) complementary_points = get_complementary_points(df_donor_info, recipient_path, (x, y), config) @@ -157,6 +200,7 @@ def test_get_complementary_points_2_more_fields(tmp_path_factory): f"DONOR_CLASS_LIST={DONOR_CLASS_LIST}", f"RECIPIENT_CLASS_LIST={RECIPIENT_CLASS_LIST}", f"+VIRTUAL_CLASS_TRANSLATION={VIRTUAL_CLASS_TRANSLATION}", + "DONOR_USE_SYNTHETIC_POINTS=true", ], ) @@ -193,7 +237,7 @@ def test_append_points(tmp_path_factory): config = compose( config_name="configs_patchwork.yaml", overrides=[ - f"filepath.RECIPIENT_DIRECTORY={RECIPIENT_TEST_DIR}", + f"filepath.RECIPIENT_DIRECTORY={TEST_DATA_DIR}", f"filepath.RECIPIENT_NAME={RECIPIENT_TEST_NAME}", f"filepath.OUTPUT_DIR={tmp_file_dir}", f"filepath.OUTPUT_NAME={tmp_file_name}", @@ -251,7 +295,7 @@ def test_append_points_new_column(tmp_path_factory): config = compose( config_name="configs_patchwork.yaml", overrides=[ - f"filepath.RECIPIENT_DIRECTORY={RECIPIENT_TEST_DIR}", + f"filepath.RECIPIENT_DIRECTORY={TEST_DATA_DIR}", f"filepath.RECIPIENT_NAME={RECIPIENT_TEST_NAME}", f"filepath.OUTPUT_DIR={tmp_file_dir}", f"filepath.OUTPUT_NAME={tmp_file_name}", @@ -326,6 +370,7 @@ def test_patchwork_default(tmp_path_factory, recipient_path, expected_nb_added_p f"DONOR_CLASS_LIST={DONOR_CLASS_LIST}", f"RECIPIENT_CLASS_LIST={RECIPIENT_CLASS_LIST}", f"+VIRTUAL_CLASS_TRANSLATION={VIRTUAL_CLASS_TRANSLATION}", + "DONOR_USE_SYNTHETIC_POINTS=true", "NEW_COLUMN=null", ], ) @@ -346,7 +391,7 @@ def test_patchwork_default(tmp_path_factory, recipient_path, expected_nb_added_p @pytest.mark.parametrize( - "recipient_path, expected_nb_added_points", + "recipient_path, donor_use_synthetic_points, expected_nb_added_points", # expected_nb_points value set after inspection of the initial result using qgis: # - there are points only inside the shapefile geometry # - when visualizing a grid, there seems to be no points in the cells where there is ground points in the @@ -354,19 +399,32 @@ def test_patchwork_default(tmp_path_factory, recipient_path, expected_nb_added_p [ ( "test/data/lidar_HD_decimated/Semis_2022_0673_6362_LA93_IGN69_decimated.laz", + True, 128675, ), # One donor + ( + "test/data/lidar_HD_decimated/Semis_2022_0673_6362_LA93_IGN69_decimated.laz", + False, + 127961, + ), # One donor, no synthetic points ( "test/data/lidar_HD_decimated/Semis_2022_0673_6363_LA93_IGN69_decimated.laz", + True, 149490, ), # Two donors + ( + "test/data/lidar_HD_decimated/Semis_2022_0673_6363_LA93_IGN69_decimated.laz", + False, + 149340, + ), # Two donors, no synthetic points ( "test/data/lidar_HD_decimated/Semis_2022_0674_6363_LA93_IGN69_decimated.laz", + True, 0, ), # No donor ], ) -def test_patchwork_with_origin(tmp_path_factory, recipient_path, expected_nb_added_points): +def test_patchwork_with_origin(tmp_path_factory, recipient_path, donor_use_synthetic_points, expected_nb_added_points): input_shp_path = "test/data/shapefile_local/patchwork_geometries.shp" tmp_file_dir = tmp_path_factory.mktemp("data") tmp_output_las_name = "result_patchwork.laz" @@ -386,6 +444,7 @@ def test_patchwork_with_origin(tmp_path_factory, recipient_path, expected_nb_add f"filepath.OUTPUT_INDICES_MAP_NAME={tmp_output_indices_map_name}", f"DONOR_CLASS_LIST={DONOR_CLASS_LIST}", f"RECIPIENT_CLASS_LIST={RECIPIENT_CLASS_LIST}", + f"DONOR_USE_SYNTHETIC_POINTS={donor_use_synthetic_points}", "NEW_COLUMN='Origin'", ], ) @@ -411,6 +470,7 @@ def test_patchwork_with_origin(tmp_path_factory, recipient_path, expected_nb_add @pytest.mark.parametrize( "input_shp_path, recipient_path, expected_nb_added_points", # Same tests as "test_patchwork_default", but with shapefiles that refer to paths in mounted stores + # All tests keep synthetic points [ ( "test/data/shapefile_mounted_unix_path/patchwork_geometries.shp",