示例#1
0
class EMRotorModule(EMGUIModule):
	
	def get_gl_widget(self,qt_context_parent,gl_context_parent):
		
		if self.gl_widget == None:
			
			self.gl_context_parent = gl_context_parent
			self.qt_context_parent = qt_context_parent
			self.gl_widget = EM3DGLWindowOverride(self,self.rotor)
		return self.gl_widget
		
	

	def get_qt_widget(self):
		if self.qt_context_parent == None:	
			from emimageutil import EMParentWin
			self.gl_context_parent = EMRotorWidget(self)
			self.qt_context_parent = EMParentWin(self.gl_context_parent)
			self.gl_widget = self.gl_context_parent
		
			self.qt_context_parent.setAcceptDrops(True)

		return self.qt_context_parent
	
	def __init__(self, data=None,application=None):
		EMGUIModule.__init__(self,ensure_gl_context=True)
		self.parent = None
		try: self.parent.setAcceptDrops(True)
		except:	pass

		
		self.rotor = EMGLRotorWidget(self,0,-70,-15,EMGLRotorWidget.TOP_ROTARY,100)
		self.rotor.set_angle_range(40.0)
		self.rotor.set_mouse_mode("mxrotor")
		self.widget = EM3DGLWindowOverride(self,self.rotor)
		self.widget.set_draw_frame(False)
		
		self.z_near = 0
		self.z_far = 0
		
		self.inspector = None
		
	def __del__(self):
		for widget in self.rotor.get_widgets():
			self.application.deregister_qt_emitter(widget.get_drawable().get_drawable())
			
	def draw(self):
		lrt = self.widget.get_lr_bt_nf()
		z = self.gl_context_parent.get_depth_for_height(abs(lrt[3]-lrt[2]))
		
		z_near = z-lrt[4]-1000
		z_trans = 0
		z_far = z-lrt[5]
		if z_near < 0:
			z_trans = z_near
			z_near = 1
			z_far -= z_trans
		if z_far < 0: z_far = 0.1 # hacking alert
		z_far += abs(lrt[3]-lrt[2]) # hacking alert
		if self.z_near != z_near or self.z_far != z_far:
			self.z_near = z_near
			self.z_far = z_far
			if isinstance(self.gl_context_parent,EMRotorWidget):
				self.gl_context_parent.set_near_far(self.z_near,self.z_far)
			else: print "bug 3"

		glPushMatrix()
		glTranslate(0,0,-z)
		self.widget.draw()
		glPopMatrix()
	
	def updateGL(self):
		try: self.gl_widget.updateGL()
		except: pass
		
	def mousePressEvent(self, event):
		if event.button()==Qt.MidButton:
			pass
			#self.show_inspector(True)
		else:
			self.widget.mousePressEvent(event)
	
	def mouseMoveEvent(self, event):
		self.widget.mouseMoveEvent(event)
		self.updateGL()
		
	def mouseReleaseEvent(self, event):
		self.widget.mouseReleaseEvent(event)
		self.updateGL()
	def wheelEvent(self, event):
		self.widget.wheelEvent(event)
		self.updateGL()
	def dragEnterEvent(self,event):
		pass

	def get_inspector(self): return None

	def dropEvent(self,event):
		pass
	
	def get_core_object(self):
		pass
	
	def add_file_dialog(self):
		fd = QtGui.QFileDialog(self.parent,"Open File",QtCore.QDir.currentPath(),QtCore.QString("Image files (*.img *.hed *.mrc)"))
		fd.show()
		fd.hide()

		self.add_qt_widget(fd)
	def keyPressEvent(self,event):
		if event.key() == Qt.Key_0:
			self.add_file_dialog()
			
	def add_qt_widget(self,qt_widget):
		from emfloatingwidgets import EMQtGLView, EM2DGLWindow
		gl_view = EMQtGLView(self,qt_widget)
		gl_view.setQtWidget(qt_widget)
		gl_widget = EM2DGLWindow(self,gl_view)
		#gl_widget = EMGLViewQtWidget(self.gl_context_parent)
		#gl_widget.setQtWidget(qt_widget)
		self.application.register_qt_emitter(gl_widget,self.application.get_qt_emitter(self))
		self.rotor.add_widget(gl_widget)
			
	def width(self):
		return self.gl_widget.width()
	
	def height(self):
		return self.gl_widget.height()
	
	def register_animatable(self,animatable):
		self.qt_context_parent.register_animatable(animatable)
	
	def projection_or_viewport_changed(self):
		self.rotor.resize_event(-1,1)
		
	def update_rotor_position(self,*args):
		pass
