def initUI(self):

		# If not in offline mode, do not initialize setup
		if not self.offline_mode:
			self.setup = Setup()
		
		# Create widgets, pass self so they can talk to each other
		print('Setting up widgets')

		# set up widgets
		if not self.offline_mode:
			self.axisControl    = AxisControl(self)
			self.savedPositions = SavedPositions(self)

			self.cameraWidget   = CameraWidget(self)
			
			self.mologramTab    = MologramWidget(self)
			self.saveImage      = SaveImage(self)
		else:
			self.axisControl    = QtGui.QLabel('')
			self.cameraWidget   = QtGui.QLabel('')
			self.savedPositions = QtGui.QLabel('')
			self.mologramTab    = QtGui.QLabel('')
			self.saveImage      = QtGui.QLabel('')

		# set up tabs
		if not self.offline_mode:
			self.imageAquisitionTab = ImageAquisitionTab(self)
			self.manualControlTab   = ManualControlTab(self)
			self.calibrationTab     = CalibrationTab(self)
			self.imageProcessingTab = ImageProcessingTab(self)
		else:
			self.imageAquisitionTab = QtGui.QLabel('')
			self.manualControlTab   = QtGui.QLabel('')
			self.calibrationTab     = QtGui.QLabel('')
			self.imageProcessingTab = QtGui.QLabel('')

		self.plotTab   			= PlotTab(self)
		self.postProcessingTab  = PostProcessingTab(self)
		print('Done setting up widgets')

		self.tabs_top = QtGui.QTabWidget()
		self.tabs_top.addTab(self.mologramTab,'Mologram Position')
		self.tabs_top.addTab(self.plotTab, 'Time Stack Plots')

		self.tabs_bot = QtGui.QTabWidget()
		self.tabs_bot.addTab(self.manualControlTab,'Manual Motor Control')
		self.tabs_bot.addTab(self.imageAquisitionTab, 'Image Acquisition')
		self.tabs_bot.addTab(self.calibrationTab, 'Calibration')
		self.tabs_bot.addTab(self.postProcessingTab, 'Post Processing')
		self.tabs_bot.addTab(self.imageProcessingTab, 'Image Processing')
	
		# declare layouts
		main_hbox  = QtGui.QHBoxLayout()
		left_vbox  = QtGui.QVBoxLayout()
		right_vbox = QtGui.QVBoxLayout()

		top_left_hbox = QtGui.QHBoxLayout()
		btm_left_vbox = QtGui.QVBoxLayout()

		v_splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
		v_splitter.addWidget(self.tabs_top)
		v_splitter.addWidget(self.tabs_bot)

		h_splitter = QtGui.QSplitter(QtCore.Qt.Horizontal)
		h_splitter.addWidget(v_splitter)
		h_splitter.addWidget(self.cameraWidget)

		main_hbox.addWidget(h_splitter)

		self.setLayout(main_hbox)
