Skip to content

Commit

Permalink
Merge pull request #375 from KRiedmiller/cyl_radii_type
Browse files Browse the repository at this point in the history
Cyl radii type
  • Loading branch information
dokempf authored Feb 18, 2025
2 parents 02f7ae3 + 0fcdaf8 commit ee52bb3
Show file tree
Hide file tree
Showing 12 changed files with 58 additions and 48 deletions.
4 changes: 2 additions & 2 deletions jupyter/4dobc-creation.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
"metadata": {},
"outputs": [],
"source": [
"analysis.m3c2 = py4dgeo.M3C2(cyl_radii=[2.0], normal_radii=[2.0])"
"analysis.m3c2 = py4dgeo.M3C2(cyl_radius=2.0, normal_radii=[2.0])"
]
},
{
Expand Down Expand Up @@ -258,7 +258,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.6"
"version": "3.12.3"
}
},
"nbformat": 4,
Expand Down
10 changes: 4 additions & 6 deletions jupyter/customization.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,7 @@
"metadata": {},
"outputs": [],
"source": [
"DirectionAlgorithm(\n",
" epochs=(epoch1, epoch2), corepoints=corepoints, cyl_radii=(5.0,)\n",
").run()"
"DirectionAlgorithm(epochs=(epoch1, epoch2), corepoints=corepoints, cyl_radius=5.0).run()"
]
},
{
Expand Down Expand Up @@ -188,7 +186,7 @@
"CallbackAlgorithm(\n",
" epochs=(epoch1, epoch2),\n",
" corepoints=corepoints,\n",
" cyl_radii=(2.0,),\n",
" cyl_radius=2.0,\n",
" normal_radii=(1.0, 2.0),\n",
").run()"
]
Expand Down Expand Up @@ -221,7 +219,7 @@
"PythonFallbackM3C2(\n",
" epochs=(epoch1, epoch2),\n",
" corepoints=corepoints,\n",
" cyl_radii=(2.0,),\n",
" cyl_radius=2.0,\n",
" normal_radii=(1.0, 2.0),\n",
").run()"
]
Expand Down Expand Up @@ -267,7 +265,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.6"
"version": "3.12.3"
}
},
"nbformat": 4,
Expand Down
4 changes: 2 additions & 2 deletions jupyter/m3c2.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
"m3c2 = py4dgeo.M3C2(\n",
" epochs=(epoch1, epoch2),\n",
" corepoints=corepoints,\n",
" cyl_radii=(2.0,),\n",
" cyl_radius=2.0,\n",
" normal_radii=[0.5, 1.0, 2.0],\n",
")\n",
"\n",
Expand Down Expand Up @@ -209,7 +209,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.12"
"version": "3.12.3"
}
},
"nbformat": 4,
Expand Down
4 changes: 2 additions & 2 deletions jupyter/m3c2ep.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@
" epochs=(epoch1, epoch2),\n",
" corepoints=corepoints,\n",
" normal_radii=(0.5, 1.0, 2.0),\n",
" cyl_radii=(0.5,),\n",
" cyl_radius=0.5,\n",
" max_distance=3.0,\n",
" Cxx=Cxx,\n",
" tfM=tfM,\n",
Expand Down Expand Up @@ -364,7 +364,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.4"
"version": "3.12.3"
}
},
"nbformat": 4,
Expand Down
8 changes: 3 additions & 5 deletions src/py4dgeo/cloudcompare.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"normalscale": "normal_radii",
"registrationerror": "reg_error",
"searchdepth": "max_distance",
"searchscale": "cyl_radii",
"searchscale": "cyl_radius",
"usemedian": "robust_aggr",
}

Expand All @@ -21,10 +21,8 @@ def __init__(self, **params):
# Apply changes that are not a mere renaming

