import os
import numpy as np
from sora.config.decorators import deprecated_alias
__all__ = ['calc_fresnel', 'calc_magnitude_drop']
[docs]
@deprecated_alias(lambida='bandpass') # remove this line for v1.0
def calc_fresnel(distance, bandpass):
"""Calculates the Fresnel scale.
Fresnel Scale = square root of half the multiplication of wavelength and
object distance.
Parameters
----------
distance : `int`, `float` array
Distances, in km.
bandpass : `int`, `float`, array
Wavelength, in km.
Returns
-------
fresnel_scale : `float`, array
Fresnel scale, in km.
"""
return np.sqrt(bandpass * distance / 2)
def bar_fresnel(X, X01, X02, fresnel_scale, opacity):
"""Returns the modelled light curve considering fresnel diffraction.
Parameters
----------
X : array
Array with time values converted in km using the event velocity.
X01 : `int`, `float`
Immersion time converted in km using the event velocity.
X02 `int`, `float`
Emersion time converted in km using the event velocity.
fresnel_scale : `int`, `float`
Fresnel scale, in km.
opacity : `int`, `float`
Opacity. Opaque = 1.0, transparent = 0.0.
Returns
-------
flux_fresnel : array
The light curve with fresnel diffraction.
"""
import scipy.special as scsp
# Converting from km to units of fresnel scale
x = X / fresnel_scale
x01 = X01 / fresnel_scale
x02 = X02 / fresnel_scale
# Fresnel diffraction parameters
x1 = x - x01
x2 = x - x02
s1, c1 = scsp.fresnel(x1)
s2, c2 = scsp.fresnel(x2)
cc = c1 - c2
ss = s1 - s2
r_ampli = - (cc + ss) * (opacity / 2.)
i_ampli = (cc - ss) * (opacity / 2.)
# Determining the flux considering fresnel diffraction
flux_fresnel = (1.0 + r_ampli) ** 2 + i_ampli ** 2
return flux_fresnel
def fit_pol(x, y, deg):
"""Fits a n-degree polynomial to the data.
Parameters
----------
x : `array`
x-values.
y : `array`
y-values.
deg : `int`
Degree of the polynomial.
Returns
-------
param : array
Array with the fitted values.
param_err : array
Array with the errors of the fitted values.
"""
from scipy.odr import odrpack as odr
from scipy.odr import models
func = models.polynomial(deg)
mydata = odr.Data(x, y)
myodr = odr.ODR(mydata, func, maxit=200)
myodr.set_job(fit_type=2)
fit = myodr.run()
param = fit.beta[::-1]
param_err = fit.sd_beta[::-1]
return param, param_err
[docs]
def calc_magnitude_drop(mag_star, mag_obj):
"""Determines the magnitude drop of the occultation.
Parameters
----------
mag_star : `int`, `float`
Star magnitude.
mag_obj : `int`, `float`
Object apparent magnitude to the date.
Returns
-------
mag_drop : `float`
Magnitude drop for the given magnitudes.
bottom_flux : `float`
Normalized bottom flux for the given magnitudes.
"""
contrast = 1 / (1 + (10 ** ((mag_star - mag_obj) * 0.4)))
mag_combined = mag_star - (2.5 * (np.log10(1 / contrast)))
mag_drop = mag_obj - mag_combined
bottom_flux = 10 ** ((mag_combined - mag_obj) * 0.4)
mag_drop = mag_drop
bottom_flux = bottom_flux
return mag_drop, bottom_flux
def read_lc_file(lc_file, usecols=None, skiprows=0):
"""Reads light curve data from a file.
Parameters
----------
file : `str`, required
A file with the time and flux in the first and second columns, respectively.
A third column with error in flux can also be given.
usecols : `int`, `tuple`, array, optional
Which columns to read, with the first being the time, the seconds the
flux and third the flux error.
skiprows : `int`, optional, default=0
Skip the first skiprows lines, including comments.
Returns
-------
:rtype: : (array, array, array)
"""
from astropy.io import ascii
from astropy.time import Time
if not os.path.isfile(lc_file):
raise ValueError('{} not found'.format(lc_file))
if usecols is not None:
if len(usecols) == 2:
try:
time, flux = np.loadtxt(lc_file, usecols=usecols, skiprows=skiprows, unpack=True)
return time, flux
except:
pass
elif len(usecols) == 3:
try:
time, flux, dflux = np.loadtxt(lc_file, usecols=usecols, skiprows=skiprows, unpack=True)
return time, flux, dflux
except:
pass
else:
raise ValueError('usecols should have 2 or 3 values')
else:
try:
time, flux = np.loadtxt(lc_file, usecols=[0, 1], skiprows=skiprows, unpack=True)
return time, flux
except:
pass
try:
time, flux, dflux = np.loadtxt(lc_file, usecols=[0, 1, 2], skiprows=skiprows, unpack=True)
return time, flux, dflux
except:
pass
try:
lc_data = ascii.read(lc_file, data_start=skiprows)
if usecols is not None:
if len(usecols) == 2:
time_col_index, flux_col_index = usecols
time_col_name = lc_data.colnames[time_col_index]
flux_col_name = lc_data.colnames[flux_col_index]
if ":" in str(lc_data[time_col_name].data[0]):
time, flux = Time(lc_data[time_col_name].data).jd, lc_data[flux_col_name].data
else:
time, flux = Time(lc_data[time_col_name].data, format="jd").jd, lc_data[flux_col_name].data
return time, flux
elif len(usecols) == 3:
time_col_index, flux_col_index, dflux_col_index = usecols
time_col_name = lc_data.colnames[time_col_index]
flux_col_name = lc_data.colnames[flux_col_index]
dflux_col_name = lc_data.colnames[dflux_col_index]
if ":" in str(lc_data[time_col_name].data[0]):
time, flux = Time(lc_data[time_col_name].data).jd, lc_data[flux_col_name].data
else:
time, flux = Time(lc_data[time_col_name].data, format="jd").jd, lc_data[flux_col_name].data
dflux = lc_data[dflux_col_name].data
return time, flux, dflux
else:
raise ValueError('usecols should have 2 or 3 values')
else:
if len(lc_data.colnames) == 2:
time_col_index, flux_col_index = [0, 1]
time_col_name = lc_data.colnames[time_col_index]
flux_col_name = lc_data.colnames[flux_col_index]
time, flux = Time(lc_data[time_col_name].data).jd, lc_data[flux_col_name].data
return time, flux
elif len(lc_data.colnames) == 3:
time_col_index, flux_col_index, dflux_col_index = [0, 1, 2]
time_col_name = lc_data.colnames[time_col_index]
flux_col_name = lc_data.colnames[flux_col_index]
dflux_col_name = lc_data.colnames[dflux_col_index]
time, flux = Time(lc_data[time_col_name].data).jd, lc_data[flux_col_name].data
dflux = lc_data[dflux_col_name].data
return time, flux, dflux
else:
raise ValueError('file columns should have 2 or 3 values')
except:
raise ValueError('An error has occurred in reading the {}'.format(lc_file))