U
    e»{j¦f  ã                   @   s¤   d Z ddl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mZ d	d
ddgZG dd	„ d	eƒZG dd
„ d
eƒZG dd„ deƒZG dd„ deƒZdS )z$
Models that have physical origins.
é    N)Ú	constants)Úunits)ÚAstropyUserWarningé   )ÚFittable1DModel)ÚInputParameterErrorÚ	ParameterÚ	BlackBodyÚDrude1DÚ	Plummer1DÚNFWc                       sø   e Zd ZdZeddejdd�Zedddd�Zd	Z	d
e 
¡ iZejejd ej ej ej  Zejejd ej ej ej  ejejd ej ej ej  dœZ‡ fdd„Zdd„ Zedd„ ƒZdd„ Zedd„ ƒZedd„ ƒZedd„ ƒZ‡  ZS )r	   aZ  
    Blackbody model using the Planck function.

    Parameters
    ----------
    temperature : `~astropy.units.Quantity` ['temperature']
        Blackbody temperature.

    scale : float or `~astropy.units.Quantity` ['dimensionless']
        Scale factor.  If dimensionless, input units will assumed
        to be in Hz and output units in (erg / (cm ** 2 * s * Hz * sr).
        If not dimensionless, must be equivalent to either
        (erg / (cm ** 2 * s * Hz * sr) or erg / (cm ** 2 * s * AA * sr),
        in which case the result will be returned in the requested units and
        the scale will be stripped of units (with the float value applied).

    Notes
    -----

    Model formula:

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

    Examples
    --------
    >>> from astropy.modeling import models
    >>> from astropy import units as u
    >>> bb = models.BlackBody(temperature=5000*u.K)
    >>> bb(6000 * u.AA)  # doctest: +FLOAT_CMP
    <Quantity 1.53254685e-05 erg / (cm2 Hz s sr)>

    .. plot::
        :include-source:

        import numpy as np
        import matplotlib.pyplot as plt

        from astropy.modeling.models import BlackBody
        from astropy import units as u
        from astropy.visualization import quantity_support

        bb = BlackBody(temperature=5778*u.K)
        wav = np.arange(1000, 110000) * u.AA
        flux = bb(wav)

        with quantity_support():
            plt.figure()
            plt.semilogx(wav, flux)
            plt.axvline(bb.nu_max.to(u.AA, equivalencies=u.spectral()).value, ls='--')
            plt.show()
    g     ˆ³@r   zBlackbody temperature©ÚdefaultÚminÚunitÚdescriptionç      ð?zScale factor©r   r   r   TÚxé   )ÚSNUZSLAMc                    sz   |  dd ¡}t|dƒrd|j tj¡sd|j}| | jt dtj ¡¡sRt	d|› �ƒ‚|j
|d< || _n| j| _tƒ j||ŽS )NÚscaler   r   z8scale units not dimensionless or in surface brightness: )ÚgetÚhasattrr   Úis_equivalentÚuÚdimensionless_unscaledÚ_native_unitsÚspectral_densityÚAAÚ
ValueErrorÚvalueÚ_output_unitsÚsuperÚ__init__)ÚselfÚargsÚkwargsr   Zoutput_units©Ú	__class__© ú_/var/www/html/bwave/python/venv/lib/python3.8/site-packages/astropy/modeling/physical_models.pyr$   d   s     ÿ ÿÿ
zBlackBody.__init__c              	   C   st  t |tjƒst |tj¡}n|}t |tjƒs@t || jd ¡}n|}t t ¡ t ¡  ¡�( tj|tjt	j
d�}t |tj¡}W 5 Q R X t	 |dk ¡r¤td|› �ƒ‚t	 t	 |¡¡rÂt	 |dk¡rÎt dt¡ tj| tj|  }t	 |¡}	dtj |d  tjd |	  tj }
| jjd	k	�rFt|d
ƒ�s8|| jj }| tj¡j}||
 | jt |¡¡ }t|d
ƒ�rn|S |jS )a¢  Evaluate the model.

        Parameters
        ----------
        x : float, `~numpy.ndarray`, or `~astropy.units.Quantity` ['frequency']
            Frequency at which to compute the blackbody. If no units are given,
            this defaults to Hz (or AA if `scale` was initialized with units
            equivalent to erg / (cm ** 2 * s * AA * sr)).

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

        scale : float, `~numpy.ndarray`, or `~astropy.units.Quantity` ['dimensionless']
            Desired scale for the blackbody.

        Returns
        -------
        y : number or ndarray
            Blackbody spectrum. The units are determined from the units of
            ``scale``.

        .. note::

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

        .. warning::

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

        Raises
        ------
        ValueError
            Invalid temperature.

        ZeroDivisionError
            Wavelength is zero (when converting to frequency).
        r   )Zdtyper   z Temperature should be positive: z4Input contains invalid wavelength/frequency value(s)g       @é   r   Nr   ) Ú
