σ
ίΘ[c           @` sr  d  Z  d d l m Z m Z m Z m Z d d l Z d d l m Z d d l	 Z
 d d l m Z d d l m Z d d	 l m Z d d
 l m Z d d l m Z d d d g Z e j e j d e j e j Z e j e j d e j e j Z e j   E e j d e   e
 j! e
 j" d   p=e
 j! e
 j" d   Z# Wd QXd e f d     YZ$ d   Z% d   Z& d S(   u  
Model and functions related to blackbody radiation.

.. _blackbody-planck-law:

Blackbody Radiation
-------------------

Blackbody flux is calculated with Planck law
(:ref:`Rybicki & Lightman 1979 <ref-rybicki1979>`):

.. math::

    B_{\lambda}(T) = \frac{2 h c^{2} / \lambda^{5}}{exp(h c / \lambda k T) - 1}

    B_{\nu}(T) = \frac{2 h \nu^{3} / c^{2}}{exp(h \nu / k T) - 1}

where the unit of :math:`B_{\lambda}(T)` is
:math:`erg \; s^{-1} cm^{-2} \mathring{A}^{-1} sr^{-1}`, and
:math:`B_{\nu}(T)` is :math:`erg \; s^{-1} cm^{-2} Hz^{-1} sr^{-1}`.
:func:`~astropy.modeling.blackbody.blackbody_lambda` and
:func:`~astropy.modeling.blackbody.blackbody_nu` calculate the
blackbody flux for :math:`B_{\lambda}(T)` and :math:`B_{\nu}(T)`,
respectively.

For blackbody representation as a model, see :class:`BlackBody1D`.

.. _blackbody-examples:

Examples
^^^^^^^^

>>> import numpy as np
>>> from astropy import units as u
>>> from astropy.modeling.blackbody import blackbody_lambda, blackbody_nu

Calculate blackbody flux for 5000 K at 100 and 10000 Angstrom while suppressing
any Numpy warnings:

>>> wavelengths = [100, 10000] * u.AA
>>> temperature = 5000 * u.K
>>> with np.errstate(all='ignore'):
...     flux_lam = blackbody_lambda(wavelengths, temperature)
...     flux_nu = blackbody_nu(wavelengths, temperature)
>>> flux_lam  # doctest: +FLOAT_CMP
<Quantity [  1.27452545e-108,  7.10190526e+005] erg / (Angstrom cm2 s sr)>
>>> flux_nu  # doctest: +FLOAT_CMP
<Quantity [  4.25135927e-123,  2.36894060e-005] erg / (cm2 Hz s sr)>

Plot a blackbody spectrum for 5000 K:

.. plot::

    import matplotlib.pyplot as plt
    import numpy as np
    from astropy import constants as const
    from astropy import units as u
    from astropy.modeling.blackbody import blackbody_lambda

    temperature = 5000 * u.K
    wavemax = (const.b_wien / temperature).to(u.AA)  # Wien's displacement law
    waveset = np.logspace(
        0, np.log10(wavemax.value + 10 * wavemax.value), num=1000) * u.AA
    with np.errstate(all='ignore'):
        flux = blackbody_lambda(waveset, temperature)

    fig, ax = plt.subplots(figsize=(8, 5))
    ax.plot(waveset.value, flux.value)
    ax.axvline(wavemax.value, ls='--')
    ax.get_yaxis().get_major_formatter().set_powerlimits((0, 1))
    ax.set_xlabel(r'$\lambda$ ({0})'.format(waveset.unit))
    ax.set_ylabel(r'$B_{\lambda}(T)$')
    ax.set_title('Blackbody, T = {0}'.format(temperature))

Note that an array of temperatures can also be given instead of a single
temperature. In this case, the Numpy broadcasting rules apply: for instance, if
the frequency and temperature have the same shape, the output will have this
shape too, while if the frequency is a 2-d array with shape ``(n, m)`` and the
temperature is an array with shape ``(m,)``, the output will have a shape
``(n, m)``.

See Also
^^^^^^^^

.. _ref-rybicki1979:

Rybicki, G. B., & Lightman, A. P. 1979, Radiative Processes in Astrophysics (New York, NY: Wiley)

i    (   t   absolute_importt   unicode_literalst   divisiont   print_functionN(   t   OrderedDicti   (   t   Fittable1DModel(   t	   Parameteri   (   t	   constants(   t   units(   t   AstropyUserWarningu   BlackBody1Du   blackbody_nuu   blackbody_lambdau   ignoreiθ  g    _ Bt   BlackBody1Dc           B` s   e  Z d  Z e d d d d d e j  Z e d d d e j e j d e j	  Z
 e Z i e j   d 6Z d	   Z e d
    Z d   Z e d    Z RS(   u(  
    One dimensional blackbody model.

    Parameters
    ----------
    temperature : :class:`~astropy.units.Quantity`
        Blackbody temperature.
    bolometric_flux : :class:`~astropy.units.Quantity`
        The bolometric flux of the blackbody (i.e., the integral over the
        spectral axis).

    Notes
    -----

    Model formula:

        .. math:: f(x) = \pi B_{\nu} f_{\text{bolometric}} / (\sigma  T^{4})

    Examples
    --------
    >>> from astropy.modeling import models
    >>> from astropy import units as u
    >>> bb = models.BlackBody1D()
    >>> bb(6000 * u.AA)  # doctest: +FLOAT_CMP
    <Quantity 1.3585381201978953e-15 erg / (cm2 Hz s)>

    .. plot::
        :include-source:

        import numpy as np
        import matplotlib.pyplot as plt

        from astropy.modeling.models import BlackBody1D
        from astropy.modeling.blackbody import FLAM
        from astropy import units as u
        from astropy.visualization import quantity_support

        bb = BlackBody1D(temperature=5778*u.K)
        wav = np.arange(1000, 110000) * u.AA
        flux = bb(wav).to(FLAM, u.spectral_density(wav))

        with quantity_support():
            plt.figure()
            plt.semilogx(wav, flux)
            plt.axvline(bb.lambda_max.to(u.AA).value, ls='--')
            plt.show()

    t   defaulti  t   mini    t   uniti   i   u   xc         C` s¦   t  | t j  r3 | j t j d t j   } n t j | t j  } t j t j t	 | |  t
 j | d j d t j  | } t | d  r | S| j Sd S(   uΥ  Evaluate the model.

        Parameters
        ----------
        x : float, `~numpy.ndarray`, or `~astropy.units.Quantity`
            Frequency at which to compute the blackbody. If no units are given,
            this defaults to Hz.

        temperature : float, `~numpy.ndarray`, or `~astropy.units.Quantity`
            Temperature of the blackbody. If no units are given, this defaults
            to Kelvin.

        bolometric_flux : float, `~numpy.ndarray`, or `~astropy.units.Quantity`
            Desired integral for the blackbody.

        Returns
        -------
        y : number or ndarray
            Blackbody spectrum. The units are determined from the units of
            ``bolometric_flux``.
        t   equivalenciesi   i   u   unitN(   t
   isinstancet   ut   Quantityt   tot   Kt   temperaturet   npt   pit   srt   blackbody_nut   constt   sigma_sbt   Hzt   hasattrt   value(   t   selft   xR   t   bolometric_fluxt   fnu(    (    s9   lib/python2.7/site-packages/astropy/modeling/blackbody.pyt   evaluateΈ   s    !	9c         C` s   i t  j d 6S(   Nu   x(   R   R   (   R   (    (    s9   lib/python2.7/site-packages/astropy/modeling/blackbody.pyt   input_unitsκ   s    c         C` s*   t  d t j f d | d t j f g  S(   Nu   temperatureu   bolometric_fluxu   y(   R   R   R   R   (   R   t   inputs_unitt   outputs_unit(    (    s9   lib/python2.7/site-packages/astropy/modeling/blackbody.pyt   _parameter_units_for_data_unitsρ   s    c         C` s   t  j |  j S(   u=   Peak wavelength when the curve is expressed as power density.(   R   t   b_wienR   (   R   (    (    s9   lib/python2.7/site-packages/astropy/modeling/blackbody.pyt
   lambda_maxυ   s    (   t   __name__t
   __module__t   __doc__R   R   R   R   t   ergt   cmt   sR    t   Truet   input_units_allow_dimensionlesst   spectralt   input_units_equivalenciesR"   t   propertyR#   R&   R(   (    (    (    s9   lib/python2.7/site-packages/astropy/modeling/blackbody.pyR
   y   s   0*	2	c   	   	   C` s΄  t  j t  j   t  j    A t  j |  t  j d t j } t  j | t  j d t j } Wd QXt j	 | d k   r t
 d j |    n  t j t j |   s½ t j	 | d k  rΠ t j d t  n  t j | t j | } t j |  } t rjt j |  } t j	 |  rj| j r@t j |  r@t j } qgt j | t j t j |  | @ <qjn  d t j | d t j d | } | j t t  j |   } | t  j S(	   uq  Calculate blackbody flux per steradian, :math:`B_{\nu}(T)`.

    .. note::

        Use `numpy.errstate` to suppress Numpy warnings, if desired.

    .. warning::

        Output values might contain ``nan`` and ``inf``.

    Parameters
    ----------
    in_x : number, array-like, or `~astropy.units.Quantity`
        Frequency, wavelength, or wave number.
        If not a Quantity, it is assumed to be in Hz.

    temperature : number, array-like, or `~astropy.units.Quantity`
        Blackbody temperature.
        If not a Quantity, it is assumed to be in Kelvin.

    Returns
    -------
    flux : `~astropy.units.Quantity`
        Blackbody monochromatic flux in
        :math:`erg \; cm^{-2} s^{-1} Hz^{-1} sr^{-1}`.

    Raises
    ------
    ValueError
        Invalid temperature.

    ZeroDivisionError
        Wavelength is zero (when converting to frequency).

    t   dtypeNi    u#   Temperature should be positive: {0}u4   Input contains invalid wavelength/frequency value(s)g       @i   i   (   R   t   add_enabled_equivalenciesR1   R   R   R   R   t   float64R   t   anyt
   ValueErrort   formatt   allt   isfinitet   warningst   warnR	   R   t   ht   k_Bt   expm1t   _has_buggy_expm1t   isnant   isscalart   inft   wheret   cR   t   FNUt   spectral_densityR   (	   t   in_xR   t   freqt   tempt	   log_boltzt   boltzm1t   boltzm1_nanst   bb_nut   flux(    (    s9   lib/python2.7/site-packages/astropy/modeling/blackbody.pyR   ϋ   s&    % $.	
*$c         C` sl   t  |  d d  d k r0 t j |  t j  }  n  t |  |  t j } | j t t j	 |    } | t j S(   uI  Like :func:`blackbody_nu` but for :math:`B_{\lambda}(T)`.

    Parameters
    ----------
    in_x : number, array-like, or `~astropy.units.Quantity`
        Frequency, wavelength, or wave number.
        If not a Quantity, it is assumed to be in Angstrom.

    temperature : number, array-like, or `~astropy.units.Quantity`
        Blackbody temperature.
        If not a Quantity, it is assumed to be in Kelvin.

    Returns
    -------
    flux : `~astropy.units.Quantity`
        Blackbody monochromatic flux in
        :math:`erg \; cm^{-2} s^{-1} \mathring{A}^{-1} sr^{-1}`.

    u   unitN(
   t   getattrt   NoneR   R   t   AAR   R   R   t   FLAMRH   (   RI   R   RO   RP   (    (    s9   lib/python2.7/site-packages/astropy/modeling/blackbody.pyt   blackbody_lambdaB  s
    ('   R+   t
   __future__R    R   R   R   R<   t   collectionsR   t   numpyR   t   coreR   t
   parametersR   t    R   R   R   R   t   utils.exceptionsR	   t   __all__R,   R-   R.   R   RG   RS   RT   t   catch_warningst   simplefiltert   RuntimeWarningRB   R@   RA   R
   R   RU   (    (    (    s9   lib/python2.7/site-packages/astropy/modeling/blackbody.pyt   <module>Z   s$   """6	G