Esempio n. 1
0
 def _monotonic_slopes(delta, h, deriv):
     # c.f. scipy PCHIP implementation
     # build m = dy/dx (default value is 0)
     m = numpy.zeros(
         len(delta) + 1, object if delta.dtype == object else float)
     # delta,h live on intervals; x,y,m on knots
     # exclude ends, and points where delta[i-1] and delta[i] differ in sign or vanish
     idx = numpy.arange(1, len(m) - 1)[(delta[1:] * delta[:-1]) > 0]
     w1 = 2 * h[idx] + h[idx - 1]
     w2 = h[idx] + 2 * h[idx - 1]
     m[idx] = (w1 + w2) / (w1 / delta[idx - 1] + w2 / delta[idx])
     # endpoints
     for i, hi, deltai in [(0, h[:2], delta[:2]),
                           (-1, h[:-3:-1], delta[:-3:-1])]:
         if deriv[i] is not None:
             m[i] = deriv[i]
             continue
         m[i] = ((2 * hi[0] + hi[1]) * deltai[0] -
                 hi[0] * deltai[1]) / (hi[0] + hi[1])
         if m[i] * deltai[0] <= 0:
             m[i] = 0
         elif deltai[0] * deltai[1] <= 0 and _gvar.fabs(
                 m[i]) > 3 * _gvar.fabs(deltai[0]):
             m[i] = 3 * deltai[0]
     return m
Esempio n. 2
0
def sinc1d_complex(x, h, a, dx, fwhm):
    """The "complex" version of the sinc (understood as the Fourier
    Transform of a boxcar function from 0 to MPD).

    This is the real sinc function when ones wants to fit both the real
    part and the imaginary part of the spectrum.

    :param x: 1D array of float64 giving the positions where the
      function is evaluated
    
    :param h: Height
    :param a: Amplitude
    :param dx: Position of the center
    :param fwhm: FWHM of the sinc
    """
    width = gvar.fabs(fwhm) / orb.constants.FWHM_SINC_COEFF
    width /= np.pi
    width /= 2.###
    X = (x-dx) / (2*width)

    s1dc_re = h + a * np.sin(X) / (X)
    s1dc_re[X == 0] = h + a
    
    s1dc_im = - h + a * (np.cos(X) - 1.) / (X)
    s1dc_im[X == 0] = 0
    return (s1dc_re, s1dc_im)
Esempio n. 3
0
def sinc1d_flux(a, fwhm):
    """Compute flux of a 1D sinc.

    :param a: Amplitude
    :param fwhm: FWHM
    """
    width = fwhm / orb.constants.FWHM_SINC_COEFF
    return a * gvar.fabs(width)
Esempio n. 4
0
def gaussian1d_flux(a, fwhm):
    """Compute flux of a 1D Gaussian.

    :param a: Amplitude
    :param fwhm: FWHM
    """
    width = fwhm / orb.constants.FWHM_COEFF
    return a * gvar.fabs(math.sqrt(2*math.pi) * width)
Esempio n. 5
0
def vel2sigma(vel, lines, axis_step):
    """Convert a velocity in km/s to a broadening in channels.
    :param vel: velocity in km/s
    :param lines: line position in the unit of axis_step
    :param axis_step: axis step size
    """
    sigma = lines * vel / orb.constants.LIGHT_VEL_KMS
    sigma /= axis_step  # convert sigma cm-1->pix
    return gvar.fabs(sigma)
Esempio n. 6
0
def sigma2vel(sigma, lines, axis_step):
    """Convert a broadening in channels to a velocity in km/s
    :param sigma: broadening in channels
    :param lines: line position in the unit of axis_step
    :param axis_step: axis step size
    """
    vel = sigma * axis_step  # convert sigma pix->cm-1
    # convert sigma cm-1-> km/s
    vel = orb.constants.LIGHT_VEL_KMS * vel / lines
    return gvar.fabs(vel)
Esempio n. 7
0
 def _steffen_slopes(delta, h, deriv):
     # c.f. scipy PCHIP implementation
     # build m = dy/dx (default value is 0)
     m = numpy.zeros(
         len(delta) + 1, object if delta.dtype == object else float)
     # delta,h live on intervals; x,y,m on knots
     # interior points
     p = (delta[:-1] * h[1:] + delta[1:] * h[:-1]) / (h[:-1] + h[1:])
     idx = (numpy.sign(delta[:-1]) * numpy.sign(delta[1:]) <= 0)
     p[idx] *= 0
     idx = _gvar.fabs(p) > 2 * _gvar.fabs(delta[:-1])
     p[idx] = 2 * delta[:-1][idx]
     idx = _gvar.fabs(p) > 2 * _gvar.fabs(delta[1:])
     p[idx] = 2 * delta[1:][idx]
     m[1:-1] = p
     # endpoints
     for i, hi, deltai in [(0, h[:2], delta[:2]),
                           (-1, h[:-3:-1], delta[:-3:-1])]:
         if deriv[i] is not None:
             m[i] = deriv[i]
             continue
         m[i] = ((2 * hi[0] + hi[1]) * deltai[0] -
                 hi[0] * deltai[1]) / (hi[0] + hi[1])
         if m[i] * deltai[0] <= 0:
             m[i] = 0
         elif deltai[0] * deltai[1] <= 0 and _gvar.fabs(
                 m[i]) > 3 * _gvar.fabs(deltai[0]):
             m[i] = 3 * deltai[0]
     return m
