Commit 04ad3255 authored by Shuai Feng's avatar Shuai Feng
Browse files

add justification of input pars range

parent b60cc912
Pipeline #6989 passed with stage
in 0 seconds
...@@ -8,14 +8,14 @@ from skimage.transform import resize ...@@ -8,14 +8,14 @@ from skimage.transform import resize
def Sersic2D(x, y, mag = 12.0, r_eff = 1.0, n = 2.0, ellip = 0.5, def Sersic2D(x, y, mag = 12.0, r_eff = 1.0, n = 2.0, ellip = 0.5,
theta = 0.0, x_0 = 0.0, y_0 = 0.0, pixelscale = 0.01): theta = 0.0, x_0 = 0.0, y_0 = 0.0, pixelscale = 0.01):
""" """
Model of 2D - Sersic profile Sersic2D: Caculate the surface brightness at given spatial position base on the Sersic model.
Parameters Parameters
---------- ----------
x : float array x : float array
_description_ Coordinate of spatial position in the x-axis
y : _type_ y : float array
_description_ Coordinate of spatial position in the y-axis
mag : float, optional mag : float, optional
Integral magnitude of sersic model, by default 12.0 Integral magnitude of sersic model, by default 12.0
r_eff : float, optional r_eff : float, optional
...@@ -27,9 +27,9 @@ def Sersic2D(x, y, mag = 12.0, r_eff = 1.0, n = 2.0, ellip = 0.5, ...@@ -27,9 +27,9 @@ def Sersic2D(x, y, mag = 12.0, r_eff = 1.0, n = 2.0, ellip = 0.5,
theta : float, optional theta : float, optional
Position angle in degree, by default 0.0 Position angle in degree, by default 0.0
x_0 : float, optional x_0 : float, optional
Offset of the center of Sersic model, by default 0.0 Offset of the center of Sersic model in x-axis, by default 0.0
y_0 : float, optional y_0 : float, optional
Offset of the center of Sersic model, by default 0.0 Offset of the center of Sersic model in y-axis, by default 0.0
pixelscale : float, optional pixelscale : float, optional
Size of each pixel in arcsec^2, by default 0.01 Size of each pixel in arcsec^2, by default 0.01
...@@ -38,10 +38,14 @@ def Sersic2D(x, y, mag = 12.0, r_eff = 1.0, n = 2.0, ellip = 0.5, ...@@ -38,10 +38,14 @@ def Sersic2D(x, y, mag = 12.0, r_eff = 1.0, n = 2.0, ellip = 0.5,
_description_ _description_
""" """
# Convert the angle in degree to angle to radians
theta_radian = theta / 180 * np.pi
# Produce Sersic profile # Produce Sersic profile
bn = sp.gammaincinv(2. * n, 0.5) bn = sp.gammaincinv(2. * n, 0.5)
a, b = r_eff, (1 - ellip) * r_eff a, b = r_eff, (1 - ellip) * r_eff
cos_theta, sin_theta = np.cos(theta), np.sin(theta) cos_theta, sin_theta = np.cos(theta_radian), np.sin(theta_radian)
x_maj = (x - x_0) * cos_theta + (y - y_0) * sin_theta x_maj = (x - x_0) * cos_theta + (y - y_0) * sin_theta
x_min = -(x - x_0) * sin_theta + (y - y_0) * cos_theta x_min = -(x - x_0) * sin_theta + (y - y_0) * cos_theta
z = (abs(x_maj / a) ** 2 + abs(x_min / b) ** 2) ** (1 / 2) z = (abs(x_maj / a) ** 2 + abs(x_min / b) ** 2) ** (1 / 2)
...@@ -60,35 +64,40 @@ def Sersic2D(x, y, mag = 12.0, r_eff = 1.0, n = 2.0, ellip = 0.5, ...@@ -60,35 +64,40 @@ def Sersic2D(x, y, mag = 12.0, r_eff = 1.0, n = 2.0, ellip = 0.5,
def VelMap2D(x, y, vmax = 200.0, rt = 1.0, ellip = 0.5, def VelMap2D(x, y, vmax = 200.0, rt = 1.0, ellip = 0.5,
theta = 0.0, x_0 = 0.0, y_0 = 0.0): theta = 0.0, x_0 = 0.0, y_0 = 0.0):
""" """
VelMap2D _summary_ VelMap2D: Caculate the velocity at given spatial position base on the rotating disk model.
The rotation curve is adpot as the tanh model.
Parameters Parameters
---------- ----------
x : _type_ x : float array
_description_ Coordinate of spatial position in the x-axis
y : _type_ y : float array
_description_ Coordinate of spatial position in the y-axis
vmax : int, optional vmax : float, optional
_description_, by default 200 Maximum rotational velocity of rotation curve, by default 200.0
rt : int, optional rt : float, optional
_description_, by default 1 Turn-over radius of rotation curve, by default 1.0
ellip : float, optional ellip : float, optional
_description_, by default 0.5 Ellipicity of disk model, by default 0.5
theta : int, optional theta : float, optional
_description_, by default 0 Position angle of disk model, by default 0.0
x_0 : int, optional x_0 : float, optional
_description_, by default 0 Offset of the center of disk model in the x-axis, by default 0.0
y_0 : int, optional y_0 : float, optional
_description_, by default 0 Offset of the center of disk model in the y-axis, by default 0.0
Returns Returns
------- -------
_type_ _type_
_description_ _description_
""" """
# Convert the angle in degree to angle to radians
theta_radian = theta / 180 * np.pi
# Produce tanh profile # Produce tanh profile
a, b = rt, (1 - ellip) * rt a, b = rt, (1 - ellip) * rt
cos_theta, sin_theta = np.cos(theta), np.sin(theta) cos_theta, sin_theta = np.cos(theta_radian), np.sin(theta_radian)
x_maj = (x - x_0) * cos_theta + (y - y_0) * sin_theta x_maj = (x - x_0) * cos_theta + (y - y_0) * sin_theta
x_min = -(x - x_0) * sin_theta + (y - y_0) * cos_theta x_min = -(x - x_0) * sin_theta + (y - y_0) * cos_theta
z = (abs(x_maj / a) ** 2 + abs(x_min / b) ** 2) ** (1 / 2) z = (abs(x_maj / a) ** 2 + abs(x_min / b) ** 2) ** (1 / 2)
...@@ -96,40 +105,46 @@ def VelMap2D(x, y, vmax = 200.0, rt = 1.0, ellip = 0.5, ...@@ -96,40 +105,46 @@ def VelMap2D(x, y, vmax = 200.0, rt = 1.0, ellip = 0.5,
return profile return profile
def GradMap2D(x, y, a0 = 10, r_eff = 1, gred = -1, ellip = 0.5, def GradMap2D(x, y, a0 = 10.0, r_eff = 1.0, gred = -1.0, ellip = 0.5,
theta = 0, x_0 = 0, y_0 = 0): theta = 0.0, x_0 = 0.0, y_0 = 0.0):
""" """
GradMap2D _summary_ GradMap2D: Caculate the intensity at given spatial position base on the disk model.
The radial profile is adpot as the gradient model.
Parameters Parameters
---------- ----------
x : _type_ x : float array
_description_ Coordinate of spatial position in the x-axis
y : _type_ y : float array
_description_ Coordinate of spatial position in the y-axis
a0 : int, optional a0 : float, optional
_description_, by default 10 Intensity at the center, by default 10.0
r_eff : int, optional r_eff : float, optional
_description_, by default 1 Effective radius, by default 1.0
gred : int, optional gred : float, optional
_description_, by default -1 Gradient, by default -1.0
ellip : float, optional ellip : float, optional
_description_, by default 0.5 Ellipicity of disk model, by default 0.5
theta : int, optional theta : float, optional
_description_, by default 0 Position angle of disk model, by default 0.0
x_0 : int, optional x_0 : float, optional
_description_, by default 0 Offset of the center of disk model in the x-axis, by default 0.0
y_0 : int, optional y_0 : float, optional
_description_, by default 0 Offset of the center of disk model in the y-axis, by default 0.0
Returns Returns
------- -------
_type_ _type_
_description_ _description_
""" """
# Convert the angle in degree to angle to radians
theta_radian = theta / 180 * np.pi
# Produce gradiant profile # Produce gradiant profile
a, b = r_eff, (1 - ellip) * r_eff a, b = r_eff, (1 - ellip) * r_eff
cos_theta, sin_theta = np.cos(theta), np.sin(theta) cos_theta, sin_theta = np.cos(theta_radian), np.sin(theta_radian)
x_maj = (x - x_0) * cos_theta + (y - y_0) * sin_theta x_maj = (x - x_0) * cos_theta + (y - y_0) * sin_theta
x_min = -(x - x_0) * sin_theta + (y - y_0) * cos_theta x_min = -(x - x_0) * sin_theta + (y - y_0) * cos_theta
z = (abs(x_maj / a) ** 2 + abs(x_min / b) ** 2) ** (1 / 2) z = (abs(x_maj / a) ** 2 + abs(x_min / b) ** 2) ** (1 / 2)
...@@ -200,7 +215,7 @@ class Map2d(object): ...@@ -200,7 +215,7 @@ class Map2d(object):
---------- ----------
mag : float, optional mag : float, optional
Integral magnitude, by default 12.0 Integral magnitude, by default 12.0
r_eff : float, optional reff : float, optional
Effective radius in arcsec, by default 2.0 Effective radius in arcsec, by default 2.0
n : float, optional n : float, optional
Sersic index, by default 2.5 Sersic index, by default 2.5
...@@ -209,8 +224,21 @@ class Map2d(object): ...@@ -209,8 +224,21 @@ class Map2d(object):
theta : float, optional theta : float, optional
Position angle in degree, by default -50.0 Position angle in degree, by default -50.0
""" """
self.mag = mag
# Check Input Parameters
if (mag > 26) or (mag < 8):
print("Notice: Your input integral magnitude of Sersic mode (mag) is > 26 mag or < 8 mag.")
if (r_eff <= 0):
raise Exception("Effective radius (r_eff) should be > 0 arcsec!")
if (n <= 0):
raise Exception("Sersic index (n) should be > 0!")
if (ellip >= 1) or (ellip < 0):
raise Exception("Ellipcity (ellip) should be >= 0 and < 1!")
if (theta > 180) or (theta < -180):
print("Notice: Your input position angle (theta) is > 180 degree or < -180 degree.")
self.reff = r_eff / self.xsamp self.reff = r_eff / self.xsamp
self.mag = mag
self.n = n self.n = n
self.ellip = ellip self.ellip = ellip
self.theta = theta self.theta = theta
...@@ -234,6 +262,17 @@ class Map2d(object): ...@@ -234,6 +262,17 @@ class Map2d(object):
theta : float, optional theta : float, optional
Position angle of rotating disk, by default -50.0 Position angle of rotating disk, by default -50.0
""" """
# Check Input Parameters
if (vmax <= 0):
print("Notice: Your input maximum rotational velocity (vmax) is <= 0 km/s!")
if (rt <= 0):
raise Exception("Turn-over radius (rt) should be > 0 arcsec!")
if (ellip >= 1) or (ellip < 0):
raise Exception("Ellipcity (ellip) should be >= 0 and < 1!")
if (theta > 180) or (theta < -180):
print("Notice: Your input position angle (theta) is > 180 degree or < -180 degree.")
self.vmax = vmax self.vmax = vmax
self.rt = rt / self.xsamp self.rt = rt / self.xsamp
self.ellip = ellip self.ellip = ellip
...@@ -248,7 +287,7 @@ class Map2d(object): ...@@ -248,7 +287,7 @@ class Map2d(object):
Parameters Parameters
---------- ----------
a0 : float, optional a0 : float, optional
Amplitude at the central pixel, by default 10 Amplitude at the center, by default 10
r_eff : float, optional r_eff : float, optional
Effective radius, by default 1 Effective radius, by default 1
gred : float, optional gred : float, optional
...@@ -258,6 +297,14 @@ class Map2d(object): ...@@ -258,6 +297,14 @@ class Map2d(object):
theta : int, optional theta : int, optional
Position angle, by default 0 Position angle, by default 0
""" """
# Check Input Parameters
if (r_eff <= 0):
raise Exception("Effective radius (r_eff) should be > 0 arcsec!")
if (ellip >= 1) or (ellip < 0):
raise Exception("Ellipcity (ellip) should be >= 0 and < 1!")
if (theta > 180) or (theta < -180):
print("Notice: Your input position angle (theta) is > 180 degree or < -180 degree.")
self.a0 = a0 self.a0 = a0
self.reff = r_eff / self.xsamp self.reff = r_eff / self.xsamp
self.gred = gred self.gred = gred
...@@ -320,8 +367,16 @@ class StellarPopulationMap(): ...@@ -320,8 +367,16 @@ class StellarPopulationMap():
self.mag = self.sbright - 2.5 * np.log10(self.dpix * self.dpix) self.mag = self.sbright - 2.5 * np.log10(self.dpix * self.dpix)
self.age = 10 ** self.logage / 1e9 self.age = 10 ** self.logage / 1e9
self.vdisp[self.vdisp < 10] = 10 # Check Input Maps
self.ebv[self.ebv < 0] = 0 ind_overrange = (self.vdisp < 10)
if len(self.vdisp[ind_overrange]) > 0:
print("Notice: Spaxel with <10km/s in the input vdisp map will be automatically adjusted to 10km/s.")
self.vdisp[ind_overrange] = 10
ind_overrange = (self.ebv < 0)
if len(self.ebv[ind_overrange]) > 0:
print("Notice: Spaxel with < 0 mag in the input ebv map will be automatically adjusted to 0 mag.")
self.ebv[ind_overrange] = 0
class IonizedGasMap(): class IonizedGasMap():
""" """
...@@ -358,5 +413,16 @@ class IonizedGasMap(): ...@@ -358,5 +413,16 @@ class IonizedGasMap():
self.vdisp = vdisp.map self.vdisp = vdisp.map
self.ebv = ebv.map self.ebv = ebv.map
self.vdisp[self.vdisp < 10] = 10 #self.vdisp[self.vdisp < 10] = 10
self.ebv[self.ebv < 0] = 0 #self.ebv[self.ebv < 0] = 0
\ No newline at end of file
# Check Input Maps
ind_overrange = (self.vdisp < 10)
if len(self.vdisp[ind_overrange]) > 0:
print("Notice: Spaxel with <10km/s in the input vdisp map will be automatically adjusted to 10km/s.")
self.vdisp[ind_overrange] = 10
ind_overrange = (self.ebv < 0)
if len(self.ebv[ind_overrange]) > 0:
print("Notice: Spaxel with < 0 mag in the input ebv map will be automatically adjusted to 0 mag.")
self.ebv[ind_overrange] = 0
\ No newline at end of file
...@@ -382,12 +382,18 @@ class HII_Region(): ...@@ -382,12 +382,18 @@ class HII_Region():
def __init__(self, config, temp, halpha = 100.0, logz = 0.0, def __init__(self, config, temp, halpha = 100.0, logz = 0.0,
vel = 100.0, vdisp = 120.0, ebv = 0.1): vel = 100.0, vdisp = 120.0, ebv = 0.1):
# Check Input Parameters
#if (halpha < 0):
# print("Notice: Your input Halpha flux (halpha) is < 0 erg/s/A/cm^2. ")
if (logz > -2) & (logz < 0.5): if (logz > -2) & (logz < 0.5):
indz = np.argmin(np.abs(logz - temp.logz_grid)) indz = np.argmin(np.abs(logz - temp.logz_grid))
flux_ratio = temp.flux_ratio[indz, :] flux_ratio = temp.flux_ratio[indz, :]
else: else:
raise ValueError('The value of logZ is not in the range of [-2, 0.5]!') raise ValueError('Input gas-phase metallicity (logz) should be [-2, 0.5]!')
#if (ebv < 0):
# ebv = 0
# print('Notice: Your input dust extinction (ebv) is < 0 mag, which will be automatically adjusted to 0 mag. ')
# Make emission line spectra through adding emission lines # Make emission line spectra through adding emission lines
emlines = temp.emission_lines * flux_ratio emlines = temp.emission_lines * flux_ratio
...@@ -414,6 +420,7 @@ class HII_Region(): ...@@ -414,6 +420,7 @@ class HII_Region():
sigma_dif[idx] = 0.1 sigma_dif[idx] = 0.1
flux_broad = gaussian_filter1d(flux_logwave, sigma_dif) flux_broad = gaussian_filter1d(flux_logwave, sigma_dif)
else: else:
print('Notice: Your input velocity dispersion (vdisp) is <= 0 km/s. The nagtive value will be automatically adjusted to 0 km/s. ')
flux_broad = flux_logwave flux_broad = flux_logwave
# Redshift # Redshift
...@@ -459,11 +466,11 @@ class AGN_NLR(): ...@@ -459,11 +466,11 @@ class AGN_NLR():
def __init__(self, config, temp, halpha = 100.0, logz = 0.0, def __init__(self, config, temp, halpha = 100.0, logz = 0.0,
vel = 100.0, vdisp = 120.0, ebv = 0.1): vel = 100.0, vdisp = 120.0, ebv = 0.1):
if (logz > -2) & (logz < 0.5): if (logz >= -2.3) & (logz <= 0.54):
indz = np.argmin(np.abs(logz - temp.logz_grid)) indz = np.argmin(np.abs(logz - temp.logz_grid))
flux_ratio = temp.flux_ratio[indz, :] flux_ratio = temp.flux_ratio[indz, :]
else: else:
raise ValueError('The value of logZ is not in the range of [-2, 0.5]!') raise ValueError('The value of logZ is not in the range of [-2.3, 0.54]')
# Make emission line spectra through adding emission lines # Make emission line spectra through adding emission lines
emlines = temp.emission_lines * (flux_ratio / flux_ratio[6] ) emlines = temp.emission_lines * (flux_ratio / flux_ratio[6] )
...@@ -686,21 +693,43 @@ class AGN(): ...@@ -686,21 +693,43 @@ class AGN():
halpha_broad = 100.0, halpha_narrow = 100.0, vdisp_broad = 5000.0, vdisp_narrow = 500.0, halpha_broad = 100.0, halpha_narrow = 100.0, vdisp_broad = 5000.0, vdisp_narrow = 500.0,
vel = 1000.0, logz = 0.0, ebv = 0.1, dist = 20.0): vel = 1000.0, logz = 0.0, ebv = 0.1, dist = 20.0):
NLR = AGN_NLR(config, nlr_template, halpha = halpha_narrow, logz = logz, # Check Input Parameters
vel = vel, vdisp = vdisp_narrow, ebv = ebv) if (bhmass <0):
if halpha_broad > 0: raise Exception("Input black hole mass (bhmass) should be >= 0 solarmass.")
BLR = AGN_BLR(config, hbeta_flux = halpha_broad / 2.579, if (edd_ratio < 0):
hbeta_fwhm = vdisp_broad / 2.355, ebv = ebv, vel = vel) raise Exception("Input Eddington ratio (edd_ratio) should be >= 0.")
if (halpha_broad < 0):
m5100 = BHmass_to_M5100(bhmass, edd_ratio = edd_ratio, dist = dist) print("Notice: Your input braod Halpha emission line flux (halpha_broad) is <0 erg/s/A/cm^2, which will be automatically adjusted to 0.")
PL = AGN_Powerlaw(config, m5100 = m5100, ebv = ebv, vel = vel) if (vdisp_broad < 0):
Fe = AGN_FeII(config, hbeta_broad = halpha_broad / 2.579, ebv = ebv, vel = vel) raise Exception('Input velocity dispersion of broad lines (vdisp_broad) should be >= 0 km/s')
if (vdisp_narrow < 0):
raise Exception('Input velocity dispersion of narrow lines (vdisp_narrow) should be >= 0 km/s')
if (logz > 0.54):
logz = 0.54
print("Notice: Your input metallicity of narrow lines (logz) is > 0.54, which will be automatically adjusted to 0.54")
if (logz < -2.3):
raise Exception('Input metallicity of narrow lines (logz) should be < -2.3')
if (dist <= 0):
raise Exception('Input luminosity distance (dist) should be > 0 Mpc')
self.wave = config.wave self.wave = config.wave
self.flux = NLR.flux + PL.flux + Fe.flux self.flux = self.wave * 0
if halpha_broad > 0: if (vdisp_narrow > 0) & (halpha_narrow > 0):
NLR = AGN_NLR(config, nlr_template, halpha = halpha_narrow, logz = logz,
vel = vel, vdisp = vdisp_narrow, ebv = ebv)
self.flux = self.flux + NLR.flux
if (halpha_broad > 0) & (vdisp_broad > 0):
BLR = AGN_BLR(config, hbeta_flux = halpha_broad / 2.579,
hbeta_fwhm = vdisp_broad / 2.355, ebv = ebv, vel = vel)
self.flux = self.flux + BLR.flux self.flux = self.flux + BLR.flux
if (bhmass > 0) & (edd_ratio > 0):
m5100 = BHmass_to_M5100(bhmass, edd_ratio = edd_ratio, dist = dist)
PL = AGN_Powerlaw(config, m5100 = m5100, ebv = ebv, vel = vel)
Fe = AGN_FeII(config, hbeta_broad = halpha_broad / 2.579, ebv = ebv, vel = vel)
self.flux = self.flux + PL.flux + Fe.flux
def BHmass_to_M5100(bhmass, edd_ratio = 0.05, dist = 21.0): def BHmass_to_M5100(bhmass, edd_ratio = 0.05, dist = 21.0):
""" """
...@@ -928,10 +957,23 @@ class StellarContinuum(): ...@@ -928,10 +957,23 @@ class StellarContinuum():
""" """
def __init__(self, config, template, mag = 15.0, age = 1.0, feh = 0.0, def __init__(self, config, template, mag = 15.0, age = 1.0, feh = 0.0,
vel = 100.0, vdisp = 100.0, ebv = 0.1): vel = 100.0, vdisp = 100.0, ebv = 0.1):
# Check Input Parameters
if (mag > 26) or (mag < 8):
print("Notice: Your input magnitude (mag) is > 26 mag or < 8 mag.")
if (age < 0.06) or (age > 17.8):
print("Notice: Your input median age (age) is beyond the range of stellar template [0.06, 17.8], which will be automatically adjusted to the upper/lower limit.")
if (feh > 0.22):
print("Notice: Your input median metallicity (feh) is beyond the range of stellar template [-2.32, 0.22], which will be automatically adjusted to the upper limit.")
if (feh < -2.32):
raise Exception('Your input median metallicity (feh) is beyond the range of stellar template [-2.32, 0.22]')
#if (ebv < 0):
# ebv = 0
# print('Notice: Your input dust extinction (ebv) is < 0 mag, which will be automatically adjusted to 0 mag. ')
# ----------------- # -----------------
# Stellar Continuum # Stellar Continuum
SSP_temp = template.templates SSP_temp = template.templates
# Select metal bins # Select metal bins
...@@ -958,6 +1000,9 @@ class StellarContinuum(): ...@@ -958,6 +1000,9 @@ class StellarContinuum():
idx = (sigma_gal <= sigma_LSF) idx = (sigma_gal <= sigma_LSF)
sigma_dif[idx] = 0.1 sigma_dif[idx] = 0.1
flux0 = gaussian_filter1d(Stellar, sigma_dif) flux0 = gaussian_filter1d(Stellar, sigma_dif)
else:
if sigma_gal < 0:
print('Notice: Your input velocity dispersion (vdisp) is < 0 km/s, which will be automatically adjusted to 0 km/s. ')
# Dust Reddening # Dust Reddening
if np.isscalar(ebv): if np.isscalar(ebv):
...@@ -1068,6 +1113,17 @@ class SingleStar(): ...@@ -1068,6 +1113,17 @@ class SingleStar():
""" """
def __init__(self, config, template, mag = 15.0, teff = 10000.0, feh = 0.0, vel = 100.0, ebv = 0.0): def __init__(self, config, template, mag = 15.0, teff = 10000.0, feh = 0.0, vel = 100.0, ebv = 0.0):
# Check Input Parameters
if (mag > 26) or (mag < 8):
print("Notice: Your input magnitude (mag) is > 26 mag or < 8 mag.")
if (teff < 2820) or (teff > 20129):
print("Notice: Your input effective tempreture (teff) is beyond the range of stellar template [2820, 20129], which will be automatically adjusted to the upper/lower limit.")
if (feh > 0.81):
print("Notice: Your input metallicity (feh) is beyond the range of stellar template [-2.69, 0.81], which will be automatically adjusted to the upper limit.")
if (feh < -2.69):
raise Exception('Your input metallicity (feh) is beyond the range of stellar template [-2.69, 0.81]')
StarTemp = template.templates StarTemp = template.templates
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment