def test_invalid_because_not_4x4(): with pytest.raises(ValueError): _ = mu.create_vtk_matrix_from_numpy(np.random.random((3, 4))) with pytest.raises(ValueError): _ = mu.create_vtk_matrix_from_numpy(np.random.random((4, 3)))
def run_demo(input_file, output_file, transform_file): """ Takes a poly data input, transforms it by a 4x4 matrix, writes output. :param input_file: Input poly data as .vtk, .vtp, .stl or .ply file. :param output_file: Output poly data as .vtk file. :param transform_file: 4x4 matrix in plain text (e.g. numpy.savetxt) format. :return: """ if not output_file.endswith('.vtk'): raise ValueError('Currently, only .vtk outputs are supported.') model = sm.VTKSurfaceModel(input_file, colour=[1.0, 1.0, 1.0], visibility=True) matrix = np.loadtxt(transform_file) transform = mu.create_vtk_matrix_from_numpy(matrix) model.set_model_transform(transform) # this line can go, when scikit-surgeryvtk updates to 0.22.0 model.transform_filter.Update() writer = vtk.vtkPolyDataWriter() writer.SetFileName(output_file) writer.SetInputData(model.transform_filter.GetOutput()) writer.Write()
def test_numpy_to_vtk(): numpy_array = np.random.random((4, 4)) vtk_matrix = mu.create_vtk_matrix_from_numpy(numpy_array) converted_back = mu.create_numpy_matrix_from_vtk(vtk_matrix) assert np.allclose(numpy_array, converted_back) assert id(numpy_array) != id(converted_back)
def test_create_vtk_matrix_4x4_from_numpy(): array = np.random.rand(4, 4) vtk_matrix = mu.create_vtk_matrix_from_numpy(array) for i in range(4): for j in range(4): assert vtk_matrix.GetElement(i, j) == array[i, j]
def set_pose_with_matrices(self, p2c, l2c, angle_of_handle): """ Method to apply 4x4 transformations to actors. :param p2c: 4x4 matrix, either numpy or vtk matrix. :param l2c: 4x4 matrix, either numpy or vtk matrix. :param angle_of_handle: angle in deg. :return: N/A """ # First we can compute the angle of the handle. # This applies directly to the data, as it comes out # of the vtkTransformPolyDataFilter, before the actor transformation. probe_offset = np.eye(4) probe_offset[0][3] = 0.007877540588378196 probe_offset[1][3] = 36.24640712738037 probe_offset[2][3] = -3.8626091003417997 r_x = \ cmu.construct_rx_matrix(angle_of_handle, is_in_radians=False) rotation_about_x = \ cmu.construct_rigid_transformation(r_x, np.zeros((3, 1))) self.cyl_trans.SetMatrix( vmu.create_vtk_matrix_from_numpy(probe_offset @ rotation_about_x)) self.cyl_transform_filter.Update() # Check p2c, l2c: if numpy, convert to vtk. if isinstance(p2c, np.ndarray): p2c = vmu.create_vtk_matrix_from_numpy(p2c) if isinstance(l2c, np.ndarray): l2c = vmu.create_vtk_matrix_from_numpy(l2c) # This is where we apply transforms to each actor. # Apply p2c to probe self.cyl_actor.PokeMatrix(p2c) probe_model = self.model_loader.get_surface_model('probe') probe_model.actor.PokeMatrix(p2c) # Apply l2c to organs in scene. for model in self.model_loader.get_surface_models(): if model.get_name() != 'probe': model.actor.PokeMatrix(l2c) # Force re-render self.overlay.Render() self.repaint()
def set_camera_pose(self, camera_to_world): """ Sets the camera position and orientation, from a numpy 4x4 array. :param camera_to_world: camera_to_world transform. """ vm.validate_rigid_matrix(camera_to_world) self.camera_to_world = camera_to_world vtk_cam = self.get_foreground_camera() vtk_mat = mu.create_vtk_matrix_from_numpy(camera_to_world) cm.set_camera_pose(vtk_cam, vtk_mat, self.opencv_style) self.Render()
def set_all_model_to_world(self, model_to_world): """ Decomposes the model_to_world string into rx,ry,rx,tx,ty,rz, constructs a 4x4 matrix, and applies it to all models. :param model_to_world: [4x4] numpy ndarray, rigid transform """ if model_to_world is not None: m2w = mu.create_matrix_from_list(model_to_world) vtk_matrix = mu.create_vtk_matrix_from_numpy(m2w) for model in self.model_loader.get_surface_models(): model.set_user_matrix(vtk_matrix)
def set_model_to_worlds(self, dict_of_transforms): """ Given a dictionary of transforms, will iterate by name, and apply the transform to the named object. :param dict_of_transforms: {name, [rx, ry, rz, tx, ty, tz]} """ if dict_of_transforms is not None: for name in dict_of_transforms: if name in self.model_loader.get_surface_model_names(): model = self.model_loader.get_surface_model(name) m2w = mu.create_matrix_from_list(dict_of_transforms[name]) vtk_matrix = mu.create_vtk_matrix_from_numpy(m2w) model.set_user_matrix(vtk_matrix) else: raise ValueError("'" + name + "' is not in set of models.")
def test_set_pose_identity_should_give_origin(): np_matrix = np.eye(4) vtk_matrix = mu.create_vtk_matrix_from_numpy(np_matrix) vtk_camera = vtk.vtkCamera() cam.set_camera_pose(vtk_camera, vtk_matrix) position = vtk_camera.GetPosition() focal_point = vtk_camera.GetFocalPoint() view_up = vtk_camera.GetViewUp() # Identity matrix should give: # Position at origin # Facing along positive z axis # If x points right in the image, y axis points down. assert position == (0, 0, 0) assert focal_point[2] > 0 assert view_up == (0, -1, 0)
def test_create_vtk_matrix_4x4_from_numpy_fail_on_invalid_shape(): array = np.ones([2, 3]) with pytest.raises(ValueError): mu.create_vtk_matrix_from_numpy(array)
def test_create_vtk_matrix_4x4_from_numpy_fail_on_invalid_type(): with pytest.raises(TypeError): mu.create_vtk_matrix_from_numpy("hello")
def test_invalid_because_not_numpy_matrix(): with pytest.raises(TypeError): _ = mu.create_vtk_matrix_from_numpy("banana")
def set_pose(self, anatomy_pose_params, probe_pose_params, angle_of_handle, anatomy_location=None ): """ This is the main method to call to setup the pose of all anatomy and for the LUS probe, and the handle. You can then call get_image() to get the rendered image, or call get_masks() to get a set of rendered masks, and the relevant pose parameters for ML purposes. The liver2camera and probe2camera are returned as 4x4 matrices. This is because there are multiple different parameterisations that the user might be working in. e.g. Euler angles, Rodrigues etc. :param anatomy_pose_params: [rx, ry, rz, tx, ty, tz] in deg/mm :param probe_pose_params: [rx, ry, rz, tx, ty, tz] in deg/mm :param angle_of_handle: angle in deg :param anatomy_location: [1x3] location of random point on liver surface :return: [liver2camera4x4, probe2camera4x4, angle, anatomy_location1x3] """ # The 'anatomy_location' picks a point on the surface and moves # the LUS probe to have it's centroid based there. This is in effect # updating the so-called 'reference' position of the probe. # Subsequent offsets in [rx, ry, rz, tx, ty, tz] are from this new posn. p2c = self.reference_p2c if anatomy_location is not None: picked = np.zeros((4, 1)) picked[0][0] = anatomy_location[0] picked[1][0] = anatomy_location[1] picked[2][0] = anatomy_location[2] picked[3][0] = 1 picked_point = self.reference_l2c @ picked # This p2c then becomes the 'reference_probe2camera'. p2c[0][3] = picked_point[0] p2c[1][3] = picked_point[1] p2c[2][3] = picked_point[2] # Compute the transformation for the anatomy. # We assume that the anatomy has been normalised (zero-centred). rotation_tx = vmu.create_matrix_from_list([anatomy_pose_params[0], anatomy_pose_params[1], anatomy_pose_params[2], 0, 0, 0], is_in_radians=False) translation_tx = vmu.create_matrix_from_list([0, 0, 0, anatomy_pose_params[3], anatomy_pose_params[4], anatomy_pose_params[5]], is_in_radians=False) anatomy_tx = translation_tx @ self.reference_l2c @ rotation_tx full_anatomy_tx_vtk = \ vmu.create_vtk_matrix_from_numpy(anatomy_tx) # Now we compute the position of the probe. # We assume that the probe model has been normalised (zero-centred). probe_tx = vmu.create_matrix_from_list(probe_pose_params, is_in_radians=False) p2l = np.linalg.inv(self.reference_l2c) @ p2c probe_actor_tx = p2l @ probe_tx full_probe_actor_tx = anatomy_tx @ probe_actor_tx full_probe_actor_tx_vtk = \ vmu.create_vtk_matrix_from_numpy(full_probe_actor_tx) # Apply the transforms to each actor. self.set_pose_with_matrices(full_probe_actor_tx_vtk, full_anatomy_tx_vtk, angle_of_handle) # Return parameters for final solution. liver_model = self.model_loader.get_surface_model('liver') final_l2c = \ vmu.create_numpy_matrix_from_vtk(liver_model.actor.GetMatrix()) probe_model = self.model_loader.get_surface_model('probe') final_p2c = \ vmu.create_numpy_matrix_from_vtk(probe_model.actor.GetMatrix()) return [final_l2c, final_p2c, angle_of_handle, anatomy_location]