Skip to content

Commit

Permalink
Merge branch 'master' into feature_hypha
Browse files Browse the repository at this point in the history
  • Loading branch information
beniroquai committed Jul 4, 2023
2 parents d38c4bc + a2a5dca commit 974d925
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 158 deletions.
130 changes: 5 additions & 125 deletions imswitch/imcontrol/controller/controllers/FocusLockController.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,15 @@ def __init__(self, *args, **kwargs):
return

self.camera = self._setupInfo.focusLock.camera
if self.camera == "ESP32":
self.isESP32 = True
else:
self.isESP32 = False
self.positioner = self._setupInfo.focusLock.positioner
self.updateFreq = self._setupInfo.focusLock.updateFreq
self.cropFrame = (self._setupInfo.focusLock.frameCropx,
self._setupInfo.focusLock.frameCropy,
self._setupInfo.focusLock.frameCropw,
self._setupInfo.focusLock.frameCroph)

if self.isESP32:
# Create an instance of the ESP32CameraThread class
self.ESP32Camera = ESP32CameraThread('Espressif')

# Start the thread
self.ESP32Camera.startStreaming()
else:
self._master.detectorsManager[self.camera].crop(*self.cropFrame)
self._master.detectorsManager[self.camera].crop(*self.cropFrame)
self._widget.setKp(self._setupInfo.focusLock.piKp)
self._widget.setKi(self._setupInfo.focusLock.piKi)

Expand Down Expand Up @@ -89,7 +79,7 @@ def __init__(self, *args, **kwargs):
self.setPointData = np.zeros(self.buffer)
self.timeData = np.zeros(self.buffer)

if not self.isESP32: self._master.detectorsManager[self.camera].startAcquisition()
self._master.detectorsManager[self.camera].startAcquisition()
self.__processDataThread = ProcessDataThread(self)
self.__focusCalibThread = FocusCalibThread(self)

Expand Down Expand Up @@ -234,16 +224,8 @@ def __init__(self, controller, *args, **kwargs):


def grabCameraFrame(self):
if not self._controller.isESP32:
detectorManager = self._controller._master.detectorsManager[self._controller.camera]
self.latestimg = detectorManager.getLatestFrame()
else:
try:
self.latestimg = self._controller.ESP32Camera.grabLatestFrame()
except:
self.latestimg = np.zeros((self._controller.ESP32Camera.Ny,self._controller.ESP32Camera.Nx))


detectorManager = self._controller._master.detectorsManager[self._controller.camera]
self.latestimg = detectorManager.getLatestFrame()

# 1.5 swap axes of frame (depending on setup, make this a variable in the json)
if self._controller._setupInfo.focusLock.swapImageAxes:
Expand All @@ -252,7 +234,7 @@ def grabCameraFrame(self):

def update(self, twoFociVar):

if self._controller.isESP32:
if self._controller._master.detectorsManager[self._controller.camera].model == "ESP32SerialCamera":
imagearraygf = ndi.filters.gaussian_filter(self.latestimg, 5)
# mBackground = np.mean(mStack, (0)) #np.ones(mStack.shape[1:])#
mBackground = ndi.filters.gaussian_filter(self.latestimg,15)
Expand Down Expand Up @@ -407,108 +389,6 @@ def ki(self, value):



class ESP32CameraThread(object):
# attention a threading class won't work in windows!!! #FIXME:
def __init__(self, manufacturer):
self.manufacturer = manufacturer
self.serialdevice = None
self.Nx, self.Ny = 320,240
self.frame = np.zeros((self.Ny,self.Nx))

# string to send data to camera
self.newCommand = ""
self.exposureTime = -1
self.gain = -1

def setExposureTime(self, exposureTime):
self.newCommand = "t"+str(exposureTime)
self.exposureTime = exposureTime

def setGain(self, gain):
self.newCommand = "g"+str(gain)
self.gain = gain

def connect_to_usb_device(self):
ports = serial.tools.list_ports.comports()
for port in ports:
if port.manufacturer == self.manufacturer or port.manufacturer=="Microsoft":
try:
ser = serial.Serial(port.device, baudrate=2000000, timeout=1)
ser.write_timeout=.5
print(f"Connected to device: {port.description}")
return ser
except serial.SerialException:
print(f"Failed to connect to device: {port.description}")
print("No matching USB device found.")
return None

def startStreaming(self):
self.isRunning = True
self.mThread = threading.Thread(target=self.startStreamingThread)
self.mThread.start()

