コード例 #1
0
class EMVolumeModel(EM3DModel):
	def __init__(self, gl_widget, image=None):
		self.data = None
		EM3DModel.__init__(self, gl_widget)
		
		self.init()
		self.initialized = True
		
		self.initializedGL= False
		
		self.inspector=None
		
		self.tex_names_list = []		# A storage object, used to remember and later delete texture names
		
		self.axes_idx = -1
		self.axes = []
		self.axes.append(Vec3f(1,0,0))
		self.axes.append(Vec3f(0,1,0))
		self.axes.append(Vec3f(0,0,1))
		#self.axes.append( Vec3f(-1,0,0) )
		#self.axes.append( Vec3f(0,-1,0) )
		#self.add_render_axis(1,1,1)
		#self.add_render_axis(-1,1,1)
		#self.add_render_axis(-1,-1,1)
		#self.add_render_axis(1,-1,1)
		
		#self.add_render_axis(1,1,0)
		#self.add_render_axis(-1,1,0)
		#self.add_render_axis(-1,-1,0)
		#self.add_render_axis(1,-1,0)
		
		#self.add_render_axis(0,1,1)
		#self.add_render_axis(0,-1,1)
		
		#self.add_render_axis(1,0,1)
		#self.add_render_axis(-1,0,1)
			
		if image :
			self.set_data(image)
