Cameras (pyobs.modules.camera)
Camera modules. TODO: write doc
BaseCamera
- class BaseCamera(fits_headers: dict[str, Any] | None = None, centre: tuple[float, float] | None = None, rotation: float = 0.0, flip: bool | None = None, flip_x: bool = False, flip_y: bool = False, filenames: str = '/cache/pyobs-{DAY-OBS|date:}-{FRAMENUM|string:04d}-{IMAGETYP|type}00.fits.gz', fits_namespaces: list[str] | None = None, meridian_flip_on: str | None = None, fits_header_timeout: float = 15.0, max_stack_bytes: int = 2147483648, stack_frame_overhead: float = 10.0, stack_timeout_margin: float = 60.0, **kwargs: Any)
Bases:
Module,ImageFitsHeaderMixin,ICamera,IExposure,IExposureTime,IImageType,IResettable,DataSequenceMixin,DataPipelineMixin,IDataStackBase class for all camera modules.
Creates a new BaseCamera.
- Parameters:
fits_headers – Additional FITS headers.
centre – (x, y) tuple of camera centre.
rotation – Rotation east of north.
flip – Whether or not to flip the image along its first axis (deprecated, use flip_x).
flip_x – Whether or not to flip the image along its first axis.
flip_y – Whether or not to flip the image along its second axis.
filenames – Template for file naming.
fits_namespaces – List of namespaces for FITS headers that this camera should request
fits_header_timeout – Maximum seconds to wait for a peer’s FITS headers before skipping them.
max_stack_bytes – Memory cap for a grab_stack() cube (count * frame size), in bytes.
stack_frame_overhead – Estimated per-frame readout/transfer time in seconds, added to the exposure time when computing grab_stack()’s timeout.
stack_timeout_margin – Extra seconds added to grab_stack()’s timeout, covering header requests, cube assembly and the data pipeline.
- async abort(**kwargs: Any) None[source]
Aborts the current exposure and sequence. Derived class must implement IAbortable for this!
- Returns:
Success or not.
- async add_custom_fits_headers(image: Image) None[source]
Add FITS headers in derived classes.
- Parameters:
image – Image to write FITS headers to.
- async apply_meridian_flip(image: Image) None[source]
If the telescope has a meridian flip (MERIDIAN keyword in header), flip the image on both axes.
- Parameters:
image – Image to be flipped.
- async full_reset(**kwargs: Any) None[source]
Reset the camera completely to its configured defaults, hardware included.
- Raises:
DeviceBusyError – If the camera is currently exposing, or running a sequence or stack.
- async grab_data(broadcast: bool = True, **kwargs: Any) str[source]
Grabs an image ans returns reference.
- Parameters:
broadcast – Broadcast existence of image.
- Returns:
Name of image that was taken.
- Raises:
DeviceBusyError – If the camera is already busy (exposing or running a sequence).
GrabImageError – If there was a problem grabbing the image.
- async grab_stack(count: int, broadcast: bool = True, **kwargs: Any) str[source]
Grab count consecutive frames into one product and return its name.
Without a pipeline selected (IDataPipeline), the product is a 3D cube of all frames. With one, the pipeline runs on the cube (e.g. to combine it) and only its result is stored.
- Parameters:
count – Number of frames.
broadcast – Broadcast existence of the product.
- Returns:
Name of the stored product.
- Raises:
InvalidArgumentError – If count < 1, or the stack would exceed the module’s memory cap.
DeviceBusyError – If the camera is exposing, or running a sequence or another stack.
AbortedError – If the stack was aborted.
GrabImageError – If a frame could not be grabbed, frames don’t match, or the pipeline failed.
- async reset(**kwargs: Any) None[source]
Reset exposure time, image type, binning and window to their defaults.
- Raises:
DeviceBusyError – If the camera is currently exposing, or running a sequence or stack.
- static set_biassec_trimsec(hdr: Header, left: int, top: int, width: int, height: int) None[source]
Calculates and sets the BIASSEC and TRIMSEC areas.
- Parameters:
hdr – FITS header (in/out)
left – left edge of data area
top – top edge of data area
width – width of data area
height – height of data area
BaseSpectrograph
- class BaseSpectrograph(fits_headers: dict[str, Any] | None = None, filenames: str = '/cache/pyobs-{DAY-OBS|date:}-{FRAMENUM|string:04d}.fits.gz', fits_namespaces: list[str] | None = None, **kwargs: Any)
Bases:
Module,SpectrumFitsHeaderMixin,ISpectrograph,IExposure,IResettable,DataSequenceMixinBase class for all spectrograph modules.
Creates a new BaseCamera.
- Parameters:
fits_headers – Additional FITS headers.
flip – Whether or not to flip the image along its first axis.
filenames – Template for file naming.
fits_namespaces – List of namespaces for FITS headers that this camera should request
- async abort(**kwargs: Any) None[source]
Aborts the current exposure and sequence. Derived class must implement the actual hardware abort for this!
- Raises:
ValueError – If exposure could not be aborted.
- async full_reset(**kwargs: Any) None[source]
Reset the spectrograph completely to its configured defaults, hardware included.
- Raises:
DeviceBusyError – If the spectrograph is currently exposing or running a sequence.
- async grab_data(broadcast: bool = True, **kwargs: Any) str[source]
Grabs a spectrum and returns reference.
- Parameters:
broadcast – Broadcast existence of image.
- Returns:
Name of image that was taken.
- Raises:
DeviceBusyError – If the spectrograph is already busy (exposing).
GrabImageError – If there was a problem grabbing the spectrum.
- async reset(**kwargs: Any) None[source]
Reset the spectrograph. The base class has no settings of its own, this is a hook for drivers.
- Raises:
DeviceBusyError – If the spectrograph is currently exposing or running a sequence.
- async store_spectrum(hdulist: HDUList, filename: str, broadcast: bool) None[source]
Store spectrum at given destination. Can be overwritten by derived classes to custom store a file. In those cases, this version should be called!
- Parameters:
hdulist – HDU list with spectrum.
filename – Name to store file with.
broadcast – Whether to broadcast new spectrum.
BaseVideo
- class BaseVideo(http_port: int = 37077, interval: float = 0.5, video_path: str | None = '/webcam/video.mjpg', raw_path: str | None = '/webcam/video.raw', filenames: str = '/webcam/pyobs-{DAY-OBS|date:}-{FRAMENUM|string:04d}.fits', fits_namespaces: list[str] | None = None, fits_headers: dict[str, Any] | None = None, centre: tuple[float, float] | None = None, rotation: float = 0.0, cache_size: int = 5, flip: bool = False, sleep_time: int = 60, fits_header_timeout: float = 15.0, token: str | None = None, max_stack_bytes: int = 2147483648, stack_frame_overhead: float = 2.0, stack_timeout_margin: float = 60.0, buffer_frames: int = 4, readout_time: float = 0.0, stretch: str = 'linear', cuts: str | None = None, cut_lo: float | None = None, cut_hi: float | None = None, jpeg_quality: int = 80, **kwargs: Any)
Bases:
Module,ImageFitsHeaderMixin,IVideo,IImageType,IResettable,DataPipelineMixin,IDataStackBase class for all webcam modules.
Drivers implement
frames(), an async iterator yieldingFrameobjects; BaseVideo runs it while the camera is active and puts every frame into a small ring buffer, from which grab_data(), grab_stack(), the MJPEG live view and the raw stream read. Drivers that still push frames themselves via_set_image()keep working, but that path is deprecated.The built-in HTTP server serves the MJPEG live view, the raw frame stream and cached FITS images. Set the
tokenparameter to protect all of them: machine clients sendAuthorization: Bearer <token>(aspyobs.vfs.HttpFiledoes), browsers log in once at/loginand get an HMAC-signed session cookie that rides the same-origin<img>requests. Without a token (the default), no auth is enforced.Creates a new BaseWebcam.
On the receiving end, a VFS root with a HTTPFile must exist with the same name as in image_path and video_path, i.e. “webcam” in the default settings.
- Parameters:
http_port – HTTP port for webserver.
interval – Min interval between two frames sent to one MJPEG live-view connection.
video_path – VFS path to video. None disables the MJPEG live view.
raw_path – VFS path to the raw frame stream. None disables it.
filename – Filename pattern for FITS images.
fits_namespaces – List of namespaces for FITS headers that this camera should request.
fits_headers – Additional FITS headers.
centre – (x, y) tuple of camera centre.
rotation – Rotation east of north.
cache_size – Size of cache for previous images.
flip – Whether to flip around Y axis.
sleep_time – Time in s with inactivity after which the camera should go to sleep.
fits_header_timeout – Maximum seconds to wait for a peer’s FITS headers before skipping them.
token – Shared secret required in the “Authorization: Bearer <token>” header (or a login-page cookie) for stream and data access. If None (default), no auth is enforced.
max_stack_bytes – Memory cap for a grab_stack() cube (count * frame size), in bytes. A stacked product also sits in the in-memory DataCache (cache_size) once stored, so peak memory use with several cached stacks can be well above this cap.
stack_frame_overhead – Estimated per-frame overhead in seconds, added to the frame interval when computing grab_stack()’s timeout.
stack_timeout_margin – Extra seconds added to grab_stack()’s timeout, covering header requests, cube assembly and the data pipeline.
buffer_frames – Number of recent frames kept in memory for grab_data(), grab_stack() and the streams. grab_stack() fails if it falls behind by more than this.
readout_time – Readout time in seconds, used to estimate a frame’s exposure start when the driver doesn’t provide one (start = arrival - exposure time - readout time).
stretch – Default stretch function for the MJPEG live view (linear, sqrt, asinh, log).
cuts – Default cuts for the MJPEG live view (full, minmax, percentile, manual). None means “full” for 8-bit data and “minmax” otherwise.
cut_lo – Default low cut (percentile or value, depending on cuts).
cut_hi – Default high cut (percentile or value, depending on cuts).
jpeg_quality – Default JPEG quality for the MJPEG live view.
- async abort(**kwargs: Any) None[source]
Abort a running stack.
Pending single grab_data() requests are not affected – BaseVideo already serves those concurrently with a running stack.
- static create_jpeg(data: ndarray[tuple[Any, ...], dtype[Any]], params: StretchParams | None = None, quality: int = 80) bytes[source]
Create a JPEG image from a numpy array and return as bytes.
- Parameters:
data – Numpy array to convert to JPEG.
params – How to stretch the data to 8 bit, defaults if None.
quality – JPEG quality.
- Returns:
Bytes containing JPEG image.
- frames() AsyncIterator[Frame][source]
Yield frames from the camera, to be implemented by drivers as an async generator.
BaseVideo starts iterating when the camera gets activated and closes the iterator (
aclose(), i.e. GeneratorExit/CancelledError at the currentawait) when it goes to sleep, so drivers start acquisition at the top and stop it in afinallyblock. If the iterator raises, it is restarted with a back-off.Blocking SDK calls must not run on the event loop; use a worker thread.
Drivers that don’t implement this push frames via the deprecated
_set_image().
- async full_reset(**kwargs: Any) None[source]
Reset the camera completely to its configured defaults, hardware included.
- Raises:
DeviceBusyError – If a stack is currently running.
- async grab_data(broadcast: bool = True, **kwargs: Any) str[source]
Grabs an image and returns reference.
Returns the first frame that started exposing after this call, with the camera settings that were current at the time of the call. FITS headers from other modules are requested right away, i.e. before that exposure starts. Nothing of this runs in the frame loop, so the streams keep flowing while the image is built.
- Parameters:
broadcast – Broadcast existence of image.
- Returns:
Name of image that was taken.
- Raises:
GrabImageError – If there was a problem grabbing the image.
- async grab_stack(count: int, broadcast: bool = True, **kwargs: Any) str[source]
Grab count consecutive frames into one product and return its name.
Without a pipeline selected (IDataPipeline), the product is a 3D cube of all frames. With one, the pipeline runs on the cube (e.g. to combine it) and only its result is stored. Single grab_data() calls during a stack are still served concurrently.
The first frame is chosen like in grab_data(); all following ones must be consecutive and taken with the same settings.
- Parameters:
count – Number of frames.
broadcast – Broadcast existence of the product.
- Returns:
Name of the stored product.
- Raises:
InvalidArgumentError – If count < 1, or the stack would exceed the module’s memory cap.
DeviceBusyError – If another stack is already running.
AbortedError – If the stack was aborted.
GrabImageError – If a frame could not be grabbed, frames were dropped or don’t match, or the pipeline failed.
- async image_handler(request: Request) Response[source]
Handles access to /* and returns a specified image.
- Parameters:
request – Request to respond to.
- Returns:
Response containing image.
- async image_jpeg() tuple[int | None, bytes | None][source]
Return the newest frame as JPEG with the module’s default stretch.
- async login_handler(request: Request) Response[source]
Handles GET access to /login and returns the login form.
Served unauthenticated: this is the bootstrap a browser needs, since it cannot attach an “Authorization” header to an <img> request. Only registered when a token is configured.
- Parameters:
request – Request to respond to.
- Returns:
Response containing the login form.
- async login_post_handler(request: Request) Response[source]
Handles POST access to /login, verifying the password and issuing the session cookie.
- Parameters:
request – Request to respond to.
- Returns:
303 redirect to / on success, 401 on wrong password.
- async logout_handler(request: Request) Response[source]
Handles GET access to /logout and clears the session cookie.
- Parameters:
request – Request to respond to.
- Returns:
303 redirect to /login.
- async ping_handler(request: Request) Response[source]
Handles GET access to /ping for testing connectivity.
- Parameters:
request – Request to respond to.
- Returns:
Response with a JSON status.
- async raw_handler(request: Request) StreamResponse[source]
Handles access to /video.raw and returns raw frames.
Optional query parameters:
x,y,w,hcrop the frame (unbinned pixels, all four or none),binbins it in software (block mean, after cropping),max_ratecaps the frames per second sent to this connection (newest frame wins).- Parameters:
request – Request to respond to.
- Returns:
Response containing raw frame stream.
- async reset(**kwargs: Any) None[source]
Reset the image type to its default.
- Raises:
DeviceBusyError – If a stack is currently running.
- async set_image_type(image_type: ImageType, **kwargs: Any) None[source]
Set the image type.
- Parameters:
image_type – New image type.
- async video_handler(request: Request) StreamResponse[source]
Handles access to /video.mjpg and returns the video.
Optional query parameters set the stretch for this connection (defaults from the module config):
stretch,cuts,lo,hi,scale(downsampling factor) andquality(JPEG quality). Connections with the same settings share the encoding work.- Parameters:
request – Request to respond to.
- Returns:
Response containing video stream.
DummyCamera
- class DummyCamera(readout_time: float = 2, image_size: tuple[int, int] | None = None, pixel_size: float = 0.015, focal_length: float = 5000.0, images: str | None = None, max_mag: float = 20.0, seeing: float = 3.0, telescope: str | None = None, roof: str | None = None, **kwargs: Any)
Bases:
BaseCamera,IWindow,IBinning,ICooling,IGain,IImageFormatA dummy camera for testing.
Creates a new dummy camera.
- Parameters:
readout_time – Readout time in seconds.
image_size – Size of simulated image in pixels (width, height).
pixel_size – Square pixel size in mm.
focal_length – Focal length in mm (for plate scale calculation).
images – Filename pattern for pre-recorded images to use instead of simulation.
max_mag – Maximum magnitude of simulated stars.
seeing – Seeing in arcsec FWHM.
telescope – Name of telescope module to read pointing from (for star simulation).
roof – Name of roof module to read open/closed state from. When given, the sky (flat flux and stars) is only simulated while the roof is not parked – frames come back dark otherwise. Fails closed: until the roof’s state has been received, the roof is assumed closed.
- async full_reset(**kwargs: Any) None[source]
Reset the camera completely to its configured defaults, hardware included.
- Raises:
DeviceBusyError – If the camera is currently exposing, or running a sequence or stack.
- async reset(**kwargs: Any) None[source]
Reset exposure time, image type, binning and window to their defaults.
- Raises:
DeviceBusyError – If the camera is currently exposing, or running a sequence or stack.
- async set_binning(x: int, y: int, **kwargs: Any) None[source]
Set the camera binning.
- Parameters:
x – X binning.
y – Y binning.
- Raises:
ValueError – If binning could not be set.
- async set_cooling(enabled: bool, setpoint: float, **kwargs: Any) None[source]
Enables/disables cooling and sets setpoint.
- Parameters:
enabled – Enable or disable cooling.
setpoint – Setpoint in celsius for the cooling.
- Raises:
ValueError – If cooling could not be set.
- async set_gain(gain: float, **kwargs: Any) None[source]
Set the camera gain.
- Parameters:
gain – New camera gain.
- Raises:
ValueError – If gain could not be set.
- async set_image_format(fmt: ImageFormat, **kwargs: Any) None[source]
Set the camera image format.
- Parameters:
fmt – New image format.
- Raises:
ValueError – If format could not be set.
DummySpectrograph
- class DummySpectrograph(**kwargs: Any)
Bases:
BaseSpectrographA dummy spectrograph for testing.
Creates a new dummy cammera.
- Parameters:
readout_time – Readout time in seconds.
sim – Dictionary with config for image simulator.
PipelineCamera
- class PipelineCamera(**kwargs: Any)
Bases:
Module,ICamera,ImageFitsHeaderMixin,PipelineMixinA virtual camera based on an image pipeline.
Creates a new pipeline cammera.