def stopStreaming(self):
self.isRunning = False
self.mThread.join()
try:self.serialdevice.close()
except:pass

def startStreamingThread(self):
self.serialdevice = self.connect_to_usb_device()
nFrame = 0
nTrial = 0
while self.isRunning:
try:

# send new comamand to change camera settings, reset command
if not self.newCommand == "":
self.serialdevice.write((self.newCommand+' \n').encode())
self.newCommand = ""

# request new image
self.serialdevice.write((' \n').encode())

# don't read to early
time.sleep(.05)
# readline of camera
imageB64 = self.serialdevice.readline()

# decode byte stream
image = np.array(Image.open(io.BytesIO(base64.b64decode(imageB64.decode()))))
self.frame = np.mean(image,-1)

nFrame += 1

except Exception as e:
# try to reconnect
#print(e) # most of the time "incorrect padding of the bytes "
nFrame = 0
nTrial+=1
try:
self.serialdevice.flushInput()
self.serialdevice.flushOutput()
except:
pass
if nTrial > 10 and type(e)==serial.serialutil.SerialException:
try:
# close the device - similar to hard reset
self.serialdevice.setDTR(False)
self.serialdevice.setRTS(True)
time.sleep(.1)
self.serialdevice.setDTR(False)
self.serialdevice.setRTS(False)
time.sleep(.5)
#self.serialdevice.close()
except: pass
self.serialdevice = self.connect_to_usb_device()
nTrial = 0


def grabLatestFrame(self):
return self.frame




# Copyright (C) 2020-2021 ImSwitch developers
# This file is part of ImSwitch.
Expand Down
10 changes: 5 additions & 5 deletions imswitch/imcontrol/controller/controllers/MCTController.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ def takeTimelapseThread(self, tperiod = 1):
self.stages.setSpeed(speed=1000, axis="Z")

# ensure motors are enabled
self.stages.enalbeMotors(enable=True)
#self.stages.enalbeMotors(enable=True)

try:
# want to do autofocus?
Expand Down Expand Up @@ -413,10 +413,10 @@ def acquireScan(self, timestamp=0):

# in case something is not connected we want to reconnect!
# TODO: This should go into some function outside the MCT!!!
if not ("IDENTIFIER_NAME" in self._master.UC2ConfigManager.ESP32.state.get_state() and self._master.UC2ConfigManager.ESP32.state.get_state()["IDENTIFIER_NAME"] == "uc2-esp"):
mThread = threading.Thread(target=self._master.UC2ConfigManager.initSerial)
mThread.start()
mThread.join()
#if not ("IDENTIFIER_NAME" in self._master.UC2ConfigManager.ESP32.state.get_state() and self._master.UC2ConfigManager.ESP32.state.get_state()["IDENTIFIER_NAME"] == "uc2-esp"):
# mThread = threading.Thread(target=self._master.UC2ConfigManager.initSerial)
# mThread.start()
# mThread.join()

# initialize xyz coordinates
if self.xyScanEnabled:
Expand Down
12 changes: 9 additions & 3 deletions imswitch/imcontrol/model/interfaces/CameraESP32CamSerial.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def __init__(self):
self.model = "ESP32Camera"
self.shape = (0, 0)

self.isConnected = False

# camera parameters
self.framesize = 100
self.exposure_time = 0
Expand All @@ -25,15 +27,17 @@ def __init__(self):
self.SensorHeight = 240

self.manufacturer = 'Espressif'
self.serialdevice = None
self.frame = np.zeros((self.SensorHeight,self.SensorWidth))

self.frame = np.ones((self.SensorHeight,self.SensorWidth))
self.isRunning = False

# string to send data to camera
self.newCommand = ""
self.exposureTime = -1
self.gain = -1

self.serialdevice = self.connect_to_usb_device()

def connect_to_usb_device(self):
ports = serial.tools.list_ports.comports()
for port in ports:
Expand Down Expand Up @@ -107,7 +111,9 @@ def getLast(self):
return self.frame

def startStreamingThread(self):
self.serialdevice = self.connect_to_usb_device()
# if we have never connected anything we should return and not always try to reconnecnt
if self.serialdevice is None:
return
nFrame = 0
nTrial = 0
while self.isRunning:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def getParameter(self, name):


def getChunk(self):
pass
return np.expand_dims(self._camera.getLastChunk(),0)

def flushBuffers(self):
pass
Expand Down
37 changes: 13 additions & 24 deletions imswitch/imcontrol/model/managers/positioners/ESP32StageManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import time
import numpy as np
from imswitch.imcommon.model import APIExport, generateAPI, initLogger