#	def __del__(self):
#		print "vol died"

	def add_render_axis(self,a,b,c):
		v = Vec3f(a,b,c);
		v.normalize()
		self.axes.append( v )
	
	def eye_coords_dif(self,x1,y1,x2,y2,mdepth=True):
		return self.vdtools.eye_coords_dif(x1,y1,x2,y2,mdepth)
	
	def get_type(self):
		return "Volume"

	def init(self):
		self.data=None

		self.mmode=0
		
		self.cam = Camera2(self)
		self.cube = False
		
		self.vdtools = EMViewportDepthTools(self)
		
		self.contrast = 1.0
		self.brightness = 0.0
		self.texsample = 1.0
		self.glcontrast = 1.0
		self.glbrightness = 0.0
		self.cube = False
		
		self.tex_name = 0
		
		self.rank = 1
		
		self.tex_dl = 0
		self.inspector=None
		
		self.force_texture_update = False

		self.glflags = EMOpenGLFlagsAndTools()		# OpenGL flags - this is a singleton convenience class for testing texture support
	
	def update_data(self,data):
		self.set_data(data)
		self.updateGL()
		
	def set_data(self,data):
		"""Pass in a 3D EMData object"""
		
		
		self.data=data
		if data==None:
			print "Error, the data is empty"
			return
		
	 	if (isinstance(data,EMData) and data.get_zsize()<=1) :
			print "Error, the data is not 3D"
			return
		
		if not self.inspector or self.inspector ==None:
			self.inspector=EMVolumeInspector(self)
		
		self.update_data_and_texture()
		
		from emglobjects import EM3DGLWidget
		if isinstance(self.get_gl_widget(),EM3DGLWidget):
			self.get_gl_widget().set_camera_defaults(self.data)
		
	def test_accum(self):
		# this code will do volume rendering using the accumulation buffer
		# I opted not to go this way because you can't retain depth in the accumulation buffer
		# Note that it only works in the z-direction
		glClear(GL_ACCUM_BUFFER_BIT)
		
		self.accum = True
		self.zsample = self.texsample*(self.data.get_zsize())
		
		if self.tex_name == 0:
			print "Error, can not render 3D texture - texture name is 0"
			return
		
		
		for z in range(0,int(self.texsample*(self.data.get_zsize()))):
			glEnable(GL_TEXTURE_3D)
			glBindTexture(GL_TEXTURE_3D, self.tex_name)
			glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
			glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP)
			glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP)
			glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP)
			glTexParameter(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
			glTexParameter(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)

			glBegin(GL_QUADS)
			
			zz = float(z)/float(self.data.get_zsize()-1)/self.texsample
			glTexCoord3f(0,0,zz)
			glVertex3f(0,0,zz)
			
			glTexCoord3f(1,0,zz)
			glVertex3f(1,0,zz)
			
			glTexCoord3f(1,1,zz)
			glVertex3f(1,1,zz)
			
			glTexCoord3f(0,1,zz)
			glVertex3f(0,1,zz)
		
			glEnd()
			glDisable(GL_TEXTURE_3D)
		
			if ( self.accum ):
				glAccum(GL_ADD, 1.0/self.zsample*self.brightness)
				glAccum(GL_ACCUM, 1.0/self.zsample*self.contrast)
		
		
		glAccum(GL_RETURN, 1.0)
		
	def render(self):
		lighting = glIsEnabled(GL_LIGHTING)
		cull = glIsEnabled(GL_CULL_FACE)
		depth = glIsEnabled(GL_DEPTH_TEST)
		
		polygonmode = glGetIntegerv(GL_POLYGON_MODE)

		glDisable(GL_LIGHTING)
		glDisable(GL_CULL_FACE)
		glDisable(GL_DEPTH_TEST)
		
		glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
		
		glPushMatrix()
		self.cam.position(True)
		# the ones are dummy variables atm... they don't do anything
		self.vdtools.update(1,1)
		glPopMatrix()
		
		self.cam.position()
		self.vdtools.store_model()

		# here is where the correct display list (x,y or z direction) is determined
		self.texture_update_if_necessary()

		glStencilFunc(GL_EQUAL,self.rank,0)
		glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE)
		glPushMatrix()
		glTranslate(-self.data.get_xsize()/2.0,-self.data.get_ysize()/2.0,-self.data.get_zsize()/2.0)
		glScalef(self.data.get_xsize(),self.data.get_ysize(),self.data.get_zsize())
		glEnable(GL_BLEND)
		#glBlendEquation(GL_MAX)
		if self.glflags.blend_equation_supported():
			glBlendEquation(GL_FUNC_ADD)
		glDepthMask(GL_FALSE)
		glBlendFunc(GL_ONE, GL_ONE)
		glCallList(self.tex_dl)
		glDepthMask(GL_TRUE)
		glDisable(GL_BLEND)
		glPopMatrix()

		# this is the accumulation buffer version of the volume model - it was for testing purposes
		# and is left here commented out incase anyone wants to investigate it in the future
		#glPushMatrix()
		#glTranslate(-self.data.get_xsize()/2.0,-self.data.get_ysize()/2.0,-self.data.get_zsize()/2.0)
		#glScalef(self.data.get_xsize(),self.data.get_ysize(),self.data.get_zsize())
		#self.test_accum()
		#glPopMatrix()
		
		#breaks in desktop!
		#glStencilFunc(GL_EQUAL,self.rank,self.rank)
		#glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP)
		#glPushMatrix()
		#glLoadIdentity()
		#[width,height] = self.parent.get_near_plane_dims()
		#z = self.parent.get_start_z()
		#glTranslate(-width/2.0,-height/2.0,-z-0.01)
		#glScalef(width,height,1.0)
		self.draw_bc_screen()
		#glPopMatrix()
		
		glStencilFunc(GL_ALWAYS,1,1)
		if self.cube:
			glPushMatrix()
			self.draw_volume_bounds()
			glPopMatrix()
			
		if ( lighting ): glEnable(GL_LIGHTING)
		if ( cull ): glEnable(GL_CULL_FACE)
		if ( depth ): glEnable(GL_DEPTH_TEST)
		
		if ( polygonmode[0] == GL_LINE ): glPolygonMode(GL_FRONT, GL_LINE)
		if ( polygonmode[1] == GL_LINE ): glPolygonMode(GL_BACK, GL_LINE)
	
	def texture_update_if_necessary(self):
		
		t3d = self.vdtools.getEmanMatrix()
		
		
		point = Vec3f(0,0,1)
		
		point = point*t3d
		
		point[0] = abs(point[0])
		point[1] = abs(point[1])
		point[2] = abs(point[2])
		#point[1] = -point[1]
		#if ( point[2] < 0 ):
			#point[2] = -point[2]
			#point[1] = -point[1]
			#point[0] = -point[0]
	
		currentaxis = self.axes_idx
		
		closest = 2*pi
		lp = point.length()
		point.normalize()
		idx = 0
		for i in self.axes:
			try:
				angle = abs(acos(point.dot(i)))
			except:
				t3d.printme()
				print 'warning, there is a bug in the volume render which may cause incorrect rendering'
				return
			if (angle < closest):
				closest = angle
				self.axes_idx = idx
			
			idx += 1

		if (currentaxis != self.axes_idx or self.force_texture_update):
			#print self.axes[self.axes_idx]
			self.gen_texture()
			
	def gen_texture(self):
		if self.glflags.threed_texturing_supported():
			self.get_3D_texture()
		else:
			self.gen_2D_texture()
			
	def get_3D_texture(self):
		if ( self.tex_dl != 0 ): glDeleteLists( self.tex_dl, 1)
		
		self.tex_dl = glGenLists(1)
		
		if self.tex_dl == 0:
			print "Error, failed to generate display list"
			return
		
		n = self.get_dimension_size()
		v = self.axes[self.axes_idx]
		[t,alt,phi] = self.get_eman_transform(v)
		v1 = t*Vec3f(-0.5,-0.5,0)
		v2 = t*Vec3f(-0.5, 0.5,0)
		v3 = t*Vec3f( 0.5, 0.5,0)
		v4 = t*Vec3f( 0.5,-0.5,0)
		vecs = [v1,v2,v3,v4]
		total = self.texsample*n
		self.data.add(self.brightness)
		if self.contrast != 0:
			self.data.mult(self.contrast*1.0/total)
		if ( self.force_texture_update ):
			if self.tex_name != 0:
				glDeleteTextures(self.tex_name)
			
			self.tex_name = self.glflags.gen_textureName(self.data)
			
			self.force_texture_update = False
			
		
		if self.tex_name == 0:
			print "Error, can not render 3D texture - texture name is 0"
			return
		
		
		glNewList(self.tex_dl,GL_COMPILE)
		glEnable(GL_TEXTURE_3D)
		glBindTexture(GL_TEXTURE_3D, self.tex_name)
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)
		glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP)
		glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP)
		glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP)
		glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
		if ( not data_dims_power_of(self.data,2) and self.glflags.npt_textures_unsupported()):
			glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
		else:
			glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)

		glPushMatrix()
		glTranslate(0.5,0.5,0.5)
		glBegin(GL_QUADS)
		
		
		for i in range(0,int(self.texsample*n)):
			nn = float(i)/float(n)/self.texsample

			trans = (nn-0.5)*v
			
			for r in vecs:
			
				w = [r[0] + trans[0], r[1] + trans[1], r[2] + trans[2]]
				t = [w[0]+0.5,w[1]+0.5,w[2]+0.5]
				glTexCoord3fv(t)
				glVertex3fv(w)
			
		glEnd()
		glPopMatrix()
		glDisable(GL_TEXTURE_3D)
		glEndList()
		
		if self.contrast != 0:	self.data.mult(total*1.0/self.contrast)
		self.data.add(-self.brightness)
		
		
	def get_eman_transform(self,p):
		
		if ( p[2] == 0 ):
			alt = 90
		else :
			alt = acos(p[2])*180.0/pi
		
		phi = atan2(p[0],p[1])
		phi *= 180.0/pi
		
		t = Transform({"type":"eman","alt":alt,"phi":phi})
		
		return [t,alt,phi]
			
	def get_dimension_size(self):
		if ( self.axes_idx == 0 ):
			return self.data.get_xsize()
		elif ( self.axes_idx == 1 ):
			return self.data.get_ysize()
		elif ( self.axes_idx == 2 ):
			return self.data.get_zsize()
		else:
			#print "unsupported axis"
			# this is a hack and needs to be fixed eventually
			return self.data.get_xsize()
			#return 0
	def get_correct_dims_2d_emdata(self):
		if ( self.axes_idx == 0 ):
			return EMData(self.data.get_ysize(),self.data.get_zsize())
		elif ( self.axes_idx == 1 ):
			return EMData(self.data.get_xsize(),self.data.get_zsize())
		elif ( self.axes_idx == 2 ):
			return EMData(self.data.get_xsize(),self.data.get_ysize())
		else:
			#print "unsupported axis"
			# this is a hack and needs to be fixed eventually
			return EMData(self.data.get_xsize(),self.data.get_zsize())

	
	def gen_2D_texture(self):
			
		if ( self.tex_dl != 0 ): 
			glDeleteLists( self.tex_dl, 1)
		
		for i in self.tex_names_list:
			glDeleteTextures(i)
			
		self.tex_dl = glGenLists(1)
		if (self.tex_dl == 0 ):
			print "error, could not generate list"
			return

		glNewList(self.tex_dl,GL_COMPILE)
		glEnable(GL_TEXTURE_2D)

		n = self.get_dimension_size()
		v = self.axes[self.axes_idx]
		[t,alt,phi] = self.get_eman_transform(v)
		total = self.texsample*n
		for i in range(0,int(self.texsample*n)):
			nn = float(i)/float(n)/self.texsample
			
			trans = (nn-0.5)*v
			t.set_trans(2.0*int(n/2)*trans)
			
			if False and EMUtil.cuda_available(): # disable for the time being - big textures won't work on CPU
				tmp = self.data.cut_slice_cuda(t)
			else:
				tmp = self.get_correct_dims_2d_emdata() 
				tmp.cut_slice(self.data,t,True)
			tmp.add(self.brightness)
			tmp.mult(self.contrast*1.0/total)
			#tmp.write_image("tmp.img",-1)
			
			# get the texture name, store it, and bind it in OpenGL
			tex_name = self.glflags.gen_textureName(tmp)
			self.tex_names_list.append(tex_name)
			glBindTexture(GL_TEXTURE_2D, tex_name)
			
			self.loat_default_2D_texture_parms()
			
			glPushMatrix()
			
			glTranslate(trans[0]+0.5,trans[1]+0.5,trans[2]+0.5)
			glRotatef(-phi,0,0,1)
			glRotatef(-alt,1,0,0)
			glBegin(GL_QUADS)
			glTexCoord2f(0,0)
			glVertex2f(-0.5,-0.5)
			
			glTexCoord2f(1,0)
			glVertex2f( 0.5,-0.5)
			
			glTexCoord2f(1,1)
			glVertex2f( 0.5, 0.5)
			
			glTexCoord2f(0,1)
			glVertex2f(-0.5, 0.5)
			glEnd()
			glPopMatrix()
		
		glDisable(GL_TEXTURE_2D)
		glEndList()
		
		# this may have been toggled (i.e. if the image contrast or brightness changed)
		if self.force_texture_update == True:
			self.force_texture_update = False
	
	def loat_default_2D_texture_parms(self):
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)
		if ( not data_dims_power_of(self.data,2) and self.glflags.npt_textures_unsupported()):
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
		else:
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) 
		
	def update_data_and_texture(self):
	
		if ( not isinstance(self.data,EMData) ): return
		
		hist = self.data.calc_hist(256,0,1.0)
		self.inspector.set_hist(hist,0,1.0)

		self.force_texture_update = True

	def set_contrast(self,val):
		self.contrast = val
		self.update_data_and_texture()
		self.updateGL()
		
	def set_brightness(self,val):
		self.brightness = val
		self.update_data_and_texture()
		self.updateGL()
		
	def set_texture_sample(self,val):
		if ( val < 0 ) :
			print "Error, cannot handle texture sample less than 0"
			return
		
		self.texsample = val
		self.force_texture_update = True
		self.updateGL()

	def update_inspector(self,t3d):
		if not self.inspector or self.inspector ==None:
			self.inspector=EMVolumeInspector(self)
		self.inspector.update_rotations(t3d)
	
	def get_inspector(self):
		if not self.inspector : self.inspector=EMVolumeInspector(self)
		return self.inspector
		
	def resize(self):
		self.vdtools.set_update_P_inv()