示例#2
0
class EMImageRotorModule(EMGUIModule):
	
	def get_desktop_hint(self):
		return "rotor"
		
		
	def get_gl_widget(self,qt_context_parent,gl_context_parent):
		from emfloatingwidgets import EM3DGLWindowOverride
		if self.gl_widget == None:
			
			self.gl_context_parent = gl_context_parent
			self.qt_context_parent = qt_context_parent
			
			self.gl_widget = EM3DGLWindowOverride(self,self.rotor)
			
			self.rotor.target_zoom_events_allowed(False)
			self.rotor.target_translations_allowed(False)
		return self.gl_widget
		
	def __del__(self):
		for widget in self.rotor.get_widgets():
			self.application.deregister_qt_emitter(widget.get_drawable().get_drawable())

	def get_qt_widget(self):
		if self.qt_context_parent == None:	
			from emimageutil import EMParentWin
			self.gl_context_parent = EMImageRotorWidget(self)
			self.qt_context_parent = EMParentWin(self.gl_context_parent)
			self.gl_widget = self.gl_context_parent
		
			self.qt_context_parent.setAcceptDrops(True)

		return self.qt_context_parent
	

	#def get_qt_widget(self):
		#if self.parent == None:
			#from emimageutil import EMParentWin
			#self.gl_parent = EMImageRotorWidget(self)
			#self.parent = EMParentWin(self.gl_parent)
			#self.set_gl_parent(self.gl_parent)

		#return self.parent
	
	def __init__(self, data=None,application=None):
		self.rotor = EMGLRotorWidget(self,15,10,45,EMGLRotorWidget.LEFT_ROTARY)
		EMGUIModule.__init__(self,ensure_gl_context=True)
		self.data=None
		
		self.initsizeflag = True
		if data:
			self.set_data(data)
		
		self.widget = EM3DGLWindow(self,self.rotor)
		self.widget.set_draw_frame(False)
		
		self.z_near = 0
		self.z_far = 0
		
		self.hud_data = [] # a list of strings to be rendered to the heads up display (hud)
	
		self.load_font_renderer()
		
	def optimally_resize(self):
		if isinstance(self.gl_context_parent,EMImageRotorWidget):
			self.qt_context_parent.resize(*self.get_optimal_size())
		else:
			self.gl_widget.resize(*self.get_optimal_size())
		
	def load_font_renderer(self):
		try:
			self.font_renderer = get_3d_font_renderer()
			self.font_renderer.set_face_size(20)
			self.font_renderer.set_depth(4)
			self.font_renderer.set_font_mode(FTGLFontMode.EXTRUDE)
			
#			self.font_renderer.set_font_file_name("/usr/share/fonts/dejavu/DejaVuSerif.ttf")
			self.font_render_mode = EMGUIModule.FTGL
		except:
			self.font_render_mode = EMGUIModule.GLUT
		
	def set_extra_hud_data(self,hud_data):
		self.hud_data = hud_data
	
	def get_optimal_size(self):
		lr = self.rotor.get_lr_bt_nf()
		width = lr[1] - lr[0]
		height = lr[3] - lr[2]
		return [width+80,height+20]
	
		#self.rotor.set_shapes([],1.01)
	def context(self):
		# asking for the OpenGL context from the parent
		return self.gl_context_parent.context()
	
	def emit(self,*args,**kargs):
		#print "emitting",signal,event
		self.application.get_qt_emitter(self).emit(*args,**kargs)
		#if b != None:
			
		#elif a != None:
			#self.application.get_qt_emitter(self).emit(signal,event,a)
		#else:
			#self.application.get_qt_emitter(self).emit(signal,event)

	def set_mouse_mode(self,mode):
		self.mmode = mode
		self.rotor.set_mouse_mode(mode)

	def set_frozen(self,frozen,idx=0):
		self.rotor.set_frozen(frozen,idx)

	def set_shapes(self,shapes,shrink,idx=0):
		self.rotor.set_shapes(shapes,shrink,idx)

	def register_animatable(self,animatable):
		self.get_qt_context_parent().register_animatable(animatable)
	
	def get_inspector(self):
		return None
	
	def width(self):
		try: return self.get_parent().width()
		except: return 0
	
	def height(self):
		try: return self.get_parent().height()
		except: return 0

	def getImageFileName(self):
		''' warning - could return none in some circumstances'''
		try: return self.gl_widget.getImageFileName()
		except: return None
		
	def set_data(self,data):
		if data == None or not isinstance(data,list) or len(data)==0:
			self.data = [] 
			return
		
		self.data = data
		self.rotor.clear_widgets()
		for d in self.data:
			w = EM2DGLView(self,d)
			#w.get_drawable().set_app(self.application)
