def test_markers_creation():
    dims = ("axis", "channel", "time")
    array = Markers()
    np.testing.assert_array_equal(x=array, y=xr.DataArray())
    assert array.dims == dims

    array = Markers(MARKERS_DATA.values)
    is_expected_array(array, **EXPECTED_VALUES[57])

    size = 3, 10, 100
    array = Markers.from_random_data(size=size)
    assert array.shape == (4, size[1], size[2])
    assert array.dims == dims

    with pytest.raises(ValueError):
        Markers(ANALOGS_DATA)
Пример #2
0
def test_rototrans_creation():
    dims = ("row", "col", "time")
    array = Rototrans()
    np.testing.assert_array_equal(x=array,
                                  y=xr.DataArray(np.eye(4)[..., np.newaxis]))
    assert array.dims == dims

    data = Markers(MARKERS_DATA.values)
    array = Rototrans.from_markers(
        origin=data.isel(channel=[0]),
        axis_1=data.isel(channel=[0, 1]),
        axis_2=data.isel(channel=[0, 2]),
        axes_name="xy",
        axis_to_recalculate="y",
    )
    is_expected_array(array, **EXPECTED_VALUES[67])

    size = 4, 4, 100
    array = Rototrans.from_random_data(size=size)
    assert array.shape == size
    assert array.dims == dims

    with pytest.raises(ValueError):
        Angles(ANALOGS_DATA)
Пример #3
0
def test_proc_norm():
    n_frames = 100
    n_markers = 10
    m = Markers(np.random.rand(3, n_markers, n_frames))

    # norm by hand
    expected_norm = np.linalg.norm(m[:3, ...], axis=0)

    # norm with pyomeca
    computed_norm = m.meca.norm(dim="axis")

    np.testing.assert_almost_equal(computed_norm, expected_norm, decimal=10)

    is_expected_array(MARKERS_DATA.meca.norm(dim="axis"),
                      **EXPECTED_VALUES[44])
    is_expected_array(MARKERS_DATA.meca.norm(dim="channel"),
                      **EXPECTED_VALUES[45])
    is_expected_array(MARKERS_DATA.meca.norm(dim="time"),
                      **EXPECTED_VALUES[46])

    is_expected_array(ANALOGS_DATA.meca.norm(dim="channel"),
                      **EXPECTED_VALUES[47])
    is_expected_array(ANALOGS_DATA.meca.norm(dim="time"),
                      **EXPECTED_VALUES[48])
Пример #4
0
    def __init__(
        self,
        parent,
        markers_size=0.010,
        markers_color=(1, 1, 1),
        markers_opacity=1.0,
        global_ref_frame_length=0.15,
        global_ref_frame_width=5,
        global_center_of_mass_size=0.0075,
        global_center_of_mass_color=(0, 0, 0),
        global_center_of_mass_opacity=1.0,
        segments_center_of_mass_size=0.005,
        segments_center_of_mass_color=(0, 0, 0),
        segments_center_of_mass_opacity=1.0,
        mesh_color=(0, 0, 0),
        mesh_opacity=1.0,
        muscle_color=(150 / 255, 15 / 255, 15 / 255),
        muscle_opacity=1.0,
        rt_length=0.1,
        rt_width=2,
    ):
        """
        Creates a model that will holds things to plot
        Parameters
        ----------
        parent
            Parent of the Model window
        markers_size : float
            Size the markers should be drawn
        markers_color : Tuple(int)
            Color the markers should be drawn (1 is max brightness)
        markers_opacity : float
            Opacity of the markers (0.0 is completely transparent, 1.0 completely opaque)
        rt_length : int
            Length of the axes of the system of axes
        """
        QtWidgets.QWidget.__init__(self, parent)
        self.parent_window = parent

        palette = QPalette()
        palette.setColor(self.backgroundRole(), QColor(255, 255, 255))
        self.setAutoFillBackground(True)
        self.setPalette(palette)

        self.markers = Markers()
        self.markers_size = markers_size
        self.markers_color = markers_color
        self.markers_opacity = markers_opacity
        self.markers_actors = list()

        self.has_global_ref_frame = False
        self.global_ref_frame_length = global_ref_frame_length
        self.global_ref_frame_width = global_ref_frame_width

        self.global_center_of_mass = Markers()
        self.global_center_of_mass_size = global_center_of_mass_size
        self.global_center_of_mass_color = global_center_of_mass_color
        self.global_center_of_mass_opacity = global_center_of_mass_opacity
        self.global_center_of_mass_actors = list()

        self.segments_center_of_mass = Markers()
        self.segments_center_of_mass_size = segments_center_of_mass_size
        self.segments_center_of_mass_color = segments_center_of_mass_color
        self.segments_center_of_mass_opacity = segments_center_of_mass_opacity
        self.segments_center_of_mass_actors = list()

        self.all_rt = []
        self.n_rt = 0
        self.rt_length = rt_length
        self.rt_width = rt_width
        self.rt_actors = list()
        self.parent_window.should_reset_camera = True

        self.all_meshes = []
        self.mesh_color = mesh_color
        self.mesh_opacity = mesh_opacity
        self.mesh_actors = list()

        self.all_muscles = []
        self.muscle_color = muscle_color
        self.muscle_opacity = muscle_opacity
        self.muscle_actors = list()