コード例 #2
0
ファイル: emimage3dslice.py プロジェクト: cpsemmens/eman2
class EM3DSliceModel(EM3DModel):
	
	def __init__(self, gl_widget, image=None):
		self.data = None
		EM3DModel.__init__(self, gl_widget)
		self.init()
		self.initialized = True
		
		self.inspector=None
	
		self.axes = []
		self.axes.append( Vec3f(1,0,0) )
		self.axes.append( Vec3f(0,1,0) )
		self.axes.append( Vec3f(0,0,1) )
		self.axes_idx = 2
		
		self.track = False
		self.bright = 0
		self.contrast = 1.0
		self.busy = True
		if image :
			self.set_data(image)
			
	def set_contrast(self,val):
		self.contrast = val
		self.generate_current_display_list()
		self.updateGL()
	def set_brightness(self,val):
		self.bright = val
		self.generate_current_display_list()
		self.updateGL()
		
#	def __del__(self):
#		print "slice died"
	
	def get_type(self):
		return "Slice Viewer"

	def init(self):
		self.data=None

		self.mmode=0
		self.cam = Camera2(self)
		
		self.vdtools = EMViewportDepthTools(self)
		
		self.cube = False
		self.inspector=None
		
		self.tex_name = 0
		self.tex_dl = 0

		self.glcontrast = 1.0
		self.glbrightness = 0.0
		
		self.rank = 1
		
		self.glflags = EMOpenGLFlagsAndTools()		# OpenGL flags - this is a singleton convenience class for testing texture support
		
	def eye_coords_dif(self,x1,y1,x2,y2,mdepth=True):
		return self.vdtools.eye_coords_dif(x1,y1,x2,y2,mdepth)
	
	def update_data(self,data):
		if data==None:
			print "Error, the data is empty"
			return
		
		if (isinstance(data,EMData) and data.get_zsize()<=1) :
			print "Error, the data is not 3D"
			return
		
