Пример #1
0
class ISO(Fittable1DModel):
    '''ISO dark mater halo model
    Inputs:
        r:  array_like.
            Radius in Kpc.

        Parameters of ISO model.
        rho_0:    float or int.
            Central mass density in 10^-3 Msol/pc^3.
        rc: float or int.
            Core radius in Kpc.
    Outputs
        v:  array_like.
            velocity in km/s.
    '''
    inputs = ('r', )
    outputs = ('v', )

    rho_0 = Parameter(bounds=(1e-8, 1e3))
    rc = Parameter(bounds=(0, 300))
    fit_deriv = None

    @staticmethod
    def evaluate(r, rho_0, rc):
        '''ISO dark mater halo function.
        '''
        r = r * u.kpc
        rho_0 = rho_0 * 10**(-3) * u.M_sun / (u.pc)**3
        rc = rc * u.kpc
        c = (rc / r).value
        v = np.sqrt(4 * np.pi * G * rho_0 * np.power(rc, 2) *
                    (1.0 - c * np.arctan(1 / c)))
        v = v.to(u.km / u.s)
        v = v.value
        return (v)
Пример #2
0
class SEDModel(FittableModel):
    """


    Parameters
    ----------
    spectrum : specutils.Spectrum1D
    filters : wsynphot.FilterSet
    distance : float
        distance to the supernova in Mpc
    fraction : float
        fraction of luminosity in the spectrum
    """

    inputs = ('luminosity')
    outputs = ('flux')

    distance = Parameter()
    fraction = Parameter(default=1.0)


    def __init__(self, spectrum, distance, fraction=1.0):
        assert False # unusable for now
        super(SEDModel, self).__init__(distance=distance, fraction=fraction)
        assert spectrum.unit == u.erg / u.s / u.angstrom
        luminosity_density = spectrum.data * spectrum.unit
        norm_factor = np.trapz(luminosity_density, spectrum.wavelength)
        self.normed_luminosity_density = (luminosity_density / norm_factor)

    def evaluate(self, luminosity, distance, fraction):
        luminosity_density = (
            self.normed_luminosity_density * luminosity * fraction)
        return luminosity_density / 4 * np.pi * (distance * mpc_to_cm) ** 2
Пример #3
0
class Paczynski1990Velocity(Fittable1DModel):
    r"""Distribution by Lyne 1982 and adopted by Paczynski and Faucher.

    .. math::
        f(v) = A\frac{4}{\pi} \frac{1}{v_0 \left[1 + (v / v_0) ^ 2 \right] ^ 2}

    Reference: https://ui.adsabs.harvard.edu/abs/1990ApJ...348..485P (Formula (3))

    Parameters
    ----------
    amplitude : float
        Value of the integral
    v_0 : float
        Velocity parameter (km s^-1)
    """

    amplitude = Parameter()
    v_0 = Parameter()

    def __init__(self, amplitude=1, v_0=560, **kwargs):
        super().__init__(amplitude=amplitude, v_0=v_0, **kwargs)

    @staticmethod
    def evaluate(v, amplitude, v_0):
        """One dimensional Paczynski 1990 velocity model function."""
        return amplitude * 4.0 / (np.pi * v_0 * (1 + (v / v_0) ** 2) ** 2)
Пример #4
0
class Exponential(Fittable1DModel):
    """Exponential distribution.

    .. math ::
        f(z) = A \\exp \\left(- \\frac{|z|}{z_0} \\right)

    Usually used for height distribution above the Galactic plane,
    with 0.05 kpc as a commonly used birth height distribution.

    Parameters
    ----------
    amplitude : float
        See model formula
    z_0 : float
        Scale height of the distribution

    See Also
    --------
    CaseBattacharya1998, Paczynski1990, YusifovKucuk2004, Lorimer2006,
    YusifovKucuk2004B, FaucherKaspi2006, Exponential
    """

    amplitude = Parameter()
    z_0 = Parameter()
    evolved = False

    def __init__(self, amplitude=1, z_0=0.05, **kwargs):
        super(Exponential, self).__init__(amplitude=amplitude,
                                          z_0=z_0,
                                          **kwargs)

    @staticmethod
    def evaluate(z, amplitude, z_0):
        """Evaluate model."""
        return amplitude * np.exp(-np.abs(z) / z_0)
