
    IR-eg                         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 g d	Z G d
 de          Z G d de          Z G d de          Z G d de          ZdS )z$
Models that have physical origins.
    N)	constants)units)AstropyUserWarning   )Fittable1DModel)InputParameterError	Parameter)	BlackBodyDrude1D	Plummer1DNFWc                       e Zd ZdZ eddej        d          Z eddd          Zd	Z	d
 ej
                    iZej        ej        dz  ej        z  ej        z  ej        z  z  Zej        ej        dz  ej        z  ej        z  ej        z  z  ej        ej        dz  ej        z  ej        z  ej        z  z  dZ fdZd Zed             Zd Zed             Zed             Zed             Z xZS )r
   aY  
    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 / (Hz s sr cm2)>

    .. 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   )SNUSLAMc                    |                     dd           }t          |d          r|j                            t          j                  se|j        }|                    | j        t	          j        dt          j        z                      st          d|           |j
        |d<   || _        n| j        | _         t                      j        |i |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   output_units	__class__s        @lib/python3.11/site-packages/astropy/modeling/physical_models.pyr(   zBlackBody.__init__c   s    

7D)) 5&!! 	4%**B*B$+
 +
 	4 !:L--"A$6q14x$@$@   !:+7: :  
 $kF7O!-D!%!3Duww0000    c                 .   t          |t          j                  s t          j        |t          j                  }n|}t          |t          j                  s!t          j        || j        d                   }n|}t          j        t          j                    t          j                    z             5  t          j        |t          j        t          j
                  }t          j        |t          j                  }ddd           n# 1 swxY w Y   t          j        |dk               rt          d|           t          j        t          j        |                    rt          j        |dk              rt          j        dt"                     t$          j        |z  t$          j        |z  z  }t          j        |          }	dt$          j        z  |dz  z  t$          j        d	z  |	z  z  t          j        z  }
| j        j        Ct5          |d
          s|| j        j        z  }|                    t          j                  j        }||
                    | j        t          j        |                    z  }t5          |d
          r|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   )dtypeNr   z Temperature should be positive: z4Input contains invalid wavelength/frequency value(s)g       @   r   r   ) 
