# ---------------------------------------------------------#
# astroNN.gaia.gaia_shared: shared functions for apogee
# ---------------------------------------------------------#
import os
import warnings
import numpy as np
from astropy import units as u
from astroNN.config import MAGIC_NUMBER
default_parallax_unit = u.mas
# Sun's absmag in different Johnson/Cousins/2MASS/Sloan bands in Vega system
# sun abs mag in pass bands source: https://arxiv.org/pdf/1804.07788.pdf --> Table 3
solar_absmag_bands = {
"U": 5.61, # Johnson U
"B": 5.44, # Johnson B
"V": 4.81, # Johnson V
"R": 4.43, # Cousins R
"I": 4.10, # Cousins I
"J": 3.67, # 2MASS J
"H": 3.32, # 2MASS H
"K": 3.27, # 2MASS Ks
"Ks": 3.27, # 2MASS Ks
"u": 5.49, # SDSS u
"g": 5.23, # SDSS g
"r": 4.53, # SDSS r
"i": 4.19, # SDSS i
"z": 4.01, # SDSS z
"G": 4.67, # Gaia G, https://arxiv.org/pdf/1806.01953.pdf
}
def gaia_env():
"""
Get Gaia environment variable
:return: Path to Gaia Data
:rtype: str
:History: 2017-Oct-26 - Written - Henry Leung (University of Toronto)
"""
from astroNN.config import ENVVAR_WARN_FLAG
_GAIA = os.getenv("GAIA_TOOLS_DATA")
if _GAIA is None and ENVVAR_WARN_FLAG is True:
warnings.warn("Gaia environment variable GAIA_TOOLS_DATA not set")
return _GAIA
def gaia_default_dr(dr=None):
"""
Check if dr argument is provided, if none then use default
:param dr: Gaia DR
:type dr: Union[NoneType, int]
:return: Gaia DR
:rtype: int
:History: 2017-Oct-26 - Written - Henry Leung (University of Toronto)
"""
if dr is None:
dr = 3
warnings.warn(f"dr is not provided, using default dr={dr}")
else:
pass
return dr
[docs]
def mag_to_fakemag(mag, parallax, parallax_err=None):
"""
To convert apparent magnitude to astroNN fakemag, Magic Number will be preserved
:param mag: apparent magnitude
:type mag: Union[float, ndarray]
:param parallax: parallax (mas) or with astropy(can be distance with units) so astroNN will convert to appropriate units
:type parallax: Union[float, ndarray, astropy Quantity]
:param parallax_err: parallax_error (mas) or with astropy so astroNN will convert to appropriate units
:type parallax_err: Union[NoneType, float, ndarray, astropy Quantity]
:return: astroNN fakemag, with addition (with additional return of propagated error if parallax_err is provided)
:rtype: Union[float, ndarray]
:History: 2017-Oct-14 - Written - Henry Leung (University of Toronto)
"""
# Check unit if available
if isinstance(parallax, u.Quantity):
original_parallax_unit = parallax.unit
parallax = parallax.to(default_parallax_unit, equivalencies=u.parallax())
if parallax_err is not None:
if not isinstance(parallax_err, u.Quantity):
# assume parallax error carry the same original unit as parallax if no units detected
parallax_err = (
(parallax_err * original_parallax_unit)
.to(default_parallax_unit)
.value
)
if isinstance(parallax_err, u.Quantity):
parallax_err = parallax_err.to(default_parallax_unit).value
mag = np.array(mag)
parallax_unitless = np.array(
parallax
) # Take the value as we cant apply pow() to astropy unit
magic_idx = (
(parallax_unitless == MAGIC_NUMBER)
| (mag == MAGIC_NUMBER)
| (mag < -90.0)
| np.isnan(parallax_unitless)
| np.isnan(mag)
) # check for magic number
with (
warnings.catch_warnings()
): # suppress numpy Runtime warning caused by MAGIC_NUMBER
warnings.simplefilter("ignore")
fakemag = parallax_unitless * (10.0 ** (0.2 * mag))
if parallax_unitless.shape != (): # check if its only 1 element
fakemag[magic_idx] = MAGIC_NUMBER
else:
fakemag = MAGIC_NUMBER if magic_idx == [1] else fakemag
if parallax_err is None:
return fakemag
else:
fakemag_err = np.abs((parallax_err / parallax_unitless) * fakemag)
if parallax_unitless.shape != (): # check if its only 1 element
fakemag_err[magic_idx] = MAGIC_NUMBER
else:
fakemag_err = MAGIC_NUMBER if magic_idx == [1] else fakemag_err
return fakemag, fakemag_err
[docs]
def mag_to_absmag(mag, parallax, parallax_err=None):
"""
To convert apparent magnitude to absolute magnitude, Magic Number will be preserved
:param mag: apparent magnitude
:type mag: Union[float, ndarray]
:param parallax: parallax (mas) or with astropy (can be distance with units) so astroNN will convert to appropriate units
:type parallax: Union[float, ndarray, astropy Quantity]
:param parallax_err: parallax_error (mas) or with astropy so astroNN will convert to appropriate units
:type parallax_err: Union[NoneType, float, ndarray, astropy Quantity]
:return: absolute magnitude (with additional return of propagated error if parallax_err is provided)
:rtype: Union[float, ndarray]
:History: 2017-Oct-14 - Written - Henry Leung (University of Toronto)
"""
# Check unit if available
if isinstance(parallax, u.Quantity):
original_parallax_unit = parallax.unit
parallax = parallax.to(default_parallax_unit, equivalencies=u.parallax())
if parallax_err is not None:
if not isinstance(parallax_err, u.Quantity):
# assume parallax error carry the same original unit as parallax if no units detected
parallax_err = (
(parallax_err * original_parallax_unit)
.to(default_parallax_unit)
.value
)
if isinstance(parallax_err, u.Quantity):
parallax_err = parallax_err.to(default_parallax_unit).value
# warnings.warn(f'Please be advised that astroNN mag_to_absmag() expects {default_parallax_unit.name}, '
# f'astroNN has corrected the unit according to astropy unit framework')
# else:
# warnings.warn(f'Please be advised that astroNN mag_to_absmag expects parallax in {default_parallax_unit.name}')
mag = np.array(mag)
parallax_unitless = np.array(
parallax
) # Take the value as we cant apply log10 to astropy unit
magic_idx = (
(parallax_unitless == MAGIC_NUMBER)
| (mag == MAGIC_NUMBER)
| (mag < -90.0)
| np.isnan(parallax_unitless)
| np.isnan(mag)
) # check for magic number
with (
warnings.catch_warnings()
): # suppress numpy Runtime warning caused by MAGIC_NUMBER
warnings.simplefilter("ignore")
absmag = mag + 5.0 * (np.log10(parallax_unitless) - 2.0)
if parallax_unitless.shape != (): # check if its only 1 element
absmag[magic_idx] = MAGIC_NUMBER
else:
absmag = MAGIC_NUMBER if magic_idx == [1] else absmag
if parallax_err is None:
return absmag
else:
absmag_err = 5.0 * np.abs(parallax_err / (parallax_unitless * absmag))
if parallax_unitless.shape != (): # check if its only 1 element
absmag_err[magic_idx] = MAGIC_NUMBER
else:
absmag_err = MAGIC_NUMBER if magic_idx == [1] else absmag_err
return absmag, absmag_err
# noinspection PyUnresolvedReferences
[docs]
def absmag_to_pc(absmag, mag):
"""
To convert absolute magnitude to parsec, Magic Number will be preserved
:param absmag: absolute magnitude
:type absmag: Union[float, ndarray]
:param mag: apparent magnitude
:type mag: Union[float, ndarray]
:return: parsec
:rtype: astropy Quantity
:History: 2017-Nov-16 - Written - Henry Leung (University of Toronto)
"""
absmag = np.array(absmag)
mag = np.array(mag)
magic_idx = (
(absmag == MAGIC_NUMBER)
| (mag == MAGIC_NUMBER)
| np.isnan(absmag)
| np.isnan(mag)
) # check for magic number
with (
warnings.catch_warnings()
): # suppress numpy Runtime warning caused by MAGIC_NUMBER
warnings.simplefilter("ignore")
pc = 10.0 ** (((mag - absmag) / 5.0) + 1.0)
if absmag.shape != (): # check if its only 1 element
pc[magic_idx] = MAGIC_NUMBER
return pc * u.parsec
else:
return (MAGIC_NUMBER if magic_idx == [1] else pc) * u.parsec
[docs]
def fakemag_to_absmag(fakemag):
"""
To convert fakemag to absmag, Magic Number will be preserved
:param fakemag: eastroNN fakemag
:type fakemag: Union[float, ndarray]
:return: absolute magnitude
:rtype: Union[float, ndarray]
:History: 2018-Jan-31 - Written - Henry Leung (University of Toronto)
"""
fakemag = np.array(fakemag)
# treat non-negative fakemag as MAGIC_NUMBER
magic_idx = (
(fakemag == MAGIC_NUMBER) | (fakemag <= 0.0) | np.isnan(fakemag)
) # check for magic number and negative fakemag
with (
warnings.catch_warnings()
): # suppress numpy Runtime warning caused by MAGIC_NUMBER
warnings.simplefilter("ignore")
absmag = 5.0 * (np.log10(fakemag) - 2.0)
if absmag.shape != (): # check if its only 1 element
absmag[magic_idx] = MAGIC_NUMBER
else: # for float
absmag = MAGIC_NUMBER if magic_idx == [1] else absmag
return absmag
[docs]
def absmag_to_fakemag(absmag):
"""
To convert absmag to fakemag, Magic Number will be preserved
:param absmag: absolute magnitude
:type absmag: Union[float, ndarray]
:return: astroNN fakemag
:rtype: Union[float, ndarray]
:History: 2018-Jan-31 - Written - Henry Leung (University of Toronto)
"""
absmag = np.array(absmag)
magic_idx = (absmag == MAGIC_NUMBER) | np.isnan(absmag) # check for magic number
with (
warnings.catch_warnings()
): # suppress numpy Runtime warning caused by MAGIC_NUMBER
warnings.simplefilter("ignore")
fakemag = 10.0 ** (0.2 * absmag + 2.0)
if fakemag.shape != (): # check if its only 1 element
fakemag[magic_idx] = MAGIC_NUMBER
else: # for float
fakemag = MAGIC_NUMBER if magic_idx == [1] else fakemag
return fakemag
# noinspection PyUnresolvedReferences
[docs]
def fakemag_to_pc(fakemag, mag, fakemag_err=None):
"""
To convert fakemag to parsec, Magic Number will be preserved
:param fakemag: astroNN fakemag
:type fakemag: Union[float, ndarray]
:param mag: apparent magnitude
:type mag: Union[float, ndarray]
:param fakemag_err: Optional, fakemag_err
:type fakemag_err: Union[NoneType, float, ndarray]
:return: array of pc with astropy Quantity (with additional return of propagated error if fakemag_err is provided)
:rtype: astropy Quantity
:History: 2018-Jan-31 - Written - Henry Leung (University of Toronto)
"""
fakemag = np.array(fakemag)
mag = np.array(mag)
# treat non-positive fakemag as MAGIC_NUMBER, check for magic number and negative fakemag
magic_idx = (
(fakemag == MAGIC_NUMBER)
| (mag == MAGIC_NUMBER)
| (fakemag <= 0.0)
| np.isnan(fakemag)
| np.isnan(mag)
)
with (
warnings.catch_warnings()
): # suppress numpy Runtime warning caused by MAGIC_NUMBER
warnings.simplefilter("ignore")
pc = 1000.0 * (10.0 ** (0.2 * mag)) / fakemag
if fakemag.shape != (): # check if its only 1 element
pc[magic_idx] = MAGIC_NUMBER
else: # for float
pc = MAGIC_NUMBER if magic_idx == [1] else pc
if fakemag_err is None:
return pc * u.parsec
else:
with (
warnings.catch_warnings()
): # suppress numpy Runtime warning caused by MAGIC_NUMBER
warnings.simplefilter("ignore")
pc_err = (fakemag_err / fakemag) * pc
if fakemag.shape != (): # check if its only 1 element
pc_err[magic_idx] = MAGIC_NUMBER
else: # for float
pc_err = MAGIC_NUMBER if magic_idx == [1] else pc_err
return pc * u.parsec, pc_err * u.parsec
# noinspection PyUnresolvedReferences
[docs]
def fakemag_to_parallax(fakemag, mag, fakemag_err=None):
"""
To convert fakemag to parallax, Magic Number will be preserved
:param fakemag: astroNN fakemag
:type fakemag: Union[float, ndarray]
:param mag: apparent magnitude
:type mag: Union[float, ndarray]
:param fakemag_err: Optional, fakemag_err
:type fakemag_err: Union[NoneType, float, ndarray]
:return: array of parallax in mas with astropy Quantity (with additional return of propagated error if fakemag_err is provided)
:rtype: astropy Quantity
:History: 2018-Aug-11 - Written - Henry Leung (University of Toronto)
"""
fakemag = np.array(fakemag)
mag = np.array(mag)
# treat non-positive fakemag as MAGIC_NUMBER, check for magic number and negative fakemag
magic_idx = (
(fakemag == MAGIC_NUMBER)
| (mag == MAGIC_NUMBER)
| (fakemag <= 0.0)
| np.isnan(fakemag)
| np.isnan(mag)
)
with (
warnings.catch_warnings()
): # suppress numpy Runtime warning caused by MAGIC_NUMBER
warnings.simplefilter("ignore")
parallax = fakemag / (10.0 ** (0.2 * mag))
if fakemag.shape != (): # check if its only 1 element
parallax[magic_idx] = MAGIC_NUMBER
else: # for float
parallax = MAGIC_NUMBER if magic_idx == [1] else parallax
if fakemag_err is None:
return parallax * u.mas
else:
with (
warnings.catch_warnings()
): # suppress numpy Runtime warning caused by MAGIC_NUMBER
warnings.simplefilter("ignore")
parallax_err = (fakemag_err / fakemag) * parallax
if fakemag.shape != (): # check if its only 1 element
parallax_err[magic_idx] = MAGIC_NUMBER
else: # for float
parallax_err = MAGIC_NUMBER if magic_idx == [1] else parallax_err
return parallax * u.mas, parallax_err * u.mas
[docs]
def fakemag_to_logsol(fakemag, band="K"):
"""
| To convert fakemag to log10 solar luminosity, negative fakemag will be converted to MAGIC_NUMBER because of
| fakemag cannot be negative in physical world
:param fakemag: astroNN fakemag
:type fakemag: Union[float, ndarray]
:param band: band of your fakemag to use with
:type band: str(['U', 'B', 'V', 'R', 'I', 'J', 'H', 'K','u', 'g', 'r', 'i', 'z'])
:return: log solar luminosity
:rtype: Union[float, ndarray]
:History: 2018-May-06 - Written - Henry Leung (University of Toronto)
"""
fakemag = np.array(fakemag)
magic_idx = (
(fakemag == MAGIC_NUMBER) | (fakemag <= 0.0) | np.isnan(fakemag)
) # check for magic number
with (
warnings.catch_warnings()
): # suppress numpy Runtime warning caused by MAGIC_NUMBER
warnings.simplefilter("ignore")
log10sol_lum = np.array(
0.4 * (solar_absmag_bands[band] - fakemag_to_absmag(fakemag))
)
if log10sol_lum.shape != (): # check if its only 1 element
log10sol_lum[magic_idx] = MAGIC_NUMBER
else: # for float
log10sol_lum = MAGIC_NUMBER if magic_idx == [1] else log10sol_lum
return log10sol_lum
[docs]
def absmag_to_logsol(absmag, band="K"):
"""
To convert absmag to log10 solar luminosity
:param absmag: absolute magnitude
:type absmag: Union[float, ndarray]
:param band: band of your absmag to use with
:type band: str(['U', 'B', 'V', 'R', 'I', 'J', 'H', 'K','u', 'g', 'r', 'i', 'z'])
:return: log solar luminosity
:rtype: Union[float, ndarray]
:History: 2018-May-06 - Written - Henry Leung (University of Toronto)
"""
absmag = np.array(absmag)
magic_idx = (absmag == MAGIC_NUMBER) | np.isnan(absmag) # check for magic number
with (
warnings.catch_warnings()
): # suppress numpy Runtime warning caused by MAGIC_NUMBER
warnings.simplefilter("ignore")
log10sol_lum = np.array(0.4 * (solar_absmag_bands[band] - absmag))
if log10sol_lum.shape != (): # check if its only 1 element
log10sol_lum[magic_idx] = MAGIC_NUMBER
else: # for float
log10sol_lum = MAGIC_NUMBER if magic_idx == [1] else log10sol_lum
return log10sol_lum
[docs]
def logsol_to_fakemag(logsol, band="K"):
"""
| To convert log10 solar luminosity to fakemag, negative fakemag will be converted to MAGIC_NUMBER because of fakemag
| cannot be negative in physical world
:param logsol: log solar luminosity
:type logsol: Union[float, ndarray]
:param band: band of your fakemag to use with
:type band: str(['U', 'B', 'V', 'R', 'I', 'J', 'H', 'K','u', 'g', 'r', 'i', 'z'])
:return: astroNN fakemag
:rtype: Union[float, ndarray]
:History: 2018-May-06 - Written - Henry Leung (University of Toronto)
"""
logsol = np.array(logsol)
magic_idx = (logsol == MAGIC_NUMBER) | np.isnan(logsol) # check for magic number
with (
warnings.catch_warnings()
): # suppress numpy Runtime warning caused by MAGIC_NUMBER
warnings.simplefilter("ignore")
fakemag = np.array(absmag_to_fakemag(solar_absmag_bands[band] - logsol / 0.4))
if fakemag.shape != (): # check if its only 1 element
fakemag[magic_idx] = MAGIC_NUMBER
else: # for float
fakemag = MAGIC_NUMBER if magic_idx == [1] else fakemag
return fakemag
[docs]
def logsol_to_absmag(logsol, band="K"):
"""
| To convert log10 solar luminosity to absmag, negative fakemag will be converted to MAGIC_NUMBER because of fakemag
| cannot be negative in physical world
:param logsol: log solar luminosity
:type logsol: Union[float, ndarray]
:param band: band of your absmag to use with
:type band: str(['U', 'B', 'V', 'R', 'I', 'J', 'H', 'K','u', 'g', 'r', 'i', 'z'])
:return: absmag
:rtype: Union[float, ndarray]
:History: 2018-May-06 - Written - Henry Leung (University of Toronto)
"""
logsol = np.array(logsol)
magic_idx = (logsol == MAGIC_NUMBER) | np.isnan(logsol) # check for magic number
with (
warnings.catch_warnings()
): # suppress numpy Runtime warning caused by MAGIC_NUMBER
warnings.simplefilter("ignore")
absmag = solar_absmag_bands[band] - logsol / 0.4
if absmag.shape != (): # check if its only 1 element
absmag[magic_idx] = MAGIC_NUMBER
else: # for float
absmag = MAGIC_NUMBER if magic_idx == [1] else absmag
return absmag
# noinspection PyUnresolvedReferences
[docs]
def fakemag_to_mag(fakemag, pc, pc_err=None):
"""
To convert apparent magnitude to astroNN fakemag, Magic Number will be preserved
:param fakemag: fakemag
:type fakemag: Union[float, ndarray]
:param pc: parsec or with astropy (can be parallax with units) so astroNN will convert to appropriate units
:type pc: Union[float, ndarray, astropy Quantity]
:param pc_error: parsec uncertainty or with astropy so astroNN will convert to appropriate units
:type pc_error: Union[NoneType, float, ndarray, astropy Quantity]
:return: astroNN fakemag, with addition (with additional return of propagated error if parallax_err is provided)
:rtype: Union[float, ndarray]
:History: 2018-Aug-1 - Written - Henry Leung (University of Toronto)
"""
# Check unit if available
if isinstance(pc, u.Quantity):
original_parallax_unit = pc.unit
pc = pc.to(u.parsec, equivalencies=u.parallax())
if pc_err is not None:
if not isinstance(pc_err, u.Quantity):
# assume parallax error carry the same original unit as parallax if no units detected
pc_err = (pc_err * original_parallax_unit).to(u.parsec).value
if isinstance(pc_err, u.Quantity):
pc_err = pc_err.to(u.parsec).value
fakemag = np.array(fakemag)
pc_unitless = np.array(pc) # Take the value as we cant apply pow() to astropy unit
magic_idx = (
(pc_unitless == MAGIC_NUMBER)
| (fakemag == MAGIC_NUMBER)
| (fakemag <= 0.0)
| np.isnan(pc_unitless)
| np.isnan(fakemag)
) # check for magic number
with (
warnings.catch_warnings()
): # suppress numpy Runtime warning caused by MAGIC_NUMBER
warnings.simplefilter("ignore")
mag = np.log10((pc_unitless / 1000) * fakemag) / 0.2
if pc_unitless.shape != (): # check if its only 1 element
mag[magic_idx] = MAGIC_NUMBER
else:
fakemag = MAGIC_NUMBER if magic_idx == [1] else fakemag
if pc_err is None:
return mag
else:
mag_err = np.abs((pc_err / pc) * fakemag)
if pc_unitless.shape != (): # check if its only 1 element
mag_err[magic_idx] = MAGIC_NUMBER
else:
mag_err = MAGIC_NUMBER if magic_idx == [1] else mag_err
return mag, mag_err
[docs]
def extinction_correction(mag, extinction):
"""
To correct magnitude with extinction, this function assumes extinction is at the same wavelength as the magnitude
you have provided
:param mag: apparent magnitude
:type mag: Union[float, ndarray]
:param extinction: extinction
:type extinction: Union[float, ndarray]
:return: corrected magnitude
:rtype: Union[float, ndarray]
:History: 2018-May-13 - Written - Henry Leung (University of Toronto)
"""
mag = np.array(mag)
extinction = np.array(extinction)
extinction[extinction < -1.0] = (
0.0 # extinction cannot be that negative, if yes then assume no extinction
)
magic_idx = (
(mag == MAGIC_NUMBER) | (mag < -90.0) | np.isnan(mag)
) # check for magic number
mag_ec = mag - extinction
if mag_ec.shape != (): # check if its only 1 element
mag_ec[magic_idx] = MAGIC_NUMBER
return mag_ec
else:
return MAGIC_NUMBER if magic_idx == [1] else mag_ec