Пример #5
0
    def __init__(
            self,
            model_path=None,
            loaded_model=None,
            show_meshes=True,
            show_global_center_of_mass=True,
            show_segments_center_of_mass=True,
            segments_center_of_mass_size=0.005,
            show_global_ref_frame=True,
            show_local_ref_frame=True,
            show_markers=True,
            markers_size=0.010,
            show_contacts=True,
            contacts_size=0.010,
            show_muscles=True,
            show_wrappings=True,
            show_analyses_panel=True,
            background_color=(0.5, 0.5, 0.5),
            **kwargs,
    ):
        """
        Class that easily shows a biorbd model
        Args:
            loaded_model: reference to a biorbd loaded model (if both loaded_model and model_path, load_model is selected
            model_path: path of the model to load
        """

        # Load and store the model
        if loaded_model is not None:
            if not isinstance(loaded_model, biorbd.Model):
                raise TypeError(
                    "loaded_model should be of a biorbd.Model type")
            self.model = loaded_model
        elif model_path is not None:
            self.model = biorbd.Model(model_path)
        else:
            raise ValueError("loaded_model or model_path must be provided")

        # Create the plot
        self.vtk_window = VtkWindow(background_color=background_color)
        self.vtk_model = VtkModel(
            self.vtk_window,
            markers_color=(0, 0, 1),
            markers_size=markers_size,
            contacts_size=contacts_size,
            segments_center_of_mass_size=segments_center_of_mass_size)
        self.is_executing = False
        self.animation_warning_already_shown = False

        # Set Z vertical
        cam = self.vtk_window.ren.GetActiveCamera()
        cam.SetFocalPoint(0, 0, 0)
        cam.SetPosition(5, 0, 0)
        cam.SetRoll(-90)

        # Get the options
        self.show_markers = show_markers
        self.show_contacts = show_contacts
        self.show_global_ref_frame = show_global_ref_frame
        self.show_global_center_of_mass = show_global_center_of_mass
        self.show_segments_center_of_mass = show_segments_center_of_mass
        self.show_local_ref_frame = show_local_ref_frame
        if self.model.nbMuscles() > 0:
            self.show_muscles = show_muscles
        else:
            self.show_muscles = False
            show_wrappings = False
        self.show_wrappings = show_wrappings

        if sum([
                len(i)
                for i in self.model.meshPoints(np.zeros(self.model.nbQ()))
        ]) > 0:
            self.show_meshes = show_meshes
        else:
            self.show_meshes = 0

        # Create all the reference to the things to plot
        self.nQ = self.model.nbQ()
        self.Q = np.zeros(self.nQ)
        if self.show_markers:
            self.Markers = InterfacesCollections.Markers(self.model)
            self.markers = Markers(np.ndarray((3, self.model.nbMarkers(), 1)))
        if self.show_contacts:
            self.Contacts = InterfacesCollections.Contact(self.model)
            self.contacts = Markers(np.ndarray(
                (3, self.model.nbContacts(), 1)))
        if self.show_global_center_of_mass:
            self.CoM = InterfacesCollections.CoM(self.model)
            self.global_center_of_mass = Markers(np.ndarray((3, 1, 1)))
        if self.show_segments_center_of_mass:
            self.CoMbySegment = InterfacesCollections.CoMbySegment(self.model)
            self.segments_center_of_mass = Markers(
                np.ndarray((3, self.model.nbSegment(), 1)))
        if self.show_meshes:
            self.mesh = []
            self.meshPointsInMatrix = InterfacesCollections.MeshPointsInMatrix(
                self.model)
            for i, vertices in enumerate(
                    self.meshPointsInMatrix.get_data(Q=self.Q,
                                                     compute_kin=False)):
                triangles = np.array([p.face() for p in self.model.meshFaces()[i]], dtype="int32") \
                    if len(self.model.meshFaces()[i]) else np.ndarray((0, 3), dtype="int32")
                self.mesh.append(Mesh(vertex=vertices, triangles=triangles.T))
        if self.show_muscles:
            self.model.updateMuscles(self.Q, True)
            self.muscles = []
            for group_idx in range(self.model.nbMuscleGroups()):
                for muscle_idx in range(
                        self.model.muscleGroup(group_idx).nbMuscles()):
                    musc = self.model.muscleGroup(group_idx).muscle(muscle_idx)
                    tp = np.zeros(
                        (3, len(musc.position().musclesPointsInGlobal()), 1))
                    self.muscles.append(Mesh(vertex=tp))
            self.musclesPointsInGlobal = InterfacesCollections.MusclesPointsInGlobal(
                self.model)
        if self.show_local_ref_frame or self.show_global_ref_frame:
            self.rt = []
            self.allGlobalJCS = InterfacesCollections.AllGlobalJCS(self.model)
            for rt in self.allGlobalJCS.get_data(Q=self.Q, compute_kin=False):
                self.rt.append(Rototrans(rt))

            if self.show_global_ref_frame:
                self.vtk_model.create_global_ref_frame()
        if self.show_wrappings:
            self.wraps_base = []
            self.wraps_current = []
            for m in range(self.model.nbMuscles()):
                path_modifier = self.model.muscle(m).pathModifier()
                wraps = []
                wraps_current = []
                for w in range(path_modifier.nbWraps()):
                    wrap = path_modifier.object(w)
                    if wrap.typeOfNode() == biorbd.VIA_POINT:
                        continue  # Do not show via points
                    elif wrap.typeOfNode() == biorbd.WRAPPING_HALF_CYLINDER:
                        wrap_cylinder = biorbd.WrappingHalfCylinder(wrap)
                        res = 11  # resolution
                        x = np.sin(np.linspace(0, np.pi,
                                               res)) * wrap_cylinder.radius()
                        y = np.cos(np.linspace(0, np.pi,
                                               res)) * wrap_cylinder.radius()
                        z = np.ones((res, )) * wrap_cylinder.length()
                        vertices = np.concatenate([
                            np.array([0, 0, z[0]])[:, np.newaxis], [x, y, z],
                            np.array([0, 0, -z[0]])[:, np.newaxis], [x, y, -z]
                        ],
                                                  axis=1)

                        tri_0_0 = np.zeros((res - 1, 1))
                        tri_1_0 = np.arange(1, res)[:, np.newaxis]
                        tri_2_0 = np.arange(2, res + 1)[:, np.newaxis]
                        tri_0 = np.concatenate([tri_0_0, tri_1_0, tri_2_0],
                                               axis=1)
                        tri_1 = tri_0 + res + 1
                        tri_2 = np.concatenate(
                            [tri_1_0, tri_2_0, tri_1_0 + res + 1], axis=1)
                        tri_3 = np.concatenate(
                            [tri_1_0 + res + 1, tri_1_0 + res + 2, tri_2_0],
                            axis=1)
                        tri_4 = np.array([[1, res, res + 2],
                                          [res, res + 2, res + res + 1]])
                        triangles = np.array(np.concatenate(
                            (tri_0, tri_1, tri_2, tri_3, tri_4)),
                                             dtype="int32").T
                    else:
                        raise NotImplementedError(
                            "The wrapping object is not implemented in bioviz")
                    wraps.append(
                        Mesh(vertex=vertices[:, :, np.newaxis],
                             triangles=triangles))
                    wraps_current.append(
                        Mesh(vertex=vertices[:, :, np.newaxis],
                             triangles=triangles))
                self.wraps_base.append(wraps)
                self.wraps_current.append(wraps_current)

        self.show_analyses_panel = show_analyses_panel
        if self.show_analyses_panel:
            self.muscle_analyses = []
            self.palette_active = QPalette()
            self.palette_inactive = QPalette()
            self.set_viz_palette()
            self.animated_Q = []

            self.play_stop_push_button = []
            self.is_animating = False
            self.is_recording = False
            self.start_icon = QIcon(
                QPixmap(f"{os.path.dirname(__file__)}/ressources/start.png"))
            self.pause_icon = QIcon(
                QPixmap(f"{os.path.dirname(__file__)}/ressources/pause.png"))
            self.record_icon = QIcon(
                QPixmap(f"{os.path.dirname(__file__)}/ressources/record.png"))
            self.add_icon = QIcon(
                QPixmap(f"{os.path.dirname(__file__)}/ressources/add.png"))
            self.stop_icon = QIcon(
                QPixmap(f"{os.path.dirname(__file__)}/ressources/stop.png"))

            self.double_factor = 10000
            self.sliders = list()
            self.movement_slider = []

            self.active_analyses_widget = None
            self.analyses_layout = QHBoxLayout()
            self.analyses_muscle_widget = QWidget()
            self.add_options_panel()

        # Update everything at the position Q=0
        self.set_q(self.Q)
