"""
Modules for reading attributes from a FITS or ASCII file.
"""
import os
import warnings
from typing import Optional
import numpy as np
from astropy.io import fits
from typeguard import typechecked
from pynpoint.core.attributes import get_attributes
from pynpoint.core.processing import ReadingModule
[docs]class AttributeReadingModule(ReadingModule):
"""
Module for reading a list of values from a FITS or ASCII file and appending them as a non-static
attributes to a dataset.
"""
__author__ = 'Tomas Stolker'
@typechecked
def __init__(self,
name_in: str,
data_tag: str,
file_name: str,
attribute: str,
input_dir: Optional[str] = None,
overwrite: bool = False) -> None:
"""
Parameters
----------
name_in : str
Unique name of the module instance.
data_tag : str
Tag of the database entry to which the attribute is written.
file_name : str
Name of the input file with the attribute value. Should be equal in size to the number
of images in ``data_tag``. In case the ``file_name`` is ending with ``.fits``, then a
FITS file is read. Otherwise, a single column of values is expected in an ASCII file.
file_name : str
Name of the input file with a list of values.
attribute : str
Name of the attribute as to be written in the database.
input_dir : str, None
Input directory where the input file is located. If not specified the Pypeline default
directory is used.
overwrite : bool
Overwrite if the attribute is already exists.
Returns
-------
NoneType
None
"""
super().__init__(name_in, input_dir=input_dir)
self.m_data_port = self.add_output_port(data_tag)
self.m_file_name = file_name
self.m_attribute = attribute
self.m_overwrite = overwrite
[docs] @typechecked
def run(self) -> None:
"""
Run method of the module. Reads a list of values from a FITS or ASCII file and writes them
as non-static attribute to a dataset.
Returns
-------
NoneType
None
"""
print('Reading attribute data...', end='')
attributes = get_attributes()
if self.m_attribute not in attributes:
raise ValueError(f'\'{self.m_attribute}\' is not a valid attribute.')
if self.m_file_name.endswith('fits'):
values = fits.getdata(os.path.join(self.m_input_location, self.m_file_name))
else:
values = np.loadtxt(os.path.join(self.m_input_location, self.m_file_name),
dtype=attributes[self.m_attribute]['type'])
if values.ndim != 1:
raise ValueError(f'The input file {self.m_file_name} should contain a 1D list with '
f'attributes.')
status = self.m_data_port.check_non_static_attribute(self.m_attribute, values)
if status == 1:
self.m_data_port.add_attribute(self.m_attribute, values, static=False)
elif status == -1 and self.m_overwrite:
self.m_data_port.add_attribute(self.m_attribute, values, static=False)
elif status == -1 and not self.m_overwrite:
warnings.warn(f'The attribute \'{self.m_attribute}\' is already present. Set the '
f'\'overwrite\' parameter to True in order to overwrite the values with '
f'{self.m_file_name}.')
elif status == 0:
warnings.warn(f'The \'{self.m_attribute}\' attribute is already present and '
f'contains the same values as are present in {self.m_file_name}.')
print(' [DONE]')
self.m_data_port.close_port()
[docs]class ParangReadingModule(ReadingModule):
"""
Module for reading a list of parallactic angles from a FITS or ASCII file.
"""
__author__ = 'Tomas Stolker'
@typechecked
def __init__(self,
name_in: str,
data_tag: str,
file_name: str,
input_dir: Optional[str] = None,
overwrite: bool = False) -> None:
"""
Parameters
----------
name_in : str
Unique name of the module instance.
data_tag : str
Tag of the database entry to which the ``PARANG`` attribute is written.
file_name : str
Name of the input file with the parallactic angles (deg). Should be equal in size
to the number of images in ``data_tag``. In case the ``file_name`` is ending with
``.fits``, then a FITS file is read. Otherwise, a single column of values is expected
in an ASCII file.
input_dir : str, None
Input directory where the input file is located. If not specified the Pypeline default
directory is used.
overwrite : bool
Overwrite if the ``PARANG`` attribute already exists.
Returns
-------
NoneType
None
"""
super().__init__(name_in, input_dir=input_dir)
self.m_data_port = self.add_output_port(data_tag)
self.m_file_name = file_name
self.m_overwrite = overwrite
[docs] @typechecked
def run(self) -> None:
"""
Run method of the module. Reads the parallactic angles from a FITS or ASCII file and
writes the values as non-static attribute (``PARANG``) to the database tag.
Returns
-------
NoneType
None
"""
print('Reading parallactic angles...', end='')
if self.m_file_name.endswith('fits'):
parang = fits.getdata(os.path.join(self.m_input_location, self.m_file_name))
else:
parang = np.loadtxt(os.path.join(self.m_input_location, self.m_file_name))
print(' [DONE]')
if parang.ndim != 1:
raise ValueError(f'The input file {self.m_file_name} should contain a 1D data set with '
f'the parallactic angles.')
print(f'Number of angles: {parang.size}')
print(f'Rotation range: {parang[0]:.2f} -> {parang[-1]:.2f} deg')
status = self.m_data_port.check_non_static_attribute('PARANG', parang)
if status == 1:
self.m_data_port.add_attribute('PARANG', parang, static=False)
elif status == -1 and self.m_overwrite:
self.m_data_port.add_attribute('PARANG', parang, static=False)
elif status == -1 and not self.m_overwrite:
warnings.warn(f'The PARANG attribute is already present. Set the \'overwrite\' '
f'parameter to True in order to overwrite the values with '
f'{self.m_file_name}.')
elif status == 0:
warnings.warn(f'The PARANG attribute is already present and contains the same values '
f'as are present in {self.m_file_name}.')
self.m_data_port.close_port()
[docs]class WavelengthReadingModule(ReadingModule):
"""
Module for reading a list of wavelengths from a FITS or ASCII file.
"""
__author__ = 'Tomas Stolker'
@typechecked
def __init__(self,
name_in: str,
data_tag: str,
file_name: str,
input_dir: Optional[str] = None,
overwrite: bool = False) -> None:
"""
Parameters
----------
name_in : str
Unique name of the module instance.
data_tag : str
Tag of the database entry to which the ``WAVELENGTH`` attribute is written.
file_name : str
Name of the input file with the wavelengths (a.u.). Should be equal in size
to the number of images in ``data_tag``. In case the ``file_name`` is ending with
``.fits``, then a FITS file is read. Otherwise, a single column of values is expected
in an ASCII file.
input_dir : str, None
Input directory where the input file is located. If not specified the Pypeline default
directory is used.
overwrite : bool
Overwrite if the ``WAVELENGTH`` attribute already exists.
Returns
-------
NoneType
None
"""
super().__init__(name_in, input_dir=input_dir)
self.m_data_port = self.add_output_port(data_tag)
self.m_file_name = file_name
self.m_overwrite = overwrite
[docs] @typechecked
def run(self) -> None:
"""
Run method of the module. Reads the parallactic angles from a FITS or ASCII file and writes
the values as non-static attribute (``WAVELENGTH``) to the database tag.
Returns
-------
NoneType
None
"""
print('Reading wavelengths...', end='')
if self.m_file_name.endswith('fits'):
wavelength = fits.getdata(os.path.join(self.m_input_location, self.m_file_name))
else:
wavelength = np.loadtxt(os.path.join(self.m_input_location, self.m_file_name))
print(' [DONE]')
if wavelength.ndim != 1:
raise ValueError(f'The input file {self.m_file_name} should contain a 1D data set with '
f'the wavelengths.')
print(f'Number of wavelengths: {wavelength.size}')
print(f'Wavelength range: {wavelength[0]:.2f} - {wavelength[-1]:.2f}')
status = self.m_data_port.check_non_static_attribute('WAVELENGTH', wavelength)
if status == 1:
self.m_data_port.add_attribute('WAVELENGTH', wavelength, static=False)
elif status == -1 and self.m_overwrite:
self.m_data_port.add_attribute('WAVELENGTH', wavelength, static=False)
elif status == -1 and not self.m_overwrite:
warnings.warn(f'The WAVELENGTH attribute is already present. Set the \'overwrite\' '
f'parameter to True in order to overwrite the values with '
f'{self.m_file_name}.')
elif status == 0:
warnings.warn(f'The WAVELENGTH attribute is already present and contains the same '
f'values as are present in {self.m_file_name}.')
self.m_data_port.close_port()