imswitchclient 0.1.2__tar.gz → 0.1.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. imswitchclient-0.1.4/PKG-INFO +189 -0
  2. imswitchclient-0.1.4/README.md +150 -0
  3. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/imswitchclient/ImSwitchClient.py +10 -2
  4. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/imswitchclient/__init__.py +1 -1
  5. imswitchclient-0.1.4/imswitchclient/histoscanManager.py +132 -0
  6. imswitchclient-0.1.4/imswitchclient/objectiveController.py +45 -0
  7. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/imswitchclient/positionersManager.py +40 -2
  8. imswitchclient-0.1.4/imswitchclient/recordingManager.py +106 -0
  9. imswitchclient-0.1.4/imswitchclient/socketClient.py +46 -0
  10. imswitchclient-0.1.4/imswitchclient.egg-info/PKG-INFO +189 -0
  11. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/imswitchclient.egg-info/SOURCES.txt +4 -11
  12. imswitchclient-0.1.4/imswitchclient.egg-info/requires.txt +6 -0
  13. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/setup.cfg +3 -3
  14. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/setup.py +4 -4
  15. imswitchclient-0.1.2/AUTHORS.rst +0 -13
  16. imswitchclient-0.1.2/PKG-INFO +0 -102
  17. imswitchclient-0.1.2/README.md +0 -80
  18. imswitchclient-0.1.2/docs/Makefile +0 -20
  19. imswitchclient-0.1.2/docs/authors.rst +0 -1
  20. imswitchclient-0.1.2/docs/conf.py +0 -162
  21. imswitchclient-0.1.2/docs/contributing.rst +0 -1
  22. imswitchclient-0.1.2/docs/history.rst +0 -1
  23. imswitchclient-0.1.2/docs/index.rst +0 -20
  24. imswitchclient-0.1.2/docs/installation.rst +0 -51
  25. imswitchclient-0.1.2/docs/make.bat +0 -36
  26. imswitchclient-0.1.2/docs/readme.rst +0 -1
  27. imswitchclient-0.1.2/docs/usage.rst +0 -7
  28. imswitchclient-0.1.2/imswitchclient/recordingManager.py +0 -28
  29. imswitchclient-0.1.2/imswitchclient.egg-info/PKG-INFO +0 -102
  30. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/CONTRIBUTING.rst +0 -0
  31. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/HISTORY.rst +0 -0
  32. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/LICENSE +0 -0
  33. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/MANIFEST.in +0 -0
  34. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/imswitchclient/client.py +0 -0
  35. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/imswitchclient/lasersManager.py +0 -0
  36. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/imswitchclient.egg-info/dependency_links.txt +0 -0
  37. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/imswitchclient.egg-info/not-zip-safe +0 -0
  38. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/imswitchclient.egg-info/top_level.txt +0 -0
  39. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/tests/__init__.py +0 -0
  40. {imswitchclient-0.1.2 → imswitchclient-0.1.4}/tests/test_imswitchclient.py +0 -0