def test_rt_from_markers():
    all_m = Markers.from_random_data()

    rt_xy = Rototrans.from_markers(
        origin=all_m.isel(channel=[0]),
        axis_1=all_m.isel(channel=[0, 1]),
        axis_2=all_m.isel(channel=[0, 2]),
        axes_name="xy",
        axis_to_recalculate="y",
    )

    rt_yx = Rototrans.from_markers(
        origin=all_m.isel(channel=[0]),
        axis_1=all_m.isel(channel=[0, 2]),
        axis_2=all_m.isel(channel=[0, 1]),
        axes_name="yx",
        axis_to_recalculate="y",
    )

    rt_xy_x_recalc = Rototrans.from_markers(
        origin=all_m.isel(channel=[0]),
        axis_1=all_m.isel(channel=[0, 1]),
        axis_2=all_m.isel(channel=[0, 2]),
        axes_name="yx",
        axis_to_recalculate="x",
    )
    rt_xy_x_recalc = rt_xy_x_recalc.isel(col=[1, 0, 2, 3])
    rt_xy_x_recalc[:, 2, :] = -rt_xy_x_recalc[:, 2, :]

    rt_yz = Rototrans.from_markers(
        origin=all_m.isel(channel=[0]),
        axis_1=all_m.isel(channel=[0, 1]),
        axis_2=all_m.isel(channel=[0, 2]),
        axes_name="yz",
        axis_to_recalculate="z",
    )

    rt_zy = Rototrans.from_markers(
        origin=all_m.isel(channel=[0]),
        axis_1=all_m.isel(channel=[0, 2]),
        axis_2=all_m.isel(channel=[0, 1]),
        axes_name="zy",
        axis_to_recalculate="z",
    )
    rt_xy_from_yz = rt_yz.isel(col=[1, 2, 0, 3])

    rt_xz = Rototrans.from_markers(
        origin=all_m.isel(channel=[0]),
        axis_1=all_m.isel(channel=[0, 1]),
        axis_2=all_m.isel(channel=[0, 2]),
        axes_name="xz",
        axis_to_recalculate="z",
    )

    rt_zx = Rototrans.from_markers(
        origin=all_m.isel(channel=[0]),
        axis_1=all_m.isel(channel=[0, 2]),
        axis_2=all_m.isel(channel=[0, 1]),
        axes_name="zx",
        axis_to_recalculate="z",
    )
    rt_xy_from_zx = rt_xz.isel(col=[0, 2, 1, 3])
    rt_xy_from_zx[:, 2, :] = -rt_xy_from_zx[:, 2, :]

    np.testing.assert_array_equal(rt_xy, rt_xy_x_recalc)
    np.testing.assert_array_equal(rt_xy, rt_yx)
    np.testing.assert_array_equal(rt_yz, rt_zy)
    np.testing.assert_array_equal(rt_xz, rt_zx)
    np.testing.assert_array_equal(rt_xy, rt_xy_from_yz)
    np.testing.assert_array_equal(rt_xy, rt_xy_from_zx)

    # Produce one that we know the solution
    ref_m = Markers(
        np.array(((1, 2, 3), (4, 5, 6), (6, 5, 4))).T[:, :, np.newaxis])
    rt_xy_from_known_m = Rototrans.from_markers(
        origin=ref_m.isel(channel=[0]),
        axis_1=ref_m.isel(channel=[0, 1]),
        axis_2=ref_m.isel(channel=[0, 2]),
        axes_name="xy",
        axis_to_recalculate="y",
    )

    rt_xy_expected = Rototrans(
        np.array([
            [0.5773502691896257, 0.7071067811865475, -0.408248290463863, 1.0],
            [0.5773502691896257, 0.0, 0.816496580927726, 2.0],
            [0.5773502691896257, -0.7071067811865475, -0.408248290463863, 3.0],
            [0, 0, 0, 1.0],
        ]))

    np.testing.assert_array_equal(rt_xy_from_known_m, rt_xy_expected)

    exception_default_params = dict(
        origin=all_m.isel(channel=[0]),
        axis_1=all_m.isel(channel=[0, 1]),
        axis_2=all_m.isel(channel=[0, 2]),
        axes_name="xy",
        axis_to_recalculate="y",
    )
    with pytest.raises(ValueError):
        Rototrans.from_markers(**{
            **exception_default_params,
            **dict(origin=all_m.isel(channel=[0, 1]))
        })

    with pytest.raises(ValueError):
        Rototrans.from_markers(**{
            **exception_default_params,
            **dict(axis_1=all_m.isel(channel=[0]))
        })

    with pytest.raises(ValueError):
        Rototrans.from_markers(**{
            **exception_default_params,
            **dict(axis_2=all_m.isel(channel=[0]))
        })

    with pytest.raises(ValueError):
        Rototrans.from_markers(
            **{
                **exception_default_params,
                **dict(axis_1=all_m.isel(channel=[0, 1], time=slice(None, 50))),
            })

    with pytest.raises(ValueError):
        Rototrans.from_markers(**{
            **exception_default_params,
            **dict(axes_name="yyz")
        })

    with pytest.raises(ValueError):
        Rototrans.from_markers(**{
            **exception_default_params,
            **dict(axes_name="xxz")
        })

    with pytest.raises(ValueError):
        Rototrans.from_markers(**{
            **exception_default_params,
            **dict(axes_name="zzz")
        })

    with pytest.raises(ValueError):
        Rototrans.from_markers(**{
            **exception_default_params,
            **dict(axis_to_recalculate="h")
        })
