def test_odf_slicer(interactive=False): # Prepare our data sphere = get_sphere('repulsion100') shape = (11, 11, 11, sphere.vertices.shape[0]) odfs = np.ones(shape) affine = np.array([[2.0, 0.0, 0.0, 3.0], [0.0, 2.0, 0.0, 3.0], [0.0, 0.0, 2.0, 1.0], [0.0, 0.0, 0.0, 1.0]]) mask = np.ones(odfs.shape[:3], bool) mask[:4, :4, :4] = False # Test that affine and mask work odf_actor = actor.odf_slicer(odfs, sphere=sphere, affine=affine, mask=mask, scale=.25, colormap='blues') k = 2 I, J, _ = odfs.shape[:3] odf_actor.display_extent(0, I - 1, 0, J - 1, k, k) scene = window.Scene() scene.add(odf_actor) scene.reset_camera() scene.reset_clipping_range() if interactive: window.show(scene, reset_camera=False) arr = window.snapshot(scene) report = window.analyze_snapshot(arr, find_objects=True) npt.assert_equal(report.objects, 11 * 11 - 16) # Test that global colormap works odf_actor = actor.odf_slicer(odfs, sphere=sphere, mask=mask, scale=.25, colormap='blues', norm=False, global_cm=True) scene.clear() scene.add(odf_actor) scene.reset_camera() scene.reset_clipping_range() if interactive: window.show(scene) # Test that the most basic odf_slicer instanciation works odf_actor = actor.odf_slicer(odfs) scene.clear() scene.add(odf_actor) scene.reset_camera() scene.reset_clipping_range() if interactive: window.show(scene) # Test that odf_slicer.display works properly scene.clear() scene.add(odf_actor) scene.add(actor.axes((11, 11, 11))) for i in range(11): odf_actor.display(i, None, None) if interactive: window.show(scene) for j in range(11): odf_actor.display(None, j, None) if interactive: window.show(scene) # With mask equal to zero everything should be black mask = np.zeros(odfs.shape[:3]) odf_actor = actor.odf_slicer(odfs, sphere=sphere, mask=mask, scale=.25, colormap='blues', norm=False, global_cm=True) scene.clear() scene.add(odf_actor) scene.reset_camera() scene.reset_clipping_range() if interactive: window.show(scene) # global_cm=True with colormap=None should raise an error npt.assert_raises(IOError, actor.odf_slicer, odfs, sphere=sphere, mask=None, scale=.25, colormap=None, norm=False, global_cm=True) # Dimension mismatch between sphere vertices and number # of SF coefficients will raise an error. npt.assert_raises(ValueError, actor.odf_slicer, odfs, mask=None, sphere=get_sphere('repulsion200'), scale=.25) # colormap=None and global_cm=False results in directionally encoded colors odf_actor = actor.odf_slicer(odfs, sphere=sphere, mask=None, scale=.25, colormap=None, norm=False, global_cm=False) scene.clear() scene.add(odf_actor) scene.reset_camera() scene.reset_clipping_range() if interactive: window.show(scene) # Test that SH coefficients input works B = sh_to_sf_matrix(sphere, return_inv=False) odfs = np.zeros((11, 11, 11, B.shape[0])) odfs[..., 0] = 1.0 odf_actor = actor.odf_slicer(odfs, sphere=sphere, B_matrix=B) scene.clear() scene.add(odf_actor) scene.reset_camera() scene.reset_clipping_range() if interactive: window.show(scene) # Dimension mismatch between sphere vertices and dimension of # B matrix will raise an error. npt.assert_raises(ValueError, actor.odf_slicer, odfs, mask=None, sphere=get_sphere('repulsion200')) # Test that constant colormap color works. Also test that sphere # normals are oriented correctly. Will show purple spheres with # a white contour. odf_contour = actor.odf_slicer(odfs, sphere=sphere, B_matrix=B, colormap=(255, 255, 255)) odf_contour.GetProperty().SetAmbient(1.0) odf_contour.GetProperty().SetFrontfaceCulling(True) odf_actor = actor.odf_slicer(odfs, sphere=sphere, B_matrix=B, colormap=(255, 0, 255), scale=0.4) scene.clear() scene.add(odf_contour) scene.add(odf_actor) scene.reset_camera() scene.reset_clipping_range() if interactive: window.show(scene) # Test that we can change the sphere on an active actor new_sphere = get_sphere('symmetric362') new_B = sh_to_sf_matrix(new_sphere, return_inv=False) odf_actor.update_sphere(new_sphere.vertices, new_sphere.faces, new_B) if interactive: window.show(scene) del odf_actor del odfs
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) scene.add(slicer) scene.reset_camera() scene.reset_clipping_range() # window.show(scene) # copy pixels in numpy array directly arr = window.snapshot(scene, 'test_slicer.png', offscreen=True) if verbose: print(arr.sum()) print(np.sum(arr == 0)) print(np.sum(arr > 0)) print(arr.shape) print(arr.dtype) report = window.analyze_snapshot(arr, find_objects=True) npt.assert_equal(report.objects, 1) # print(arr[..., 0]) # The slicer can cut directly a smaller part of the image slicer.display_extent(10, 30, 10, 30, 35, 35) scene.ResetCamera() scene.add(slicer) # 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) 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)) scene.clear() rgb = np.zeros((30, 30, 30, 3), dtype='f8') rgb[..., 0] = 255 rgb_actor = actor.slicer(rgb) scene.add(rgb_actor) scene.reset_camera() scene.reset_clipping_range() arr = window.snapshot(scene, offscreen=True) report = window.analyze_snapshot(arr, colors=[(255, 0, 0)]) npt.assert_equal(report.objects, 1) npt.assert_equal(report.colors_found, [True]) lut = actor.colormap_lookup_table(scale_range=(0, 255), hue_range=(0.4, 1.), saturation_range=(1, 1.), value_range=(0., 1.)) 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.opacity(0.5) slicer_lut.tolerance(0.03) slicer_lut2 = slicer_lut.copy() npt.assert_equal(slicer_lut2.GetOpacity(), 0.5) npt.assert_equal(slicer_lut2.picker.GetTolerance(), 0.03) slicer_lut2.opacity(1) slicer_lut2.tolerance(0.025) slicer_lut2.display(None, None, 10) scene.add(slicer_lut2) scene.reset_clipping_range() arr = window.snapshot(scene, offscreen=True) report = window.analyze_snapshot(arr, find_objects=True) npt.assert_equal(report.objects, 1) scene.clear() 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) scene.add(slicer) scene.reset_camera() scene.reset_clipping_range() arr = window.snapshot(scene, offscreen=True) report = window.analyze_snapshot(arr, find_objects=True) npt.assert_equal(report.objects, 1) npt.assert_equal(data.shape, slicer.shape) slicer2 = slicer.copy() npt.assert_equal(slicer2.shape, slicer.shape) scene.clear() data = (255 * np.random.rand(50, 50, 50)) affine = np.diag([1, 3, 2, 1]) from dipy.align.reslice import reslice data2, affine2 = reslice(data, affine, zooms=(1, 3, 2), new_zooms=(1, 1, 1)) slicer = actor.slicer(data2, affine2, interpolation='linear') slicer.display(None, None, 25) scene.add(slicer) scene.reset_camera() scene.reset_clipping_range() # window.show(scene, reset_camera=False) arr = window.snapshot(scene, offscreen=True) report = window.analyze_snapshot(arr, find_objects=True) npt.assert_equal(report.objects, 1) npt.assert_array_equal([1, 3, 2] * np.array(data.shape), np.array(slicer.shape))
def test_bundle_maps(): scene = window.Scene() bundle = fornix_streamlines() bundle, _ = center_streamlines(bundle) mat = np.array([[1, 0, 0, 100], [0, 1, 0, 100], [0, 0, 1, 100], [0, 0, 0, 1.]]) bundle = transform_streamlines(bundle, mat) # metric = np.random.rand(*(200, 200, 200)) metric = 100 * np.ones((200, 200, 200)) # add lower values metric[100, :, :] = 100 * 0.5 # create a nice orange-red colormap lut = actor.colormap_lookup_table(scale_range=(0., 100.), hue_range=(0., 0.1), saturation_range=(1, 1), value_range=(1., 1)) line = actor.line(bundle, metric, linewidth=0.1, lookup_colormap=lut) scene.add(line) scene.add(actor.scalar_bar(lut, ' ')) report = window.analyze_scene(scene) npt.assert_almost_equal(report.actors, 1) # window.show(scene) scene.clear() nb_points = np.sum([len(b) for b in bundle]) values = 100 * np.random.rand(nb_points) # values[:nb_points/2] = 0 line = actor.streamtube(bundle, values, linewidth=0.1, lookup_colormap=lut) scene.add(line) # window.show(scene) report = window.analyze_scene(scene) npt.assert_equal(report.actors_classnames[0], 'vtkLODActor') scene.clear() colors = np.random.rand(nb_points, 3) # values[:nb_points/2] = 0 line = actor.line(bundle, colors, linewidth=2) scene.add(line) # window.show(scene) report = window.analyze_scene(scene) npt.assert_equal(report.actors_classnames[0], 'vtkLODActor') # window.show(scene) arr = window.snapshot(scene) report2 = window.analyze_snapshot(arr) npt.assert_equal(report2.objects, 1) # try other input options for colors scene.clear() actor.line(bundle, (1., 0.5, 0)) actor.line(bundle, np.arange(len(bundle))) actor.line(bundle) colors = [np.random.rand(*b.shape) for b in bundle] actor.line(bundle, colors=colors)
def test_add_shader_callback(): cube = generate_cube_with_effect() showm = window.ShowManager() showm.scene.add(cube) class Timer(object): idx = 0.0 timer = Timer() def timer_callback(obj, event): # nonlocal timer, showm timer.idx += 1.0 showm.render() if timer.idx > 90: showm.exit() def my_cbk(_caller, _event, calldata=None): program = calldata if program is not None: try: program.SetUniformf("time", timer.idx) except ValueError: pass add_shader_callback(cube, my_cbk) showm.initialize() showm.add_timer_callback(True, 100, timer_callback) showm.start() arr = window.snapshot(showm.scene, offscreen=True) report = window.analyze_snapshot(arr) npt.assert_equal(report.objects, 1) cone_actor = actor.cone(np.array([[0, 0, 0]]), np.array([[0, 1, 0]]), (0, 0, 1)) test_values = [] def callbackLow(_caller, _event, calldata=None): program = calldata if program is not None: test_values.append(0) id_observer = add_shader_callback(cone_actor, callbackLow, 0) with pytest.raises(Exception): add_shader_callback(cone_actor, callbackLow, priority='str') mapper = cone_actor.GetMapper() mapper.RemoveObserver(id_observer) scene = window.Scene() scene.add(cone_actor) arr1 = window.snapshot(scene, size=(200, 200)) assert len(test_values) == 0 test_values = [] def callbackHigh(_caller, _event, calldata=None): program = calldata if program is not None: test_values.append(999) def callbackMean(_caller, _event, calldata=None): program = calldata if program is not None: test_values.append(500) add_shader_callback(cone_actor, callbackHigh, 999) add_shader_callback(cone_actor, callbackLow, 0) id_mean = add_shader_callback(cone_actor, callbackMean, 500) # check the priority of each call arr2 = window.snapshot(scene, size=(200, 200)) assert np.abs( [test_values[0] - 999, test_values[1] - 500, test_values[2] - 0]).sum() == 0 # check if the correct observer was removed mapper.RemoveObserver(id_mean) test_values = [] arr3 = window.snapshot(scene, size=(200, 200)) assert np.abs([test_values[0] - 999, test_values[1] - 0]).sum() == 0
def test_contour_from_roi(interactive=False): # Render volume scene = window.Scene() data = np.zeros((50, 50, 50)) data[20:30, 25, 25] = 1. data[25, 20:30, 25] = 1. affine = np.eye(4) surface = actor.contour_from_roi(data, affine, color=np.array([1, 0, 1]), opacity=.5) scene.add(surface) scene.reset_camera() scene.reset_clipping_range() if interactive: window.show(scene) # Test Errors npt.assert_raises(ValueError, actor.contour_from_roi, np.ones(50)) # Test binarization scene2 = window.Scene() data2 = np.zeros((50, 50, 50)) data2[20:30, 25, 25] = 1. data2[35:40, 25, 25] = 1. affine = np.eye(4) surface2 = actor.contour_from_roi(data2, affine, color=np.array([0, 1, 1]), opacity=.5) scene2.add(surface2) scene2.reset_camera() scene2.reset_clipping_range() if interactive: window.show(scene2) arr = window.snapshot(scene, 'test_surface.png', offscreen=True) arr2 = window.snapshot(scene2, 'test_surface2.png', offscreen=True) report = window.analyze_snapshot(arr, find_objects=True) report2 = window.analyze_snapshot(arr2, find_objects=True) npt.assert_equal(report.objects, 1) npt.assert_equal(report2.objects, 2) # test on real streamlines using tracking example if have_dipy: from dipy.data import read_stanford_labels from dipy.reconst.shm import CsaOdfModel from dipy.data import default_sphere from dipy.direction import peaks_from_model from fury.colormap import line_colors from dipy.tracking import utils try: from dipy.tracking.local import ThresholdTissueClassifier \ as ThresholdStoppingCriterion from dipy.tracking.local import LocalTracking except ImportError: from dipy.tracking.stopping_criterion import \ ThresholdStoppingCriterion from dipy.tracking.local_tracking import LocalTracking hardi_img, gtab, labels_img = read_stanford_labels() data = np.asanyarray(hardi_img.dataobj) labels = np.asanyarray(labels_img.dataobj) affine = hardi_img.affine white_matter = (labels == 1) | (labels == 2) csa_model = CsaOdfModel(gtab, sh_order=6) csa_peaks = peaks_from_model(csa_model, data, default_sphere, relative_peak_threshold=.8, min_separation_angle=45, mask=white_matter) classifier = ThresholdStoppingCriterion(csa_peaks.gfa, .25) seed_mask = labels == 2 seeds = utils.seeds_from_mask(seed_mask, density=[1, 1, 1], affine=affine) # Initialization of LocalTracking. # The computation happens in the next step. streamlines = LocalTracking(csa_peaks, classifier, seeds, affine, step_size=2) # Compute streamlines and store as a list. streamlines = list(streamlines) # Prepare the display objects. streamlines_actor = actor.line(streamlines, line_colors(streamlines)) seedroi_actor = actor.contour_from_roi(seed_mask, affine, [0, 1, 1], 0.5) # Create the 3d display. r = window.Scene() r2 = window.Scene() r.add(streamlines_actor) arr3 = window.snapshot(r, 'test_surface3.png', offscreen=True) report3 = window.analyze_snapshot(arr3, find_objects=True) r2.add(streamlines_actor) r2.add(seedroi_actor) arr4 = window.snapshot(r2, 'test_surface4.png', offscreen=True) report4 = window.analyze_snapshot(arr4, find_objects=True) # assert that the seed ROI rendering is not far # away from the streamlines (affine error) npt.assert_equal(report3.objects, report4.objects)
def initialize(self): # Bring used components self.registerVtkWebProtocol(protocols.vtkWebMouseHandler()) self.registerVtkWebProtocol(protocols.vtkWebViewPort()) self.registerVtkWebProtocol(protocols.vtkWebViewPortImageDelivery()) self.registerVtkWebProtocol(protocols.vtkWebViewPortGeometryDelivery()) # Update authentication key to use self.updateSecret(_WebSpheres.authKey) # Create default pipeline (Only once for all the session) if not _WebSpheres.view: # FURY specific code scene = window.Scene() scene.background((1, 1, 1)) n_points = 1000000 translate = 100 colors = 255 * np.random.rand(n_points, 3) centers = translate * np.random.rand(n_points, 3) - translate / 2 radius = np.random.rand(n_points) / 10 polydata = vtk.vtkPolyData() verts = np.array([[0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [1.0, 1.0, 0.0], [1.0, 0.0, 0.0]]) verts -= np.array([0.5, 0.5, 0]) big_verts = np.tile(verts, (centers.shape[0], 1)) big_cents = np.repeat(centers, verts.shape[0], axis=0) big_verts += big_cents # print(big_verts) big_scales = np.repeat(radius, verts.shape[0], axis=0) # print(big_scales) big_verts *= big_scales[:, np.newaxis] # print(big_verts) tris = np.array([[0, 1, 2], [2, 3, 0]], dtype='i8') big_tris = np.tile(tris, (centers.shape[0], 1)) shifts = np.repeat( np.arange(0, centers.shape[0] * verts.shape[0], verts.shape[0]), tris.shape[0]) big_tris += shifts[:, np.newaxis] # print(big_tris) big_cols = np.repeat(colors, verts.shape[0], axis=0) # print(big_cols) big_centers = np.repeat(centers, verts.shape[0], axis=0) # print(big_centers) big_centers *= big_scales[:, np.newaxis] # print(big_centers) set_polydata_vertices(polydata, big_verts) set_polydata_triangles(polydata, big_tris) set_polydata_colors(polydata, big_cols) vtk_centers = numpy_to_vtk(big_centers, deep=True) vtk_centers.SetNumberOfComponents(3) vtk_centers.SetName("center") polydata.GetPointData().AddArray(vtk_centers) canvas_actor = get_actor_from_polydata(polydata) canvas_actor.GetProperty().BackfaceCullingOff() mapper = canvas_actor.GetMapper() mapper.MapDataArrayToVertexAttribute( "center", "center", vtk.vtkDataObject.FIELD_ASSOCIATION_POINTS, -1) vtk_major_version = vtk.vtkVersion.GetVTKMajorVersion() vtk_minor_version = vtk.vtkVersion.GetVTKMinorVersion() if vtk_major_version > 8 or (vtk_major_version == 8 and vtk_minor_version >= 90): mapper = canvas_actor.GetShaderProperty() mapper.AddShaderReplacement( vtk.vtkShader.Vertex, "//VTK::ValuePass::Dec", True, """ //VTK::ValuePass::Dec in vec3 center; out vec3 centeredVertexMC; """, False) mapper.AddShaderReplacement( vtk.vtkShader.Vertex, "//VTK::ValuePass::Impl", True, """ //VTK::ValuePass::Impl centeredVertexMC = vertexMC.xyz - center; float scalingFactor = 1. / abs(centeredVertexMC.x); centeredVertexMC *= scalingFactor; vec3 cameraRight = vec3(MCVCMatrix[0][0], MCVCMatrix[1][0], MCVCMatrix[2][0]); vec3 cameraUp = vec3(MCVCMatrix[0][1], MCVCMatrix[1][1], MCVCMatrix[2][1]); vec2 squareVertices = vec2(.5, -.5); vec3 vertexPosition = center + cameraRight * squareVertices.x * vertexMC.x + cameraUp * squareVertices.y * vertexMC.y; gl_Position = MCDCMatrix * vec4(vertexPosition, 1.); gl_Position /= gl_Position.w; """, False) mapper.AddShaderReplacement( vtk.vtkShader.Fragment, "//VTK::ValuePass::Dec", True, """ //VTK::ValuePass::Dec in vec3 centeredVertexMC; """, False) mapper.AddShaderReplacement( vtk.vtkShader.Fragment, "//VTK::Light::Impl", True, """ // Renaming variables passed from the Vertex Shader vec3 color = vertexColorVSOutput.rgb; vec3 point = centeredVertexMC; float len = length(point); // VTK Fake Spheres float radius = 1.; if(len > radius) discard; vec3 normalizedPoint = normalize(vec3(point.xy, sqrt(1. - len))); vec3 direction = normalize(vec3(1., -1., 1.)); float df = max(0, dot(direction, normalizedPoint)); float sf = pow(df, 24); fragOutput0 = vec4(max(df * color, sf * vec3(1)), 1); """, False) scene.add(canvas_actor) #scene.add(actor.axes()) showm = window.ShowManager(scene) renderWindow = showm.window # VTK Web application specific _WebSpheres.view = renderWindow self.getApplication().GetObjectIdMap().\ SetActiveObject('VIEW', renderWindow)
""" shader_to_actor(utah, "vertex", impl_code=vertex_shader_code_impl, decl_code=vertex_shader_code_decl) shader_to_actor(utah, "fragment", decl_code=fragment_shader_code_decl) shader_to_actor(utah, "fragment", impl_code=fragment_shader_code_impl, block="light") ############################################################################### # Let's create a scene. scene = window.Scene() global timer timer = 0 ############################################################################## # The timer will call this user defined callback every 30 milliseconds. def timer_callback(obj, event): global timer timer += 1.0 showm.render() scene.azimuth(5)
def test_scene(): scene = window.Scene() # Scene size test npt.assert_equal(scene.size(), (0, 0)) # Color background test # Background color for scene (1, 0.5, 0). 0.001 added here to remove # numerical errors when moving from float to int values bg_float = (1, 0.501, 0) # That will come in the image in the 0-255 uint scale bg_color = tuple((np.round(255 * np.array(bg_float))).astype('uint8')) scene.background(bg_float) arr = window.snapshot(scene) report = window.analyze_snapshot(arr, bg_color=bg_color, colors=[bg_color, (0, 127, 0)]) npt.assert_equal(report.objects, 0) npt.assert_equal(report.colors_found, [True, False]) # Add actor to scene to test the remove actor function by analyzing a # snapshot axes = actor.axes() scene.add(axes) arr = window.snapshot(scene) report = window.analyze_snapshot(arr, 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) 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) 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) npt.assert_equal(report.objects, 0) # Test change background color from scene by analyzing the scene ren2 = window.Scene(bg_float) ren2.background((0, 0, 0.)) report = window.analyze_scene(ren2) npt.assert_equal(report.bg_color, (0, 0, 0)) # Add actor to scene to test the remove actor function by analyzing the # scene ren2.add(axes) report = window.analyze_scene(ren2) npt.assert_equal(report.actors, 1) # Test remove actor function by analyzing the scene ren2.rm(axes) report = window.analyze_scene(ren2) npt.assert_equal(report.actors, 0) # Test camera information retrieving with captured_output() as (out, err): scene.camera_info() npt.assert_equal( out.getvalue().strip(), '# Active Camera\n ' 'Position (0.00, 0.00, 1.00)\n ' 'Focal Point (0.00, 0.00, 0.00)\n ' 'View Up (0.00, 1.00, 0.00)') npt.assert_equal(err.getvalue().strip(), '') # Test skybox scene = window.Scene() npt.assert_equal(scene.GetUseImageBasedLighting(), False) npt.assert_equal(scene.GetAutomaticLightCreation(), 1) npt.assert_equal(scene.GetSphericalHarmonics(), None) npt.assert_equal(scene.GetEnvironmentTexture(), None) test_tex = Texture() scene = window.Scene(skybox=test_tex) npt.assert_equal(scene.GetUseImageBasedLighting(), True) npt.assert_equal(scene.GetAutomaticLightCreation(), 0) npt.assert_equal(scene.GetSphericalHarmonics(), None) npt.assert_equal(scene.GetEnvironmentTexture(), test_tex) # Test automatically shown skybox test_tex = Texture() test_tex.CubeMapOn() checker_arr = np.array([[1, 0], [0, 1]], dtype=np.uint8) * 255 for i in range(6): vtk_img = ImageData() vtk_img.SetDimensions(2, 2, 1) img_arr = np.zeros((2, 2, 3), dtype=np.uint8) img_arr[:, :, i // 2] = checker_arr vtk_arr = numpy_support.numpy_to_vtk( img_arr.reshape((-1, 3), order='F')) vtk_arr.SetName('Image') img_point_data = vtk_img.GetPointData() img_point_data.AddArray(vtk_arr) img_point_data.SetActiveScalars('Image') test_tex.SetInputDataObject(i, vtk_img) scene = window.Scene(skybox=test_tex) report = window.analyze_scene(scene) npt.assert_equal(report.actors, 1) ss = window.snapshot(scene) npt.assert_array_equal(ss[75, 75, :], [0, 0, 255]) npt.assert_array_equal(ss[75, 225, :], [0, 0, 0]) scene.yaw(90) ss = window.snapshot(scene) npt.assert_array_equal(ss[75, 75, :], [255, 0, 0]) npt.assert_array_equal(ss[75, 225, :], [0, 0, 0]) scene.pitch(90) ss = window.snapshot(scene) npt.assert_array_equal(ss[75, 75, :], [0, 0, 0]) npt.assert_array_equal(ss[75, 225, :], [0, 255, 0])
def test_record(): xyzr = np.array([[0, 0, 0, 10], [100, 0, 0, 25], [200, 0, 0, 50]]) colors = np.array([[1, 0, 0, 1], [0, 1, 0, 1], [0, 0, 1., 1]]) sphere_actor = actor.sphere(centers=xyzr[:, :3], colors=colors[:], radii=xyzr[:, 3], phi=30, theta=30, use_primitive=True) scene = window.Scene() scene.add(sphere_actor) def test_content(filename='fury.png', colors_found=(True, True)): npt.assert_equal(os.path.isfile(filename), True) arr = io.load_image(filename) report = window.analyze_snapshot(arr, colors=[(0, 255, 0), (0, 0, 255)]) npt.assert_equal(report.objects, 3) npt.assert_equal(report.colors_found, colors_found) return arr # Basic test with InTemporaryDirectory(): window.record(scene) test_content() # test out_path and path_numbering, n_frame with InTemporaryDirectory(): filename = "tmp_snapshot.png" window.record(scene, out_path=filename) test_content(filename) window.record(scene, out_path=filename, path_numbering=True) test_content(filename + "000000.png") window.record(scene, out_path=filename, path_numbering=True, n_frames=3) test_content(filename + "000000.png") test_content(filename + "000001.png") test_content(filename + "000002.png") npt.assert_equal(os.path.isfile(filename + "000003.png"), False) # test verbose with captured_output() as (out, _): window.record(scene, verbose=True) npt.assert_equal( out.getvalue().strip(), "Camera Position (315.32, 0.00, 536.73)\n" "Camera Focal Point (119.97, 0.00, 0.00)\n" "Camera View Up (0.00, 1.00, 0.00)") # test camera option with InTemporaryDirectory(): window.record(scene, cam_pos=(310, 0, 530), cam_focal=(120, 0, 0), cam_view=(0, 0, 1)) test_content() # test size and clipping # Skip it on Mac mainly due to offscreen case on Travis. It works well # with a display. Need to check if screen_clip works. Need to check if # ReadFrontBufferOff(), ShouldRerenderOn() could improved this OSX case. if not skip_osx: with InTemporaryDirectory(): window.record(scene, out_path='fury_1.png', size=(1000, 1000), magnification=5) npt.assert_equal(os.path.isfile('fury_1.png'), True) arr = io.load_image('fury_1.png') npt.assert_equal(arr.shape, (5000, 5000, 3)) window.record(scene, out_path='fury_2.png', size=(5000, 5000), screen_clip=True) npt.assert_equal(os.path.isfile('fury_2.png'), True) arr = io.load_image('fury_2.png') assert_less_equal(arr.shape[0], 5000) assert_less_equal(arr.shape[1], 5000)
def plot_an_odf_slice(odf_4d, full_sphere, background_data, tile_size, filename, centroid, axis, camera_distance, subtract_iso, mask_image): view_up = [(0., 0., 1.), (0., 0., 1.), (0., -1., 0.)] # Adjust the centroid so it's only a single slice slicenum = int(np.round(centroid)[axis]) centroid[axis] = 0 position = centroid.copy() position[axis] = position[axis] + camera_distance # Roll if viewing an axial slice roll = 3 if axis == 2 else 0 position[1] = position[1] - roll # Ensure the dimensions reflect that there is only one slice new_shape = list(odf_4d.shape) new_shape[axis] = 1 image_shape = new_shape[:3] if axis == 0: odf_slice = odf_4d[slicenum, :, :, :].reshape(new_shape) image_slice = background_data[slicenum, :, :].reshape(image_shape) elif axis == 1: odf_slice = odf_4d[:, slicenum, :, :].reshape(new_shape) image_slice = background_data[:, slicenum, :].reshape(image_shape) elif axis == 2: odf_slice = odf_4d[:, :, slicenum, :].reshape(new_shape) image_slice = background_data[:, :, slicenum].reshape(image_shape) # Tile to get the whole ODF odf_slice = np.tile(odf_slice, (1, 1, 1, 2)) if subtract_iso: odf_slice = odf_slice - odf_slice.min(3, keepdims=True) # Make graphics objects odf_actor = actor.odf_slicer(odf_slice, sphere=full_sphere, colormap=None, scale=0.6, mask=image_slice) image_actor = actor.slicer(image_slice, opacity=0.6, interpolation='nearest') image_size = (tile_size, tile_size) scene = window.Scene() scene.add(image_actor) scene.add(odf_actor) xfov_min, xfov_max = 0, new_shape[0] - 1 yfov_min, yfov_max = 0, new_shape[1] - 1 zfov_min, zfov_max = 0, new_shape[2] - 1 odf_actor.display_extent(xfov_min, xfov_max, yfov_min, yfov_max, zfov_min, zfov_max) image_actor.display_extent(xfov_min, xfov_max, yfov_min, yfov_max, zfov_min, zfov_max) scene.set_camera(focal_point=tuple(centroid), position=tuple(position), view_up=view_up[axis]) window.record(scene, out_path=filename, reset_camera=False, size=image_size) scene.clear()
def test_frame_rate_and_anti_aliasing(): """Testing frame rate with/out anti-aliasing""" length_ = 200 multi_samples = 32 max_peels = 8 st_x = np.arange(length_) st_y = np.sin(np.arange(length_)) st_z = np.zeros(st_x.shape) st = np.zeros((length_, 3)) st[:, 0] = st_x st[:, 1] = st_y st[:, 2] = st_z all_st = [] all_st.append(st) for i in range(1000): all_st.append(st + i * np.array([0., .5, 0])) # st_actor = actor.line(all_st, linewidth=1) # TODO: textblock disappears when lod=True st_actor = actor.streamtube(all_st, linewidth=0.1, lod=False) scene = window.Scene() scene.background((1, 1., 1)) # quick game style antialiasing scene.fxaa_on() scene.fxaa_off() # the good staff is later with multi-sampling tb = ui.TextBlock2D(font_size=40, color=(1, 0.5, 0)) panel = ui.Panel2D(position=(400, 400), size=(400, 400)) panel.add_element(tb, (0.2, 0.5)) counter = itertools.count() showm = window.ShowManager(scene, size=(1980, 1080), reset_camera=False, order_transparent=True, multi_samples=multi_samples, max_peels=max_peels, occlusion_ratio=0.0) showm.initialize() scene.add(panel) scene.add(st_actor) scene.reset_camera_tight() scene.zoom(5) class FrameRateHolder(object): fpss = [] frh = FrameRateHolder() def timer_callback(_obj, _event): cnt = next(counter) if cnt % 1 == 0: fps = np.round(scene.frame_rate, 0) frh.fpss.append(fps) msg = "FPS " + str(fps) + ' ' + str(cnt) tb.message = msg showm.render() if cnt > 10: showm.exit() # Run every 200 milliseconds showm.add_timer_callback(True, 200, timer_callback) showm.start() arr = window.snapshot(scene, size=(1980, 1080), offscreen=True, order_transparent=True, multi_samples=multi_samples, max_peels=max_peels, occlusion_ratio=0.0) assert_greater(np.sum(arr), 0) # TODO: check why in osx we have issues in Azure if not skip_osx: assert_greater(np.median(frh.fpss), 0) frh.fpss = [] counter = itertools.count() multi_samples = 0 showm = window.ShowManager(scene, size=(1980, 1080), reset_camera=False, order_transparent=True, multi_samples=multi_samples, max_peels=max_peels, occlusion_ratio=0.0) showm.initialize() showm.add_timer_callback(True, 200, timer_callback) showm.start() arr2 = window.snapshot(scene, size=(1980, 1080), offscreen=True, order_transparent=True, multi_samples=multi_samples, max_peels=max_peels, occlusion_ratio=0.0) assert_greater(np.sum(arr2), 0) if not skip_osx: assert_greater(np.median(frh.fpss), 0)
def plot_peak_slice(odf_4d, sphere, background_data, out_file, axis, slicenum, mask_data, tile_size=1200, normalize_peaks=True): view_up = [(0., 0., 1.), (0., 0., 1.), (0., -1., 0.)] # Make a slice mask to reduce memory new_shape = list(odf_4d.shape) new_shape[axis] = 1 image_shape = new_shape[:3] midpoint = (new_shape[0] / 2., new_shape[1] / 2., new_shape[2] / 2.) if axis == 0: odf_slice = odf_4d[slicenum, :, :, :].reshape(new_shape) image_slice = background_data[slicenum, :, :].reshape(image_shape) mask_slice = mask_data[slicenum, :, :].reshape(image_shape) camera_dist = max(midpoint[1], midpoint[2]) * np.pi elif axis == 1: odf_slice = odf_4d[:, slicenum, :, :].reshape(new_shape) image_slice = background_data[:, slicenum, :].reshape(image_shape) mask_slice = mask_data[:, slicenum, :].reshape(image_shape) camera_dist = max(midpoint[0], midpoint[2]) * np.pi elif axis == 2: odf_slice = odf_4d[:, :, slicenum, :].reshape(new_shape) image_slice = background_data[:, :, slicenum].reshape(image_shape) mask_slice = mask_data[:, :, slicenum].reshape(image_shape) camera_dist = max(midpoint[0], midpoint[1]) * np.pi position = list(midpoint) position[axis] += camera_dist # Find the actual peaks peak_dirs, peak_values = peaks_from_odfs(odf_slice, sphere, relative_peak_threshold=.1, min_separation_angle=15, mask=mask_slice, normalize_peaks=normalize_peaks, npeaks=3) if normalize_peaks: peak_values = peak_values / peak_values.max() * np.pi peak_actor = actor.peak_slicer(peak_dirs, peak_values, colors=None) image_actor = actor.slicer(image_slice, opacity=0.6, interpolation='nearest') image_size = (tile_size, tile_size) scene = window.Scene() scene.add(image_actor) scene.add(peak_actor) xfov_min, xfov_max = 0, new_shape[0] - 1 yfov_min, yfov_max = 0, new_shape[1] - 1 zfov_min, zfov_max = 0, new_shape[2] - 1 peak_actor.display_extent(xfov_min, xfov_max, yfov_min, yfov_max, zfov_min, zfov_max) image_actor.display_extent(xfov_min, xfov_max, yfov_min, yfov_max, zfov_min, zfov_max) scene.set_camera(focal_point=tuple(midpoint), position=tuple(position), view_up=view_up[axis]) window.record(scene, out_path=out_file, reset_camera=False, size=image_size)
def initialize_scene(self): self.scene = window.Scene() # Initialize a Plane actor with the 1st video frame along with # the actor grid which is to be updated in each iteration self.plane_actor = actor.texture(self.current_video_frame) self.scene.add(self.plane_actor)
def test_picking_manager(): xyz = 10 * np.random.rand(100, 3) colors = np.random.rand(100, 4) radii = np.random.rand(100) + 0.5 scene = window.Scene() sphere_actor = actor.sphere(centers=xyz, colors=colors, radii=radii) scene.add(sphere_actor) showm = window.ShowManager(scene, size=(900, 768), reset_camera=False, order_transparent=True) showm.initialize() tb = ui.TextBlock2D(bold=True) # use itertools to avoid global variables counter = itertools.count() pickm = pick.PickingManager() record_indices = { 'vertex_indices': [], 'face_indices': [], 'xyz': [], 'actor': [] } def timer_callback(_obj, _event): cnt = next(counter) tb.message = "Let's count up to 100 and exit :" + str(cnt) showm.scene.azimuth(0.05 * cnt) # sphere_actor.GetProperty().SetOpacity(cnt/100.) if cnt % 10 == 0: # pick at position info = pickm.pick((900 / 2, 768 / 2), scene) record_indices['vertex_indices'].append(info['vertex']) record_indices['face_indices'].append(info['face']) record_indices['xyz'].append(info['xyz']) record_indices['actor'].append(info['actor']) showm.render() if cnt == 15: showm.exit() scene.add(tb) # Run every 200 milliseconds showm.add_timer_callback(True, 200, timer_callback) showm.start() assert_greater(np.sum(np.array(record_indices['vertex_indices'])), 1) assert_greater(np.sum(np.array(record_indices['face_indices'])), 1) for ac in record_indices['actor']: if ac is not None: npt.assert_equal(ac is sphere_actor, True) assert_greater( np.sum(np.abs(np.diff(np.array(record_indices['xyz']), axis=0))), 0)
def test_peak_slicer(interactive=False): _peak_dirs = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype='f4') # peak_dirs.shape = (1, 1, 1) + peak_dirs.shape peak_dirs = np.zeros((11, 11, 11, 3, 3)) peak_values = np.random.rand(11, 11, 11, 3) peak_dirs[:, :, :] = _peak_dirs scene = window.Scene() peak_actor = actor.peak_slicer(peak_dirs) scene.add(peak_actor) scene.add(actor.axes((11, 11, 11))) if interactive: window.show(scene) scene.clear() scene.add(peak_actor) scene.add(actor.axes((11, 11, 11))) for k in range(11): peak_actor.display_extent(0, 10, 0, 10, k, k) for j in range(11): peak_actor.display_extent(0, 10, j, j, 0, 10) for i in range(11): peak_actor.display(i, None, None) scene.rm_all() peak_actor_sym = actor.peak_slicer(peak_dirs, peak_values, mask=None, affine=np.diag([3, 2, 1, 1]), colors=None, opacity=0.8, linewidth=3, lod=True, lod_points=10**4, lod_points_size=3) peak_actor_asym = actor.peak_slicer(peak_dirs, peak_values, mask=None, affine=np.diag([3, 2, 1, 1]), colors=None, opacity=0.8, linewidth=3, lod=True, lod_points=10**4, lod_points_size=3, symmetric=False) scene.add(peak_actor_sym) scene.add(peak_actor_asym) scene.add(actor.axes((11, 11, 11))) if interactive: window.show(scene) report = window.analyze_scene(scene) ex = ['vtkLODActor', 'vtkLODActor', 'vtkOpenGLActor'] npt.assert_equal(report.actors_classnames, ex) # 6d data data_6d = (255 * np.random.rand(5, 5, 5, 5, 5, 5)) npt.assert_raises(ValueError, actor.peak_slicer, data_6d, data_6d)
def test_custom_interactor_style_events(recording=False): print("Using VTK {}".format(vtk.vtkVersion.GetVTKVersion())) filename = "test_custom_interactor_style_events.log.gz" recording_filename = pjoin(DATA_DIR, filename) scene = window.Scene() # the show manager allows to break the rendering process # 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) # Create a cursor, a circle that will follow the mouse. polygon_source = vtk.vtkRegularPolygonSource() polygon_source.GeneratePolygonOff() # Only the outline of the circle. polygon_source.SetNumberOfSides(50) polygon_source.SetRadius(10) # polygon_source.SetRadius polygon_source.SetCenter(0, 0, 0) mapper = vtk.vtkPolyDataMapper2D() vtk_utils.set_input(mapper, polygon_source.GetOutputPort()) cursor = vtk.vtkActor2D() cursor.SetMapper(mapper) cursor.GetProperty().SetColor(1, 0.5, 0) scene.add(cursor) def follow_mouse(iren, obj): obj.SetPosition(*iren.event.position) iren.force_render() interactor_style.add_active_prop(cursor) interactor_style.add_callback(cursor, "MouseMoveEvent", follow_mouse) # create some minimalistic streamlines lines = [ np.array([[-1, 0, 0.], [1, 0, 0.]]), np.array([[-1, 1, 0.], [1, 1, 0.]]) ] colors = np.array([[1., 0., 0.], [0.3, 0.7, 0.]]) tube1 = actor.streamtube([lines[0]], colors[0]) tube2 = actor.streamtube([lines[1]], colors[1]) scene.add(tube1) scene.add(tube2) # Define some counter callback. states = defaultdict(lambda: 0) def counter(iren, _obj): states[iren.event.name] += 1 # Assign the counter callback to every possible event. for event in [ "CharEvent", "MouseMoveEvent", "KeyPressEvent", "KeyReleaseEvent", "LeftButtonPressEvent", "LeftButtonReleaseEvent", "RightButtonPressEvent", "RightButtonReleaseEvent", "MiddleButtonPressEvent", "MiddleButtonReleaseEvent" ]: interactor_style.add_callback(tube1, event, counter) # Add callback to scale up/down tube1. def scale_up_obj(iren, obj): counter(iren, obj) scale = np.asarray(obj.GetScale()) + 0.1 obj.SetScale(*scale) iren.force_render() iren.event.abort() # Stop propagating the event. def scale_down_obj(iren, obj): counter(iren, obj) scale = np.array(obj.GetScale()) - 0.1 obj.SetScale(*scale) iren.force_render() iren.event.abort() # Stop propagating the event. interactor_style.add_callback(tube2, "MouseWheelForwardEvent", scale_up_obj) interactor_style.add_callback(tube2, "MouseWheelBackwardEvent", scale_down_obj) # Add callback to hide/show tube1. def toggle_visibility(iren, obj): key = iren.event.key if key.lower() == "v": obj.SetVisibility(not obj.GetVisibility()) iren.force_render() interactor_style.add_active_prop(tube1) interactor_style.add_active_prop(tube2) interactor_style.remove_active_prop(tube2) interactor_style.add_callback(tube1, "CharEvent", toggle_visibility) if recording: show_manager.record_events_to_file(recording_filename) print(list(states.items())) else: show_manager.play_events_from_file(recording_filename) msg = ("Wrong count for '{}'.") expected = [('CharEvent', 6), ('KeyPressEvent', 6), ('KeyReleaseEvent', 6), ('MouseMoveEvent', 1652), ('LeftButtonPressEvent', 1), ('RightButtonPressEvent', 1), ('MiddleButtonPressEvent', 2), ('LeftButtonReleaseEvent', 1), ('MouseWheelForwardEvent', 3), ('MouseWheelBackwardEvent', 1), ('MiddleButtonReleaseEvent', 2), ('RightButtonReleaseEvent', 1)] # Useful loop for debugging. for event, count in expected: if states[event] != count: print("{}: {} vs. {} (expected)".format( event, states[event], count)) for event, count in expected: npt.assert_equal(states[event], count, err_msg=msg.format(event))
def test_tensor_slicer(interactive=False): evals = np.array([1.4, .35, .35]) * 10**(-3) evecs = np.eye(3) mevals = np.zeros((3, 2, 4, 3)) mevecs = np.zeros((3, 2, 4, 3, 3)) mevals[..., :] = evals mevecs[..., :, :] = evecs sphere = get_sphere('symmetric724') affine = np.eye(4) scene = window.Scene() tensor_actor = actor.tensor_slicer(mevals, mevecs, affine=affine, sphere=sphere, scale=.3, opacity=0.4) _, J, K = mevals.shape[:3] scene.add(tensor_actor) scene.reset_camera() scene.reset_clipping_range() tensor_actor.display_extent(0, 1, 0, J, 0, K) if interactive: window.show(scene, reset_camera=False) tensor_actor.GetProperty().SetOpacity(1.0) if interactive: window.show(scene, reset_camera=False) npt.assert_equal(scene.GetActors().GetNumberOfItems(), 1) # Test extent big_extent = scene.GetActors().GetLastActor().GetBounds() big_extent_x = abs(big_extent[1] - big_extent[0]) tensor_actor.display(x=2) if interactive: window.show(scene, reset_camera=False) small_extent = scene.GetActors().GetLastActor().GetBounds() small_extent_x = abs(small_extent[1] - small_extent[0]) npt.assert_equal(big_extent_x > small_extent_x, True) # Test empty mask empty_actor = actor.tensor_slicer(mevals, mevecs, affine=affine, mask=np.zeros(mevals.shape[:3]), sphere=sphere, scale=.3) npt.assert_equal(empty_actor.GetMapper(), None) # Test mask mask = np.ones(mevals.shape[:3]) mask[:2, :3, :3] = 0 cfa = color_fa(fractional_anisotropy(mevals), mevecs) tensor_actor = actor.tensor_slicer(mevals, mevecs, affine=affine, mask=mask, scalar_colors=cfa, sphere=sphere, scale=.3) scene.clear() scene.add(tensor_actor) scene.reset_camera() scene.reset_clipping_range() if interactive: window.show(scene, reset_camera=False) mask_extent = scene.GetActors().GetLastActor().GetBounds() mask_extent_x = abs(mask_extent[1] - mask_extent[0]) npt.assert_equal(big_extent_x > mask_extent_x, True) # test display tensor_actor.display() current_extent = scene.GetActors().GetLastActor().GetBounds() current_extent_x = abs(current_extent[1] - current_extent[0]) npt.assert_equal(big_extent_x > current_extent_x, True) if interactive: window.show(scene, reset_camera=False) tensor_actor.display(y=1) current_extent = scene.GetActors().GetLastActor().GetBounds() current_extent_y = abs(current_extent[3] - current_extent[2]) big_extent_y = abs(big_extent[3] - big_extent[2]) npt.assert_equal(big_extent_y > current_extent_y, True) if interactive: window.show(scene, reset_camera=False) tensor_actor.display(z=1) current_extent = scene.GetActors().GetLastActor().GetBounds() current_extent_z = abs(current_extent[5] - current_extent[4]) big_extent_z = abs(big_extent[5] - big_extent[4]) npt.assert_equal(big_extent_z > current_extent_z, True) if interactive: window.show(scene, reset_camera=False) # Test error handling of the method when # incompatible dimension of mevals and evecs are passed. mevals = np.zeros((3, 2, 3)) mevecs = np.zeros((3, 2, 4, 3, 3)) with npt.assert_raises(RuntimeError): tensor_actor = actor.tensor_slicer(mevals, mevecs, affine=affine, mask=mask, scalar_colors=cfa, sphere=sphere, scale=.3)
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), 1.) 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.5, 0), 1.) 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.5, 0.5), 1.) scene = window.Scene() actors = [] texts = [] actors.append(contour_actor1) text_actor1 = actor.text_3d('cube 1', justification='center') texts.append(text_actor1) actors.append(contour_actor2) text_actor2 = actor.text_3d('cube 2', justification='center') texts.append(text_actor2) actors.append(contour_actor3) text_actor3 = actor.text_3d('cube 3', justification='center') texts.append(text_actor3) actors.append(shallow_copy(contour_actor1)) text_actor1 = 'cube 4' texts.append(text_actor1) actors.append(shallow_copy(contour_actor2)) text_actor2 = 'cube 5' texts.append(text_actor2) actors.append(shallow_copy(contour_actor3)) text_actor3 = 'cube 6' texts.append(text_actor3) # show the grid without the captions container = grid(actors=actors, captions=None, caption_offset=(0, -40, 0), cell_padding=(10, 10), dim=(2, 3)) scene.add(container) scene.projection('orthogonal') counter = itertools.count() show_m = window.ShowManager(scene) show_m.initialize() def timer_callback(_obj, _event): cnt = next(counter) # show_m.scene.zoom(1) show_m.render() if cnt == 4: show_m.exit() show_m.destroy_timers() show_m.add_timer_callback(True, 200, timer_callback) show_m.start() arr = window.snapshot(scene) arr[arr < 20] = 0 report = window.analyze_snapshot(arr) npt.assert_equal(report.objects, 6) scene.rm_all() counter = itertools.count() show_m = window.ShowManager(scene) show_m.initialize() # show the grid with the captions container = grid(actors=actors, captions=texts, caption_offset=(0, -50, 0), cell_padding=(10, 10), dim=(3, 3)) scene.add(container) show_m.add_timer_callback(True, 200, timer_callback) show_m.start() arr = window.snapshot(scene) report = window.analyze_snapshot(arr) npt.assert_equal(report.objects > 6, True)
def test_button_and_slider_widgets(): recording = False filename = "test_button_and_slider_widgets.log.gz" recording_filename = pjoin(DATA_DIR, filename) scene = window.Scene() # create some minimalistic streamlines lines = [ np.array([[-1, 0, 0.], [1, 0, 0.]]), np.array([[-1, 1, 0.], [1, 1, 0.]]) ] colors = np.array([[1., 0., 0.], [0.3, 0.7, 0.]]) stream_actor = actor.streamtube(lines, colors) states = { 'camera_button_count': 0, 'plus_button_count': 0, 'minus_button_count': 0, 'slider_moved_count': 0, } scene.add(stream_actor) # the show manager allows to break the rendering process # in steps so that the widgets can be added properly show_manager = window.ShowManager(scene, size=(800, 800)) if recording: show_manager.initialize() show_manager.render() def button_callback(obj, event): # print('Camera pressed') states['camera_button_count'] += 1 def button_plus_callback(obj, event): # print('+ pressed') states['plus_button_count'] += 1 def button_minus_callback(obj, event): # print('- pressed') states['minus_button_count'] += 1 fetch_viz_icons() button_png = read_viz_icons(fname='camera.png') button = widget.button(show_manager.iren, show_manager.scene, button_callback, button_png, (.98, 1.), (80, 50)) button_png_plus = read_viz_icons(fname='plus.png') button_plus = widget.button(show_manager.iren, show_manager.scene, button_plus_callback, button_png_plus, (.98, .9), (120, 50)) button_png_minus = read_viz_icons(fname='minus.png') button_minus = widget.button(show_manager.iren, show_manager.scene, button_minus_callback, button_png_minus, (.98, .9), (50, 50)) def print_status(obj, event): rep = obj.GetRepresentation() stream_actor.SetPosition((rep.GetValue(), 0, 0)) states['slider_moved_count'] += 1 slider = widget.slider(show_manager.iren, show_manager.scene, callback=print_status, min_value=-1, max_value=1, value=0., label="X", right_normalized_pos=(.98, 0.6), size=(120, 0), label_format="%0.2lf") # This callback is used to update the buttons/sliders' position # so they can stay on the right side of the window when the window # is being resized. global size size = scene.GetSize() if recording: show_manager.record_events_to_file(recording_filename) print(states) else: show_manager.play_events_from_file(recording_filename) npt.assert_equal(states["camera_button_count"], 7) npt.assert_equal(states["plus_button_count"], 3) npt.assert_equal(states["minus_button_count"], 4) npt.assert_equal(states["slider_moved_count"], 116) if not recording: button.Off() slider.Off() # Uncomment below to test the slider and button with analyze # button.place(scene) # slider.place(scene) report = window.analyze_scene(scene) # import pylab as plt # plt.imshow(report.labels, origin='lower') # plt.show() npt.assert_equal(report.actors, 1) report = window.analyze_scene(scene) npt.assert_equal(report.actors, 1)
def test_sdf_actor(interactive=False): scene = window.Scene() scene.background((1, 1, 1)) centers = np.array([[2, 0, 0], [0, 2, 0], [0, 0, 0], [2, 2, 0]]) * 11 colors = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 0]]) directions = np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1], [1, 1, 0]]) scales = [1, 2, 3, 4] primitive = ['sphere', 'ellipsoid', 'torus', 'capsule'] sdf_actor = actor.sdf(centers, directions, colors, primitive, scales) scene.add(sdf_actor) scene.add(actor.axes()) if interactive: window.show(scene) arr = window.snapshot(scene) report = window.analyze_snapshot(arr, colors=colors) npt.assert_equal(report.objects, 4) # Draw 3 spheres as the primitive type is str scene.clear() primitive = 'sphere' sdf_actor = actor.sdf(centers, directions, colors, primitive, scales) scene.add(sdf_actor) scene.add(actor.axes()) if interactive: window.show(scene) arr = window.snapshot(scene) report = window.analyze_snapshot(arr, colors=colors) npt.assert_equal(report.objects, 4) # A sphere and default back to two torus # as the primitive type is list scene.clear() primitive = ['sphere'] with npt.assert_warns(UserWarning): sdf_actor = actor.sdf(centers, directions, colors, primitive, scales) scene.add(sdf_actor) scene.add(actor.axes()) if interactive: window.show(scene) arr = window.snapshot(scene) report = window.analyze_snapshot(arr, colors=colors) npt.assert_equal(report.objects, 4) # One sphere and ellipsoid each # Default to torus scene.clear() primitive = ['sphere', 'ellipsoid'] with npt.assert_warns(UserWarning): sdf_actor = actor.sdf(centers, directions, colors, primitive, scales) scene.add(sdf_actor) scene.add(actor.axes()) if interactive: window.show(scene) arr = window.snapshot(scene) report = window.analyze_snapshot(arr, colors=colors) npt.assert_equal(report.objects, 4)
def test_active_camera(): scene = window.Scene() scene.add(actor.axes(scale=(1, 1, 1))) scene.reset_camera() scene.reset_clipping_range() direction = scene.camera_direction() position, focal_point, view_up = scene.get_camera() scene.set_camera((0., 0., 1.), (0., 0., 0), view_up) position, focal_point, view_up = scene.get_camera() npt.assert_almost_equal(np.dot(direction, position), -1) scene.zoom(1.5) new_position, _, _ = scene.get_camera() npt.assert_array_almost_equal(position, new_position) scene.zoom(1) # rotate around focal point scene.azimuth(90) position, _, _ = scene.get_camera() npt.assert_almost_equal(position, (1.0, 0.0, 0)) arr = window.snapshot(scene) report = window.analyze_snapshot(arr, colors=[(255, 0, 0)]) npt.assert_equal(report.colors_found, [True]) # rotate around camera's center scene.yaw(90) arr = window.snapshot(scene) report = window.analyze_snapshot(arr, colors=[(0, 0, 0)]) npt.assert_equal(report.colors_found, [True]) scene.yaw(-90) scene.elevation(90) arr = window.snapshot(scene) report = window.analyze_snapshot(arr, colors=(0, 255, 0)) npt.assert_equal(report.colors_found, [True]) scene.set_camera((0., 0., 1.), (0., 0., 0), view_up) # vertical rotation of the camera around the focal point scene.pitch(10) scene.pitch(-10) # rotate around the direction of projection scene.roll(90) # inverted normalized distance from focal point along the direction # of the camera position, _, _ = scene.get_camera() scene.dolly(0.5) new_position, focal_point, view_up = scene.get_camera() npt.assert_almost_equal(position[2], 0.5 * new_position[2]) cam = scene.camera() npt. assert_equal(new_position, cam.GetPosition()) npt. assert_equal(focal_point, cam.GetFocalPoint()) npt. assert_equal(view_up, cam.GetViewUp())
def main(): # Callback required for FURY def keypress_callback(obj, _): key = obj.GetKeySym().lower() nonlocal clusters_linewidth, background_linewidth nonlocal curr_streamlines_actor, concat_streamlines_actor, show_curr_actor iterator = len(accepted_streamlines) + len(rejected_streamlines) renwin = interactor_style.GetInteractor().GetRenderWindow() renderer = interactor_style.GetCurrentRenderer() if key == 'c' and iterator < len(sft_accepted_on_size): if show_curr_actor: renderer.rm(concat_streamlines_actor) renwin.Render() show_curr_actor = False logging.info('Streamlines rendering OFF') else: renderer.add(concat_streamlines_actor) renderer.rm(curr_streamlines_actor) renderer.add(curr_streamlines_actor) renwin.Render() show_curr_actor = True logging.info('Streamlines rendering ON') return if key == 'q': show_manager.exit() if iterator < len(sft_accepted_on_size): logging.warning( 'Early exit, everything remaining to be rejected.') return if key in ['a', 'r'] and iterator < len(sft_accepted_on_size): if key == 'a': accepted_streamlines.append(iterator) choices.append('a') logging.info('Accepted file {}'.format( filename_accepted_on_size[iterator])) elif key == 'r': rejected_streamlines.append(iterator) choices.append('r') logging.info('Rejected file {}'.format( filename_accepted_on_size[iterator])) iterator += 1 if key == 'z': if iterator > 0: last_choice = choices.pop() if last_choice == 'r': rejected_streamlines.pop() else: accepted_streamlines.pop() logging.info('Rewind on step.') iterator -= 1 else: logging.warning('Cannot rewind, first element.') if key in ['a', 'r', 'z'] and iterator < len(sft_accepted_on_size): renderer.rm(curr_streamlines_actor) curr_streamlines = sft_accepted_on_size[iterator].streamlines curr_streamlines_actor = actor.line(curr_streamlines, opacity=0.8, linewidth=clusters_linewidth) renderer.add(curr_streamlines_actor) if iterator == len(sft_accepted_on_size): print('No more cluster, press q to exit') renderer.rm(curr_streamlines_actor) renwin.Render() parser = _build_arg_parser() args = parser.parse_args() assert_inputs_exist(parser, args.in_bundles) assert_outputs_exist(parser, args, [args.out_accepted, args.out_rejected]) if args.out_accepted_dir: assert_output_dirs_exist_and_empty(parser, args, args.out_accepted_dir, create_dir=True) if args.out_rejected_dir: assert_output_dirs_exist_and_empty(parser, args, args.out_rejected_dir, create_dir=True) if args.verbose: logging.basicConfig(level=logging.INFO) if args.min_cluster_size < 1: parser.error('Minimum cluster size must be at least 1.') clusters_linewidth = args.clusters_linewidth background_linewidth = args.background_linewidth # To accelerate procedure, clusters can be discarded based on size # Concatenation is to give spatial context sft_accepted_on_size, filename_accepted_on_size = [], [] sft_rejected_on_size, filename_rejected_on_size = [], [] concat_streamlines = [] for filename in args.in_bundles: if not is_header_compatible(args.in_bundles[0], filename): return basename = os.path.basename(filename) sft = load_tractogram_with_reference(parser, args, filename, bbox_check=False) if len(sft) >= args.min_cluster_size: sft_accepted_on_size.append(sft) filename_accepted_on_size.append(basename) concat_streamlines.extend(sft.streamlines) else: logging.info('File {} has {} streamlines,' 'automatically rejected.'.format(filename, len(sft))) sft_rejected_on_size.append(sft) filename_rejected_on_size.append(basename) if not filename_accepted_on_size: parser.error('No cluster survived the cluster_size threshold.') logging.info('{} clusters to be classified.'.format( len(sft_accepted_on_size))) # The clusters are sorted by size for simplicity/efficiency tuple_accepted = zip( *sorted(zip(sft_accepted_on_size, filename_accepted_on_size), key=lambda x: len(x[0]), reverse=True)) sft_accepted_on_size, filename_accepted_on_size = tuple_accepted # Initialize the actors, scene, window, observer concat_streamlines_actor = actor.line(concat_streamlines, colors=(1, 1, 1), opacity=args.background_opacity, linewidth=background_linewidth) curr_streamlines_actor = actor.line(sft_accepted_on_size[0].streamlines, opacity=0.8, linewidth=clusters_linewidth) scene = window.Scene() interactor_style = interactor.CustomInteractorStyle() show_manager = window.ShowManager(scene, size=(800, 800), reset_camera=False, interactor_style=interactor_style) scene.add(concat_streamlines_actor) scene.add(curr_streamlines_actor) interactor_style.AddObserver('KeyPressEvent', keypress_callback) # Lauch rendering and selection procedure choices, accepted_streamlines, rejected_streamlines = [], [], [] show_curr_actor = True show_manager.start() # Early exit means everything else is rejected missing = len(args.in_bundles) - len(choices) - len(sft_rejected_on_size) len_accepted = len(sft_accepted_on_size) rejected_streamlines.extend(range(len_accepted - missing, len_accepted)) if missing > 0: logging.info('{} clusters automatically rejected' 'from early exit'.format(missing)) # Save accepted clusters (by GUI) accepted_streamlines = save_clusters(sft_accepted_on_size, accepted_streamlines, args.out_accepted_dir, filename_accepted_on_size) accepted_sft = StatefulTractogram(accepted_streamlines, sft_accepted_on_size[0], Space.RASMM) save_tractogram(accepted_sft, args.out_accepted, bbox_valid_check=False) # Save rejected clusters (by GUI) rejected_streamlines = save_clusters(sft_accepted_on_size, rejected_streamlines, args.out_rejected_dir, filename_accepted_on_size) # Save rejected clusters (by size) rejected_streamlines.extend( save_clusters(sft_rejected_on_size, range(len(sft_rejected_on_size)), args.out_rejected_dir, filename_rejected_on_size)) rejected_sft = StatefulTractogram(rejected_streamlines, sft_accepted_on_size[0], Space.RASMM) save_tractogram(rejected_sft, args.out_rejected, bbox_valid_check=False)