class MainWidget(QtGui.QWidget):
	# Constructor
	def __init__(self,app):

		# Call parent class constructor
		super(MainWidget,self).__init__()

		# Initialize member variables		
		self.enable_image_processing = False
		self.app = app

		# Determine whether in offline mode
		self.offline_mode = self.ask_offline_mode()

		# Call child constructor
		self.initUI()
		self.set_offline_mode()

		# Update image and positions
		self.updateAll()

	# Initialization of GUI
	def initUI(self):

		# If not in offline mode, do not initialize setup
		if not self.offline_mode:
			self.setup = Setup()
		
		# Create widgets, pass self so they can talk to each other
		print('Setting up widgets')

		# set up widgets
		if not self.offline_mode:
			self.axisControl    = AxisControl(self)
			self.savedPositions = SavedPositions(self)

			self.cameraWidget   = CameraWidget(self)
			
			self.mologramTab    = MologramWidget(self)
			self.saveImage      = SaveImage(self)
		else:
			self.axisControl    = QtGui.QLabel('')
			self.cameraWidget   = QtGui.QLabel('')
			self.savedPositions = QtGui.QLabel('')
			self.mologramTab    = QtGui.QLabel('')
			self.saveImage      = QtGui.QLabel('')

		# set up tabs
		if not self.offline_mode:
			self.imageAquisitionTab = ImageAquisitionTab(self)
			self.manualControlTab   = ManualControlTab(self)
			self.calibrationTab     = CalibrationTab(self)
			self.imageProcessingTab = ImageProcessingTab(self)
		else:
			self.imageAquisitionTab = QtGui.QLabel('')
			self.manualControlTab   = QtGui.QLabel('')
			self.calibrationTab     = QtGui.QLabel('')
			self.imageProcessingTab = QtGui.QLabel('')

		self.plotTab   			= PlotTab(self)
		self.postProcessingTab  = PostProcessingTab(self)
		print('Done setting up widgets')

		self.tabs_top = QtGui.QTabWidget()
		self.tabs_top.addTab(self.mologramTab,'Mologram Position')
		self.tabs_top.addTab(self.plotTab, 'Time Stack Plots')

		self.tabs_bot = QtGui.QTabWidget()
		self.tabs_bot.addTab(self.manualControlTab,'Manual Motor Control')
		self.tabs_bot.addTab(self.imageAquisitionTab, 'Image Acquisition')
		self.tabs_bot.addTab(self.calibrationTab, 'Calibration')
		self.tabs_bot.addTab(self.postProcessingTab, 'Post Processing')
		self.tabs_bot.addTab(self.imageProcessingTab, 'Image Processing')
	
		# declare layouts
		main_hbox  = QtGui.QHBoxLayout()
		left_vbox  = QtGui.QVBoxLayout()
		right_vbox = QtGui.QVBoxLayout()

		top_left_hbox = QtGui.QHBoxLayout()
		btm_left_vbox = QtGui.QVBoxLayout()

		v_splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
		v_splitter.addWidget(self.tabs_top)
		v_splitter.addWidget(self.tabs_bot)

		h_splitter = QtGui.QSplitter(QtCore.Qt.Horizontal)
		h_splitter.addWidget(v_splitter)
		h_splitter.addWidget(self.cameraWidget)

		main_hbox.addWidget(h_splitter)

		self.setLayout(main_hbox)

	def set_experiment_folder_path(self,experiment_folder_path):

		self.experiment_folder_path = experiment_folder_path

	def get_experiment_folder_path(self):

		return self.experiment_folder_path

	def ask_offline_mode(self):
		msg = QtGui.QMessageBox()
		msg.setWindowTitle("Offline mode")
		msg.setIcon(QtGui.QMessageBox.Question)
		msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
		msg.setText("Do you wish to start in offline mode?")
		retval = msg.exec_()

		return retval == QtGui.QMessageBox.Yes

	def set_offline_mode(self):

		# Disable tabs that are not useful in offline mode		
		self.tabs_top.setTabEnabled(0,not self.offline_mode)	# Mologram Position		
		self.tabs_bot.setTabEnabled(0,not self.offline_mode)	# Manual motor control		
		self.tabs_bot.setTabEnabled(1,not self.offline_mode)	# Image Acquisition		
		self.tabs_bot.setTabEnabled(2,not self.offline_mode)	# Calibration			
	#	self.tabs_bot.setTabEnabled(3,not self.offline_mode)	# Post Processing			
		self.tabs_bot.setTabEnabled(4,			# Image Processing
			not self.offline_mode and self.enable_image_processing)

	# linked to the main calibration button
	def calib(self):

		if not self.offline_mode:
			self.setup.calib()

			msg = QtGui.QMessageBox()
			msg.setWindowTitle("Calibration")
			msg.setIcon(QtGui.QMessageBox.Information)
			msg.setStandardButtons(QtGui.QMessageBox.Ok)

			msg.setText("Calibration is finshed")
			msg.exec_()

	def updatePos(self):
		if not self.offline_mode:
			self.axisControl.updatePos()
			self.savedPositions.updatePos()
			self.mologramTab.updateDisplay()

	def updateImg(self,Stack=False):

		time1 = time.time()

		if not self.offline_mode:

			self.cameraWidget.updateImage(Stack)
			
		time2 = time.time()
		self.plotTab.updateImage()
		time3 = time.time()

		print('Total update time: ' + str(time3-time1))
		if not self.offline_mode:
			print('  >> camera widget update time: ' + str(time2-time1))
		print('  >> plot tab update time:      ' + str(time3-time2))

		if self.enable_image_processing == True:
			self.imageProcessingTab.updateCanvas()


	def updateAll(self):
		print("default update all launched")
		self.updatePos()
		self.updateImg()

	def updateAllStack(self):
		# special update function during stack execution, because the camera should not
		# be used to get additional images otherwise the software crashes.
		self.updatePos()
		self.updateImg(Stack=True)

	def toggle_enable_image_processing(self):
		self.enable_image_processing = not(self.enable_image_processing)
		self.tabs_bot.setTabEnabled(4,self.enable_image_processing)
		self.updateImg()

	def redraw(self):
		self.app.processEvents()

	""" Tell the GUI that the current motor is in movemnt or not """
	def set_in_movement(self,state):

		# When in movement, disable buttons that would enable a simultaneous movement
		widget_list = [self.axisControl, self.mologramTab]

		for widget in widget_list:
			widget.set_in_movement(state)

	def stop_moving(self):
		self.set_in_movement(False)
		self.updateAll()