#		self.data = data.copy()
#		
#		min = self.data.get_attr("minimum")
#		max = self.data.get_attr("maximum")
#		
#		self.data.add(-min)
#		self.data.mult(1/(max-min))

		self.generate_current_display_list()
		self.updateGL()
		
	def set_default_contrast_settings(self):
		min = self.data.get_attr("minimum")
		max = self.data.get_attr("maximum")
#		
#		self.data.add(-min)
#		self.data.mult(1/(max-min))
		self.bright = -min
		if max != min:	self.contrast = 1.0/(max-min)
		else: self.contrast = 1
		
	def set_data(self,data,fact=1.0):
		"""Pass in a 3D EMData object"""
		
		self.busy = True
		if data==None:
			print "Error, the data is empty"
			return
		
		if (isinstance(data,EMData) and data.get_zsize()<=1) :
			print "Error, the data is not 3D"
			self.busy = False
			return
		
		self.data = data
		
		self.set_default_contrast_settings()
		
		if not self.inspector or self.inspector ==None:
			self.inspector=EM3DSliceInspector(self)
		
		self.inspector.set_contrast_bright(self.contrast,self.bright)
		hist = self.data.calc_hist(256,0,1.0,self.bright,self.contrast)
		self.inspector.set_hist(hist,0,1.0) 
		
		self.slice = data.get_zsize()/2
		self.zslice = data.get_zsize()/2-1
		if self.zslice < 0: self.zslice = 0
		self.yslice = data.get_ysize()/2-1
		if self.yslice < 0: self.yslice = 0
		self.xslice = data.get_xsize()/2-1
		if self.xslice < 0: self.xslice = 0
		self.trackslice = self.xslice
		self.axis = 'z'
		self.inspector.set_sliceRange(0,data.get_zsize()-1)
		self.inspector.set_slice(self.zslice)
		self.generate_current_display_list()
		
		from emglobjects import EM3DGLWidget
		if isinstance(self.get_gl_widget(),EM3DGLWidget):
			self.get_gl_widget().set_camera_defaults(self.data)
			
		if ( self.tex_dl != 0 ): 
			glDeleteLists( self.tex_dl, 1)
			self.tex_dl = 0
		self.busy = False
	def get_eman_transform(self,p):
		
		if ( p[2] == 0 ):
			alt = 90
		else :
			alt = acos(p[2])*180.0/pi
		
		phi = atan2(p[0],p[1])
		phi *= 180.0/pi
		
		return [Transform({"type":"eman","alt":alt,"phi":phi}),alt,phi]
			
	def get_dimension_size(self):
		if ( self.axes_idx == 0 ):
			return self.data.get_xsize()
		elif ( self.axes_idx == 1 ):
			return self.data.get_ysize()
		elif ( self.axes_idx == 2 ):
			return self.data.get_zsize()
		else:
			#print "unsupported axis"
			# this is a hack and needs to be fixed eventually
			return self.data.get_xsize()
			#return 0
	def get_correct_dims_2d_emdata(self):
		if ( self.axes_idx == 0 ):
			return EMData(self.data.get_ysize(),self.data.get_zsize())
		elif ( self.axes_idx == 1 ):
			return EMData(self.data.get_xsize(),self.data.get_zsize())
		elif ( self.axes_idx == 2 ):
			return EMData(self.data.get_xsize(),self.data.get_ysize())
		else:
			#print "unsupported axis"
			# this is a hack and needs to be fixed eventually
			return EMData(self.data.get_xsize(),self.data.get_zsize())

	def generate_current_display_list(self):
		if self.busy: return
		if ( self.tex_dl != 0 ): glDeleteLists( self.tex_dl, 1)
		
		self.tex_dl = glGenLists(1)

		if (self.tex_dl == 0): return #OpenGL is initialized yet

		self.gen_2D_texture()
	
		
	def gen_2D_texture(self):
		glNewList(self.tex_dl,GL_COMPILE)
		
		n = self.get_dimension_size()
		v = self.axes[self.axes_idx]
		
		[t,alt,phi] = self.get_eman_transform(v)
			
		nn = float(self.slice)/float(n)
		trans = (nn-0.5)*v
		t.set_trans(n*trans)
	
		if False and EMUtil.cuda_available(): # disable for the time being - big textures won't work on CPU
			tmp = self.data.cut_slice_cuda(t)
		else:
			tmp = self.get_correct_dims_2d_emdata()
			tmp.cut_slice(self.data,t,True)
			
		tmp.add(self.bright)
		tmp.mult(self.contrast)
		
		hist = tmp.calc_hist(256,0,1.0,self.bright,self.contrast)
		self.inspector.set_hist(hist,0,1.0) 
		
		if ( self.tex_name != 0 ): glDeleteTextures(self.tex_name)
		self.tex_name = 0
		
		self.tex_name = self.glflags.gen_textureName(tmp)
		
		glEnable(GL_TEXTURE_2D)
		glBindTexture(GL_TEXTURE_2D, self.tex_name)
			
		#glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
