Source code for pdrtpy.utils.helpers
"""
General helper utilities for PDR Toolbox.
"""
import warnings
from copy import deepcopy
from pdrtpy.utils.fits import comment
[docs]
def warn(cls, msg):
"""Issue a warning.
Parameters
----------
cls : class
The calling class.
msg : str
The warning message.
"""
# use stacklevel=3 so we get a reference to the caller of warn().
warnings.warn(cls.__class__.__name__ + ": " + msg, stacklevel=3)
[docs]
def is_image(image):
"""Check if a Measurement is an image.
To be an image it must have a header with axes keywords and a WCS.
This is to distinguish Measurements that have a data array with more
than one member from a true image.
Parameters
----------
image : :class:`astropy.io.fits.ImageHDU`, :class:`astropy.nddata.CCDData`, or :class:`~pdrtpy.measurement.Measurement`
The image to check. It must have a :class:`numpy.ndarray` data member
and :class:`astropy.units.Unit` unit member or a header BUNIT keyword.
Returns
-------
bool
True if it is an image, False otherwise.
"""
if getattr(image, "header", None) is None or getattr(image, "wcs", None) is None:
return False
if image.wcs.naxis is None or image.wcs.wcs is None:
return False
if image.wcs.naxis == 0: # naxis=1 ok -- a 1-D image is still an image.
return False
if image.wcs.wcs.ctype is None:
return False
return True
[docs]
def is_ratio(identifier):
"""Is the identifier a ratio (as opposed to an intensity).
Returns
-------
bool
"""
# find() returns -1 if char not found.
# in our case, also rule out that the / is in the zeroth position.
return identifier.find("/") > 0
[docs]
def is_even(number):
"""Check if number is even.
Parameters
----------
number : float
A number.
Returns
-------
bool
True if even, False otherwise.
"""
return abs(number) % 2 == 0
[docs]
def is_odd(number):
"""Check if number is odd.
Parameters
----------
number : float
A number.
Returns
-------
bool
True if odd, False otherwise.
"""
return not is_even(number)
def _has_substring(s, ids):
return any([s in c for c in ids])
def _has_H2(ids):
return _has_substring("H2", ids)
def _trim_to_H2(image):
"""H2 models in wk2006 are a smaller grid 17x17 vs 25x29. So when performing operations
involving other models, we have to trim the other models to 17x17; log(n,G0) from 1 to 5.
Parameters
----------
image : :class:`~pdrtpy.measurement.Measurement`
The model to trim.
Returns
-------
:class:`~pdrtpy.measurement.Measurement`
The trimmed model.
"""
f = deepcopy(image)
# Slice the WCS. Note this is in numpy array order, not WCS axis order
f.wcs = f.wcs[6:23, 0:17]
f.data = f.data[6:23, 0:17]
f.meta["NAXIS1"] = 17
f.meta["NAXIS2"] = 17
comment("Trimmed model", f)
return f
def _trim_all_to_H2(models):
"""H2 models in wk2006 are a smaller grid 17x17 vs 25x29. So when performing operations
involving other models, we have to trim the other models to 17x17; log(n,G0) from 1 to 5.
Parameters
----------
models : list or dict of :class:`~pdrtpy.measurement.Measurement`
Models to trim.
"""
if type(models) is dict:
for id in models:
if "H2" not in id:
models[id] = _trim_to_H2(models[id])
else:
# have to iterate over index to ensure "pass by reference"
# if we did for m in models: m = ..., then models
# remains unchanged at end of function. Wheee, python!
for j in range(len(models)):
if "H2" not in models[j].id:
models[j] = _trim_to_H2(models[j])