From bea3c6c6933a2ad56f118b424d9769a7bd7fedff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wachiou=20BOURA=C3=8FMA?= <100234404+WassCodeur@users.noreply.github.com> Date: Wed, 10 Jul 2024 08:33:37 +0000 Subject: [PATCH] NF: Add keyword_only decorator to enforce keyword-only arguments (#888) * parent 4baa99d82b57561f41c39cdab9c6d0bbac28415a author WassCodeur 1716302141 +0000 committer WassCodeur 1717549770 +0000 NF: Add keyword_only decorator to enforce keyword-only arguments RF: Refactor keyword-only code and Add keyword-only arguments to functions TEST: Add test for keyword_only" decorator Refactor code to use keyword-only arguments in several functions NF: remove some doctest and add a short comment on line 111 to explain what the loop does in fury/decorators.py RF: Refactor keyword-only code and Add keyword-only arguments to functions Refactor code to use keyword-only arguments in several functions * NF: Add keyword_only decorator to enforce keyword-only arguments * NF: Add keyword_only decorator to enforce keyword-only arguments * RF: Refactor keyword-only code and Add keyword-only arguments to functions * TEST: Add test for keyword_only" decorator * Refactor interactor.py and molecular.py * RF: Rename and update decorator for version checks - Renamed `keyword-only` decorator to `warn_on_args_to_kwargs` for greater clarity. - Updated `warn_on_args_to_kwargs` to include version parameters `from_version` and `until_version`. - Added logic to raise a RuntimeError if the current version of FURY_VERSION is greater than `until_version`. - Moved `__version__` definition to a new `fury/version.py` module to avoid circular import problems. - Updated all functions using the decorator to reflect the new name and parameters. - Adjusted import declarations and ensured compatibility across the code base. * RF: Refactor the code by removing version constraints in the call to the warn_on_args_to_kwargs decorator * RF: Refactor warn_on_args_to_kwargs code and Add warn_on_args_to_kwargs arguments to functions in window.py and actor.py * RF: update the version checks in the decorator: warn_on_args_to_kwargs and update the unittest * RF: warn_on_args_to_kwargs decorator parent 4baa99d82b57561f41c39cdab9c6d0bbac28415a author WassCodeur 1716302141 +0000 committer WassCodeur 1717549770 +0000 NF: Add keyword_only decorator to enforce keyword-only arguments RF: Refactor keyword-only code and Add keyword-only arguments to functions TEST: Add test for keyword_only" decorator Refactor code to use keyword-only arguments in several functions NF: remove some doctest and add a short comment on line 111 to explain what the loop does in fury/decorators.py RF: Refactor keyword-only code and Add keyword-only arguments to functions Refactor code to use keyword-only arguments in several functions NF: Add keyword_only decorator to enforce keyword-only arguments RF: Refactor keyword-only code and Add keyword-only arguments to functions Refactor interactor.py and molecular.py RF: Rename and update decorator for version checks - Renamed `keyword-only` decorator to `warn_on_args_to_kwargs` for greater clarity. - Updated `warn_on_args_to_kwargs` to include version parameters `from_version` and `until_version`. - Added logic to raise a RuntimeError if the current version of FURY_VERSION is greater than `until_version`. - Moved `__version__` definition to a new `fury/version.py` module to avoid circular import problems. - Updated all functions using the decorator to reflect the new name and parameters. - Adjusted import declarations and ensured compatibility across the code base. RF: update the version checks in the decorator: warn_on_args_to_kwargs and update the unittest RF: warn_on_args_to_kwargs decorator --- fury/actor.py | 259 +++++++++++++++++------- fury/actors/odf_slicer.py | 4 +- fury/colormap.py | 28 ++- fury/convert.py | 10 +- fury/decorators.py | 161 +++++++++++++++ fury/gltf.py | 79 +++++--- fury/interactor.py | 12 +- fury/io.py | 45 +++- fury/layout.py | 78 +++++-- fury/material.py | 59 +++++- fury/molecular.py | 80 ++++++-- fury/optpkg.py | 7 +- fury/pick.py | 50 ++++- fury/pkg_info.py | 3 + fury/primitive.py | 42 ++-- fury/shaders/tests/test_base.py | 2 +- fury/testing.py | 23 ++- fury/tests/test_actors.py | 177 ++++++++++------ fury/tests/test_colormap.py | 26 ++- fury/tests/test_decorators.py | 46 ++++- fury/tests/test_deprecator.py | 14 +- fury/tests/test_gltf.py | 14 +- fury/tests/test_interactor.py | 13 +- fury/tests/test_io.py | 79 +++++++- fury/tests/test_layout.py | 28 ++- fury/tests/test_molecular.py | 120 +++++++---- fury/tests/test_primitive.py | 25 ++- fury/tests/test_stream.py | 20 +- fury/tests/test_testing.py | 33 ++- fury/tests/test_thread.py | 2 +- fury/tests/test_transform.py | 8 +- fury/tests/test_utils.py | 47 +++-- fury/tests/test_window.py | 34 ++-- fury/transform.py | 10 +- fury/ui/core.py | 4 +- fury/ui/helpers.py | 17 +- fury/ui/tests/test_containers.py | 50 ++++- fury/ui/tests/test_elements.py | 2 +- fury/ui/tests/test_elements_callback.py | 11 +- fury/ui/tests/test_helpers.py | 14 +- fury/utils.py | 57 ++++-- fury/window.py | 63 ++++-- 42 files changed, 1393 insertions(+), 463 deletions(-) diff --git a/fury/actor.py b/fury/actor.py index 3094ef1121..346373bc96 100644 --- a/fury/actor.py +++ b/fury/actor.py @@ -15,6 +15,7 @@ tensor_ellipsoid, ) from fury.colormap import colormap_lookup_table +from fury.decorators import warn_on_args_to_kwargs from fury.deprecator import deprecate_with_version, deprecated_params from fury.io import load_image from fury.lib import ( @@ -88,8 +89,10 @@ ) +@warn_on_args_to_kwargs() def slicer( data, + *, affine=None, value_range=None, opacity=1.0, @@ -265,7 +268,8 @@ def display_extent(self, x1, x2, y1, y2, z1, z2): # line = np.array([[xmin, ymin, zmin]]) # self.outline_actor = actor.line() - def display(self, x=None, y=None, z=None): + @warn_on_args_to_kwargs() + def display(self, *, x=None, y=None, z=None): if x is None and y is None and z is None: self.display_extent(ex1, ex2, ey1, ey2, ez2 // 2, ez2 // 2) if x is not None: @@ -321,7 +325,12 @@ def shallow_copy(self): lut = lookup_colormap if lookup_colormap is None: # Create a black/white lookup table. - lut = colormap_lookup_table((r1, r2), (0, 0), (0, 0), (0, 1)) + lut = colormap_lookup_table( + scale_range=(r1, r2), + hue_range=(0, 0), + saturation_range=(0, 0), + value_range=(0, 1), + ) plane_colors = ImageMapToColors() plane_colors.SetOutputFormatToRGB() @@ -345,7 +354,8 @@ def shallow_copy(self): return image_actor -def surface(vertices, faces=None, colors=None, smooth=None, subdivision=3): +@warn_on_args_to_kwargs() +def surface(vertices, *, faces=None, colors=None, smooth=None, subdivision=3): """Generate a surface actor from an array of vertices. The color and smoothness of the surface can be customized by specifying @@ -422,7 +432,8 @@ def surface(vertices, faces=None, colors=None, smooth=None, subdivision=3): return surface_actor -def contour_from_roi(data, affine=None, color=None, opacity=1): +@warn_on_args_to_kwargs() +def contour_from_roi(data, *, affine=None, color=None, opacity=1): """Generate surface actor from a binary ROI. The color and opacity of the surface can be customized. @@ -541,7 +552,8 @@ def contour_from_roi(data, affine=None, color=None, opacity=1): return skin_actor -def contour_from_label(data, affine=None, color=None): +@warn_on_args_to_kwargs() +def contour_from_label(data, *, affine=None, color=None): """Generate surface actor from a labeled Array. The color and opacity of individual surfaces can be customized. @@ -586,15 +598,17 @@ def contour_from_label(data, affine=None, color=None): for i, roi_id in enumerate(unique_roi_id): roi_data = np.isin(data, roi_id).astype(int) roi_surface = contour_from_roi( - roi_data, affine, color=color[i], opacity=opacity[i] + roi_data, affine=affine, color=color[i], opacity=opacity[i] ) unique_roi_surfaces.AddPart(roi_surface) return unique_roi_surfaces +@warn_on_args_to_kwargs() def streamtube( lines, + *, colors=None, opacity=1, linewidth=0.1, @@ -662,7 +676,7 @@ def streamtube( >>> scene = window.Scene() >>> lines = [np.random.rand(10, 3), np.random.rand(20, 3)] >>> colors = np.random.rand(2, 3) - >>> c = actor.streamtube(lines, colors) + >>> c = actor.streamtube(lines, colores=colors) >>> scene.add(c) >>> #window.show(scene) @@ -687,7 +701,7 @@ def streamtube( """ # Poly data with lines and colors - poly_data, color_is_scalar = lines_to_vtk_polydata(lines, colors) + poly_data, color_is_scalar = lines_to_vtk_polydata(lines, colors=colors) next_input = poly_data # set primitives count @@ -760,8 +774,10 @@ def streamtube( return actor +@warn_on_args_to_kwargs() def line( lines, + *, colors=None, opacity=1, linewidth=1, @@ -832,13 +848,13 @@ def line( >>> scene = window.Scene() >>> lines = [np.random.rand(10, 3), np.random.rand(20, 3)] >>> colors = np.random.rand(2, 3) - >>> c = actor.line(lines, colors) + >>> c = actor.line(lines, colors=colors) >>> scene.add(c) >>> #window.show(scene) """ # Poly data with lines and colors - poly_data, color_is_scalar = lines_to_vtk_polydata(lines, colors) + poly_data, color_is_scalar = lines_to_vtk_polydata(lines, colors=colors) next_input = poly_data # set primitives count @@ -882,7 +898,8 @@ def line( if depth_cue: - def callback(_caller, _event, calldata=None): + @warn_on_args_to_kwargs() + def callback(_caller, _event, *, calldata=None): program = calldata if program is not None: program.SetUniformf("linewidth", linewidth) @@ -896,7 +913,8 @@ def callback(_caller, _event, calldata=None): return actor -def scalar_bar(lookup_table=None, title=" "): +@warn_on_args_to_kwargs() +def scalar_bar(*, lookup_table=None, title=" "): """Default scalar bar actor for a given colormap (colorbar). Parameters @@ -927,8 +945,14 @@ def scalar_bar(lookup_table=None, title=" "): return scalar_bar +@warn_on_args_to_kwargs() def axes( - scale=(1, 1, 1), colorx=(1, 0, 0), colory=(0, 1, 0), colorz=(0, 0, 1), opacity=1 + *, + scale=(1, 1, 1), + colorx=(1, 0, 0), + colory=(0, 1, 0), + colorz=(0, 0, 1), + opacity=1, ): """Create an actor with the coordinate's system axes where red = x, green = y, blue = z. @@ -956,12 +980,14 @@ def axes( colors = np.array([colorx + (opacity,), colory + (opacity,), colorz + (opacity,)]) scales = np.asarray(scale) - arrow_actor = arrow(centers, dirs, colors, scales, repeat_primitive=False) + arrow_actor = arrow(centers, dirs, colors, scales=scales, repeat_primitive=False) return arrow_actor +@warn_on_args_to_kwargs() def odf_slicer( odfs, + *, affine=None, mask=None, sphere=None, @@ -1032,7 +1058,7 @@ def odf_slicer( if sphere is None: # Use a default sphere with 100 vertices - vertices, faces = fp.prim_sphere("repulsion100") + vertices, faces = fp.prim_sphere(name="repulsion100") else: vertices = sphere.vertices faces = fix_winding_order(vertices, sphere.faces, clockwise=True) @@ -1078,7 +1104,8 @@ def _makeNd(array, ndim): return array.reshape(new_shape) -def _roll_evals(evals, axis=-1): +@warn_on_args_to_kwargs() +def _roll_evals(evals, *, axis=-1): """Check evals shape. Helper function to check that the evals provided to functions calculating @@ -1107,7 +1134,8 @@ def _roll_evals(evals, axis=-1): return evals -def _fa(evals, axis=-1): +@warn_on_args_to_kwargs() +def _fa(evals, *, axis=-1): r"""Return Fractional anisotropy (FA) of a diffusion tensor. Parameters @@ -1133,7 +1161,7 @@ def _fa(evals, axis=-1): \lambda_2^2+\lambda_3^2}} """ - evals = _roll_evals(evals, axis) + evals = _roll_evals(evals, axis=axis) # Make sure not to get nans all_zero = (evals == 0).all(axis=0) ev1, ev2, ev3 = evals @@ -1178,9 +1206,11 @@ def _color_fa(fa, evecs): return np.abs(evecs[..., 0]) * np.clip(fa, 0, 1)[..., None] +@warn_on_args_to_kwargs() def tensor_slicer( evals, evecs, + *, affine=None, mask=None, sphere=None, @@ -1256,7 +1286,8 @@ def display_extent(self, x1, x2, y1, y2, z1, z2): ) self.SetMapper(self.mapper) - def display(self, x=None, y=None, z=None): + @warn_on_args_to_kwargs() + def display(self, *, x=None, y=None, z=None): if x is None and y is None and z is None: self.display_extent( 0, @@ -1283,9 +1314,11 @@ def display(self, x=None, y=None, z=None): return tensor_actor +@warn_on_args_to_kwargs() def _tensor_slicer_mapper( evals, evecs, + *, affine=None, mask=None, sphere=None, @@ -1389,8 +1422,10 @@ def _tensor_slicer_mapper( return mapper +@warn_on_args_to_kwargs() def peak_slicer( peaks_dirs, + *, peaks_values=None, mask=None, affine=None, @@ -1510,7 +1545,8 @@ def display_extent(self, x1, x2, y1, y2, z1, z2): self.SetProperty(self.line.GetProperty()) self.SetMapper(self.line.GetMapper()) - def display(self, x=None, y=None, z=None): + @warn_on_args_to_kwargs() + def display(self, *, x=None, y=None, z=None): if x is None and y is None and z is None: self.display_extent( 0, @@ -1537,8 +1573,10 @@ def display(self, x=None, y=None, z=None): return peak_actor +@warn_on_args_to_kwargs() def peak( peaks_dirs, + *, peaks_values=None, mask=None, affine=None, @@ -1652,7 +1690,8 @@ def peak( ) -def dot(points, colors=None, opacity=None, dot_size=5): +@warn_on_args_to_kwargs() +def dot(points, *, colors=None, opacity=None, dot_size=5): """Create one or more 3d points. Parameters @@ -1699,7 +1738,7 @@ def dot(points, colors=None, opacity=None, dot_size=5): vtk_faces.InsertNextCell(1) vtk_faces.InsertCellPoint(idd) - color_tuple = color_check(len(points), colors) + color_tuple = color_check(len(points), colors=colors) color_array, global_opacity = color_tuple # Create a polydata object @@ -1734,7 +1773,8 @@ def dot(points, colors=None, opacity=None, dot_size=5): )(dot) -def point(points, colors, point_radius=0.1, phi=8, theta=8, opacity=1.0): +@warn_on_args_to_kwargs() +def point(points, colors, *, point_radius=0.1, phi=8, theta=8, opacity=1.0): """Visualize points as sphere glyphs. Parameters @@ -1778,9 +1818,11 @@ def point(points, colors, point_radius=0.1, phi=8, theta=8, opacity=1.0): ) +@warn_on_args_to_kwargs() def sphere( centers, colors, + *, radii=1.0, phi=16, theta=16, @@ -1863,16 +1905,18 @@ def sphere( big_verts, big_faces, big_colors, _ = res prim_count = len(centers) sphere_actor = get_actor_from_primitive( - big_verts, big_faces, big_colors, prim_count=prim_count + big_verts, big_faces, colors=big_colors, prim_count=prim_count ) sphere_actor.GetProperty().SetOpacity(opacity) return sphere_actor +@warn_on_args_to_kwargs() def cylinder( centers, directions, colors, + *, radius=0.05, heights=1, capped=False, @@ -1948,7 +1992,7 @@ def cylinder( big_verts, big_faces, big_colors, _ = res prim_count = len(centers) cylinder_actor = get_actor_from_primitive( - big_verts, big_faces, big_colors, prim_count=prim_count + big_verts, big_faces, colors=big_colors, prim_count=prim_count ) else: @@ -1976,10 +2020,12 @@ def cylinder( return cylinder_actor +@warn_on_args_to_kwargs() def disk( centers, directions, colors, + *, rinner=0.3, router=0.7, cresolution=6, @@ -2053,7 +2099,8 @@ def disk( return disk_actor -def square(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): +@warn_on_args_to_kwargs() +def square(centers, *, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): """Visualize one or many squares with different features. Parameters @@ -2077,7 +2124,7 @@ def square(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): >>> scene = window.Scene() >>> centers = np.random.rand(5, 3) >>> dirs = np.random.rand(5, 3) - >>> sq_actor = actor.square(centers, dirs) + >>> sq_actor = actor.square(centers, directions=dirs) >>> scene.add(sq_actor) >>> # window.show(scene) @@ -2095,13 +2142,14 @@ def square(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): big_verts, big_faces, big_colors, _ = res prim_count = len(centers) sq_actor = get_actor_from_primitive( - big_verts, big_faces, big_colors, prim_count=prim_count + big_verts, big_faces, colors=big_colors, prim_count=prim_count ) sq_actor.GetProperty().BackfaceCullingOff() return sq_actor -def rectangle(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=(1, 2, 0)): +@warn_on_args_to_kwargs() +def rectangle(centers, *, directions=(1, 0, 0), colors=(1, 0, 0), scales=(1, 2, 0)): """Visualize one or many rectangles with different features. Parameters @@ -2129,7 +2177,7 @@ def rectangle(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=(1, 2, 0)) >>> scene = window.Scene() >>> centers = np.random.rand(5, 3) >>> dirs = np.random.rand(5, 3) - >>> rect_actor = actor.rectangle(centers, dirs) + >>> rect_actor = actor.rectangle(centers, directions=dirs) >>> scene.add(rect_actor) >>> # window.show(scene) @@ -2137,8 +2185,9 @@ def rectangle(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=(1, 2, 0)) return square(centers=centers, directions=directions, colors=colors, scales=scales) +@warn_on_args_to_kwargs() @deprecated_params(["size", "heights"], ["scales", "scales"], since="0.6", until="0.8") -def box(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=(1, 2, 3)): +def box(centers, *, directions=(1, 0, 0), colors=(1, 0, 0), scales=(1, 2, 3)): """Visualize one or many boxes with different features. Parameters @@ -2162,7 +2211,7 @@ def box(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=(1, 2, 3)): >>> scene = window.Scene() >>> centers = np.random.rand(5, 3) >>> dirs = np.random.rand(5, 3) - >>> box_actor = actor.box(centers, dirs, (1, 1, 1)) + >>> box_actor = actor.box(centers, directions=dirs, colors=(1, 1, 1)) >>> scene.add(box_actor) >>> # window.show(scene) @@ -2180,13 +2229,14 @@ def box(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=(1, 2, 3)): big_verts, big_faces, big_colors, _ = res prim_count = len(centers) box_actor = get_actor_from_primitive( - big_verts, big_faces, big_colors, prim_count=prim_count + big_verts, big_faces, colors=big_colors, prim_count=prim_count ) return box_actor +@warn_on_args_to_kwargs() @deprecated_params("heights", "scales", since="0.6", until="0.8") -def cube(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): +def cube(centers, *, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): """Visualize one or many cubes with different features. Parameters @@ -2210,7 +2260,7 @@ def cube(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): >>> scene = window.Scene() >>> centers = np.random.rand(5, 3) >>> dirs = np.random.rand(5, 3) - >>> cube_actor = actor.cube(centers, dirs) + >>> cube_actor = actor.cube(centers, directions=dirs) >>> scene.add(cube_actor) >>> # window.show(scene) @@ -2218,10 +2268,12 @@ def cube(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): return box(centers=centers, directions=directions, colors=colors, scales=scales) +@warn_on_args_to_kwargs() def arrow( centers, directions, colors, + *, heights=1.0, resolution=10, tip_length=0.35, @@ -2270,7 +2322,7 @@ def arrow( >>> centers = np.random.rand(5, 3) >>> directions = np.random.rand(5, 3) >>> heights = np.random.rand(5) - >>> arrow_actor = actor.arrow(centers, directions, (1, 1, 1), heights) + >>> arrow_actor = actor.arrow(centers, directions, (1, 1, 1), heights=heights) >>> scene.add(arrow_actor) >>> # window.show(scene) @@ -2288,7 +2340,7 @@ def arrow( big_vertices, big_faces, big_colors, _ = res prim_count = len(centers) arrow_actor = get_actor_from_primitive( - big_vertices, big_faces, big_colors, prim_count=prim_count + big_vertices, big_faces, colors=big_colors, prim_count=prim_count ) return arrow_actor @@ -2313,10 +2365,12 @@ def arrow( return arrow_actor +@warn_on_args_to_kwargs() def cone( centers, directions, colors, + *, heights=1.0, resolution=10, vertices=None, @@ -2357,7 +2411,7 @@ def cone( >>> centers = np.random.rand(5, 3) >>> directions = np.random.rand(5, 3) >>> heights = np.random.rand(5) - >>> cone_actor = actor.cone(centers, directions, (1, 1, 1), heights) + >>> cone_actor = actor.cone(centers, directions, (1, 1, 1), heights=heights) >>> scene.add(cone_actor) >>> # window.show(scene) @@ -2389,13 +2443,14 @@ def cone( big_verts, big_faces, big_colors, _ = res prim_count = len(centers) cone_actor = get_actor_from_primitive( - big_verts, big_faces, big_colors, prim_count=prim_count + big_verts, big_faces, colors=big_colors, prim_count=prim_count ) return cone_actor -def triangularprism(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): +@warn_on_args_to_kwargs() +def triangularprism(centers, *, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): """Visualize one or many regular triangular prisms with different features. Parameters @@ -2421,11 +2476,11 @@ def triangularprism(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): >>> dirs = np.random.rand(3, 3) >>> colors = np.random.rand(3, 3) >>> scales = np.random.rand(3, 1) - >>> actor = actor.triangularprism(centers, dirs, colors, scales) + >>> actor = actor.triangularprism(centers, directions=dirs, colors=colors, scales=scales) >>> scene.add(actor) >>> # window.show(scene) - """ + """ # noqa: E501 verts, faces = fp.prim_triangularprism() res = fp.repeat_primitive( verts, @@ -2438,12 +2493,13 @@ def triangularprism(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): big_verts, big_faces, big_colors, _ = res prim_count = len(centers) tprism_actor = get_actor_from_primitive( - big_verts, big_faces, big_colors, prim_count=prim_count + big_verts, big_faces, colors=big_colors, prim_count=prim_count ) return tprism_actor -def rhombicuboctahedron(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): +@warn_on_args_to_kwargs() +def rhombicuboctahedron(centers, *, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): """Visualize one or many rhombicuboctahedron with different features. Parameters @@ -2469,11 +2525,11 @@ def rhombicuboctahedron(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales= >>> dirs = np.random.rand(3, 3) >>> colors = np.random.rand(3, 3) >>> scales = np.random.rand(3, 1) - >>> actor = actor.rhombicuboctahedron(centers, dirs, colors, scales) + >>> actor = actor.rhombicuboctahedron(centers, directions=dirs, colors=colors, scales=scales) >>> scene.add(actor) >>> # window.show(scene) - """ + """ # noqa: E501 verts, faces = fp.prim_rhombicuboctahedron() res = fp.repeat_primitive( verts, @@ -2486,12 +2542,13 @@ def rhombicuboctahedron(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales= big_verts, big_faces, big_colors, _ = res prim_count = len(centers) rcoh_actor = get_actor_from_primitive( - big_verts, big_faces, big_colors, prim_count=prim_count + big_verts, big_faces, colors=big_colors, prim_count=prim_count ) return rcoh_actor -def pentagonalprism(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): +@warn_on_args_to_kwargs() +def pentagonalprism(centers, *, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): """Visualize one or many pentagonal prisms with different features. Parameters @@ -2518,11 +2575,11 @@ def pentagonalprism(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): >>> dirs = np.random.rand(3, 3) >>> colors = np.random.rand(3, 3) >>> scales = np.random.rand(3, 1) - >>> actor_pentagonal = actor.pentagonalprism(centers, dirs, colors, scales) + >>> actor_pentagonal = actor.pentagonalprism(centers, directions=dirs, colors=colors, scales=scales) >>> scene.add(actor_pentagonal) >>> # window.show(scene) - """ + """ # noqa: E501 verts, faces = fp.prim_pentagonalprism() res = fp.repeat_primitive( verts, @@ -2536,12 +2593,13 @@ def pentagonalprism(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): big_verts, big_faces, big_colors, _ = res prim_count = len(centers) pent_actor = get_actor_from_primitive( - big_verts, big_faces, big_colors, prim_count=prim_count + big_verts, big_faces, colors=big_colors, prim_count=prim_count ) return pent_actor -def octagonalprism(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): +@warn_on_args_to_kwargs() +def octagonalprism(centers, *, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): """Visualize one or many octagonal prisms with different features. Parameters @@ -2567,11 +2625,11 @@ def octagonalprism(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): >>> dirs = np.random.rand(3, 3) >>> colors = np.random.rand(3, 3) >>> scales = np.random.rand(3, 1) - >>> actor = actor.octagonalprism(centers, dirs, colors, scales) + >>> actor = actor.octagonalprism(centers, directions=dirs, colors=colors, scales=scales) >>> scene.add(actor) >>> # window.show(scene) - """ + """ # noqa: E501 verts, faces = fp.prim_octagonalprism() res = fp.repeat_primitive( verts, @@ -2585,12 +2643,13 @@ def octagonalprism(centers, directions=(1, 0, 0), colors=(1, 0, 0), scales=1): big_verts, big_faces, big_colors, _ = res prim_count = len(centers) oct_actor = get_actor_from_primitive( - big_verts, big_faces, big_colors, prim_count=prim_count + big_verts, big_faces, colors=big_colors, prim_count=prim_count ) return oct_actor -def frustum(centers, directions=(1, 0, 0), colors=(0, 1, 0), scales=1): +@warn_on_args_to_kwargs() +def frustum(centers, *, directions=(1, 0, 0), colors=(0, 1, 0), scales=1): """Visualize one or many frustum pyramids with different features. Parameters @@ -2616,7 +2675,7 @@ def frustum(centers, directions=(1, 0, 0), colors=(0, 1, 0), scales=1): >>> dirs = np.random.rand(4, 3) >>> colors = np.random.rand(4, 3) >>> scales = np.random.rand(4, 1) - >>> actor = actor.frustum(centers, dirs, colors, scales) + >>> actor = actor.frustum(centers, directions=dirs, colors=colors, scales=scales) >>> scene.add(actor) >>> # window.show(scene) @@ -2634,13 +2693,14 @@ def frustum(centers, directions=(1, 0, 0), colors=(0, 1, 0), scales=1): big_verts, big_faces, big_colors, _ = res prim_count = len(centers) frustum_actor = get_actor_from_primitive( - big_verts, big_faces, big_colors, prim_count=prim_count + big_verts, big_faces, colors=big_colors, prim_count=prim_count ) return frustum_actor +@warn_on_args_to_kwargs() def superquadric( - centers, roundness=(1, 1), directions=(1, 0, 0), colors=(1, 0, 0), scales=1 + centers, *, roundness=(1, 1), directions=(1, 0, 0), colors=(1, 0, 0), scales=1 ): """Visualize one or many superquadrics with different features. @@ -2705,13 +2765,15 @@ def have_2_dimensions(arr): big_verts, big_faces, big_colors, _ = res prim_count = len(centers) spq_actor = get_actor_from_primitive( - big_verts, big_faces, big_colors, prim_count=prim_count + big_verts, big_faces, colors=big_colors, prim_count=prim_count ) return spq_actor +@warn_on_args_to_kwargs() def billboard( centers, + *, colors=(0, 1, 0), scales=1, vs_dec=None, @@ -2766,7 +2828,7 @@ def billboard( prim_count = len(centers) bb_actor = get_actor_from_primitive( - big_verts, big_faces, big_colors, prim_count=prim_count + big_verts, big_faces, colors=big_colors, prim_count=prim_count ) bb_actor.GetMapper().SetVBOShiftScaleMethod(False) bb_actor.GetProperty().BackfaceCullingOff() @@ -2859,7 +2921,9 @@ def billboard( return bb_actor +@warn_on_args_to_kwargs() def vector_text( + *, text="Origin", pos=(0, 0, 0), scale=(0.2, 0.2, 0.2), @@ -2965,8 +3029,10 @@ def add_to_scene(scene): )(vector_text) +@warn_on_args_to_kwargs() def text_3d( text, + *, position=(0, 0, 0), color=(1, 1, 1), font_size=12, @@ -3014,7 +3080,8 @@ def font_size(self, size): self.GetTextProperty().SetFontSize(24) text_actor.SetScale((1.0 / 24.0 * size,) * 3) - def font_family(self, _family="Arial"): + @warn_on_args_to_kwargs() + def font_family(self, *, _family="Arial"): self.GetTextProperty().SetFontFamilyToArial() def justification(self, justification): @@ -3041,7 +3108,8 @@ def vertical_justification(self, justification): "Unknown vertical justification: '{}'".format(justification) ) - def font_style(self, bold=False, italic=False, shadow=False): + @warn_on_args_to_kwargs() + def font_style(self, *, bold=False, italic=False, shadow=False): tprop = self.GetTextProperty() if bold: tprop.BoldOn() @@ -3069,8 +3137,8 @@ def get_position(self): text_actor.message(text) text_actor.font_size(font_size) text_actor.set_position(position) - text_actor.font_family(font_family) - text_actor.font_style(bold, italic, shadow) + text_actor.font_family(_family=font_family) + text_actor.font_style(bold=bold, italic=italic, shadow=shadow) text_actor.color(color) text_actor.justification(justification) text_actor.vertical_justification(vertical_justification) @@ -3096,7 +3164,8 @@ class Container: """ - def __init__(self, layout=None): + @warn_on_args_to_kwargs() + def __init__(self, *, layout=None): """Parameters ---------- layout : ``fury.layout.Layout`` object @@ -3229,8 +3298,10 @@ def __len__(self): return len(self._items) +@warn_on_args_to_kwargs() def grid( actors, + *, captions=None, caption_offset=(0, -100, 0), cell_padding=0, @@ -3311,7 +3382,8 @@ def grid( return grid -def figure(pic, interpolation="nearest"): +@warn_on_args_to_kwargs() +def figure(pic, *, interpolation="nearest"): """Return a figure as an image actor. Parameters @@ -3357,7 +3429,8 @@ def figure(pic, interpolation="nearest"): return image_actor -def texture(rgb, interp=True): +@warn_on_args_to_kwargs() +def texture(rgb, *, interp=True): """Map an RGB or RGBA texture on a plane. Parameters @@ -3436,7 +3509,8 @@ def texture_update(texture_actor, arr): grid.GetPointData().SetScalars(vtkarr) -def _textured_sphere_source(theta=60, phi=60): +@warn_on_args_to_kwargs() +def _textured_sphere_source(*, theta=60, phi=60): """Use vtkTexturedSphereSource to set the theta and phi. Parameters @@ -3458,7 +3532,8 @@ def _textured_sphere_source(theta=60, phi=60): return tss -def texture_on_sphere(rgb, theta=60, phi=60, interpolate=True): +@warn_on_args_to_kwargs() +def texture_on_sphere(rgb, *, theta=60, phi=60, interpolate=True): """Map an RGB or RGBA texture on a sphere. Parameters @@ -3494,7 +3569,8 @@ def texture_on_sphere(rgb, theta=60, phi=60, interpolate=True): return earthActor -def texture_2d(rgb, interp=False): +@warn_on_args_to_kwargs() +def texture_2d(rgb, *, interp=False): """Create 2D texture from array. Parameters @@ -3560,7 +3636,10 @@ def texture_2d(rgb, interp=False): return act -def sdf(centers, directions=(1, 0, 0), colors=(1, 0, 0), primitives="torus", scales=1): +@warn_on_args_to_kwargs() +def sdf( + centers, *, directions=(1, 0, 0), colors=(1, 0, 0), primitives="torus", scales=1 +): """Create a SDF primitive based actor. Parameters @@ -3597,7 +3676,7 @@ def sdf(centers, directions=(1, 0, 0), colors=(1, 0, 0), primitives="torus", sca rep_verts, rep_faces, rep_colors, rep_centers = repeated prim_count = len(centers) box_actor = get_actor_from_primitive( - rep_verts, rep_faces, rep_colors, prim_count=prim_count + rep_verts, rep_faces, colors=rep_colors, prim_count=prim_count ) box_actor.GetMapper().SetVBOShiftScaleMethod(False) @@ -3641,8 +3720,10 @@ def sdf(centers, directions=(1, 0, 0), colors=(1, 0, 0), primitives="torus", sca return box_actor +@warn_on_args_to_kwargs() def markers( centers, + *, colors=(0, 1, 0), scales=1, marker="3d", @@ -3707,7 +3788,7 @@ def markers( big_verts, big_faces, big_colors, big_centers = res prim_count = len(centers) sq_actor = get_actor_from_primitive( - big_verts, big_faces, big_colors, prim_count=prim_count + big_verts, big_faces, colors=big_colors, prim_count=prim_count ) sq_actor.GetMapper().SetVBOShiftScaleMethod(False) sq_actor.GetProperty().BackfaceCullingOff() @@ -3780,7 +3861,12 @@ def markers( attribute_to_actor(sq_actor, list_of_markers, "marker") def callback( - _caller, _event, calldata=None, uniform_type="f", uniform_name=None, value=None + _caller, + _event, + calldata=None, + uniform_type="f", + uniform_name=None, + value=None, ): program = calldata if program is not None: @@ -3819,7 +3905,16 @@ def callback( return sq_actor -def ellipsoid(centers, axes, lengths, colors=(1, 0, 0), scales=1.0, opacity=1.0): +@warn_on_args_to_kwargs() +def ellipsoid( + centers, + axes, + lengths, + *, + colors=(1, 0, 0), + scales=1.0, + opacity=1.0, +): """VTK actor for visualizing ellipsoids. Parameters @@ -3884,7 +3979,17 @@ def ellipsoid(centers, axes, lengths, colors=(1, 0, 0), scales=1.0, opacity=1.0) return tensor_ellipsoid(centers, axes, lengths, colors, scales, opacity) -def uncertainty_cone(evals, evecs, signal, sigma, b_matrix, scales=0.6, opacity=1.0): +@warn_on_args_to_kwargs() +def uncertainty_cone( + evals, + evecs, + signal, + sigma, + b_matrix, + *, + scales=0.6, + opacity=1.0, +): """VTK actor for visualizing the cone of uncertainty representing the variance of the main direction of diffusion. diff --git a/fury/actors/odf_slicer.py b/fury/actors/odf_slicer.py index 8b75d200ab..fefbd5abea 100644 --- a/fury/actors/odf_slicer.py +++ b/fury/actors/odf_slicer.py @@ -254,14 +254,14 @@ def _generate_color_for_vertices(self, sf): if self.colormap is None: raise IOError("if global_cm=True, colormap must be defined.") else: - all_colors = create_colormap(sf.ravel(), self.colormap) * 255 + all_colors = create_colormap(sf.ravel(), name=self.colormap) * 255 elif self.colormap is not None: if isinstance(self.colormap, str): # Map ODFs values [min, max] to [0, 1] for each ODF range_sf = sf.max(axis=-1) - sf.min(axis=-1) rescaled = sf - sf.min(axis=-1, keepdims=True) rescaled[range_sf > 0] /= range_sf[range_sf > 0][..., None] - all_colors = create_colormap(rescaled.ravel(), self.colormap) * 255 + all_colors = create_colormap(rescaled.ravel(), name=self.colormap) * 255 else: all_colors = np.tile( np.array(self.colormap).reshape(1, 3), diff --git a/fury/colormap.py b/fury/colormap.py index 4d9a5c0b1b..10659bc992 100644 --- a/fury/colormap.py +++ b/fury/colormap.py @@ -6,6 +6,7 @@ from scipy import linalg from fury.data import DATA_DIR +from fury.decorators import warn_on_args_to_kwargs from fury.lib import LookupTable # Allow import, but disable doctests if we don't have matplotlib @@ -14,7 +15,9 @@ cm, have_matplotlib, _ = optional_package("matplotlib.cm") +@warn_on_args_to_kwargs() def colormap_lookup_table( + *, scale_range=(0, 1), hue_range=(0.8, 0), saturation_range=(1, 1), @@ -242,7 +245,8 @@ def orient2rgb(v): return orient -def line_colors(streamlines, cmap="rgb_standard"): +@warn_on_args_to_kwargs() +def line_colors(streamlines, *, cmap="rgb_standard"): """Create colors for streamlines to be used in actor.line. Parameters @@ -308,7 +312,8 @@ def simple_cmap(v): return simple_cmap -def create_colormap(v, name="plasma", auto=True): +@warn_on_args_to_kwargs() +def create_colormap(v, *, name="plasma", auto=True): """Create colors from a specific colormap and return it as an array of shape (N,3) where every row gives the corresponding r,g,b value. The colormaps we use are similar with those of matplotlib. @@ -511,7 +516,8 @@ def _lab2rgb(lab): return _xyz2rgb(tmp) -def distinguishable_colormap(bg=(0, 0, 0), exclude=None, nb_colors=None): +@warn_on_args_to_kwargs() +def distinguishable_colormap(*, bg=(0, 0, 0), exclude=None, nb_colors=None): """Generate colors that are maximally perceptually distinct. This function generates a set of colors which are distinguishable @@ -903,7 +909,8 @@ def get_xyz_coords(illuminant, observer): ) from err -def xyz2lab(xyz, illuminant="D65", observer="2"): +@warn_on_args_to_kwargs() +def xyz2lab(xyz, *, illuminant="D65", observer="2"): """XYZ to CIE-LAB color space conversion. Parameters @@ -950,7 +957,8 @@ def xyz2lab(xyz, illuminant="D65", observer="2"): return np.concatenate([x[..., np.newaxis] for x in [L, a, b]], axis=-1) -def lab2xyz(lab, illuminant="D65", observer="2"): +@warn_on_args_to_kwargs() +def lab2xyz(lab, *, illuminant="D65", observer="2"): """CIE-LAB to XYZcolor space conversion. Parameters @@ -1001,7 +1009,8 @@ def lab2xyz(lab, illuminant="D65", observer="2"): return out -def rgb2lab(rgb, illuminant="D65", observer="2"): +@warn_on_args_to_kwargs() +def rgb2lab(rgb, *, illuminant="D65", observer="2"): """Conversion from the sRGB color space (IEC 61966-2-1:1999) to the CIE Lab colorspace under the given illuminant and observer. @@ -1028,10 +1037,11 @@ def rgb2lab(rgb, illuminant="D65", observer="2"): This implementation might have been modified. """ - return xyz2lab(rgb2xyz(rgb), illuminant, observer) + return xyz2lab(rgb2xyz(rgb), illuminant=illuminant, observer=observer) -def lab2rgb(lab, illuminant="D65", observer="2"): +@warn_on_args_to_kwargs() +def lab2rgb(lab, *, illuminant="D65", observer="2"): """Lab to RGB color space conversion. Parameters @@ -1057,4 +1067,4 @@ def lab2rgb(lab, illuminant="D65", observer="2"): This implementation might have been modified. """ - return xyz2rgb(lab2xyz(lab, illuminant, observer)) + return xyz2rgb(lab2xyz(lab, illuminant=illuminant, observer=observer)) diff --git a/fury/convert.py b/fury/convert.py index 25ad4d1a8b..3945375d73 100644 --- a/fury/convert.py +++ b/fury/convert.py @@ -3,11 +3,13 @@ import numpy as np +from fury.decorators import warn_on_args_to_kwargs from fury.io import load_image +@warn_on_args_to_kwargs() def matplotlib_figure_to_numpy( - fig, dpi=100, fname=None, flip_up_down=True, transparent=False + fig, *, dpi=100, fname=None, flip_up_down=True, transparent=False ): """Convert a Matplotlib figure to a 3D numpy array with RGBA channels. @@ -54,7 +56,11 @@ def matplotlib_figure_to_numpy( arr = load_image(fname) else: fig.savefig( - fname, dpi=dpi, transparent=transparent, bbox_inches="tight", pad_inches=0 + fname, + dpi=dpi, + transparent=transparent, + bbox_inches="tight", + pad_inches=0, ) arr = load_image(fname) diff --git a/fury/decorators.py b/fury/decorators.py index 4cb1ee2cff..6ff1d3e19c 100644 --- a/fury/decorators.py +++ b/fury/decorators.py @@ -1,8 +1,15 @@ """Decorators for FURY tests.""" +from functools import wraps +from inspect import signature import platform import re import sys +from warnings import warn + +from packaging import version + +import fury skip_linux = is_linux = platform.system().lower() == "linux" skip_osx = is_osx = platform.system().lower() == "darwin" @@ -43,3 +50,157 @@ def doctest_skip_parser(func): new_lines.append(code) func.__doc__ = "\n".join(new_lines) return func + + +def warn_on_args_to_kwargs( + from_version="0.1.0", + until_version="0.11.0", +): + """Decorator to enforce keyword-only arguments. + + This decorator enforces that all arguments after the first one are + keyword-only arguments. It also checks that all keyword arguments are + expected by the function. + + Parameters + ---------- + from_version: str, optional + The version of fury from which the function was supported. + until_version: str, optional + The version of fury until which the function was supported. + + Returns + ------- + decorator: Callable + Decorator function. + + Examples + -------- + >>> from fury.decorators import warn_on_args_to_kwargs + >>> import fury + >>> @warn_on_args_to_kwargs() + ... def f(a, b, *, c, d=1, e=1): + ... return a + b + c + d + e + >>> CURRENT_VERSION = fury.__version__ + >>> fury.__version__ = "0.11.0" + >>> f(1, 2, 3, 4, 5) + 15 + >>> f(1, 2, c=3, d=4, e=5) + 15 + >>> f(1, 2, 2, 4, e=5) + 14 + >>> f(1, 2, c=3, d=4) + 11 + >>> f(1, 2, d=3, e=5) + Traceback (most recent call last): + ... + TypeError: f() missing 1 required keyword-only argument: 'c' + >>> fury.__version__ = "0.12.0" + >>> f(1, 2, 3, 4, e=5) + Traceback (most recent call last): + ... + TypeError: f() takes 2 positional arguments but 4 positional arguments (and 1 keyword-only argument) were given + >>> fury.__version__ = CURRENT_VERSION + """ # noqa: E501 + + def decorator(func): + """Decorator function. This function enforces that all arguments after + the first one are keyword-only arguments. It also checks that all + keyword arguments are expected by the function. + + Parameters + ---------- + func: function + Function to be decorated. + + Returns + ------- + wrapper: Callable + Decorated function. + """ + + @wraps(func) + def wrapper(*args, **kwargs): + sig = signature(func) + params = sig.parameters + # + KEYWORD_ONLY_ARGS = [ + arg.name for arg in params.values() if arg.kind == arg.KEYWORD_ONLY + ] + POSITIONAL_ARGS = [ + arg.name + for arg in params.values() + if arg.kind in (arg.POSITIONAL_OR_KEYWORD, arg.POSITIONAL_ONLY) + ] + + # Keyword-only arguments that do not have default values and not in kwargs + missing_kwargs = [ + arg + for arg in KEYWORD_ONLY_ARGS + if arg not in kwargs and params[arg].default == params[arg].empty + ] + + # Keyword-only arguments that have default values + ARG_DEFAULT = [ + arg + for arg in KEYWORD_ONLY_ARGS + if arg not in kwargs and params[arg].default != params[arg].empty + ] + func_params_sample = [] + + # Create a sample of the function parameters + for arg in params.values(): + if arg.kind in (arg.POSITIONAL_OR_KEYWORD, arg.POSITIONAL_ONLY): + func_params_sample.append(f"{arg.name}_value") + elif arg.kind == arg.KEYWORD_ONLY: + func_params_sample.append(f"{arg.name}='value'") + func_params_sample = ", ".join(func_params_sample) + args_kwargs_len = len(args) + len(kwargs) + params_len = len(params) + try: + return func(*args, **kwargs) + except TypeError as e: + FURY_CURRENT_VERSION = fury.__version__ + + if ARG_DEFAULT: + missing_kwargs += ARG_DEFAULT + if missing_kwargs and params_len >= args_kwargs_len: + # if the version of fury is greater than until_version, + # an error should be displayed, + if version.parse(FURY_CURRENT_VERSION) > version.parse( + until_version + ): + raise TypeError(e) from e + + positional_args_len = len(POSITIONAL_ARGS) + args_k = list(args[positional_args_len:]) + args = list(args[:positional_args_len]) + kwargs.update(dict(zip(missing_kwargs, args_k))) + result = func(*args, **kwargs) + + # if from_version is less or equal to fury.__version__ and, + # less or equal to until_version + # a warning should be displayed. + if ( + version.parse(from_version) + <= version.parse(FURY_CURRENT_VERSION) + <= version.parse(until_version) + ): + warn( + f"We'll no longer accept the way you call the " + f"{func.__name__} function in future versions of FURY.\n\n" + "Here's how to call the Function {}: {}({})\n".format( + func.__name__, func.__name__, func_params_sample + ), + UserWarning, + stacklevel=3, + ) + + # if the current version of fury is less than from_version, + # the function should be called without any changes. + + return result + + return wrapper + + return decorator diff --git a/fury/gltf.py b/fury/gltf.py index 5b02ff68d1..962515ab92 100644 --- a/fury/gltf.py +++ b/fury/gltf.py @@ -17,6 +17,7 @@ step_interpolator, tan_cubic_spline_interpolator, ) +from fury.decorators import warn_on_args_to_kwargs from fury.lib import Camera, Matrix4x4, Texture, Transform, numpy_support comp_type = { @@ -32,7 +33,8 @@ class glTF: - def __init__(self, filename, apply_normals=False): + @warn_on_args_to_kwargs() + def __init__(self, filename, *, apply_normals=False): """Read and generate actors from glTF files. Parameters @@ -87,7 +89,7 @@ def __init__(self, filename, apply_normals=False): self.morph_vertices = [] self.morph_weights = [] - self.inspect_scene(0) + self.inspect_scene(scene_id=0) self._actors = [] self._bactors = {} @@ -121,7 +123,8 @@ def actors(self): return self._actors - def inspect_scene(self, scene_id=0): + @warn_on_args_to_kwargs() + def inspect_scene(self, *, scene_id=0): """Loop over nodes in a scene. Parameters @@ -138,7 +141,8 @@ def inspect_scene(self, scene_id=0): for i, animation in enumerate(self.gltf.animations): self.transverse_channels(animation, i) - def transverse_node(self, nextnode_id, matrix, parent=None, is_joint=False): + @warn_on_args_to_kwargs() + def transverse_node(self, nextnode_id, matrix, *, parent=None, is_joint=False): """Load mesh and generates transformation matrix. Parameters @@ -204,7 +208,9 @@ def transverse_node(self, nextnode_id, matrix, parent=None, is_joint=False): for bone, ibm in zip(joints, ibms): self.bones.append(bone) self.ibms[bone] = ibm - self.transverse_node(joints[0], np.identity(4), parent, is_joint=True) + self.transverse_node( + joints[0], np.identity(4), parent=parent, is_joint=True + ) if node.camera is not None: camera_id = node.camera @@ -212,7 +218,12 @@ def transverse_node(self, nextnode_id, matrix, parent=None, is_joint=False): if node.children: for child_id in node.children: - self.transverse_node(child_id, next_matrix, parent, is_joint) + self.transverse_node( + child_id, + next_matrix, + parent=parent, + is_joint=is_joint, + ) def load_mesh(self, mesh_id, transform_mat, parent): """Load the mesh data from accessor and applies the transformation. @@ -645,12 +656,14 @@ def generate_tmatrix(self, transf, prop): matrix = transf return matrix + @warn_on_args_to_kwargs() def transverse_animations( self, animation, bone_id, timestamp, joint_matrices, + *, parent_bone_deform=None, ): """Calculate skinning matrix (Joint Matrices) and transform bone for @@ -696,7 +709,11 @@ def transverse_animations( c_bones = node.children for c_anim, c_bone in zip(c_animations, c_bones): self.transverse_animations( - c_anim, c_bone, timestamp, joint_matrices, new_deform + c_anim, + c_bone, + timestamp, + joint_matrices, + parent_bone_deform=new_deform, ) def update_skin(self, animation): @@ -722,16 +739,25 @@ def update_skin(self, animation): parent_transform = np.identity(4) for child in _animation.child_animations: self.transverse_animations( - child, self.bones[0], timestamp, joint_matrices, parent_transform + child, + self.bones[0], + timestamp, + joint_matrices, + parent_bone_deform=parent_transform, ) for i, vertex in enumerate(self._vertices): - vertex[:] = self.apply_skin_matrix(self._vcopy[i], joint_matrices, i) + vertex[:] = self.apply_skin_matrix( + self._vcopy[i], + joint_matrices, + actor_index=i, + ) actor_transf = self.transformations[i] vertex[:] = transform.apply_transformation(vertex, actor_transf) utils.update_actor(self._actors[i]) utils.compute_bounds(self._actors[i]) - def initialize_skin(self, animation, bones=False, length=0.2): + @warn_on_args_to_kwargs() + def initialize_skin(self, animation, *, bones=False, length=0.2): """Create bones and add to the animation and initialise `update_skin` Parameters @@ -748,11 +774,12 @@ def initialize_skin(self, animation, bones=False, length=0.2): """ self.show_bones = bones if bones: - self.get_joint_actors(length, False) + self.get_joint_actors(length=length, with_transforms=False) animation.add_actor(list(self._bactors.values())) self.update_skin(animation) - def apply_skin_matrix(self, vertices, joint_matrices, actor_index=0): + @warn_on_args_to_kwargs() + def apply_skin_matrix(self, vertices, joint_matrices, *, actor_index=0): """Apply the skinnig matrix, that transform the vertices. Parameters @@ -845,7 +872,8 @@ def skin_animation(self): root_animation.add_actor(self._actors) return root_animations - def get_joint_actors(self, length=0.5, with_transforms=False): + @warn_on_args_to_kwargs() + def get_joint_actors(self, *, length=0.5, with_transforms=False): """Create an arrow actor for each bone in a skinned model. Parameters @@ -1039,7 +1067,8 @@ def main_animation(self): return main_animation -def export_scene(scene, filename="default.gltf"): +@warn_on_args_to_kwargs() +def export_scene(scene, *, filename="default.gltf"): """Generate gltf from FURY scene. Parameters @@ -1175,8 +1204,8 @@ def _connect_primitives(gltf, actor, buff_file, byteoffset, count, name): gltflib.FLOAT, len(vertices) // atype, gltflib.VEC3, - amax, - amin, + max=amax, + min=amin, ) byteoffset += blength vertex = count @@ -1200,8 +1229,8 @@ def _connect_primitives(gltf, actor, buff_file, byteoffset, count, name): gltflib.FLOAT, len(normals) // atype, gltflib.VEC3, - amax, - amin, + max=amax, + min=amin, ) byteoffset += blength normal = count @@ -1251,7 +1280,7 @@ def _connect_primitives(gltf, actor, buff_file, byteoffset, count, name): color = count count += 1 material = None if tcoords is None else 0 - prim = get_prim(vertex, index, color, tcoord, normal, material, mode) + prim = get_prim(vertex, index, color, tcoord, normal, material, mode=mode) return prim, byteoffset, count @@ -1271,7 +1300,8 @@ def write_scene(gltf, nodes): gltf.scenes.append(scene) -def write_node(gltf, mesh_id=None, camera_id=None): +@warn_on_args_to_kwargs() +def write_node(gltf, *, mesh_id=None, camera_id=None): """Create node Parameters @@ -1339,7 +1369,8 @@ def write_camera(gltf, camera): gltf.cameras.append(cam) -def get_prim(vertex, index, color, tcoord, normal, material, mode=4): +@warn_on_args_to_kwargs() +def get_prim(vertex, index, color, tcoord, normal, material, *, mode=4): """Return a Primitive object. Parameters @@ -1409,8 +1440,9 @@ def write_material(gltf, basecolortexture: int, uri: str): gltf.images.append(image) +@warn_on_args_to_kwargs() def write_accessor( - gltf, bufferview, byte_offset, comp_type, count, accssor_type, max=None, min=None + gltf, bufferview, byte_offset, comp_type, count, accssor_type, *, max=None, min=None ): """Write accessor in the gltf. @@ -1447,7 +1479,8 @@ def write_accessor( gltf.accessors.append(accessor) -def write_bufferview(gltf, buffer, byte_offset, byte_length, byte_stride=None): +@warn_on_args_to_kwargs() +def write_bufferview(gltf, buffer, byte_offset, byte_length, *, byte_stride=None): """Write bufferview in the gltf. Parameters diff --git a/fury/interactor.py b/fury/interactor.py index 399f449925..febe0d6100 100644 --- a/fury/interactor.py +++ b/fury/interactor.py @@ -4,6 +4,7 @@ import numpy as np +from fury.decorators import warn_on_args_to_kwargs from fury.lib import ( Command, InteractorStyle, @@ -173,7 +174,8 @@ def _process_event(self, obj, evt): self.event.reset() # Event fully processed. - def _button_clicked(self, button, last_event=-1, before_last_event=-2): + @warn_on_args_to_kwargs() + def _button_clicked(self, button, *, last_event=-1, before_last_event=-2): if len(self.history) < abs(before_last_event): return False @@ -186,7 +188,10 @@ def _button_clicked(self, button, last_event=-1, before_last_event=-2): return True def _button_double_clicked(self, button): - if not (self._button_clicked(button) and self._button_clicked(button, -3, -4)): + if not ( + self._button_clicked(button) + and self._button_clicked(button, last_event=-3, before_last_event=-4) + ): return False return True @@ -383,7 +388,8 @@ def force_render(self): """Causes the scene to refresh.""" self.GetInteractor().GetRenderWindow().Render() - def add_callback(self, prop, event_type, callback, priority=0, args=None): + @warn_on_args_to_kwargs() + def add_callback(self, prop, event_type, callback, *, priority=0, args=None): """Add a callback associated to a specific event for a VTK prop. Parameters diff --git a/fury/io.py b/fury/io.py index 828002c2d5..8f29000140 100644 --- a/fury/io.py +++ b/fury/io.py @@ -6,6 +6,7 @@ from PIL import Image import numpy as np +from fury.decorators import warn_on_args_to_kwargs from fury.lib import ( BMPReader, BMPWriter, @@ -34,7 +35,8 @@ from fury.utils import set_input -def load_cubemap_texture(fnames, interpolate_on=True, mipmap_on=True): +@warn_on_args_to_kwargs() +def load_cubemap_texture(fnames, *, interpolate_on=True, mipmap_on=True): """Load a cube map texture from a list of 6 images. Parameters @@ -74,7 +76,8 @@ def load_cubemap_texture(fnames, interpolate_on=True, mipmap_on=True): return texture -def load_image(filename, as_vtktype=False, use_pillow=True): +@warn_on_args_to_kwargs() +def load_image(filename, *, as_vtktype=False, use_pillow=True): """Load an image. Parameters @@ -92,8 +95,8 @@ def load_image(filename, as_vtktype=False, use_pillow=True): desired image array """ - is_url = filename.lower().startswith("http://") or filename.lower().startswith( - "https://" + is_url = (filename.lower().startswith("http://")) or ( + filename.lower().startswith("https://") ) if is_url: @@ -135,7 +138,14 @@ def load_image(filename, as_vtktype=False, use_pillow=True): # width, height vtk_image.SetDimensions(image.shape[1], image.shape[0], depth) - vtk_image.SetExtent(0, image.shape[1] - 1, 0, image.shape[0] - 1, 0, 0) + vtk_image.SetExtent( + 0, + image.shape[1] - 1, + 0, + image.shape[0] - 1, + 0, + 0, + ) vtk_image.SetSpacing(1.0, 1.0, 1.0) vtk_image.SetOrigin(0.0, 0.0, 0.0) @@ -210,9 +220,11 @@ def load_text(file): return text +@warn_on_args_to_kwargs() def save_image( arr, filename, + *, compression_quality=75, compression_type="deflation", use_pillow=True, @@ -307,7 +319,13 @@ def save_image( writer.SetQuality(compression_quality) if extension.lower() in [".tif", ".tiff"]: compression_type = compression_type or "nocompression" - l_compression = ["nocompression", "packbits", "jpeg", "deflate", "lzw"] + l_compression = [ + "nocompression", + "packbits", + "jpeg", + "deflate", + "lzw", + ] if compression_type.lower() in l_compression: comp_id = l_compression.index(compression_type.lower()) @@ -363,7 +381,8 @@ def load_polydata(file_name): return reader.GetOutput() -def save_polydata(polydata, file_name, binary=False, color_array_name=None): +@warn_on_args_to_kwargs() +def save_polydata(polydata, file_name, *, binary=False, color_array_name=None): """Save a vtk polydata to a supported format file. Save formats can be VTK, FIB, PLY, STL and XML. @@ -413,7 +432,8 @@ def save_polydata(polydata, file_name, binary=False, color_array_name=None): writer.Write() -def load_sprite_sheet(sheet_path, nb_rows, nb_cols, as_vtktype=False): +@warn_on_args_to_kwargs() +def load_sprite_sheet(sheet_path, nb_rows, nb_cols, *, as_vtktype=False): """Process and load sprites from a sprite sheet. Parameters @@ -450,13 +470,18 @@ def load_sprite_sheet(sheet_path, nb_rows, nb_cols, as_vtktype=False): nxt_col * sprite_size_y, ) - sprite_arr = sprite_sheet[box[0] : box[2], box[1] : box[3]] + sprite_arr = sprite_sheet[ + box[0] : box[2], box[1] : box[3] # noqa: E203 + ] if as_vtktype: with InTemporaryDirectory() as tdir: tmp_img_path = os.path.join(tdir, f"{row}{col}.png") save_image(sprite_arr, tmp_img_path, compression_quality=100) - sprite_dicts[(row, col)] = load_image(tmp_img_path, as_vtktype=True) + sprite_dicts[(row, col)] = load_image( + tmp_img_path, + as_vtktype=True, + ) else: sprite_dicts[(row, col)] = sprite_arr diff --git a/fury/layout.py b/fury/layout.py index 7647949b56..f227b99cd3 100644 --- a/fury/layout.py +++ b/fury/layout.py @@ -2,6 +2,7 @@ import numpy as np +from fury.decorators import warn_on_args_to_kwargs from fury.utils import get_bounding_box_sizes, get_grid_cells_position, is_ui @@ -32,8 +33,10 @@ class GridLayout(Layout): """ + @warn_on_args_to_kwargs() def __init__( self, + *, cell_padding=0, cell_shape="rect", aspect_ratio=16 / 9.0, @@ -88,11 +91,25 @@ def get_cells_shape(self, actors): """ if self.cell_shape == "rect": - bounding_box_sizes = np.asarray(list(map(self.compute_sizes, actors))) + bounding_box_sizes = np.asarray( + list( + map( + self.compute_sizes, + actors, + ) + ) + ) cell_shape = np.max(bounding_box_sizes, axis=0)[:2] shapes = [cell_shape] * len(actors) elif self.cell_shape == "square": - bounding_box_sizes = np.asarray(list(map(self.compute_sizes, actors))) + bounding_box_sizes = np.asarray( + list( + map( + self.compute_sizes, + actors, + ) + ) + ) cell_shape = np.max(bounding_box_sizes, axis=0)[:2] shapes = [(max(cell_shape),) * 2] * len(actors) elif self.cell_shape == "diagonal": @@ -110,7 +127,11 @@ def get_cells_shape(self, actors): longest_diagonal = np.max(diagonals) shapes = [(longest_diagonal, longest_diagonal)] * len(actors) else: - raise ValueError("Unknown cell shape: '{0}'".format(self.cell_shape)) + raise ValueError( + "Unknown cell shape: '{0}'".format( + self.cell_shape, + ) + ) return shapes @@ -133,7 +154,11 @@ def compute_positions(self, actors): # Add padding, if any, around every cell. shapes = [np.array(self.cell_padding) / 2.0 + s for s in shapes] - positions = get_grid_cells_position(shapes, self.aspect_ratio, self.dim) + positions = get_grid_cells_position( + shapes, + aspect_ratio=self.aspect_ratio, + dim=self.dim, + ) positions += self.position_offset return positions @@ -161,7 +186,8 @@ def compute_sizes(self, actor): class HorizontalLayout(GridLayout): """Provide functionalities for laying out actors in a horizontal layout.""" - def __init__(self, cell_padding=0, cell_shape="rect"): + @warn_on_args_to_kwargs() + def __init__(self, *, cell_padding=0, cell_shape="rect"): """Initialize the Horizontal layout. Parameters @@ -216,7 +242,8 @@ def compute_positions(self, actors): class VerticalLayout(GridLayout): """Provide functionalities for laying out actors in a vertical stack.""" - def __init__(self, cell_padding=0, cell_shape="rect"): + @warn_on_args_to_kwargs() + def __init__(self, *, cell_padding=0, cell_shape="rect"): """Initialize the Vertical layout. Parameters @@ -270,7 +297,8 @@ def compute_positions(self, actors): class XLayout(HorizontalLayout): """Provide functionalities for laying out actors along x-axis.""" - def __init__(self, direction="x+", cell_padding=0, cell_shape="rect"): + @warn_on_args_to_kwargs() + def __init__(self, *, direction="x+", cell_padding=0, cell_shape="rect"): """Initialize the X layout. Parameters @@ -297,7 +325,10 @@ def __init__(self, direction="x+", cell_padding=0, cell_shape="rect"): if self.direction not in ["x+", "x-"]: raise ValueError(f"{direction} is not a valid direction") - super(XLayout, self).__init__(cell_padding=cell_padding, cell_shape=cell_shape) + super(XLayout, self).__init__( + cell_padding=cell_padding, + cell_shape=cell_shape, + ) def get_cells_shape(self, actors): """Get the 2D shape (on the xy-plane) of some actors according to @@ -352,7 +383,8 @@ def apply(self, actors): class YLayout(VerticalLayout): """Provide functionalities for laying out actors along y-axis.""" - def __init__(self, direction="y+", cell_padding=0, cell_shape="rect"): + @warn_on_args_to_kwargs() + def __init__(self, *, direction="y+", cell_padding=0, cell_shape="rect"): """Initialize the Y layout. Parameters @@ -379,7 +411,10 @@ def __init__(self, direction="y+", cell_padding=0, cell_shape="rect"): if self.direction not in ["y+", "y-"]: raise ValueError(f"{direction} is not a valid direction") - super(YLayout, self).__init__(cell_padding=cell_padding, cell_shape=cell_shape) + super(YLayout, self).__init__( + cell_padding=cell_padding, + cell_shape=cell_shape, + ) def get_cells_shape(self, actors): """Get the 2D shape (on the xy-plane) of some actors according to @@ -434,7 +469,8 @@ def apply(self, actors): class ZLayout(GridLayout): """Provide functionalities for laying out actors along z-axis.""" - def __init__(self, direction="z+", cell_padding=0, cell_shape="rect"): + @warn_on_args_to_kwargs() + def __init__(self, *, direction="z+", cell_padding=0, cell_shape="rect"): """Initialize the Z layout. Parameters @@ -461,7 +497,10 @@ def __init__(self, direction="z+", cell_padding=0, cell_shape="rect"): if self.direction not in ["z+", "z-"]: raise ValueError(f"{direction} is not a valid direction") - super(ZLayout, self).__init__(cell_padding=cell_padding, cell_shape=cell_shape) + super(ZLayout, self).__init__( + cell_padding=cell_padding, + cell_shape=cell_shape, + ) def get_cells_shape(self, actors): """Get the shape (on the z-plane) of some actors according to @@ -482,7 +521,14 @@ def get_cells_shape(self, actors): actors = actors[::-1] if self.cell_shape == "rect" or self.cell_shape == "square": - bounding_box_sizes = np.asarray(list(map(get_bounding_box_sizes, actors))) + bounding_box_sizes = np.asarray( + list( + map( + get_bounding_box_sizes, + actors, + ) + ) + ) cell_shape = np.max(bounding_box_sizes, axis=0)[2] shapes = [cell_shape] * len(actors) elif self.cell_shape == "diagonal": @@ -491,7 +537,11 @@ def get_cells_shape(self, actors): longest_diagonal = np.max([a.GetLength() for a in actors]) shapes = [longest_diagonal] * len(actors) else: - raise ValueError("Unknown cell shape: '{0}'".format(self.cell_shape)) + raise ValueError( + "Unknown cell shape: '{0}'".format( + self.cell_shape, + ) + ) return shapes diff --git a/fury/material.py b/fury/material.py index 22891395aa..98b97eae4c 100644 --- a/fury/material.py +++ b/fury/material.py @@ -1,6 +1,7 @@ import os import warnings +from fury.decorators import warn_on_args_to_kwargs from fury.lib import VTK_OBJECT, calldata_type from fury.shaders import ( add_shader_callback, @@ -134,8 +135,10 @@ def coat_ior(self, coat_ior): self.__actor_properties.SetCoatIOR(coat_ior) +@warn_on_args_to_kwargs() def manifest_pbr( actor, + *, metallic=0, roughness=0.5, anisotropy=0, @@ -208,8 +211,10 @@ def manifest_pbr( return None +@warn_on_args_to_kwargs() def manifest_principled( actor, + *, subsurface=0, metallic=0, specular=0, @@ -284,20 +289,40 @@ def manifest_principled( @calldata_type(VTK_OBJECT) def uniforms_callback(_caller, _event, calldata=None): if calldata is not None: - calldata.SetUniformf("subsurface", principled_params["subsurface"]) + calldata.SetUniformf( + "subsurface", + principled_params["subsurface"], + ) calldata.SetUniformf("metallic", principled_params["metallic"]) - calldata.SetUniformf("specularTint", principled_params["specular_tint"]) - calldata.SetUniformf("roughness", principled_params["roughness"]) - calldata.SetUniformf("anisotropic", principled_params["anisotropic"]) + calldata.SetUniformf( + "specularTint", + principled_params["specular_tint"], + ) + calldata.SetUniformf( + "roughness", + principled_params["roughness"], + ) + calldata.SetUniformf( + "anisotropic", + principled_params["anisotropic"], + ) calldata.SetUniformf("sheen", principled_params["sheen"]) - calldata.SetUniformf("sheenTint", principled_params["sheen_tint"]) - calldata.SetUniformf("clearcoat", principled_params["clearcoat"]) calldata.SetUniformf( - "clearcoatGloss", principled_params["clearcoat_gloss"] + "sheenTint", + principled_params["sheen_tint"], + ) + calldata.SetUniformf( + "clearcoat", + principled_params["clearcoat"], + ) + calldata.SetUniformf( + "clearcoatGloss", + principled_params["clearcoat_gloss"], ) calldata.SetUniform3f( - "anisotropicDirection", principled_params["anisotropic_direction"] + "anisotropicDirection", + principled_params["anisotropic_direction"], ) add_shader_callback(actor, uniforms_callback) @@ -374,7 +399,13 @@ def uniforms_callback(_caller, _event, calldata=None): # Importing Geometry Shadowing and Masking Function (GF): Smith Ground # Glass Unknown (G_{GGX}) needed for the Isotropic Specular and Clear # Coat lobes - smith_ggx = import_fury_shader(os.path.join("lighting", "gf", "smith_ggx.frag")) + smith_ggx = import_fury_shader( + os.path.join( + "lighting", + "gf", + "smith_ggx.frag", + ) + ) # Importing Geometry Shadowing and Masking Function (GF): Anisotropic # form of the Smith Ground Glass Unknown (G_{GGXanisotropic}) needed @@ -390,7 +421,13 @@ def uniforms_callback(_caller, _event, calldata=None): subsurface = import_fury_shader( os.path.join("lighting", "principled", "subsurface.frag") ) - sheen = import_fury_shader(os.path.join("lighting", "principled", "sheen.frag")) + sheen = import_fury_shader( + os.path.join( + "lighting", + "principled", + "sheen.frag", + ) + ) specular_isotropic = import_fury_shader( os.path.join("lighting", "principled", "specular_isotropic.frag") ) @@ -574,8 +611,10 @@ def uniforms_callback(_caller, _event, calldata=None): return None +@warn_on_args_to_kwargs() def manifest_standard( actor, + *, ambient_level=0, ambient_color=(1, 1, 1), diffuse_level=1, diff --git a/fury/molecular.py b/fury/molecular.py index 394591297c..ea0e13b521 100644 --- a/fury/molecular.py +++ b/fury/molecular.py @@ -5,6 +5,7 @@ import numpy as np from fury.actor import streamtube +from fury.decorators import warn_on_args_to_kwargs from fury.lib import ( VTK_FLOAT, VTK_ID_TYPE, @@ -34,8 +35,10 @@ class Molecule(Mol): This is a more pythonic version of ``Molecule``. """ + @warn_on_args_to_kwargs() def __init__( self, + *, atomic_numbers=None, coords=None, atom_names=None, @@ -107,7 +110,10 @@ def __init__( self.helix = helix self.is_hetatm = is_hetatm coords = numpy_to_vtk_points(coords) - atom_nums = nps.numpy_to_vtk(atomic_numbers, array_type=VTK_UNSIGNED_SHORT) + atom_nums = nps.numpy_to_vtk( + atomic_numbers, + array_type=VTK_UNSIGNED_SHORT, + ) atom_nums.SetName("Atomic Numbers") fieldData = DataSetAttributes() fieldData.AddArray(atom_nums) @@ -151,7 +157,8 @@ def add_atom(molecule, atomic_num, x_coord, y_coord, z_coord): molecule.AppendAtom(atomic_num, x_coord, y_coord, z_coord) -def add_bond(molecule, atom1_index, atom2_index, bond_order=1): +@warn_on_args_to_kwargs() +def add_bond(molecule, atom1_index, atom2_index, *, bond_order=1): """Add bonding data to our molecule. Establish a bond of type bond_order between the atom at atom1_index and the atom at atom2_index. @@ -413,7 +420,8 @@ def atomic_number(self, element_name): """ return self.GetAtomicNumber(element_name) - def atomic_radius(self, atomic_number, radius_type="VDW"): + @warn_on_args_to_kwargs() + def atomic_radius(self, atomic_number, *, radius_type="VDW"): """Given an atomic number, return either the covalent radius of the atom (in Ã…) or return the Van Der Waals radius (in Ã…) of the atom depending on radius_type. @@ -457,7 +465,8 @@ def atom_color(self, atomic_number): return rgb -def sphere_cpk(molecule, colormode="discrete"): +@warn_on_args_to_kwargs() +def sphere_cpk(molecule, *, colormode="discrete"): """Create an actor for sphere molecular representation. It's also referred to as CPK model and space-filling model. @@ -502,7 +511,10 @@ def sphere_cpk(molecule, colormode="discrete"): msp_mapper.SetAtomColorMode(0) else: msp_mapper.SetAtomColorMode(1) - warnings.warn("Incorrect colormode specified! Using discrete.", stacklevel=2) + warnings.warn( + "Incorrect colormode specified! Using discrete.", + stacklevel=2, + ) # To-Do manipulate shading properties to make it look aesthetic molecule_actor = Actor() @@ -510,8 +522,10 @@ def sphere_cpk(molecule, colormode="discrete"): return molecule_actor +@warn_on_args_to_kwargs() def ball_stick( molecule, + *, colormode="discrete", atom_scale_factor=0.3, bond_thickness=0.1, @@ -586,13 +600,17 @@ def ball_stick( bs_mapper.SetBondColorMode(0) else: bs_mapper.SetAtomColorMode(1) - warnings.warn("Incorrect colormode specified! Using discrete.", stacklevel=2) + warnings.warn( + "Incorrect colormode specified! Using discrete.", + stacklevel=2, + ) molecule_actor = Actor() molecule_actor.SetMapper(bs_mapper) return molecule_actor -def stick(molecule, colormode="discrete", bond_thickness=0.1): +@warn_on_args_to_kwargs() +def stick(molecule, *, colormode="discrete", bond_thickness=0.1): """Create an actor for stick molecular representation. Parameters @@ -623,7 +641,10 @@ def stick(molecule, colormode="discrete", bond_thickness=0.1): """ if molecule.total_num_bonds == 0: raise ValueError( - "No bonding data available for the molecule! Stick " "model cannot be made!" + ( + "No bonding data available for the molecule! Stick " + "model cannot be made!" + ) ) colormode = colormode.lower() mst_mapper = OpenGLMoleculeMapper() @@ -641,7 +662,10 @@ def stick(molecule, colormode="discrete", bond_thickness=0.1): mst_mapper.SetBondColorMode(0) else: mst_mapper.SetAtomColorMode(1) - warnings.warn("Incorrect colormode specified! Using discrete.", stacklevel=2) + warnings.warn( + "Incorrect colormode specified! Using discrete.", + stacklevel=2, + ) molecule_actor = Actor() molecule_actor.SetMapper(mst_mapper) return molecule_actor @@ -677,13 +701,21 @@ def ribbon(molecule): resi = molecule.residue_seq[i] for j, _ in enumerate(molecule.sheet): sheet = molecule.sheet[j] - if molecule.chain[i] != sheet[0] or resi < sheet[1] or resi > sheet[3]: + if ( + (molecule.chain[i] != sheet[0]) + or (resi < sheet[1]) + or (resi > sheet[3]) + ): continue secondary_structures[i] = ord("s") for j, _ in enumerate(molecule.helix): helix = molecule.helix[j] - if molecule.chain[i] != helix[0] or resi < helix[1] or resi > helix[3]: + if ( + (molecule.chain[i] != helix[0]) + or (resi < helix[1]) + or (resi > helix[3]) + ): continue secondary_structures[i] = ord("h") @@ -735,13 +767,21 @@ def ribbon(molecule): # for secondary structures begin newarr = np.ones(num_total_atoms) - s_sb = nps.numpy_to_vtk(num_array=newarr, deep=True, array_type=VTK_UNSIGNED_CHAR) + s_sb = nps.numpy_to_vtk( + num_array=newarr, + deep=True, + array_type=VTK_UNSIGNED_CHAR, + ) s_sb.SetName("secondary_structures_begin") output.GetPointData().AddArray(s_sb) # for secondary structures end newarr = np.ones(num_total_atoms) - s_se = nps.numpy_to_vtk(num_array=newarr, deep=True, array_type=VTK_UNSIGNED_CHAR) + s_se = nps.numpy_to_vtk( + num_array=newarr, + deep=True, + array_type=VTK_UNSIGNED_CHAR, + ) s_se.SetName("secondary_structures_end") output.GetPointData().AddArray(s_se) @@ -766,10 +806,17 @@ def ribbon(molecule): rgb = np.ones((num_total_atoms, 3)) for i in range(num_total_atoms): - radii[i] = np.repeat(table.atomic_radius(all_atomic_numbers[i], "VDW"), 3) + radii[i] = np.repeat( + table.atomic_radius(all_atomic_numbers[i], radius_type="VDW"), + 3, + ) rgb[i] = table.atom_color(all_atomic_numbers[i]) - Rgb = nps.numpy_to_vtk(num_array=rgb, deep=True, array_type=VTK_UNSIGNED_CHAR) + Rgb = nps.numpy_to_vtk( + num_array=rgb, + deep=True, + array_type=VTK_UNSIGNED_CHAR, + ) Rgb.SetName("rgb_colors") output.GetPointData().SetScalars(Rgb) @@ -792,7 +839,8 @@ def ribbon(molecule): return molecule_actor -def bounding_box(molecule, colors=(1, 1, 1), linewidth=0.3): +@warn_on_args_to_kwargs() +def bounding_box(molecule, *, colors=(1, 1, 1), linewidth=0.3): """Create a bounding box for a molecule. Parameters diff --git a/fury/optpkg.py b/fury/optpkg.py index 053b62c6b0..763ec64b20 100644 --- a/fury/optpkg.py +++ b/fury/optpkg.py @@ -2,6 +2,8 @@ import importlib +from fury.decorators import warn_on_args_to_kwargs + try: import pytest except ImportError: @@ -46,7 +48,7 @@ class TripWire: ... except ImportError: ... silly_module_name = TripWire('We do not have silly_module_name') >>> msg = 'with silly string' - >>> silly_module_name.do_silly_thing(msg) #doctest: +IGNORE_EXCEPTION_DETAIL + >>> silly_module_name.do_silly_thing(msg) #doctest: +IGNORE_EXCEPTION_DETAIL # noqa Traceback (most recent call last): ... TripWireError: We do not have silly_module_name @@ -65,7 +67,8 @@ def __call__(self, *args, **kwargs): raise TripWireError(self._msg) -def optional_package(name, trip_msg=None): +@warn_on_args_to_kwargs() +def optional_package(name, *, trip_msg=None): """Return package-like thing and module setup for package `name`. Parameters diff --git a/fury/pick.py b/fury/pick.py index 6949638c5d..49941849a1 100644 --- a/fury/pick.py +++ b/fury/pick.py @@ -2,6 +2,7 @@ import numpy as np +from fury.decorators import warn_on_args_to_kwargs from fury.lib import ( CellPicker, DataObject, @@ -16,7 +17,15 @@ class PickingManager: """Picking Manager helps with picking 3D objects.""" - def __init__(self, vertices=True, faces=True, actors=True, world_coords=True): + @warn_on_args_to_kwargs() + def __init__( + self, + *, + vertices=True, + faces=True, + actors=True, + world_coords=True, + ): """Initialize Picking Manager. Parameters @@ -120,7 +129,8 @@ def pickable_off(self, actors): class SelectionManager: """Selection Manager helps with picking many objects simultaneously.""" - def __init__(self, select="faces"): + @warn_on_args_to_kwargs() + def __init__(self, *, select="faces"): """Initialize Selection Manager. Parameters @@ -171,7 +181,8 @@ def pick(self, disp_xy, sc): """ return self.select(disp_xy, sc, area=0)[0] - def select(self, disp_xy, sc, area=0): + @warn_on_args_to_kwargs() + def select(self, disp_xy, sc, *, area=0): """Select multiple objects using display coordinates. Parameters @@ -202,26 +213,49 @@ def select(self, disp_xy, sc, area=0): res = self.hsel.Select() except OverflowError: - return {0: {"node": None, "vertex": None, "face": None, "actor": None}} + return { + 0: { + "node": None, + "vertex": None, + "face": None, + "actor": None, + } + } num_nodes = res.GetNumberOfNodes() if num_nodes < 1: sel_node = None - return {0: {"node": None, "vertex": None, "face": None, "actor": None}} + return { + 0: { + "node": None, + "vertex": None, + "face": None, + "actor": None, + } + } else: for i in range(num_nodes): sel_node = res.GetNode(i) - info = {"node": None, "vertex": None, "face": None, "actor": None} + info = { + "node": None, + "vertex": None, + "face": None, + "actor": None, + } if sel_node is not None: selected_nodes = set( np.floor( - numpy_support.vtk_to_numpy(sel_node.GetSelectionList()) + numpy_support.vtk_to_numpy( + sel_node.GetSelectionList(), + ) ).astype(int) ) info["node"] = sel_node - info["actor"] = sel_node.GetProperties().Get(sel_node.PROP()) + info["actor"] = sel_node.GetProperties().Get( + sel_node.PROP(), + ) if self.selected_type == "faces": info["face"] = list(selected_nodes) if self.selected_type == "vertex": diff --git a/fury/pkg_info.py b/fury/pkg_info.py index 7bd7da41ef..3773fbf227 100644 --- a/fury/pkg_info.py +++ b/fury/pkg_info.py @@ -4,6 +4,8 @@ from packaging.version import Version +from fury.decorators import warn_on_args_to_kwargs + try: from ._version import __version__ except ImportError: @@ -12,6 +14,7 @@ COMMIT_HASH = "$Format:%h$" +@warn_on_args_to_kwargs() def pkg_commit_hash(pkg_path: str | None = None) -> tuple[str, str]: """Get short form of commit hash diff --git a/fury/primitive.py b/fury/primitive.py index 768a926262..67a94663dc 100644 --- a/fury/primitive.py +++ b/fury/primitive.py @@ -9,6 +9,7 @@ from scipy.version import short_version from fury.data import DATA_DIR +from fury.decorators import warn_on_args_to_kwargs from fury.transform import cart2sphere, sphere2cart from fury.utils import fix_winding_order @@ -46,8 +47,9 @@ def faces_from_sphere_vertices(vertices): return faces +@warn_on_args_to_kwargs() def repeat_primitive_function( - func, centers, func_args=None, directions=(1, 0, 0), colors=(1, 0, 0), scales=1 + func, centers, *, func_args=None, directions=(1, 0, 0), colors=(1, 0, 0), scales=1 ): """Repeat Vertices and triangles of a specific primitive function. @@ -91,12 +93,11 @@ def repeat_primitive_function( "sq_params should 1 or equal to the numbers \ of centers" ) - vertices = np.concatenate([func(i)[0] for i in func_args]) return repeat_primitive( - vertices=vertices, - faces=faces, - centers=centers, + vertices, + faces, + centers, directions=directions, colors=colors, scales=scales, @@ -104,10 +105,12 @@ def repeat_primitive_function( ) +@warn_on_args_to_kwargs() def repeat_primitive( vertices, faces, centers, + *, directions=None, colors=(1, 0, 0), scales=1, @@ -173,7 +176,8 @@ def repeat_primitive( axis=0, ).reshape((big_triangles.shape[0], 1)) - def normalize_input(arr, arr_name=""): + @warn_on_args_to_kwargs() + def normalize_input(arr, *, arr_name=""): if ( isinstance(arr, (tuple, list, np.ndarray)) and len(arr) in [3, 4] @@ -192,12 +196,12 @@ def normalize_input(arr, arr_name=""): return np.array(arr) # update colors - colors = normalize_input(colors, "colors") + colors = normalize_input(colors, arr_name="colors") big_colors = np.repeat(colors, unit_verts_size, axis=0) big_colors *= 255 # update orientations - directions = normalize_input(directions, "directions") + directions = normalize_input(directions, arr_name="directions") for pts, dirs in enumerate(directions): # Normal vector of the object. dir_abs = np.linalg.norm(dirs) @@ -295,7 +299,8 @@ def prim_box(): return vertices, triangles -def prim_sphere(name="symmetric362", gen_faces=False, phi=None, theta=None): +@warn_on_args_to_kwargs() +def prim_sphere(*, name="symmetric362", gen_faces=False, phi=None, theta=None): """Provide vertices and triangles of the spheres. Parameters @@ -413,7 +418,7 @@ def _fexp(x, p): """Return a different kind of exponentiation.""" return np.sign(x) * (np.abs(x) ** p) - sphere_verts, sphere_triangles = prim_sphere(sphere_name) + sphere_verts, sphere_triangles = prim_sphere(name=sphere_name) _, sphere_phi, sphere_theta = cart2sphere(*sphere_verts.T) phi, theta = roundness @@ -605,7 +610,8 @@ def prim_rhombicuboctahedron(): return vertices, triangles -def prim_star(dim=2): +@warn_on_args_to_kwargs() +def prim_star(*, dim=2): """Return vertices and triangle for star geometry. Parameters @@ -918,7 +924,8 @@ def prim_frustum(): return vertices, triangles -def prim_cylinder(radius=0.5, height=1, sectors=36, capped=True): +@warn_on_args_to_kwargs() +def prim_cylinder(*, radius=0.5, height=1, sectors=36, capped=True): """Return vertices and triangles for a cylinder. Parameters @@ -1045,8 +1052,14 @@ def prim_cylinder(radius=0.5, height=1, sectors=36, capped=True): return vertices, triangles +@warn_on_args_to_kwargs() def prim_arrow( - height=1.0, resolution=10, tip_length=0.35, tip_radius=0.1, shaft_radius=0.03 + *, + height=1.0, + resolution=10, + tip_length=0.35, + tip_radius=0.1, + shaft_radius=0.03, ): """Return vertices and triangle for arrow geometry. @@ -1135,7 +1148,8 @@ def prim_arrow( return vertices, triangles -def prim_cone(radius=0.5, height=1, sectors=10): +@warn_on_args_to_kwargs() +def prim_cone(*, radius=0.5, height=1, sectors=10): """Return vertices and triangle of a Cone. Parameters diff --git a/fury/shaders/tests/test_base.py b/fury/shaders/tests/test_base.py index 7fc7f34381..14c518c598 100644 --- a/fury/shaders/tests/test_base.py +++ b/fury/shaders/tests/test_base.py @@ -191,7 +191,7 @@ def test_add_shader_callback(): scene = window.Scene() scene.add(cube) - showm = window.ShowManager(scene) + showm = window.ShowManager(scene=scene) class Timer: idx = 0.0 diff --git a/fury/testing.py b/fury/testing.py index 79f790f7a7..7904f77c42 100644 --- a/fury/testing.py +++ b/fury/testing.py @@ -13,6 +13,8 @@ from numpy.testing import assert_array_equal import scipy # type: ignore +from fury.decorators import warn_on_args_to_kwargs + @contextmanager def captured_output(): @@ -37,13 +39,18 @@ def captured_output(): sys.stdout, sys.stderr = old_out, old_err -def assert_operator(value1, value2, msg="", op=operator.eq): +@warn_on_args_to_kwargs() +def assert_operator(value1, value2, *, msg="", op=operator.eq): """Check Boolean statement.""" if not op(value1, value2): raise AssertionError(msg.format(str(value2), str(value1))) -assert_greater_equal = partial(assert_operator, op=operator.ge, msg="{0} >= {1}") +assert_greater_equal = partial( + assert_operator, + op=operator.ge, + msg="{0} >= {1}", +) assert_greater = partial(assert_operator, op=operator.gt, msg="{0} > {1}") assert_less_equal = partial(assert_operator, op=operator.le, msg="{0} =< {1}") assert_less = partial(assert_operator, op=operator.lt, msg="{0} < {1}") @@ -63,7 +70,8 @@ def assert_arrays_equal(arrays1, arrays2): class EventCounter: - def __init__(self, events_names=None): + @warn_on_args_to_kwargs() + def __init__(self, *, events_names=None): if events_names is None: events_names = [ "CharEvent", @@ -113,7 +121,11 @@ def check_counts(self, expected): msg = "Wrong count for '{}'." for event, count in expected.events_counts.items(): - assert_equal(self.events_counts[event], count, msg=msg.format(event)) + assert_equal( + self.events_counts[event], + count, + msg=msg.format(event), + ) class clear_and_catch_warnings(warnings.catch_warnings): @@ -161,7 +173,8 @@ class clear_and_catch_warnings(warnings.catch_warnings): class_modules = () - def __init__(self, record=True, modules=()): + @warn_on_args_to_kwargs() + def __init__(self, *, record=True, modules=()): self.modules = set(modules).union(self.class_modules) self._warnreg_copies = {} super(clear_and_catch_warnings, self).__init__(record=record) diff --git a/fury/tests/test_actors.py b/fury/tests/test_actors.py index 46625250df..b76fec2998 100644 --- a/fury/tests/test_actors.py +++ b/fury/tests/test_actors.py @@ -48,8 +48,8 @@ def test_slicer(verbose=False): scene = window.Scene() data = 255 * np.random.rand(50, 50, 50) affine = np.eye(4) - slicer = actor.slicer(data, affine, value_range=[data.min(), data.max()]) - slicer.display(None, None, 25) + slicer = actor.slicer(data, affine=affine, value_range=[data.min(), data.max()]) + slicer.display(x=None, y=None, z=25) scene.add(slicer) scene.reset_camera() @@ -57,7 +57,7 @@ def test_slicer(verbose=False): # window.show(scene) # copy pixels in numpy array directly - arr = window.snapshot(scene, "test_slicer.png", offscreen=True) + arr = window.snapshot(scene, fname="test_slicer.png", offscreen=True) if verbose: print(arr.sum()) @@ -80,14 +80,22 @@ def test_slicer(verbose=False): # save pixels in png file not a numpy array with InTemporaryDirectory() as tmpdir: fname = os.path.join(tmpdir, "slice.png") - window.snapshot(scene, fname, offscreen=True) + window.snapshot(scene, fname=fname, offscreen=True) report = window.analyze_snapshot(fname, find_objects=True) npt.assert_equal(report.objects, 1) # Test Errors data_4d = 255 * np.random.rand(50, 50, 50, 50) - npt.assert_raises(ValueError, actor.slicer, data_4d) - npt.assert_raises(ValueError, actor.slicer, np.ones(10)) + npt.assert_raises( + ValueError, + actor.slicer, + data_4d, + ) + npt.assert_raises( + ValueError, + actor.slicer, + np.ones(10), + ) scene.clear() @@ -114,9 +122,9 @@ def test_slicer(verbose=False): scene.clear() slicer_lut = actor.slicer(data, lookup_colormap=lut) - slicer_lut.display(10, None, None) - slicer_lut.display(None, 10, None) - slicer_lut.display(None, None, 10) + slicer_lut.display(x=10, y=None, z=None) + slicer_lut.display(x=None, y=10, z=None) + slicer_lut.display(x=None, y=None, z=10) slicer_lut.opacity(0.5) slicer_lut.tolerance(0.03) @@ -125,7 +133,7 @@ def test_slicer(verbose=False): npt.assert_equal(slicer_lut2.picker.GetTolerance(), 0.03) slicer_lut2.opacity(1) slicer_lut2.tolerance(0.025) - slicer_lut2.display(None, None, 10) + slicer_lut2.display(x=None, y=None, z=10) scene.add(slicer_lut2) scene.reset_clipping_range() @@ -138,8 +146,8 @@ def test_slicer(verbose=False): data = 255 * np.random.rand(50, 50, 50) affine = np.diag([1, 3, 2, 1]) - slicer = actor.slicer(data, affine, interpolation="nearest") - slicer.display(None, None, 25) + slicer = actor.slicer(data, affine=affine, interpolation="nearest") + slicer.display(x=None, y=None, z=25) scene.add(slicer) scene.reset_camera() @@ -187,7 +195,7 @@ def test_surface(): ) scene.add(surface_actor) # window.show(scene, size=(600, 600), reset_camera=False) - arr = window.snapshot(scene, "test_surface.png", offscreen=True) + arr = window.snapshot(scene, fname="test_surface.png", offscreen=True) report = window.analyze_snapshot(arr, find_objects=True) npt.assert_equal(report.objects, 1) @@ -200,7 +208,7 @@ def test_contour_from_roi(interactive=False): data[25, 20:30, 25] = 1.0 affine = np.eye(4) surface = actor.contour_from_roi( - data, affine, color=np.array([1, 0, 1]), opacity=0.5 + data, affine=affine, color=np.array([1, 0, 1]), opacity=0.5 ) scene.add(surface) @@ -219,7 +227,7 @@ def test_contour_from_roi(interactive=False): data2[35:40, 25, 25] = 1.0 affine = np.eye(4) surface2 = actor.contour_from_roi( - data2, affine, color=np.array([0, 1, 1]), opacity=0.5 + data2, affine=affine, color=np.array([0, 1, 1]), opacity=0.5 ) scene2.add(surface2) @@ -228,8 +236,8 @@ def test_contour_from_roi(interactive=False): if interactive: window.show(scene2) - arr = window.snapshot(scene, "test_surface.png", offscreen=True) - arr2 = window.snapshot(scene2, "test_surface2.png", offscreen=True) + arr = window.snapshot(scene, fname="test_surface.png", offscreen=True) + arr2 = window.snapshot(scene2, fname="test_surface2.png", offscreen=True) report = window.analyze_snapshot(arr, find_objects=True) report2 = window.analyze_snapshot(arr2, find_objects=True) @@ -287,10 +295,10 @@ def test_contour_from_label(interactive=False): window.show(scene2) arr = window.snapshot( - scene, "test_surface.png", offscreen=True, order_transparent=False + scene, fname="test_surface.png", offscreen=True, order_transparent=False ) arr2 = window.snapshot( - scene2, "test_surface2.png", offscreen=True, order_transparent=True + scene2, fname="test_surface2.png", offscreen=True, order_transparent=True ) report = window.analyze_snapshot( @@ -312,14 +320,14 @@ def test_streamtube_and_line_actors(): lines = [line1, line2] colors = np.array([[1, 0, 0], [0, 0, 1.0]]) - c = actor.line(lines, colors, linewidth=3) + c = actor.line(lines, colors=colors, linewidth=3) scene.add(c) - c = actor.line(lines, colors, spline_subdiv=5, linewidth=3) + c = actor.line(lines, colors=colors, spline_subdiv=5, linewidth=3) scene.add(c) # create streamtubes of the same lines and shift them a bit - c2 = actor.streamtube(lines, colors, linewidth=0.1) + c2 = actor.streamtube(lines, colors=colors, linewidth=0.1) c2.SetPosition(2, 0, 0) scene.add(c2) @@ -333,7 +341,7 @@ def test_streamtube_and_line_actors(): npt.assert_equal(report.colors_found, [True, True]) # as before with splines - c2 = actor.streamtube(lines, colors, spline_subdiv=5, linewidth=0.1) + c2 = actor.streamtube(lines, colors=colors, spline_subdiv=5, linewidth=0.1) c2.SetPosition(2, 0, 0) scene.add(c2) @@ -346,7 +354,7 @@ def test_streamtube_and_line_actors(): npt.assert_equal(report.objects, 4) npt.assert_equal(report.colors_found, [True, True]) - c3 = actor.line(lines, colors, depth_cue=True, fake_tube=True) + c3 = actor.line(lines, colors=colors, depth_cue=True, fake_tube=True) shader_obj = c3.GetShaderProperty() mapper_code = shader_obj.GetGeometryShaderCode() @@ -355,9 +363,9 @@ def test_streamtube_and_line_actors(): npt.assert_equal(c3.GetProperty().GetRenderLinesAsTubes(), True) - c4 = actor.streamtube(lines, colors, replace_strips=False) + c4 = actor.streamtube(lines, colors=colors, replace_strips=False) - c5 = actor.streamtube(lines, colors, replace_strips=True) + c5 = actor.streamtube(lines, colors=colors, replace_strips=True) strips4 = c4.GetMapper().GetInput().GetStrips().GetData().GetSize() strips5 = c5.GetMapper().GetInput().GetStrips().GetData().GetSize() @@ -398,9 +406,9 @@ def test_bundle_maps(): value_range=(1.0, 1), ) - line = actor.line(bundle, metric, linewidth=0.1, lookup_colormap=lut) + line = actor.line(bundle, colors=metric, linewidth=0.1, lookup_colormap=lut) scene.add(line) - scene.add(actor.scalar_bar(lut, " ")) + scene.add(actor.scalar_bar(lookup_table=lut, title=" ")) report = window.analyze_scene(scene) @@ -413,7 +421,7 @@ def test_bundle_maps(): values = 100 * np.random.rand(nb_points) # values[:nb_points/2] = 0 - line = actor.streamtube(bundle, values, linewidth=0.1, lookup_colormap=lut) + line = actor.streamtube(bundle, colors=values, linewidth=0.1, lookup_colormap=lut) scene.add(line) # window.show(scene) @@ -425,7 +433,7 @@ def test_bundle_maps(): colors = np.random.rand(nb_points, 3) # values[:nb_points/2] = 0 - line = actor.line(bundle, colors, linewidth=2) + line = actor.line(bundle, colors=colors, linewidth=2) scene.add(line) # window.show(scene) @@ -439,8 +447,8 @@ def test_bundle_maps(): # try other input options for colors scene.clear() - actor.line(bundle, (1.0, 0.5, 0)) - actor.line(bundle, np.arange(len(bundle))) + actor.line(bundle, colors=(1.0, 0.5, 0)) + actor.line(bundle, colors=np.arange(len(bundle))) actor.line(bundle) colors = [np.random.rand(*b.shape) for b in bundle] actor.line(bundle, colors=colors) @@ -452,7 +460,7 @@ def test_odf_slicer(interactive=False): # vertices and faces of a sphere rather that needing # a specific type of sphere. We can use prim_sphere # as an alternative to get_sphere. - vertices, faces = prim_sphere("repulsion100", True) + vertices, faces = prim_sphere(name="repulsion100", gen_faces=True) sphere = Sphere() sphere.vertices = vertices sphere.faces = faces @@ -521,13 +529,13 @@ def test_odf_slicer(interactive=False): # Test that odf_slicer.display works properly scene.clear() scene.add(odf_actor) - scene.add(actor.axes((11, 11, 11))) + scene.add(actor.axes(scale=(11, 11, 11))) for i in range(11): - odf_actor.display(i, None, None) + odf_actor.display(x=i, y=None, z=None) if interactive: window.show(scene) for j in range(11): - odf_actor.display(None, j, None) + odf_actor.display(x=None, y=j, z=None) if interactive: window.show(scene) @@ -562,7 +570,7 @@ def test_odf_slicer(interactive=False): global_cm=True, ) - vertices2, faces2 = prim_sphere("repulsion200", True) + vertices2, faces2 = prim_sphere(name="repulsion200", gen_faces=True) sphere2 = Sphere() sphere2.vertices = vertices2 sphere2.faces = faces2 @@ -607,13 +615,13 @@ def test_peak_slicer(interactive=False): scene = window.Scene() peak_actor = actor.peak_slicer(peak_dirs) scene.add(peak_actor) - scene.add(actor.axes((11, 11, 11))) + scene.add(actor.axes(scale=(11, 11, 11))) if interactive: window.show(scene) scene.clear() scene.add(peak_actor) - scene.add(actor.axes((11, 11, 11))) + scene.add(actor.axes(scale=(11, 11, 11))) for k in range(11): peak_actor.display_extent(0, 10, 0, 10, k, k) @@ -621,13 +629,13 @@ def test_peak_slicer(interactive=False): peak_actor.display_extent(0, 10, j, j, 0, 10) for i in range(11): - peak_actor.display(i, None, None) + peak_actor.display(x=i, y=None, z=None) scene.rm_all() peak_actor_sym = actor.peak_slicer( peak_dirs, - peak_values, + peaks_values=peak_values, mask=None, affine=np.diag([3, 2, 1, 1]), colors=None, @@ -640,7 +648,7 @@ def test_peak_slicer(interactive=False): peak_actor_asym = actor.peak_slicer( peak_dirs, - peak_values, + peaks_values=peak_values, mask=None, affine=np.diag([3, 2, 1, 1]), colors=None, @@ -654,7 +662,7 @@ def test_peak_slicer(interactive=False): scene.add(peak_actor_sym) scene.add(peak_actor_asym) - scene.add(actor.axes((11, 11, 11))) + scene.add(actor.axes(scale=(11, 11, 11))) if interactive: window.show(scene) @@ -739,7 +747,7 @@ def test_tensor_slicer(interactive=False): mevals[..., :] = evals mevecs[..., :, :] = evecs - vertices, faces = prim_sphere("symmetric724", True) + vertices, faces = prim_sphere(name="symmetric724", gen_faces=True) sphere = Sphere() sphere.vertices = vertices sphere.faces = faces @@ -892,7 +900,7 @@ def test_points(interactive=False): def test_vector_text(interactive=False): npt.assert_raises(ExpiredDeprecationError, actor.label, "FURY Rocks") - text_actor = actor.vector_text("FURY Rocks", direction=None) + text_actor = actor.vector_text(text="FURY Rocks", direction=None) scene = window.Scene() scene.add(text_actor) @@ -904,35 +912,35 @@ def test_vector_text(interactive=False): if interactive: window.show(scene, reset_camera=False) - text_actor = actor.vector_text("FURY Rocks") + text_actor = actor.vector_text(text="FURY Rocks") npt.assert_equal(scene.GetActors().GetNumberOfItems(), 1) center = np.array(text_actor.GetCenter()) [assert_greater_equal(v, 0) for v in center] - text_actor_centered = actor.vector_text("FURY Rocks", align_center=True) + text_actor_centered = actor.vector_text(text="FURY Rocks", align_center=True) center = np.array(text_actor_centered.GetCenter()) npt.assert_equal(center, np.zeros(3)) - text_actor_rot_1 = actor.vector_text("FURY Rocks", direction=(1, 1, 1)) - text_actor_rot_2 = actor.vector_text("FURY Rocks", direction=(1, 1, 0)) + text_actor_rot_1 = actor.vector_text(text="FURY Rocks", direction=(1, 1, 1)) + text_actor_rot_2 = actor.vector_text(text="FURY Rocks", direction=(1, 1, 0)) center_1 = text_actor_rot_1.GetCenter() center_2 = text_actor_rot_2.GetCenter() assert_not_equal(np.linalg.norm(center_1), np.linalg.norm(center_2)) # test centered - text_centered = actor.vector_text("FURY Rocks", align_center=True) + text_centered = actor.vector_text(text="FURY Rocks", align_center=True) center_3 = text_centered.GetCenter() npt.assert_almost_equal(np.linalg.norm(center_3), 0.0) text_extruded = actor.vector_text( - "FURY Rocks", scale=(0.2, 0.2, 0.2), extrusion=1.123 + text="FURY Rocks", scale=(0.2, 0.2, 0.2), extrusion=1.123 ) z_max = text_extruded.GetBounds()[-1] npt.assert_almost_equal(z_max, 1.123) text_extruded_centered = actor.vector_text( - "FURY Rocks", + text="FURY Rocks", scale=(0.2, 0.2, 0.2), direction=None, align_center=True, @@ -1253,16 +1261,31 @@ def test_container(): def test_grid(_interactive=False): vol1 = np.zeros((100, 100, 100)) vol1[25:75, 25:75, 25:75] = 100 - contour_actor1 = actor.contour_from_roi(vol1, np.eye(4), (1.0, 0, 0), 1.0) + contour_actor1 = actor.contour_from_roi( + vol1, + affine=np.eye(4), + color=(1.0, 0, 0), + opacity=1.0, + ) vol2 = np.zeros((100, 100, 100)) vol2[25:75, 25:75, 25:75] = 100 - contour_actor2 = actor.contour_from_roi(vol2, np.eye(4), (1.0, 0.5, 0), 1.0) + contour_actor2 = actor.contour_from_roi( + vol2, + affine=np.eye(4), + color=(1.0, 0.5, 0), + opacity=1.0, + ) vol3 = np.zeros((100, 100, 100)) vol3[25:75, 25:75, 25:75] = 100 - contour_actor3 = actor.contour_from_roi(vol3, np.eye(4), (1.0, 0.5, 0.5), 1.0) + contour_actor3 = actor.contour_from_roi( + vol3, + affine=np.eye(4), + color=(1.0, 0.5, 0.5), + opacity=1.0, + ) scene = window.Scene() actors = [] @@ -1303,11 +1326,11 @@ def test_grid(_interactive=False): scene.add(container) - scene.projection("orthogonal") + scene.projection(proj_type="orthogonal") counter = itertools.count() - show_m = window.ShowManager(scene) + show_m = window.ShowManager(scene=scene) def timer_callback(_obj, _event): nonlocal counter @@ -1329,7 +1352,7 @@ def timer_callback(_obj, _event): scene.rm_all() counter = itertools.count() - show_m = window.ShowManager(scene) + show_m = window.ShowManager(scene=scene) # show the grid with the captions container = grid( @@ -1461,8 +1484,8 @@ def test_matplotlib_figure(): arr = matplotlib_figure_to_numpy(fig, dpi=500, transparent=True) plt.close("all") - fig_actor = actor.figure(arr, "cubic") - fig_actor2 = actor.figure(arr, "cubic") + fig_actor = actor.figure(arr, interpolation="cubic") + fig_actor2 = actor.figure(arr, interpolation="cubic") scene = window.Scene() scene.background((1, 1, 1.0)) @@ -1473,7 +1496,7 @@ def test_matplotlib_figure(): ax_actor.SetPosition(-50, 500, -800) fig_actor2.SetPosition(500, 800, -400) display = window.snapshot( - scene, "test_mpl.png", order_transparent=False, offscreen=True + scene, fname="test_mpl.png", order_transparent=False, offscreen=True ) _ = window.analyze_snapshot( display, bg_color=(255, 255, 255.0), colors=[(31, 119, 180)], find_objects=False @@ -1643,7 +1666,13 @@ def test_sdf_actor(interactive=False): scales = [1, 2, 3, 4] primitive = ["sphere", "ellipsoid", "torus", "capsule"] - sdf_actor = actor.sdf(centers, directions, colors, primitive, scales) + sdf_actor = actor.sdf( + centers, + directions=directions, + colors=colors, + primitives=primitive, + scales=scales, + ) scene.add(sdf_actor) scene.add(actor.axes()) if interactive: @@ -1656,7 +1685,13 @@ def test_sdf_actor(interactive=False): # Draw 3 spheres as the primitive type is str scene.clear() primitive = "sphere" - sdf_actor = actor.sdf(centers, directions, colors, primitive, scales) + sdf_actor = actor.sdf( + centers, + directions=directions, + colors=colors, + primitives=primitive, + scales=scales, + ) scene.add(sdf_actor) scene.add(actor.axes()) if interactive: @@ -1671,7 +1706,13 @@ def test_sdf_actor(interactive=False): scene.clear() primitive = ["sphere"] with npt.assert_warns(UserWarning): - sdf_actor = actor.sdf(centers, directions, colors, primitive, scales) + sdf_actor = actor.sdf( + centers, + directions=directions, + colors=colors, + primitives=primitive, + scales=scales, + ) scene.add(sdf_actor) scene.add(actor.axes()) @@ -1687,7 +1728,13 @@ def test_sdf_actor(interactive=False): scene.clear() primitive = ["sphere", "ellipsoid"] with npt.assert_warns(UserWarning): - sdf_actor = actor.sdf(centers, directions, colors, primitive, scales) + sdf_actor = actor.sdf( + centers, + directions=directions, + colors=colors, + primitives=primitive, + scales=scales, + ) scene.add(sdf_actor) scene.add(actor.axes()) diff --git a/fury/tests/test_colormap.py b/fury/tests/test_colormap.py index 14b79a1177..653fe271ec 100644 --- a/fury/tests/test_colormap.py +++ b/fury/tests/test_colormap.py @@ -71,8 +71,20 @@ def test_line_colors(): def test_create_colormap(): value = np.arange(25) - npt.assert_raises(ValueError, colormap.create_colormap, value.reshape((5, 5))) - npt.assert_raises(AttributeError, colormap.create_colormap, value, name="fake") + npt.assert_raises( + ValueError, + colormap.create_colormap, + value.reshape((5, 5)), + name="plasma", + auto=True, + ) + npt.assert_raises( + AttributeError, + colormap.create_colormap, + value, + name="fake", + auto=True, + ) npt.assert_warns( PendingDeprecationWarning, colormap.create_colormap, @@ -163,14 +175,16 @@ def test_color_converters(): illuminant = "D65" observer = "2" expected_lab = np.array([31.57976662, -1.86550104, -17.84845331]) - lab_color = colormap.rgb2lab(color, illuminant, observer) - rgb_color = colormap.lab2rgb(expected_lab, illuminant, observer) + lab_color = colormap.rgb2lab(color, illuminant=illuminant, observer=observer) + rgb_color = colormap.lab2rgb(expected_lab, illuminant=illuminant, observer=observer) npt.assert_almost_equal(lab_color, expected_lab) npt.assert_almost_equal(rgb_color, color) for color in colors: - lab_color = colormap.rgb2lab(color, illuminant, observer) - rgb_from_lab_color = colormap.lab2rgb(lab_color, illuminant, observer) + lab_color = colormap.rgb2lab(color, illuminant=illuminant, observer=observer) + rgb_from_lab_color = colormap.lab2rgb( + lab_color, illuminant=illuminant, observer=observer + ) npt.assert_almost_equal(rgb_from_lab_color, color) # testing rgb2hsv and hsv2rgb diff --git a/fury/tests/test_decorators.py b/fury/tests/test_decorators.py index 914424484a..7e62b1fff8 100644 --- a/fury/tests/test_decorators.py +++ b/fury/tests/test_decorators.py @@ -2,11 +2,13 @@ import numpy.testing as npt -from fury.decorators import doctest_skip_parser +import fury +from fury.decorators import doctest_skip_parser, warn_on_args_to_kwargs from fury.testing import assert_true HAVE_AMODULE = False HAVE_BMODULE = True +FURY_CURRENT_VERSION = fury.__version__ def test_skipper(): @@ -49,3 +51,45 @@ def f(): del HAVE_AMODULE f.__doc__ = docstring npt.assert_raises(NameError, doctest_skip_parser, f) + + +def test_warn_on_args_to_kwargs(): + @warn_on_args_to_kwargs() + def func(a, b, *, c, d=4, e=5): + return a + b + c + d + e + + # if FURY_CURRENT_VERSION is less than from_version + fury.__version__ = "0.0.0" + npt.assert_equal(func(1, 2, 3, 4, 5), 15) + npt.assert_equal(func(1, 2, c=3, d=4, e=5), 15) + npt.assert_raises(TypeError, func, 1, 3) + + # if FURY_CURRENT_VERSION is greater than until_version + fury.__version__ = "0.12.0" + npt.assert_equal(func(1, 2, c=3, d=4, e=5), 15) + npt.assert_equal(func(1, 2, c=3, d=5), 16) + npt.assert_equal(func(1, 2, c=3), 15) + npt.assert_raises(TypeError, func, 1, 3, 4) + npt.assert_raises(TypeError, func, 1, 3) + + # if FURY_CURRENT_VERSION is less than from_version + fury.__version__ = "0.10.0" + npt.assert_equal(func(1, 2, c=3, d=4, e=5), 15) + npt.assert_equal(func(1, 2, c=3, d=5), 16) + with npt.assert_warns(UserWarning): + npt.assert_equal(func(1, 2, 3, 4, 5), 15) + with npt.assert_warns(UserWarning): + npt.assert_equal(func(1, 2, 4), 16) + npt.assert_raises(TypeError, func, 1, 3) + + # if FURY_CURRENT_VERSION is equal to from_version + fury.__version__ = "0.11.0" + with npt.assert_warns(UserWarning): + npt.assert_equal(func(1, 2, 3, 6), 17) + with npt.assert_warns(UserWarning): + npt.assert_equal(func(1, 2, 10), 22) + npt.assert_raises(TypeError, func, 1, 2, e=10) + npt.assert_raises(TypeError, func, 1, 2, d=10) + npt.assert_raises(TypeError, func, 1, 3) + + fury.__version__ = FURY_CURRENT_VERSION diff --git a/fury/tests/test_deprecator.py b/fury/tests/test_deprecator.py index ca1bacad89..88f261eab0 100644 --- a/fury/tests/test_deprecator.py +++ b/fury/tests/test_deprecator.py @@ -108,20 +108,20 @@ class CustomError(Exception): dec = deprecate_with_version func = dec("foo")(func_no_doc) - with clear_and_catch_warnings(modules=[my_mod]) as w: + with clear_and_catch_warnings(record=True, modules=[my_mod]) as w: warnings.simplefilter("always") npt.assert_equal(func(), None) npt.assert_equal(len(w), 1) assert_true(w[0].category is DeprecationWarning) npt.assert_equal(func.__doc__, "foo\n") func = dec("foo")(func_doc) - with clear_and_catch_warnings(modules=[my_mod]) as w: + with clear_and_catch_warnings(record=True, modules=[my_mod]) as w: warnings.simplefilter("always") npt.assert_equal(func(1), None) npt.assert_equal(len(w), 1) npt.assert_equal(func.__doc__, "A docstring\n\nfoo\n") func = dec("foo")(func_doc_long) - with clear_and_catch_warnings(modules=[my_mod]) as w: + with clear_and_catch_warnings(record=True, modules=[my_mod]) as w: warnings.simplefilter("always") npt.assert_equal(func(1, 2), None) npt.assert_equal(len(w), 1) @@ -130,12 +130,12 @@ class CustomError(Exception): # Try some since and until versions func = dec("foo", "0.2")(func_no_doc) npt.assert_equal(func.__doc__, "foo\n\n* deprecated from version: 0.2\n") - with clear_and_catch_warnings(modules=[my_mod]) as w: + with clear_and_catch_warnings(record=True, modules=[my_mod]) as w: warnings.simplefilter("always") npt.assert_equal(func(), None) npt.assert_equal(len(w), 1) func = dec("foo", until="10.6")(func_no_doc) - with clear_and_catch_warnings(modules=[my_mod]) as w: + with clear_and_catch_warnings(record=True, modules=[my_mod]) as w: warnings.simplefilter("always") npt.assert_equal(func(), None) npt.assert_equal(len(w), 1) @@ -168,14 +168,14 @@ class CustomError(Exception): # Check different warnings and errors func = dec("foo", warn_class=UserWarning)(func_no_doc) - with clear_and_catch_warnings(modules=[my_mod]) as w: + with clear_and_catch_warnings(record=True, modules=[my_mod]) as w: warnings.simplefilter("always") npt.assert_equal(func(), None) npt.assert_equal(len(w), 1) assert_true(w[0].category is UserWarning) func = dec("foo", error_class=CustomError)(func_no_doc) - with clear_and_catch_warnings(modules=[my_mod]) as w: + with clear_and_catch_warnings(record=True, modules=[my_mod]) as w: warnings.simplefilter("always") npt.assert_equal(func(), None) npt.assert_equal(len(w), 1) diff --git a/fury/tests/test_gltf.py b/fury/tests/test_gltf.py index 8e9febe2ff..14e22ad9ca 100644 --- a/fury/tests/test_gltf.py +++ b/fury/tests/test_gltf.py @@ -129,14 +129,14 @@ def test_export_gltf(): cube = actor.cube(np.add(centers, np.array([2, 0, 0])), colors=colors) scene.add(cube) - export_scene(scene, "test.gltf") + export_scene(scene, filename="test.gltf") gltf_obj = glTF("test.gltf") actors = gltf_obj.actors() npt.assert_equal(len(actors), 1) sphere = actor.sphere(centers, np.array([1, 0, 0]), use_primitive=False) scene.add(sphere) - export_scene(scene, "test.gltf") + export_scene(scene, filename="test.gltf") gltf_obj = glTF("test.gltf") actors = gltf_obj.actors() @@ -149,7 +149,7 @@ def test_export_gltf(): focal_point=(0.0, 0.0, 0.0), view_up=(0.0, 0.0, 1.0), ) - export_scene(scene, "test.gltf") + export_scene(scene, filename="test.gltf") gltf_obj = glTF("test.gltf") actors = gltf_obj.actors() @@ -167,7 +167,7 @@ def test_export_gltf(): gltf_obj = glTF(filename) box_actor = gltf_obj.actors() scene.add(*box_actor) - export_scene(scene, "test.gltf") + export_scene(scene, filename="test.gltf") scene.clear() gltf_obj = glTF("test.gltf") @@ -192,7 +192,7 @@ def test_simple_animation(): animation = gltf_obj.main_animation() timeline.add_animation(animation) scene = window.Scene() - showm = window.ShowManager(scene, size=(900, 768)) + showm = window.ShowManager(scene=scene, size=(900, 768)) showm.initialize() scene.add(timeline) @@ -259,7 +259,7 @@ def test_skinning(): npt.assert_equal(len(ibms), 2) scene = window.Scene() - showm = window.ShowManager(scene, size=(900, 768)) + showm = window.ShowManager(scene=scene, size=(900, 768)) showm.initialize() scene.add(timeline) @@ -333,7 +333,7 @@ def test_morphing(): gltf_obj.update_morph(anim_1) scene = window.Scene() - showm = window.ShowManager(scene, size=(900, 768)) + showm = window.ShowManager(scene=scene, size=(900, 768)) showm.initialize() timeline_1 = Timeline() diff --git a/fury/tests/test_interactor.py b/fury/tests/test_interactor.py index 33c6132ce7..5608bde622 100644 --- a/fury/tests/test_interactor.py +++ b/fury/tests/test_interactor.py @@ -24,7 +24,10 @@ def test_custom_interactor_style_events(recording=False): # in steps so that the widgets can be added properly interactor_style = interactor.CustomInteractorStyle() show_manager = window.ShowManager( - scene, size=(800, 800), reset_camera=False, interactor_style=interactor_style + scene=scene, + size=(800, 800), + reset_camera=False, + interactor_style=interactor_style, ) # Create a cursor, a circle that will follow the mouse. @@ -56,8 +59,8 @@ def follow_mouse(iren, obj): np.array([[-1, 1, 0.0], [1, 1, 0.0]]), ] colors = np.array([[1.0, 0.0, 0.0], [0.3, 0.7, 0.0]]) - tube1 = actor.streamtube([lines[0]], colors[0]) - tube2 = actor.streamtube([lines[1]], colors[1]) + tube1 = actor.streamtube([lines[0]], colors=colors[0]) + tube2 = actor.streamtube([lines[1]], colors=colors[1]) scene.add(tube1) scene.add(tube2) @@ -157,8 +160,8 @@ def test_double_click_events(recording=False): cube = actor.cube( np.array([(0, 0, 0)]), - np.array([(0.16526678, 0.0186237, 0.01906076)]), - (1, 1, 1), + directions=np.array([(0.16526678, 0.0186237, 0.01906076)]), + colors=(1, 1, 1), scales=3, ) diff --git a/fury/tests/test_io.py b/fury/tests/test_io.py index 277a25e2e9..84d0c679e7 100644 --- a/fury/tests/test_io.py +++ b/fury/tests/test_io.py @@ -44,8 +44,22 @@ def test_save_and_load_polydata(): npt.assert_array_equal(data, out_data) - npt.assert_raises(IOError, save_polydata, PolyData(), "test.vti") - npt.assert_raises(IOError, save_polydata, PolyData(), "test.obj") + npt.assert_raises( + IOError, + save_polydata, + PolyData(), + "test.vti", + binary=False, + color_array_name=None, + ) + npt.assert_raises( + IOError, + save_polydata, + PolyData(), + "test.obj", + binary=False, + color_array_name=None, + ) npt.assert_raises(IOError, load_polydata, "test.vti") npt.assert_raises(FileNotFoundError, load_polydata, "does-not-exist.obj") @@ -136,21 +150,56 @@ def test_save_load_image(): data[..., 0], out_image[..., 0], decimal=0 ) - npt.assert_raises(IOError, load_image, invalid_link) - npt.assert_raises(IOError, load_image, "test.vtk") - npt.assert_raises(IOError, load_image, "test.vtk", use_pillow=False) npt.assert_raises( - IOError, save_image, np.random.randint(0, 255, size=(50, 3)), "test.vtk" + IOError, + load_image, + invalid_link, + as_vtktype=False, + use_pillow=True, + ) + npt.assert_raises( + IOError, + load_image, + "test.vtk", + as_vtktype=False, + use_pillow=True, + ) + npt.assert_raises( + IOError, + load_image, + "test.vtk", + as_vtktype=False, + use_pillow=False, ) npt.assert_raises( IOError, save_image, np.random.randint(0, 255, size=(50, 3)), "test.vtk", + compression_quality=75, + compression_type="deflation", + use_pillow=True, + dpi=(72, 72), + ) + npt.assert_raises( + IOError, + save_image, + np.random.randint(0, 255, size=(50, 3)), + "test.vtk", + compression_quality=75, + compression_type="deflation", use_pillow=False, + dpi=(72, 72), ) npt.assert_raises( - IOError, save_image, np.random.randint(0, 255, size=(50, 3, 1, 1)), "test.png" + IOError, + save_image, + np.random.randint(0, 255, size=(50, 3, 1, 1)), + "test.png", + compression_quality=75, + compression_type="deflation", + use_pillow=True, + dpi=(72, 72), ) compression_type = [None, "bits", "random"] @@ -221,7 +270,13 @@ def test_load_cubemap_texture(): save_image(data, fname_path) fnames = [fname_path] * 5 - npt.assert_raises(IOError, load_cubemap_texture, fnames) + npt.assert_raises( + IOError, + load_cubemap_texture, + fnames, + interpolate_on=True, + mipmap_on=True, + ) fnames = [fname_path] * 6 texture = load_cubemap_texture(fnames) @@ -234,7 +289,13 @@ def test_load_cubemap_texture(): ) fnames = [fname_path] * 7 - npt.assert_raises(IOError, load_cubemap_texture, fnames) + npt.assert_raises( + IOError, + load_cubemap_texture, + fnames, + interpolate_on=True, + mipmap_on=True, + ) def test_load_sprite_sheet(): diff --git a/fury/tests/test_layout.py b/fury/tests/test_layout.py index e7480b46c6..48f3b0ce38 100644 --- a/fury/tests/test_layout.py +++ b/fury/tests/test_layout.py @@ -46,11 +46,17 @@ def get_default_cubes( cube_first_scale, cube_second_scale = scales cube_first = actor.cube( - cube_first_center, cube_first_direction, cube_first_color, cube_first_scale + cube_first_center, + directions=cube_first_direction, + colors=cube_first_color, + scales=cube_first_scale, ) cube_second = actor.cube( - cube_second_center, cube_second_direction, cube_second_color, cube_second_scale + cube_second_center, + directions=cube_second_direction, + colors=cube_second_color, + scales=cube_second_scale, ) return (cube_first, cube_second) @@ -263,7 +269,11 @@ def test_x_layout(): negative_x_layout = XLayout(direction="x-") with npt.assert_raises(ValueError): - _ = XLayout(direction="Invalid direction") + _ = XLayout( + direction="Invalid direction", + cell_padding=0, + cell_shape="rect", + ) positive_positions = positive_x_layout.compute_positions(actors) negative_positions = negative_x_layout.compute_positions(actors) @@ -300,7 +310,11 @@ def test_y_layout(): negative_y_layout = YLayout(direction="y-") with npt.assert_raises(ValueError): - _ = YLayout(direction="Invalid direction") + _ = YLayout( + direction="Invalid direction", + cell_padding=0, + cell_shape="rect", + ) positive_positions = positive_y_layout.compute_positions(actors) negative_positions = negative_y_layout.compute_positions(actors) @@ -338,7 +352,11 @@ def test_z_layout(): diagonal_z_layout = ZLayout(direction="z+", cell_shape="diagonal") with npt.assert_raises(ValueError): - _ = XLayout(direction="Invalid direction") + _ = XLayout( + direction="Invalid direction", + cell_padding=0, + cell_shape="rect", + ) with npt.assert_raises(ValueError): invalid_shape_layout = ZLayout(direction="z+", cell_shape="Invalid Shape") diff --git a/fury/tests/test_molecular.py b/fury/tests/test_molecular.py index f3ab321163..2a1aa50993 100644 --- a/fury/tests/test_molecular.py +++ b/fury/tests/test_molecular.py @@ -10,12 +10,12 @@ def test_periodic_table(): npt.assert_equal(table.atomic_number("C"), 6) npt.assert_equal(table.element_name(7), "Nitrogen") npt.assert_equal(table.atomic_symbol(8), "O") - npt.assert_allclose(table.atomic_radius(1, "VDW"), 1.2, 0.1, 0) - npt.assert_allclose(table.atomic_radius(6, "Covalent"), 0.75, 0.1, 0) + npt.assert_allclose(table.atomic_radius(1, radius_type="VDW"), 1.2, 0.1, 0) + npt.assert_allclose(table.atomic_radius(6, radius_type="Covalent"), 0.75, 0.1, 0) npt.assert_array_almost_equal(table.atom_color(1), np.array([1, 1, 1])) # Test errors - npt.assert_raises(ValueError, table.atomic_radius, 4, "test") + npt.assert_raises(ValueError, table.atomic_radius, 4, radius_type="test") def get_default_molecular_info(all_info=False): @@ -64,17 +64,41 @@ def test_molecule_creation(): # Test errors elements = np.array([6, 6]) - npt.assert_raises(ValueError, mol.Molecule, elements, atom_coords) + npt.assert_raises( + ValueError, + mol.Molecule, + atomic_numbers=elements, + coords=atom_coords, + atom_names=None, + model=None, + residue_seq=None, + chain=None, + sheet=None, + helix=None, + is_hetatm=None, + ) elements = list(range(8)) - npt.assert_raises(ValueError, mol.Molecule, elements, atom_coords) + npt.assert_raises( + ValueError, + mol.Molecule, + atomic_numbers=elements, + coords=atom_coords, + atom_names=None, + model=None, + residue_seq=None, + chain=None, + sheet=None, + helix=None, + is_hetatm=None, + ) def test_add_atom_bond_creation(): molecule = mol.Molecule() mol.add_atom(molecule, 6, 0, 0, 0) mol.add_atom(molecule, 6, 1, 0, 0) - mol.add_bond(molecule, 0, 1, 1) + mol.add_bond(molecule, 0, 1, bond_order=1) npt.assert_equal(molecule.total_num_bonds, 1) npt.assert_equal(molecule.total_num_atoms, 2) @@ -116,7 +140,7 @@ def test_bond_order(): molecule = mol.Molecule() mol.add_atom(molecule, 6, 0, 0, 0) mol.add_atom(molecule, 6, 1, 0, 0) - mol.add_bond(molecule, 0, 1, 3) + mol.add_bond(molecule, 0, 1, bond_order=3) npt.assert_equal(mol.get_bond_order(molecule, 0), 3) # Testing set_bond_order @@ -131,7 +155,7 @@ def test_deep_copy_molecule(): molecule1 = mol.Molecule() mol.add_atom(molecule1, 6, 0, 0, 0) mol.add_atom(molecule1, 6, 1, 0, 0) - mol.add_bond(molecule1, 0, 1, 1) + mol.add_bond(molecule1, 0, 1, bond_order=1) molecule2 = mol.Molecule() mol.deep_copy_molecule(molecule2, molecule1) npt.assert_equal(molecule2.total_num_bonds, 1) @@ -140,14 +164,14 @@ def test_deep_copy_molecule(): def test_compute_bonding(): atomic_numbers, atom_coords = get_default_molecular_info() - molecule = mol.Molecule(atomic_numbers, atom_coords) + molecule = mol.Molecule(atomic_numbers=atomic_numbers, coords=atom_coords) mol.compute_bonding(molecule) npt.assert_equal(molecule.total_num_bonds, 7) def test_sphere_cpk(interactive=False): atomic_numbers, atom_coords = get_default_molecular_info() - molecule = mol.Molecule(atomic_numbers, atom_coords) + molecule = mol.Molecule(atomic_numbers=atomic_numbers, coords=atom_coords) table = mol.PTable() colormodes = ["discrete", "single"] colors = np.array( @@ -159,7 +183,7 @@ def test_sphere_cpk(interactive=False): ) scene = window.Scene() for i, colormode in enumerate(colormodes): - test_actor = mol.sphere_cpk(molecule, colormode) + test_actor = mol.sphere_cpk(molecule, colormode=colormode) scene.add(test_actor) scene.reset_camera() @@ -176,7 +200,7 @@ def test_sphere_cpk(interactive=False): scene.clear() # Testing warnings - npt.assert_warns(UserWarning, mol.sphere_cpk, molecule, "multiple") + npt.assert_warns(UserWarning, mol.sphere_cpk, molecule, colormode="multiple") def test_bstick(interactive=False): @@ -185,9 +209,17 @@ def test_bstick(interactive=False): mol.add_atom(molecule, 6, 2, 0, 0) # Test errors for inadequate bonding data - npt.assert_raises(ValueError, mol.ball_stick, molecule) + npt.assert_raises( + ValueError, + mol.ball_stick, + molecule, + colormode="discrete", + atom_scale_factor=0.3, + bond_thickness=0.1, + multiple_bonds=True, + ) - mol.add_bond(molecule, 0, 1, 1) + mol.add_bond(molecule, 0, 1, bond_order=1) colormodes = ["discrete", "single"] atom_scale_factor = [0.3, 0.4] bond_thickness = [0.1, 0.2] @@ -204,10 +236,10 @@ def test_bstick(interactive=False): for i, colormode in enumerate(colormodes): test_actor = mol.ball_stick( molecule, - colormode, - atom_scale_factor[i], - bond_thickness[i], - multiple_bonds[i], + colormode=colormode, + atom_scale_factor=atom_scale_factor[i], + bond_thickness=bond_thickness[i], + multiple_bonds=multiple_bonds[i], ) scene.add(test_actor) scene.reset_camera() @@ -224,7 +256,15 @@ def test_bstick(interactive=False): scene.clear() # Testing warnings - npt.assert_warns(UserWarning, mol.ball_stick, molecule, "multiple") + npt.assert_warns( + UserWarning, + mol.ball_stick, + molecule, + colormode="multiple", + atom_scale_factor=0.3, + bond_thickness=0.1, + multiple_bonds=True, + ) def test_stick(interactive=False): @@ -233,8 +273,10 @@ def test_stick(interactive=False): mol.add_atom(molecule, 6, 2, 0, 0) # Test errors for inadequate bonding data - npt.assert_raises(ValueError, mol.stick, molecule) - mol.add_bond(molecule, 0, 1, 1) + npt.assert_raises( + ValueError, mol.stick, molecule, colormode="discrete", bond_thickness=0.1 + ) + mol.add_bond(molecule, 0, 1, bond_order=1) colormodes = ["discrete", "single"] bond_thickness = [0.1, 0.12] @@ -248,7 +290,11 @@ def test_stick(interactive=False): ) scene = window.Scene() for i, colormode in enumerate(colormodes): - test_actor = mol.stick(molecule, colormode, bond_thickness[i]) + test_actor = mol.stick( + molecule, + colormode=colormode, + bond_thickness=bond_thickness[i], + ) scene.add(test_actor) scene.reset_camera() scene.reset_clipping_range() @@ -264,7 +310,9 @@ def test_stick(interactive=False): scene.clear() # Testing warnings - npt.assert_warns(UserWarning, mol.stick, molecule, "multiple") + npt.assert_warns( + UserWarning, mol.stick, molecule, colormode="multiple", bond_thickness=0.1 + ) def test_ribbon(interactive=False): @@ -337,18 +385,22 @@ def test_ribbon(interactive=False): helix = secondary_structure sheet = [] molecule = mol.Molecule( - elements, - atom_coords, - atom_names, - model, - residue_seq, - chain, - sheet, - helix, - is_hetatm, + atomic_numbers=elements, + coords=atom_coords, + atom_names=atom_names, + model=model, + residue_seq=residue_seq, + chain=chain, + sheet=sheet, + helix=helix, + is_hetatm=is_hetatm, ) test_actor = mol.ribbon(molecule) - scene.set_camera((28, 113, 74), (34, 106, 70), (-0.37, 0.29, -0.88)) + scene.set_camera( + position=(28, 113, 74), + focal_point=(34, 106, 70), + view_up=(-0.37, 0.29, -0.88), + ) scene.add(test_actor) scene.reset_camera() scene.reset_clipping_range() @@ -367,7 +419,7 @@ def test_bounding_box(interactive=False): molecule = mol.Molecule() mol.add_atom(molecule, 6, 0, 0, 0) mol.add_atom(molecule, 6, 1, 1, 1) - mol.add_bond(molecule, 0, 1, 1) + mol.add_bond(molecule, 0, 1, bond_order=1) molecule_actor = mol.stick(molecule) test_box = mol.bounding_box(molecule, colors=(0, 1, 1), linewidth=0.1) diff --git a/fury/tests/test_primitive.py b/fury/tests/test_primitive.py index baac44a2b6..9325eaa34a 100644 --- a/fury/tests/test_primitive.py +++ b/fury/tests/test_primitive.py @@ -24,7 +24,7 @@ def test_vertices_primitives(): npt.assert_equal(vertices.min(), e_min) npt.assert_equal(vertices.max(), e_max) - vertices, _ = fp.prim_star(3) + vertices, _ = fp.prim_star(dim=3) npt.assert_equal(vertices.shape, (12, 3)) npt.assert_almost_equal(abs(np.mean(vertices)), 0.11111111) npt.assert_equal(vertices.min(), -3) @@ -108,7 +108,7 @@ def test_spheres_primitives(): ] for name, nb_verts, nb_triangles in l_primitives: - verts, faces = fp.prim_sphere(name) + verts, faces = fp.prim_sphere(name=name) npt.assert_equal(verts.shape, (nb_verts, 3)) npt.assert_almost_equal(np.mean(verts), 0) npt.assert_equal(len(faces), nb_triangles) @@ -116,7 +116,14 @@ def test_spheres_primitives(): list(set(np.concatenate(faces, axis=None))), list(range(len(verts))) ) - npt.assert_raises(ValueError, fp.prim_sphere, "sym362") + npt.assert_raises( + ValueError, + fp.prim_sphere, + name="sym362", + gen_faces=False, + phi=None, + theta=None, + ) l_primitives = [ (10, 10, 82, 160), @@ -138,7 +145,7 @@ def test_spheres_primitives(): def test_superquadric_primitives(): # test default, should be like a sphere 362 sq_verts, sq_faces = fp.prim_superquadric() - s_verts, s_faces = fp.prim_sphere("symmetric362") + s_verts, s_faces = fp.prim_sphere(name="symmetric362") npt.assert_equal(sq_verts.shape, s_verts.shape) npt.assert_equal(sq_faces.shape, s_faces.shape) @@ -211,7 +218,7 @@ def test_cone_primitive(): ) # test warnings - npt.assert_raises(ValueError, fp.prim_cone, 0.5, 1, 2) + npt.assert_raises(ValueError, fp.prim_cone, radius=0.5, height=1, sectors=2) def test_repeat_primitive(): @@ -223,9 +230,7 @@ def test_repeat_primitive(): for i in [-1, 1]: dirs = dirs * i - res = fp.repeat_primitive( - vertices=verts, faces=faces, centers=centers, directions=dirs, colors=colors - ) + res = fp.repeat_primitive(verts, faces, centers, directions=dirs, colors=colors) big_verts, big_faces, big_colors, big_centers = res @@ -263,8 +268,8 @@ def test_repeat_primitive_function(): phi_theta = np.array([[1, 1], [1, 2], [2, 1]]) _ = fp.repeat_primitive_function( - func=fp.prim_superquadric, - centers=centers, + fp.prim_superquadric, + centers, func_args=phi_theta, directions=dirs, colors=colors, diff --git a/fury/tests/test_stream.py b/fury/tests/test_stream.py index 5db6a05dac..af2cf31b0e 100644 --- a/fury/tests/test_stream.py +++ b/fury/tests/test_stream.py @@ -56,7 +56,7 @@ def test(use_raw_array, ms_stream=16): scene = window.Scene() scene.add(actors) showm = window.ShowManager( - scene, + scene=scene, reset_camera=False, size=(width_0, height_0), order_transparent=False, @@ -108,7 +108,7 @@ def test_pillow(): scene = window.Scene() scene.add(actors) showm = window.ShowManager( - scene, + scene=scene, reset_camera=False, size=(width_0, height_0), order_transparent=False, @@ -165,7 +165,7 @@ def test_rtc_video_stream_whitout_cython(loop: asyncio.AbstractEventLoop): scene = window.Scene() scene.add(actors) showm = window.ShowManager( - scene, + scene=scene, reset_camera=False, size=(width_0, height_0), order_transparent=False, @@ -212,7 +212,7 @@ def test(use_raw_array, ms_stream=16): scene = window.Scene() scene.add(actors) showm = window.ShowManager( - scene, + scene=scene, reset_camera=False, size=(width_0, height_0), order_transparent=False, @@ -275,7 +275,7 @@ def test(use_raw_array, ms_stream=16, whithout_iren_start=False): scene = window.Scene() scene.add(actors) showm = window.ShowManager( - scene, + scene=scene, reset_camera=False, size=(width_0, height_0), order_transparent=False, @@ -314,7 +314,7 @@ def test_stream_client_resize(): scene = window.Scene() scene.add(actors) showm = window.ShowManager( - scene, + scene=scene, reset_camera=False, size=(width_0, height_0), order_transparent=False, @@ -360,7 +360,7 @@ async def test(use_raw_array, ms_stream=16): scene = window.Scene() scene.add(actors) showm = window.ShowManager( - scene, + scene=scene, reset_camera=False, size=(width_0, height_0), order_transparent=False, @@ -448,7 +448,7 @@ def test(use_raw_array, ms_stream, whitouth_iren_start): scene = window.Scene() scene.add(actors) - showm = window.ShowManager(scene, size=(width_0, height_0)) + showm = window.ShowManager(scene=scene, size=(width_0, height_0)) stream = FuryStreamClient( showm, use_raw_array=use_raw_array, whithout_iren_start=whitouth_iren_start @@ -734,7 +734,7 @@ def test(use_raw_array): scene = window.Scene() scene.add(actors) showm = window.ShowManager( - scene, + scene=scene, reset_camera=False, size=(width_0, height_0), order_transparent=False, @@ -790,7 +790,7 @@ def test_widget(): scene = window.Scene() scene.add(actors) showm = window.ShowManager( - scene, + scene=scene, reset_camera=False, size=(width_0, height_0), order_transparent=False, diff --git a/fury/tests/test_testing.py b/fury/tests/test_testing.py index 39aae8bf72..4165313537 100644 --- a/fury/tests/test_testing.py +++ b/fury/tests/test_testing.py @@ -1,5 +1,6 @@ """Testing file unittest.""" +import operator import sys import warnings @@ -48,7 +49,9 @@ def _add_to_scene(self, _scene): simple_ui = SimplestUI() current_size = (900, 600) scene = window.Scene() - show_manager = window.ShowManager(scene, size=current_size, title="FURY GridUI") + show_manager = window.ShowManager( + scene=scene, size=current_size, title="FURY GridUI" + ) scene.add(simple_ui) event_counter = ft.EventCounter() event_counter.monitor(simple_ui) @@ -69,14 +72,26 @@ def foo(): def test_assert(): - npt.assert_raises(AssertionError, ft.assert_false, True) - npt.assert_raises(AssertionError, ft.assert_true, False) - npt.assert_raises(AssertionError, ft.assert_less, 2, 1) - npt.assert_raises(AssertionError, ft.assert_less_equal, 2, 1) - npt.assert_raises(AssertionError, ft.assert_greater, 1, 2) - npt.assert_raises(AssertionError, ft.assert_greater_equal, 1, 2) - npt.assert_raises(AssertionError, ft.assert_not_equal, 5, 5) - npt.assert_raises(AssertionError, ft.assert_operator, 2, 1) + npt.assert_raises( + AssertionError, ft.assert_false, True, msg="True is not false", op=operator.eq + ) + npt.assert_raises( + AssertionError, ft.assert_true, False, msg="False is not true", op=operator.eq + ) + npt.assert_raises( + AssertionError, ft.assert_less, 2, 1, msg="{0} < {1}", op=operator.lt + ) + npt.assert_raises( + AssertionError, ft.assert_less_equal, 2, 1, msg="{0} =< {1}", op=operator.le + ) + npt.assert_raises( + AssertionError, ft.assert_greater, 1, 2, msg="{0} > {1}", op=operator.gt + ) + npt.assert_raises( + AssertionError, ft.assert_greater_equal, 1, 2, msg="{0} >= {1}", op=operator.ge + ) + npt.assert_raises(AssertionError, ft.assert_not_equal, 5, 5, msg="", op=operator.ne) + npt.assert_raises(AssertionError, ft.assert_operator, 2, 1, msg="", op=operator.eq) arr = [np.arange(k) for k in range(2, 12, 3)] arr2 = [np.arange(k) for k in range(2, 12, 4)] diff --git a/fury/tests/test_thread.py b/fury/tests/test_thread.py index 35e2ac0416..8c26e30d48 100644 --- a/fury/tests/test_thread.py +++ b/fury/tests/test_thread.py @@ -20,7 +20,7 @@ def test_multithreading(): # Preparing the show manager as usual showm = window.ShowManager( - scene, size=(900, 768), reset_camera=False, order_transparent=True + scene=scene, size=(900, 768), reset_camera=False, order_transparent=True ) # showm.initialize() diff --git a/fury/tests/test_transform.py b/fury/tests/test_transform.py index 8c463592eb..dfb260024f 100644 --- a/fury/tests/test_transform.py +++ b/fury/tests/test_transform.py @@ -66,17 +66,17 @@ def test_sphere_cart(): def test_euler_matrix(): - rotation = euler_matrix(1, 2, 3, "syxz") + rotation = euler_matrix(1, 2, 3, axes="syxz") npt.assert_equal(np.allclose(np.sum(rotation[0]), -1.34786452), True) - rotation = euler_matrix(1, 2, 3, (0, 1, 0, 1)) + rotation = euler_matrix(1, 2, 3, axes=(0, 1, 0, 1)) npt.assert_equal(np.allclose(np.sum(rotation[0]), -0.383436184), True) ai, aj, ak = (4.0 * np.pi) * (np.random.random(3) - 0.5) for axes in _AXES2TUPLE.keys(): - _ = euler_matrix(ai, aj, ak, axes) + _ = euler_matrix(ai, aj, ak, axes=axes) for axes in _TUPLE2AXES.keys(): - _ = euler_matrix(ai, aj, ak, axes) + _ = euler_matrix(ai, aj, ak, axes=axes) def test_translate(): diff --git a/fury/tests/test_utils.py b/fury/tests/test_utils.py index 7fdc3230e5..e7c3474384 100644 --- a/fury/tests/test_utils.py +++ b/fury/tests/test_utils.py @@ -135,7 +135,7 @@ def test_polydata_lines(): line_2 = line_1 + np.array([0.5, 0.0, 0.0]) lines = [line_1, line_2] - pd_lines, is_cmap = utils.lines_to_vtk_polydata(lines, colors) + pd_lines, is_cmap = utils.lines_to_vtk_polydata(lines, colors=colors) res_lines = utils.get_polydata_lines(pd_lines) npt.assert_array_equal(lines, res_lines) npt.assert_equal(is_cmap, False) @@ -440,7 +440,14 @@ def test_numpy_to_vtk_image_data(): numpy_img_array = numpy_support.vtk_to_numpy(vtk_img_array) npt.assert_equal(np.flipud(array), numpy_img_array.reshape(h, w, elements)) - npt.assert_raises(IOError, utils.numpy_to_vtk_image_data, np.array([1, 2, 3])) + npt.assert_raises( + IOError, + utils.numpy_to_vtk_image_data, + np.array([1, 2, 3]), + spacing=(1, 1, 1), + origin=(0, 0, 0), + deep=True, + ) def test_get_grid_cell_position(): @@ -475,7 +482,7 @@ def test_rotate(interactive=False): rot = (90, 1, 0, 0) - rotate(act2, rot) + rotate(act2, rotation=rot) act3 = utils.shallow_copy(act) @@ -483,7 +490,7 @@ def test_rotate(interactive=False): rot = (90, 0, 1, 0) - rotate(act3, rot) + rotate(act3, rotation=rot) scene.add(act3) @@ -554,7 +561,7 @@ def test_vertices_from_actor(interactive=False): big_verts = res[0] big_faces = res[1] big_colors = res[2] - actr = get_actor_from_primitive(big_verts, big_faces, big_colors) + actr = get_actor_from_primitive(big_verts, big_faces, colors=big_colors) actr.GetProperty().BackfaceCullingOff() if interactive: scene = window.Scene() @@ -643,7 +650,14 @@ def test_get_actor_from_primitive(): vertices, triangles = fp.prim_frustum() colors = np.array([1, 0, 0]) npt.assert_raises( - ValueError, get_actor_from_primitive, vertices, triangles, colors=colors + ValueError, + get_actor_from_primitive, + vertices, + triangles, + colors=colors, + normals=None, + backface_culling=True, + prim_count=1, ) @@ -824,7 +838,7 @@ def test_color_check(): points = np.array([[0, 0, 0], [0, 1, 0], [1, 0, 0]]) colors = np.array([[1, 0, 0, 0.5], [0, 1, 0, 0.5], [0, 0, 1, 0.5]]) - color_tuple = color_check(len(points), colors) + color_tuple = color_check(len(points), colors=colors) color_array, global_opacity = color_tuple npt.assert_equal(color_array, np.floor(colors * 255)) @@ -833,7 +847,7 @@ def test_color_check(): points = np.array([[0, 0, 0], [0, 1, 0], [1, 0, 0]]) colors = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) - color_tuple = color_check(len(points), colors) + color_tuple = color_check(len(points), colors=colors) color_array, global_opacity = color_tuple npt.assert_equal(color_array, np.floor(colors * 255)) @@ -842,7 +856,7 @@ def test_color_check(): points = np.array([[0, 0, 0], [0, 1, 0], [1, 0, 0]]) colors = (1, 1, 1, 0.5) - color_tuple = color_check(len(points), colors) + color_tuple = color_check(len(points), colors=colors) color_array, global_opacity = color_tuple npt.assert_equal(color_array, np.floor(np.array([colors] * 3) * 255)) @@ -851,7 +865,7 @@ def test_color_check(): points = np.array([[0, 0, 0], [0, 1, 0], [1, 0, 0]]) colors = (1, 0, 0) - color_tuple = color_check(len(points), colors) + color_tuple = color_check(len(points), colors=colors) color_array, global_opacity = color_tuple npt.assert_equal(color_array, np.floor(np.array([colors] * 3) * 255)) @@ -878,12 +892,17 @@ def test_is_ui(): def test_empty_list_to_polydata(): lines = [[]] - npt.assert_raises(ValueError, utils.lines_to_vtk_polydata, lines) + npt.assert_raises( + ValueError, + utils.lines_to_vtk_polydata, + lines, + colors=None, + ) def test_empty_array_to_polydata(): lines = np.array([[]]) - npt.assert_raises(ValueError, utils.lines_to_vtk_polydata, lines) + npt.assert_raises(ValueError, utils.lines_to_vtk_polydata, lines, colors=None) @pytest.mark.skipif(not have_dipy, reason="Requires DIPY") @@ -891,7 +910,7 @@ def test_empty_array_sequence_to_polydata(): from dipy.tracking.streamline import Streamlines lines = Streamlines() - npt.assert_raises(ValueError, utils.lines_to_vtk_polydata, lines) + npt.assert_raises(ValueError, utils.lines_to_vtk_polydata, lines, colors=None) def test_set_polydata_primitives_count(): @@ -944,7 +963,7 @@ def test_set_actor_origin(): cube = actor.cube(np.array([[0, 0, 0]])) orig_vert = np.copy(vertices_from_actor(cube)) - utils.set_actor_origin(cube, np.array([0.5, 0.5, 0.5])) + utils.set_actor_origin(cube, center=np.array([0.5, 0.5, 0.5])) new_vert = np.copy(vertices_from_actor(cube)) npt.assert_array_equal(orig_vert, new_vert + np.array([0.5, 0.5, 0.5])) diff --git a/fury/tests/test_window.py b/fury/tests/test_window.py index 87115298e7..3c3e11b4e4 100644 --- a/fury/tests/test_window.py +++ b/fury/tests/test_window.py @@ -36,26 +36,26 @@ def test_scene(): axes = actor.axes() scene.add(axes) arr = window.snapshot(scene) - report = window.analyze_snapshot(arr, bg_color) + report = window.analyze_snapshot(arr, bg_color=bg_color) npt.assert_equal(report.objects, 1) # Test remove actor function by analyzing a snapshot scene.rm(axes) arr = window.snapshot(scene) - report = window.analyze_snapshot(arr, bg_color) + report = window.analyze_snapshot(arr, bg_color=bg_color) npt.assert_equal(report.objects, 0) # Add actor to scene to test the remove all actors function by analyzing a # snapshot scene.add(axes) arr = window.snapshot(scene) - report = window.analyze_snapshot(arr, bg_color) + report = window.analyze_snapshot(arr, bg_color=bg_color) npt.assert_equal(report.objects, 1) # Test remove all actors function by analyzing a snapshot scene.rm_all() arr = window.snapshot(scene) - report = window.analyze_snapshot(arr, bg_color) + report = window.analyze_snapshot(arr, bg_color=bg_color) npt.assert_equal(report.objects, 0) # Test change background color from scene by analyzing the scene - ren2 = window.Scene(bg_float) + ren2 = window.Scene(background=bg_float) ren2.background((0, 0, 0.0)) report = window.analyze_scene(ren2) npt.assert_equal(report.bg_color, (0, 0, 0)) @@ -130,7 +130,9 @@ def test_active_camera(): direction = scene.camera_direction() position, focal_point, view_up = scene.get_camera() - scene.set_camera((0.0, 0.0, 1.0), (0.0, 0.0, 0), view_up) + scene.set_camera( + position=(0.0, 0.0, 1.0), focal_point=(0.0, 0.0, 0), view_up=view_up + ) position, focal_point, view_up = scene.get_camera() npt.assert_almost_equal(np.dot(direction, position), -1) @@ -168,7 +170,9 @@ def test_active_camera(): report = window.analyze_snapshot(arr, colors=(0, 255, 0)) npt.assert_equal(report.colors_found, [True]) - scene.set_camera((0.0, 0.0, 1.0), (0.0, 0.0, 0), view_up) + scene.set_camera( + position=(0.0, 0.0, 1.0), focal_point=(0.0, 0.0, 0), view_up=view_up + ) # vertical rotation of the camera around the focal point scene.pitch(10) @@ -203,14 +207,14 @@ def test_parallel_projection(): # Put the camera on a angle so that the # camera can show the difference between perspective # and parallel projection - scene.set_camera((1.5, 1.5, 1.5)) + scene.set_camera(position=(1.5, 1.5, 1.5)) scene.GetActiveCamera().Zoom(2) # window.show(scene, reset_camera=True) scene.reset_camera() arr = window.snapshot(scene) - scene.projection("parallel") + scene.projection(proj_type="parallel") # window.show(scene, reset_camera=False) arr2 = window.snapshot(scene) # Because of the parallel projection the two axes @@ -218,7 +222,7 @@ def test_parallel_projection(): # pixels rather than in perspective projection were # the axes being further will be smaller. npt.assert_equal(np.sum(arr2 > 0) > np.sum(arr > 0), True) - scene.projection("perspective") + scene.projection(proj_type="perspective") arr2 = window.snapshot(scene) npt.assert_equal(np.sum(arr2 > 0), np.sum(arr > 0)) @@ -322,7 +326,7 @@ def test_save_screenshot(): scene.add(sphere_actor) window_sz = (400, 400) - show_m = window.ShowManager(scene, size=window_sz) + show_m = window.ShowManager(scene=scene, size=window_sz) with InTemporaryDirectory(): fname = "test.png" @@ -359,7 +363,7 @@ def test_stereo(): np.array([[-1, 1, 0.0], [1, 1, 0.0]]), ] colors = np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) - stream_actor = actor.streamtube(lines, colors, linewidth=0.3, opacity=0.5) + stream_actor = actor.streamtube(lines, colors=colors, linewidth=0.3, opacity=0.5) scene.add(stream_actor) @@ -398,7 +402,7 @@ def test_frame_rate(): scene.add(sphere_actor) showm = window.ShowManager( - scene, size=(900, 768), reset_camera=False, order_transparent=True + scene=scene, size=(900, 768), reset_camera=False, order_transparent=True ) counter = itertools.count() @@ -540,7 +544,7 @@ def test_opengl_state_simple(): scales=0.2, ) showm = window.ShowManager( - scene, size=(900, 768), reset_camera=False, order_transparent=False + scene=scene, size=(900, 768), reset_camera=False, order_transparent=False ) scene.add(actors) @@ -566,7 +570,7 @@ def test_opengl_state_add_remove_and_check(): scales=0.2, ) showm = window.ShowManager( - scene, size=(900, 768), reset_camera=False, order_transparent=False + scene=scene, size=(900, 768), reset_camera=False, order_transparent=False ) scene.add(actor_no_depth_test) diff --git a/fury/transform.py b/fury/transform.py index ac9c1aba82..be7b9fd6ab 100644 --- a/fury/transform.py +++ b/fury/transform.py @@ -3,6 +3,8 @@ import numpy as np from scipy.spatial.transform import Rotation as Rot # type: ignore +from fury.decorators import warn_on_args_to_kwargs + # axis sequences for Euler angles _NEXT_AXIS = [1, 2, 0, 1] @@ -37,7 +39,8 @@ _TUPLE2AXES = {v: k for k, v in _AXES2TUPLE.items()} -def euler_matrix(ai, aj, ak, axes="sxyz"): +@warn_on_args_to_kwargs() +def euler_matrix(ai, aj, ak, *, axes="sxyz"): """Return homogeneous rotation matrix from Euler angles and axis sequence. Code modified from the work of Christoph Gohlke link provided here @@ -252,7 +255,10 @@ def translate(translation): iden = np.identity(4) translation = np.append(translation, 0).reshape(-1, 1) - t = np.array([[0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1]], np.float32) + t = np.array( + [[0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1]], + np.float32, + ) translation = np.multiply(t, translation) translation = np.add(iden, translation) diff --git a/fury/ui/core.py b/fury/ui/core.py index 5507a613a7..6ced09f591 100644 --- a/fury/ui/core.py +++ b/fury/ui/core.py @@ -175,7 +175,9 @@ def add_to_scene(self, scene): if callback[0] == self._scene: iren.add_callback(iren, callback[1], callback[2], args=[self]) else: - iren.add_callback(*callback, args=[self]) + # iren.add_callback(*callback, args=[self]) + if len(callback) > 3: + iren.add_callback(*callback[:3], priority=callback[3], args=[self]) def add_callback(self, prop, event_type, callback, priority=0): """Add a callback to a specific event for this UI component. diff --git a/fury/ui/helpers.py b/fury/ui/helpers.py index 8a9c39de5b..939519a270 100644 --- a/fury/ui/helpers.py +++ b/fury/ui/helpers.py @@ -2,10 +2,13 @@ import numpy as np +from fury.decorators import warn_on_args_to_kwargs + TWO_PI = 2 * np.pi -def clip_overflow(textblock, width, side="right"): +@warn_on_args_to_kwargs() +def clip_overflow(textblock, width, *, side="right"): """Clips overflowing text of TextBlock2D with respect to width. Parameters @@ -27,7 +30,7 @@ def clip_overflow(textblock, width, side="right"): original_str = textblock.message prev_bg = textblock.have_bg - clip_idx = check_overflow(textblock, width, "...", side) + clip_idx = check_overflow(textblock, width, overflow_postfix="...", side=side) if clip_idx == 0: return original_str @@ -36,7 +39,8 @@ def clip_overflow(textblock, width, side="right"): return textblock.message -def wrap_overflow(textblock, wrap_width, side="right"): +@warn_on_args_to_kwargs() +def wrap_overflow(textblock, wrap_width, *, side="right"): """Wraps overflowing text of TextBlock2D with respect to width. Parameters @@ -59,7 +63,7 @@ def wrap_overflow(textblock, wrap_width, side="right"): str_copy = textblock.message wrap_idxs = [] - wrap_idx = check_overflow(textblock, wrap_width, "", side) + wrap_idx = check_overflow(textblock, wrap_width, overflow_postfix="", side=side) if wrap_idx == 0: return original_str @@ -69,7 +73,7 @@ def wrap_overflow(textblock, wrap_width, side="right"): while wrap_idx != 0: str_copy = str_copy[wrap_idx:] textblock.message = str_copy - wrap_idx = check_overflow(textblock, wrap_width, "", side) + wrap_idx = check_overflow(textblock, wrap_width, overflow_postfix="", side=side) if wrap_idx != 0: wrap_idxs.append(wrap_idxs[-1] + wrap_idx + 1) @@ -80,7 +84,8 @@ def wrap_overflow(textblock, wrap_width, side="right"): return textblock.message -def check_overflow(textblock, width, overflow_postfix="", side="right"): +@warn_on_args_to_kwargs() +def check_overflow(textblock, width, *, overflow_postfix="", side="right"): """Checks if the text is overflowing. Parameters diff --git a/fury/ui/tests/test_containers.py b/fury/ui/tests/test_containers.py index 333fb7b443..1c016290d3 100644 --- a/fury/ui/tests/test_containers.py +++ b/fury/ui/tests/test_containers.py @@ -22,7 +22,7 @@ def setup_module(): def test_wrong_interactor_style(): panel = ui.Panel2D(size=(300, 150)) dummy_scene = window.Scene() - _ = window.ShowManager(dummy_scene, interactor_style="trackball") + _ = window.ShowManager(scene=dummy_scene, interactor_style="trackball") npt.assert_raises(TypeError, panel.add_to_scene, dummy_scene) @@ -35,17 +35,32 @@ def test_grid_ui1(interactive=False): vol1[25:75, 25:75, 25:75] = 100 colors = distinguishable_colormap(nb_colors=3) - contour_actor1 = actor.contour_from_roi(vol1, np.eye(4), colors[0], 1.0) + contour_actor1 = actor.contour_from_roi( + vol1, + affine=np.eye(4), + color=colors[0], + opacity=1.0, + ) vol2 = np.zeros((100, 100, 100)) vol2[25:75, 25:75, 25:75] = 100 - contour_actor2 = actor.contour_from_roi(vol2, np.eye(4), colors[1], 1.0) + contour_actor2 = actor.contour_from_roi( + vol2, + affine=np.eye(4), + color=colors[1], + opacity=1.0, + ) vol3 = np.zeros((100, 100, 100)) vol3[25:75, 25:75, 25:75] = 100 - contour_actor3 = actor.contour_from_roi(vol3, np.eye(4), colors[2], 1.0) + contour_actor3 = actor.contour_from_roi( + vol3, + affine=np.eye(4), + color=colors[2], + opacity=1.0, + ) scene = window.Scene() actors = [] @@ -88,7 +103,7 @@ def test_grid_ui1(interactive=False): texts.append(text_actor3) counter = itertools.count() - show_m = window.ShowManager(scene) + show_m = window.ShowManager(scene=scene) def timer_callback(_obj, _event): nonlocal show_m, counter @@ -136,17 +151,32 @@ def test_grid_ui2(interactive=False): vol1[25:75, 25:75, 25:75] = 100 colors = distinguishable_colormap(nb_colors=3) - contour_actor1 = actor.contour_from_roi(vol1, np.eye(4), colors[0], 1.0) + contour_actor1 = actor.contour_from_roi( + vol1, + affine=np.eye(4), + color=colors[0], + opacity=1.0, + ) vol2 = np.zeros((100, 100, 100)) vol2[25:75, 25:75, 25:75] = 100 - contour_actor2 = actor.contour_from_roi(vol2, np.eye(4), colors[1], 1.0) + contour_actor2 = actor.contour_from_roi( + vol2, + affine=np.eye(4), + color=colors[1], + opacity=1.0, + ) vol3 = np.zeros((100, 100, 100)) vol3[25:75, 25:75, 25:75] = 100 - contour_actor3 = actor.contour_from_roi(vol3, np.eye(4), colors[2], 1.0) + contour_actor3 = actor.contour_from_roi( + vol3, + affine=np.eye(4), + color=colors[2], + opacity=1.0, + ) scene = window.Scene() actors = [] @@ -198,7 +228,9 @@ def test_grid_ui2(interactive=False): current_size = (900, 600) scene = window.Scene() - show_manager = window.ShowManager(scene, size=current_size, title="FURY GridUI") + show_manager = window.ShowManager( + scene=scene, size=current_size, title="FURY GridUI" + ) grid_ui2 = ui.GridUI( actors=actors, diff --git a/fury/ui/tests/test_elements.py b/fury/ui/tests/test_elements.py index 7df1645b18..2f72949cc7 100644 --- a/fury/ui/tests/test_elements.py +++ b/fury/ui/tests/test_elements.py @@ -1171,7 +1171,7 @@ def test_ui_draw_shape(): current_size = (900, 900) scene = window.Scene() show_manager = window.ShowManager( - scene, size=current_size, title="DrawShape UI Example" + scene=scene, size=current_size, title="DrawShape UI Example" ) scene.add(line, circle, quad) diff --git a/fury/ui/tests/test_elements_callback.py b/fury/ui/tests/test_elements_callback.py index 89c6aa506a..4fa62e34bd 100644 --- a/fury/ui/tests/test_elements_callback.py +++ b/fury/ui/tests/test_elements_callback.py @@ -51,7 +51,7 @@ def test_frame_rate_and_anti_aliasing(): counter = itertools.count() showm = window.ShowManager( - scene, + scene=scene, size=(1980, 1080), reset_camera=False, order_transparent=True, @@ -103,7 +103,7 @@ def timer_callback(_obj, _event): counter = itertools.count() multi_samples = 0 showm = window.ShowManager( - scene, + scene=scene, size=(1980, 1080), reset_camera=False, order_transparent=True, @@ -145,7 +145,7 @@ def test_timer(): sphere_actor = actor.sphere(centers=xyzr[:, :3], colors=colors[:], radii=xyzr[:, 3]) - vertices, faces = prim_sphere("repulsion724") + vertices, faces = prim_sphere(name="repulsion724") sphere_actor2 = actor.sphere( centers=xyzr2[:, :3], @@ -161,7 +161,10 @@ def test_timer(): tb = ui.TextBlock2D() counter = itertools.count() showm = window.ShowManager( - scene, size=(1024, 768), reset_camera=False, order_transparent=True + scene=scene, + size=(1024, 768), + reset_camera=False, + order_transparent=True, ) scene.add(tb) diff --git a/fury/ui/tests/test_helpers.py b/fury/ui/tests/test_helpers.py index 039d28d833..34f7c10397 100644 --- a/fury/ui/tests/test_helpers.py +++ b/fury/ui/tests/test_helpers.py @@ -32,26 +32,26 @@ def test_clip_overflow(): npt.assert_equal("A ...", text.message) text.message = "Hello" - clip_overflow(text, text.size[0], "left") + clip_overflow(text, text.size[0], side="left") npt.assert_equal("Hello", text.message) text.message = "Hello wassup" - clip_overflow(text, text.size[0], "left") + clip_overflow(text, text.size[0], side="left") npt.assert_equal("...up", text.message) text.message = "A very very long message to clip text overflow" - clip_overflow(text, text.size[0], "left") + clip_overflow(text, text.size[0], side="left") npt.assert_equal("...ow", text.message) text.message = "A very very long message to clip text overflow" - clip_overflow(text, text.size[0], "LeFT") + clip_overflow(text, text.size[0], side="LeFT") npt.assert_equal("...ow", text.message) text.message = "A very very long message to clip text overflow" - clip_overflow(text, text.size[0], "RigHT") + clip_overflow(text, text.size[0], side="RigHT") npt.assert_equal("A ...", text.message) - npt.assert_raises(ValueError, clip_overflow, text, text.size[0], "middle") + npt.assert_raises(ValueError, clip_overflow, text, text.size[0], side="middle") def test_wrap_overflow(): @@ -97,7 +97,7 @@ def test_check_overflow(): text.message = "A very very long message to clip text overflow" - overflow_idx = check_overflow(text, 100, "~") + overflow_idx = check_overflow(text, 100, overflow_postfix="~") npt.assert_equal(4, overflow_idx) npt.assert_equal("A ve~", text.message) diff --git a/fury/utils.py b/fury/utils.py index 12aeb22148..7c269ea5a8 100644 --- a/fury/utils.py +++ b/fury/utils.py @@ -2,6 +2,7 @@ from scipy.ndimage import map_coordinates from fury.colormap import line_colors +from fury.decorators import warn_on_args_to_kwargs from fury.lib import ( VTK_DOUBLE, VTK_FLOAT, @@ -116,7 +117,8 @@ def numpy_to_vtk_colors(colors): return vtk_colors -def numpy_to_vtk_cells(data, is_coords=True): +@warn_on_args_to_kwargs() +def numpy_to_vtk_cells(data, *, is_coords=True): """Convert numpy array to a vtk cell array. Parameters @@ -172,8 +174,9 @@ def numpy_to_vtk_cells(data, is_coords=True): return cell_array +@warn_on_args_to_kwargs() def numpy_to_vtk_image_data( - array, spacing=(1.0, 1.0, 1.0), origin=(0.0, 0.0, 0.0), deep=True + array, *, spacing=(1.0, 1.0, 1.0), origin=(0.0, 0.0, 0.0), deep=True ): """Convert numpy array to a vtk image data. @@ -243,7 +246,8 @@ def map_coordinates_3d_4d(input_array, indices): return np.ascontiguousarray(np.array(values_4d).T) -def lines_to_vtk_polydata(lines, colors=None): +@warn_on_args_to_kwargs() +def lines_to_vtk_polydata(lines, *, colors=None): """Create a vtkPolyData with lines and colors. Parameters @@ -501,7 +505,8 @@ def get_polydata_colors(polydata): return numpy_support.vtk_to_numpy(vtk_colors) -def get_polydata_field(polydata, field_name, as_vtk=False): +@warn_on_args_to_kwargs() +def get_polydata_field(polydata, field_name, *, as_vtk=False): """Get a field from a vtk polydata. Parameters @@ -526,7 +531,8 @@ def get_polydata_field(polydata, field_name, as_vtk=False): return numpy_support.vtk_to_numpy(vtk_field_data) -def add_polydata_numeric_field(polydata, field_name, field_data, array_type=VTK_INT): +@warn_on_args_to_kwargs() +def add_polydata_numeric_field(polydata, field_name, field_data, *, array_type=VTK_INT): """Add a field to a vtk polydata. Parameters @@ -668,7 +674,8 @@ def set_polydata_tangents(polydata, tangents): return polydata -def set_polydata_colors(polydata, colors, array_name="colors"): +@warn_on_args_to_kwargs() +def set_polydata_colors(polydata, colors, *, array_name="colors"): """Set polydata colors with a numpy array (ndarrays Nx3 int). Parameters @@ -781,8 +788,15 @@ def get_actor_from_polydata(polydata): return get_actor_from_polymapper(poly_mapper) +@warn_on_args_to_kwargs() def get_actor_from_primitive( - vertices, triangles, colors=None, normals=None, backface_culling=True, prim_count=1 + vertices, + triangles, + *, + colors=None, + normals=None, + backface_culling=True, + prim_count=1, ): """Get actor from a vtkPolyData. @@ -831,9 +845,11 @@ def get_actor_from_primitive( return current_actor +@warn_on_args_to_kwargs() def repeat_sources( centers, colors, + *, active_scalars=1.0, directions=None, source=None, @@ -1047,7 +1063,8 @@ def get_bounding_box_sizes(actor): return (X2 - X1, Y2 - Y1, Z2 - Z1) -def get_grid_cells_position(shapes, aspect_ratio=16 / 9.0, dim=None): +@warn_on_args_to_kwargs() +def get_grid_cells_position(shapes, *, aspect_ratio=16 / 9.0, dim=None): """Construct a XY-grid based on the cells content shape. This function generates the coordinates of every grid cell. The width and @@ -1103,7 +1120,8 @@ def shallow_copy(vtk_object): return copy -def rotate(actor, rotation=(90, 1, 0, 0)): +@warn_on_args_to_kwargs() +def rotate(actor, *, rotation=(90, 1, 0, 0)): """Rotate actor around axis by angle. Parameters @@ -1286,7 +1304,8 @@ def change_vertices_order(triangle): return np.array([triangle[2], triangle[1], triangle[0]]) -def fix_winding_order(vertices, triangles, clockwise=False): +@warn_on_args_to_kwargs() +def fix_winding_order(vertices, triangles, *, clockwise=False): """Return corrected triangles. Given an ordering of the triangle's three vertices, a triangle can appear @@ -1318,7 +1337,8 @@ def fix_winding_order(vertices, triangles, clockwise=False): return corrected_triangles -def vertices_from_actor(actor, as_vtk=False): +@warn_on_args_to_kwargs() +def vertices_from_actor(actor, *, as_vtk=False): """Access to vertices from actor. Parameters @@ -1339,7 +1359,8 @@ def vertices_from_actor(actor, as_vtk=False): return numpy_support.vtk_to_numpy(vtk_array) -def colors_from_actor(actor, array_name="colors", as_vtk=False): +@warn_on_args_to_kwargs() +def colors_from_actor(actor, *, array_name="colors", as_vtk=False): """Access colors from actor which uses polydata. Parameters @@ -1392,7 +1413,8 @@ def tangents_from_actor(act): return get_polydata_tangents(polydata) -def array_from_actor(actor, array_name, as_vtk=False): +@warn_on_args_to_kwargs() +def array_from_actor(actor, array_name, *, as_vtk=False): """Access array from actor which uses polydata. Parameters @@ -1459,7 +1481,8 @@ def compute_bounds(actor): actor.GetMapper().GetInput().ComputeBounds() -def update_actor(actor, all_arrays=True): +@warn_on_args_to_kwargs() +def update_actor(actor, *, all_arrays=True): """Update actor. Parameters @@ -1524,7 +1547,8 @@ def update_surface_actor_colors(actor, colors): ) -def color_check(pts_len, colors=None): +@warn_on_args_to_kwargs() +def color_check(pts_len, *, colors=None): """Returns a VTK scalar array containing colors information for each one of the points according to the policy defined by the parameter colors. @@ -1580,7 +1604,8 @@ def is_ui(actor): return all(hasattr(actor, attr) for attr in ["add_to_scene", "_setup"]) -def set_actor_origin(actor, center=None): +@warn_on_args_to_kwargs() +def set_actor_origin(actor, *, center=None): """Change the origin of an actor to a custom position. Parameters diff --git a/fury/window.py b/fury/window.py index 7c36cedf3d..fc79285faa 100644 --- a/fury/window.py +++ b/fury/window.py @@ -10,6 +10,7 @@ from fury import __version__ as fury_version import fury.animation as anim +from fury.decorators import warn_on_args_to_kwargs from fury.interactor import CustomInteractorStyle from fury.io import load_image, save_image from fury.lib import ( @@ -47,7 +48,8 @@ class Scene(OpenGLRenderer): available in ``vtkRenderer`` if necessary. """ - def __init__(self, background=(0, 0, 0), skybox=None): + @warn_on_args_to_kwargs() + def __init__(self, *, background=(0, 0, 0), skybox=None): self.__skybox = skybox self.__skybox_actor = None if skybox: @@ -61,7 +63,8 @@ def background(self, color): """Set a background color.""" self.SetBackground(color) - def skybox(self, visible=True, gamma_correct=True): + @warn_on_args_to_kwargs() + def skybox(self, *, visible=True, gamma_correct=True): """Show or hide the skybox. Parameters @@ -112,7 +115,8 @@ def rm_all(self): """Remove all actors from the scene.""" self.RemoveAllViewProps() - def projection(self, proj_type="perspective"): + @warn_on_args_to_kwargs() + def projection(self, *, proj_type="perspective"): """Decide between parallel or perspective projection. Parameters @@ -130,7 +134,8 @@ def reset_camera(self): """Reset the camera to an automatic position given by the engine.""" self.ResetCamera() - def reset_camera_tight(self, margin_factor=1.02): + @warn_on_args_to_kwargs() + def reset_camera_tight(self, *, margin_factor=1.02): """Resets camera so the content fit tightly within the window. Parameters @@ -180,7 +185,8 @@ def camera_info(self): print(" Focal Point (%.2f, %.2f, %.2f)" % cam.GetFocalPoint()) print(" View Up (%.2f, %.2f, %.2f)" % cam.GetViewUp()) - def set_camera(self, position=None, focal_point=None, view_up=None): + @warn_on_args_to_kwargs() + def set_camera(self, *, position=None, focal_point=None, view_up=None): """Set up camera position / Focal Point / View Up.""" if position is not None: self.GetActiveCamera().SetPosition(*position) @@ -290,8 +296,10 @@ def fxaa_off(self): class ShowManager: """Class interface between the scene, the window and the interactor.""" + @warn_on_args_to_kwargs() def __init__( self, + *, scene=None, title="FURY", size=(300, 300), @@ -521,7 +529,8 @@ def is_done(self): except AttributeError: return True - def start(self, multithreaded=False, desired_fps=60): + @warn_on_args_to_kwargs() + def start(self, *, multithreaded=False, desired_fps=60): """Start interaction. Parameters @@ -666,7 +675,8 @@ def _stop_recording_and_close(_obj, _evt): events = f.read() return events - def record_events_to_file(self, filename="record.log"): + @warn_on_args_to_kwargs() + def record_events_to_file(self, *, filename="record.log"): """Record events during the interaction. The recording is represented as a list of VTK events @@ -744,7 +754,8 @@ def play_events_from_file(self, filename): self.play_events(events) - def add_window_callback(self, win_callback, event=Command.ModifiedEvent): + @warn_on_args_to_kwargs() + def add_window_callback(self, win_callback, *, event=Command.ModifiedEvent): """Add window callbacks.""" self.window.AddObserver(event, win_callback) self.window.Render() @@ -761,7 +772,8 @@ def add_timer_callback(self, repeat, duration, timer_callback): self.timers.append(timer_id) return timer_id - def add_iren_callback(self, iren_callback, event="MouseMoveEvent"): + @warn_on_args_to_kwargs() + def add_iren_callback(self, iren_callback, *, event="MouseMoveEvent"): if not self.iren.GetInitialized(): self.initialize() self.iren.AddObserver(event, iren_callback) @@ -784,7 +796,8 @@ def exit(self): self.destroy_timers() self.timers.clear() - def save_screenshot(self, fname, magnification=1, size=None, stereo=None): + @warn_on_args_to_kwargs() + def save_screenshot(self, fname, *, magnification=1, size=None, stereo=None): """Save a screenshot of the current window in the specified filename. Parameters @@ -829,8 +842,10 @@ def save_screenshot(self, fname, magnification=1, size=None, stereo=None): ) +@warn_on_args_to_kwargs() def show( scene, + *, title="FURY", size=(300, 300), png_magnify=1, @@ -904,12 +919,12 @@ def show( """ show_manager = ShowManager( - scene, - title, - size, - png_magnify, - reset_camera, - order_transparent, + scene=scene, + title=title, + size=size, + png_magnify=png_magnify, + reset_camera=reset_camera, + order_transparent=order_transparent, stereo=stereo, multi_samples=multi_samples, max_peels=max_peels, @@ -919,7 +934,9 @@ def show( show_manager.start() +@warn_on_args_to_kwargs() def record( + *, scene=None, cam_pos=None, cam_focal=None, @@ -1073,7 +1090,8 @@ def record( renWin.Finalize() -def antialiasing(scene, win, multi_samples=8, max_peels=4, occlusion_ratio=0.0): +@warn_on_args_to_kwargs() +def antialiasing(scene, win, *, multi_samples=8, max_peels=4, occlusion_ratio=0.0): """Enable anti-aliasing and ordered transparency. Parameters @@ -1116,8 +1134,10 @@ def antialiasing(scene, win, multi_samples=8, max_peels=4, occlusion_ratio=0.0): scene.SetOcclusionRatio(occlusion_ratio) +@warn_on_args_to_kwargs() def snapshot( scene, + *, fname=None, size=(300, 300), offscreen=True, @@ -1190,7 +1210,11 @@ def snapshot( if order_transparent: antialiasing( - scene, render_window, multi_samples, max_peels, occlusion_ratio + scene, + render_window, + multi_samples=multi_samples, + max_peels=max_peels, + occlusion_ratio=occlusion_ratio, ) render_window.Render() @@ -1238,8 +1262,9 @@ class ReportScene: return report +@warn_on_args_to_kwargs() def analyze_snapshot( - im, bg_color=colors.black, colors=None, find_objects=True, strel=None + im, *, bg_color=colors.black, colors=None, find_objects=True, strel=None ): """Analyze snapshot from memory or file.