Descriptors

Descriptors are regular methods that translate metadata from the raw data (e.g., cards from FITS headers) to values useful for the user, potentially doing some processing in between. They exist to:

  • Abstract the actual organization of the metadata, with arbitrarily complex processing to generate a useful value. These abstractions can be modified to be instrument-specific.

  • Provide a common interface to a set of instruments. This simplifies user training (no need to learn a different API for each instrument), and facilitates the reuse of code for pipelines and data processing.

  • They can be used to directly translate character-limited FITS header keywords into more descriptive names of arbitrary length.

Descriptors should be decorated using ~astrodata.astro_data_descriptor. The only function of this decorator is to ensure that the descriptor is marked as such: it does not alter its input or output in any way. This lets the user explore the API of an AstroData object via the ~astrodata.AstroData.descriptors property. Here’s an example of how we could use a descriptor to build a simple class on top of the AstroData base class:

Note

The above example is oversimplified, and would only work with a fits file containing these keywords. In practice, an AstroData extension like this would be specific to an instrument/file format that would be resolved using tags.

Descriptors can be decorated with returns_list() to eliminate the need to code some logic. Some descriptors return single values, while some return lists, one per extension. Typically, the former descriptors refer calues associated with an entire observation (and, for MEF files, are usually extracted from metadata in the PHU, such as airmass), while the latter descriptors where different extensions might return different values (and typically come from metadata in the individual HDUs, such as gain). A list is returned even if there is only one extension in the AstroData object, as this allows code to be written generically to iterate over the AstroData object and the descriptor return, without needing to know how many extensions there are.

The ~astrodata.core.returns_list decorator ensures that the descriptor returns an appropriate object (value or list), using the following rules to avoid unexpected behavior/confusing errors:

  • If the AstroData object is not a single slice:

    • If the undecorated descriptor returns a list, an exception is raised if the list is not the same length as the number of extensions.

    • If the undecorated descriptor returns a single value, the decorator will turn it into a list of the correct length by copying this value.

  • If the AstroData object is a single slice and the undecorated descriptor returns a list, only the first element is returned.

An example of the use of this decorator is the NIRI ~gemini_instruments.niri.AstroDataNiri.gain descriptor, which reads the value from a lookup table and simply returns it. A single value is only appropriate if the AstroData object is singly-sliced and the decorator ensures that a list is returned otherwise.