Пример #1
0
def test_custom_model(amplitude=4, frequency=1):

    def sine_model(x, amplitude=4, frequency=1):
        """
        Model function
        """
        return amplitude * np.sin(2 * np.pi * frequency * x)

    def sine_deriv(x, amplitude=4, frequency=1):
        """
        Jacobian of model function, e.g. derivative of the function with
        respect to the *parameters*
        """
        da = np.sin(2 * np.pi * frequency * x)
        df = 2 * np.pi * x * amplitude * np.cos(2 * np.pi * frequency * x)
        return np.vstack((da, df))

    SineModel = models.custom_model(sine_model, fit_deriv=sine_deriv)

    x = np.linspace(0, 4, 50)
    sin_model = SineModel()

    y = sin_model.evaluate(x, 5., 2.)
    y_prime = sin_model.fit_deriv(x, 5., 2.)

    np.random.seed(0)
    data = sin_model(x) + np.random.rand(len(x)) - 0.5
    fitter = fitting.LevMarLSQFitter()
    model = fitter(sin_model, x, data)
    assert np.all((np.array([model.amplitude.value, model.frequency.value]) -
                   np.array([amplitude, frequency])) < 0.001)
Пример #2
0
def get_varying_conv_gaussian_model(g_list):

    # VaryingConvolutionGaussian
    def _f(x, y,
           a_0=1, 
           a_1=0, a_2=0, a_3=0,
           b_0=0., 
           b_1=0, b_2=0, b_3=0, # b_4=0, b_5=0,
           # c_0=0.25, 
           c_1=0, c_2=0, c_3=0):
        """
        b : shift
        c : sigma
        """
        from astropy.modeling.utils import poly_map_domain
        domain = [0, 2047]
        window = [-1, 1]
        #dw = window[1] - window[0]

        x = poly_map_domain(x, domain, window)
        # y = poly_map_domain(y, [0, 1], window)

        # a_0 = a_2 + 1 # so that it always 1 at the center
        a_coeffs = [a_0, a_1, a_2, a_3]
        a = models.Chebyshev1D.clenshaw(x, a_coeffs)

        #b_0 = b_2 # so that the curve passes through 0 at the center
        b_coeffs = [b_0, b_1, b_2, b_3]
        b = models.Chebyshev1D.clenshaw(x, b_coeffs)

        c_0 = c_2
        c_coeffs = [c_0, c_1, c_2, c_3]
        c = models.Chebyshev1D.clenshaw(x, c_coeffs)

        #z1, z2, z3, z4 = [poly_map_domain(z, [0, 1], window) for z in [z1, z2, z3, z4]]
        #w1, w2, w3, w4 = [w*dw for w in [w1, w2, w3, w4]]

        y_b = y - b
        shifted_y = [y_b - g1.mean.value for g1 in g_list]

        c2 = c**2
        broadened_sigma2 = [c2 + g1.stddev**2 for g1 in g_list]

        # argument for the exponetial function
        d_list = [-yy**2/s2/2. for (yy, s2) in zip(shifted_y, broadened_sigma2)]

        _ = np.sum([g1.amplitude*np.exp(d) for (g1, d) in zip(g_list, d_list)],
                   axis=0)

        return a * _

    VaryingConvolutionGaussian = models.custom_model(_f)

    return VaryingConvolutionGaussian
Пример #3
0
def norm_pdf_t(x):
    return np.exp(-0.5 * x * x) / M_SQRT_2_PI


def gauss_box_model(x, amplitude=1.0, location=0.0, s=1.0, d=0.5):
    '''Integrate a Gaussian profile.'''
    m2 = (x + d - location) / s
    m1 = (x - d - location) / s
    return amplitude * (norm.cdf(m2) - norm.cdf(m1))


def gauss_box_model_deriv(x, amplitude=1.0, location=0.0, s=1.0, d=0.5):
    '''Integrate a Gaussian profile.'''
    z2 = (x + d - location) / s
    z1 = (x - d - location) / s

    da = norm.cdf(z2) - norm.cdf(z1)

    fp2 = norm_pdf_t(z2)
    fp1 = norm_pdf_t(z1)

    dl = -amplitude / s * (fp2 - fp1)
    ds = -amplitude / s * (fp2 * z2 - fp1 * z1)
    dd = amplitude / s * (fp2 + fp1)

    return (da, dl, ds, dd)


GaussBox = custom_model(
    gauss_box_model, func_fit_deriv=gauss_box_model_deriv)
Пример #4
0
    d_x = 2 * amplitude * \
        sinc((x-mean)/width) * (
                  x * np.cos((x-mean)/width) -
                  np.sin((x - mean) / width)) / ((x - mean) / width) ** 2
    d_x = np.asarray(d_x)
    d_amplitude = sinc((x-mean)/width)**2
    d_x[x_is_zero] = 0

    d_mean = d_x*(-1/width)
    d_width = d_x*(-(x-mean)/(width)**2)

    return [d_amplitude, d_mean, d_width]


_SincSquareModel = models.custom_model(sinc_square_model,
                                       fit_deriv=sinc_square_deriv)


class SincSquareModel(_SincSquareModel):
    def __reduce__(cls):
        members = dict(cls.__dict__)
        return (type(cls), (), members)


def fit_sinc(x, y, amp=1.5, mean=0., width=1., tied={}, fixed={}, bounds={},
             obs_length=None):
    """
    Fit a sinc function to x,y values.

    Parameters
    ----------
Пример #5
0
          np.exp((-(1 / (stddev**2)) * (x - mean)**2)) *
          (x - mean) / (stddev**2))
    d_stddev = (2 * amplitude *
            np.exp((-(1 / (stddev**2)) * (x - mean)**2)) *
            ((x - mean)**2) / (stddev**3))
    d_const = np.zeros_like(x)
    d_amplitude2 = np.exp((-(1 / (stddev2**2)) * (x - mean2)**2))
    d_mean2 = (2 * amplitude2 *
          np.exp((-(1 / (stddev2**2)) * (x - mean2)**2)) *
          (x - mean) / (stddev2**2))
    d_stddev2 = (2 * amplitude2 *
            np.exp((-(1 / (stddev2**2)) * (x - mean2)**2)) *
            ((x - mean2)**2) / (stddev2**3))
    return [d_amplitude, d_mean, d_stddev, d_const, d_amplitude2, d_mean2, d_stddev2]

LineAbsModel = custom_model(lineabs_model, fit_deriv=lineabs_deriv)


'''This class is just Gaussian + constant. 

Can be removed once astropy supports fitting of composite models.
Also (known bug, but not fixed yet), fitting does not work with bounds.
However, without bounds the fit will just put the gauss in the sharpest spike.
Workaround set in eval method.
'''

def line_model(x, amplitude=1, mean=1, stddev=1, const=1):
        if stddev < 0.1: stddev = 0.25
        return const + amplitude * np.exp((-(1 / (2. * stddev**2)) * (x - mean)**2))

def line_deriv(x, amplitude=1, mean=1, stddev=1, const=1):
Пример #6
0
 class Ellipsoid3D(models.custom_model(ellipsoid)):
     @property
     def bounding_box(self):
         return ((self.z0 - self.c, self.z0 + self.c),
                 (self.y0 - self.b, self.y0 + self.b), (self.x0 - self.a,
                                                        self.x0 + self.a))