#			self.application.register_qt_emitter(w.get_drawable(),self.application.get_qt_emitter(self))
			x = EM2DGLWindow(self,w)
			x.set_width(w.width())
			x.set_height(w.height())
			self.rotor.add_widget(x)

	def updateGL(self):
		try: self.gl_widget.updateGL()
		except: pass


	def render(self):
		if not self.data : return
		
		#glLoadIdentity()
		GL.glEnable(GL.GL_DEPTH_TEST)
		GL.glEnable(GL.GL_LIGHTING)
		
		lr = self.rotor.get_lr_bt_nf()
		lrt = lr
		#lr = self.widget.get_lr_bt_nf()
		
		z = self.gl_context_parent.get_depth_for_height(abs(lr[3]-lr[2]))
		
		z_near = z-lrt[4]
		z_trans = 0
		z_far = z-lrt[5]
		if z_near < 0:
			z_trans = z_near
			z_near = 0.1
			z_far -= z_trans
		if z_far < 0: z_far = 0.1 # hacking alert
		if self.z_near != z_near or self.z_far != z_far:
			self.z_near = z_near
			self.z_far = z_far
			if isinstance(self.gl_context_parent,EMImageRotorWidget):
				self.gl_context_parent.set_near_far(self.z_near,self.z_far)
			else: print "bug"

		#FTGL.print_message("hello world",36);
		
		#print self.z_near,self.z_far,-self.parent.get_depth_for_height(abs(lr[3]-lr[2]))+z_trans
		
		glPushMatrix()
		glTranslate(0,0,-z)
		#glTranslate(0,-75,0) # This number is a FIXME issue
		#FTGL.print_message("hello hello",36);
		self.widget.draw()
		glPopMatrix()
		
		self.draw_hud()
	
	def dragEnterEvent(self,event):
		pass

	
	def dropEvent(self,event):
		pass

	def mousePressEvent(self, event):
		if event.button()==Qt.MidButton or (event.button()==Qt.LeftButton and event.modifiers()&Qt.AltModifier):
			self.show_inspector(True)
		else:
			if self.widget.isinwin(event.x(),self.gl_context_parent.viewport_height()-event.y()):
				self.widget.mousePressEvent(event)
			
		self.updateGL()
		
	def mouseMoveEvent(self, event):
		if self.widget.isinwin(event.x(),self.gl_context_parent.viewport_height()-event.y()):
			self.widget.mouseMoveEvent(event)
			self.updateGL()
		
	def mouseReleaseEvent(self, event):
		if self.widget.isinwin(event.x(),self.gl_context_parent.viewport_height()-event.y()):
			self.widget.mouseReleaseEvent(event)
			self.updateGL()
			
	def wheelEvent(self, event):
		if self.widget.isinwin(event.x(),self.gl_context_parent.viewport_height()-event.y()):
			self.widget.wheelEvent(event)
			self.updateGL()
		
	def leaveEvent(self):
		pass
	
	def keyPressEvent(self,event):
		#if self.widget.isinwin(event.x(),self.gl_context_parent.viewport_height()-event.y()):
		self.widget.keyPressEvent(event)
		self.updateGL()
		
	def resize_event(self, width, height):
		self.rotor.resize_event(width,height)


	def draw_hud(self):
		width = self.gl_widget.width()
		height = self.gl_widget.height()
		glMatrixMode(GL_PROJECTION)
		glPushMatrix()
		glLoadIdentity()
		glOrtho(0,width,0,height,-100,100)
		glMatrixMode(GL_MODELVIEW)
		glLoadIdentity()
		glEnable(GL_LIGHTING)
		glEnable(GL_NORMALIZE)
		glMaterial(GL_FRONT,GL_AMBIENT,(0.2, 1.0, 0.2,1.0))
		glMaterial(GL_FRONT,GL_DIFFUSE,(0.2, 1.0, 0.9,1.0))
		glMaterial(GL_FRONT,GL_SPECULAR,(1.0	, 0.5, 0.2,1.0))
		glMaterial(GL_FRONT,GL_SHININESS,20.0)
		enable_depth = glIsEnabled(GL_DEPTH_TEST)
		glDisable(GL_DEPTH_TEST)
		glColor(1.0,1.0,1.0)
		
		
		if self.font_render_mode == EMImageMXModule.FTGL:
			panels = len(self.rotor)
			idx = self.rotor.current_index()
			string = str(idx+1) + ' / ' + str(panels)
			bbox = self.font_renderer.bounding_box(string)
			x_offset = width-(bbox[3]-bbox[0]) - 10
			y_offset = 10
			
			glPushMatrix()
			glTranslate(x_offset,y_offset,0)
			glRotate(20,0,1,0)
			self.font_renderer.render_string(string)
			glPopMatrix()
			y_offset += bbox[4]-bbox[1]
			for s in self.hud_data:
				string = str(s)
				bbox = self.font_renderer.bounding_box(string)
				x_offset = width-(bbox[3]-bbox[0]) - 10
				y_offset += 10
				glPushMatrix()
				glTranslate(x_offset,y_offset,0)
				glRotate(20,0,1,0)
				self.font_renderer.render_string(string)
				glPopMatrix()
				y_offset += bbox[4]-bbox[1]
		else:
			pass
		
		if enable_depth: glEnable(GL_DEPTH_TEST)
		glMatrixMode(GL_PROJECTION)
		glPopMatrix()
		glMatrixMode(GL_MODELVIEW)