#		if ( not data_dims_power_of(self.data,2) and self.glflags.npt_textures_unsupported()):
#			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
#		else:
#			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)
		
			
		glPushMatrix()
		glTranslate(trans[0]+0.5,trans[1]+0.5,trans[2]+0.5)
		glRotatef(-phi,0,0,1)
		glRotatef(-alt,1,0,0)
		glBegin(GL_QUADS)
		glTexCoord2f(0,0)
		glVertex2f(-0.5,-0.5)
		
		glTexCoord2f(1,0)
		glVertex2f( 0.5,-0.5)
		
		glTexCoord2f(1,1)
		glVertex2f( 0.5, 0.5)
		
		glTexCoord2f(0,1)
		glVertex2f(-0.5, 0.5)
		glEnd()
		glPopMatrix()
		
		glDisable(GL_TEXTURE_2D)
		glEndList()
		
	def render(self):
		if self.busy: return
		lighting = glIsEnabled(GL_LIGHTING)
		cull = glIsEnabled(GL_CULL_FACE)
		polygonmode = glGetIntegerv(GL_POLYGON_MODE)
		glDisable(GL_LIGHTING)
		glDisable(GL_CULL_FACE)
		
		glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
		
		glPushMatrix()
		self.cam.position(True)
		# the ones are dummy variables atm... they don't do anything
		self.vdtools.update(1,1)
		glPopMatrix()
		
		self.cam.position()
		self.vdtools.store_model()
		
		if ( self.track ):
			self.loadTrackAxis()
			self.generate_current_display_list()
		
		if ( self.tex_dl == 0 ):
			self.generate_current_display_list()
		
		glStencilFunc(GL_EQUAL,self.rank,0)
		glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE)
		glPushMatrix()
		glTranslate(-self.data.get_xsize()/2.0,-self.data.get_ysize()/2.0,-self.data.get_zsize()/2.0)
		glScalef(self.data.get_xsize(),self.data.get_ysize(),self.data.get_zsize())
		glCallList(self.tex_dl)
		glPopMatrix()
		
		#breaks in desktop!
		#glStencilFunc(GL_EQUAL,self.rank,self.rank)
		#glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP)
		#glPushMatrix()
		##glLoadIdentity()
		#[width,height] = self.parent.get_near_plane_dims()
		#z = self.parent.get_start_z()
		#glTranslate(-width/2.0,-height/2.0,-z-0.01)
		#glScalef(width,height,1.0)
		self.draw_bc_screen()
		#glPopMatrix()
		
		glStencilFunc(GL_ALWAYS,1,1)
		glColor3f(1,1,1)
		if self.cube:
			glPushMatrix()
			self.draw_volume_bounds()
			glPopMatrix()
			
		if ( lighting ): glEnable(GL_LIGHTING)
		if ( cull ): glEnable(GL_CULL_FACE)
		
		if ( polygonmode[0] == GL_LINE ): glPolygonMode(GL_FRONT, GL_LINE)
		if ( polygonmode[1] == GL_LINE ): glPolygonMode(GL_BACK, GL_LINE)
	
	def set_slice(self,val):
		self.slice = val
		if self.axis == 'z':
			self.zslice = val
		elif self.axis == 'y':
			self.yslice = val
		elif self.axis == 'x':
			self.xslice = val
		else:
			self.trackslice = val
		
		self.generate_current_display_list()
		self.updateGL()
		
	def setAxis(self,val):
		self.axis = str(val).strip()
		
		if (self.inspector != None):
			if self.axis == 'z':
				self.inspector.set_sliceRange(0,self.data.get_zsize()-1)
				self.inspector.set_slice(self.zslice)
				self.axes_idx = 2
				self.track = False
			elif self.axis == 'y':
				self.inspector.set_sliceRange(0,self.data.get_ysize()-1)
				self.inspector.set_slice(self.yslice)
				self.axes_idx = 1
				self.track = False
			elif self.axis == 'x':
				self.inspector.set_sliceRange(0,self.data.get_xsize()-1)
				self.inspector.set_slice(self.xslice)
				self.axes_idx = 0
				self.track = False
			elif self.axis == 'track':
				self.track = True
				self.inspector.set_sliceRange(0,self.data.get_xsize()-1)
				self.inspector.set_slice(self.trackslice)
				self.axes_idx = 3
				
				self.loadTrackAxis()
			else:
				print "Error, unknown axis", self.axis, val
		
		self.generate_current_display_list()
		self.updateGL()

	def update_inspector(self,t3d):
		if not self.inspector or self.inspector ==None:
			self.inspector=EM3DSliceInspector(self)
		self.inspector.update_rotations(t3d)
	
	def get_inspector(self):
		if not self.inspector : self.inspector=EM3DSliceInspector(self)
		return self.inspector

	def loadTrackAxis(self):
		t3d = self.vdtools.getEmanMatrix()
		#at3d = self.cam.t3d_stack[len(self.cam.t3d_stack)-1]
		
		point = Vec3f(0,0,1)
		
		point *= 1.0/self.vdtools.getCurrentScale()
		
		point = point*t3d
		
		#if ( point[2] != 0 ): point[2] = -point[2]
		
		if len(self.axes) == 3 :
			self.axes.append(point)
		else:
			self.axes[3] = point

	def resize(self):
		self.vdtools.set_update_P_inv()
