diff --git a/noctua/devices/stx.py b/noctua/devices/stx.py index ed9c75293d20e396eed246e1eea000bd2bcf1499..50fd59cb95d787c4edda696ed7a2f6837f137fa5 100644 --- a/noctua/devices/stx.py +++ b/noctua/devices/stx.py @@ -30,7 +30,7 @@ class STX(BaseDevice): self.addr = self.url self.timeout = 3 self._last_command_time = 0 - self._command_interval = 0.05 # 50 milliseconds + self._command_interval = 0.05 # 50 milliseconds def _wait_if_needed(self): """ @@ -60,7 +60,7 @@ class STX(BaseDevice): def get(self, method, params=[]): '''Send a HTTP GET request to the device address.''' - self._wait_if_needed() # Wait before sending command + self._wait_if_needed() # Wait before sending command res = requests.get(f"{self.addr}/{method}.cgi", params="&".join(params), timeout=self.timeout, verify=False) @@ -84,8 +84,8 @@ class STX(BaseDevice): @check.request_errors def put(self, method, params={}): '''Send a HTTP GET request to the device address.''' - - self._wait_if_needed() # Wait before sending command + + self._wait_if_needed() # Wait before sending command res = requests.get(f"{self.addr}/{method}.cgi", params=urlencode(params), timeout=self.timeout) diff --git a/noctua/devices/stx2.py b/noctua/devices/stx2.py index 420b7d672571c7a0bfea4f7163e6e85c79cc0fe0..29635a31ab08a15e3b18ada35b9b97e6de2dc59b 100644 --- a/noctua/devices/stx2.py +++ b/noctua/devices/stx2.py @@ -40,7 +40,7 @@ class STX(BaseDevice): self.addr = self.url self.timeout = 3 self._last_command_time = 0 - self._command_interval = 0.05 # 50 milliseconds + self._command_interval = 0.05 # 50 milliseconds def _wait_if_needed(self): """ @@ -171,7 +171,9 @@ class Camera(STX): If None, the current UTC time is used. """ if self.state != 0: - log.error(f"Cannot start exposure, camera is not idle. State: {self.state}") + log.error( + f"Cannot start exposure, camera is not idle. State: { + self.state}") self.error.append("Camera not idle") return @@ -214,7 +216,9 @@ class Camera(STX): The height of the sub-frame in pixels. """ if self.state != 0: - log.error(f"Cannot set window, camera is not idle. State: {self.state}") + log.error( + f"Cannot set window, camera is not idle. State: { + self.state}") self.error.append("Camera not idle") return @@ -224,140 +228,166 @@ class Camera(STX): "NumX": width, "NumY": height } - + self.put("ImagerSetSettings", params=params) def full_frame(self): """Sets the camera to use the full sensor area.""" - + params = ["CameraXSize", "CameraYSize"] cam_x, cam_y = self.get("ImagerGetSettings", params=params) - if self.error: return [None, None] - + if self.error: + return [None, None] + self.set_window(0, 0, int(cam_x), int(cam_y)) def half_frame(self): """Sets the camera to use a centered 50% sub-frame.""" - + params = ["CameraXSize", "CameraYSize"] cam_x, cam_y = self.get("ImagerGetSettings", params=params) - if self.error: return [None, None] + if self.error: + return [None, None] start_x = int(cam_x) // 4 start_y = int(cam_y) // 4 width = int(cam_x) // 2 height = int(cam_y) // 2 - + self.set_window(start_x, start_y, width, height) def small_frame(self): """Sets the camera to use a centered 10% sub-frame.""" - + params = ["CameraXSize", "CameraYSize"] cam_x, cam_y = self.get("ImagerGetSettings", params=params) - if self.error: return [None, None] - + if self.error: + return [None, None] + cam_x, cam_y = res start_x = int(cam_x) * 9 // 20 start_y = int(cam_y) * 9 // 20 width = int(cam_x) // 10 height = int(cam_y) // 10 - + self.set_window(start_x, start_y, width, height) @property def binning(self): """list of int: The current [X, Y] binning factor.""" - + params = ["BinX", "BinY"] binx, biny = self.get("ImagerGetSettings", params=params) - if self.error: return [None, None] - + if self.error: + return [None, None] + return [int(binx), int(biny)] @binning.setter def binning(self, b): - + if self.state != 0: - log.error(f"Cannot change binning, camera is not idle. State: {self.state}") + log.error( + f"Cannot change binning, camera is not idle. State: { + self.state}") self.error.append("Camera not idle") return - + params = {"BinX": b[0], "BinY": b[1]} self.put("ImagerSetSettings", params=params) @property def filter(self): """int: The currently selected filter position (1-8).""" - + params = ["CurrentFilter"] res = self.get("GetFilterSetting", params=params) - if self.error: return None - + if self.error: + return None + return res @property def cooler(self): """bool: The current state of the CCD cooler (True=On, False=Off).""" - + params = ["CoolerState"] res = self.get("ImagerGetSettings", params=params) - if self.error: return None - + if self.error: + return None + return bool(res) @cooler.setter def cooler(self, b): - + if self.state != 0: - log.error(f"Cannot change cooler state, camera is not idle. State: {self.state}") + log.error( + f"Cannot change cooler state, camera is not idle. State: { + self.state}") self.error.append("Camera not idle") return - + params = {"CoolerState": "1" if b else "0"} self.put("ImagerSetSettings", params=params) @filter.setter def filter(self, n): - + if self.is_moving != 0: - log.error(f"Cannot change filter, filter wheel is moving. State: {self.is_moving}") + log.error( + f"Cannot change filter, filter wheel is moving. State: { + self.is_moving}") self.error.append("Filter wheel busy") return - + params = {"NewPosition": n} self.put("ChangeFilter", params=params) @property def temperature(self): """float: The current CCD temperature in degrees Celsius.""" - + params = ["CCDTemperature"] res = self.get("ImagerGetSettings", params=params) - if self.error: return None - + if self.error: + return None + return round(res, 1) @temperature.setter def temperature(self, t): - + if self.state != 0: - log.error(f"Cannot change temperature, camera is not idle. State: {self.state}") + log.error( + f"Cannot change temperature, camera is not idle. State: { + self.state}") self.error.append("Camera not idle") return - + params = {"CCDTemperatureSetpoint": t} self.put("ImagerSetSettings", params=params) @property def all(self): """dict: A comprehensive dictionary of the current camera state.""" - - params = ["AmbientTemperature", "CCDTemperatureSetpoint", "CCDTemperature", - "CoolerState", "CoolerPower", "BinX", "BinY", "CameraXSize", - "CameraYSize", "StartX", "StartY", "NumX", "NumY"] + + params = [ + "AmbientTemperature", + "CCDTemperatureSetpoint", + "CCDTemperature", + "CoolerState", + "CoolerPower", + "BinX", + "BinY", + "CameraXSize", + "CameraYSize", + "StartX", + "StartY", + "NumX", + "NumY"] res = self.get("ImagerGetSettings", params=params) - + if self.error or not res or len(res) != len(params): return {} @@ -383,40 +413,44 @@ class Camera(STX): @property def ambient(self): """float: The ambient temperature in degrees Celsius.""" - + params = ["AmbientTemperature"] - res = self.get("ImagerGetSettings", params=params) - if self.error: return None - + res = self.get("ImagerGetSettings", params=params) + if self.error: + return None + return round(res, 1) @property def center(self): """list of int: The sensor's [X, Y] center coordinates for current binning.""" - + params = ["CameraXSize", "CameraYSize", "BinX", "BinY"] camx, camy, binx, biny = self.get("ImagerGetSettings", params=params) - if self.error: return [None, None] - + if self.error: + return [None, None] + return [int(camx) // int(binx) // 2, int(camy) // int(biny) // 2] @property def description(self): """str: The camera model description string.""" - + res = self.get("Description") - if self.error: return None - + if self.error: + return None + return res @property def fan(self): """int: The current cooler power level in percent.""" - + params = ["CoolerPower"] res = self.get("ImagerGetSettings", params=params) - if self.error: return None - + if self.error: + return None + return round(res) @property @@ -424,19 +458,21 @@ class Camera(STX): """int: The current state of the filter wheel. 0=Idle, 1=Moving, 2=Error. """ - + res = self.get("FilterState") - if self.error: return None - + if self.error: + return None + return res @property def max_range(self): """list of int: The maximum sensor dimensions [X, Y] for current binning.""" - + params = ["CameraXSize", "CameraYSize"] b_x, b_y = self.get("ImagerGetSettings", params=params) - if self.error: return [None, None] + if self.error: + return [None, None] b_x, b_y = self.binning return [int(res[0]) // b_x, int(res[1]) // b_y] @@ -444,11 +480,12 @@ class Camera(STX): @property def setpoint(self): """float: The current CCD temperature setpoint in degrees Celsius.""" - + params = ["CCDTemperatureSetpoint"] res = self.get("ImagerGetSettings", params=params) - if self.error: return None - + if self.error: + return None + return res @property @@ -456,10 +493,11 @@ class Camera(STX): """int: The current state of the imaging CCD. 0=Idle, 2=Exposing, 3=Reading, 5=Error. """ - + res = self.get("ImagerState") - if self.error: return None - + if self.error: + return None + return res @property @@ -467,29 +505,32 @@ class Camera(STX): """int: The status of the image buffer. 1 if an image is ready for download, 0 otherwise. """ - - res = self.get("ImagerImageReady") - if self.error: return None - + + res = self.get("ImagerImageReady") + if self.error: + return None + return res @property def version(self): """list of str: Camera firmware and API version numbers.""" - + res = self.get("VersionNumbers") - if self.error: return None - + if self.error: + return None + return res @property def xrange(self): """list of int: The current [start, end] X-axis window for current binning.""" - + params = ["StartX", "NumX", "BinX"] startx, numx, binx = self.get("ImagerGetSettings", params=params) - if self.error: return [None, None] - + if self.error: + return [None, None] + x_start = int(startx) // int(binx) x_end = (int(startx) + int(numx)) // int(binx) return [x_start, x_end] @@ -497,10 +538,11 @@ class Camera(STX): @property def yrange(self): """list of int: The current [start, end] Y-axis window for current binning.""" - + params = ["StartY", "NumY", "BinY"] starty, numy, biny = self.get("ImagerGetSettings", params=params) - if self.error: return [None, None] + if self.error: + return [None, None] y_start = int(starty) // int(biny) y_end = (int(starty) + int(numy)) // int(biny) @@ -509,21 +551,25 @@ class Camera(STX): @property def xystart(self): """list of int: The current [X, Y] start coordinates for current binning.""" - + params = ["StartX", "StartY", "BinX", "BinY"] - startx, starty, binx, biny = self.get("ImagerGetSettings", params=params) - if self.error: return [None, None] - + startx, starty, binx, biny = self.get( + "ImagerGetSettings", params=params) + if self.error: + return [None, None] + return [int(startx) // int(binx), int(starty) // int(biny)] @property def xyend(self): """list of int: The current [X, Y] end coordinates for current binning.""" - + params = ["StartX", "StartY", "NumX", "NumY", "BinX", "BinY"] - startx, starty, numx, numy, binx, biny = self.get("ImagerGetSettings", params=params) - if self.error: return [None, None] - + startx, starty, numx, numy, binx, biny = self.get( + "ImagerGetSettings", params=params) + if self.error: + return [None, None] + x_end = (int(startx) + int(numx)) // int(binx) y_end = (int(starty) + int(numy)) // int(biny) return [x_end, y_end]