# This module should be removed when we have a working gempy for new astrodata
import math
import re
from astropy import coordinates, units, _erfa
# The unitDict dictionary defines the factors for the function
# convert_units
unitDict = {
'meters': 0,
'micrometers': -6,
'nanometers': -9,
'angstroms': -10,
}
[docs]def isBlank(bstring):
return not (bstring and bstring.strip())
[docs]def removeComponentID(instr):
"""
Remove a component ID from a filter name
:param instr: the filter name
:type instr: string
:rtype: string
:return: the filter name with the component ID removed, or `None` if the input is not a valid string
"""
try:
m = re.match(r"(?P<filt>.*?)_G(.*?)", instr)
except TypeError:
return None
if not m:
# There was no "_G" in the input string. Return the input string
ret_str = str(instr)
else:
ret_str = str(m.group("filt"))
return ret_str
[docs]def sectionStrToIntList(section):
"""
Convert the input section in the form '[x1:x2,y1:y2]' to a tuple in the
form (x1 - 1, x2, y1 - 1, y2), where x1, x2, y1 and y2 are
integers. The values in the output tuple are converted to use 0-based and
non-inclusive indexing, making it compatible with numpy.
:param section: the section (in the form [x1:x2,y1:y2]) to be
converted to a tuple
:type section: string
:rtype: tuple
:return: the converted section as a tuple that uses 0-based and
non-inclusive in the form (x1 - 1, x2, y1 - 1, y2)
"""
# Strip the square brackets from the input section and then create a
# list in the form ['x1:x2','y1:y2']
xylist = section.strip('[]').split(',')
# Create variables containing the single x1, x2, y1 and y2 values
x1 = int(xylist[0].split(':')[0]) - 1
x2 = int(xylist[0].split(':')[1])
y1 = int(xylist[1].split(':')[0]) - 1
y2 = int(xylist[1].split(':')[1])
# Return the tuple in the form (x1 - 1, x2, y1 - 1, y2)
return (x1, x2, y1, y2)
[docs]def parse_percentile(string):
# Given the type of string that ought to be present in the site condition
# headers, this function returns the integer percentile number
#
# Is it 'Any' - ie 100th percentile?
if (string == "Any"):
return 100
# Is it a xx-percentile string?
try:
m = re.match("^(\d\d)-percentile$", string)
except TypeError:
return None
if m:
return int(m.group(1))
# We didn't recognise it
return None
[docs]def convert_units(input_units, input_value, output_units):
"""
:param input_units: the units of the value specified by input_value.
Possible values are 'meters', 'micrometers',
'nanometers' and 'angstroms'.
:type input_units: string
:param input_value: the input value to be converted from the
input_units to the output_units
:type input_value: float
:param output_units: the units of the returned value. Possible values
are 'meters', 'micrometers', 'nanometers' and
'angstroms'.
:type output_units: string
:rtype: float
:return: the converted value of input_value from input_units to
output_units
"""
# Determine the factor required to convert the input_value from the
# input_units to the output_units
power = unitDict[input_units] - unitDict[output_units]
factor = math.pow(10, power)
# Return the converted output value
if input_value is not None:
return input_value * factor
[docs]def toicrs(frame, ra, dec, equinox=2000.0, ut_datetime=None):
# Utility function. Converts and RA and Dec in the specified reference frame
# and equinox at ut_datetime into ICRS. This is used by the ra and dec descriptors.
# Assume equinox is julian calendar
equinox = 'J{}'.format(equinox)
# astropy doesn't understand APPT coordinates. However, it does understand
# CIRS coordinates, and we can convert from APPT to CIRS by adding the
# equation of origins to the RA. We can get that using ERFA.
# To proceed with this, we first let astopy construct the CIRS frame, so
# that we can extract the obstime object from that to pass to erfa.
appt_frame = (frame == 'APPT')
if frame == 'APPT':
frame = 'cirs'
if frame == 'FK5':
frame = 'fk5'
# Try this with the passed frame but, if it doesn't work, convert to "cirs"
# If that doesn't work, then raise an error
try:
coords = coordinates.SkyCoord(ra=ra*units.degree, dec=dec*units.degree,
frame=frame, equinox=equinox, obstime=ut_datetime)
except ValueError:
frame = 'cirs'
coords = coordinates.SkyCoord(ra=ra*units.degree, dec=dec*units.degree,
frame=frame, equinox=equinox, obstime=ut_datetime)
if appt_frame:
# Call ERFA.apci13 to get the Equation of Origin (EO).
# We just discard the astrom context return
astrom, eo = _erfa.apci13(coords.obstime.jd1, coords.obstime.jd2)
astrom = None
# eo comes back as a single element array in radians
eo = float(eo)
eo = eo * units.radian
# re-create the coords frame object with the corrected ra
coords = coordinates.SkyCoord(ra=coords.ra+eo, dec=coords.dec,
frame=coords.frame.name, equinox=coords.equinox,
obstime=coords.obstime)
# Now we can just convert to ICRS...
icrs = coords.icrs
# And return values in degrees
return (icrs.ra.degree, icrs.dec.degree)
[docs]def detsec_to_pixels(ad, detx, dety):
# Utility function to convert a location in "detector section pixels" to
# an image extension and real pixels on that extension.
xbin, ybin = ad.detector_x_bin(), ad.detector_y_bin()
for i, detsec in enumerate(ad.detector_section()):
if (detx < detsec.x1 or detx >= detsec.x2 or dety < detsec.y1 or
dety >= detsec.y2):
continue
datasec = ad.data_section()[i]
return (i, datasec.x1 + (detx - detsec.x1) // xbin,
datasec.y1 + (dety - detsec.y1) // ybin)
return None
### END temporary functions