コード例 #3
0
class EM3DSliceModel(EM3DModel):
    def __init__(self, gl_widget, image=None):
        self.data = None
        EM3DModel.__init__(self, gl_widget)
        self.init()
        self.initialized = True

        self.inspector = None

        self.axes = []
        self.axes.append(Vec3f(1, 0, 0))
        self.axes.append(Vec3f(0, 1, 0))
        self.axes.append(Vec3f(0, 0, 1))
        self.axes_idx = 2

        self.track = False
        self.bright = 0
        self.contrast = 1.0
        self.busy = True
        if image:
            self.set_data(image)

    def set_contrast(self, val):
        self.contrast = val
        self.generate_current_display_list()
        self.updateGL()

    def set_brightness(self, val):
        self.bright = val
        self.generate_current_display_list()
        self.updateGL()

#	def __del__(self):
#		print "slice died"

    def get_type(self):
        return "Slice Viewer"

    def init(self):
        self.data = None

        self.mmode = 0
        self.cam = Camera2(self)

        self.vdtools = EMViewportDepthTools(self)

        self.cube = False
        self.inspector = None

        self.tex_name = 0
        self.tex_dl = 0

        self.glcontrast = 1.0
        self.glbrightness = 0.0

        self.rank = 1

        self.glflags = EMOpenGLFlagsAndTools(
        )  # OpenGL flags - this is a singleton convenience class for testing texture support

    def eye_coords_dif(self, x1, y1, x2, y2, mdepth=True):
        return self.vdtools.eye_coords_dif(x1, y1, x2, y2, mdepth)

    def update_data(self, data):
        if data == None:
            print("Error, the data is empty")
            return

        if (isinstance(data, EMData) and data.get_zsize() <= 1):
            print("Error, the data is not 3D")
            return