import threading


PHYS_FACTOR = 1
gTIMEOUT = 100
class ESP32StageManager(PositionerManager):
Expand Down Expand Up @@ -218,35 +220,23 @@ def move(self, value=0, axis="X", is_absolute=False, is_blocking=True, accelerat

if axis == 'X':
self._motor.move_x(value, speed, acceleration=acceleration, is_absolute=is_absolute, is_enabled=isEnable, is_blocking=is_blocking, timeout=timeout)
if not is_absolute: self._position[axis] = self._position[axis] + value
else: self._position[axis] = value
elif axis == 'Y':
self._motor.move_y(value, speed, acceleration=acceleration, is_absolute=is_absolute, is_enabled=isEnable, is_blocking=is_blocking, timeout=timeout)
if not is_absolute: self._position[axis] = self._position[axis] + value
else: self._position[axis] = value
elif axis == 'Z':
self._motor.move_z(value, speed, acceleration=acceleration, is_absolute=is_absolute, is_enabled=isEnable, is_blocking=is_blocking, timeout=timeout)
if not is_absolute: self._position[axis] = self._position[axis] + value
else: self._position[axis] = value
elif axis == 'T':
self._motor.move_t(value, speed, acceleration=acceleration, is_absolute=is_absolute, is_enabled=isEnable, is_blocking=is_blocking, timeout=timeout)
if not is_absolute: self._position[axis] = self._position[axis] + value
else: self._position[axis] = value
elif axis == 'XY':
self._motor.move_xy(value, speed, acceleration=acceleration, is_absolute=is_absolute, is_enabled=isEnable, is_blocking=is_blocking, timeout=timeout)
for i, iaxis in enumerate(("X", "Y")):
if not is_absolute:
self._position[iaxis] = self._position[iaxis] + value[i]
else:
self._position[iaxis] = value[i]
elif axis == 'XYZ':
self._motor.move_xyz(value, speed, acceleration=acceleration, is_absolute=is_absolute, is_enabled=isEnable, is_blocking=is_blocking, timeout=timeout)
for i, iaxis in enumerate(("X", "Y")):
if not is_absolute: self._position[iaxis] = self._position[iaxis] + value[i]
else: self._position[iaxis] = value[i]
else:
print('Wrong axis, has to be "X" "Y" or "Z".')

# finally update positions
threading.Thread(target=self.getPosition).start()


def measure(self, sensorID=0, NAvg=100):
return self._motor.read_sensor(sensorID=sensorID, NAvg=NAvg)

Expand All @@ -271,23 +261,24 @@ def setSpeed(self, speed, axis=None):
self._speed[axis] = speed

def setPosition(self, value, axis):
# if value: value += 1 # TODO: Firmware weirdness
# self._motor.set_position(axis=axis, position=value) # TODO: this line does nothing
# self._motor.set_motor_currentPosition(axis=axis, currentPosition=value) # axis, currentPosition
# print(f"setPosition - Axis: {axis} -> New Value: {value}")
self._position[axis] = value

def closeEvent(self):
pass

def getPosition(self):
# load position from device
# t,x,y,z
try:
time.sleep(0.5)
allPositions = self._motor.get_position()
except:
allPositions = [0,0,0,0]

return {"X": allPositions[1], "Y": allPositions[2], "Z": allPositions[3], "T": allPositions[0]}
allPositionsDict={"X": allPositions[1], "Y": allPositions[2], "Z": allPositions[3], "T": allPositions[0]}
for iPosAxis, iPosVal in allPositionsDict.items():
self.setPosition(iPosVal,iPosAxis)
return allPositionsDict

def forceStop(self, axis):
if axis=="X":
Expand Down Expand Up @@ -330,12 +321,10 @@ def doHome(self, axis, isBlocking=False):
def home_x(self, isBlocking):
self._homeModule.home_x(speed=self.homeSpeedX, direction=self.homeDirectionX, isBlocking=isBlocking)
self.setPosition(axis="X", value=0)
# self._position["X"] = 0

def home_y(self,isBlocking):
self._homeModule.home_y(speed=self.homeSpeedY, direction=self.homeDirectionY, isBlocking=isBlocking)
self.setPosition(axis="Y", value=0)
# self._position["Y"] = 0

def home_z(self,isBlocking):
self._homeModule.home_z(speed=self.homeSpeedZ, direction=self.homeDirectionZ, isBlocking=isBlocking)
Expand Down

0 comments on commit 974d925

Please sign in to comment.