Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added focus executable, not tested #2

Merged
merged 1 commit into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions nightskycam_focus/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,31 @@ class CommandType(Enum):
APERTURE = "A"


class Aperture(Enum):
MAX = 441
V0 = 441
V1 = 512
V2 = 646
V3 = 706
V4 = 857
V5 = 926
V6 = 1110
V7 = 1159
V8 = 1271
V9 = 1347
V10 = 1468
V11 = 2303
MIN = 2303

@classmethod
def is_valid(cls, aperture: str) -> bool:
return aperture in cls.__members__

@classmethod
def get(cls, aperture: str) -> "Aperture":
return cls.__members__[aperture]


PIN = NewType("PIN", int)
SS_PIN = PIN(5)
RESET_PIN = PIN(6)
Expand Down Expand Up @@ -79,7 +104,9 @@ def _prepare_message(command: int, v1: int, v2: int) -> List[int]:
_ERROR_RESET = (2, 2, 2, 2)


def _spi_send(spi: spidev.SpiDev, command_type: CommandType, value: int) -> None:
def _spi_send(
spi: spidev.SpiDev, command_type: CommandType, value: int
) -> None:
logging.debug(f"command {command_type}: {value}")
v1, v2 = divmod(value, 256)
command = ord(command_type.value)
Expand Down Expand Up @@ -163,5 +190,6 @@ def set_focus(target_value: int) -> None:
_send_command(CommandType.FOCUS, target_value)


def set_aperture(target_value: int) -> None:
_send_command(CommandType.APERTURE, target_value)
def set_aperture(target_value: Aperture) -> None:
value: int = target_value.value
_send_command(CommandType.APERTURE, value)
117 changes: 102 additions & 15 deletions nightskycam_focus/main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from pathlib import Path
import argparse
import logging
import sys
Expand All @@ -7,12 +8,15 @@
import numpy as np
from camera_zwo_asi import ImageType
from camera_zwo_asi.camera import Camera
from camera_zwo_asi.image import Image

from .adapter import adapter
from .adapter import adapter, set_focus, set_aperture, Aperture
from .focus import find_focus