class EMImageMXRotorModule(EMGUIModule):
	
	def get_desktop_hint(self):
		return "rotor"
	
	
	def get_gl_widget(self,qt_context_parent,gl_context_parent):
		from emfloatingwidgets import EM3DGLWindowOverride
		if self.gl_widget == None:
			
			self.gl_context_parent = gl_context_parent
			self.qt_context_parent = qt_context_parent
			
			self.gl_widget = EM3DGLWindowOverride(self,self.rotor)
			self.gl_widget.set_enable_clip(False)
			self.widget = self.gl_widget
			self.gl_widget.resize(640,640)
			self.disable_mx_zoom()
			self.disable_mx_translate()
			
		return self.gl_widget
		
	def get_qt_widget(self):
		if self.qt_context_parent == None:	
			from emimageutil import EMParentWin
			self.gl_context_parent = EMImageMXRotorWidget(self)
			self.qt_context_parent = EMParentWin(self.gl_context_parent)
			self.gl_widget = self.gl_context_parent
		
			self.qt_context_parent.setAcceptDrops(True)

		return self.qt_context_parent
	
		
	def using_ftgl(self): return False
	
	def __init__(self, data=None,application=None):
		self.widget = None
		self.data=None
		self.rotor = EMGLRotorWidget(self,-15,70,-15,EMGLRotorWidget.BOTTOM_ROTARY,200)
		#self.rotor.set_angle_range(110.0)
		#self.rotor.set_child_mouse_events(False)
		self.rotor.set_mouse_mode("mxrotor")
		
		
		self.image_file_name = None	# keeps track of the image file name (if any) - book keeping purposes only
		self.emdata_list_cache = None # all import emdata list cache, the object that stores emdata objects efficiently. Must be initialized via set_data or set_image_file_name
		
		self.default_mxs = 3
		self.visible_mxs = self.default_mxs	# the number of visible imagemxs in the rotor
		self.mx_rows = 4 # the number of rows in any given imagemx
		self.mx_cols = 4 # the number of columns in any given imagemx
		self.start_mx = 0 # the starting index for the currently visible set of imagemxs
		
		EMGUIModule.__init__(self,ensure_gl_context=True)
		
		self.inspector = None
		self.minden=0
		self.maxden=1.0
		self.mindeng=0
		self.maxdeng=1.0
		self.hist = None
		self.gamma=1.0
		self.mmode = 'app'
		self.rot_mode = 'app'
		
		self.vals_to_display = ["Img #"]
		
		self.z_near = 0
		self.z_far = 0

		self.init_flag = True
		
		self.__init_font_renderer()
		
		if data:
			self.set_data(data)

	def __del__(self):
		for widget in self.rotor.get_widgets():
			get_application().deregister_qt_emitter(widget.get_drawable().get_drawable())
		
	def __init_gl_widget(self):
		self.widget = EM3DGLWindowOverride(self,self.rotor)
		self.widget.set_enable_clip(False)
		self.widget.set_draw_frame(False)
		self.disable_mx_zoom()
		self.disable_mx_translate()
			
	def __init_font_renderer(self):
		try:
			self.font_renderer = get_3d_font_renderer()
			self.font_renderer.set_face_size(32)
			self.font_renderer.set_depth(8)
