def __init__(self): HasTraits.__init__(self) x, y, z = ogrid[-10:10:100j, -10:10:100j, -10:10:100j] scalars = sin(x*y*z)/(x*y*z) src = ArraySource(scalar_data=scalars) self.scene.mayavi_scene.add_child(src) src.add_module(IsoSurface())
def __init__(self): HasTraits.__init__(self) x, y, z = ogrid[-10:10, -10:10, -10:10] scalars = x**2 + y**2 + z**2 src = ArraySource(scalar_data=scalars) self.scene.mayavi_scene.add_child(src) src.add_module(IsoSurface())
def on_patient_loaded(self, msg): self.data = msg.data ct_data = self.data.voxelplan_images x, y, z = ogrid[0:1:ct_data.dimx, 0:1:ct_data.dimy, 0:1:ct_data.dimz] src = ArraySource(scalar_data=ct_data.cube) self.scene.engine.add_source(src) src.add_module(IsoSurface())
def __init__(self): HasTraits.__init__(self) # Create some data, and plot it using the embedded scene's engine x, y, z = ogrid[-10:10:100j, -10:10:100j, -10:10:100j] scalars = sin(x * y * z) / (x * y * z) src = ArraySource(scalar_data=scalars) self.scene.engine.add_source(src) src.add_module(IsoSurface())
def affine_img_src(data, affine, scale=1, name='AffineImage', reverse_x=False): """ Make a Mayavi source defined by a 3D array and an affine, for wich the voxel of the 3D array are mapped by the affine. Parameters ----------- data: 3D ndarray The data arrays affine: (4 x 4) ndarray The (4 x 4) affine matrix relating voxels to world coordinates. scale: float, optional An optional addition scaling factor. name: string, optional The name of the Mayavi source created. reverse_x: boolean, optional Reverse the x (lateral) axis. Useful to compared with images in radiologic convention. Notes ------ The affine should be diagonal. """ # Late import to avoid triggering wx imports before needed. try: from mayavi.sources.api import ArraySource except ImportError: # Try out old install of Mayavi, with namespace packages from enthought.mayavi.sources.api import ArraySource center = np.r_[0, 0, 0, 1] spacing = np.diag(affine)[:3] origin = np.dot(affine, center)[:3] if reverse_x: # Radiologic convention spacing[0] *= -1 origin[0] *= -1 src = ArraySource(scalar_data=np.asarray(data, dtype=np.float), name=name, spacing=scale * spacing, origin=scale * origin) return src
def visStack(v, opacity=.5, color=(1, 0, 0), mode=''): if mode != 'same': mlab.figure(bgcolor=(1, 1, 1)) s = mlab.get_engine() # Returns the running mayavi engine. scene = s.current_scene # Returns the current scene. scene.scene.disable_render = True # for speed origion = [0, 0, 0] label = 'Segmentation' A = ArraySource(scalar_data=v) A.origin = np.array(origion) D = s.add_source(A) # add the data to the Mayavi engine #Apply gaussain 3d filter to smooth visualization # F=mlab.pipeline.user_defined(D, filter='ImageGaussianSmooth') # F.filter.set_standard_deviation(0,0,0) contour = Contour() s.add_filter(contour) # smooth = mlab.pipeline.user_defined(contour, filter='SmoothPolyDataFilter') # smooth.filter.number_of_iterations = 1 # smooth.filter.relaxation_factor = 0 surface = Surface() s.add_module(surface) surface.module_manager.scalar_lut_manager.lut_mode = u'coolwarm' surface.module_manager.scalar_lut_manager.reverse_lut = True surface.actor.property.opacity = opacity surface.actor.mapper.scalar_visibility = False surface.actor.property.color = color #color return surface
def init_view_objects(self, *args): """Initialize (or re-initialize) all the view elements in the scene. This needs to be called when q-space modeled area changes (changing the outline) or q-resolution, etc. """ #Prevent drawing all the intermediate steps self.scene.disable_render = True #First, we need to remove any data sources and modules from a previous run, # if they exist. # (this is only needed when chaning q-space parameters) for x in [ 'data_src', 'point_data_src', 'iso', 'points_module_surface', 'points_module_glyph', 'outline', 'mouse_text', 'mouse_cube' ]: if hasattr(self, x): getattr(self, x).remove() #Now the corner labels if hasattr(self, 'corner_text'): for txt in self.corner_text: txt.remove() engine = self.engine #We get the qspace_displayed array from experiment and make a copy of it. # This object will REMAIN here and just have its data updated. self.data_src = ArraySource( scalar_data=model.experiment.exp.get_qspace_displayed().copy()) self.data_src.scalar_name = "coverage" self.data_src.visible = False engine.add_source(self.data_src) # --- Text overlay for warnings ---- txt = Text(text="(Points were thinned down)", position_in_3d=False) txt.x_position = 0.02 txt.y_position = 0.98 txt.actor.text_scale_mode = "none" txt.actor.text_property.font_size = 14 txt.actor.text_property.vertical_justification = "top" self.warning_text = txt engine.add_module(self.warning_text) self.warning_text.visible = self.warning_text_visible #---- Make the isosurface object that goes with the volume coverage data ----- iso = IsoSurface() self.iso = iso #Scale the isosurface so that the size is actually q-vector iso.actor.actor.scale = tuple( np.array([1.0, 1.0, 1.0]) * model.experiment.exp.inst.q_resolution) #And we offset the position so that the center is at q-space (0,0,0) iso.actor.actor.position = tuple( np.array([1.0, 1.0, 1.0]) * -model.experiment.exp.inst.qlim) # When set to 1, This helps them to show up right in partially transparent mode. iso.actor.property.backface_culling = 0 iso.actor.property.frontface_culling = 0 #Add the module to the data source, to make it plot that data self.data_src.add_module(iso) # ---- Now we make a point data source, for the individual reflection plot --- self.point_data_src = VTKDataSource(name="Reflection point positions") self.point_data_src.visible = False engine.add_source(self.point_data_src) self.point_data_src.data = self.make_point_data( ) #still needs to get set. # ---- Make a module of simple points, using the Surface module ---- self.points_module_surface = Surface() self.points_module_surface.name = "Single reflections as pixels (Surface)" self.point_data_src.add_module(self.points_module_surface) # points representation = just plot a pixel for each vertex. self.points_module_surface.actor.property.set(representation='points', point_size=3) # ---- Make a module of glyphs, making spheres for each point ---- self.points_module_glyph = Glyph() self.points_module_glyph.name = "Single reflections as spheres (Glyph)" #No scaling of glyph size with scalar data self.points_module_glyph.glyph.scale_mode = 'data_scaling_off' gs = self.points_module_glyph.glyph.glyph_source gs.glyph_source = gs.glyph_dict['sphere_source'] #How many vertices does each sphere have? 3 = fastest. gs.glyph_source.phi_resolution = 3 gs.glyph_source.theta_resolution = 3 #And how big does each sphere end up? gs.glyph_source.radius = 0.1 #Add the module to the same point data source, to show it self.point_data_src.add_module(self.points_module_glyph) # Hide points initially self.points_module_surface.visible = False self.points_module_glyph.visible = False #Get the color look-up table self.points_lut = self.points_module_glyph.module_manager.scalar_lut_manager.lut.table.to_array( ) self.points_lut_original = 1 * self.points_lut # ---- Simple outline for all of the data. ----- self.outline = Outline() #Manually make the outline = the modeled volume, which is +- qlim = 1/d_min self.outline.manual_bounds = True self.outline.bounds = tuple( np.array([-1., 1., -1., 1., -1., 1.]) * model.experiment.exp.inst.qlim) #Add it to the scene directly. engine.add_module(self.outline) #--- Label the HKL of the corners --- if config_gui.cfg.label_corners: q = model.instrument.inst.qlim #This the reciprocal lattice vectors rec = model.experiment.exp.crystal.reciprocal_lattice self.corner_text = [] for x in [-q, q]: for y in [-q, q]: for z in [-q, q]: (h, k, l) = model.crystal_calc.get_hkl_from_q( column([x, y, z]), rec) label = "%d,%d,%d" % (h, k, l) txt = Text(text=label, position_in_3d=False) txt.position_in_3d = True txt.x_position = x txt.y_position = y txt.z_position = z txt.actor.text_scale_mode = "none" txt.actor.text_property.font_size = 14 txt.actor.text_property.vertical_justification = "top" txt.actor.text_property.justification = "left" txt.actor.property.color = (0.75, 1.0, 1.0) engine.add_module(txt) self.corner_text.append(txt) # ---- A text overlay, to show what is under the mouse ----- # self.mouse_text = Text(text=self.MOUSE_TEXT_WITH_NO_REFLECTION, position_in_3d=False) # self.mouse_text.x_position=0.02 # self.mouse_text.y_position=0.98 # self.mouse_text.actor.text_scale_mode = "none" # self.mouse_text.actor.text_property.font_size = 20 # self.mouse_text.actor.text_property.vertical_justification = "top" # engine.add_module(self.mouse_text) # ---- A cube highlighting where the mouse is ---- self.mouse_cube = Glyph() self.mouse_cube.name = "Cube highlighting mouse position (Glyph)" #No scaling of glyph size with scalar data self.mouse_cube.glyph.scale_mode = 'data_scaling_off' self.mouse_cube.glyph.color_mode = 'no_coloring' gs = self.mouse_cube.glyph.glyph_source gs.glyph_source = gs.glyph_dict['cube_source'] self.mouse_cube.actor.property.representation = "wireframe" self.mouse_cube.actor.property.specular = 1.0 # to make edge always white self.mouse_point_data_src = VTKDataSource() self.mouse_point_data_src.name = "Mouse position (VTK Data)" self.mouse_point_data_src.visible = True engine.add_source(self.mouse_point_data_src) self.mouse_point_data_src.data = self.make_single_point_data((0, 0, 0)) self.mouse_point_data_src.add_module(self.mouse_cube) self.mouse_cube.visible = False # #--- Reciprocal axes 3D view ---- # c = model.experiment.exp.crystal #@type c Crystal # (a,b,c) = (c.recip_a, c.recip_b, c.recip_c) # offset = model.experiment.exp.inst.qlim # self.scene.mlab.plot3d([offset, offset+a[0]], [offset, offset+a[1]], [offset, offset+a[2]], color=(1,0,0)) # self.scene.mlab.plot3d([offset, offset+b[0]], [offset, offset+b[1]], [offset, offset+b[2]], color=(0,1,0)) # self.scene.mlab.plot3d([offset, offset+c[0]], [offset, offset+c[1]], [offset, offset+c[2]], color=(0,0,1)) #Re-enable drawing self.scene.disable_render = False