@@ -0,0 +1,189 @@
1
+ Metadata-Version: 2.4
2
+ Name: imswitchclient
3
+ Version: 0.1.4
4
+ Summary: This is a package that connects ImSwitch's REST API to the rest of the world (e.g. jupyter lab)
5
+ Home-page: https://github.com/openuc2/imswitchclient
6
+ Author: Benedict Diederich
7
+ Author-email: benedictdied@gmail.com
8
+ License: MIT license
9
+ Keywords: imswitchclient
10
+ Classifier: Development Status :: 2 - Pre-Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Natural Language :: English
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.6
16
+ Classifier: Programming Language :: Python :: 3.7
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Requires-Python: >=3.9
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: requests
22
+ Requires-Dist: Pillow
23
+ Requires-Dist: numpy
24
+ Requires-Dist: matplotlib
25
+ Requires-Dist: opencv-python
26
+ Requires-Dist: python-socketio==5.12.1
27
+ Dynamic: author
28
+ Dynamic: author-email
29
+ Dynamic: classifier
30
+ Dynamic: description
31
+ Dynamic: description-content-type
32
+ Dynamic: home-page
33
+ Dynamic: keywords
34
+ Dynamic: license
35
+ Dynamic: license-file
36
+ Dynamic: requires-dist
37
+ Dynamic: requires-python
38
+ Dynamic: summary
39
+
40
+ # ImSwitchClient Documentation
41
+
42
+ ## Introduction
43
+
44
+ `ImSwitchClient` is a Python wrapper designed for interacting with the ImSwitch REST API, enabling remote control over ImSwitch functionalities, such as stage positioning, laser control, and image acquisition. This client simplifies API interactions and allows seamless integration into Python scripts and Jupyter Notebooks.
45
+
46
+ [![PyPI Version](https://img.shields.io/pypi/v/imswitchclient.svg)](https://pypi.python.org/pypi/imswitchclient)
47
+
48
+ ## Try on GOOGLE COLAB:
49
+
50
+ Hit this link and test:
51
+
52
+ <a target="_blank" href="https://colab.research.google.com/drive/1W3Jcw4gFn0jtQXa3_2aCtJYJglMNGkXr?usp=sharing">
53
+ <img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
54
+ </a>
55
+
56
+
57
+ <a target="_blank" href="https://colab.research.google.com/github/openUC2/imswitchclient/blob/main/examples/StageCalibration.ipynb">
58
+ <img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
59
+ </a>
60
+
61
+ ## Features
62
+
63
+ - **Remote Control**: Interface with ImSwitch through REST API endpoints.
64
+ - **Comprehensive API Access**: Easily control positioners, lasers, detectors, and imaging settings.
65
+ - **Interactive API Exploration**: Utilize the FastAPI Swagger UI at `http://localhost:8000/docs`.
66
+ - **Modular Design**: Includes managers for lasers, positioners, image acquisition, and more.
67
+ - **Open Source**: Inspired by OpenFlexure Client, freely available under the MIT license.
68
+
69
+ ## Installation
70
+
71
+ You can install `ImSwitchClient` via pip:
72
+
73
+ ```bash
74
+ pip install imswitchclient
75
+ ```
76
+
77
+ ## Getting Started
78
+
79
+ ### Initializing the Client
80
+
81
+ ```python
82
+ import imswitchclient.ImSwitchClient as imc
83
+
84
+ # Initialize the client
85
+ client = imc.ImSwitchClient(host="0.0.0.0", isHttps=True, port=8001)
86
+ ```
87
+
88
+ ### Example: Moving a Stage and Acquiring an Image
89
+
90
+ ```python
91
+ import numpy as np
92
+ import matplotlib.pyplot as plt
93
+ import time
94
+
95
+ # Retrieve positioner names
96
+ positioner_names = client.positionersManager.getAllDeviceNames()
97
+ positioner_name = positioner_names[0]
98
+
99
+ # Get current position
100
+ current_positions = client.positionersManager.getPositionerPositions()[positioner_name]
101
+ initial_position = (current_positions["X"], current_positions["Y"])
102
+
103
+ # Turn on illumination
104
+ laser_name = client.lasersManager.getLaserNames()[0]
105
+ client.lasersManager.setLaserActive(laser_name, True)
106
+ client.lasersManager.setLaserValue(laser_name, 512)
107
+
108
+ # Move the stage and capture an image
109
+ def capture_image_at_position(x, y):
110
+ client.positionersManager.movePositioner(positioner_name, "X", x, is_absolute=True, is_blocking=True)
111
+ client.positionersManager.movePositioner(positioner_name, "Y", y, is_absolute=True, is_blocking=True)
112
+ last_frame = client.recordingManager.snapNumpyToFastAPI()
113
+ plt.imshow(last_frame)
114
+ plt.show()
115
+
116
+ # Example scanning
117
+ for ix in range(5):
118
+ for iy in range(5):
119
+ new_x = initial_position[0] + ix * 50
120
+ new_y = initial_position[1] + iy * 50
121
+ capture_image_at_position(new_x, new_y)
122
+
123
+ # Return stage to initial position
124
+ client.positionersManager.movePositioner(positioner_name, "X", initial_position[0], is_absolute=True, is_blocking=True)
125
+ client.positionersManager.movePositioner(positioner_name, "Y", initial_position[1], is_absolute=True, is_blocking=True)
126
+ ```
127
+
128
+ ### Laser Control Example
129
+
130
+ ```python
131
+ laser_name = client.lasersManager.getLaserNames()[0]
132
+ client.lasersManager.setLaserActive(laser_name, True)
133
+ client.lasersManager.setLaserValue(laser_name, 800)
134
+
135
+ # Verify laser status
136
+ print(client.lasersManager.getLaserNames())
137
+ client.lasersManager.setLaserActive(laser_name, False)
138
+ ```
139
+
140
+ ### Recording an Image
141
+
142
+ ```python
143
+ # Take a snapshot
144
+ image = client.recordingManager.snapNumpyToFastAPI()
145
+ plt.imshow(image)
146
+ plt.show()
147
+ ```
148
+
149
+ ### Setting Live View
150
+
151
+ ```python
152
+ client.viewManager.setLiveViewActive(True)
153
+ client.viewManager.setLiveViewCrosshairVisible(True)
154
+ client.viewManager.setLiveViewGridVisible(False)
155
+ ```
156
+
157
+ ## API Overview
158
+
159
+ The ImSwitch API provides access to various components:
160
+
161
+ ### Positioners Manager
162
+ - `getAllDeviceNames()` - Get all available positioners.
163
+ - `getPositionerPositions()` - Get current position.
164
+ - `movePositioner(name, axis, value, is_absolute, is_blocking)` - Move the stage.
165
+ - `homeAxis(name, axis, is_blocking)` - Home the positioner.
166
+
167
+ ### Lasers Manager
168
+ - `getLaserNames()` - Get available lasers.
169
+ - `setLaserActive(name, status)` - Turn laser on/off.
170
+ - `setLaserValue(name, value)` - Set laser intensity.
171
+
172
+ ### Recording Manager
173
+ - `snapNumpyToFastAPI()` - Capture an image.
174
+ - `startRecording()` - Begin recording.
175
+ - `stopRecording()` - Stop recording.
176
+
177
+ ### View Manager
178
+ - `setLiveViewActive(status)` - Enable live view.
179
+ - `setLiveViewCrosshairVisible(status)` - Show/hide crosshair.
180
+ - `setLiveViewGridVisible(status)` - Show/hide grid.
181
+
182
+ ## Contributing
183
+
184
+ Contributions are welcome! Visit the GitHub repository for details: [https://github.com/openUC2/imswitchclient](https://github.com/openUC2/imswitchclient)
185
+
186
+ ## License
187
+
188
+ This project is licensed under the MIT License.
189
+
@@ -0,0 +1,150 @@
1
+ # ImSwitchClient Documentation
2
+
3
+ ## Introduction
4
+
5
+ `ImSwitchClient` is a Python wrapper designed for interacting with the ImSwitch REST API, enabling remote control over ImSwitch functionalities, such as stage positioning, laser control, and image acquisition. This client simplifies API interactions and allows seamless integration into Python scripts and Jupyter Notebooks.
6
+
7
+ [![PyPI Version](https://img.shields.io/pypi/v/imswitchclient.svg)](https://pypi.python.org/pypi/imswitchclient)
8
+
9
+ ## Try on GOOGLE COLAB:
10
+
11
+ Hit this link and test:
12
+
13
+ <a target="_blank" href="https://colab.research.google.com/drive/1W3Jcw4gFn0jtQXa3_2aCtJYJglMNGkXr?usp=sharing">
14
+ <img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
15
+ </a>
16
+
17
+
18
+ <a target="_blank" href="https://colab.research.google.com/github/openUC2/imswitchclient/blob/main/examples/StageCalibration.ipynb">
19
+ <img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
20
+ </a>
21
+
22
+ ## Features
23
+
24
+ - **Remote Control**: Interface with ImSwitch through REST API endpoints.
25
+ - **Comprehensive API Access**: Easily control positioners, lasers, detectors, and imaging settings.
26
+ - **Interactive API Exploration**: Utilize the FastAPI Swagger UI at `http://localhost:8000/docs`.
27
+ - **Modular Design**: Includes managers for lasers, positioners, image acquisition, and more.
28
+ - **Open Source**: Inspired by OpenFlexure Client, freely available under the MIT license.
29
+
30
+ ## Installation
31
+
32
+ You can install `ImSwitchClient` via pip:
33
+
34
+ ```bash
35
+ pip install imswitchclient
36
+ ```
37
+
38
+ ## Getting Started
39
+
40
+ ### Initializing the Client
41
+
42
+ ```python
43
+ import imswitchclient.ImSwitchClient as imc
44
+
45
+ # Initialize the client
46
+ client = imc.ImSwitchClient(host="0.0.0.0", isHttps=True, port=8001)
47
+ ```
48
+
49
+ ### Example: Moving a Stage and Acquiring an Image
50
+
51
+ ```python
52
+ import numpy as np
53
+ import matplotlib.pyplot as plt
54
+ import time
55
+
56
+ # Retrieve positioner names
57
+ positioner_names = client.positionersManager.getAllDeviceNames()
58
+ positioner_name = positioner_names[0]
59
+
60
+ # Get current position
61
+ current_positions = client.positionersManager.getPositionerPositions()[positioner_name]
62
+ initial_position = (current_positions["X"], current_positions["Y"])
63
+
64
+ # Turn on illumination
65
+ laser_name = client.lasersManager.getLaserNames()[0]
66
+ client.lasersManager.setLaserActive(laser_name, True)
67
+ client.lasersManager.setLaserValue(laser_name, 512)
68
+
69
+ # Move the stage and capture an image
70
+ def capture_image_at_position(x, y):
71
+ client.positionersManager.movePositioner(positioner_name, "X", x, is_absolute=True, is_blocking=True)
72
+ client.positionersManager.movePositioner(positioner_name, "Y", y, is_absolute=True, is_blocking=True)
73
+ last_frame = client.recordingManager.snapNumpyToFastAPI()
74
+ plt.imshow(last_frame)
75
+ plt.show()
76
+
77
+ # Example scanning
78
+ for ix in range(5):
79
+ for iy in range(5):
80
+ new_x = initial_position[0] + ix * 50
81
+ new_y = initial_position[1] + iy * 50
82
+ capture_image_at_position(new_x, new_y)
83
+
84
+ # Return stage to initial position
85
+ client.positionersManager.movePositioner(positioner_name, "X", initial_position[0], is_absolute=True, is_blocking=True)
86
+ client.positionersManager.movePositioner(positioner_name, "Y", initial_position[1], is_absolute=True, is_blocking=True)
87
+ ```
88
+
89
+ ### Laser Control Example
90
+
91
+ ```python
92
+ laser_name = client.lasersManager.getLaserNames()[0]
93
+ client.lasersManager.setLaserActive(laser_name, True)
94
+ client.lasersManager.setLaserValue(laser_name, 800)
95
+
96
+ # Verify laser status
97
+ print(client.lasersManager.getLaserNames())
98
+ client.lasersManager.setLaserActive(laser_name, False)
99
+ ```
100
+
101
+ ### Recording an Image
102
+
103
+ ```python
104
+ # Take a snapshot
105
+ image = client.recordingManager.snapNumpyToFastAPI()
106
+ plt.imshow(image)
107
+ plt.show()
108
+ ```
109
+
110
+ ### Setting Live View
111
+
112
+ ```python
113
+ client.viewManager.setLiveViewActive(True)
114
+ client.viewManager.setLiveViewCrosshairVisible(True)
115
+ client.viewManager.setLiveViewGridVisible(False)
116
+ ```
117
+
118
+ ## API Overview
119
+
120
+ The ImSwitch API provides access to various components:
121
+
122
+ ### Positioners Manager
123
+ - `getAllDeviceNames()` - Get all available positioners.
124
+ - `getPositionerPositions()` - Get current position.
125
+ - `movePositioner(name, axis, value, is_absolute, is_blocking)` - Move the stage.
126
+ - `homeAxis(name, axis, is_blocking)` - Home the positioner.
127
+
128
+ ### Lasers Manager
129
+ - `getLaserNames()` - Get available lasers.
130
+ - `setLaserActive(name, status)` - Turn laser on/off.
131
+ - `setLaserValue(name, value)` - Set laser intensity.
132
+
133
+ ### Recording Manager
134
+ - `snapNumpyToFastAPI()` - Capture an image.
135
+ - `startRecording()` - Begin recording.
136
+ - `stopRecording()` - Stop recording.
137
+
138
+ ### View Manager
139
+ - `setLiveViewActive(status)` - Enable live view.
140
+ - `setLiveViewCrosshairVisible(status)` - Show/hide crosshair.
141
+ - `setLiveViewGridVisible(status)` - Show/hide grid.
142
+
143
+ ## Contributing
144
+
145
+ Contributions are welcome! Visit the GitHub repository for details: [https://github.com/openUC2/imswitchclient](https://github.com/openUC2/imswitchclient)
146
+
147
+ ## License
148
+
149
+ This project is licensed under the MIT License.
150
+
@@ -10,10 +10,12 @@ import os
10
10
  from .positionersManager import positionersManager
11
11
  from .recordingManager import recordingManager
12
12
  from .lasersManager import lasersManager
13
-
13
+ from .histoscanManager import histoscanManager
14
+ from .objectiveController import objectiveController
15
+ from .socketClient import socketClient
14
16
 
15
17
  class ImSwitchClient(object):
16
- def __init__(self, host="0.0.0.0", isHttps=True, port=8001):
18
+ def __init__(self, host="0.0.0.0", isHttps=True, port=8001, socket_port=8002):
17
19
  self.host = host
18
20
  self.port = port
19
21
  self.isHttps = isHttps
@@ -25,6 +27,12 @@ class ImSwitchClient(object):
25
27
  self.positionersManager = positionersManager(self)
26
28
  self.recordingManager = recordingManager(self)
27
29
  self.lasersManager = lasersManager(self)
30
+ self.histoscanManager = histoscanManager(self)
31
+ self.objectiveController = objectiveController(self)
32
+
33
+ # initialize Socket.IO client
34
+ self.socketClient = socketClient(host=self.host, port=socket_port, isHttps=self.isHttps)
35
+
28
36
 
29
37
  @property
30
38
  def base_uri(self):
@@ -3,4 +3,4 @@ from imswitchclient import *
3
3
 
4
4
  __author__ = """Benedict Diederich"""
5
5
  __email__ = 'benedictdied@gmail.com'
6
- __version__ = "v0.1.2"#'0.1.2'
6
+ __version__ = "v0.1.4"#'0.1.3'
@@ -0,0 +1,132 @@
1
+ from PIL import Image
2
+ import numpy as np
3
+ import io
4
+ import json
5
+
6
+ class histoscanManager(object):
7
+
8
+ '''
9
+ http://localhost:8001/HistoScanController/startHistoScanTileBasedByParameters?numberTilesX=2&numberTilesY=2&stepSizeX=100&stepSizeY=100&nTimes=1&tPeriod=1&initPosX=0&initPosY=0
10
+ http://localhost:8001/HistoScanController/startStageMapping
11
+ http://localhost:8001/HistoScanController/stopHistoScan
12
+ '''
13
+
14
+ def __init__(self, parent):
15
+ self.parent = parent
16
+
17
+ def stopHistoScan(self):
18
+ url = f"{self.parent.base_uri}/HistoScanController/stopHistoScan"
19
+ headers = {'accept': 'application/json'}
20
+ response = self.parent.get_json(url, headers=headers)
21
+ return response
22
+
23
+ def startStageScanningPositionlistbased(self, positionList:list, nTimes:int=1, tPeriod:int=1, illuSource:str=None):
24
+ url = f"{self.parent.base_uri}/HistoScanController/startStageScanningPositionlistbased"
25
+
26
+ payload = {
27
+ "positionList": str(positionList),
28
+ "nTimes": nTimes,
29
+ "tPeriod": tPeriod,
30
+ "illuSource": illuSource
31
+ }
32
+ if nTimes < 1:
33
+ raise ValueError("nTimes must be greater than 0")
34
+ response = self.parent.get_json(url, payload=payload)
35
+ return response
36
+
37
+
38
+ def startStageScanningPositionlistbased(self, positionList:str, nTimes:int=1, tPeriod:int=1, illuSource:str=None):
39
+ '''
40
+ https://localhost:8001/HistoScanController/startStageScanningPositionlistbased?positionList=dadf&nTimes=1&tPeriod=0
41
+
42
+ positionList: list of tuples with X/Y positions (e.g. "[(10, 10, 100), (100, 100, 100)]")
43
+ nTimes: number of times to repeat the scan
44
+ tPeriod: time between scans
45
+ '''
46
+
47
+ url = f"{self.parent.base_uri}/HistoScanController/startStageScanningPositionlistbased"
48
+ payload = {
49
+ "positionList": positionList,
50
+ "nTimes": nTimes,
51
+ "tPeriod": tPeriod,
52
+ "illuSource": illuSource
53
+ }
54
+ if nTimes < 1:
55
+ raise ValueError("nTimes must be greater than 0")
56
+ response = self.parent.get_json(url, payload=payload)
57
+ return response
58
+
59
+
60
+ def startHistoScanTileBasedByParameters(self, numberTilesX, numberTilesY, stepSizeX, stepSizeY, initPosX, initPosY, nTimes=1, tPeriod=1):
61
+ url = f"{self.parent.base_uri}/HistoScanController/startHistoScanTileBasedByParameters"
62
+ payload = {
63
+ "numberTilesX": numberTilesX,
64
+ "numberTilesY": numberTilesY,
65
+ "stepSizeX": stepSizeX,
66
+ "stepSizeY": stepSizeY,
67
+ "nTimes": nTimes,
68
+ "tPeriod": tPeriod,
69
+ "initPosX": initPosX,
70
+ "initPosY": initPosY
71
+ }
72
+ if nTimes < 1:
73
+ raise ValueError("nTimes must be greater than 0")
74
+ response = self.parent.get_json(url, payload=payload)
75
+ return response
76
+
77
+ def startStageMapping(self):
78
+ url = f"{self.parent.base_uri}/HistoScanController/startStageMapping"
79
+ payload = {
80
+ }
81
+ response = self.parent.get_json(url, payload=payload)
82
+ return response
83
+
84
+ def getStatusScanRunning(self):
85
+ url = f"{self.parent.base_uri}/HistoScanController/getStatusScanRunning"
86
+ payload = {
87
+ }
88
+ response = self.parent.get_json(url, payload=payload)
89
+ return response
90
+
91
+ def getLastStitchedImage(self):
92
+ '''
93
+ https://localhost:8001/HistoScanController/
94
+ Retrieve numpy image based on
95
+ return Response(im_bytes, headers=headers, media_type='image/png')
96
+ '''
97
+ url = f"{self.parent.base_uri}/HistoScanController/getLastStitchedImage"
98
+ headers = {'accept': 'application/json'}
99
+ response = self.parent.get_json(url, headers=headers)
100
+ content_type = response.headers.get('content-type')
101
+ if content_type == 'image/png':
102
+ image_data = response.content
103
+ image = Image.open(io.BytesIO(image_data))
104
+ return np.array(image)
105
+ else:
106
+ raise ValueError("Unexpected response content-type. Expected 'image/png'.")
107
+
108
+
109
+ def startStageScanning(self, minPosX:float=None, maxPosX:float=None, minPosY:float=None, maxPosY:float=None,
110
+ overlap:float=None, nTimes:int=1, tPeriod:int=0, positionList:list=None,
111
+ isStitchAshlar:bool=False, isStitchAshlarFlipX:bool=False, isStitchAshlarFlipY:bool=False,
112
+ resizeFactor=0.25):
113
+ '''
114
+ generic stage scan, rather low-level
115
+ '''
116
+ url = f"{self.parent.base_uri}/HistoScanController/startStageScanning"
117
+ payload = {
118
+ "minPosX": minPosX,
119
+ "maxPosX": maxPosX,
120
+ "minPosY": minPosY,
121
+ "maxPosY": maxPosY,
122
+ "overlap": overlap,
123
+ "nTimes": nTimes,
124
+ "tPeriod": tPeriod,
125
+ "positionList": json.dumps(positionList),
126
+ "isStitchAshlar": isStitchAshlar,
127
+ "isStitchAshlarFlipX": isStitchAshlarFlipX,
128
+ "isStitchAshlarFlipY": isStitchAshlarFlipY,
129
+ "resizeFactor": resizeFactor
130
+ }
131
+ response = self.parent.get_json(url, payload=payload)
132
+ return response
@@ -0,0 +1,45 @@
1
+ class objectiveController(object):
2
+
3
+ def __init__(self, parent):
4
+ self.parent = parent
5
+
6
+ def calibrateObjective(self, homeDirection=None, homePolarity=None):
7
+ url = f"{self.parent.base_uri}/ObjectiveController/calibrateObjective"
8
+ params = {}
9
+ if homeDirection is not None:
10
+ params['homeDirection'] = homeDirection
11
+ if homePolarity is not None:
12
+ params['homePolarity'] = homePolarity
13
+ response = self.parent.get_json(url, payload=params)
14
+ return response
15
+
16
+ def getCurrentObjective(self):
17
+ url = f"{self.parent.base_uri}/ObjectiveController/getCurrentObjective"
18
+ response = self.parent.get_json(url)
19
+ return response
20
+
21
+ def getStatus(self):
22
+ url = f"{self.parent.base_uri}/ObjectiveController/getstatus"
23
+ response = self.parent.get_json(url)
24
+ return response
25
+
26
+ def moveToObjective(self, slot):
27
+ url = f"{self.parent.base_uri}/ObjectiveController/moveToObjective"
28
+ payload = {"slot": slot}
29
+ response = self.parent.get_json(url, payload=payload)
30
+ return response
31
+
32
+ def setPositions(self, x1=None, x2=None, z1=None, z2=None, isBlocking=False):
33
+ url = f"{self.parent.base_uri}/ObjectiveController/setPositions"
34
+ payload = {}
35
+ if x1 is not None:
36
+ payload["x1"] = x1
37
+ if x2 is not None:
38
+ payload["x2"] = x2
39
+ if z1 is not None:
40
+ payload["z1"] = z1
41
+ if z2 is not None:
42
+ payload["z2"] = z2
43
+ payload["isBlocking"] = isBlocking
44
+ response = self.parent.get_json(url, payload=payload)
45
+ return response
@@ -3,6 +3,7 @@ class positionersManager(object):
3
3
 
4
4
  def __init__(self, parent):
5
5
  self.parent = parent
6
+ self.allStageNames = self.getAllDeviceNames()
6
7
 
7
8
  def getAllDeviceNames(self):
8
9
  url = f"{self.parent.base_uri}/PositionerController/getPositionerNames"
@@ -10,10 +11,26 @@ class positionersManager(object):
10
11
 
11
12
  response = self.parent.get_json(url, headers=headers)
12
13
  return response
13
-
14
+
15
+ def stop(self, positioner_name, axis):
16
+ if positioner_name is None:
17
+ positioner_name = self.allStageNames[0]
18
+
19
+ url = f"{self.parent.base_uri}/PositionerController/stop"
20
+ payload = {
21
+ 'positionerName': positioner_name,
22
+ 'axis': axis
23
+ }
24
+ response = self.parent.get_json(url, payload=payload)
25
+ return response
26
+
14
27
  def movePositionerForever(self, speed=(0, 0, 0, 0), is_stop=False):
28
+ if positioner_name is None:
29
+ positioner_name = self.allStageNames[0]
30
+
15
31
  url = f"{self.parent.base_uri}/PositionerController/movePositionerForever"
16
32
  payload = {
33
+ 'positionerName': positioner_name,
17
34
  'speed': speed,
18
35
  'isStop': is_stop
19
36
  }
@@ -21,6 +38,9 @@ class positionersManager(object):
21
38
  return response
22
39
 
23
40
  def setPositionerSpeed(self, positioner_name, axis, speed):
41
+ if positioner_name is None:
42
+ positioner_name = self.allStageNames[0]
43
+
24
44
  url = f"{self.parent.base_uri}/PositionerController/setPositionerSpeed"
25
45
  payload = {
26
46
  'positionerName': positioner_name,
@@ -31,6 +51,9 @@ class positionersManager(object):
31
51
  return response
32
52
 
33
53
  def movePositioner(self, positioner_name, axis, dist, is_absolute=True, is_blocking=True, speed=10000):
54
+ if positioner_name is None:
55
+ positioner_name = self.allStageNames[0]
56
+
34
57
  url = f"{self.parent.base_uri}/PositionerController/movePositioner"
35
58
  payload = {
36
59
  'positionerName': positioner_name,
@@ -45,9 +68,24 @@ class positionersManager(object):
45
68
  response = self.parent.get_json(url, payload=payload)
46
69
  return response
47
70
 
48
- def getPositionerPositions(self):
71
+ def getPositionerPositions(self, id=None):
49
72
  url = f"{self.parent.base_uri}/PositionerController/getPositionerPositions"
50
73
  payload = {
51
74
  }
52
75
  response = self.parent.get_json(url, payload=payload)
76
+ if type(id) == int:
77
+ return response[id]
78
+ return response
79
+
80
+ def homeAxis(self, positioner_name, axis, is_blocking=False):
81
+ url = f"{self.parent.base_uri}/PositionerController/homeAxis"
82
+ if positioner_name is None:
83
+ positioner_name = self.allStageNames[0]
84
+
85
+ payload = {
86
+ 'positionerName': positioner_name,
87
+ 'axis': axis,
88
+ 'isBlocking': is_blocking
89
+ }
90
+ response = self.parent.get_json(url, payload=payload)
53
91
  return response