#			self.font_renderer.set_font_mode(FTGLFontMode.EXTRUDE)
			self.font_render_mode = EMGUIModule.FTGL
		except:
			self.font_render_mode = EMGUIModule.GLUT
		
	def get_inspector(self):
		return self.inspector
	
	#def emit(self,*args,**kargs):
		#self.application.get_qt_emitter(self).emit(*args,**kargs)
		
	def set_selected(self,n,update_gl=True):
		widget = self.rotor[0]
		if widget != None:
			widget.get_drawable().get_drawable().set_selected(n,update_gl)
			
	def get_rows(self):
		return self.mx_rows
	
	def get_cols(self):
		return self.mx_cols
	
	def get_mxs(self):
		return self.visible_mxs

	def context(self):
		# asking for the OpenGL context from the parent
		return self.gl_context_parent.context()
	
	def is_visible(self,n):
		widget = self.rotor[0]
		if widget != None:
			img_offset = widget.get_drawable().get_drawable().get_img_num_offset()
			if n >= img_offset and n < (img_offset+self.mx_rows*self.mx_cols):
				return True
			else: return False
		else: return False
	
	def scroll_to(self,n,unused):
		widget = self.rotor[0]
		if widget != None:
			img_offset = widget.get_drawable().get_drawable().get_img_num_offset()
			scroll = (n-img_offset)/(self.mx_rows*self.mx_cols)
			self.rotor.explicit_animation(-scroll)
	
	def set_mx_cols(self,cols):
		self.mx_cols = cols
		self.emdata_list_cache.set_cache_size(8*self.visible_mxs*self.mx_rows*self.mx_cols)
		self.__refresh_rotor(True)
		self.updateGL()
		
	def set_mx_rows(self,rows):
		self.mx_rows = rows
		self.emdata_list_cache.set_cache_size(8*self.visible_mxs*self.mx_rows*self.mx_cols)
		self.__refresh_rotor(True)
		self.updateGL()
	
	def set_display_values(self,v2d):
		self.vals_to_display = v2d
		self.__refresh_rotor(False)
		self.updateGL()

	def set_mxs(self,mxs):
		self.visible_mxs = mxs
		self.emdata_list_cache.set_cache_size(8*self.visible_mxs*self.mx_rows*self.mx_cols)
		self.__regenerate_rotor() # this could be done more efficiently
		self.__refresh_rotor_size()
		self.updateGL()
	
	def set_mouse_mode(self,mode):
		self.mmode = mode
		try:
			for i in range(self.visible_mxs):
				w = self.rotor[i].get_drawable()
				w.set_mouse_mode(self.mmode)
		except: pass
	def set_scale(self,scale):
		pass
	
	def get_density_min(self):
		return self.rotor[0].get_drawable().get_drawable().get_density_min()
	
	def get_density_max(self):
		return self.rotor[0].get_drawable().get_drawable().get_density_max()
	
	def get_hist(self):
		return self.rotor[0].get_drawable().get_drawable().get_hist()
	
	def set_density_max(self,val):
		self.maxden=val
		self.update_min_max_gamma()
	
	def set_density_min(self,val):
		self.minden=val
		self.update_min_max_gamma()
		
	def set_gamma(self,val):
		self.gamma=val
		self.update_min_max_gamma()
	
	def set_plane(self,plane):
		self.plane = plane
	
	def disable_mx_zoom(self):
		'''
		Disable mx zoom.
		'''
		self.rotor.target_zoom_events_allowed(False)
		
	def disable_mx_translate(self):
		self.widget.target_translations_allowed(False)
	
	def allow_camera_rotations(self,bool=False):
		self.widget.allow_camera_rotations(bool)
	
	def pop_box_image(self,idx):
		val = self.emdata_list_cache.delete_box(idx)
		if val == 1:
			self.max_idx = self.emdata_list_cache.get_max_idx()
			self.__refresh_rotor()
		elif val == 2:
			w = self.rotor[0].get_drawable()
			w.force_display_update()
		else:
			print 'failed to delete box image'
		
	def update_min_max_gamma(self,update_gl=True):
		for i in range(self.visible_mxs):
			w = self.rotor[i].get_drawable().get_drawable()
			w.set_min_max_gamma(self.minden,self.maxden,self.gamma,False)
			if  i == 0 and  self.inspector != None:	
				try:
					self.inspector.set_hist(w.get_hist(),self.minden,self.maxden)
				except:
					# the histogram isn't created yet - this is a FIXME
					pass
		
		if update_gl: self.updateGL()
	
	def set_den_range(self,minden,maxden):
		self.minden=minden
		self.maxden=maxden
		self.update_min_max_gamma()
				
	def update_rotor_position(self,inc):
		self.start_mx += inc
	
		if inc > 0:
			end_changed = self.visible_mxs
			start_changed = self.visible_mxs-inc
			
			#print start_changed,end_changed
			#for idx in range(start_changed,end_changed):
			
		elif inc < 0:
			
			end_changed = -inc
			start_changed = 0
			
		else: return
		
		#print "iterating through",start_changed,end_changed,"start_mx is",self.start_mx
		
		self.__update_rotor_range(start_changed ,end_changed)
		
		try:
			w = self.rotor[0].get_drawable().get_drawable()
			self.inspector.set_hist(w.get_hist(),self.minden,self.maxden)
		except: pass
	
	def __update_rotor_range(self,start_changed,end_changed):
		
		num_per_view = self.mx_rows*self.mx_cols
		
		for idx in range(start_changed,end_changed):
			n = idx+ self.start_mx
			
			panel = n
			if panel != 0: panel %= self.get_num_panels()
			
			start_idx = panel*num_per_view
			image_offset = start_idx 
			if image_offset != 0: image_offset %= self.emdata_list_cache.get_max_idx()
			
			d = []
			if image_offset > (self.emdata_list_cache.get_max_idx()-num_per_view):
				num_visible = self.emdata_list_cache.get_max_idx() - image_offset
				num_none = num_per_view - num_visible
				for i in range(start_idx,start_idx+num_visible): d.append(self.emdata_list_cache[i])
				for i in range(num_none): d.append(None)
			else:
				for i in range(start_idx,start_idx+num_per_view): d.append(self.emdata_list_cache[i])
			

			w = self.rotor[idx].get_drawable().get_drawable()
			w.set_data(d,"",False)

			w.set_img_num_offset(image_offset)
			w.set_max_idx(self.emdata_list_cache.get_max_idx())
			w.set_min_max_gamma(self.minden,self.maxden,self.gamma,False)
	
	def get_num_panels(self):
		return int(ceil(float(self.emdata_list_cache.get_max_idx())/ (self.mx_rows*self.mx_cols)))

	def set_rotor_mode(self,mode):
		self.rot_mode = mode
		self.rotor.set_mouse_mode(mode)

	def optimize_fit(self,update_gl=True):
		render_width = self.gl_widget.width()
		render_height = self.gl_widget.height()
		try:
			self.mx_rows = render_width/self.emdata_list_cache.get_xsize()
			self.mx_cols = render_height/self.emdata_list_cache.get_ysize()
			if self.mx_rows == 0: self.mx_rows = 1
			if self.mx_cols == 0: self.mx_cols = 1
		except: return
		
		try:
			self.inspector.set_n_cols(self.mx_cols)
			self.inspector.set_n_rows(self.mx_rows)
		except: pass

		#try:
			#self.widget.set_width(render_width)
			#self.widget.set_height(render_height)
		#except: pass
		
		self.__refresh_rotor(True)
		if update_gl: self.updateGL()
		
	def set_frozen(self,frozen):
		self.rotor.set_frozen(frozen)

	def set_shapes(self,shapes,shrink):
		self.rotor.set_shapes(shapes,shrink)

	def register_animatable(self,animatable):
		self.qt_context_parent.register_animatable(animatable)
		
	def width(self):
		try: return self.gl_widget.width()
		except: return 0
	
	def height(self):
		try: return self.gl_widget.height()
		except: return 0
	
	def get_image_file_name(self):
		''' warning - could return none in some circumstances'''
		try: return self.gl_parent.get_image_file_name()
		except: return None
	
	def get_image(self,idx):
		return self.emdata_list_cache[idx]
	
	def set_data(self,data):
		if data == None or not isinstance(data,list) or len(data)==0:
			self.data = [] 
			return
		fac = int(ceil(float(len(data))/(self.mx_rows*self.mx_cols)))
		if fac == 0: fac = 1
		self.emdata_list_cache = EMDataListCache(data,8*self.visible_mxs*self.mx_rows*self.mx_cols)
		if self.init_flag:
			if fac < self.visible_mxs:
				self.visible_mxs = fac
			self.__regenerate_rotor()
			self.init_flag = False
		else:
