astra.filename_templates#

Astronomical image processing and FITS file management utilities.

This module provides functions for handling astronomical images captured from observatory cameras. It manages image directory creation, data type conversion, and FITS file saving with proper headers and metadata.

Key features: - Automatic directory creation with date-based naming - Image data type conversion and array reshaping for FITS compatibility - FITS file saving with comprehensive metadata and WCS support - Intelligent filename generation based on observation parameters

The module handles various image types including light frames, bias frames, dark frames, and calibration images, ensuring proper metadata preservation and file organization for astronomical data processing pipelines.

Classes

FilenameTemplates([object, calibration, ...])

Filename templates using Python str.format() syntax.

JinjaFilenameTemplates(object, calibration, ...)

Filename templates using Jinja2 syntax.

class astra.filename_templates.FilenameTemplates(object: str = '{action_date}/{device}_{filter_name}_{object_name}_{exptime:.3f}_{timestamp}.fits', calibration: str = '{action_date}/{device}_{imagetype}_{exptime:.3f}_{timestamp}.fits', flats: str = '{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits', autofocus: str = 'autofocus/{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits', calibrate_guiding: str = 'calibrate_guiding/{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits', pointing_model: str = 'pointing_model/{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits', default: str = '{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits')[source]#

Bases: object

Filename templates using Python str.format() syntax.

The templates can be customised by passing a dictionary to FilenameTemplates.from_dict(), which is the constructor used in astra. If the templates contain Jinja2 syntax, the JinjaFilenameTemplates class will be used instead, which allows more advanced logic (see examples below).

Examples:

>>> from astra.image_handler import FilenameTemplates

Default templates >>> templates = FilenameTemplates() >>> templates.render_filename( … **templates.TEST_KWARGS | {“action_type”: “object”, “imagetype”: “light”} … ) ‘20240101/TestCamera_TestFilter_TestObject_300.123_2025-01-01_00-00-00.fits’

Lets create a template with more advanced logic using using Jinja2 >>> flat_template = ( … # use subdirs … “{{ imagetype.split(‘_’)[0].upper() }}/{{ device }}_” … # customise timestamp format … + “{{ datetime_timestamp.strftime(‘%Y%m%d_%H%M%S.%f’)[:-5] }}_” … # Add custom logic … + “{{ ‘Dusk’ if (datetime_timestamp + datetime.timedelta(hours=5)).hour > 12 else ‘Dawn’ }}” … + “_sequence_{{ ‘%03d’|format(sequence_counter) }}” … + “.fits” … ) >>> filename_templates = FilenameTemplates.from_dict( … {“flats”: flat_template} … ) >>> filename_templates.render_filename( … **filename_templates.TEST_KWARGS | { … “action_type”: “flats”, “imagetype”: “Flat Frame” … } … ) ‘FLAT/TestCamera_20250101_000000.0_Dawn_sequence_000.fits’

object: str = '{action_date}/{device}_{filter_name}_{object_name}_{exptime:.3f}_{timestamp}.fits'#
calibration: str = '{action_date}/{device}_{imagetype}_{exptime:.3f}_{timestamp}.fits'#
flats: str = '{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits'#
autofocus: str = 'autofocus/{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits'#
calibrate_guiding: str = 'calibrate_guiding/{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits'#
pointing_model: str = 'pointing_model/{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits'#
default: str = '{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits'#
TEST_KWARGS = {'action_date': '20240101', 'action_datetime': datetime.datetime(2024, 1, 1, 0, 0), 'action_type': 'object', 'datetime': <module 'datetime' from '/opt/buildhome/.local/share/mise/installs/python/3.11.14/lib/python3.11/datetime.py'>, 'datetime_timestamp': datetime.datetime(2025, 1, 1, 0, 0), 'device': 'TestCamera', 'exptime': 300.123456, 'filter_name': 'TestFilter', 'imagetype': 'light', 'object_name': 'TestObject', 'sequence_counter': 0, 'timestamp': '2025-01-01_00-00-00'}#
SUPPORTED_ACTION_TYPES = ['object', 'calibration', 'flats', 'autofocus', 'calibrate_guiding', 'pointing_model', 'default']#
SUPPORTED_IMAGETYPES = ['light', 'bias', 'dark', 'flat', 'default']#
property SUPPORTED_ARGS: set[str]#
classmethod from_dict(template_dict: dict[str, str]) FilenameTemplates[source]#
render_filename(action_type, **kwargs) str[source]#
class astra.filename_templates.JinjaFilenameTemplates(object: str = "{{ action_date }}/{{ device }}_{{ filter_name }}_{{ object_name }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits", calibration: str = "{{ action_date }}/{{ device }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits", flats: str = "{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits", autofocus: str = "autofocus/{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits", calibrate_guiding: str = "calibrate_guiding/{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits", pointing_model: str = "pointing_model/{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits", default: str = "{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits", _compiled_templates: dict[str, ~jinja2.environment.Template] = <factory>)[source]#

Bases: FilenameTemplates

Filename templates using Jinja2 syntax.

Examples:

Lets create a template with more advanced logic using using Jinja2 >>> from astra.image_handler import JinjaFilenameTemplates >>> flat_template = ( … # use subdirs … “{{ imagetype.split(‘_’)[0].upper() }}/{{ device }}_” … # customise timestamp format … + “{{ datetime_timestamp.strftime(‘%Y%m%d_%H%M%S.%f’)[:-5] }}_” … # Add custom logic … + “{{ ‘Dusk’ if (datetime_timestamp + datetime.timedelta(hours=5)).hour > 12 else ‘Dawn’ }}” … + “_sequence_{{ ‘%03d’|format(sequence_counter) }}” … + “.fits” … ) >>> filename_templates = FilenameTemplates.from_dict( … {“flats”: flat_template} … ) >>> filename_templates.render_filename( … **filename_templates.TEST_KWARGS | { … “action_type”: “flats”, “imagetype”: “Flat Frame” … } … ) ‘FLAT/TestCamera_20250101_000000.0_Dawn_sequence_000.fits’

object: str = "{{ action_date }}/{{ device }}_{{ filter_name }}_{{ object_name }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits"#
calibration: str = "{{ action_date }}/{{ device }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits"#
flats: str = "{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits"#
autofocus: str = "autofocus/{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits"#
calibrate_guiding: str = "calibrate_guiding/{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits"#
pointing_model: str = "pointing_model/{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits"#
default: str = "{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits"#
render_filename(action_type, **kwargs) str[source]#