def on_draw(self, event): gloo.clear() if self.data is not None: # Draw first the data, then colormap, and then linecut cmap_texture = gloo.Texture1D(self.colormap.get_colors(), interpolation='linear') # Drawing of the plot self.data_program['u_colormap'] = cmap_texture self.data_program['z_min'] = self.colormap.min self.data_program['z_max'] = self.colormap.max self.data_program.draw('triangles') # Drawing of the colormap bar self.colorbar_program['u_colormap'] = cmap_texture colorbar_vertices = [(self.xmax + self.cm_dx * .2, self.ymax), (self.xmax + self.cm_dx * .2, self.ymin), (self.xmax + self.cm_dx, self.ymax), (self.xmax + self.cm_dx, self.ymin)] self.colorbar_program['a_position'] = colorbar_vertices self.colorbar_program['a_texcoord'] = [[1], [0], [1], [0]] self.colorbar_program.draw('triangle_strip') # Drawing of the linecut self.linecut_program.draw('lines') self.has_redrawn = True
def node_colors(self, value): self._node_colors = value value = value.astype(np.float32) value = np.concatenate([value[0:1, :], value, value[-2:-1, :]], axis=0) nodes_colormap = gloo.Texture1D(data=value, interpolation='linear', wrapping='clamp_to_edge') self.nodes_program['depth_colormap'] = nodes_colormap self.nodes_program['num_depth_colors'] = self._node_colors.shape[0]
def __init__(self, vertices=None, faces=None, normals=None, sulcus=None, alpha=1., camera=None): """Init.""" self._camera = None self._camera_transform = vist.NullTransform() self._translucent = True self._alpha = alpha self._n_overlay = 0 self._data_lim = [] self._colormaps = [] # Initialize the vispy.Visual class with the vertex / fragment buffer : Visual.__init__(self, vcode=VERT_SHADER, fcode=FRAG_SHADER) # _________________ BUFFERS _________________ # Vertices / faces / normals / color : def_3 = np.zeros((0, 3), dtype=np.float32) self._vert_buffer = gloo.VertexBuffer(def_3) self._normals_buffer = gloo.VertexBuffer(def_3) self._bgd_buffer = gloo.VertexBuffer() self._xrange_buffer = gloo.VertexBuffer() self._alphas_buffer = gloo.VertexBuffer() self._index_buffer = gloo.IndexBuffer() # _________________ PROGRAMS _________________ self.shared_program.vert['a_position'] = self._vert_buffer self.shared_program.vert['a_normal'] = self._normals_buffer self.shared_program.vert['u_n_overlays'] = self._n_overlay self.shared_program.frag['u_alpha'] = alpha # _________________ TEXTURE _________________ color_1d = np.c_[np.array([1.] * 4), np.array(SULCUS_COLOR)].T text_1d = gloo.Texture1D(color_1d.astype(np.float32)) self.shared_program.vert['u_bgd_text'] = text_1d # _________________ LIGHTS _________________ self.shared_program.frag['u_light_intensity'] = LIGHT_INTENSITY self.shared_program.frag['u_coef_ambient'] = COEF_AMBIENT # _________________ DATA / CAMERA / LIGHT _________________ self.set_data(vertices, faces, normals, sulcus) self.set_camera(camera) # _________________ GL STATE _________________ self.set_gl_state('translucent', depth_test=True, cull_face=False, blend=True, blend_func=('src_alpha', 'one_minus_src_alpha')) self._draw_mode = 'triangles' self.freeze()
def set_data(self, data): self.data = data self.data_changed = True vertices = self.generate_vertices(data) self.xmin = np.nanmin(vertices['a_position'][:, 0]) self.xmax = np.nanmax(vertices['a_position'][:, 0]) self.ymin = np.nanmin(vertices['a_position'][:, 1]) self.ymax = np.nanmax(vertices['a_position'][:, 1]) if self.xmin == self.xmax or self.ymin == self.ymax: logger.error(('Cannot plot because min and max values of' ' vertices are identical')) return # Determines the width of the colorbar self.cm_dx = (self.xmax - self.xmin) * 0.1 self.view = translate((0, 0, 0)) # Orthogonal projection matrix self.projection = ortho(self.xmin, self.xmax + self.cm_dx, self.ymin, self.ymax, -1, 1) self.data_program['u_view'] = self.view self.data_program['u_projection'] = self.projection cmap_texture = gloo.Texture1D(self.colormap.get_colors(), interpolation='linear') self.data_program['u_colormap'] = cmap_texture self.colorbar_program['u_view'] = self.view self.colorbar_program['u_projection'] = self.projection self.linecut_program['u_view'] = self.view self.linecut_program['u_projection'] = self.projection self.vbo = gloo.VertexBuffer(vertices) self.data_program.bind(self.vbo) self.update()
def _build_bgd_texture(self): color_1d = np.c_[np.array([1.] * 4), np.array(self.mask_color), np.array(SULCUS_COLOR)].T text_1d = gloo.Texture1D(color_1d.astype(np.float32)) self.shared_program.vert['u_bgd_text'] = text_1d
def __init__(self, pos=None, columns=None, offsets=None, scales=None, color=(0.5, 0.5, 0.5, 1), width=1, index=None, visibility=None): visuals.Visual.__init__(self, VERTEX_SHADER, FRAGMENT_SHADER) self._update_lock = False self._need_pos_update = True self._need_color_update = True self._need_indices_update = True self._need_index_update = True self._need_scales_update = True self._need_offsets_update = True # Data if pos is None: pos = np.empty(1, dtype=object) pos[0] = np.array([0], dtype=np.float32) self._line_sizes = np.array([len(x) for x in pos]) self._pos_len = np.sum(self._line_sizes) if pos.dtype != 'O': new_pos = np.empty(pos.shape[0], dtype=object) for i, p in enumerate(pos): new_pos[i] = p self._pos = new_pos else: self._pos = pos # Visibility if visibility is None: self._visibility = np.ones(self._pos.shape[0], bool) else: self._visibility = visibility # Width self._width = width # Indices self._update_indices() # Index self._conn = np.arange(self._pos_len, dtype=np.uint32) if index is None: self._index = np.ones(self._pos_len, 'bool') else: self._index = index # Offsets if offsets is None: self._offsets = np.ones((self._pos.shape[0], 3), np.float32) else: self._offsets = offsets # Scales if scales is None: self._scales = np.ones((self._pos.shape[0], 3), np.float32) else: self._scales = scales self._bounds = None self.set_gl_state('translucent', line_width=self._width) # Construct LUT lookup and color array if isinstance(color, tuple): self._lut = np.array(color).reshape(1, 4).astype(np.float32) self._color = np.zeros(self._pos_len, np.float32) elif isinstance(color, np.ndarray) and color.shape[0] == pos.shape[0]: self._lut = color self._color = np.zeros(self._pos_len, np.float32) for i, idx in enumerate(self._indices): self._color[int(idx[0]):int(idx[1])] = i else: self._lut = np.unique(self._color, axis=0) self._color = color.astype(np.float32) for i, c in enumerate(self._lut): self.color[np.where((self.color == c).all(axis=1))[0], 0] = i self._color = self._color[:, 0] # Samplers self._indices_tex = gloo.Texture1D(self._indices.astype(np.float32), internalformat='rgba32f') self.shared_program['indices'] = self._indices_tex self._offsets_tex = gloo.Texture1D(self._offsets.astype(np.float32), internalformat='rgb32f') self.shared_program['offsets'] = self._offsets_tex self._scales_tex = gloo.Texture1D(self._scales.astype(np.float32), internalformat='rgb32f') self.shared_program['scales'] = self._scales_tex self._lut_tex = gloo.Texture1D(self._lut.astype(np.float32), internalformat='rgba32f') self.shared_program['lut'] = self._lut_tex # Buffers self.shared_program.vert['to_vec4'] = vec2to4 self._pos_vbo = gloo.VertexBuffer() self.shared_program['position'] = self._pos_vbo self._color_vbo = gloo.VertexBuffer() self.shared_program['color'] = self._color_vbo self._index_buffer = gloo.IndexBuffer() # Variables self.shared_program['n_lines'] = len(self._line_sizes) self._draw_mode = 'line_strip'
def __init__(self): app.Canvas.__init__(self, size=(512, 512), title='Particle Renderer', keys='interactive') # enable geometry shader gloo.gl.use_gl('gl+') # load and compile shader with open('shader/particleRenderer.frag', 'r') as file: fragmentString = file.read() with open('shader/particleRenderer.geom', 'r') as file: geomString = file.read() with open('shader/particleRenderer.vert', 'r') as file: vertexString = file.read() self.program = Program() self.program.set_shaders(vertexString, fragmentString, geomString, True) ###################################### # settings # when changing near/far or fov you have to call resetProjection() for the changes to take effect # everything closer to the camera than near ot further away than far will not be drawn self.nearDistance = 0.1 self.farDistance = 20 self.fov = 45.0 # field of view in degree # initial camera position # call resetCamera or press "R" to go the initial position self.initialCamPosition = glm.vec3(3, 3, 3) self.initialCamTarget = glm.vec3(0, 0, 0) # you can change settings of the camera yourself with self.cam.xxx = yyy # you can also move the camera by calling setPosition / setTarget and # thereby predefine an animation (eg for videos/talks) # you can also change the camera control mode 1 = fly camera, 0 = trackball camera self.cam = Camera(1, self.initialCamPosition, self.initialCamTarget) # the CameraInputHandler links the camera to keybiard and mouse input, you can also change keybindings there self.camInputHandler = CameraInputHandler(self.cam) # // positions where spheres are rendered self.program['input_position'] = [(0, 0, 0), (1, 1, 1), (1, 1, -1), (1, -1, 1), (1, -1, -1), (-1, 1, 1), (-1, 1, -1), (-1, -1, 1), (-1, -1, -1)] # vector field for color # self.program['input_vector'] = # scalar field, used for color in color mode 3 self.program['input_scalar'] = np.array( [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9], dtype=np.float32) # radius per particle, set self.program['enableSizePerParticle'] = True to enable self.program['input_radius'] = [[0.15], [0.1], [0.2], [0.1], [0.2], [0.05], [0.1], [0.15], [0.1]] # size self.program[ 'enableSizePerParticle'] = False # enable this and set a size for each particle above self.program[ 'sphereRadius'] = 0.15 # radius of the spheres if "size per particle" is disabled # background gloo.set_state(clear_color=(0.30, 0.30, 0.35, 1.00)) # background color # transfer function / color self.program[ 'colorMode'] = 3 # 1: color by vector field direction, 2: color by vector field magnitude, 3: color by scalar field, 0: constant color self.program['defaultColor'] = (1, 1, 1 ) # particle color in color mode 0 self.program[ 'lowerBound'] = 0.0 # lowest value of scalar field / vector field magnitude self.program[ 'upperBound'] = 1.0 # lowest value of scalar field / vector field magnitude self.program[ 'customTransferFunc'] = True # set to true to use a custom transfer function # Transfer function uses a 1D Texture. # Provide 1D list of colors (r,g,b) as the textures data attribute, colors will be evenly spread over # the range [lowerBound,upperBound]. Meaning particles where the scalar is equal to lowerBound will # have the first specified color, the one with a scalar equal to lowerBound will have the last. Values that # lie in between the colors are interpolated linearly self.program['transferFunc'] = gloo.Texture1D( format='rgba', interpolation='linear', internalformat='rgba8', data=cm.viridis(range(256)).astype(np.float32)) # sphere look self.program['brightness'] = 1 # additional brightness control self.program[ 'materialAlpha'] = 1.0 # set lower than one to make spheres self.program['materialShininess'] = 4.0 # material shininess self.program[ 'useTexture'] = False # use the below texture for coloring (will be tinted according to set color) # provide a numpy array of shaper (x,y,3) for rgb pixels of the 2d image self.program['colorTexture'] = gloo.Texture2D( format='rgb', interpolation='linear', internalformat='rgb8', data=_checkerboard().astype(np.float32)) self.program[ 'uvUpY'] = False # rotates texture by 90 degrees so that sphere poles are along the Y axis # light settings self.program['lightPosition'] = (500, 500, 1000 ) # position of the ligth self.program['lightDiffuse'] = (0.4, 0.4, 0.4 ) # diffuse color of the light self.program['lightSpecular'] = (0.3, 0.3, 0.3 ) # specular color of the light self.program['ambientLight'] = (0.1, 0.1, 0.1) # ambient light color self.program[ 'lightInViewSpace'] = True # should the light move around with the camera? # settings for flat shading self.program[ 'renderFlatDisks'] = False # render flat discs instead of spheres self.program[ 'flatFalloff'] = False # when using flat discs, enable this darken the edges # settings for additional depth cues self.program[ 'enableEdgeHighlights'] = False # add black edge around the particles for better depth perception # style of blending self.useAdditiveBlending(False) # orientation helper self.enableOrientationIndicator = True # enable / disable orientation indicator in the lower left self.enableOriginIndicator = True # enable / disable orientation indicator at the origin self.originIndicatorSize = 1.0 # change size of the origin indicator # other self.program[ 'spriteScale'] = 1.1 # increase this if spheres appear to have cut off edges ############################################ # setup orientation indicator # load and compile shader with open('shader/oriIndicator.frag', 'r') as file: oriFragmentString = file.read() with open('shader/oriIndicator.vert', 'r') as file: oriVertexString = file.read() self._oriProgram = Program(oriVertexString, oriFragmentString) self._oriProgram['input_position'] = [(0, 0, 0), (1, 0, 0), (0, 0, 0), (0, 1, 0), (0, 0, 0), (0, 0, 1)] # model matrix model = np.eye(4, dtype=np.float32) self.program['model'] = model # camera and view matrix self.program['view'] = self.cam.viewMatrix # projection matrix self._projection = glm.mat4(1.0) self._oriProjection = glm.mat4(1.0) self.resetProjection() # timing self._lastTime = time.time() # show window self.show()