Skip to content

Commit

Permalink
Fix type error in DropPointsByClass
Browse files Browse the repository at this point in the history
  • Loading branch information
leavauchier committed Mar 7, 2024
1 parent 11bbad5 commit 2dac87d
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 15 deletions.
10 changes: 5 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0
rev: v4.5.0
hooks:
# list of supported hooks: https://pre-commit.com/hooks.html
- id: trailing-whitespace
Expand All @@ -12,26 +12,26 @@ repos:

# python code formatting
- repo: https://github.com/psf/black
rev: 20.8b1
rev: 24.2.0
hooks:
- id: black
args: [--line-length, "99"]

# python import sorting
- repo: https://github.com/PyCQA/isort
rev: 5.8.0
rev: 5.13.2
hooks:
- id: isort

# yaml formatting
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.3.0
rev: v4.0.0-alpha.8
hooks:
- id: prettier
types: [yaml]

# python code analysis
- repo: https://github.com/PyCQA/flake8
rev: 3.9.2
rev: 7.0.0
hooks:
- id: flake8
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# CHANGELOG
### 3.8.2
- fix: type error in edge case when dropping points in transforms

### 3.8.1
- fix: propagate input las format to output las (in particular epsg which comes either from input or config)

Expand Down
7 changes: 4 additions & 3 deletions myria3d/pctl/transforms/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ def subsample_data(data, num_nodes, choice):
continue
elif torch.is_tensor(item) and item.size(0) == num_nodes and item.size(0) != 1:
data[key] = item[choice]
elif isinstance(item, np.ndarray) and item.shape[0] == num_nodes and item.shape[0] != 1:
data[key] = item[choice]

return data


Expand Down Expand Up @@ -234,7 +237,5 @@ def __call__(self, data):
if points_to_drop.sum() > 0:
points_to_keep = torch.logical_not(points_to_drop)
data = subsample_data(data, num_nodes=data.num_nodes, choice=points_to_keep)
# Here we also subsample these idx since we do not need to interpolate these points back
if "idx_in_original_cloud" in data:
data.idx_in_original_cloud = data.idx_in_original_cloud[points_to_keep]

return data
2 changes: 1 addition & 1 deletion package_metadata.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__: "3.8.1"
__version__: "3.8.2"
__name__: "myria3d"
__url__: "https://github.com/IGNF/myria3d"
__description__: "Deep Learning for the Semantic Segmentation of Aerial Lidar Point Clouds"
Expand Down
28 changes: 28 additions & 0 deletions tests/myria3d/models/test_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import hydra
from pytorch_lightning import LightningDataModule
from tests.conftest import make_default_hydra_cfg

from myria3d.models.model import Model


def test_model_get_batch_tensor_by_enumeration():
config = make_default_hydra_cfg(
overrides=[
"predict.src_las=tests/data/toy_dataset_src/862000_6652000.classified_toy_dataset.100mx100m.las",
"datamodule.epsg=2154",
"work_dir=./../../..",
"datamodule.subtile_width=1",
"datamodule.hdf5_file_path=null",
]
)

datamodule: LightningDataModule = hydra.utils.instantiate(config.datamodule)
datamodule._set_predict_data(config.predict.src_las)

model = Model(
neural_net_class_name="PyGRandLANet",
neural_net_hparams=dict(num_features=2, num_classes=7),
)
for batch in datamodule.predict_dataloader():
# Check that no error is raised ("TypeError: object of type 'numpy.int64' has no len()")
_ = model._get_batch_tensor_by_enumeration(batch.idx_in_original_cloud)
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import numpy as np
import pytest
import torch_geometric
import torch
import torch_geometric

from myria3d.pctl.transforms.transforms import TargetTransform, DropPointsByClass
from myria3d.pctl.transforms.transforms import DropPointsByClass, TargetTransform


def test_TargetTransform_with_valid_config():
Expand All @@ -12,10 +12,12 @@ def test_TargetTransform_with_valid_config():
# 1 becomes 0, and 6 becomes 1.
classification_dict = {1: "unclassified", 6: "building"}
tt = TargetTransform(classification_preprocessing_dict, classification_dict)

y = np.array([1, 1, 2, 2, 6, 6])
data = torch_geometric.data.Data(x=None, y=y)
assert np.array_equal(tt(data).y, np.array([0, 0, 0, 0, 1, 1]))
idx = np.arange(6)
data = torch_geometric.data.Data(x=None, y=y, idx_in_original_cloud=idx)
out_data = tt(data)
assert np.array_equal(out_data.y, np.array([0, 0, 0, 0, 1, 1]))
assert np.array_equal(out_data.idx_in_original_cloud, idx)


def test_TargetTransform_throws_type_error_if_invalid_classification_dict():
Expand All @@ -34,11 +36,16 @@ def test_DropPointsByClass():
# points with class 65 are droped.
y = torch.Tensor([1, 65, 65, 2, 65])
x = torch.rand((5, 3))
data = torch_geometric.data.Data(x=x, y=y)
idx = np.arange(5) # Not a tensor
data = torch_geometric.data.Data(x=x, y=y, idx_in_original_cloud=idx)
drop_transforms = DropPointsByClass()
transformed_data = drop_transforms(data)
assert torch.equal(transformed_data.y, torch.Tensor([1, 2]))
assert transformed_data.x.size(0) == 2
print(type(transformed_data.idx_in_original_cloud))
assert isinstance(transformed_data.idx_in_original_cloud, np.ndarray)
assert transformed_data.idx_in_original_cloud.size == 2
assert np.all(transformed_data.idx_in_original_cloud == np.array([0, 3]))

# No modification
x = torch.rand((3, 3))
Expand All @@ -47,3 +54,15 @@ def test_DropPointsByClass():
transformed_data = drop_transforms(data)
assert torch.equal(data.x, transformed_data.x)
assert torch.equal(data.y, transformed_data.y)

# Keep one point only
y = torch.Tensor([1, 65, 65, 65, 65])
x = torch.rand((5, 3))
idx = np.arange(5) # Not a tensor
data = torch_geometric.data.Data(x=x, y=y, idx_in_original_cloud=idx)
transformed_data = drop_transforms(data)
assert torch.equal(transformed_data.y, torch.Tensor([1]))
assert transformed_data.x.size(0) == 1
assert isinstance(transformed_data.idx_in_original_cloud, np.ndarray)
assert transformed_data.idx_in_original_cloud.shape[0] == 1
assert np.all(transformed_data.idx_in_original_cloud == np.array([0]))

0 comments on commit 2dac87d

Please sign in to comment.