isinstancer   ÚQuantityÚKÚinput_unitsZadd_enabled_equivalenciesÚspectralÚtemperatureÚHzÚnpZfloat64Úanyr    ÚallÚisfiniteÚwarningsÚwarnr   ÚconstÚhÚk_BÚexpm1ÚcÚsrr   r   r   Útor   r!   r"   r   )r%   r   r2   r   Zin_tempZin_xÚfreqÚtempZ	log_boltzZboltzm1Zbb_nuÚyr*   r*   r+   Úevaluate|   s6    'þ
&zBlackBody.evaluatec                 C   s6   | j  | jd ¡r"| jd tjiS | jd tjiS d S )Nr   r   )r"   r   Ú_native_output_unitsÚinputsr   r3   r   ©r%   r*   r*   r+   r0   Ö   s    zBlackBody.input_unitsc                 C   s
   dt jiS )Nr2   )r   r/   ©r%   Zinputs_unitZoutputs_unitr*   r*   r+   Ú_parameter_units_for_data_unitsà   s    z)BlackBody._parameter_units_for_data_unitsc                 C   s\   | j jdk	r| j j tj¡}n| j j}|tj | j	d  t
j }| tjtjd tj  ¡S )zBolometric flux.Né   r   )r   r   Zquantityr@   r   r   r!   r:   Zsigma_sbr2   r4   ÚpiÚergÚcmÚs)r%   r   Znative_bolfluxr*   r*   r+   Úbolometric_fluxã   s
    zBlackBody.bolometric_fluxc                 C   s   t j| j S )z=Peak wavelength when the curve is expressed as power density.)r:   Zb_wienr2   rG   r*   r*   r+   Ú
lambda_maxñ   s    zBlackBody.lambda_maxc                 C   s   dt j | j t j S )z<Peak frequency when the curve is expressed as power density.gÒ>±©N’@)r:   r<   r2   r;   rG   r*   r*   r+   Únu_maxö   s    zBlackBody.nu_max)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r/   r2   r   Ú _input_units_allow_dimensionlessr1   Zinput_units_equivalenciesrL   rM   rN   r3   r?   r   r   rE   r$   rD   Úpropertyr0   rI   rO   rP   rQ   Ú__classcell__r*   r*   r(   r+   r	      s2   5   ÿ"  þZ
	

c                   @   s„   e Zd ZdZeddd�Zeddd�Zeddd�Zedd„ ƒZ	ed	d
„ ƒZ
edd„ ƒZdd„ Zedd„ ƒZejdd„ ƒZddd„ZdS )r
   a@  
    Drude model based one the behavior of electons in materials (esp. metals).

    Parameters
    ----------
    amplitude : float
        Peak value
    x_0 : float
        Position of the peak
    fwhm : float
        Full width at half maximum

    Model formula:

        .. math:: f(x) = A \frac{(fwhm/x_0)^2}{((x/x_0 - x_0/x)^2 + (fwhm/x_0)^2}

    Examples
    --------

    .. plot::
        :include-source:

        import numpy as np
        import matplotlib.pyplot as plt

        from astropy.modeling.models import Drude1D

        fig, ax = plt.subplots()

        # generate the curves and plot them
        x = np.arange(7.5 , 12.5 , 0.1)

        dmodel = Drude1D(amplitude=1.0, fwhm=1.0, x_0=10.0)
        ax.plot(x, dmodel(x))

        ax.set_xlabel('x')
        ax.set_ylabel('F(x)')

        plt.show()
    r   z
Peak Value©r   r   zPosition of the peakzFull width at half maximumc                 C   s0   ||| d  | | ||   d || d   S )z6
        One dimensional Drude model function
        r   r*   )r   Ú	amplitudeÚx_0Úfwhmr*   r*   r+   rD   *  s    