isinstancer   QuantityKinput_unitsadd_enabled_equivalenciesspectraltemperatureHznpfloat64anyr$   allisfinitewarningswarnr   consthk_Bexpm1csrr   r   r   tor    r%   r&   r"   )r)   r   r9   r   in_tempin_xfreqtemp	log_boltzboltzm1bb_nuys               r.   evaluatezBlackBody.evaluate{   sj   N +qz22 	"jac22GG!G!QZ(( 	 :a!1#!677DDD ()GHH 	, 	,:dAD
;;;D:gqs++D	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	, 	,
 6$( 	HFFFGGGvbk$''(( 	BF419,=,= 	MF"  
 GdNei$&67	(9%% ega'57A:+?@14G:?&5&)) 0 
/HHQ566<E EHHT/1CD1I1IJJJ
 ;'' 	Hws   3AD

DDc                     | j                             | j        d                   r| j        d         t          j        iS | j        d         t          j        iS )Nr   r   )r&   r   _native_output_unitsinputsr   r:   r#   r)   s    r.   r6   zBlackBody.input_units   sM     ++D,Ee,LMM 	*KNAD)) KNAD))r/   c                     dt           j        iS )Nr9   )r   r5   r)   inputs_unitoutputs_units      r.   _parameter_units_for_data_unitsz)BlackBody._parameter_units_for_data_units   s    qs##r/   c                 L   | j         j        *| j         j                            t          j                  }n| j         j        }|t          j        z  | j	        dz  z  t          j        z  }|                    t          j        t          j        dz  t          j        z  z            S )zBolometric flux.N   r   )r   r   quantityrH   r   r    r%   rB   sigma_sbr9   r;   piergcms)r)   r   native_bolfluxs      r.   bolometric_fluxzBlackBody.bolometric_flux   s~     :?&J'**1+CDDEEJ$E /$2BA2EEM  !$'AC-!8999r/   c                 *    t           j        | j        z  S )z=Peak wavelength when the curve is expressed as power density.)rB   b_wienr9   rU   s    r.   
lambda_maxzBlackBody.lambda_max   s     |d...r/   c                 J    dt           j        z  | j        z  t           j        z  S )z<Peak frequency when the curve is expressed as power density.g>N@)rB   rD   r9   rC   rU   s    r.   nu_maxzBlackBody.nu_max   s      59$t'77%'AAr/   )__name__
__module____qualname____doc__r	   r   r5   r9   r    _input_units_allow_dimensionlessr8   input_units_equivalenciesr`   ra   rb   r:   rG   r!   r#   rS   r(   rQ   propertyr6   rZ   rd   rg   ri   __classcell__r-   s   @r.   r
   r
      s       1 1h )AAC5L  K IcqnEEEE (,$ "%jajll 3 EQT1Wqs]QT1AD89M ua!#,qt34q13-45 
1 1 1 1 10X X Xt * * X*$ $ $ : : X: / / X/ B B XB B B B Br/   r
   c                       e Zd ZdZ edd          Z edd          Z edd          Zed             Z	ed             Z
ed	             Zd
 Zed             Zd Zee_        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                 H    |||z  dz  z  | |z  || z  z
  dz  ||z  dz  z   z  S )z7
        One dimensional Drude model function.
        r    )r   	amplitudex_0fwhms       r.   rQ   zDrude1D.evaluate(  sE     s
q "C#'!a'4#:!*;;=	
r/   c                     ||z  dz  | |z  || z  z
  dz  ||z  dz  z   z  }d|z  |z  d|z  ||dz  |dz  z  z  |  |z  d| z  z
  | |z  || z  z
  z  d|dz  z  |dz  z  z
  z  z   z  }d|z  |z  |z  d|z
  z  }|||gS )z5
        Drude1D model function derivatives.
        r   r   r2   rv   )r   rw   rx   ry   d_amplituded_x_0d_fwhms          r.   	fit_derivzDrude1D.fit_deriv3  s    
 cza'AGcAg,=!+CtczVWFW+WX S6D!G#% R#XA%!c'C!G*;<47{S!V+-	 	 i-+-4[IUF++r/   c                 P    | j         j        d S | j        d         | j         j        iS Nr   )rx   
input_unitrT   rU   s    r.   r6   zDrude1D.input_unitsJ  s(    8&4A 344r/   c                 t    || j         d                  || j         d                  || j        d                  dS )Nr   )rx   ry   rw   )rT   outputsrW   s      r.   rZ   z'Drude1D._parameter_units_for_data_unitsP  s;    t{1~.A/%dl1o6
 
 	
r/   c                 P    | j         j        d S | j        d         | j         j        iS r   )rw   r   r   rU   s    r.   return_unitszDrude1D.return_unitsW  s(    >&4Q!455r/   c                 T    t          j        |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)r;   r=   r   )r)   vals     r.   _x_0_validatorzDrude1D._x_0_validator]  s4    6#( 	K%&IJJJ	K 	Kr/   2   c                 8    | j         }|| j        z  }||z
  ||z   fS )zTuple defining the default ``bounding_box`` limits,
        ``(x_low, x_high)``.

        Parameters
        ----------
        factor : float
            The multiple of FWHM used to define the limits.
        )rx   ry   )r)   factorx0dxs       r.   bounding_boxzDrude1D.bounding_boxd  s*     XdiRb!!r/   N)r   )rj   rk   rl   rm   r	   rw   rx   ry   staticmethodrQ   r   rp   r6   rZ   r   r   
_validatorr   rv   r/   r.   r   r      s       & &P 	#<@@@I
)C-C
D
D
DC9S.JKKKD
 
 \
 , , \,, 5 5 X5

 
 
 6 6 X6
K K K
 $CN" " " " " "r/   r   c                       e Zd ZdZ edd          Z edd          Zed             Zed             Z	e
d             Z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 clusterrt   z7Scale parameter which sets the size of the cluster corec                 V    d|z  dt           j        z  |dz  z  z  d| |z  dz  z   dz  z  S )z9
        Evaluate plummer density profile model.
        r2   r\   r   r   g      r;   r_   )r   massr_plums      r.   rQ   zPlummer1D.evaluate  s<     X!be)fai/0AV8I4Iv3VV	
r/   c                     ddt           j        z  |dz  z  | |z  dz  dz   dz  z  z  }d|z  | dz  z  d|z  |dz  z  z
  dt           j        z  |dz  z  d| |z  dz  z   dz  z  z  }||gS )	z.
        Plummer1D model derivatives.
        r2   r\   r   r   g      @   	   g      @r   )r   r   r   d_massd_r_plums        r.   r   zPlummer1D.fit_deriv  s    
 q25y619,1v:!2Ca2GU1STUHq!tOa$h&::Y"qAJ1+<'<%&HH
 !!r/   c                 \    | j         j        }| j        j        }||d S | j        d         |iS r   )r   r   r   rT   )r)   	mass_unitr_plum_units      r.   r6   zPlummer1D.input_units  s7    I(	k,!44A,,r/   c                 ~    || j         d                  || j        d                  dz  z  || j        d                  dS )Nr   r2   )r   r   )r   rT   rW   s      r.   rZ   z)Plummer1D._parameter_units_for_data_units  sC     a1KA4OST4TT!$+a.1
 
 	
r/   N)rj   rk   rl   rm   r	   r   r   r   rQ   r   rp   r6   rZ   rv   r/   r.   r   r   s  s         , 9S.EFFFDYM  F
 
 
 \
 " " \" - - X-
 
 
 
 
r/   r   c                       e Zd ZdZ eddej        d          Z eddd          Z eddd          Z	d	Z
 ej        ej        ej                  ej        e	j        d
df fd	Zd Zd Zed             Zd Zed             Zd Zed             Zed             Zed             Zed             Zd Zed             Zed             Zd Z x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   Concentrationr   g        RedshiftT)critical   Nc                 x   |ddl m} |                                }|                     |||           t	          |t
          j                  s t          j        |t
          j                  }n|}|                     ||           | 	                    ||            t                      j        d|||d| d S )Nr   )default_cosmologyr   concentrationredshiftrv   )astropy.cosmologyr   r   _density_deltar3   r   r4   M_sun	_radius_s
_density_sr'   r(   )
r)   r   r   r   
massfactorcosmor+   r   in_massr-   s
            r.   r(   zNFW.__init__  s     =;;;;;;%))++E 	Jx888 $
++ 	jqw//GGG 	t]+++ 	m,,, 	
	
 	
LR	
 	
 	
 	
 	
r/   c                 b   t          |d          r|}nt          j        |t          j                  }||                     ||                              |j                  z  }|                     ||          |t          j        d          |z   dz  z  z  }t          |d          r|S |j        S )a3  
        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   )	r   r   r4   kpcr   rH   r   r   r%   )r)   rr   r   r   in_rradius_reduceddensitys           r.   rQ   zNFW.evaluate  s    8 1f 	(DD:a''D t] C C F Fty Q QQ
 //$66ajoo>1DD
 4   	!N= r/   c                    t          |t                    r|d                                         dk    rd}|d                                         }n`|d                                         dk    rt          |d                   }d}n)|d                                         dk    rt          |d                   }d}nt	          d	|d          d
          	 |                                dk    rd}|                                }n|d                                         dk    s|d                                         dk    r2t          |dd                   }|d                                         }nt	          d| d          n(# t
          t          f$ r t          d| d          w xY w|dk    rW|                    |          dz
  }dt          j	        dz  z  d|z  z   d|dz  z  z
  }||
                    |          z  | _        n]|dk    r||
                    |          z  | _        n9|dk    r3||
                    |          z  |                    |          z  | _        | j        S )z*
        Calculate density delta.
        r   virialNr   r   rF   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@)r3   tuplelowerfloatr$   AttributeError	TypeErrorOmr;   r_   critical_densitydensity_delta)r)   r   r   r   deltamasstypeOm_cd_cs           r.   r   zNFW._density_deltaH  s   
 j%(( *	R
 !}""$$00%a=..00A$$&&*44jm,,A$$&&&00jm,, *:a= * * *  
R
 ##%%11 E)//11HH^))++s22jn6J6J6L6LPS6S6S!*QrT"233E)"~3355HH$2j 2 2 2   #I. R R R Pj P P PQQQR x88H%%+D/D4K/$q.@C!$u'='=h'G'G!GD__!&)?)?)I)I!ID__..x888588H;M;MM  !!s   B0F
 
%F/c                 B    t          j        d| z             | d| z   z  z
  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   )r;   log)rP   s    r.   A_NFWz	NFW.A_NFW  s#     vcAg!sQw-00r/   c                    t          |t          j                  s t          j        |t          j                  }n|}|dt          j        z  |                     ||          dz  z  |                     |          z  z  | _        | j        S )z=
        Calculate scale density of the NFW profile.
              @r2   )	r3   r   r4   r   r;   r_   r   r   	density_sr)   r   r   r   s       r.   r   zNFW._density_s  s    
 $