#			print "here we are", fac,self.visible_mxs,self.default_mxs
			if fac < self.visible_mxs:
				self.visible_mxs = fac
				self.__regenerate_rotor()
				self.__refresh_rotor_size()
			elif self.visible_mxs < self.default_mxs and fac >= self.default_mxs:
#				print "setting visible mxs"
				self.visible_mxs = self.default_mxs
				self.__regenerate_rotor()
				self.__refresh_rotor_size()
			elif fac > self.visible_mxs and self.visible_mxs < self.default_mxs:
				self.visible_mxs = fac
				self.__regenerate_rotor()
				self.__refresh_rotor_size()
			else:
				self.__refresh_rotor(True)
			
	
	def set_image_file_name(self,name):
		#print "set image file name",name
		self.image_file_name = name
		self.emdata_list_cache = EMDataListCache(name)
		self.__regenerate_rotor()
	
	def __refresh_rotor(self,inc_size=False):
			
		self.__update_rotor_range(0,self.visible_mxs)
		
		if inc_size:
			self.__refresh_rotor_size()

	def __refresh_rotor_size(self):
		if len(self.rotor) == 0: return
		
		
		
		self.render_width = self.gl_widget.width()
		self.render_height = self.gl_widget.height()
		width = self.mx_rows*(self.emdata_list_cache.get_xsize()+2)-2
		height = self.mx_cols*(self.emdata_list_cache.get_ysize()+2)-2
		scale1 = self.render_height/float(height)
		scale2 = self.render_width/float(width)
		
		if self.render_width > self.render_height:
			self.render_height = float(height)/width*self.render_width
			scale = scale2
		else:
			self.render_width = float(width)/height*self.render_height
			scale = scale1
		
		for idx in range(0,self.visible_mxs):
			e = self.rotor[idx]
			w = e.get_drawable().get_drawable()

			w.set_scale(scale,False)
			e.set_width(self.render_width)
			e.set_height(self.render_height)
			e.set_update_frame(True)
			##w.set_mx_cols(self.mx_rows,False)
			
		self.rotor.update()

	def __regenerate_rotor(self):
		for widget in self.rotor.get_widgets():
			get_application().deregister_qt_emitter(widget.get_drawable().get_drawable())
			self.rotor.clear_widgets()
