diff --git a/imswitch/imcontrol/controller/controllers/HyphaController.py b/imswitch/imcontrol/controller/controllers/HyphaController.py index a099f51ba..febee379f 100644 --- a/imswitch/imcontrol/controller/controllers/HyphaController.py +++ b/imswitch/imcontrol/controller/controllers/HyphaController.py @@ -132,7 +132,7 @@ def on_ended(): print(f"Track {track.kind} ended") - def laserActivate(self, laserId=0, value=0): + def setLaserActive(self, laserId=0, value=0): """ Activates or deactivates a laser by setting its enabled state. @@ -155,7 +155,7 @@ def laserActivate(self, laserId=0, value=0): """ self.lasers[laserId].setEnabled(value) - def laserValue(self, laserId=0, value=0): + def setLaserValue(self, laserId=0, value=0): """ Sets the value of a laser. @@ -178,7 +178,7 @@ def laserValue(self, laserId=0, value=0): """ self.lasers[laserId].setValue(value) - def ledValue(self, ledId=0, value=0): + def setLEDValue(self, ledId=0, value=0): """ Sets the value of an LED in an LED matrix. @@ -200,7 +200,7 @@ def ledValue(self, ledId=0, value=0): """ self.ledMatrix[ledId].setValue(value) - def snapImage(self, path="Default.tif"): + def getImage(self, path="Default.tif"): """ Captures a single microscopic image and saves it to a specified path. @@ -234,7 +234,7 @@ def snapImage(self, path="Default.tif"): tif.imsave(path,mImage) return mImage - def move(self, value, axis, is_absolute=True, is_blocking=True): + def setPosition(self, value, axis, is_absolute=True, is_blocking=True): """ Moves the microscope stage in the specified axis by a certain distance. @@ -249,10 +249,10 @@ def move(self, value, axis, is_absolute=True, is_blocking=True): Example Use: # Move the stage 10000 µm in the positive X direction in absolute coordinates and wait for the stage to arrive. - self.move(value=10000, axis="X", is_absolute=True, is_blocking=True) + self.setPosition(value=10000, axis="X", is_absolute=True, is_blocking=True) # move the stage 10000 µm in the negative Y direction in relative coordinates and return immediately. - self.move(value=-10000, axis="Y", is_absolute=False, is_blocking=False) + self.setPosition(value=-10000, axis="Y", is_absolute=False, is_blocking=False) Notes: - Successful movement requires supported axis. @@ -295,11 +295,11 @@ def start_service(self, service_id, server_url="https://ai.imjoy.io/", workspace "require_context": True, }, "type": "microscope", - "move": self.move, - "laserActivate": self.laserActivate, - "laserValue": self.laserValue, - "ledValue": self.ledValue, - "snapImage": self.snapImage + "move": self.setPosition, + "setLaserActive": self.setLaserActive, + "setLaserValue": self.setLaserValue, + "setLEDValue": self.setLEDValue, + "getImage": self.getImage } ) # print("Workspace: ", workspace, "Token:", await server.generate_token({"expires_in": 3600*24*100})) diff --git a/imswitch/imcontrol/controller/controllers/RecordingController.py b/imswitch/imcontrol/controller/controllers/RecordingController.py index 433272e28..189f58b8b 100644 --- a/imswitch/imcontrol/controller/controllers/RecordingController.py +++ b/imswitch/imcontrol/controller/controllers/RecordingController.py @@ -6,6 +6,8 @@ from fastapi.responses import StreamingResponse from fastapi import FastAPI, Response import cv2 +from PIL import Image +import io from imswitch.imcommon.framework import Timer from imswitch.imcommon.model import ostools, APIExport @@ -380,8 +382,6 @@ def sendScanFreq(self): def getTimelapseFreq(self): return self._widget.getTimelapseFreq() - - def start_stream(self): ''' return a generator that converts frames into jpeg's reads to stream @@ -421,7 +421,6 @@ def streamer(self): def video_feeder(self): return StreamingResponse(self.streamer(), media_type="multipart/x-mixed-replace;boundary=frame") - ''' def snapImage(self, name=None) -> None: self.snap(name) @@ -431,7 +430,7 @@ def snapImageToPath(self, fileName: str = "."): """ Take a snap and save it to a .tiff file at the given fileName. """ self.snap(name = fileName) - @APIExport(runOnUIThread=True) + @APIExport(runOnUIThread=False) def snapImage(self, output: bool = False):# -> np.ndarray: """ Take a snap and save it to a .tiff file at the set file path. """ if output: @@ -440,14 +439,18 @@ def snapImage(self, output: bool = False):# -> np.ndarray: self.snap() @APIExport(runOnUIThread=False) - def snapNumpyToFastAPI(self, ) -> Response: + def snapNumpyToFastAPI(self, detectorName=None) -> Response: # Create a 2D NumPy array representing the image - image = self.snap() - image = np.random.randint(0, 255, size=(100, 100), dtype=np.uint8) + images = self.snapNumpy() + + # get the image from the first detector if detectorName is not specified + if detectorName is None: + detectorName = self.getDetectorNamesToCapture()[0] + + # get the image from the specified detector + image = images[detectorName] # using an in-memory image - from PIL import Image - import io im = Image.fromarray(image) # save image to an in-memory bytes buffer @@ -457,7 +460,6 @@ def snapNumpyToFastAPI(self, ) -> Response: headers = {'Content-Disposition': 'inline; filename="test.png"'} return Response(im_bytes, headers=headers, media_type='image/png') - @APIExport(runOnUIThread=True) def startRecording(self) -> None: