"""
Spectral-related functions.
"""
from gavo.base import unitconv
from gavo.base import osinter
from gavo.utils import excs
######################## specconv
[docs]def toStdSpecUnit(fromUnit):
"""returns a pair of (standard unit, factor) to turn fromUnit into
one of J, Hz, or m.
Unconvertable units raise a UfuncError.
"""
for stdUnit in ["J", "Hz", "m"]:
try:
factor = unitconv.computeConversionFactor(fromUnit, stdUnit)
except unitconv.IncompatibleUnits:
continue
return stdUnit, factor
raise unitconv.IncompatibleUnits(
f"{fromUnit} is not a spectral unit understood here")
SPEC_CONVERSION = {
("J", "m"): "h*c/(({expr})*{f})",
("J", "Hz"): "({expr})*{f}/h",
("J", "J"): "({expr})*{f}",
("Hz", "m"): "c/({expr})/{f}",
("Hz", "Hz"): "{f}*({expr})",
("Hz", "J"): "h*{f}*({expr})",
("m", "m"): "{f}*({expr})",
("m", "Hz"): "c/({expr})/{f}",
("m", "J"): "h*c/({expr})/{f}",}
[docs]def getSpecExpr(fromUnit, toUnit):
"""returns an expression that turns a value in fromUnit to one in toUnit.
The value in fromUnit is represented by a {} so you can just .format
the expression it is in into the resulting string.
"""
fromStd, fromFactor = toStdSpecUnit(fromUnit)
toStd, toFactor = toStdSpecUnit(toUnit)
convExpr = SPEC_CONVERSION[fromStd, toStd
].replace("h", str(unitconv.PLANCK_H)
).replace("c", str(unitconv.LIGHT_C))
return "{}/{}".format(
convExpr.format(f=fromFactor, expr="{}"),
toFactor)
[docs]def getSpecConverter(fromUnit, toUnit):
"""Returns a function converting spectral values in fromUnit to toUnit.
"""
return eval("lambda x: "+getSpecExpr(fromUnit, toUnit).format("x"))
########### our filter library
NM = 1e-9
[docs]def getFilterMap():
"""returns a pair for filter_def, aliases mapping.
This parses from the built-in data/filters.txt; filter_def maps
filter names to tuples of lower, central, long wavelength in metres.
(we may add further fields later, so it's safer to [:3] these results).
Aliases just maps common filter names to our canontical names
for these filters.
"""
filterMap, aliases = {}, {}
with osinter.openDistFile("data/filters.txt", encoding="utf-8") as f:
for index, line in enumerate(f):
if not line:
break
line = line.strip()
if line.startswith("#"):
continue
parts = line.split("\t")
primary = parts[0].strip()
if primary.startswith("="):
primary = primary[1:].strip()
for p in parts[1:]:
aliases[p.strip()] = primary
else:
try:
filterMap[primary] = (
float(parts[1])*NM, float(parts[2])*NM, float(parts[3])*NM)
except IndexError:
raise excs.ReportableError("Bad filtermap: filters.txt,"
" line %d."%(index+1))
return filterMap, aliases