class FLCDM(Fittable1DModel):
    """
    All parameters go here.
    """
    H0 = Parameter(default=1.)
    Om = Parameter(default=1.)
    Ol = Parameter(default=1.)

    @staticmethod
    def evaluate(x, H0, Om, Ol):
        c = 2.99792458E+5
        return np.log10((c*(1.+x)/H0) * (((1.+x)**3.)*Om + Ol)**-0.5)

    @staticmethod
    def fit_deriv(x, H0, Om, Ol):
        """
        Logged DL.
        These are the derivatives of the DL func for the Lambda CDM model. 
        x - the z that is not part of the integral.
        """
        c = 2.99792458E+5
        #d_H0 = -0.434294/H0
        #d_H0 = np.ones(x.shape)
        d_H0 = np.ones(x.shape) * -0.434294/H0
        d_Om = -(0.217147*(x + 1)**3)/(Om*(x + 1)**3 + Ol)
        d_Ol = -0.217147/(Om*(x + 1)**3 + Ol)
        return [d_H0, d_Om, d_Ol]
Пример #6
0
class PsfModel(Fittable2DModel):

    x_0 = Parameter(default=1, min=0)
    y_0 = Parameter(default=1, min=0)
    I_0 = Parameter(default=1, min=1e-5)

    def __init__(self,
                 psf,
                 x_0=x_0.default,
                 y_0=y_0.default,
                 I_0=I_0.default,
                 **kwargs):
        self.psf = psf
        super().__init__(x_0, y_0, I_0, **kwargs)
        return None

    def evaluate(self, x, y, x_0, y_0, I_0):

        canvas = np.zeros_like(x)
        Npsf, Mpsf = self.psf.shape
        N, M = x.shape

        if x.shape > self.psf.shape:
            canvas[:Npsf, :Mpsf] = self.psf
        else:
            diffN = Npsf - N
            diffM = Npsf - N
            canvas = self.psf[diffN // 2:-diffN // 2, diffM // 2:-diffM // 2]

        xCen, yCen = barycenter(canvas, np.ones_like(canvas))
        dx = (x_0 - xCen)
        dy = (y_0 - yCen)
        finalPSF = shift(canvas, (dx, dy), order=2)
        return I_0 * finalPSF
Пример #7
0
class single_cog_model(FittableModel):
    """Generate a single COG model

    Parameters
    ----------
    logN
    b

    input : wrest*f
    output : redEW
      reduced EWs
    """
    inputs = ('wrestxf', )
    outputs = ('redEW', )

    # Free parameters (generally)
    logN = Parameter()
    b = Parameter()  # Assumes km/s

    # Fixed parameters

    @staticmethod
    def evaluate(wrestf, logN, b):
        # F(tau0)
        tau0 = 1.497e-15 * (wrestf) * (10.**logN) / b
        Ftau0 = intFtau0(tau0)
        # Finish
        redEW = 2 * b * Ftau0 / 3e5
        return redEW
Пример #8
0
class mflux_tauevo(FittableModel):
    """ Mean flux evolution * exp(delta*(lambda/1280-1)),
    Meant for use with astropy.modeling to correct the fitted Lya forest continuum
    Abscissa parameter x is the restframe wavelength, and free parameters p0, p1
    set the power law.
    This function NEEDS the quasar redshift zqso to be set

    input: lambda_r :: Rest wavelength Assumed in Angstroms
    output: absorbed, normalized flux
    Parameters: logN,b,z,wrest,f,gamma,fwhm
    """
    inputs = ('lambda_r',)
    outputs = ('flux',)

    # Free parameters (generally)
    p0 = Parameter()
    p1 = Parameter()

    # Fixed parameters
    zqso = Parameter(fixed=True)
    lamb_piv = Parameter(fixed=True)

    @staticmethod
    def evaluate(lambda_r, p0, p1, zqso, lamb_piv): #logN,b,z,wrest,f,gamma,fwhm):
        zfor = (lambda_r/1216.) * (1. + zqso) - 1.
        tau = pyteff.lyman_alpha_obs(zfor)
        #tau = old_taueff_evo(zfor)
        fmean = np.exp(-1*tau)

        mfluxtauevo = fmean * mfluxcorr(lambda_r, p0, p1, lamb_piv=lamb_piv)
        return mfluxtauevo
Пример #9
0
class Paczynski1990(Fittable1DModel):
    """Radial distribution of the birth surface density of neutron stars - Paczynski 1990.

    .. math ::
        f(r) = A r_{exp}^{-2} \\exp \\left(-\\frac{r}{r_{exp}} \\right)

    Reference: http://adsabs.harvard.edu/abs/1990ApJ...348..485P (Formula (2))

    Parameters
    ----------
    amplitude : float
        See formula
    r_exp : float
        See formula

    See Also
    --------
    CaseBattacharya1998, YusifovKucuk2004, Lorimer2006, YusifovKucuk2004B,
    FaucherKaspi2006, Exponential
    """

    amplitude = Parameter()
    r_exp = Parameter()
    evolved = False

    def __init__(self, amplitude=1, r_exp=4.5, **kwargs):
        super(Paczynski1990, self).__init__(amplitude=amplitude,
                                            r_exp=r_exp,
                                            **kwargs)

    @staticmethod
    def evaluate(r, amplitude, r_exp):
        """Evaluate model."""
        return amplitude * r_exp**-2 * np.exp(-r / r_exp)
Пример #10
0
class Powerlaw(FittableModel):
    """
    Represents a simple power-law curve

    The curve is defined as

        amplitude * (t_offset)**alpha

    Be wary of using an init_alpha<0, since this results in an asymptote at
    t=0.

    NB  The curve will always begin at the origin, because maths.
    (Cannot raise a negative number to a fractional power unless you
    deal with complex numbers. Also 0.**Y == 0. )
    """
    inputs = ('t', )
    outputs = ('flux', )

    init_amp = Parameter()
    alpha_one = Parameter()
    t_offset_min = Parameter(default=0.)
    t0 = Parameter(default=0.)

    @staticmethod
    def evaluate(t, init_amp, alpha_one, t_offset_min, t0):
        if np.ndim(t) == 0:
            t = np.asarray(t, dtype=np.float).reshape((1, ))
        t_offset = t - t0
        result = np.zeros_like(t_offset)
        t_valid = t_offset >= t_offset_min
        result[t_valid] = (init_amp * np.power(t_offset[t_valid], alpha_one))
        return result
class FlatLambdaCDM(FIttable1dModel):
    """
    All parameters go here.
    """
    #c = Parameter(default=1.)
    #H0 = Parameter(default=1.)
    Om = Parameter(default=0.27)
    Ol = Parameter(default=1.-0.27)
    z = Parameter(default=1.)

    @staticmethod
    def evaluate(x, z, Om, Ol):
        H0 = 71.
        c = 2.99792458E+5
        return (c*(1.+x)/H0) * (((1.+z)**3.)*Om + Ol)**-0.5
    
    @staticmethod
    def fit_deriv(x, z, Om, Ol):
        """
        These are the derivatives of the DL func for the Lambda CDM model. 
        x - the z that is not part of the integral.
        """
        H0 = 71.
        c = 2.99792458E+5
        d_z = (-1.5*Om*(1+z)**2)/((Om*(1+z)**3 + Ol)**1.5)
        d_Om = -(0.5*(1+z)**3)/(Om*(1+z)**3 + Ol)**1.5
        d_Ol = -0.5/(Om*(1+z)**3 + Ol)**1.5
        A = (c*(1.+x)/H0)
        d_z = A * d_z
        d_Om = A * d_Om
        d_Ol = A * d_Ol
        # np.ones(x.shape)
        return [d_z, d_Om, d_Ol]
Пример #12
0
class FaucherKaspi2006VelocityMaxwellian(Fittable1DModel):
    r"""Maxwellian pulsar velocity distribution.

    .. math::
        f(v) = A \sqrt{ \frac{2}{\pi}} \frac{v ^ 2}{\sigma ^ 3 }
               \exp \left(-\frac{v ^ 2}{2 \sigma ^ 2} \right)

    Reference: https://ui.adsabs.harvard.edu/abs/2006ApJ...643..332F

    Parameters
    ----------
    amplitude : float
        Value of the integral
    sigma : float
        Velocity parameter (km s^-1)
    """

    amplitude = Parameter()
    sigma = Parameter()

    def __init__(self, amplitude=1, sigma=265, **kwargs):
        super().__init__(amplitude=amplitude, sigma=sigma, **kwargs)

    @staticmethod
    def evaluate(v, amplitude, sigma):
        """One dimensional velocity model function."""
        term1 = np.sqrt(2 / np.pi) * v ** 2 / sigma ** 3
        term2 = np.exp(-v ** 2 / (2 * sigma ** 2))
        return term1 * term2
Пример #13
0
class Plummer2D(Fittable2DModel):
    """
    Two-dimensional Plummer surface brightness profile.

    Parameters
    ----------
    amplitude : float
        Central surface brightness.
    scale_radius : float
        Characteristic scale radius of the mass distribution.
    x_0 : float, optional
        x position of the center.
    y_0 : float, optional
        y position of the center.
    """

    amplitude = Parameter(default=1)
    scale_radius = Parameter(default=1)
    x_0 = Parameter(default=0)
    y_0 = Parameter(default=0)

    @classmethod
    def evaluate(cls, x, y, amplitude, scale_radius, x_0, y_0):
        """Two-dimensional Plummer profile evaluation function."""
        r = np.sqrt((x - x_0)**2 + (y - y_0)**2)
        return amplitude / (1 + (r / scale_radius)**2)**2
Пример #14
0
class SymmetricMoffat2D(PSF):
    """Moffat 2D profile (normalized).  The shape is parametrized in terms
    of FWHM and alpha rather than alpha and gamma for historical reasons."""
    amplitude = Parameter(name='amplitude',default=1.)
    x_0       = Parameter(name='x_0',default=0.)
    y_0       = Parameter(name='y_0',default=0.)
    fwhm      = Parameter(name='fhwm',default=1.)
    alpha     = Parameter(name='alpha',default=3.)
    
    @fwhm.validator
    def fwhm(self, value):
        # Remember, the value can be an array
        if np.any(value <= 0.):
            raise InputParameterError(
                    "parameter 'fwhm' must be greater than zero ")

    @alpha.validator
    def alpha(self, value):
        # Remember, the value can be an array
        if np.any(value <= 1.):
            raise InputParameterError(
                    "parameter 'alpha' must be greater than 1")            
            
    @staticmethod
    def _evaluate(x,y,amplitude,x_0,y_0,fwhm,alpha):
        """The true 'evaluate' method without oversampling"""
        gamma = 0.5 * fwhm/np.sqrt(2**(1./alpha) - 1.)
        rr_gg = ((x - x_0) ** 2 + (y - y_0) ** 2) / gamma ** 2    
        return amplitude * (alpha - 1.)/(np.pi*gamma*gamma) * (1 + rr_gg)**(-alpha)
class FLCDM(Fittable1DModel):
    """
    All parameters go here.
    """
    h  = Parameter(default=70.)
    Om = Parameter(default=0.3)
    Ol = Parameter(default=0.7)

    @staticmethod
    def evaluate(x, H0, Om, Ol):
        c = 2.99792458E+5
        return (c*(1.+x)/H0) * (((1.+x)**3.)*Om + Ol)**-0.5
    
    @staticmethod
    def fit_deriv(x, H0, Om, Ol):
        """
        h : H0
        m : Om
        L : Ol
        These are the derivatives of the DL func for the Lambda CDM model. 
        x - the z that is not part of the integral.
        """
        c = 2.99792458E+5
        d_H0  = -(c*(x + 1))/(h**2*(Om*(x + 1)**3 + Ol)**0.5)
        d_Om = -(0.5*c*(x + 1)**4)/(h*(Om*(x + 1)**3 + Ol)**1.5)
        d_Ol = -(0.5*c*(x + 1))/(h*(Om*(x + 1)**3 + Ol)**1.5)
        d_z  = 
        return [d_h, d_Om, d_Ol, d_z]
Пример #16
0
class BaseExtRvAfAModel(BaseExtModel):
    """
    Base Extinction R(V)_A, f_A -dependent Model.  Do not use.
    """

    RvA = Parameter(
        description="R_A(V) = A(V)/E(B-V) = " +
        "total-to-selective extinction of component A",
        default=3.1,
    )
    fA = Parameter(description="f_A = mixture coefficent of component A",
                   default=1.0)

    def __init__(self, **kwargs):

        super().__init__(**kwargs)

        # set Rv so that extinguishing by Ebv works
        # equation 11 in Gordon et al. (2016, ApJ, 826, 104)
        self.Rv = 1.0 / (self.fA / self.RvA + (1 - self.fA) / 2.74)

    @RvA.validator
    def RvA(self, value):
        """
        Check that RvA is in the valid range

        Parameters
        ----------
        value: float
            RvA value to check

        Raises
        ------
        InputParameterError
           Input R_A(V) values outside of defined range
        """
        if not (self.RvA_range[0] <= value <= self.RvA_range[1]):
            raise InputParameterError("parameter RvA must be between " +
                                      str(self.RvA_range[0]) + " and " +
                                      str(self.RvA_range[1]))

    @fA.validator
    def fA(self, value):
        """
        Check that fA is in the valid range

        Parameters
        ----------
        value: float
            fA value to check

        Raises
        ------
        InputParameterError
           Input fA values outside of defined range
        """
        if not (self.fA_range[0] <= value <= self.fA_range[1]):
            raise InputParameterError("parameter fA must be between " +
                                      str(self.fA_range[0]) + " and " +
                                      str(self.fA_range[1]))
Пример #17
0
class Exponential1D(Fittable1DModel):
    """
    One dimensional exponential model.
    Parameters
    ----------
    amplitude : float, optional
    x_0 : float, optional
    See Also
    --------
    Exponential1D, Gaussian1D
    """
    amplitude = Parameter(default=1)
    x_0 = Parameter(default=1)

    @staticmethod
    def evaluate(x, amplitude, x_0):
        return amplitude * np.exp(x / x_0)

    @staticmethod
    def fit_deriv(x, amplitude, x_0):
        d_amplitude = np.exp(x / x_0)
        d_x_0 = -amplitude * np.exp(x / (x_0**2))
        return [d_amplitude, d_x_0]

    @property
    def inverse(self):
        new_amplitude = self.x_0
        new_x_0 = self.amplitude
        return Logarithmic1D(amplitude=new_amplitude, x_0=new_x_0)

    @x_0.validator
    def x_0(self, val):
        if val == 0:
            raise ValueError("0 is not an allowed value for x_0")
Пример #18
0
class BaseGaussian1D(Model):
    """ MGE 1D Gaussian model using astropy

    Parameters
    ----------
    **kwargs : kwargs
         Set of free arguments given to MGE_Gaussian1D

    Return
    ------
    MGE_Gaussian1D

    """
    inputs = ("x")
    outputs = ("G1D", )

    imax1d = Parameter(name="imax1d", default=1.0)
    sig1d = Parameter(name="sig1d", default=1.0)
    xcentre1d = Parameter(name="xcentre1d", default=0.0)

    @staticmethod
    def evaluate(x, imax1d, sig1d, xcentre1d):
        return astropy_models.Gaussian1D.evaluate(x,
                                                  amplitude=imax1d,
                                                  stddev=sig1d,
                                                  mean=xcentre1d)
Пример #19
0
class PSFExModel(Fittable2DModel):
    """
    Warning: does not work. I tried!
    """
    n_inputs = 2
    n_outputs = 1

    flux = Parameter()
    x_0 = Parameter()
    y_0 = Parameter()

    def __init__(self, psfex_file: str, data_shape: tuple, flux: float,
                 x_0: float, y_0: float):
        self.psfex_file = psfex_file
        self.psfex_model = pex.PSFEx(psfex_file)
        self.data_shape = data_shape

        super().__init__(flux, x_0, y_0)

    def evaluate(self, x, y, flux, x_0, y_0):
        mock = np.zeros(shape=self.data_shape)
        model_img = self.psfex_model.get_rec(y_0, x_0)
        y_cen, x_cen = self.psfex_model.get_center(y_0, x_0)
        model_img /= np.sum(model_img)
        model_img *= flux
        mock[0:model_img.shape[0], 0:model_img.shape[1]] += model_img
        mock = shift(mock, (y_0 - y_cen, x_0 - x_cen))

        return mock[int(x), int(y)]
Пример #20
0
        class ExpPhase(DiskIntegratedPhaseFunc):
            _unit = 'ref'
            p = Parameter(default=0.1 / u.sr)
            nu = Parameter(default=0.1 / u.rad)

            @staticmethod
            def evaluate(a, p, nu):
                return p * np.exp(-nu * a)
Пример #21
0
class Pix2Sky(FittableModel):
    """
    Wrapper to make an astropy.WCS object act like an astropy.modeling.Model
    object, including having an inverse.
    """
    def __init__(self,
                 wcs,
                 x_offset=0.0,
                 y_offset=0.0,
                 factor=1.0,
                 angle=0.0,
                 direction=1,
                 factor_scale=1.0,
                 angle_scale=1.0,
                 **kwargs):
        self._wcs = wcs.deepcopy()
        self._direction = direction
        self._factor_scale = float(factor_scale)
        self._angle_scale = float(angle_scale)
        super(Pix2Sky, self).__init__(x_offset, y_offset, factor, angle,
                                      **kwargs)

    inputs = ('x', 'y')
    outputs = ('x', 'y')
    x_offset = Parameter()
    y_offset = Parameter()
    factor = Parameter()
    angle = Parameter()

    def evaluate(self, x, y, x_offset, y_offset, factor, angle):
        # x_offset and y_offset are actually arrays in the Model
        #temp_wcs = self.wcs(x_offset[0], y_offset[0], factor, angle)
        temp_wcs = self.wcs
        return temp_wcs.all_pix2world(x, y, 1) if self._direction>0 \
            else temp_wcs.all_world2pix(x, y, 1)

    @property
    def inverse(self):
        inv = self.copy()
        inv._direction = -self._direction
        return inv

    @property
    def wcs(self):
        """Return the WCS modified by the translation/scaling/rotation"""
        wcs = self._wcs.deepcopy()
        x_offset = self.x_offset.value
        y_offset = self.y_offset.value
        angle = self.angle.value
        factor = self.factor.value
        wcs.wcs.crpix += np.array([x_offset, y_offset])
        if factor != self._factor_scale:
            wcs.wcs.cd *= factor / self._factor_scale
        if angle != 0.0:
            m = models.Rotation2D(angle / self._angle_scale)
            wcs.wcs.cd = m(*wcs.wcs.cd)
        return wcs
Пример #22
0
    class PSFModelWithFWHM(Fittable2DModel):
        x_0 = Parameter(default=1)
        y_0 = Parameter(default=1)
        flux = Parameter(default=1)
        fwhm = Parameter(default=5)

        def __init__(self, fwhm=fwhm.default):
            super(PSFModelWithFWHM, self).__init__(fwhm=fwhm)

        def evaluate(self, x, y, x_0, y_0, flux, fwhm):
            return flux / (fwhm * (x - x_0)**2 * (y - y_0)**2)
Пример #23
0
class Delta2D(Fittable2DModel):
    """
    Two dimensional delta function .

    This model can be used for a point source morphology.

    Parameters
    ----------
    amplitude : float
        Peak value of the point source
    x_0 : float
        x position center of the point source
    y_0 : float
        y position center of the point source

    See Also
    --------
    Shell2D, Sphere2D, astropy.modeling.models.Gaussian2D

    Notes
    -----
    Model formula:

    .. math::

        f(x, y) = \\cdot \\left \\{
                    \\begin{array}{ll}
                        A & :  x = x_0 \\ \\mathrm{and} \\ y = y_0 \\\\
                        0 & : else
                    \\end{array}
                \\right.

    The pixel positions x_0 and y_0 are rounded to integers. Subpixel
    information is lost.
    """

    amplitude = Parameter('amplitude')
    x_0 = Parameter('x_0')
    y_0 = Parameter('y_0')

    def __init__(self, amplitude, x_0, y_0, **constraints):
        super(Delta2D, self).__init__(amplitude=amplitude,
                                      x_0=x_0,
                                      y_0=y_0,
                                      **constraints)

    @staticmethod
    def evaluate(x, y, amplitude, x_0, y_0):
        """Two dimensional delta model function"""
        dx = x - x_0
        dy = y - y_0
        x_mask = np.logical_and(dx > -0.5, dx <= 0.5)
        y_mask = np.logical_and(dy > -0.5, dy <= 0.5)
        return np.select([np.logical_and(x_mask, y_mask)], [amplitude])
Пример #24
0
class GaussianRadial(Fittable1DModel):
    flux = Parameter(default=1, fixed=False)
    sigma = Parameter(default=1, fixed=False)
    sky = Parameter(default=0, fixed=False)

    @staticmethod
    def evaluate(x, sigma, flux, sky):
        return gaussian_r(x, sigma, flux, sky)

    @property
    def fwhm(self):
        return gaussian_fwhm(self.sigma)
Пример #25
0
class BaseExtRvAfAModel(BaseExtModel):
    """
    Base Extinction R(V)_A, f_A -dependent Model.  Do not use.
    """

    RvA = Parameter(
        description="R_A(V) = A(V)/E(B-V) = " +
        "total-to-selective extinction of component A",
        default=3.1,
    )
    fA = Parameter(description="f_A = mixture coefficent of component A",
                   default=1.0)

    @RvA.validator
    def RvA(self, value):
        """
        Check that RvA is in the valid range

        Parameters
        ----------
        value: float
            RvA value to check

        Raises
        ------
        InputParameterError
           Input R_A(V) values outside of defined range
        """
        if not (self.RvA_range[0] <= value <= self.RvA_range[1]):
            raise InputParameterError("parameter RvA must be between " +
                                      str(self.RvA_range[0]) + " and " +
                                      str(self.RvA_range[1]))

    @fA.validator
    def fA(self, value):
        """
        Check that fA is in the valid range

        Parameters
        ----------
        value: float
            fA value to check

        Raises
        ------
        InputParameterError
           Input fA values outside of defined range
        """
        if not (self.fA_range[0] <= value <= self.fA_range[1]):
            raise InputParameterError("parameter fA must be between " +
                                      str(self.fA_range[0]) + " and " +
                                      str(self.fA_range[1]))
Пример #26
0
class MoffatRadial(Fittable1DModel):
    flux = Parameter(default=1, fixed=False)
    alpha = Parameter(default=1, fixed=False)
    beta = Parameter(default=1.5, fixed=False)
    sky = Parameter(default=0, fixed=False)

    @staticmethod
    def evaluate(x, flux, alpha, beta, sky):
        return moffat_r(x, alpha, beta, flux, sky)

    @property
    def fwhm(self):
        return moffat_fwhm(self.alpha, self.beta)
Пример #27
0
class Test2D(Fittable2DModel):
    x_0 = Parameter(default=0)
    y_0 = Parameter(default=0)
    p = 0

    def __init__(self, x_0=x_0.default, y_0=y_0.default, p=0, **kwargs):
        self.p = p
        super().__init__(x_0, y_0, **kwargs)

    def evaluate(self, x, y, x_0, y_0):
        print(self.p)
        r = np.sqrt((x - x_0) * (x - x_0) + (y - y_0) * (y - y_0))
        return np.exp(-r / 10)
Пример #28
0
class Star2D(Fittable2DModel):
    amplitude = Parameter('amplitude', default=1)
    x_mean = Parameter('x_mean', default=0)
    y_mean = Parameter('y_mean', default=0)
    stddev = Parameter('stddev', default=1)
    saturation = Parameter('saturation', default=1)

    def __init__(self,
                 amplitude=amplitude.default,
                 x_mean=x_mean.default,
                 y_mean=y_mean.default,
                 stddev=stddev.default,
                 saturation=saturation.default,
                 **kwargs):
        super(Fittable2DModel, self).__init__(**kwargs)

    @property
    def fwhm(self):
        return self.stddev / 2.335

    @staticmethod
    def evaluate(x, y, amplitude, x_mean, y_mean, stddev, saturation):
        a = amplitude * np.exp(-(1 / (2. * stddev**2)) * (x - x_mean)**2 -
                               (1 / (2. * stddev**2)) * (y - y_mean)**2)
        if isinstance(x, float) and isinstance(y, float):
            if a > saturation:
                return saturation
            else:
                return a
        else:
            a[np.where(a >= saturation)] = saturation
            return a

    @staticmethod
    def fit_deriv(x, y, amplitude, x_mean, y_mean, stddev, saturation):
        d_amplitude = np.exp(-((1 / (2. * stddev**2)) * (x - x_mean)**2 +
                               (1 / (2. * stddev**2)) * (y - y_mean)**2))
        d_x_mean = -amplitude * (x - x_mean) / (
            stddev**2) * np.exp(-(1 / (2. * stddev**2)) * (x - x_mean)**2 -
                                (1 / (2. * stddev**2)) * (y - y_mean)**2)
        d_y_mean = -amplitude * (y - y_mean) / (
            stddev**2) * np.exp(-(1 / (2. * stddev**2)) * (x - x_mean)**2 -
                                (1 / (2. * stddev**2)) * (y - y_mean)**2)
        d_stddev = amplitude * (
            (x - x_mean)**2 +
            (y - y_mean)**2) / (stddev**3) * np.exp(-(1 / (2. * stddev**2)) *
                                                    (x - x_mean)**2 -
                                                    (1 / (2. * stddev**2)) *
                                                    (y - y_mean)**2)
        d_saturation = np.zeros_like(x)
        return [d_amplitude, d_x_mean, d_y_mean, d_stddev, d_saturation]
Пример #29
0
class AGaussian1D(Fittable1DModel):
    inputs = ('x',)
    outputs = ('y',)

    amplitude = Parameter()
    x0 = Parameter()
    l_sig = Parameter()
    r_sig = Parameter()

    @staticmethod
    def evaluate(x, amplitude, x0, l_sig, r_sig):
        sig = np.where(x < x0, l_sig, r_sig)
        f = models.Gaussian1D(amplitude, x0, sig)
        return f(x)
Пример #30
0
class LinearPhaseFunc(DiskIntegratedPhaseFunc):
    """Linear phase function model

    Examples
    --------
    >>> # Define a linear phase function model with absolute magnitude
    >>> # H = 5 and slope = 0.04 mag/deg = 2.29 mag/rad
    >>> import astropy.units as u
    >>> from sbpy.calib import solar_fluxd
    >>> from sbpy.photometry import LinearPhaseFunc
    >>>
    >>> linear_phasefunc = LinearPhaseFunc(5 * u.mag, 0.04 * u.mag/u.deg,
    ...     radius = 300 * u.km, wfb = 'V')
    >>> with solar_fluxd.set({'V': -26.77 * u.mag}):
    ...     pha = np.linspace(0, 180, 200) * u.deg
    ...     mag = linear_phasefunc.to_mag(pha)
    ...     ref = linear_phasefunc.to_ref(pha)
    ...     geomalb = linear_phasefunc.geomalb
    ...     phaseint = linear_phasefunc.phaseint
    ...     bondalb = linear_phasefunc.bondalb
    >>> print('Geometric albedo is {0:.3}'.format(geomalb))
    Geometric albedo is 0.0487
    >>> print('Bond albedo is {0:.3}'.format(bondalb))
    Bond albedo is 0.0179
    >>> print('Phase integral is {0:.3}'.format(phaseint))
    Phase integral is 0.367

    """

    _unit = 'mag'
    H = Parameter(description='Absolute magnitude')
    S = Parameter(description='Linear slope (mag/deg)')
    input_units = {'x': u.deg}

    @staticmethod
    def evaluate(a, H, S):
        return H + S * a

    @staticmethod
    def fit_deriv(a, H, S):
        if hasattr(a, '__iter__'):
            ddh = np.ones_like(a)
        else:
            ddh = 1.
        dds = a
        return [ddh, dds]

    def _parameter_units_for_data_units(self, inputs_unit, outputs_unit):
        return OrderedDict([('H', outputs_unit['y']),
                            ('S', outputs_unit['y']/inputs_unit['x'])])