コード例 #1
0
ファイル: Stack.py プロジェクト: afrutig/Moloreader_high_end
class Stack(QtGui.QWidget):
	def __init__(self,main_widget):
		super(Stack,self).__init__()

		self.counter       = 0
		self.database_path = ''
		self.num_captures  = 0
		self.time_interval = 0

		self.main_widget   = main_widget

		
		self.initUI()
		self.crop_image.setChecked(True)
		self.update_plots.setChecked(True)
		self.adjust_exposure.setChecked(True)
		self.toggle_move_to_mologram()
		self.toggle_reference_mologram()

	def initUI(self):

		# algorithm names
		self.algo_names = []
		self.algo_names.append('sum over background plus 3 sigma')

		# different types of stacks
		self.stack_type_list = []
		self.stack_type_list.append('time')
		self.stack_type_list.append('z-position (um)')
		self.stack_type_list.append('TE-position (deg)')
		self.stack_type_list.append('exposure')

		self.mologram_sides = ['left','right']

		self.time_unit_list = ['s','min']	

		# declare widgets
		# labels for the form
		self.editFolder_lbl  	= QtGui.QLabel('Experiment Folder')
		self.mologram_lbl    	= QtGui.QLabel('Move to Mologram')
		self.time_int_lbl    	= QtGui.QLabel('Time Interval')
		self.num_caps_lbl    	= QtGui.QLabel('Number of Captures')
		self.algorithm_lbl   	= QtGui.QLabel('Intensity Algorithm')
		self.stack_type_lbl  	= QtGui.QLabel('Stack Type')
		self.stack_incr_lbl  	= QtGui.QLabel('Stack Increment (down)')
		self.start_lbl      	= QtGui.QLabel('')
		self.stop_lbl        	= QtGui.QLabel('')
		self.pause_lbl       	= QtGui.QLabel('')
		self.move_to_lbl     	= QtGui.QLabel('Enable Move to Mologram')
		self.cap_laser_lbl   	= QtGui.QLabel('Record Laser Intensity')
		self.ref_molo_lbl    	= QtGui.QLabel('Reference Mologram')
		self.num_avg_lbl 		= QtGui.QLabel('Number of Avg per capture')
		self.crop_image_lbl     = QtGui.QLabel('')
		self.update_plots_lbl	= QtGui.QLabel('Update Plots')
		self.adjust_exposure_lbl= QtGui.QLabel('Adjust Exposure when saturated')

		# line edits and selectors
		self.editFolder       	= QtGui.QLineEdit()
		self.mologram_pos     	= MologramSelector()
		self.time_int_sbox    	= QtGui.QDoubleSpinBox(value = 3)
		self.stack_incr_sbox  	= QtGui.QDoubleSpinBox()
		self.number_caps      	= QtGui.QSpinBox(value = 1)
		self.time_units       	= QtGui.QComboBox()
		self.algorithms       	= QtGui.QComboBox()
		self.stack_type       	= QtGui.QComboBox()
		self.stack_unit       	= QtGui.QComboBox()
		self.mologram_side    	= QtGui.QComboBox()
		self.num_avg 		  	= QtGui.QSpinBox(value = 1)

		self.crop_image 		= QtGui.QCheckBox('Crop image to 60 x 60 um')
		self.update_plots 		= QtGui.QCheckBox('')
		self.adjust_exposure 	= QtGui.QCheckBox('')

		for name in self.mologram_sides:
			self.mologram_side.addItem(name)

		for name in self.algo_names:
			self.algorithms.addItem(name)

		for name in self.stack_type_list:
			self.stack_type.addItem(name)

		for name in self.time_unit_list:
			self.time_units.addItem(name)

		self.set_stack_unit()

		self.number_caps.setRange(0,100000)

		# Create and connect buttons	
		self.start = QtGui.QPushButton('Start Experiment')
		self.start.clicked.connect(self.start_f)
		self.start.resize(self.start.sizeHint())

		self.browse = QtGui.QPushButton('browse')
		self.browse.clicked.connect(self.browse_f)
		self.browse.resize(self.browse.sizeHint())

		self.stop = QtGui.QPushButton('Stop Experiment')
		

		self.pause = QtGui.QPushButton('Pause/Continue Experiment')
		

		self.stack_type.activated[str].connect(self.set_stack_unit)

		self.move_to_mologram_btn = QtGui.QCheckBox('Enable')
		self.move_to_mologram_btn.clicked.connect(self.toggle_move_to_mologram)

		self.reference_mologram = QtGui.QCheckBox('Enable')                  
		self.reference_mologram.clicked.connect(self.toggle_reference_mologram)

		self.record_laser_btn = QtGui.QCheckBox('')
		#self.record_laser_btn.clicked.connect(self.toggle_capture_laser)

		# layout
		hbox_folder   = QtGui.QHBoxLayout()
		hbox_time     = QtGui.QHBoxLayout()
		hbox_stack    = QtGui.QHBoxLayout()
		hbox_mologram = QtGui.QHBoxLayout()
		hbox_ref      = QtGui.QHBoxLayout()
		

		hbox_folder.addWidget(self.editFolder)
		hbox_folder.addWidget(self.browse)

		hbox_time.addWidget(self.time_int_sbox)
		hbox_time.addWidget(self.time_units)

		hbox_stack.addWidget(self.stack_incr_sbox)
		hbox_stack.addWidget(self.stack_unit)

		hbox_ref.addWidget(self.reference_mologram)
		hbox_ref.addWidget(self.mologram_side)

		

		hbox_mologram.addWidget(self.move_to_mologram_btn)
		hbox_mologram.addLayout(self.mologram_pos)

		fbox = QtGui.QFormLayout()
		fbox.addRow(self.editFolder_lbl, hbox_folder)
		fbox.addRow(self.mologram_lbl,   hbox_mologram)
		fbox.addRow(self.crop_image_lbl,self.crop_image)
		fbox.addRow(self.stack_type_lbl, self.stack_type)
		fbox.addRow(self.time_int_lbl,   hbox_time)
		fbox.addRow(self.stack_incr_lbl, hbox_stack)
		fbox.addRow(self.num_caps_lbl,   self.number_caps)
		fbox.addRow(self.num_avg_lbl,self.num_avg)
		fbox.addRow(self.ref_molo_lbl,   hbox_ref)
		fbox.addRow(self.algorithm_lbl,  self.algorithms)
		fbox.addRow(self.cap_laser_lbl,  self.record_laser_btn)
		fbox.addRow(self.update_plots_lbl,self.update_plots)
		fbox.addRow(self.adjust_exposure_lbl,self.adjust_exposure)
		fbox.addRow(self.start_lbl,      self.start)
		fbox.addRow(self.stop_lbl,       self.stop)
		fbox.addRow(self.pause_lbl,      self.pause)
		
		hbox = QtGui.QHBoxLayout()
		hbox.addLayout(fbox)
		self.setLayout(hbox)

	def set_stack_unit(self,str = None):
		""" Depending on the current stack type, set the right units for the stack units 
		QComboBox. Also disables and enables other widgets in the stack selector box."""
	
		curr_stack_type = self.stack_type.currentText()

		self.stack_unit.setEnabled(True)
		self.stack_incr_sbox.setEnabled(True)
		self.stack_unit.clear()

		if curr_stack_type == self.stack_type_list[1]:
			self.num_avg.setEnabled(True)
			
		else:
			self.num_avg.setEnabled(False)

		if   curr_stack_type == self.stack_type_list[0]:
			self.stack_unit.setEnabled(False)
			self.stack_incr_sbox.setEnabled(False)
			return
		elif curr_stack_type == self.stack_type_list[1]:
			units_list = ['um']
		elif curr_stack_type == self.stack_type_list[2]:
			units_list = ['deg']
		elif curr_stack_type == self.stack_type_list[3]:
			units_list = ['ms']

		for unit in units_list:
			self.stack_unit.addItem(unit)

	
	def fetch_mologram_data(self,database_path = None):
		""" Fetch all the rows in the SQL database for the given path and return all of the data as a numpy array """

		# Check if datapase path was passed
		if database_path == None:
			database_path = self.database_path

		if database_path == '':
			return None

		# Connect to database
		con = sqlite3.connect(database_path + '/mologram_data.db')
		cur = con.cursor()

		# fetch all rows from database
		rows = []
		for row in cur.execute('SELECT * FROM mologram_data ORDER BY key'):
			rows.append(row)

		# Close connection with SQL databse
		con.close()

		# extract data
		rows       = np.array(rows)
		print(rows.shape)
		print(type(rows))
		time       = rows[:,1]
		intensity  = rows[:,7]
		

		return time,intensity
		

	def confirm_user_input(self,experiment_folder_path,num_captures):
		# Test for incorrect user input
		if experiment_folder_path == '':
			msg = QtGui.QMessageBox()
			msg.setWindowTitle("Folder name")
			msg.setIcon(QtGui.QMessageBox.Warning)
			msg.setStandardButtons(QtGui.QMessageBox.Ok)
			msg.setText("Please select a valid experiment folder")
			msg.exec_()
			return -1

		if num_captures == 0:
			msg = QtGui.QMessageBox()
			msg.setWindowTitle("Experiment Length")
			msg.setIcon(QtGui.QMessageBox.Warning)
			msg.setStandardButtons(QtGui.QMessageBox.Ok)
			msg.setText("Please a valib experiment length")
			msg.exec_()
			return -1

		# Clear existing data in selected directory and create necessary directories
		if os.listdir(experiment_folder_path) != []:

			msg = QtGui.QMessageBox()
			msg.setWindowTitle("Question")
			msg.setIcon(QtGui.QMessageBox.Warning)
			msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
			msg.setText("Are you sure you want to delete the existing data?")
			retval = msg.exec_()

			if retval == QtGui.QMessageBox.No:
				return -1

			# Clear previous results
			os.system('sudo rm -rf ' + experiment_folder_path + '/*')

		return 0

	""" Fetch all parameters for experiment from GUI and launch the experiment in a seperate thread """
	def start_f(self):

		# Determine where to store results
		experiment_folder_path = self.editFolder.text()
		image_path    = experiment_folder_path + '/images'
		self.database_path = experiment_folder_path + '/database'

		# Confirm user input and delete experiment information if it is already there.
		if self.confirm_user_input(experiment_folder_path,self.number_caps.value()) == -1:
			return
		

		self.main_widget.set_experiment_folder_path(experiment_folder_path)

		# Create directories if non-existent
		directories = [experiment_folder_path,image_path,self.database_path]

		for directory in directories:
			if not os.path.exists(directory):
				os.makedirs(directory)

		# Thread for recording the Experiment
		self.experiment = Experiment(self.main_widget,self.database_path)

		self.connect(
			self.experiment, 
			QtCore.SIGNAL("database_updated"), 
			self.main_widget.updateAllStack
		)

		self.connect(
			self.experiment, 
			QtCore.SIGNAL("done_experiment"), 
			self.done_experiment
		)

		self.stop.clicked.connect(self.experiment.stop)
		

		self.pause.clicked.connect(self.experiment.pause)
		



		try:
			self.main_widget.plotTab.set_current_plot('time_stack')
			
		except Exception:
			pass

		# Adjust time_interval depending on time unit
		if   self.time_units.currentText() == 'ms':
			time_interval /= 1000
		elif self.time_units.currentText() == 'min':
			time_interval *= 60
		elif self.time_units.currentText() == 's':
			pass

		

		

		# If user wished so, move to mologram automatically
		if self.move_to_mologram_btn.isChecked():
			position = self.mologram_pos.position()
			print('Moving to mologram ' + position)
			self.main_widget.setup.chip.move_to(position)

		# Create file with experiment parameters for easier analysis later on
		self.create_info_file()

		# Start experiment 
		self.experiment.record_data(
			image_path         = image_path,
			database_path      = self.database_path,
			num_captures       = self.number_caps.value(),
			num_avg            = self.num_avg.value(),
			time_interval      = self.time_int_sbox.value(),
			stack_type         = self.stack_type.currentText(),
			stack_incr         = self.stack_incr_sbox.value(),
			stack_type_list    = self.stack_type_list,
			current_algo       = self.algorithms.currentText(),
			algo_names         = self.algo_names,
			record_laser       = self.record_laser_btn.isChecked(),
			reference_mologram = self.reference_mologram.isChecked(),
			mologram_side      = self.mologram_side.currentText(),
			crop_image         = self.crop_image.isChecked(),
			update_plots 	   = self.update_plots.isChecked(),
			adjust_exposure 	= self.adjust_exposure.isChecked())

	""" Create file with experiment parameters for easier analysis later on """
	def create_info_file(self):

		info = dict({})

		# Add all parameters to a dictionary
		info['Experiment Folder']   = self.database_path
		info['Number of Captures']  = self.number_caps.value()
		info['Time Interval']       = self.time_int_sbox.value()
		info['Number of Averages']  = self.num_avg.value()
		info['Stack Type']          = self.stack_type.currentText()
		info['Stack Increment']     = self.stack_incr_sbox.value()
		info['Recorded Algorithms'] = self.algorithms.currentText()
		info['Record Laser']        = self.record_laser_btn.isChecked()
		info['Mologram Name']       = self.main_widget.setup.chip.file_name()
		info['Reference Mologram']  = self.reference_mologram.isChecked()
		info['Mologram Side']       = self.mologram_side.currentText()

		# Store dictionary as JSON data in an info file 
		file = open(self.editFolder.text() + '/experiment.info','w')
		json.dump(info,file)
		file.close()

	""" Once experiment is done or if it stopped unexpectedly, show appropriate message box and update GUI """
	def done_experiment(self):

		# Indicate experiment is complete
		msg = QtGui.QMessageBox()
		msg.setWindowTitle("Experiment")
		msg.setIcon(QtGui.QMessageBox.Information)
		msg.setStandardButtons(QtGui.QMessageBox.Ok)
		msg.setText("Experiment is complete")
		msg.exec_()	

		# Update all displays
		self.main_widget.updateAll()

	def browse_f(self):
		folder = QtGui.QFileDialog.getExistingDirectory(self, 'Open file', '/home')

		self.editFolder.setText(folder)

	def toggle_move_to_mologram(self):
		self.mologram_pos.setEnabled(self.move_to_mologram_btn.isChecked())

	def toggle_reference_mologram(self):
		self.mologram_side.setEnabled(self.reference_mologram.isChecked())
