Source code for superbol.fit_blackbody
import numpy as np
from scipy.optimize import curve_fit
from astropy import units as u
from astropy import constants as const
from superbol.planck import *
[docs]def bb_flux(wavelength, temperature, angular_radius):
"""Observed flux at `wavelength` from a blackbody of `temperature` and `angular_radius` in cgs units
Args:
wavelength (float): Wavelength in Angstroms
temperature (float): Temperature in Kelvin
angular_radius (float): Angular radius :math:`(\\theta = \\frac{R}{D})`
Returns:
Astropy Quantity: blackbody flux in :math:`erg \\; s^{-1} cm^{-2} Anstrom^{-1}`
"""
bb_flux = (np.pi * u.sr) * planck_function(wavelength, temperature) * (angular_radius)**2
return bb_flux
[docs]def bb_flux_nounits(wavelength, temperature, angular_radius):
"""Identical to bb_flux, but returns the value rather than the Astropy Quantity.
This function is needed because curve_fit() does not play nice with functions that return Astropy quantities.
"""
flux = bb_flux(wavelength, temperature, angular_radius)
return flux.value
[docs]def bb_flux_integrated(wavelength, temperature, angular_radius):
"""Integrate the planck function from :math:`\\lambda = 0` to :math:`\\lambda =` `wavelength`, then convert result to observed flux
Args:
wavelength (float): Wavelength in Angstroms
temperature (float): Temperature in Kelvin
angular_radius (float): Angular radius :math:`(\\theta = \\frac{R}{D})`
Returns:
float: Value of the integrated flux in :math:`erg \\; s^{-1} cm^{-2}`
"""
bb_flux_integrated = (np.pi * u.sr) * planck_integral(wavelength, temperature) * (angular_radius)**2
return bb_flux_integrated.value
[docs]def dbb_flux_integrated_dT(wavelength, temperature, angular_radius):
"""Take the derivative of the integrated planck function, then convert result to observed flux. This is used in error propagation calculations.
Args:
wavelength (float): Wavelength in Angstroms
temperature (float): Temperature in Kelvin
angular_radius (float): Angular radius :math:`(\\theta = \\frac{R}{D})`
Returns:
float: Derivative of the integrated blackbody flux at `wavelength` with respect to `temperature`
"""
dbb_flux_integrated_dT = (np.pi * u.sr) * d_planck_integral_dT(wavelength, temperature) * (angular_radius)**2
return dbb_flux_integrated_dT.value
[docs]def bb_total_flux(temperature, angular_radius):
"""Integrate the planck function from :math:`\\lambda = 0` to :math:`\\lambda = \\infty`, then convert result to observed flux.
The calculation is done using the Stefan-Boltxmann law, rather than performing an actual integral using numerical integration. The `angular_radius` is included to convert the result to an observed flux.
Args:
temperature (float): Temperature in Kelvin
angular_radius (float): Angular radius :math:`(\\theta = \\frac{R}{D})`
Returns:
float: The value of :math:`\\sigma \\frac{R^2}{D^2} T^4`
"""
temperature = u.Quantity(temperature, u.K)
bb_total_flux = const.sigma_sb * (angular_radius**2) * temperature**4
bb_total_flux = bb_total_flux.to(u.erg / (u.s * u.cm**2))
return bb_total_flux.value
[docs]def dbb_total_flux_dT(temperature, angular_radius):
"""Take the derivative of the total blackbody flux with respect to temperature
The calculation takes a derivative of the Stefan-Boltzmann law with respect to temperature. The `angular_radius` is present to convert the result to an observed flux.
Args:
temperature (float): Temperature in Kelvin
angular_radius (float): Angular radius :math:`(\\theta = \\frac{R}{D})`
Returns:
float: The value of :math:`4 \\sigma \\frac{R^2}{D^2} T^3`
"""
temperature = u.Quantity(temperature, u.K)
bb_total_flux = 4.0 * const.sigma_sb * (angular_radius**2) * temperature**3
bb_total_flux = bb_total_flux.to(u.erg / (u.s * u.cm**2 * u.K))
return bb_total_flux.value
[docs]def bb_fit_parameters(wavelengths, fluxes, flux_uncertainties):
"""Fit a blackbody to observed `wavelengths` and `fluxes`.
The initial guesses for the `temperature` and `angular_radius` are :math:`T = 5000` K and :math:`\\theta = 1.0 \\times 10^{-10}`. These are typical for an extragalactic supernovae, but should be used with caution for any other objects.
Args:
wavelengths (list): List of wavelengths at which the fluxes were observed.
fluxes (list): List of observed monochromatic fluxes.
Returns:
tuple: Tuple containing the best fit `temperature`, `angular_radius`, as well as perr, a 2-tuple containing the `temperature` error and the `angular_radius` error.
(temperature, angular_radius, perr)
"""
popt, pcov = curve_fit(bb_flux_nounits, wavelengths, fluxes, p0=[5000, 1.0e-10], sigma=flux_uncertainties, absolute_sigma=True)
temperature = popt[0]
angular_radius = popt[1]
perr = np.sqrt(np.diag(pcov))
return temperature, angular_radius, perr