def _get_pixel_from_user(image: np.ndarray, resize: int = 4) -> Tuple[int, int]:
def _get_pixel_from_user(
image: np.ndarray, resize: int = 4
) -> Tuple[int, int]:
down_sized_image = cv2.resize(
image, (image.shape[1] // resize, image.shape[0] // resize)
)
Expand All @@ -39,15 +43,20 @@ def _click_event(event, x, y, flags, param):
return full_size_pixel


def _get_full_image(exposure: int, gain: int, camera_index: int) -> np.ndarray:
def _capture(exposure: int, gain: int, camera_index: int) -> Image:
camera = Camera(camera_index)
camera.set_control("Exposure", exposure)
camera.set_control("Gain", gain)
roi = camera.get_roi()
roi.bins = 1
roi.type = ImageType.rgb24
camera.set_roi(roi)
return camera.capture().get_image()
return camera.capture()


def _get_full_image(exposure: int, gain: int, camera_index: int) -> np.ndarray:
image = _capture(exposure, gain, camera_index)
return image.get_image()


def _add_border(img: np.array, thickness: int = 5, color=(255, 0, 0)):
Expand All @@ -68,9 +77,11 @@ def _add_border(img: np.array, thickness: int = 5, color=(255, 0, 0)):
return bordered_img


def _zwo_asi_focus():
def _zwo_asi_focus_sweep():

parser = argparse.ArgumentParser(description="Focus sweep on zwo-asi camera")
parser = argparse.ArgumentParser(
description="Focus sweep on zwo-asi camera"
)
parser.add_argument(
"--camera_index",
type=int,
Expand All @@ -91,10 +102,16 @@ def _zwo_asi_focus():
help="Camera exposure (default: %(default)s)",
)
parser.add_argument(
"--gain", type=int, default=121, help="Camera gain (default: %(default)s)"
"--gain",
type=int,
default=121,
help="Camera gain (default: %(default)s)",
)
parser.add_argument(
"--step", type=int, default=20, help="Focus step size (default: %(default)s)"
"--step",
type=int,
default=20,
help="Focus step size (default: %(default)s)",
)
parser.add_argument("--show", action="store_true", help="Show the image")
parser.add_argument(
Expand All @@ -115,16 +132,22 @@ def _zwo_asi_focus():

# setting the logs
if args.verbose:
logging.basicConfig(level=logging.DEBUG, format="focus sweep: %(message)s")
logging.basicConfig(
level=logging.DEBUG, format="focus sweep: %(message)s"
)
elif args.silent:
...
else:
logging.basicConfig(level=logging.INFO, format="focus sweep: %(message)s")
logging.basicConfig(
level=logging.INFO, format="focus sweep: %(message)s"
)

logging.info(f"capturing image (exposure: {args.exposure}, gain: {args.gain})")
logging.info(
f"capturing image (exposure: {args.exposure}, gain: {args.gain})"
)
full_image = _get_full_image(args.exposure, args.gain, args.camera_index)

logging.info(f"prompting user for target pixel")
logging.info("prompting user for target pixel")
pixel = _get_pixel_from_user(full_image)

logging.info(
Expand Down Expand Up @@ -159,16 +182,80 @@ def _zwo_asi_focus():
cv2.imwrite("focus.png", concatenated_images)


def zwo_asi_focus():
def zwo_asi_focus_sweep():
try:
_zwo_asi_focus()
_zwo_asi_focus_sweep()
sys.exit(0)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)


def zwo_asi_focus_test():
logging.basicConfig(level=logging.DEBUG, format="focus sweep: %(message)s")
logging.basicConfig(level=logging.DEBUG, format="focus test: %(message)s")
with adapter():
logging.info("adapter running")


def _check_range(value: int, minimum: int = 350, maximum: int = 650) -> int:
"""Check if the input value is an integer within the range 350 to 650."""
try:
ivalue = int(value)
except ValueError:
raise argparse.ArgumentTypeError(f"{value} is not a valid integer")
if ivalue < minimum or ivalue > maximum:
raise argparse.ArgumentTypeError(
f"{value} is an invalid value. Must be between {minimum} and {maximum}."
)
return ivalue


def _valid_aperture(value: str) -> Aperture:
try:
return Aperture.get(value)
except KeyError:
raise argparse.ArgumentTypeError(
f"{value} is not a valid aperture. Valid apertures: MAX (open), V1, ..., V10, MIN (closed)"
)


def zwo_asi_focus():
logging.basicConfig(level=logging.DEBUG, format="focus: %(message)s")
parser = argparse.ArgumentParser(
description="Focus change on zwo-asi camera"
)
parser.add_argument(
"focus",
type=_check_range,
help="desired focus. int between 350 and 650",
)
parser.add_argument(
"--aperture",
type=_valid_aperture,
help="desired aperture. MAX: open, MIN: close, V1 ... V10: intermediate values",
required=False,
)
parser.add_argument(
"--exposure",
type=int,
help="if set (microseconds), a picture will be taken and saved in the current directory",
required=False,
)
args = parser.parse_args()
with adapter():
logging.info(f"setting focus to {args.focus}")
set_focus(args.focus)
if args.aperture is not None:
logging.info(f"setting aperture to {args.aperture}")
set_aperture(args.aperture)
if args.exposure is None:
return
logging.info(f"taking picture with exposure {args.exposure}")
image = _capture(args.exposure, 121, 0)
if args.aperture:
filename = f"img_{args.focus}_{args.aperture}_{args.exposure}.tiff"
else:
filename = f"img_{args.focus}_{args.exposure}.tiff"
filepath = str(Path.cwd() / filename)
logging.info(f"saving image to {filepath}")
image.save(filepath)
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ authors = ["Vincent Berenz <[email protected]>"]
packages = [{ include = "nightskycam_focus" }]

[tool.poetry.scripts]
zwo-asi-focus = 'nightskycam_focus.main:zwo_asi_focus'
zwo-asi-focus-sweep = 'nightskycam_focus.main:zwo_asi_focus_sweep'
zwo-asi-focus-test = 'nightskycam_focus.main:zwo_asi_focus_test'
zwo-asi-focus = 'nightskycam_focus.main:zwo_asi_focus'

[tool.poetry.dependencies]
python = "^3.9"
Expand Down