++ 	jqw//GGG !ennWm449: jj''(
 ~r/   c                     | j         S )zf
        Scale density of the NFW profile. Often written in the literature as :math:`\rho_s`.
        )r   rU   s    r.   	rho_scalezNFW.rho_scale  s    
 ~r/   c                    t          |t          j                  s t          j        |t          j                  }n|}d|z  dt          j        z  | j        z  z  dz  |z  | _        | j                            t          j	                  S )z<
        Calculate scale radius of the NFW profile.
        g      @r   gUUUUUU?)
r3   r   r4   r   r;   r_   r   radius_srH   r   r   s       r.   r   zNFW._radius_s  sy    
 $
++ 	jqw//GGG Gmbed.@ @AyQ }&&&r/   c                     | j         S )z2
        Scale radius of the NFW profile.
        )r   rU   s    r.   r_szNFW.r_s  s    
 }r/   c                      | j         | j        z  S )zn
        Mass factor defined virial radius of the NFW profile (R200c for M200c, Rvir for Mvir, etc.).
        )r   r   rU   s    r.   r_virialzNFW.r_virial  s    
 x$,,,r/   c                     | j         dz  S )z6
        Radius of maximum circular velocity.
        g7L@)r   rU   s    r.   r_maxz	NFW.r_max  s    
 x'!!r/   c                 6    |                      | j                  S )z,
        Maximum circular velocity.
        )circular_velocityr   rU   s    r.   v_maxz	NFW.v_max  s    
 %%dj111r/   c           	      t   t          |d          r|}nt          j        |t          j                  }t	          j        | j        t          j        	                    |j
        dz  | j        j
        t          j        dz  z  z            z  | j        z            }|| j        	                    |j
                  z  }t	          j        |dz  |                     | j        |z            z  ||                     | j                  z  z            }|	                    t          j        t          j        z            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   r2   r   )r   r   r4   r   r;   sqrtr   rB   GrH   r   rb   r   r   r   km)r)   r   r   	v_profilereduced_radiusvelocitys         r.   r   zNFW.circular_velocity  s   8 1f 	(DD:a''D GIgjjA!#q&)@ABBCm
 
	  0 0 ; ;;
 7\DJJt'9N'JKKK

4+= > >>@
 

 {{14!#:&&&r/   c                 4    | j         d         t          j        iS r   )rT   r   r   rU   s    r.   r6   zNFW.input_units  s     A&&r/   c                     | j         j        5| j        d         t          j        | j        | j        d                  dz  z  iS | j        d         | j         j        | j        | j        d                  dz  z  iS )Nr   r2   )r   r   r   r   r   r6   rT   rU   s    r.   r   zNFW.return_units  sn     9>!LOQWt/?A/OST/T%TUU Q$2B4;q>2RVW2W!W r/   c                 "    t           j        d d dS )Nr   )r   r   rW   s      r.   rZ   z#NFW._parameter_units_for_data_units(  s    $DIIIr/   ) rj   rk   rl   rm   r	   r   r   r   r   r   rn   r4   r   r   r(   rQ   r   r   r   r   rp   r   r   r   r   r   r   r   r6   r   rZ   rq   rr   s   @r.   r   r     s       ( (Z 9WC	  D IcsPPPM y#:FFFH (,$ QZdi00#+!$!
 !
 !
 !
 !
 !
F/! /! /!b=" =" ="~ 1 1 \1  *   X' ' ',   X - - X- " " X" 2 2 X23' 3' 3'j ' ' X'   XJ J J J J J Jr/   r   )rm   r@   numpyr;   astropyr   rB   r   r   astropy.utils.exceptionsr   corer   
parametersr   r	   __all__r
   r   r   r   rv   r/   r.   <module>r      sr   
      & & & & & &       7 7 7 7 7 7 ! ! ! ! ! ! 6 6 6 6 6 6 6 6
6
6
6cB cB cB cB cB cB cB cBLu" u" u" u" u"o u" u" u"p?
 ?
 ?
 ?
 ?
 ?
 ?
 ?
DtJ tJ tJ tJ tJ/ tJ tJ tJ tJ tJr/   