diff --git a/FocusCorrectionPlaneWindow.py b/FocusCorrectionPlaneWindow.py index 63af50e..9261732 100644 --- a/FocusCorrectionPlaneWindow.py +++ b/FocusCorrectionPlaneWindow.py @@ -201,5 +201,5 @@ def handle_open_dialog(self): win = FocusCorrectionPlaneWindow(plist,imgSrc) win.show() app.exec_() - imgSrc.mmc.reset() + imgSrc.shutdown() sys.exit() \ No newline at end of file diff --git a/LiveMode.py b/LiveMode.py index 45d5a7e..02da81f 100644 --- a/LiveMode.py +++ b/LiveMode.py @@ -7,7 +7,6 @@ import pyqtgraph.ptime as ptime import time from skimage import img_as_ubyte,exposure -import MMCorePy import cv2 from pyqtgraph.widgets.RawImageWidget import RawImageWidget import functools @@ -21,13 +20,12 @@ def __init__(self,imgSrc,exposure_times=dict([]),channelGroup="Channels"): self.channelGroup=channelGroup self.exposure_times=exposure_times #self.setContentsMargins(0,0,0,0) - self.mmc = imgSrc.mmc + self.imgSrc = imgSrc - self.channels=self.mmc.getAvailableConfigs(self.channelGroup) + self.channels=self.imgSrc.get_channels() self.init_mmc() self.initUI() - self.i = 0 self.updateTime = ptime.time() self.fps = 0 @@ -36,23 +34,18 @@ def __init__(self,imgSrc,exposure_times=dict([]),channelGroup="Channels"): def init_mmc(self): #filename="C:\Users\Smithlab\Documents\ASI_LUM_RETIGA_CRISP.cfg" - #self.mmc.loadSystemConfiguration(filename) - #self.mmc.enableStderrLog(False) - #self.mmc.enableDebugLog(False) - # # mmc.setCircularBufferMemoryFootprint(100) - self.cam=self.mmc.getCameraDevice() - self.mmc.setExposure(50) - #self.mmc.setProperty(self.cam, 'Gain', 1) + + + self.imgSrc.set_exposure(50) + Nch=len(self.channels) startChan=self.channels[Nch-1] for ch in self.channels: if 'dapi' in ch.lower(): - self.mmc.setConfig(self.channelGroup,ch) - self.mmc.waitForConfig(self.channelGroup,ch) - camera = self.mmc.getCameraDevice() - self.mmc.setProperty(camera,'Binning','1x1') - print 'Binning is:', self.mmc.getProperty(camera,'Binning') - self.mmc.startContinuousSequenceAcquisition(1) + self.imgSrc.set_channel(ch) + self.imgSrc.set_binning(1) + print 'Binning is:', self.imgSrc.get_binning() + self.startContinuousSequenceAcquisition(1) def initUI(self): @@ -103,7 +96,7 @@ def initUI(self): if ch in keys: spnBox.setValue(self.exposure_times[ch]) else: - spnBox.setValue(self.mmc.getExposure()) + spnBox.setValue(self.imgSrc.get_exposure()) spnBox.setSuffix(" ms") btn.clicked.connect(self.make_channelButtonClicked(ch,spnBox)) self.expSpnBoxes.append(spnBox) @@ -145,23 +138,22 @@ def getExposureTimes(self): return exposure_times def setExposureAuto(self,evt): - - self.mmc.stopSequenceAcquisition() + + self.imgSrc.stopSequenceAcquisition() perc=95; #the goal is to make the X percentile value equal to Y percent of the maximum value #perc is X desired_frac=.7 #desired_frac is Y max_exposure = 3000 #exposure times shall not end up more than this close_frac = .2 #fractional change in exposure for which we will just trust the math - bit_depth=self.mmc.getImageBitDepth() - max_val=np.power(2,bit_depth) + max_val=self.imgSrc.get_max_pixel_value() + #loop over the channels for i,ch in enumerate(self.channels): img_counter =0 #counter to count how many snaps it takes us if 'Dark' not in ch: #don't set the 'Dark' channel for obvious reasons print ch #setup to use the channel - self.mmc.setConfig(self.channelGroup,ch) - self.mmc.waitForConfig(self.channelGroup,ch) + self.imgSrc.set_channel(ch) #get current exposure @@ -172,10 +164,10 @@ def setExposureAuto(self,evt): #follow loop till we get it right while 1: - self.mmc.setExposure(curr_exposure) - self.mmc.snapImage() + self.imgSrc.set_exposure(curr_exposure) + img=self.imgSrc.snap_image() img_counter+=1 - img=self.mmc.getImage() + vec=img.flatten() #the value which is at the perc percentile @@ -234,20 +226,17 @@ def make_channelButtonClicked(self,ch,spnBox): def channelButtonClicked(): #print ch #print spnBox.value() - self.mmc.stopSequenceAcquisition() - self.mmc.clearCircularBuffer() - self.mmc.setConfig(self.channelGroup,ch) + self.imgSrc.stopSequenceAcquisition() + self.imgSrc.set_channel(ch) expTime=spnBox.value() - self.mmc.setExposure(expTime) - self.mmc.waitForConfig(self.channelGroup,ch) - self.mmc.startContinuousSequenceAcquisition(expTime) + self.imgSrc.set_exposure(expTime) + self.imgSrc.startContinuousSequenceAcquisition(expTime) return channelButtonClicked def closeEvent(self,evt): - self.mmc.stopSequenceAcquisition() - camera = self.mmc.getCameraDevice() - self.mmc.setProperty(camera,'Binning','2x2') - print 'Binning is:', self.mmc.getProperty(camera,'Binning') + self.imgSrc.stopSequenceAcquisition() + self.imgSrc.set_binning(2) + print 'Binning is:', self.get_binning() print "stopped acquisition" #if self.timer is not None: # print "cancelling timer if it exists" @@ -276,41 +265,13 @@ def lut_convert16as8bit(self,image, display_min, display_max) : def updateData(self): - remcount = self.mmc.getRemainingImageCount() - #print 'remcount',remcount - #remcount=0 - if remcount > 0: - #rgb32 = self.mmc.popNextImage() - data = self.mmc.getLastImage() - - - if data.dtype == np.uint16: - maxval=self.imgSrc.get_max_pixel_value() - #print "max val is",maxval - #print 'max_before',np.max(data) - #data = exposure.rescale_intensity(data,in_range=(0,maxval)) - #print 'max after rescale',np.max(data) - #data = img_as_ubyte(data) - #data=self.lut_convert16as8bit(data,0,5000) + + data = self.imgSrc.get_image() + maxval=self.imgSrc.get_max_pixel_value() + self.img.setImage(data,autoLevels=True) - # "maxval",maxval,np.max(data),data.dtype - - flipx,flipy,trans = self.imgSrc.get_image_flip() - if trans: - data = np.transpose(data) - if flipx: - data = np.fliplr(data) - if flipy: - data = np.flipud(data) - data = np.rot90(data,k=3) - #gray=cv2.equalizeHist(gray) - self.img.setImage(data,autoLevels=True) - #cv2.imshow('Video', gray) - #else: - #print('No frame') - if not self.ended: - self.timer = QtCore.QTimer.singleShot(self.mmc.getExposure(), self.updateData) + self.timer = QtCore.QTimer.singleShot(self.imgSrc.get_exposure(), self.updateData) now = ptime.time() fps1 = 1.0 / (now-self.updateTime) self.updateTime = now @@ -318,17 +279,11 @@ def updateData(self): if self.i == 0: print "%0.1f fps" % self.fps - -#def myExitHandler(mmc): - - #mmc.stopSequenceAcquisition() - #QtGui.QApplication.quit() - #mmc.reset() -def launchLive(mmc,exposure_times): +def launchLive(imgSrc,exposure_times): import sys - vidview = VideoView(mmc,exposure_times) + vidview = VideoView(imgSrc,exposure_times) vidview.setGeometry(250,50,1100,1000) vidview.show() @@ -347,18 +302,18 @@ def launchLive(mmc,exposure_times): app = QtGui.QApplication(sys.argv) faulthandler.enable() - #mmc = MMCorePy.CMMCore() + defaultMMpath = "C:\Program Files\Micro-Manager-1.4" configFile = QtGui.QFileDialog.getOpenFileName( None, "pick a uManager cfg file", defaultMMpath, "*.cfg") configFile = str(configFile.replace("/", "\\")) print configFile imgSrc = imageSource(configFile) - #mmc.loadSystemConfiguration(configFile) + print "loaded configuration file" launchLive(imgSrc,dict([])) #app.exec_() print "got out of the event loop" - imgSrc.mmc.reset() + imgSrc.shutdown() print "reset micromanager core" sys.exit() diff --git a/MMArduino.py b/MMArduino.py index a94ec09..814434a 100644 --- a/MMArduino.py +++ b/MMArduino.py @@ -12,6 +12,11 @@ def __init__(self,port = 'COM8',baudrate = '57600'): self.ser.timeout =.5 self.ser.open() time.sleep(2) + self.ser.readlines() + self.sendCmd(chr(27)) + self.sendCmd(chr(27)) + self.sendCmd(chr(27)) + self.sendCmd(chr(27)) def sendMessage(self,message,debug=False): cmd = bytearray(message) answer = self.sendDirect(message,len(message)) @@ -88,7 +93,7 @@ def setTriggerPolarity(self,triggerHigh = True): return self.sendMessage([23,0]) else: return self.sendMessage([23,1]) - + def setupExposure(self,exposures,interframe=10,exp_pattern=[0,0,0,0,0,0,0,1]): i =0 for exp in exposures: diff --git a/MosaicPlanner.py b/MosaicPlanner.py index 1568ad0..c354a03 100644 --- a/MosaicPlanner.py +++ b/MosaicPlanner.py @@ -38,7 +38,7 @@ from MyLasso import MyLasso from MosaicImage import MosaicImage from Transform import Transform,ChangeTransform -from imageSourceMM import imageSource +from imageSourceDemo import imageSource from MMPropertyBrowser import MMPropertyBrowser from ASI_Control import ASI_AutoFocus from FocusCorrectionPlaneWindow import FocusCorrectionPlaneWindow @@ -510,7 +510,7 @@ def handle_close(self,evt=None): print "handling close" #if not self.mosaicImage == None: # self.mosaicImage.cursor_timer.cancel() - self.imgSrc.mmc.unloadAllDevices() + self.imgSrc.shutdown() def on_load(self,rootPath): self.rootPath = rootPath @@ -675,29 +675,8 @@ def ResetPiezo(self): do_stage_reset=self.cfg['StageResetSettings']['enableStageReset'] if do_stage_reset: - z_label = self.cfg['StageResetSettings']['compensationStage'] - piezo_label = self.cfg['StageResetSettings']['resetStage'] - min_threshold = self.cfg['StageResetSettings']['minThreshold'] - max_threshold = self.cfg['StageResetSettings']['maxThreshold'] - reset_position = self.cfg['StageResetSettings']['resetPosition'] - invert_compensation = self.cfg['StageResetSettings']['invertCompensation'] - - piezo = self.imgSrc.mmc.getPosition(piezo_label) - if (piezomax_threshold): - z = self.imgSrc.mmc.getPosition(z_label) - islocked = self.imgSrc.mmc.isContinuousFocusEnabled() - - if islocked: - self.imgSrc.mmc.enableContinuousFocus(False) - - if invert_compensation: - self.imgSrc.mmc.setPosition(z_label,z+(piezo-reset_position)) - else: - self.imgSrc.mmc.setPosition(z_label,z-(piezo-reset_position)) - self.imgSrc.mmc.setPosition(piezo_label,reset_position) - - if islocked: - self.imgSrc.mmc.enableContinuousFocus(True) + self.imgSrc.reset_piezo(self.cfg['StageResetSettings']) + def summarize_stage_settings(self): do_stage_reset = self.cfg['StageResetSettings']['enableStageReset'] @@ -829,7 +808,7 @@ def execute_imaging(self,pos_list,numFrames,numSections,channel_settings,chrome_ if pos.activated: if not goahead: break - if not self.imgSrc.mmc.isContinuousFocusEnabled(): + if not self.imgSrc.get_hardware_autofocus_state(): print "autofocus not enabled when moving between sections.. " goahead=False break @@ -844,7 +823,7 @@ def execute_imaging(self,pos_list,numFrames,numSections,channel_settings,chrome_ if not goahead: print "breaking out!" break - if not self.imgSrc.mmc.isContinuousFocusEnabled(): + if not self.imgSrc.get_hardware_autofocus_state(): print "autofocus no longer enabled while moving between frames.. quiting" goahead = False break @@ -966,7 +945,8 @@ def on_run_acq(self,event="none"): goahead = True - if not self.imgSrc.mmc.isContinuousFocusEnabled(): + + if not self.imgSrc.get_hardware_autofocus_state(): self.slack_notify('HELP! lost autofocus on way to first position',notify=True) print 'HELP! lost autofocus on way to first position' goahead=False @@ -979,7 +959,7 @@ def on_run_acq(self,event="none"): if pos.activated: if not goahead: break - if not self.imgSrc.mmc.isContinuousFocusEnabled(): + if not self.imgSrc.get_hardware_autofocus_state(): self.slack_notify('HELP! lost autofocus between sections',notify=True) goahead=False break @@ -999,7 +979,7 @@ def on_run_acq(self,event="none"): if not goahead: print "breaking out!" break - if not self.imgSrc.mmc.isContinuousFocusEnabled(): + if not self.imgSrc.get_hardware_autofocus_state(): self.slack_notify('HELP! lost autofocus between frames',notify=True) print "autofocus no longer enabled while moving between frames.. quiting" goahead = False @@ -1132,6 +1112,10 @@ def launch_MManager_browser(self, event=None): win = MMPropertyBrowser(self.imgSrc.mmc) win.show() + def launch_retake(self,event=None): + if self.retakeView is NOne: + self.retakeView = Retake(self) + def launch_snap(self, event=None): if self.snapView is None: self.imgSrc.set_binning(1) @@ -1663,7 +1647,7 @@ def on_run_multi_acq(self,event="none"): #MultiRibbons if pos.activated: if not goahead: break - if not self.imgSrc.mmc.isContinuousFocusEnabled(): + if not self.imgSrc.get_hardware_autofocus_state(): self.slack_notify('HELP! lost autofocus between frames',notify=True) print "autofocus not enabled when moving between sections.. " goahead=False @@ -1682,7 +1666,7 @@ def on_run_multi_acq(self,event="none"): #MultiRibbons if not goahead: print "breaking out!" break - if not self.imgSrc.mmc.isContinuousFocusEnabled(): + if not self.imgSrc.get_hardware_autofocus_state(): self.slack_notify('HELP! lost autofocus between frames',notify=True) print "autofocus no longer enabled while moving between frames.. quiting" goahead = False diff --git a/PositionList.py b/PositionList.py index 243905f..88a228a 100644 --- a/PositionList.py +++ b/PositionList.py @@ -53,7 +53,7 @@ class posListSchema(mm.Schema): camera_settings = mm.Nested(CameraSettingsSchema,required=True) slicePositions = mm.List(slicePositionSchema) dosort = mm.fields.Bool(required=False,default=True) - numberDisplaySettings = mm.Nested(NumberDisplaySettings) + numberDisplaySettings = mm.Nested(NumberDisplaySettingsSchema) class posList(): """class for holding, altering, and plotting the position list""" @@ -968,7 +968,7 @@ class slicePositionSchema(mm.Schema): activated = mm.fields.Bool(required=False,default=True) withpoint = mm.fields.Bool(required=False,default=True) number = mm.fields.Int(required=True) - numberDisplaySettings = mm.Nested(NumberDisplaySettings) + numberDisplaySettings = mm.Nested(NumberDisplaySettingsSchema) self.frameList = mm.Nested(posListSchema) diff --git a/QSettings.py b/QSettings.py index 794edce..c4808ce 100644 --- a/QSettings.py +++ b/QSettings.py @@ -1,6 +1,6 @@ from PyQt4 import QtCore, QtGui, uic import os -import MMCorePy + class StageResetSettings: @@ -235,14 +235,9 @@ def GetSettings(self): if __name__ == '__main__': import sys + import MMCorePy app = QtGui.QApplication(sys.argv) - defaultMMpath = "C:\Users\Administrator\Documents" - configFile = QtGui.QFileDialog.getOpenFileName( - None, "pick a uManager cfg file", defaultMMpath, "*.cfg") - configFile = str(configFile.replace("/", "\\")) - mmc = MMCorePy.CMMCore() - mmc.loadSystemConfiguration(configFile) print "loaded configuration file" #settings = StageResetSettings() #resetSettings=ChangeStageResetSettings(mmc,settings) @@ -261,6 +256,5 @@ def GetSettings(self): app.exec_() settings=resetSettings.getSettings() print(settings) - mmc.reset() - print "reset micromanager core" + sys.exit() \ No newline at end of file diff --git a/Settings.py b/Settings.py index 484d20d..e099f6b 100644 --- a/Settings.py +++ b/Settings.py @@ -432,7 +432,7 @@ class CameraSettingsSchema(mm.Schema): sensor_widht = mm.fields.Int(required=True) pix_width = mm.fields.Float(required=True) pix_height = mm.fields.Float(required=True) - + class CameraSettings(): """simple struct for containing the parameters for the camera""" def __init__(self,sensor_height=1040,sensor_width=1388,pix_width=6.5,pix_height=6.5): @@ -442,6 +442,13 @@ def __init__(self,sensor_height=1040,sensor_width=1388,pix_width=6.5,pix_height= #in microns self.pix_width=pix_width self.pix_height=pix_height + def to_dict(self): + d={'sensor_height':self.sensor_height, + 'sensor_width':self.sensor_width, + 'pix_width':,self.pix_width, + 'pix_height':self.pix_height + } + def save_settings(self,cfg): cfg['Camera_Settings']['sensor_height']=self.sensor_height cfg['Camera_Settings']['sensor_width']=self.sensor_width diff --git a/SetupAlerts.py b/SetupAlerts.py index ebc2dbe..f9ef58f 100644 --- a/SetupAlerts.py +++ b/SetupAlerts.py @@ -85,7 +85,6 @@ def launchDialog(settings): faulthandler.enable() cfg = ConfigObj(SETTINGS_FILE,unrepr=True) - #mmc = MMCorePy.CMMCore() #defaultMMpath = "C:\Program Files\Micro-Manager-1.4" #configFile = QtGui.QFileDialog.getOpenFileName( # None, "pick a uManager cfg file", defaultMMpath, "*.cfg") diff --git a/Snap.py b/Snap.py index 8fa59b2..422064a 100644 --- a/Snap.py +++ b/Snap.py @@ -23,31 +23,16 @@ def __init__(self,imgSrc,exposure_times=dict([]),channelGroup="Channels"): self.exposure_times=exposure_times #self.setContentsMargins(0,0,0,0) self.imgSrc = imgSrc - self.mmc = imgSrc.mmc - self.camera = self.mmc.getCameraDevice() - # self.mmc.setProperty(self.camera,'Binning','1x1') - # self.mmc.waitForDevice(self.camera) - self.channels=self.mmc.getAvailableConfigs(self.channelGroup) - #self.init_mmc() + + self.channels=self.imgSrc.get_channels() self.initUI() self.i = 0 self.ended = False - - # def init_mmc(self): - # #filename="C:\Users\Smithlab\Documents\ASI_LUM_RETIGA_CRISP.cfg" - # #self.mmc.loadSystemConfiguration(filename) - # #self.mmc.enableStderrLog(False) - # #self.mmc.enableDebugLog(False) - # # # mmc.setCircularBufferMemoryFootprint(100) - # #self.cam=self.mmc.getCameraDevice() - # #self.mmc.setExposure(50) - # #self.mmc.setProperty(self.cam, 'Gain', 1) - # Nch=len(self.channels) - # startChan=self.channels[Nch-1] + def initUI(self): @@ -74,23 +59,10 @@ def initUI(self): self.graphicsLayoutWidget.addItem(self.hist,0,1) - - - - #self.layout.addWidget(self.img) - - #self.setLayout(self.layout) - #self.setAutoFillBackground(True) - #p = self.palette() - #p.setColor(self.backgroundRole(), QtCore.Qt.black) - #self.setPalette(p) - keys = self.exposure_times.keys() - #gridlay=QtGui.QGridLayout(margin=0,spacing=-1) - # print 'Binning is:', self.mmc.getProperty(self.camera,'Binning') for i,ch in enumerate(self.channels): btn=QtGui.QPushButton(ch,self) self.chnButtons.append(btn) @@ -103,7 +75,7 @@ def initUI(self): if ch in keys: spnBox.setValue(self.exposure_times[ch]) else: - spnBox.setValue(self.mmc.getExposure()) + spnBox.setValue(self.imgSrc.get_exposure()) spnBox.setSuffix(" ms") btn.clicked.connect(self.make_channelButtonClicked(ch,spnBox)) self.expSpnBoxes.append(spnBox) @@ -157,41 +129,35 @@ def snapExposure(self,evt): for i,ch in enumerate(self.channels): if 'Dark' not in ch: print ch - self.mmc.setConfig(self.channelGroup,ch) - self.mmc.waitForConfig(self.channelGroup,ch) + self.imgSrc.set_channel(ch) spnBox=self.expSpnBoxes[i] curr_exposure=spnBox.value() - self.mmc.setExposure(curr_exposure) - self.mmc.snapImage() - img=self.mmc.getImage() - if data is None: - data = np.zeros((Nch,img.shape[0],img.shape[1])) + self.imgSrc.set_exposure(curr_exposure) + img=self.imgSrc.snap_image() data[i,:,:]=img print(np.max(img)) self.img.setImage(data,xvals = np.array(range(Nch))) - self.img.setLevels(0,2**self.mmc.getImageBitDepth()) - self.hist.setLevels(0,2**self.mmc.getImageBitDepth()) + self.img.setLevels(0,self.imgSrc.get_max_pixel_value()) + self.hist.setLevels(0,self.imgSrc.get_max_pixel_value()) # def autoExposure(self,evt): # - # self.mmc.stopSequenceAcquisition() + # self.imgSrc.stopSequenceAcquisition() # # perc=95; #the goal is to make the X percentile value equal to Y percent of the maximum value # #perc is X # desired_frac=.7 #desired_frac is Y # max_exposure = 3000 #exposure times shall not end up more than this # close_frac = .2 #fractional change in exposure for which we will just trust the math - # bit_depth=self.mmc.getImageBitDepth() - # max_val=np.power(2,bit_depth) + # max_val=self.imgSrc.get_max_pixel_value() # #loop over the channels # for i,ch in enumerate(self.channels): # img_counter =0 #counter to count how many snaps it takes us # if 'Dark' not in ch: #don't set the 'Dark' channel for obvious reasons # print ch # #setup to use the channel - # self.mmc.setConfig(self.channelGroup,ch) - # self.mmc.waitForConfig(self.channelGroup,ch) - # + # self.imgSrc.set_channel(ch) + # # #get current exposure # spnBox=self.expSpnBoxes[i] @@ -201,10 +167,10 @@ def snapExposure(self,evt): # #follow loop till we get it right # while 1: # - # self.mmc.setExposure(curr_exposure) - # self.mmc.snapImage() + # self.imgSrc.set_exposure(curr_exposure) + # img= self.imgSrc.snap_image() # img_counter+=1 - # img=self.mmc.getImage() + # # vec=img.flatten() # # #the value which is at the perc percentile @@ -264,23 +230,16 @@ def channelButtonClicked(): #print ch #print spnBox.value() - # self.mmc.stopSequenceAcquisition() - # self.mmc.clearCircularBuffer() - self.mmc.setConfig(self.channelGroup,ch) + self.imgSrc.set_channel(ch) expTime=spnBox.value() - self.mmc.setExposure(expTime) - self.mmc.waitForConfig(self.channelGroup,ch) - self.mmc.snapImage() - data= self.mmc.getImage() + self.imgSrc.set_exposure(expTime) + data=self.imgSrc.snap_image() self.img.setImage(data) - # self.mmc.startContinuousSequenceAcquisition(expTime) return channelButtonClicked def closeEvent(self,evt): - # camera = self.mmc.getCameraDevice() - self.mmc.setProperty(self.camera,'Binning','2x2') - print 'Binning is:', self.mmc.getProperty(self.camera,'Binning') - self.changedExposureTimes.emit() + self.imgSrc.set_binning(2) + print 'Binning is:', self.imgSrc.get_binning() return QtGui.QWidget.closeEvent(self,evt) #evt.accept() @@ -292,8 +251,6 @@ def launchSnap(imgSrc,exposure_times): #vidview.setGeometry(250,50,1100,1000) dlg.setModal(True) dlg.show() - - if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): QtGui.QApplication.instance().exec_() @@ -313,7 +270,6 @@ def launchSnap(imgSrc,exposure_times): faulthandler.enable() cfg = ConfigObj(SETTINGS_FILE,unrepr=True) - #mmc = MMCorePy.CMMCore() #defaultMMpath = "C:\Program Files\Micro-Manager-1.4" #configFile = QtGui.QFileDialog.getOpenFileName( # None, "pick a uManager cfg file", defaultMMpath, "*.cfg") @@ -324,13 +280,12 @@ def launchSnap(imgSrc,exposure_times): logname=dt.strftime('SnapLog_%Y%m%d_%H%M.txt') imgSrc = imageSource(configFile,logfile=logname) - #mmc.loadSystemConfiguration(configFile) print "loaded configuration file" imgSrc.set_binning(1) launchSnap(imgSrc,dict([])) #app.exec_() print "got out of the event loop" - imgSrc.mmc.reset() + imgSrc.shutdown() print "reset micromanager core" sys.exit() diff --git a/imageSourceDemo.py b/imageSourceDemo.py new file mode 100644 index 0000000..ab7325f --- /dev/null +++ b/imageSourceDemo.py @@ -0,0 +1,358 @@ +import numpy as np +import time +from Rectangle import Rectangle +import wx + +class imageSource(): + + def __init__(self,configFile,channelGroupName='Channels', + use_focus_plane = False, focus_points=None, + transpose_xy = False, logfile='MP_MM.txt', + MasterArduinoPort = None, interframe_time= 10, filtswitch = None): + #NEED TO IMPLEMENT IF NOT MICROMANAGER + + self.x = 0 + self.y = 0 + self.z = 0 + self.binning = 1 + self.exposure = 100 + self.hardware_autofocus_state = True + self.channels = [] + self.exposure_times = [] + self.offset = 0 + + def define_focal_plane(self,points): + if points.shape[1]>3: + self.plane_tuple = self.planeFit(points) + + def get_focal_z(self,x,y): + if self.plane_tuple is not None: + ax,ay,b = self.plane_tuple + return ax*x + ay*y + b + else: + return self.get_z() + + def planeFit(self,points): + """ + p, n = planeFit(points) + + Fit an n-dimensional plane to the points. + Return a point on the plane and the normal. + """ + from numpy.linalg import svd + points = np.reshape(points, (points.shape[0], -1)) + assert points.shape[0] < points.shape[1] + ctr = points.mean(axis=1) + x = points - ctr[:,None] + M = np.dot(x, x.T) + pt_on_plane = ctr + norm = svd(M)[0][:,-1] + d=norm[0]*pt_on_plane[0]+norm[1]*pt_on_plane[1]+norm[2]*pt_on_plane[2] + ax=-norm[0]/norm[2] + ay=-norm[1]/norm[2] + b = -d/norm[2] + return ax,ay,b + + def reset_piezo(self,cfg): + pass + + def stop_hardware_triggering(self): + pass + + def setup_hardware_triggering(self,channels,exposure_times): + self.channels = channels + self.exposure_times = exposure_times + + def startHardwareSequence(self): + pass + + def set_binning(self,bin=1): + self.binning = bin + + def get_binning(self): + return self.binning + + def image_based_autofocus(self,chan=None): + return 0.0 + + def get_max_pixel_value(self): + return np.power(2,16)-1 + + def get_exposure(self): + return self.exposure + + def set_exposure(self,exp_msec): + self.exposure = exp_msec + + def reset_focus_offset(self): + pass + + def get_hardware_autofocus_state(self): + return self.hardware_autofocus_state + + def set_hardware_autofocus_state(self,state): + self.hardware_autofocus_state = state + + def has_hardware_autofocus(self): + #NEED TO IMPLEMENT IF NOT MICROMANAGER + return True + + def stopSequenceAcquisition(self): + pass + + def startContinuousSequenceAcquisition(self,val): + pass + + def is_hardware_autofocus_done(self): + return self.hardware_autofocus_state + + + def take_hardware_snap(self): + images = [] + for ch in self.channels: + images.append(np.random(self.get_sensor_size())) + return images + + + def take_image(self,x,y): + #do not need to re-implement + #moves scope to x,y - focus scope - snap picture + #using the configured exposure time + + #print "is continuous focus enabled",self.mmc.isContinuousFocusEnabled() + #print "is continuous focus locked",self.mmc.isContinuousFocusLocked() + + if not self.get_hardware_autofocus_state(): + print 'autofocus not enabled' + wx.MessageBox('autofocus not enabled, Help me',) + return + + + #move stage to x,y + self.set_xy(x,y) + if self.use_focus_plane: + z = self.get_focal_z(x,y) + self.set_z(z) + else: + if not self.has_hardware_autofocus(): + self.image_based_autofocus() + else: + #make sure hardware autofocus worked + attempts=0 + failure=False + while not self.is_hardware_autofocus_done(): + attempts+=1 + time.sleep(.1) + if attempts>100: + failure=True + print("focus score is ",0.0,'breaking out') + break + print "not autofocusing correctly.. giving up after 10 seconds" + if failure: + return None + + #get the image data + data=self.snap_image() + + #check whether it is in focus + #if not self.meets_focus_spec(data): + #if not, attempt image based autofocus + #self.image_based_autofocus() + #data=self.snap_image() + + #check whether it is in focus + #if not self.meets_focus_spec(data): + #if not take a small stack around current point + #and return most in focus image of that + #data=self.take_best_of_stack() + + #calculate bounding box for data + bbox=self.calc_bbox(x,y) + + print "todo get some real metadata" + metadata=None + return data,bbox + def set_xy(self,x,y,use_focus_plane=False): + flipx,flipy = self.get_xy_flip() + + if use_focus_plane: + z = self.get_focal_z(x,y) + self.set_z(z) + if self.transpose_xy: + xt = x + x = y + y = xt + #if flipx==1: + # x = -x + #if flipy == 1: + # y = -y + + self.x = x + self.y = y + #print self.get_xy() + + + + def get_xy_flip(self): + xystg=self.mmc.getXYStageDevice() + flipx=int(self.mmc.getProperty(xystg,"TransposeMirrorX"))==1 + flipy=int(self.mmc.getProperty(xystg,"TransposeMirrorY"))==1 + + return False,False + def get_xy(self): + #NEED TO IMPLEMENT IF NOT MICROMANAGER + xystg=self.mmc.getXYStageDevice() + + flipx,flipy = self.get_xy_flip() + + x=self.x + y=self.y + + if self.transpose_xy: + xt = x + x = y + y = xt + + #if flipx: + # x = -x + #if flipy: + # y = -y + + return (x,y) + def get_z(self): + return self.z + def set_z(self,z): + self.z = z + + def get_pixel_size(self): + #NEED TO IMPLEMENT IF NOT MICROMANAGER + return 6.5 + + def make_random_image(self): + return np.random(self.get_sensor_size()) + def get_image(self): + return self.make_random_image() + + def get_frame_size_um(self): + (sensor_width,sensor_height)=(self.get_sensor_size()) + pixsize = self.get_pixel_size() + flipx,flipy,trans = self.get_image_flip() + if trans: + temp = sensor_width + sensor_width = sensor_height + sensor_height = temp + + return (sensor_width*pixsize,sensor_height*pixsize) + + + def calc_bbox(self,x,y): + #do not need to implement + (fw,fh)=self.get_frame_size_um() + + #we are going to follow the convention of upper left being 0,0 + #and lower right being X,X where X is positive + left = x - fw/2; + right = x + fw/2; + + top = y - fh/2; + bottom = y + fh/2; + print "fw,fh",fw,fh + + return Rectangle(left,right,top,bottom) + + #@retry(tries= 5) + def snap_image(self): + data = self.make_random_image() + data = self.flip_image(data) + return data + + + def flip_image(self,data): + + (flipx,flipy,trans) = self.get_image_flip() + if trans: + data = np.transpose(data) + if flipx: + data=np.fliplr(data) + if flipy: + data=np.flipud(data) + return data + + + + def get_sensor_size(self): + #return the height and width in pixels + return (2048,2048) + + def move_stage(self,x,y): + #need to implement if not MICROMANAGER + #move the stage to position x,y + + self.set_xy(x,y) + + + def set_channel(self,channel): + self.channel = channel + + def get_channels(self): + return ['DAPI','ALEXA488','ALEXA594','ALEXA647'] + + def take_best_of_stack(self): + print "need to implement take best of stack" + return self.snap_image() + def meets_focus_spec(data): + print "need to implement focus spec check" + return True + def get_image_flip(self): + return (False,False,True) + + def move_safe_and_focus(self,x,y): #MultiRibbons + #lower objective, move the stage to position x,y + focus_stage=self.mmc.getFocusDevice() + #self.mmc.setRelativePosition(focus_stage,-3000.0) + for j in range(300): #use small z steps to lower objective slowly + self.z -= 10 + time.sleep(0.2) + + time.sleep(1) + self.set_xy_new(x,y) + time.sleep(40) + + #self.mmc.setRelativePosition(focus_stage,2700.0) + for j in range(310): #use small z steps to raise objective slowly + self.z += 10 + time.sleep(0.2) + self.z -= 200 + i = 0 + for i in range(5): + self.z += 20 + time.sleep(1) + self.set_hardware_autofocus_state(True) + + def set_xy_new(self,x,y,use_focus_plane=False): #MultiRibbons + # modified version of set_xy to be called by move_safe_and_focus with removed self.mmc.waitForDevice(stg) + # to avoid error when waiting time exceeds 5s + flipx,flipy = self.get_xy_flip() + + if use_focus_plane: + z = self.get_focal_z(x,y) + self.set_z(z) + if self.transpose_xy: + xt = x + x = y + y = xt + #if flipx==1: + # x = -x + #if flipy == 1: + # y = -y + + self.set_xy(x,y) + + def set_autofocus_offset(self,offset): #MultiRibbons + self.offset = offset + + def get_autofocus_offset(self): #MultiRibbons + return self.offset + + def shutdown(self): + pass \ No newline at end of file diff --git a/imageSourceMM.py b/imageSourceMM.py index 3c5c6f2..f21c481 100644 --- a/imageSourceMM.py +++ b/imageSourceMM.py @@ -72,6 +72,34 @@ def __init__(self,configFile,channelGroupName='Channels', self.mmc.setConfig('Triggering','Software') #set the exposure to use + def reset_piezo(self,cfg): + + do_stage_reset=cfg['enableStageReset'] + if do_stage_reset: + z_label = cfg['compensationStage'] + piezo_label = cfg['resetStage'] + min_threshold = cfg['minThreshold'] + max_threshold = cfg['maxThreshold'] + reset_position = cfg['resetPosition'] + invert_compensation = cfg['invertCompensation'] + + piezo = self.mmc.getPosition(piezo_label) + if (piezomax_threshold): + z = self.mmc.getPosition(z_label) + islocked = self.mmc.isContinuousFocusEnabled() + + if islocked: + self.mmc.enableContinuousFocus(False) + + if invert_compensation: + self.mmc.setPosition(z_label,z+(piezo-reset_position)) + else: + self.mmc.setPosition(z_label,z-(piezo-reset_position)) + self.mmc.setPosition(piezo_label,reset_position) + + if islocked: + self.mmc.enableContinuousFocus(True) + def define_focal_plane(self,points): if points.shape[1]>3: self.plane_tuple = self.planeFit(points) @@ -154,6 +182,13 @@ def setup_hardware_triggering(self,channels,exposure_times): self.numberHardwareChannels = len(exposure_times) self.mmc.startContinuousSequenceAcquisition(0) + def stopSequenceAcquisition(self): + self.mmc.stopSequenceAcquisition() + self.mmc.clearCircularBuffer() + + def startContinuousSequenceAcquisition(self,val): + self.mmc.startContinuousSequenceAcquisition(val) + def startHardwareSequence(self): assert(self.masterArduino is not None) self.masterArduino.startTimedPattern() @@ -186,6 +221,7 @@ def set_exposure(self,exp_msec): #NEED TO IMPLEMENT IF NOT MICROMANAGER self.mmc.setExposure(exp_msec) + def reset_focus_offset(self): if self.has_hardware_autofocus(): focusDevice=self.mmc.getAutoFocusDevice() @@ -193,7 +229,7 @@ def reset_focus_offset(self): def get_hardware_autofocus_state(self): if self.has_hardware_autofocus(): - return self.mmc.isContinuousFocusLocked() + return self.mmc.isContinuousFocusEnabled() def set_hardware_autofocus_state(self,state): if self.has_hardware_autofocus(): @@ -525,4 +561,7 @@ def set_autofocus_offset(self,offset): #MultiRibbons def get_autofocus_offset(self): #MultiRibbons if self.has_hardware_autofocus(): - return self.mmc.getAutoFocusOffset() \ No newline at end of file + return self.mmc.getAutoFocusOffset() + + def shutdown(self): + self.mmc.unloadAllDevices() \ No newline at end of file