Пример #7
0
    def __init__(
            self,
            model_path=None,
            loaded_model=None,
            show_meshes=True,
            show_global_center_of_mass=True,
            show_segments_center_of_mass=True,
            show_global_ref_frame=True,
            show_local_ref_frame=True,
            show_markers=True,
            markers_size=0.010,
            show_muscles=True,
            show_analyses_panel=True,
            background_color=(0.5, 0.5, 0.5),
            **kwargs,
    ):
        """
        Class that easily shows a biorbd model
        Args:
            loaded_model: reference to a biorbd loaded model (if both loaded_model and model_path, load_model is selected
            model_path: path of the model to load
        """

        # Load and store the model
        if loaded_model is not None:
            if not isinstance(loaded_model, biorbd.Model):
                raise TypeError(
                    "loaded_model should be of a biorbd.Model type")
            self.model = loaded_model
        elif model_path is not None:
            self.model = biorbd.Model(model_path)
        else:
            raise ValueError("loaded_model or model_path must be provided")

        # Create the plot
        self.vtk_window = VtkWindow(background_color=background_color)
        self.vtk_model = VtkModel(self.vtk_window,
                                  markers_color=(0, 0, 1),
                                  markers_size=markers_size)
        self.is_executing = False
        self.animation_warning_already_shown = False

        # Set Z vertical
        cam = self.vtk_window.ren.GetActiveCamera()
        cam.SetFocalPoint(0, 0, 0)
        cam.SetPosition(5, 0, 0)
        cam.SetRoll(-90)

        # Get the options
        self.show_markers = show_markers
        self.show_global_ref_frame = show_global_ref_frame
        self.show_global_center_of_mass = show_global_center_of_mass
        self.show_segments_center_of_mass = show_segments_center_of_mass
        self.show_local_ref_frame = show_local_ref_frame
        if self.model.nbMuscles() > 0:
            self.show_muscles = show_muscles
        else:
            self.show_muscles = False
        if sum([
                len(i)
                for i in self.model.meshPoints(np.zeros(self.model.nbQ()))
        ]) > 0:
            self.show_meshes = show_meshes
        else:
            self.show_meshes = 0

        # Create all the reference to the things to plot
        self.nQ = self.model.nbQ()
        self.Q = np.zeros(self.nQ)
        self.markers = Markers(np.ndarray((3, self.model.nbMarkers(), 1)))
        if self.show_markers:
            self.Markers = InterfacesCollections.Markers(self.model)
            self.global_center_of_mass = Markers(np.ndarray((3, 1, 1)))
        if self.show_global_center_of_mass:
            self.CoM = InterfacesCollections.CoM(self.model)
            self.segments_center_of_mass = Markers(
                np.ndarray((3, self.model.nbSegment(), 1)))
        if self.show_segments_center_of_mass:
            self.CoMbySegment = InterfacesCollections.CoMbySegment(self.model)
        if self.show_meshes:
            self.mesh = []
            self.meshPointsInMatrix = InterfacesCollections.MeshPointsInMatrix(
                self.model)
            for i, vertices in enumerate(
                    self.meshPointsInMatrix.get_data(Q=self.Q,
                                                     compute_kin=False)):
                triangles = np.ndarray((len(self.model.meshFaces()[i]), 3),
                                       dtype="int32")
                for k, patch in enumerate(self.model.meshFaces()[i]):
                    triangles[k, :] = patch.face()
                self.mesh.append(Mesh(vertex=vertices, triangles=triangles.T))
        self.model.updateMuscles(self.Q, True)
        self.muscles = []
        for group_idx in range(self.model.nbMuscleGroups()):
            for muscle_idx in range(
                    self.model.muscleGroup(group_idx).nbMuscles()):
                musc = self.model.muscleGroup(group_idx).muscle(muscle_idx)
                tp = np.zeros(
                    (3, len(musc.position().musclesPointsInGlobal()), 1))
                self.muscles.append(Mesh(vertex=tp))
        self.musclesPointsInGlobal = InterfacesCollections.MusclesPointsInGlobal(
            self.model)
        self.rt = []
        self.allGlobalJCS = InterfacesCollections.AllGlobalJCS(self.model)
        for rt in self.allGlobalJCS.get_data(Q=self.Q, compute_kin=False):
            self.rt.append(Rototrans(rt))

        if self.show_global_ref_frame:
            self.vtk_model.create_global_ref_frame()

        self.show_analyses_panel = show_analyses_panel
        if self.show_analyses_panel:
            self.muscle_analyses = []
            self.palette_active = QPalette()
            self.palette_inactive = QPalette()
            self.set_viz_palette()
            self.animated_Q = []

            self.play_stop_push_button = []
            self.is_animating = False
            self.is_recording = False
            self.start_icon = QIcon(
                QPixmap(f"{os.path.dirname(__file__)}/ressources/start.png"))
            self.pause_icon = QIcon(
                QPixmap(f"{os.path.dirname(__file__)}/ressources/pause.png"))
            self.record_icon = QIcon(
                QPixmap(f"{os.path.dirname(__file__)}/ressources/record.png"))
            self.add_icon = QIcon(
                QPixmap(f"{os.path.dirname(__file__)}/ressources/add.png"))
            self.stop_icon = QIcon(
                QPixmap(f"{os.path.dirname(__file__)}/ressources/stop.png"))

            self.double_factor = 10000
            self.sliders = list()
            self.movement_slider = []

            self.active_analyses_widget = None
            self.analyses_layout = QHBoxLayout()
            self.analyses_muscle_widget = QWidget()
            self.add_options_panel()

        # Update everything at the position Q=0
        self.set_q(self.Q)