astra.filename_templates#
This module provides two primary classes for generating filenames used by Astra when writing image files.
FilenameTemplates— simple templates using Pythonstr.format.JinjaFilenameTemplates— richer templates powered by Jinja2 when templates include template logic ({{ ... }}) at the cost of a slightly slower template rendering.
Key behavior#
Normalises
imagetypevalues to a standard set (light,bias,dark,flat,default).Validates templates against a set of test keyword arguments to catch formatting errors early.
Automatically selects the Jinja2-based implementation when input templates contain Jinja2 markers.
Quick example#
>>> from astra.image_handler import FilenameTemplates
>>> templates = FilenameTemplates()
>>> templates.render_filename(**templates.TEST_KWARGS)
'20240101/TestCamera_TestFilter_TestObject_300.123_2025-01-01_00-00-00.fits'
For details and advanced examples see the class docstrings for
FilenameTemplates and JinjaFilenameTemplates.
Example configurations#
Example str.format() configurations#
The following is the default used by ASTRA in observatory_config.yaml.
filename_templates:
object: "{action_date}/{device}_{filter_name}_{object_name}_{exptime:.3f}_{timestamp}.fits"
calibration: "{action_date}/{device}_{imagetype}_{exptime:.3f}_{timestamp}.fits"
flats: "{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits"
autofocus: "autofocus/{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits"
calibrate_guiding: "calibrate_guiding/{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits"
pointing_model: "pointing_model/{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits"
default: "{action_date}/{device}_{filter_name}_{imagetype}_{exptime:.3f}_{timestamp}.fits"
Example Jinja2 configurations#
The following code would be identical to the default used by ASTRA in
observatory_config.yaml, but using Jinja2 syntax. See the example in
JinjaFilenameTemplates for more advanced examples using Jinja2 logic.
filename_templates:
object: "{{ action_date }}/{{ device }}_{{ filter_name }}_{{ object_name }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits"
calibration: "{{ action_date }}/{{ device }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits"
flats: "{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits"
autofocus: "autofocus/{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits"
calibrate_guiding: "calibrate_guiding/{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits"
pointing_model: "pointing_model/{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits"
default: "{{ action_date }}/{{ device }}_{{ filter_name }}_{{ imagetype }}_{{ '%.3f'|format(exptime) }}_{{ timestamp }}.fits"
Classes
|
Filename templates using Python |
|
Filename templates using |
- 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:
objectFilename 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, thejinja2.Templateclass will be used instead, which allows more advanced logic.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'
Let’s create a template with more advanced logic using
jinja2.Templatesyntax. As the following example illustrates,jinja2.Templatesupports more complex logic, thanstr.format()syntax, at the cost of a slightly slower template rendering performance.>>> 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'
See also
JinjaFilenameTemplatesfor more advanced template logic usingjinja2.Template.- 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'#
- TEST_KWARGS = {'action_date': '20240101', 'action_datetime': datetime.datetime(2024, 1, 1, 0, 0), 'action_type': 'object', 'datetime': <module 'datetime' from '/home/runner/work/_temp/uv-python-dir/cpython-3.11.14-linux-x86_64-gnu/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']#
- classmethod from_dict(template_dict: dict[str, str]) FilenameTemplates[source]#
Create FilenameTemplates from a dictionary.
If the templates contain Jinja2 syntax, the JinjaFilenameTemplates class will be used instead.
Examples
Basic Example using
str.format()syntax:>>> from astra.image_handler import FilenameTemplates >>> templates = FilenameTemplates.from_dict( ... { ... "object": "{device}_{object_name}_{timestamp}.fits", ... "flats": "{device}_FLAT_{timestamp}.fits" ... } ... ) >>> type(templates) <class 'astra.filename_templates.FilenameTemplates'> >>> templates.render_filename( ... **templates.TEST_KWARGS | {"action_type": "object", "imagetype": "light"} ... ) 'TestCamera_TestObject_2025-01-01_00-00-00.fits' >>> templates.render_filename( ... **templates.TEST_KWARGS | {"action_type": "flats", "imagetype": "Flat Frame"} ... ) 'TestCamera_FLAT_2025-01-01_00-00-00.fits'
Example using
jinja2.Templatesyntax:>>> from astra.image_handler import FilenameTemplates >>> templates = FilenameTemplates.from_dict( ... { ... "object": "{{ device }}_{{ object_name }}_{{ timestamp }}.fits", ... "flats": "{{ device }}_FLAT_{{ timestamp }}.fits" ... } ... ) >>> type(templates) <class 'astra.filename_templates.JinjaFilenameTemplates'> >>> templates.render_filename( ... **templates.TEST_KWARGS | {"action_type": "object", "imagetype": "light"} ... ) 'TestCamera_TestObject_2025-01-01_00-00-00.fits' >>> templates.render_filename( ... **templates.TEST_KWARGS | {"action_type": "flats", "imagetype": "Flat Frame"} ... ) 'TestCamera_FLAT_2025-01-01_00-00-00.fits'
- 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:
FilenameTemplatesFilename templates using
jinja2.Templatesyntax.Examples
Let’s create a template with more advanced logic using
jinja2.Templatesyntax.>>> 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"#