ÿþÿzDrude1D.evaluatec                 C   s¬   || d | | ||   d || d   }d| | d| ||d |d   |  | d|   | | ||    d|d  |d      }d| | | d|  }|||gS )z5
        Drude1D model function derivatives.
        r   éþÿÿÿr   r,   r*   )r   rZ   r[   r\   Zd_amplitudeZd_x_0Zd_fwhmr*   r*   r+   Ú	fit_deriv5  s&    ,ÿþÿ ÿýÿüÿzDrude1D.fit_derivc                 C   s"   | j jd krd S | jd | j jiS ©Nr   )r[   r   rF   rG   r*   r*   r+   r0   L  s    zDrude1D.input_unitsc                 C   s*   || j d  || j d  || jd  dœS )Nr   )r[   r\   rZ   )rF   ÚoutputsrH   r*   r*   r+   rI   R  s    ýz'Drude1D._parameter_units_for_data_unitsc                 C   s"   | j jd krd S | jd | j jiS r_   )rZ   r   r`   rG   r*   r*   r+   Úreturn_unitsY  s    zDrude1D.return_unitsc                 C   s   t  |dk¡rtdƒ‚dS )zEnsure `x_0` is not 0.r   z!0 is not an allowed value for x_0N)r4   r5   r   )r%   Úvalr*   r*   r+   r[   _  s    zDrude1D.x_0é2   c                 C   s    | j }|| j }|| || fS )zÓTuple defining the default ``bounding_box`` limits,
        ``(x_low, x_high)``.

        Parameters
        ----------
        factor : float
            The multiple of FWHM used to define the limits.
        )r[   r\   )r%   ÚfactorZx0Zdxr*   r*   r+   Úbounding_boxe  s    	
zDrude1D.bounding_boxN)rc   )rR   rS   rT   rU   r   rZ   r[   r\   ÚstaticmethodrD   r^   rW   r0   rI   ra   Ú	validatorre   r*   r*   r*   r+   r
   ü   s    )





c                   @   sT   e Zd ZdZeddd�Zeddd�Zedd„ ƒZedd	„ ƒZ	e
d
d„ ƒZdd„ ZdS )r   a¬  One dimensional Plummer density profile model.

    Parameters
    ----------
    mass : float
        Total mass of cluster.
    r_plum : float
        Scale parameter which sets the size of the cluster core.

    Notes
    -----
    Model formula:

    .. math::

        \rho(r)=\frac{3M}{4\pi a^3}(1+\frac{r^2}{a^2})^{-5/2}

    References
    ----------
    .. [1] https://ui.adsabs.harvard.edu/abs/1911MNRAS..71..460P
    r   zTotal mass of clusterrY   z7Scale parameter which sets the size of the cluster corec                 C   s.   d| dt j |d   d| | d  d  S )z9
        Evaluate plummer density profile model.
        r,   rJ   r   r   g      À©r4   rK   )r   ÚmassÚr_plumr*   r*   r+   rD   ‘  s    ,ÿzPlummer1D.evaluatec                 C   sx   ddt j |d  | | d d d   }d| | d  d| |d   dt j |d  d| | d  d   }||gS )	z.
        Plummer1D model derivatives.
        r,   rJ   r   r   g      @é   é	   g      @rh   )r   ri   rj   Zd_massZd_r_plumr*   r*   r+   r^   š  s
    *$ÿzPlummer1D.fit_derivc                 C   s2   | j jd kr| jjd krd S | jd | jjiS d S r_   )ri   r   rj   rF   rG   r*   r*   r+   r0   ¥  s    zPlummer1D.input_unitsc                 C   s0   || j d  || jd  d  || jd  dœS )Nr   r,   )ri   rj   )r`   rF   rH   r*   r*   r+   rI   ¬  s    þz)Plummer1D._parameter_units_for_data_unitsN)rR   rS   rT   rU   r   ri   rj   rf   rD   r^   rW   r0   rI   r*   r*   r*   r+   r   t  s   þ