#		self.data = data.copy()
#
#		min = self.data.get_attr("minimum")
#		max = self.data.get_attr("maximum")
#
#		self.data.add(-min)
#		self.data.mult(1/(max-min))

        self.generate_current_display_list()
        self.updateGL()

    def set_default_contrast_settings(self):
        min = self.data.get_attr("minimum")
        max = self.data.get_attr("maximum")
        #
        #		self.data.add(-min)
        #		self.data.mult(1/(max-min))
        self.bright = -min
        if max != min: self.contrast = 1.0 / (max - min)
        else: self.contrast = 1

    def set_data(self, data, fact=1.0):
        """Pass in a 3D EMData object"""

        self.busy = True
        if data == None:
            print("Error, the data is empty")
            return

        if (isinstance(data, EMData) and data.get_zsize() <= 1):
            print("Error, the data is not 3D")
            self.busy = False
            return

        self.data = data

        self.set_default_contrast_settings()

        if not self.inspector or self.inspector == None:
            self.inspector = EM3DSliceInspector(self)

        self.inspector.set_contrast_bright(self.contrast, self.bright)
        hist = self.data.calc_hist(256, 0, 1.0, self.bright, self.contrast)
        self.inspector.set_hist(hist, 0, 1.0)

        self.slice = data.get_zsize() / 2
        self.zslice = data.get_zsize() / 2 - 1
        if self.zslice < 0: self.zslice = 0
        self.yslice = data.get_ysize() / 2 - 1
        if self.yslice < 0: self.yslice = 0
        self.xslice = data.get_xsize() / 2 - 1
        if self.xslice < 0: self.xslice = 0
        self.trackslice = self.xslice
        self.axis = 'z'
        self.inspector.set_sliceRange(0, data.get_zsize() - 1)
        self.inspector.set_slice(self.zslice)
        self.generate_current_display_list()

        from emglobjects import EM3DGLWidget
        if isinstance(self.get_gl_widget(), EM3DGLWidget):
            self.get_gl_widget().set_camera_defaults(self.data)

        if (self.tex_dl != 0):
            glDeleteLists(self.tex_dl, 1)
            self.tex_dl = 0
        self.busy = False

    def get_eman_transform(self, p):

        if (p[2] == 0):
            alt = 90
        else:
            alt = acos(p[2]) * 180.0 / pi

        phi = atan2(p[0], p[1])
        phi *= 180.0 / pi

        return [Transform({"type": "eman", "alt": alt, "phi": phi}), alt, phi]

    def get_dimension_size(self):
        if (self.axes_idx == 0):
            return self.data.get_xsize()
        elif (self.axes_idx == 1):
            return self.data.get_ysize()
        elif (self.axes_idx == 2):
            return self.data.get_zsize()
        else:
            #print "unsupported axis"
            # this is a hack and needs to be fixed eventually
            return self.data.get_xsize()
            #return 0
    def get_correct_dims_2d_emdata(self):
        if (self.axes_idx == 0):
            return EMData(self.data.get_ysize(), self.data.get_zsize())
        elif (self.axes_idx == 1):
            return EMData(self.data.get_xsize(), self.data.get_zsize())
        elif (self.axes_idx == 2):
            return EMData(self.data.get_xsize(), self.data.get_ysize())
        else:
            #print "unsupported axis"
            # this is a hack and needs to be fixed eventually
            return EMData(self.data.get_xsize(), self.data.get_zsize())

    def generate_current_display_list(self):
        if self.busy: return
        if (self.tex_dl != 0): glDeleteLists(self.tex_dl, 1)

        self.tex_dl = glGenLists(1)

        if (self.tex_dl == 0): return  #OpenGL is initialized yet

        self.gen_2D_texture()

    def gen_2D_texture(self):
        glNewList(self.tex_dl, GL_COMPILE)

        n = self.get_dimension_size()
        v = self.axes[self.axes_idx]

        [t, alt, phi] = self.get_eman_transform(v)

        nn = float(self.slice) / float(n)
        trans = (nn - 0.5) * v
        t.set_trans(n * trans)

        if False and EMUtil.cuda_available(
        ):  # disable for the time being - big textures won't work on CPU
            tmp = self.data.cut_slice_cuda(t)
        else:
            tmp = self.get_correct_dims_2d_emdata()
            tmp.cut_slice(self.data, t, True)

        tmp.add(self.bright)
        tmp.mult(self.contrast)

        hist = tmp.calc_hist(256, 0, 1.0, self.bright, self.contrast)
        self.inspector.set_hist(hist, 0, 1.0)

        if (self.tex_name != 0): glDeleteTextures(self.tex_name)
        self.tex_name = 0

        self.tex_name = self.glflags.gen_textureName(tmp)

        glEnable(GL_TEXTURE_2D)
        glBindTexture(GL_TEXTURE_2D, self.tex_name)

        #glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
        #		if ( not data_dims_power_of(self.data,2) and self.glflags.npt_textures_unsupported()):
        #			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
        #		else:
        #			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)

        glPushMatrix()
        glTranslate(trans[0] + 0.5, trans[1] + 0.5, trans[2] + 0.5)
        glRotatef(-phi, 0, 0, 1)
        glRotatef(-alt, 1, 0, 0)
        glBegin(GL_QUADS)
        glTexCoord2f(0, 0)
        glVertex2f(-0.5, -0.5)

        glTexCoord2f(1, 0)
        glVertex2f(0.5, -0.5)

        glTexCoord2f(1, 1)
        glVertex2f(0.5, 0.5)

        glTexCoord2f(0, 1)
        glVertex2f(-0.5, 0.5)
        glEnd()
        glPopMatrix()

        glDisable(GL_TEXTURE_2D)
        glEndList()

    def render(self):
        if self.busy: return
        lighting = glIsEnabled(GL_LIGHTING)
        cull = glIsEnabled(GL_CULL_FACE)
        polygonmode = glGetIntegerv(GL_POLYGON_MODE)
        glDisable(GL_LIGHTING)
        glDisable(GL_CULL_FACE)

        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)

        glPushMatrix()
        self.cam.position(True)
        # the ones are dummy variables atm... they don't do anything
        self.vdtools.update(1, 1)
        glPopMatrix()

        self.cam.position()
        self.vdtools.store_model()

        if (self.track):
            self.loadTrackAxis()
            self.generate_current_display_list()

        if (self.tex_dl == 0):
            self.generate_current_display_list()

        glStencilFunc(GL_EQUAL, self.rank, 0)
        glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE)
        glPushMatrix()
        glTranslate(-self.data.get_xsize() / 2.0, -self.data.get_ysize() / 2.0,
                    -self.data.get_zsize() / 2.0)
        glScalef(self.data.get_xsize(), self.data.get_ysize(),
                 self.data.get_zsize())
        glCallList(self.tex_dl)
        glPopMatrix()

        #breaks in desktop!
        #glStencilFunc(GL_EQUAL,self.rank,self.rank)
        #glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP)
        #glPushMatrix()
        ##glLoadIdentity()
        #[width,height] = self.parent.get_near_plane_dims()
        #z = self.parent.get_start_z()
        #glTranslate(-width/2.0,-height/2.0,-z-0.01)
        #glScalef(width,height,1.0)
        self.draw_bc_screen()
        #glPopMatrix()

        glStencilFunc(GL_ALWAYS, 1, 1)
        glColor3f(1, 1, 1)
        if self.cube:
            glPushMatrix()
            self.draw_volume_bounds()
            glPopMatrix()

        if (lighting): glEnable(GL_LIGHTING)
        if (cull): glEnable(GL_CULL_FACE)

        if (polygonmode[0] == GL_LINE): glPolygonMode(GL_FRONT, GL_LINE)
        if (polygonmode[1] == GL_LINE): glPolygonMode(GL_BACK, GL_LINE)

    def set_slice(self, val):
        self.slice = val
        if self.axis == 'z':
            self.zslice = val
        elif self.axis == 'y':
            self.yslice = val
        elif self.axis == 'x':
            self.xslice = val
        else:
            self.trackslice = val

        self.generate_current_display_list()
        self.updateGL()

    def setAxis(self, val):
        self.axis = str(val).strip()

        if (self.inspector != None):
            if self.axis == 'z':
                self.inspector.set_sliceRange(0, self.data.get_zsize() - 1)
                self.inspector.set_slice(self.zslice)
                self.axes_idx = 2
                self.track = False
            elif self.axis == 'y':
                self.inspector.set_sliceRange(0, self.data.get_ysize() - 1)
                self.inspector.set_slice(self.yslice)
                self.axes_idx = 1
                self.track = False
            elif self.axis == 'x':
                self.inspector.set_sliceRange(0, self.data.get_xsize() - 1)
                self.inspector.set_slice(self.xslice)
                self.axes_idx = 0
                self.track = False
            elif self.axis == 'track':
                self.track = True
                self.inspector.set_sliceRange(0, self.data.get_xsize() - 1)
                self.inspector.set_slice(self.trackslice)
                self.axes_idx = 3

                self.loadTrackAxis()
            else:
                print("Error, unknown axis", self.axis, val)

        self.generate_current_display_list()
        self.updateGL()

    def update_inspector(self, t3d):
        if not self.inspector or self.inspector == None:
            self.inspector = EM3DSliceInspector(self)
        self.inspector.update_rotations(t3d)

    def get_inspector(self):
        if not self.inspector: self.inspector = EM3DSliceInspector(self)
        return self.inspector

    def loadTrackAxis(self):
        t3d = self.vdtools.getEmanMatrix()
        #at3d = self.cam.t3d_stack[len(self.cam.t3d_stack)-1]

        point = Vec3f(0, 0, 1)

        point *= 1.0 / self.vdtools.getCurrentScale()

        point = point * t3d

        #if ( point[2] != 0 ): point[2] = -point[2]

        if len(self.axes) == 3:
            self.axes.append(point)
        else:
            self.axes[3] = point

    def resize(self):
        self.vdtools.set_update_P_inv()