Esempio n. 8
0
def fast_w2pix(w, axis_min, axis_step):
    """Fast conversion of wavelength/wavenumber to pixel

    :param w: wavelength/wavenumber
    
    :param axis_min: min axis wavelength/wavenumber
    
    :param axis_step: axis step size in wavelength/wavenumber
    """
    w_ = (w - axis_min)
    if np.any(gvar.sdev(w_) != 0.):
        w_ = gvar.gvar(gvar.mean(w_), gvar.sdev(w_))
    return gvar.fabs(w_) / axis_step
Esempio n. 9
0
def sincgauss1d_complex(x, h, a, dx, fwhm, sigma):
    """The "complex" version of the sincgauss (dawson definition).

    This is the real sinc*gauss function when ones wants to fit both the real
    part and the imaginary part of the spectrum.

    :param x: 1D array of float64 giving the positions where the
      function is evaluated
    
    :param h: Height
    :param a: Amplitude
    :param dx: Position of the center
    :param fwhm: FWHM of the sinc
    :param sigma: Sigma of the gaussian.
    """
    if np.size(sigma) > 1:
        if np.any(sigma != sigma[0]):
            raise Exception('Only one value of sigma can be passed')
        else:
            sigma = sigma[0]

    sigma = np.fabs(sigma)
    fwhm = np.fabs(fwhm)

    broadening_ratio = np.fabs(sigma / fwhm)
    max_broadening_ratio = gvar.mean(broadening_ratio) + gvar.sdev(
        broadening_ratio)

    if broadening_ratio < 1e-2:
        return sinc1d_complex(x, h, a, dx, fwhm)

    if np.isclose(gvar.mean(sigma), 0.):
        return sinc1d_complex(x, h, a, dx, fwhm)

    if max_broadening_ratio > 7:
        return gaussian1d_complex(x, h, a, dx,
                                  sigma * (2. * gvar.sqrt(2. * gvar.log(2.))))

    width = gvar.fabs(fwhm) / orb.constants.FWHM_SINC_COEFF
    width /= np.pi  ###

    a_ = sigma / np.sqrt(2) / width
    b_ = ((x - dx) / np.sqrt(2) / sigma)
    if b_.dtype == np.float128: b_ = b_.astype(float)

    sg1c = orb.cgvar.sincgauss1d_complex(a_, b_)
    return (h + a * sg1c[0], h + a * sg1c[1])
Esempio n. 10
0
def sincgauss1d(x, h, a, dx, fwhm, sigma):
    """Return a 1D sinc convoluted with a gaussian of parameter sigma.

    If sigma == 0 returns a pure sinc.

    :param x: 1D array of float64 giving the positions where the
    sinc is evaluated
    
    :param h: Height
    :param a: Amplitude
    :param dx: Position of the center
    :param fwhm: FWHM of the sinc
    :param sigma: Sigma of the gaussian.
    """
    if np.size(sigma) > 1:
        if np.any(sigma != sigma[0]):
            raise Exception('Only one value of sigma can be passed')
        else:
            sigma = sigma[0]

    sigma = np.fabs(sigma)
    fwhm = np.fabs(fwhm)

    broadening_ratio = np.fabs(sigma / fwhm)
    max_broadening_ratio = gvar.mean(broadening_ratio) + gvar.sdev(
        broadening_ratio)

    if broadening_ratio < 1e-2:
        return sinc1d(x, h, a, dx, fwhm)

    if np.isclose(gvar.mean(sigma), 0.):
        return sinc1d(x, h, a, dx, fwhm)

    if max_broadening_ratio > 7:
        return gaussian1d(x, h, a, dx,
                          sigma * (2. * gvar.sqrt(2. * gvar.log(2.))))

    width = gvar.fabs(fwhm) / orb.constants.FWHM_SINC_COEFF
    width /= np.pi  ###

    a_ = sigma / math.sqrt(2) / width
    b_ = (x - dx) / math.sqrt(2) / sigma

    return h + a * orb.cgvar.sincgauss1d(a_, b_)
Esempio n. 11
0
def mertz1d(x, h, a, dx, fwhm, ratio):
    """Complex ILS when Mertz ramp is used during the Fourier transform.

    :param x: 1D array of float64 giving the positions where the
      function is evaluated
    
    :param h: Height
    :param a: Amplitude
    :param dx: Position of the center
    :param fwhm: FWHM of the sinc

    :param ratio: Ratio of the shortest side over the longest side of
      the interferogram
    """
    width = gvar.fabs(fwhm) / orb.constants.FWHM_SINC_COEFF
    width /= np.pi
    width /= 2.###
    X = (x-dx) / (2*width)

    f_real = h + a * np.sin(X) / X
    f_imag = h + a * (np.cos(X) / X - 1./((X**2)*ratio) * np.sin(ratio*X))
    return (f_real, f_imag)