c                       sþ   e Zd ZdZeddejdd�Zedddd�Zedddd�Z	d	Z
e ejej¡eje	jd
df‡ fdd„	Zdd„ Zdd„ Zedd„ ƒZdd„ Zedd„ ƒZdd„ Zedd„ ƒZedd„ ƒZedd„ ƒZed d!„ ƒZd"d#„ Zed$d%„ ƒZed&d'„ ƒZd(d)„ Z‡  ZS )*r   u´  
    Navarroâ€“Frenkâ€“White (NFW) profile - model for radial distribution of dark matter.

    Parameters
    ----------
    mass : float or `~astropy.units.Quantity` ['mass']
        Mass of NFW peak within specified overdensity radius.
    concentration : float
        Concentration of the NFW profile.
    redshift : float
        Redshift of the NFW profile.
    massfactor : tuple or str
        Mass overdensity factor and type for provided profiles:
            Tuple version:
                ("virial",) : virial radius

                ("critical", N)  : radius where density is N times that of the critical density

                ("mean", N)  : radius where density is N times that of the mean density

            String version:
                "virial" : virial radius

                "Nc"  : radius where density is N times that of the critical density (e.g. "200c")

                "Nm"  : radius where density is N times that of the mean density (e.g. "500m")
    cosmo : :class:`~astropy.cosmology.Cosmology`
        Background cosmology for density calculation. If None, the default cosmology will be used.

    Notes
    -----

    Model formula:

    .. math:: \rho(r)=\frac{\delta_c\rho_{c}}{r/r_s(1+r/r_s)^2}

    References
    ----------
    .. [1] https://arxiv.org/pdf/astro-ph/9508025
    .. [2] https://en.wikipedia.org/wiki/Navarro%E2%80%93Frenk%E2%80%93White_profile
    .. [3] https://en.wikipedia.org/wiki/Virial_mass
    r   z-Peak mass within specified overdensity radiusr   ZConcentrationr   g        ZRedshiftT)ÚcriticaléÈ   Nc           	         s€   |d krddl m} | ¡ }|  |||¡ t|tjƒsFt |tj¡}n|}|  ||¡ |  	||¡ t
ƒ jf |||dœ|—Ž d S )Nr   )Údefault_cosmology©ri   ÚconcentrationÚredshift)Zastropy.cosmologyro   r   Ú_density_deltar-   r   r.   ÚM_sunÚ	_radius_sÚ
_density_sr#   r$   )	r%   ri   rq   rr   Ú
massfactorÚcosmor'   ro   Úin_massr(   r*   r+   r$   ó  s     
  ÿÿzNFW.__init__c                 C   sp   t |dƒr|}nt |tj¡}||  ||¡ |j¡ }|  ||¡|t d¡| d   }t |dƒrf|S |jS dS )a2  
        One dimensional NFW profile function

        Parameters
        ----------
        r : float or `~astropy.units.Quantity` ['length']
            Radial position of density to be calculated for the NFW profile.
        mass : float or `~astropy.units.Quantity` ['mass']
            Mass of NFW peak within specified overdensity radius.
        concentration : float
            Concentration of the NFW profile.
        redshift : float
            Redshift of the NFW profile.

        Returns
        -------
        density : float or `~astropy.units.Quantity` ['density']
            NFW profile mass density at location ``r``. The density units are:
            [``mass`` / ``r`` ^3]

        Notes
        -----
        .. warning::

            Output values might contain ``nan`` and ``inf``.
        r   r   r   N)	r   r   r.   Úkpcru   r@   r   rv   r!   )r%   Úrri   rq   rr   Úin_rZradius_reducedZdensityr*   r*   r+   rD     s    

ÿ
zNFW.evaluatec              	   C   s°  t |tƒr†|d  ¡ dkr,d}|d  ¡ }nX|d  ¡ dkrNt|d ƒ}d}n6|d  ¡ dkrpt|d ƒ}d}ntd	|d › d
�ƒ‚n˜zl| ¡ dkr¢d}| ¡ }nN|d  ¡ dksÂ|d  ¡ dkràt|dd… ƒ}|d  ¡ }ntd|› d�ƒ‚W n* ttfk
�r   td|› d�ƒ‚Y nX |dk�rj| |¡d }dtj	d  d|  d|d   }|| 
|¡ | _n@|dk�r†|| 
|¡ | _n$|dk�rª|| 
|¡ | |¡ | _| jS )z*
        Calculate density delta.
        r   ZvirialNrm   r   r>   ZmeanÚmzMassfactor 'z,' not one of 'critical', 'mean', or 'virial'éÿÿÿÿzMassfactor z/ string not of the form '#m', '#c', or 'virial'z not a tuple or stringr   g      2@r   g     €T@g     €C@)r-   ÚtupleÚlowerÚfloatr    ÚAttributeErrorÚ	TypeErrorZOmr4   rK   Zcritical_densityÚdensity_delta)r%   rw   rx   rr   ÚdeltaZmasstypeZOm_cZd_cr*   r*   r+   rs   G  sF    
ÿ
 
ÿ
"

