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)
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)
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])
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()
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") })
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)