#		self.parent.updateGL() # i can't figure out why I have to do this (when this function is called from set_mxs
		num_per_view = self.mx_rows*self.mx_cols
		for idx in range(self.start_mx,self.start_mx+self.visible_mxs):
			n = idx
			
			panel = n
			if panel != 0: panel %= self.get_num_panels()
			
			start_idx = panel*num_per_view
		
			image_offset = start_idx 
			if image_offset != 0: image_offset %= self.emdata_list_cache.get_max_idx()
			#print idx,panel,image_offset
			
			d = []
			if image_offset > (self.emdata_list_cache.get_max_idx()-num_per_view):
				num_visible = self.emdata_list_cache.get_max_idx() - image_offset
				num_none = num_per_view - num_visible
				#print num_visible,num_none
				for i in range(start_idx,start_idx+num_visible): d.append(self.emdata_list_cache[i])
				for i in range(num_none): d.append(None)
			else:
				for i in range(start_idx,start_idx+num_per_view): d.append(self.emdata_list_cache[i])

			e = EM2DGLView(self,d)
			e.get_drawable().set_app(get_application())
			get_application().register_qt_emitter(e.get_drawable(),get_application().get_qt_emitter(self))
			x = EM2DGLWindow(self,e)
			x.decoration.draw_x_enabled = False
			x.decoration.color_flag = "black"
			self.rotor.add_widget(x)
			
			w = e.get_drawable()
	
			w.set_use_display_list(True) # saves HEAPS of time, makes interaction much smoother
			w.set_reroute_delete_target(self)
			w.set_draw_background(True)
			w.set_mouse_mode(self.mmode)
			w.set_display_values(self.vals_to_display,False)	

			w.set_img_num_offset(image_offset)
			w.set_max_idx(self.emdata_list_cache.get_max_idx())

		e = self.rotor[0]
		w = e.get_drawable().get_drawable()
		self.minden = w.get_density_min()
		self.maxden = w.get_density_max()
		self.hist = w.get_hist()
		self.mindeng = self.minden
		self.maxdeng = self.maxden
		self.gamma = w.get_gamma()
		self.update_min_max_gamma(False)
		
		self.__refresh_rotor_size()

	def updateGL(self):
		try: self.gl_widget.updateGL()
		except: pass


	def render(self):
		if self.widget == None: self.__init_gl_widget()
		
		if not self.get_qt_context_parent().isVisible(): return
		if self.emdata_list_cache == None: return
		
		
		lrt = self.widget.get_lr_bt_nf()

		
		GL.glEnable(GL.GL_DEPTH_TEST)
		GL.glEnable(GL.GL_LIGHTING)
		z = self.gl_context_parent.get_depth_for_height(abs(lrt[3]-lrt[2]))
		z2 = self.gl_context_parent.get_depth_for_width(abs(lrt[1]-lrt[0]))
		
		if z2 > z: z = z2
		
		
		z_near = z-lrt[4]-100
		z_trans = 0
		z_far = z-lrt[5]
		if z_near < 0:
			z_trans = z_near
			z_near = 1
			z_far -= z_trans
		if z_far < 0: z_far = 0.1 # hacking alert
		z_far += abs(lrt[3]-lrt[2]) # hacking alert
		if self.z_near != z_near or self.z_far != z_far:
			self.z_near = z_near
			self.z_far = z_far
			if isinstance(self.gl_context_parent,EMImageMXRotorWidget):
				self.gl_context_parent.set_near_far(self.z_near,self.z_far)
			else: print "bug 2"

		GL.glPushMatrix()
		glTranslate(-(lrt[1]+lrt[0])/2.0,-(lrt[3]+lrt[2])/2.0,-z)
		self.widget.draw()
		GL.glPopMatrix()
	
		self.draw_hud()
	
	def dragEnterEvent(self,event):
		pass

	def dropEvent(self,event):
		pass

	def get_inspector(self):
		if not self.inspector: 
			self.inspector=EMImageInspectorMX(self,allow_col_variation=True,allow_window_variation=True,allow_opt_button=True)
			self.inspector.set_limits(self.mindeng,self.maxdeng,self.minden,self.maxden)
			
		return self.inspector
	def mousePressEvent(self, event):
		if event.button()==Qt.MidButton or (event.button()==Qt.LeftButton and event.modifiers()&Qt.AltModifier):
			self.show_inspector(True)
		else:
			self.widget.mousePressEvent(event)
			
		self.updateGL()
		
	def mouseMoveEvent(self, event):
		if self.widget.isinwin(event.x(),self.gl_context_parent.viewport_height()-event.y()):
			self.widget.mouseMoveEvent(event)
			self.updateGL()
		
	def mouseReleaseEvent(self, event):
		self.widget.mouseReleaseEvent(event)
		self.updateGL()
		
	def wheelEvent(self, event):
		if self.widget.isinwin(event.x(),self.gl_context_parent.viewport_height()-event.y()):
			self.widget.wheelEvent(event)
			self.updateGL()
		
	def leaveEvent(self,event):
		pass
	
	def keyPressEvent(self,event):
		self.widget.keyPressEvent(event)
		self.updateGL()
		
	def resize_event(self, width, height):
		if self.widget != None: 
			self.widget.update()
		self.rotor.resize_event(width,height)
		self.optimize_fit(False)
	
	def projection_or_viewport_changed(self):
		self.rotor.resize_event(-1,1)
	
	def save_lst(self):
		self.emdata_list_cache.save_lst()
		
	def save_data(self):
		self.emdata_list_cache.save_data()
	
	def get_frame_buffer(self):
		return self.gl_widget.get_frame_buffer()
	
	
	ligh_yellow_diffuse = (.84,.82,.38,1.0)
	ligh_yellow_ambient = (.83,.83,.38,1.0)
	ligh_yellow_specular = (.76,.75,.39,1.0)
	def draw_hud(self):
		width = self.gl_widget.viewport_width()
		height =self.gl_widget.viewport_height()
		glMatrixMode(GL_PROJECTION)
		glPushMatrix()
		glLoadIdentity()
		glOrtho(0,width,0,height,-200,200)
		glMatrixMode(GL_MODELVIEW)
		glLoadIdentity()
		glDisable(GL_LIGHTING)
		glEnable(GL_NORMALIZE)

		glMaterial(GL_FRONT,GL_AMBIENT,EMImageMXRotorModule.ligh_yellow_ambient)
		glMaterial(GL_FRONT,GL_DIFFUSE,EMImageMXRotorModule.ligh_yellow_diffuse)
		glMaterial(GL_FRONT,GL_SPECULAR,EMImageMXRotorModule.ligh_yellow_specular)
		glMaterial(GL_FRONT,GL_SHININESS,30.0)
		
		enable_depth = glIsEnabled(GL_DEPTH_TEST)
		glDisable(GL_DEPTH_TEST)
		glEnable(GL_TEXTURE_2D)
		glColor(1.0,1.0,1.0)
		glColor(*EMImageMXRotorModule.ligh_yellow_specular)
		
		if self.font_render_mode == EMImageMXModule.FTGL:
			panels = self.get_num_panels()
			idx = self.start_mx
			if idx != 0: idx %= panels
			string = str(idx+1) + ' / ' + str(panels)
			glPushMatrix()
			glTranslate(10,height-1.2*self.font_renderer.get_face_size(),0)
			glRotate(20,0,1,0)
			self.font_renderer.render_string(string)
			glPopMatrix()
		else:
			pass
		
		if enable_depth: glEnable(GL_DEPTH_TEST)
		
		glMatrixMode(GL_PROJECTION)
		glPopMatrix()
		glMatrixMode(GL_MODELVIEW)