ÿzNFW._density_deltac                 C   s   t  d|  ¡| d|    S )zú
        Dimensionless volume integral of the NFW profile, used as an intermediate step in some
        calculations for this model.

        Notes
        -----

        Model formula:

        .. math:: A_{NFW} = [\ln(1+y) - \frac{y}{1+y}]
        r   )r4   Úlog)rC   r*   r*   r+   ÚA_NFW†  s    z	NFW.A_NFWc                 C   sP   t |tjƒst |tj¡}n|}|dtj |  ||¡d  |  |¡  | _| jS )z=
        Calculate scale density of the NFW profile.
        ç      @r,   )	r-   r   r.   rt   r4   rK   ru   r‡   Ú	density_s©r%   ri   rq   ry   r*   r*   r+   rv   •  s    ÿþýÿzNFW._density_sc                 C   s   | j S )ze
        Scale density of the NFW profile. Often written in the literature as :math:`\rho_s`
        )r‰   rG   r*   r*   r+   Ú	rho_scaleª  s    zNFW.rho_scalec                 C   sP   t |tjƒst |tj¡}n|}d| dtj | j  d | | _| j tj	¡S )z<
        Calculate scale radius of the NFW profile.
        g      @rˆ   gUUUUUUÕ?)
r-   r   r.   rt   r4   rK   r„   Úradius_sr@   rz   rŠ   r*   r*   r+   ru   ±  s    þzNFW._radius_sc                 C   s   | j S )z2
        Scale radius of the NFW profile.
        )rŒ   rG   r*   r*   r+   Úr_sÇ  s    zNFW.r_sc                 C   s   | j | j S )zn
        Mass factor defined virial radius of the NFW profile (R200c for M200c, Rvir for Mvir, etc.).
        )r�   rq   rG   r*   r*   r+   Úr_virialÎ  s    zNFW.r_virialc                 C   s
   | j d S )z6
        Radius of maximum circular velocity.
        g”Þ7¾öL@)r�   rG   r*   r*   r+   Úr_maxÕ  s    z	NFW.r_maxc                 C   s   |   | j¡S )z,
        Maximum circular velocity.
        )Úcircular_velocityr�   rG   r*   r*   r+   Úv_maxÜ  s    z	NFW.v_maxc              	   C   s¦   t |dƒr|}nt |tj¡}t | jtj 	|j
d | jj
tjd   ¡ | j ¡}|| j 	|j
¡ }t |d |  | j| ¡ ||  | j¡  ¡}| 	tjtj ¡S )a¶  
        Circular velocities of the NFW profile.

        Parameters
        ----------
        r : float or `~astropy.units.Quantity` ['length']
            Radial position of velocity to be calculated for the NFW profile.

        Returns
        -------
        velocity : float or `~astropy.units.Quantity` ['speed']
            NFW profile circular velocity at location ``r``. The velocity units are:
            [km / s]

        Notes
        -----

        Model formula:

        .. math:: v_{circ}(r)^2 = \frac{1}{x}\frac{\ln(1+cx)-(cx)/(1+cx)}{\ln(1+c)-c/(1+c)}

        .. math:: x = r/r_s

        .. warning::

            Output values might contain ``nan`` and ``inf``.
        r   r,   r   )r   r   r.   rz   r4   Úsqrtri   r:   ÚGr@   r   rN   rŽ   r‡   rq   Úkm)r%   r{   r|   Z	v_profileZreduced_radiusÚvelocityr*   r*   r+   r�   ã  s"    
"ÿþÿÿÿzNFW.circular_velocityc                 C   s   | j d tjiS r_   )rF   r   rz   rG   r*   r*   r+   r0     s    zNFW.input_unitsc                 C   sZ   | j jd kr0| jd tj| j| jd  d  iS | jd | j j| j| jd  d  iS d S )Nr   r,   )ri   r   r`   r   rt   r0   rF   rG   r*   r*   r+   ra     s
    $ ÿzNFW.return_unitsc                 C   s   t jd d dœS )Nrp   )r   rt   rH   r*   r*   r+   rI   )  s    z#NFW._parameter_units_for_data_units) rR   rS   rT   rU   r   r   rt   ri   rq   rr   rV   r.   r   r   r$   rD   rs   rf   r‡   rv   rW   r‹   ru   r�   rŽ   r�   r‘   r�   r0   ra   rI   rX   r*   r*   r(   r+   r   ³  sL   .üú#1?





6


)rU   r8   Únumpyr4   Zastropyr   r:   r   r   Zastropy.utils.exceptionsr   Úcorer   Ú
parametersr   r   Ú__all__r	   r
   r   r   r*   r*   r*   r+   Ú<module>   s    hx?