# Scale parameters are diameters in CloudCompare and radii in py4dgeo
if "cyl_radii" in py4dgeo_params:
py4dgeo_params["cyl_radii"] = tuple(
0.5 * r for r in py4dgeo_params["cyl_radii"]
)
if "cyl_radius" in py4dgeo_params:
py4dgeo_params["cyl_radius"] = py4dgeo_params["cyl_radius"] * 0.5
if "normal_radii" in py4dgeo_params:
py4dgeo_params["normal_radii"] = tuple(
0.5 * r for r in py4dgeo_params["normal_radii"]
Expand Down
25 changes: 19 additions & 6 deletions src/py4dgeo/m3c2.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from ast import List
from py4dgeo.epoch import Epoch, as_epoch
from py4dgeo.util import (
as_double_precision,
Expand All @@ -22,16 +23,18 @@
class M3C2LikeAlgorithm(abc.ABC):
def __init__(
self,
epochs: typing.Tuple[Epoch, ...] = None,
corepoints: np.ndarray = None,
cyl_radii: typing.List[float] = None,
epochs: typing.Optional[typing.Tuple[Epoch, ...]] = None,
corepoints: typing.Optional[np.ndarray] = None,
cyl_radii: typing.Optional[List] = None,
cyl_radius: typing.Optional[float] = None,
max_distance: float = 0.0,
registration_error: float = 0.0,
robust_aggr: bool = False,
):
self.epochs = epochs
self.corepoints = corepoints
self.cyl_radii = cyl_radii
self.cyl_radius = cyl_radius
self.max_distance = max_distance
self.registration_error = registration_error
self.robust_aggr = robust_aggr
Expand Down Expand Up @@ -72,9 +75,19 @@ def directions(self):
def calculate_distances(self, epoch1, epoch2):
"""Calculate the distances between two epochs"""

if self.cyl_radii is None or len(self.cyl_radii) != 1:
if isinstance(self.cyl_radii, typing.Iterable):
logger.warning(
"DEPRECATION: use cyl_radius instead of cyl_radii. In a future version, cyl_radii will be removed!"
)
if len(self.cyl_radii) != 1:
Py4DGeoError("cyl_radii must be a list containing a single float!")
elif self.cyl_radius is None:
self.cyl_radius = self.cyl_radii[0]
self.cyl_radii = None

if self.cyl_radius is None:
raise Py4DGeoError(
f"{self.name} requires exactly one cylinder radius to be given"
f"{self.name} requires exactly one cylinder radius to be given as a float."
)

# Ensure that the KDTree data structures have been built. This is no-op
Expand All @@ -85,7 +98,7 @@ def calculate_distances(self, epoch1, epoch2):

distances, uncertainties = _py4dgeo.compute_distances(
self.corepoints,
self.cyl_radii[0],
self.cyl_radius,
epoch1,
epoch2,
self.directions(),
Expand Down
4 changes: 2 additions & 2 deletions src/py4dgeo/m3c2ep.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def calculate_distances(self, epoch1, epoch2):
print(self.name + " running")
"""Calculate the distances between two epochs"""

if self.cyl_radii is None or len(self.cyl_radii) != 1:
if not isinstance(self.cyl_radius, float):
raise Py4DGeoError(
f"{self.name} requires exactly one cylinder radius to be given"
)
Expand All @@ -71,7 +71,7 @@ def calculate_distances(self, epoch1, epoch2):

# set default M3C2Meta
M3C2Meta = {"searchrad": 0.5, "maxdist": 3, "minneigh": 5, "maxneigh": 100000}
M3C2Meta["searchrad"] = self.cyl_radii[0]
M3C2Meta["searchrad"] = self.cyl_radius
M3C2Meta["maxdist"] = self.max_distance

M3C2Meta["spInfos"] = [epoch1.scanpos_info, epoch2.scanpos_info]
Expand Down
8 changes: 5 additions & 3 deletions tests/python/test_cloudcompare.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ def test_cloudcompare_m3c2(epochs):
m3c2 = M3C2(
epochs=(epoch1, epoch2),
corepoints=epoch1.cloud,
cyl_radii=(1.6,),
normal_radii=(1.1,),
cyl_radius=1.6,
normal_radii=[
1.1,
],
)

# Instantiate Cloud compare variant
cc_m3c2 = CloudCompareM3C2(
epochs=(epoch1, epoch2),
corepoints=epoch1.cloud,
searchscale=(3.2,),
searchscale=3.2,
normalscale=(2.2,),
)

Expand Down
10 changes: 5 additions & 5 deletions tests/python/test_fallback.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def callback_workingset_finder(self):
pym3c2 = CxxTestM3C2(
epochs=epochs,
corepoints=epochs[0].cloud,
cyl_radii=(3.0,),
cyl_radius=3.0,
normal_radii=(2.0,),
max_distance=6.0,
)
Expand All @@ -54,7 +54,7 @@ def callback_workingset_finder(self):
m3c2 = PythonTestM3C2(
epochs=epochs,
corepoints=epochs[0].cloud,
cyl_radii=(3.0,),
cyl_radius=3.0,
normal_radii=(2.0,),
max_distance=6.0,
)
Expand All @@ -65,12 +65,12 @@ def callback_workingset_finder(self):
def test_python_fallback_m3c2(epochs):
# Instantiate a fallback M3C2 instance
pym3c2 = PythonFallbackM3C2(
epochs=epochs, corepoints=epochs[0].cloud, cyl_radii=(3.0,), normal_radii=(2.0,)
epochs=epochs, corepoints=epochs[0].cloud, cyl_radius=3.0, normal_radii=(2.0,)
)

# And a regular C++ based one
m3c2 = M3C2(
epochs=epochs, corepoints=epochs[0].cloud, cyl_radii=(3.0,), normal_radii=(2.0,)
epochs=epochs, corepoints=epochs[0].cloud, cyl_radius=3.0, normal_radii=(2.0,)
)

compare_algorithms(m3c2, pym3c2)
Expand All @@ -87,7 +87,7 @@ def callback(*args):

# Instantiate it
m3c2 = ExcM3C2(
epochs=epochs, corepoints=epochs[0].cloud, cyl_radii=(3.0,), normal_radii=(2.0,)
epochs=epochs, corepoints=epochs[0].cloud, cyl_radius=3.0, normal_radii=(2.0,)
)

# Running it should throw the proper exception despite taking a detour
Expand Down
15 changes: 7 additions & 8 deletions tests/python/test_m3c2.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@
@pytest.mark.parametrize("robust_aggr", (True, False))
def test_m3c2(epochs, robust_aggr):
epoch1, epoch2 = epochs

# Try with wrong number of epochs
with pytest.raises(Py4DGeoError):
M3C2(epochs=(epoch1,), corepoints=epoch1.cloud, cyl_radii=(1.0,))
M3C2(epochs=(epoch1,), corepoints=epoch1.cloud, cyl_radius=1.0)

# Instantiate an M3C2 instance
m3c2 = M3C2(
epochs=(epoch1, epoch2),
corepoints=epoch1.cloud,
cyl_radii=(3.0,),
cyl_radius=3.0,
normal_radii=(2.0,),
robust_aggr=robust_aggr,
)
Expand All @@ -28,7 +27,7 @@ def test_m3c2(epochs, robust_aggr):
distances, uncertainties = M3C2(
epochs=(epoch1, epoch1),
corepoints=epoch1.cloud,
cyl_radii=(3.0,),
cyl_radius=3.0,
normal_radii=(2.0,),
robust_aggr=robust_aggr,
).run()
Expand All @@ -43,7 +42,7 @@ def test_minimal_m3c2(epochs):
m3c2 = M3C2(
epochs=(epoch1, epoch2),
corepoints=epoch1.cloud,
cyl_radii=(3.0,),
cyl_radius=3.0,
normal_radii=(2.0,),
)

Expand All @@ -57,7 +56,7 @@ def test_registration_error(epochs):
m3c2 = M3C2(
epochs=(epoch1, epoch1),
corepoints=epoch1.cloud,
cyl_radii=(3.0,),
cyl_radius=3.0,
normal_radii=(2.0,),
registration_error=1.0,
)
Expand All @@ -73,7 +72,7 @@ def test_external_normals(epochs):
d, u = M3C2(
epochs=(epoch1, epoch2),
corepoints=epoch1.cloud,
cyl_radii=(3.0,),
cyl_radius=3.0,
normal_radii=(2.0,),
corepoint_normals=np.array([[0, 0, 1]]),
).run()
Expand All @@ -82,7 +81,7 @@ def test_external_normals(epochs):
d, u = M3C2(
epochs=(epoch1, epoch2),
corepoints=epoch1.cloud,
cyl_radii=(3.0,),
cyl_radius=3.0,
normal_radii=(2.0,),
corepoint_normals=np.array([[0, 0, 1], [0, 0, 1]]),
).run()
Expand Down
12 changes: 6 additions & 6 deletions tests/python/test_m3c2ep.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def test_m3c2ep(epochs_m3c2ep, Cxx, tfM, redPoint, scanpos_info):
epochs=(epoch1, epoch2),
corepoints=corepoints,
normal_radii=(0.5, 1.0, 2.0),
cyl_radii=(0.5,),
cyl_radius=0.5,
max_distance=3.0,
Cxx=Cxx,
tfM=tfM,
Expand Down Expand Up @@ -60,7 +60,7 @@ def test_m3c2ep_external_normals(epochs_m3c2ep, Cxx, tfM, redPoint, scanpos_info
epochs=(epoch1, epoch2),
corepoints=corepoints,
corepoint_normals=np.array([[0, 0, 1], [0, 0, 1]]),
cyl_radii=(0.5,),
cyl_radius=0.5,
max_distance=3.0,
Cxx=Cxx,
tfM=tfM,
Expand All @@ -72,7 +72,7 @@ def test_m3c2ep_external_normals(epochs_m3c2ep, Cxx, tfM, redPoint, scanpos_info
epochs=(epoch1, epoch2),
corepoints=corepoints,
normal_radii=(0.5, 1.0, 2.0),
cyl_radii=(0.5,),
cyl_radius=0.5,
max_distance=3.0,
Cxx=Cxx,
tfM=tfM,
Expand All @@ -85,7 +85,7 @@ def test_m3c2ep_external_normals(epochs_m3c2ep, Cxx, tfM, redPoint, scanpos_info
epochs=(epoch1, epoch2),
corepoints=corepoints,
corepoint_normals=corepoint_normals,
cyl_radii=(0.5,),
cyl_radius=0.5,
max_distance=3.0,
Cxx=Cxx,
tfM=tfM,
Expand All @@ -100,7 +100,7 @@ def test_m3c2ep_external_normals(epochs_m3c2ep, Cxx, tfM, redPoint, scanpos_info
epochs=(epoch1, epoch2),
corepoints=corepoints,
corepoint_normals=corepoint_normals,
cyl_radii=(0.5,),
cyl_radius=0.5,
max_distance=3.0,
Cxx=Cxx,
tfM=tfM,
Expand Down Expand Up @@ -153,7 +153,7 @@ def test_m3c2ep_write_las(epochs_m3c2ep, Cxx, tfM, redPoint, scanpos_info):
epochs=(epoch1, epoch2),
corepoints=corepoints,
normal_radii=(0.5, 1.0, 2.0),
cyl_radii=(0.5,),
cyl_radius=0.5,
max_distance=3.0,
Cxx=Cxx,
tfM=tfM,
Expand Down
2 changes: 1 addition & 1 deletion tests/python/test_segmentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def test_construct_from_epochs(epochs, tmp_path):
m3c2 = M3C2(
epochs=(ref_epoch, epoch1),
corepoints=ref_epoch.cloud,
cyl_radii=[2.0],
cyl_radius=2.0,
normal_radii=[2.0],
)

Expand Down

0 comments on commit ee52bb3

Please sign in to comment.