Ejemplo n.º 1
0
def doppler_beaming(wave, flux, vrad, vrad_units='km/s'):
    r"""
    Apply non-relativistic Doppler beaming effects to a spectrum (boosting).
    
    Boosting of a spectrum :math:`(\lambda, F(\lambda))` is defined as
    (Loeb & Gaudi 2003 :cite:`loeb2003`, Bloemen 2011 :cite:`bloemen2011`):
    
    .. math::
    
        \lambda_s = \left(1 + \frac{v_\mathrm{rad}}{c}\right) \lambda \\
        F_b(\lambda) = \left(1+5\frac{v_\mathrm{rad}}{c}\right)F(\lambda_s)
        
    
    :parameter wave: wavelength array
    :type wave: ndarray
    :parameter vrad: radial velocity (negative shifts towards blue,
     positive towards red)
    :type vrad: float (units: km/s) or tuple (float,'units')
    :parameter vrad_units: units of radial velocity (default: km/s)
    :type vrad_units: str (interpretable for
     :py:func:`aspyre.units.conversions.convert`)
    :return: boosted flux
    :rtype: ndarray
    """
    cc = constants.cc
    
    # Explicitly convert km/s to m/s: giving radial velocity in wavelengths
    # offers a speed benefit. Choosing flexibility of different units will
    # require an extra step that uses the conversions module (this is a little
    # slower than explicit conversion)
    if vrad_units == 'km/s':
        cc = cc / 1000.0
    else:   
        cc = conversions.convert('m/s', vrad_units, cc)
    
    flux_shift = doppler_shift(wave, vrad, flux=flux)
    flux_boost = flux_shift + 5*vrad/cc * flux_shift

    return flux_boost
Ejemplo n.º 2
0
def doppler_shift(wave, vrad, vrad_units='km/s', flux=None, relativistic=False):
    r"""
    Shift a spectrum towards the red (+) or blue side (-) with some radial velocity.
    
    You can give units with the extra keywords :envvar:`vrad_units`, but a speed
    increase is offered if you use the default km/s. The units of
    wavelengths are not important, the shifted wavelengths will be in the same
    units as the input wave array.
    
    The Doppler shift from the original wavelength :math:`\lambda` is to the
    shifted wavelength :math:`\lambda_s` is implemented as:
    
    .. math::
    
        \lambda_s = ( 1 + z ) \lambda
        
    with
    
    .. math::
    
        z = \frac{v_\mathrm{rad}}{c}\qquad\mbox{in the nonrelativistic case}\\
        z = \sqrt{\frac{1+v_\mathrm{rad}/c}{1-v_\mathrm{rad}/c}}-1\qquad\mbox{in the relativistic case}\\
    
    When the keyword :envvar:`flux` is set, the spectrum will be interpolated
    onto the original wavelength grid (so the original wavelength grid will not
    change). When the keyword :envvar:`flux` is not set, the wavelength array
    will be changed (but the fluxes are obviously not):
    
    - When :envvar:`flux` is set, fluxes will be returned.
    
    - When :envvar:`flux` is not set, wavelengths will be returned.
    
    :note: If you want to apply a barycentric (or orbital) correction, you'd
           probably want to reverse the sign of the radial velocity!
    
    .. raw:: html

        <p class="flip1">Example usage: shift a spectrum to the red (right) with 20 km/s</p> <div class="panel1">
    
    ::
    
        wave = np.linspace(3000, 8000, 1000)
        wave_shift1 = tools.doppler_shift(wave, 20.)
        wave_shift2 = tools.doppler_shift(wave, 20000., vrad_units='m/s')
        print(wave_shift1[0], wave_shift1[-1])
        (3000.200138457119, 8000.5337025523177)
        print(wave_shift2[0], wave_shift2[-1])
        (3000.200138457119, 8000.5337025523177)
    
    Or with a complete line profile::
    
        wave = np.linspace(3000, 8000, 30)
        flux = 1.0 - 0.5*np.exp( - (wave-5500)**2/(2*500**2))
        wave0 = tools.doppler_shift(wave, 5000.,)
        flux1 = tools.doppler_shift(wave, 5000., flux=flux)
    
    Notice how, with the second ('red') version, the original wavelength array
    can be re-used, while with the first ('blue') version, the original flux
    array can be re-used. Keep in mind that when the fluxes are shifted, they
    are linearly interpolated onto the shifted wavelength array, so the shift
    is not exact::
      
        plt.figure()
        plt.plot(wave, flux, 'ko-', label='Original data')
        plt.plot(wave0,flux,'bx-',lw=2,mew=2,ms=10, label='Shifted wavelength grid')
        plt.plot(wave,flux1,'r+--',lw=2,mew=2,ms=10, label='Original wavelength grid')
        
        plt.legend(loc='best')
        plt.xlabel("Wavelength [$\AA$]")
        plt.ylabel("Normalised flux")
    
    .. image:: ../../images/api/spectra/tools/doppler_shift01.png
       :scale: 50 %
       
            
    .. raw:: html

        </div>
        <br>
    
    
    
    :parameter wave: wavelength array
    :type wave: ndarray
    :parameter vrad: radial velocity (negative shifts towards blue,
     positive towards red)
    :type vrad: float (units: km/s) or tuple (float,'units')
    :parameter vrad_units: units of radial velocity (default: km/s)
    :type vrad_units: str (interpretable for
     :py:func:`aspyre.units.conversions.convert`)
    :parameter relatvistic: apply relativistic Doppler shift
    :type relativistic: bool
    :return: shifted wavelength array/shifted flux
    :rtype: ndarray
    """ 
    cc = constants.cc
    
    # Explicitly convert km/s to m/s: giving radial velocity in wavelengths
    # offers a speed benefit. Choosing flexibility of different units will
    # require an extra step that uses the conversions module (this is a little
    # slower than explicit conversion)
    if vrad_units == 'km/s':
        cc = cc / 1000.0
    else:   
        cc = conversions.convert('m/s', vrad_units, cc)
    
    # Shift wavelengths according to the radial velocity
    z = vrad/cc
    if relativistic:
        z = np.sqrt( (1.0+z) / (1.0-z)) - 1.0
    
    wave_out = wave * (1.0 + z)
    
    # If fluxes are give, interpolate them from the original grid onto the new
    # wavelength grid
    if flux is not None:
        flux = np.interp(wave, wave_out, flux)
        return flux
    else:
        return wave_out