コード例 #2
0
class CalibrationTab(QtGui.QWidget):
	def __init__(self,main_widget):
		super(CalibrationTab,self).__init__()

		self.main_widget = main_widget

		self.heights = self.read_heights()

		self.initUI()

	def initUI(self):

		# Define buttons
		self.calibrate         = QtGui.QPushButton('Calibrate')
		self.set_position      = QtGui.QPushButton('Set Position')
		self.setSurfaceHeight  = QtGui.QPushButton('Set Surface Height')
		self.setMoloHeight     = QtGui.QPushButton('Set Mologram Height')
		self.goToSurfaceHeight = QtGui.QPushButton('Go To Surface Height')
		self.goToMoloHeight    = QtGui.QPushButton('Go To Mologram Height')

		self.mologram_pos = MologramSelector()

		# connect buttons
		self.calibrate.clicked.connect(self.onCalibrateClicked)
		self.set_position.clicked.connect(self.onSetPositionClicked)
		self.setSurfaceHeight.clicked.connect(self.onSetSurfaceHeightClicked)
		self.setMoloHeight.clicked.connect(self.onSetMologramHeightClicked)
		self.goToSurfaceHeight.clicked.connect(self.onGoToSurfaceHeightClicked)
		self.goToMoloHeight.clicked.connect(self.onGoToMologramHeightClicked)

		# Layout
		vbox = QtGui.QVBoxLayout()
		self.setLayout(vbox)

		hbox = QtGui.QHBoxLayout()
		hbox.addLayout(self.mologram_pos)
		hbox.addWidget(self.set_position)

		vbox.addWidget(self.calibrate)
		vbox.addLayout(hbox)
		vbox.addWidget(self.setSurfaceHeight)
		vbox.addWidget(self.setMoloHeight)
		vbox.addWidget(self.goToSurfaceHeight)
		vbox.addWidget(self.goToMoloHeight)

		self.calibrate.resize(self.calibrate.sizeHint())
		self.set_position.resize(self.set_position.sizeHint())
		self.setSurfaceHeight.resize(self.setSurfaceHeight.sizeHint())
		self.setMoloHeight.resize(self.setMoloHeight.sizeHint())
		self.goToSurfaceHeight.resize(self.goToSurfaceHeight.sizeHint())
		self.goToMoloHeight.resize(self.goToMoloHeight.sizeHint())

	def onCalibrateClicked(self):
		self.main_widget.calib()

	def onSetPositionClicked(self):

		pos = self.mologram_pos.position()
		x,y = self.main_widget.setup.chip.cartesian_position(pos)

		self.main_widget.setup.motors.x.set_position(x,'mm')
		self.main_widget.setup.motors.y.set_position(y,'mm')

		# update position and images
		self.main_widget.updateAll()

	def write_heights(self,heights):
		file = open('heights.txt','w')
		json.dump(heights,file)
		file.close()
		
	def read_heights(self):
		file = open('heights.txt','r')
		heights = json.load(file)
		file.close()

		return heights

	def onSetSurfaceHeightClicked(self):
		self.heights["surface_height"] = self.main_widget.setup.motors.z.pos('mm')
		self.write_heights(self.heights)

	def onGoToSurfaceHeightClicked(self):

		self.main_widget.axisControl.z.start_moving(
			distance = self.heights["surface_height"],
			unit     = 'mm',
			relative = False
		)

	def onSetMologramHeightClicked(self):
		self.heights["mologram_height"] = self.main_widget.setup.motors.z.pos('mm')
		self.write_heights(self.heights)

	def onGoToMologramHeightClicked(self):		

		self.main_widget.axisControl.z.start_moving(
			distance = self.heights["mologram_height"],
			unit     = 'mm',
			relative = False
		)