astra.action_configs#
Action configuration dataclasses for observatory operations.
- Key capabilities:
Define structured configurations for various observatory actions
Validate required fields and types for action parameters
Provide defaults from observatory configuration
Support dictionary-like access to action configuration fields
Classes
Configuration for automated autofocus calibration field selection. |
|
|
Perform an autofocus sweep to determine the optimal focus position. |
Base class for action configurations. |
|
|
Calibrate guiding parameters using timed guide pulses. |
|
Capture a sequence of calibration images (bias/dark). |
Close the observatory safely. |
|
Complete FITS headers after exposures finish. |
|
Configuration for the |
|
|
Capture a sequence of sky flats as the sky brightness evolves. |
|
Capture a sequence of light frames. |
Open the observatory for observations. |
|
|
Aid building a telescope pointing model. |
|
- class astra.action_configs.BaseActionConfig[source]#
Bases:
objectBase class for action configurations.
This class serves as a base for specific action configurations, providing validation and dictionary-like access to its fields. It supports type validation, required fields, and merging with default values, centralizing common functionality for all action configurations and ensuring that the action values passed by the user are valid.
Examples
>>> from astra.action_configs import AutofocusConfig >>> autofocus_config = AutofocusConfig(exptime=3.0) >>> exptime in autofocus_config True >>> autofocus_config['exptime'] 3.0 >>> autofocus_config.get('not_available')
- EXAMPLE_SCHEDULE: ClassVar[dict] = {'action_value': {}, 'device_name': 'camera_name', 'end_time': '2025-02-01 00:00:00.000', 'start_time': '2025-01-01 00:00:00.000'}#
- classmethod from_dict(config_dict: dict, default_dict: dict = {}, logger=None)[source]#
Create an instance from a dictionary, merging with defaults.
- classmethod defaults_from_observatory_config(device_name: str, device_type: str = 'Camera', observatory_config: object | None = None) dict[source]#
Retrieve default values for this action from the observatory configuration.
Returns a dict suitable for passing as default_dict into from_dict.
- validate()[source]#
Validate required fields and types of all fields.
- Raises:
ValueError – If required fields are missing.
TypeError – If any field has an incorrect type.
- get(key: str, default=None)[source]#
Get attribute value by key with optional default.
- Parameters:
key – Attribute name to retrieve.
default – Value to return if attribute is not found.
- Returns:
Attribute value or default if not found.
- validate_filters(filterwheel_names: dict[str, list[str]]) None[source]#
Validate that filter(s) exist in the available filterwheels.
- Parameters:
filterwheel_names – Dict mapping filterwheel device names to lists of filter names. e.g., {“fw1”: [“Clear”, “Red”, “Green”, “Blue”]}
- Raises:
ValueError – If a filter is specified but doesn’t exist in any filterwheel.
- validate_subframe() None[source]#
Validate subframe parameters.
- Raises:
ValueError – If subframe parameters are invalid.
- validate_visibility(start_time: Time, end_time: Time, observatory_location: EarthLocation, min_altitude: float = 0.0)[source]#
Validate that the target is visible during the scheduled observation window.
Checks target visibility at the beginning, middle, and end of the planned observation to ensure the target remains observable throughout.
Only implemented for object actions; override in subclasses as needed.
- has_subframe() bool[source]#
Check if subframing is enabled.
- Returns:
True if subframe_width and subframe_height are specified, False otherwise.
- class astra.action_configs.OpenActionConfig[source]#
Bases:
BaseActionConfigOpen the observatory for observations.
- Steps:
Opens dome shutter
Unparks telescope
Cools camera
- EXAMPLE_SCHEDULE: ClassVar[dict] = {'action_type': 'open', 'action_value': {}, 'device_name': 'camera_name', 'end_time': '2025-02-01 00:00:00.000', 'start_time': '2025-01-01 00:00:00.000'}#
- validate()[source]#
Validate required fields and types of all fields.
- Raises:
ValueError – If required fields are missing.
TypeError – If any field has an incorrect type.
- class astra.action_configs.CloseActionConfig[source]#
Bases:
BaseActionConfigClose the observatory safely.
- Steps:
Stop any active guiding operations
Stop telescope slewing and tracking
Park the telescope
Park the dome and close shutter
Cools camera
- EXAMPLE_SCHEDULE: ClassVar[dict] = {'action_type': 'close', 'action_value': {}, 'device_name': 'camera_name', 'end_time': '2025-02-01 00:00:00.000', 'start_time': '2025-01-01 00:00:00.000'}#
- validate()[source]#
Validate required fields and types of all fields.
- Raises:
ValueError – If required fields are missing.
TypeError – If any field has an incorrect type.
- class astra.action_configs.CompleteHeadersActionConfig[source]#
Bases:
BaseActionConfigComplete FITS headers after exposures finish.
Uses paired device polled data to fill in FITS header fields that were unavailable at exposure time. Automatically executed at the end of every schedule.
- EXAMPLE_SCHEDULE: ClassVar[dict] = {'action_type': 'complete_headers', 'action_value': {}, 'device_name': 'camera_name', 'end_time': '2025-02-01 00:00:00.000', 'start_time': '2025-01-01 00:00:00.000'}#
- validate()[source]#
Validate required fields and types of all fields.
- Raises:
ValueError – If required fields are missing.
TypeError – If any field has an incorrect type.
- class astra.action_configs.CoolCameraActionConfig[source]#
Bases:
BaseActionConfigConfiguration for the
cool_cameraschedule action.Activates the camera cooler and sets the target temperature with specified tolerance and timeout from observatory configuration.
- EXAMPLE_SCHEDULE: ClassVar[dict] = {'action_type': 'cool_camera', 'action_value': {}, 'device_name': 'camera_name', 'end_time': '2025-02-01 00:00:00.000', 'start_time': '2025-01-01 00:00:00.000'}#
- validate()[source]#
Validate required fields and types of all fields.
- Raises:
ValueError – If required fields are missing.
TypeError – If any field has an incorrect type.
- class astra.action_configs.ObjectActionConfig(object: str, exptime: float, ra: float | None = None, dec: float | None = None, alt: float | None = None, az: float | None = None, lookup_name: str | None = None, filter: str | None = None, focus_shift: float | None = None, focus_position: float | None = None, n: int | None = None, guiding: bool = False, pointing: bool = False, bin: int = 1, dir: str | None = None, execute_parallel: bool = False, disable_telescope_movement: bool = False, reset_guiding_reference: bool = True, subframe_width: int | None = None, subframe_height: int | None = None, subframe_center_x: float = 0.5, subframe_center_y: float = 0.5)[source]#
Bases:
BaseActionConfigCapture a sequence of light frames.
- Workflow:
- Pre-sequence setup (pointing, filters, focus, binning, sub-framing, headers)
Observatory opens if not already done by a prior action if coordinates specified
Capture exposures in succession
Perform pointing correction if
pointing=trueStart autoguiding if
guiding=trueStop exposures, guiding, and tracking at completion
- FIELD_DESCRIPTIONS: ClassVar[dict[str, str]] = {'alt': 'Altitude coordinate when issuing Alt/Az pointings.', 'az': 'Azimuth coordinate when issuing Alt/Az pointings.', 'bin': 'Camera binning factor.', 'dec': 'Declination to slew to', 'dir': 'Base directory path for saving images.', 'disable_telescope_movement': 'Prevent any telescope motion during the sequence.', 'execute_parallel': 'Execute action in parallel mode when supported.', 'exptime': 'Exposure time per frame in seconds.', 'filter': 'Filter name to load before imaging.', 'focus_position': 'Absolute focus position override.', 'focus_shift': 'Focus offset relative to the stored best focus.', 'guiding': 'Start autoguiding with Donuts before imaging.', 'lookup_name': "Instead of specifying ra/dec or alt/az, use SIMBAD/Astropy to look up coordinates for celestial body to observe (e.g., 'mars', 'M31').", 'n': 'Number of exposures in the sequence. If not specified, defaults to infinite exposures until end_time.', 'object': 'Target name.', 'pointing': 'Perform pointing correction with twirl before imaging.', 'ra': 'Right Ascension to slew to', 'reset_guiding_reference': 'Acquire a fresh guiding reference frame at the start.', 'subframe_center_x': 'Horizontal location of the subframe center (0=left, 1=right).', 'subframe_center_y': 'Vertical location of the subframe center (0=top, 1=bottom).', 'subframe_height': 'Height of the requested subframe in binned pixels.', 'subframe_width': 'Width of the requested subframe in binned pixels.'}#
- EXAMPLE_SCHEDULE: ClassVar[dict] = {'action_type': 'object', 'action_value': {'dec': -5.39111, 'exptime': 60.0, 'filter': 'V', 'guiding': True, 'n': 3, 'object': 'M42', 'pointing': True, 'ra': 83.82208}, 'device_name': 'camera_name', 'end_time': '2025-02-01 00:00:00.000', 'start_time': '2025-01-01 00:00:00.000'}#
- validate()[source]#
Validate required fields and types of all fields.
- Raises:
ValueError – If required fields are missing.
TypeError – If any field has an incorrect type.
- validate_visibility(start_time: Time, end_time: Time, observatory_location: EarthLocation, min_altitude: float = 0.0) None[source]#
Validate that the target is visible during the scheduled observation window.
Checks target visibility at the beginning, middle, and end of the planned observation to ensure the target remains observable throughout.
- Parameters:
start_time – Observation start time as astropy Time object
end_time – Observation end time as astropy Time object
observatory_location – Observatory location as EarthLocation object
min_altitude – Minimum altitude in degrees for target to be considered visible (default: 0°)
- Raises:
ValueError – If RA/Dec are not provided or if target is below minimum altitude at any of the three check points (start, middle, end)
Note
If RA/Dec are not provided, attempts to resolve them from ‘lookup_name’ or ‘alt’/’az’ parameters using the start time.
- class astra.action_configs.CalibrationActionConfig(exptime: List[float] = <factory>, n: List[int] = <factory>, filter: str | None = None, dir: str | None = None, bin: int = 1, execute_parallel: bool = False, subframe_width: int | None = None, subframe_height: int | None = None, subframe_center_x: float = 0.5, subframe_center_y: float = 0.5)[source]#
Bases:
BaseActionConfigCapture a sequence of calibration images (bias/dark).
- FIELD_DESCRIPTIONS: ClassVar[dict[str, str]] = {'bin': 'Camera binning factor.', 'dir': 'Base directory path for saving images.', 'execute_parallel': 'Execute action in parallel mode when supported.', 'exptime': 'Exposure times (seconds) to iterate.', 'filter': 'Filter name to load before imaging.', 'n': 'Exposure counts aligned with each exposure time.', 'subframe_center_x': 'Horizontal subframe center (0=left, 1=right).', 'subframe_center_y': 'Vertical subframe center (0=top, 1=bottom).', 'subframe_height': 'Height of the requested subframe in binned pixels.', 'subframe_width': 'Width of the requested subframe in binned pixels.'}#
- EXAMPLE_SCHEDULE: ClassVar[dict] = {'action_type': 'calibration', 'action_value': {'exptime': [0.0, 5.0, 30.0], 'n': [10, 5, 3]}, 'device_name': 'camera_name', 'end_time': '2025-02-01 00:00:00.000', 'start_time': '2025-01-01 00:00:00.000'}#
- validate()[source]#
Validate required fields and types of all fields.
- Raises:
ValueError – If required fields are missing.
TypeError – If any field has an incorrect type.
- class astra.action_configs.FlatsActionConfig(filter: List[str] = <factory>, n: List[int] = <factory>, dir: str | None = None, bin: int = 1, execute_parallel: bool = False, disable_telescope_movement: bool = False, subframe_width: int | None = None, subframe_height: int | None = None, subframe_center_x: float = 0.5, subframe_center_y: float = 0.5)[source]#
Bases:
BaseActionConfigCapture a sequence of sky flats as the sky brightness evolves.
- Steps:
Wait for Sun altitude between -1° and -12°
- Point to a near-uniform patch of sky opposite the Sun
Opens observatory if not already done by a prior action
Capture exposures and re-position between frames
Iterate through requested filters while auto-adjusting exposure times
- FIELD_DESCRIPTIONS: ClassVar[dict[str, str]] = {'bin': 'Camera binning factor.', 'dir': 'Base directory path for saving images.', 'disable_telescope_movement': 'Prevent telescope motion during the sequence.', 'execute_parallel': 'Execute action in parallel mode when supported.', 'filter': 'Filters to iterate while capturing flats.', 'n': 'Number of flats to capture per filter.', 'subframe_center_x': 'Horizontal subframe center (0=left, 1=right).', 'subframe_center_y': 'Vertical subframe center (0=top, 1=bottom).', 'subframe_height': 'Height of the requested subframe in binned pixels.', 'subframe_width': 'Width of the requested subframe in binned pixels.'}#
- EXAMPLE_SCHEDULE: ClassVar[dict] = {'action_type': 'flats', 'action_value': {'filter': ['V', 'R'], 'n': [10, 10]}, 'device_name': 'camera_name', 'end_time': '2025-02-01 00:00:00.000', 'start_time': '2025-01-01 00:00:00.000'}#
- validate()[source]#
Validate required fields and types of all fields.
- Raises:
ValueError – If required fields are missing.
TypeError – If any field has an incorrect type.
- class astra.action_configs.CalibrateGuidingActionConfig(filter: str | None = None, pulse_time: int = 5000, exptime: float = 1.0, settle_time: float = 1.0, number_of_cycles: int = 10, focus_shift: float | None = None, focus_position: float | None = None, bin: int = 1, subframe_width: int | None = None, subframe_height: int | None = None, subframe_center_x: float = 0.5, subframe_center_y: float = 0.5)[source]#
Bases:
BaseActionConfigCalibrate guiding parameters using timed guide pulses.
- Steps:
- Slews telescope to RA = LST - 1 hour, Dec = 0° at the start of sequence
Opens observatory if not already done by a prior action
Issues a series of guide pulses in each cardinal direction with specified duration and settling time
Captures exposures after each pulse and measures star shifts to determine pixel-to-time scales and camera orientation relative to mount axes
Averages results over specified number of cycles
Saves calibration parameters in the observatory configuration for use in guiding
- FIELD_DESCRIPTIONS: ClassVar[dict[str, str]] = {'bin': 'Camera binning factor.', 'exptime': 'Exposure time for calibration images.', 'filter': 'Filter to use during calibration.', 'focus_position': 'Absolute focus position override.', 'focus_shift': 'Focus offset relative to best focus.', 'number_of_cycles': 'How many calibration cycles to take average over.', 'pulse_time': 'Duration of guide pulses in milliseconds.', 'settle_time': 'Wait time after pulses before exposing.', 'subframe_center_x': 'Horizontal subframe center (0=left, 1=right).', 'subframe_center_y': 'Vertical subframe center (0=top, 1=bottom).', 'subframe_height': 'Height of the requested subframe in binned pixels.', 'subframe_width': 'Width of the requested subframe in binned pixels.'}#
- EXAMPLE_SCHEDULE: ClassVar[dict] = {'action_type': 'calibrate_guiding', 'action_value': {}, 'device_name': 'camera_name', 'end_time': '2025-02-01 00:00:00.000', 'start_time': '2025-01-01 00:00:00.000'}#
- validate()[source]#
Validate required fields and types of all fields.
- Raises:
ValueError – If required fields are missing.
TypeError – If any field has an incorrect type.
- class astra.action_configs.PointingModelActionConfig(n: int = 50, exptime: float = 3.0, dark_subtraction: bool = False, object: str = 'Pointing Model', use_local_db: bool = False, filter: str | None = None, focus_shift: float | None = None, focus_position: float | None = None, bin: int = 1, dir: str | None = None, subframe_width: int | None = None, subframe_height: int | None = None, subframe_center_x: float = 0.5, subframe_center_y: float = 0.5)[source]#
Bases:
BaseActionConfigAid building a telescope pointing model. Astra itself does not build or maintain a pointing model.
Captures a spiral of points from zenith down to 30° altitude while avoiding positions within 20° of the Moon.
Plate solves each pointing and sends SyncToCoordinates commands to the mount. The receipt of these commands can be used to build a pointing model in the mount control software. The action can be configured to use the local star catalog for plate solving to speed up the process if the online Gaia catalog is unavailable or slow.
- FIELD_DESCRIPTIONS: ClassVar[dict[str, str]] = {'bin': 'Camera binning factor.', 'dark_subtraction': 'Enable dark subtraction using previously taken calibration frames of same exposure time in the same date folder.', 'dir': 'Directory path for saving images.', 'exptime': 'Exposure time for each pointing image.', 'filter': 'Filter to use for exposures.', 'focus_position': 'Absolute focus position override.', 'focus_shift': 'Focus offset relative to best focus.', 'n': 'Number of points to include in the model.', 'object': 'Descriptive label for the pointing run.', 'subframe_center_x': 'Horizontal subframe center (0=left, 1=right).', 'subframe_center_y': 'Vertical subframe center (0=top, 1=bottom).', 'subframe_height': 'Height of the requested subframe in binned pixels.', 'subframe_width': 'Width of the requested subframe in binned pixels.', 'use_local_db': 'Use local star catalog database for plate solving (faster).'}#
- EXAMPLE_SCHEDULE: ClassVar[dict] = {'action_type': 'pointing_model', 'action_value': {}, 'device_name': 'camera_name', 'end_time': '2025-02-01 00:00:00.000', 'start_time': '2025-01-01 00:00:00.000'}#
- validate()[source]#
Validate required fields and types of all fields.
- Raises:
ValueError – If required fields are missing.
TypeError – If any field has an incorrect type.
- class astra.action_configs.SelectionMethod(value)[source]#
Bases:
Enum- SINGLE = 'single'#
- MAXIMAL = 'maximal'#
- ANY = 'any'#
- classmethod from_string(key: str, logger=None) SelectionMethod[source]#
- class astra.action_configs.AutofocusCalibrationFieldConfig(maximal_zenith_angle: float | int | Angle | None = None, airmass_threshold: float = 1.01, g_mag_range: List[float | int] = <factory>, j_mag_range: List[float | int] = <factory>, fov_height: float | int = 0, fov_width: float | int = 0, selection_method: SelectionMethod | str = 'single', use_gaia: bool = True, observation_time: Time | None = None, maximal_number_of_stars: int = 100000, ra: float | int | None = None, dec: float | int | None = None, _coordinates: SkyCoord | None = None)[source]#
Bases:
BaseActionConfigConfiguration for automated autofocus calibration field selection.
- selection_method: SelectionMethod | str = 'single'#
- FIELD_DESCRIPTIONS: ClassVar[dict[str, str]] = {'airmass_threshold': 'Highest acceptable airmass for autofocus candidates.', 'dec': 'Fixed Declination used to bypass automatic selection.', 'fov_height': 'Height of the field of view in degrees.', 'fov_width': 'Width of the field of view in degrees.', 'g_mag_range': 'Inclusive Gaia G magnitude range to consider.', 'j_mag_range': 'Inclusive 2MASS J magnitude range to consider.', 'maximal_number_of_stars': 'Maximum number of stars to query or consider.', 'maximal_zenith_angle': 'Maximum zenith angle allowed when selecting autofocus fields.', 'observation_time': 'Observation time used when evaluating constraints.', 'ra': 'Fixed Right Ascension used to bypass automatic selection.', 'selection_method': 'Strategy for selecting stars (single, maximal, any).', 'use_gaia': 'Whether to rely on Gaia catalog sources.'}#
- classmethod from_dict(config_dict: dict, logger=None, default_dict: dict = {}) AutofocusCalibrationFieldConfig[source]#
Create an instance from a dictionary, merging with defaults.
- class astra.action_configs.AutofocusConfig(exptime: float | int = 3.0, filter: str | None = None, bin: int = 1, reduce_exposure_time: bool = False, search_range: List[int] | int | None = None, search_range_is_relative: bool = False, n_steps: List[int] = <factory>, n_exposures: List[int] | int = <factory>, decrease_search_range: bool = True, star_find_threshold: float | int = 5.0, fwhm: int = 8, percent_to_cut: int = 60, focus_measure_operator: str = 'HFR', save: bool = True, extremum_estimator: str = 'LOWESS', extremum_estimator_kwargs: dict[str, ~typing.Any]=<factory>, secondary_focus_measure_operators: List[str] = <factory>, calibration_field: AutofocusCalibrationFieldConfig = <factory>, save_path: Path | None = None, subframe_width: int | None = None, subframe_height: int | None = None, subframe_center_x: float = 0.5, subframe_center_y: float = 0.5)[source]#
Bases:
BaseActionConfigPerform an autofocus sweep to determine the optimal focus position.
- Steps:
- Select a suitable autofocus field (or use provided coordinates)
Opens observatory if not already done by a prior action
Move the telescope if needed
Capture images at different focus positions
Measure star sharpness in each image
Fit a curve to determine optimal focus
Save plots/results and save the best focus position in the observatory configuration
- calibration_field: AutofocusCalibrationFieldConfig#
- FIELD_DESCRIPTIONS: ClassVar[dict[str, str]] = {'bin': 'Camera binning factor.', 'decrease_search_range': 'Reduce the search range after each sweep.', 'exptime': 'Exposure time for focus frames in seconds.', 'extremum_estimator': 'Curve-fitting method used to determine the minimum (LOWESS, medianfilter, spline, rbf).', 'extremum_estimator_kwargs': 'Additional keyword overrides for the extremum estimator.', 'filter': 'Filter to use during autofocus procedure.', 'focus_measure_operator': 'Focus metric to optimize (e.g., hfr, gauss, tenengrad, fft, normalized_variance).', 'fwhm': 'DAOStarFinder FWHM of the Gaussian kernel in pixels.', 'n_exposures': 'Number of exposures at each focus position or an array specifying exposures for each sweep. If an integer is given, the same number of exposures is used for each sweep. If an array is given, the length of the array must match the number of sweeps. ', 'n_steps': 'Number of steps for each sweep.', 'percent_to_cut': 'Percentage of worst-performing focus samples to drop when shrinking the range.', 'reduce_exposure_time': 'Automatically shorten exposures to prevent saturation.', 'save': 'Persist the optimal focus position back into observatory configuration.', 'save_path': 'Directory override for saving autofocus results.', 'search_range': 'Range of focus positions to search. Accepts a single width or explicit bounds.', 'search_range_is_relative': 'Interpret search_range relative to the current focus position.', 'secondary_focus_measure_operators': 'Additional focus metrics to compute for diagnostics.', 'star_find_threshold': 'DAOStarFinder threshold for star detection.', 'subframe_center_x': 'Horizontal subframe center (0=left, 1=right).', 'subframe_center_y': 'Vertical subframe center (0=top, 1=bottom).', 'subframe_height': 'Height of the requested subframe in binned pixels.', 'subframe_width': 'Width of the requested subframe in binned pixels.'}#
- EXAMPLE_SCHEDULE: ClassVar[dict] = {'action_type': 'autofocus', 'action_value': {'exptime': 1.0, 'filter': 'V', 'n_exposures': [1, 1], 'n_steps': [30, 20], 'search_range': 1000, 'search_range_is_relative': True}, 'device_name': 'camera_name', 'end_time': '2025-02-01 00:00:00.000', 'start_time': '2025-01-01 00:00:00.000'}#
- classmethod from_dict(config_dict: dict, logger=None, default_dict: dict = {}) AutofocusConfig[source]#
Create an instance from a dictionary, merging with defaults.