Example #1
0
    def __call__(self, duration, samplerate):
        """Produce simulated voltages for given duration and samplerate

        Parameters
        ----------
        duration : Quantity
            Should be time units
        samplerate : Quantity
            Rate at which samples should be generated

        The samples are complex, so the real and imaginary parts can be
        used as separate time streams, or can be thought of as complex
        voltages.  The total number of samples is duration * samplerate.
        """
        times = (np.arange(0., (duration * samplerate).to(1).value,
                           dtype=np.float32) / samplerate).to(duration.unit)
        nbins = times.shape[0]
        spectral_power = (np.arange(0., (duration * samplerate).to(1).value,
                                    dtype=np.float32) /
                          (duration * self.nu0)).to(1)**self.spectral_index
        spectral_power *= self.fnu0.astype(np.float32)
        spectral_phase = np.random.uniform(size=nbins) * u.cycle
        with u.add_enabled_equivalencies(u.dimensionless_angles()):
            spectrum = np.sqrt(spectral_power) * np.exp(1j * spectral_phase)
        spectrum[0] = 0.
        return times, ifft(spectrum, overwrite_x=True)
Example #2
0
    def evaluate(self, in_x):
        """
        GCC09_MWAvg function

        Parameters
        ----------
        in_x: float
           expects either x in units of wavelengths or frequency
           or assumes wavelengths in wavenumbers [1/micron]

           internally wavenumbers are used

        Returns
        -------
        axav: np array (float)
            A(x)/A(V) extinction curve [mag]

        Raises
        ------
        ValueError
           Input x values outside of defined range
        """
        # convert to wavenumbers (1/micron) if x input in units
        with u.add_enabled_equivalencies(u.spectral()):
            x_quant = u.Quantity(in_x, 1.0 / u.micron, dtype=np.float64)

        # strip the quantity to avoid needing to add units to all the
        #    polynomical coefficients
        x = x_quant.value
        # check that the wavenumbers are within the defined range
        _test_valid_x_range(x, x_range_GCC09, 'GCC09')

        # P92 parameters fit to the data using uncs as weights
        p92_fit = P92(BKG_amp=203.805939127,
                      BKG_lambda=0.0508199427208,
                      BKG_b=88.0591826413,
                      BKG_n=2.0,
                      FUV_amp=5.33962141873,
                      FUV_lambda=0.08,
                      FUV_b=-0.777129536415,
                      FUV_n=3.88322376926,
                      NUV_amp=0.0447023090042,
                      NUV_lambda=0.217548391182,
                      NUV_b=-1.95723797612,
                      NUV_n=2.0,
                      SIL1_amp=0.00264935064935,
                      SIL1_lambda=9.7,
                      SIL1_b=-1.95,
                      SIL1_n=2.0,
                      SIL2_amp=0.00264935064935,
                      SIL2_lambda=18.0,
                      SIL2_b=-1.80,
                      SIL2_n=2.0,
                      FIR_amp=0.01589610389,
                      FIR_lambda=25.0,
                      FIR_b=0.0,
                      FIR_n=2.0)

        # return A(x)/A(V)
        return p92_fit(in_x)
Example #3
0
def test_equivalency_context_manager():
    base_registry = u.get_current_unit_registry()

    def just_to_from_units(equivalencies):
        return [(equiv[0], equiv[1]) for equiv in equivalencies]

    tf_dimensionless_angles = just_to_from_units(u.dimensionless_angles())
    tf_spectral = just_to_from_units(u.spectral())
    assert base_registry.equivalencies == []
    with u.set_enabled_equivalencies(u.dimensionless_angles()):
        new_registry = u.get_current_unit_registry()
        assert (set(just_to_from_units(new_registry.equivalencies)) ==
                set(tf_dimensionless_angles))
        assert set(new_registry.all_units) == set(base_registry.all_units)
        with u.set_enabled_equivalencies(u.spectral()):
            newer_registry = u.get_current_unit_registry()
            assert (set(just_to_from_units(newer_registry.equivalencies)) ==
                    set(tf_spectral))
            assert (set(newer_registry.all_units) ==
                    set(base_registry.all_units))

        assert (set(just_to_from_units(new_registry.equivalencies)) ==
                set(tf_dimensionless_angles))
        assert set(new_registry.all_units) == set(base_registry.all_units)
        with u.add_enabled_equivalencies(u.spectral()):
            newer_registry = u.get_current_unit_registry()
            assert (set(just_to_from_units(newer_registry.equivalencies)) ==
                    set(tf_dimensionless_angles) | set(tf_spectral))
            assert (set(newer_registry.all_units) ==
                    set(base_registry.all_units))

    assert base_registry is u.get_current_unit_registry()
Example #4
0
def _get_x_in_wavenumbers(in_x):
    """
    Convert input x to wavenumber given x has units.
    Otherwise, assume x is in waveneumbers and issue a warning to this effect.

    Parameters
    ----------
    in_x : astropy.quantity or simple floats
        x values

    Returns
    -------
    x : floats
        input x values in wavenumbers w/o units
    """
    # handles the case where x is a scaler
    in_x = np.atleast_1d(in_x)

    # check if in_x is an astropy quantity, if not issue a warning
    if not isinstance(in_x, u.Quantity):
        warnings.warn("x has no units, assuming x units are inverse microns",
                      UserWarning)

    # convert to wavenumbers (1/micron) if x input in units
    # otherwise, assume x in appropriate wavenumber units
    with u.add_enabled_equivalencies(u.spectral()):
        x_quant = u.Quantity(in_x, 1.0 / u.micron, dtype=np.float64)

    # strip the quantity to avoid needing to add units to all the
    #    polynomical coefficients
    return x_quant.value
Example #5
0
    def integrate(self, *args):
        # TODO: Remove unit hardcoding when we use model with units natively.
        with u.add_enabled_equivalencies(u.spectral()):
            width = u.Quantity(self.width, u.AA)
            slope = u.Quantity(self.slope, 1 / u.AA)

        return self.amplitude * (width + self.amplitude / slope)
Example #6
0
    def integrate(self, x):
        # TODO: Remove unit hardcoding when we use model with units natively.
        with u.add_enabled_equivalencies(u.spectral()):
            x = u.Quantity(x, u.AA)
            x_0 = u.Quantity(self.x_0, u.AA)
            sig = u.Quantity(self.sigma, u.AA)

        # Roots, where y=0
        root_left = x_0 - sig
        root_right = x_0 + sig

        x_min = min(x)
        x_max = max(x)
        if x_min >= root_left or x_max <= root_right:
            raise NotImplementedError(
                'Partial analytic integration not supported')

        sig2 = sig * sig

        def _int_subregion(xx1, xx2):
            dx_min = xx1 - x_0
            dx_max = xx2 - x_0
            a1 = dx_min * np.exp(-0.5 * dx_min * dx_min / sig2)
            a2 = dx_max * np.exp(-0.5 * dx_max * dx_max / sig2)
            return abs(a2 - a1)

        # Unsigned area
        return self.amplitude * (_int_subregion(x_min, root_left) +
                                 _int_subregion(root_left, root_right) +
                                 _int_subregion(root_right, x_max))
Example #7
0
def test_dimensionless_redshift():
    """Test :func:`astropy.cosmology.units.dimensionless_redshift`."""
    z = 3 * cu.redshift
    val = 3 * u.one

    # show units not equal
    assert z.unit == cu.redshift
    assert z.unit != u.one

    # test equivalency enabled by default
    assert z == val

    # also test that it works for powers
    assert (3 * cu.redshift ** 3) == val

    # and in composite units
    assert (3 * u.km / cu.redshift ** 3) == 3 * u.km

    # test it also works as an equivalency
    with u.set_enabled_equivalencies([]):  # turn off default equivalencies
        assert z.to(u.one, equivalencies=cu.dimensionless_redshift()) == val

        with pytest.raises(ValueError):
            z.to(u.one)

    # if this fails, something is really wrong
    with u.add_enabled_equivalencies(cu.dimensionless_redshift()):
        assert z == val
Example #8
0
def test_equivalency_context_manager():
    base_registry = u.get_current_unit_registry()

    def just_to_from_units(equivalencies):
        return [(equiv[0], equiv[1]) for equiv in equivalencies]

    tf_dimensionless_angles = just_to_from_units(u.dimensionless_angles())
    tf_spectral = just_to_from_units(u.spectral())
    assert base_registry.equivalencies == []
    with u.set_enabled_equivalencies(u.dimensionless_angles()):
        new_registry = u.get_current_unit_registry()
        assert (set(just_to_from_units(new_registry.equivalencies)) ==
                set(tf_dimensionless_angles))
        assert set(new_registry.all_units) == set(base_registry.all_units)
        with u.set_enabled_equivalencies(u.spectral()):
            newer_registry = u.get_current_unit_registry()
            assert (set(just_to_from_units(newer_registry.equivalencies)) ==
                    set(tf_spectral))
            assert (set(newer_registry.all_units) ==
                    set(base_registry.all_units))

        assert (set(just_to_from_units(new_registry.equivalencies)) ==
                set(tf_dimensionless_angles))
        assert set(new_registry.all_units) == set(base_registry.all_units)
        with u.add_enabled_equivalencies(u.spectral()):
            newer_registry = u.get_current_unit_registry()
            assert (set(just_to_from_units(newer_registry.equivalencies)) ==
                    set(tf_dimensionless_angles) | set(tf_spectral))
            assert (set(newer_registry.all_units) ==
                    set(base_registry.all_units))

    assert base_registry is u.get_current_unit_registry()
Example #9
0
    def __call__(self, duration, samplerate):
        """Produce simulated voltages for given duration and samplerate

        Parameters
        ----------
        duration : Quantity
            Should be time units
        samplerate : Quantity
            Rate at which samples should be generated

        The samples are complex, so the real and imaginary parts can be
        used as separate time streams, or can be thought of as complex
        voltages.  The total number of samples is duration * samplerate.
        """
        times = (np.arange(0., (duration * samplerate).to(1).value,
                           dtype=np.float32) / samplerate).to(duration.unit)
        nbins = times.shape[0]
        spectral_power = (np.arange(0., (duration * samplerate).to(1).value,
                                    dtype=np.float32) /
                          (duration * self.nu0)).to(1) ** self.spectral_index
        spectral_power *= self.fnu0.astype(np.float32)
        spectral_phase = np.random.uniform(size=nbins) * u.cycle
        with u.add_enabled_equivalencies(u.dimensionless_angles()):
            spectrum = np.sqrt(spectral_power) * np.exp(1j * spectral_phase)
        spectrum[0] = 0.
        return times, ifft(spectrum, overwrite_x=True)
Example #10
0
def blackbody_lambda(wavelength, temperature):
    """
    Calculate the blackbody spectral density per unit wavelength.

    Parameters
    ----------
    wavelength : `~astropy.units.Quantity`
        Wavelength array to evaluate on.

    temperature : `~astropy.units.Quantity`
        Blackbody temperature.
    """

    # Convert to units for calculations, also force double precision
    with u.add_enabled_equivalencies(u.spectral() + u.temperature()):
        freq = u.Quantity(wavelength, u.Hz, dtype=np.float64)
        temp = u.Quantity(temperature, u.K, dtype=np.float64)

    log_boltz = const.h * freq / (const.k_B * temp)
    boltzm1 = np.expm1(log_boltz)

    bb_nu = (2.0 * const.h * freq ** 3 / (const.c ** 2 * boltzm1))

    flam = u.erg / (u.cm**2 * u.s * u.AA)
    flux = bb_nu.to(flam, u.spectral_density(wavelength))

    return flux / u.sr  # Add per steradian to output flux unit
Example #11
0
 def test_redlaw_call(self):
     w = self.redlaw.waveset[48:53]
     with add_enabled_equivalencies(u.spectral()):
         assert_quantity_allclose(
             w, [5.41599989, 5.3204999, 5.2249999, 5.12949991,
                 5.03399992] * (u.micron ** -1))
     assert_quantity_allclose(
         self.redlaw(w),
         [7.90572977, 8.01734924, 8.17892265, 8.40150452, 8.69231796])
Example #12
0
    def k_lambda(self, x):
        """ Compute the starburst reddening curve of Calzetti et al. (2000)
            k'(λ)=A(λ)/E(B-V)

         Parameters
         ----------
         in_x: float
            expects either x in units of wavelengths or frequency
            or assumes wavelengths in [micron]

            internally microns are used

         Returns
         -------
         k_lambda: np array (float)
             k_lambda(x) reddening curve

         Raises
         ------
         ValueError
            Input x values outside of defined range

        """
        # convert to wavenumbers (1/micron) if x input in units
        # otherwise, assume x in appropriate wavenumber units
        with u.add_enabled_equivalencies(u.spectral()):
            x_quant = u.Quantity(x, u.micron, dtype=np.float64)

        # strip the quantity to avoid needing to add units to all the
        #    polynomical coefficients
        x = x_quant.value

        # check that the wavenumbers are within the defined range
        _test_valid_x_range(x, self.x_range, "C00")

        # setup the ax vectors
        n_x = len(x)
        axEbv = np.zeros(n_x)

        # define the ranges
        uv2vis_indxs = np.where(np.logical_and(0.12 <= x, x < 0.63))
        nir_indxs = np.where(np.logical_and(0.63 <= x, x < self.x_range[1]))

        axEbv[uv2vis_indxs] = (
            2.659
            * (
                -2.156
                + 1.509 * 1 / x[uv2vis_indxs]
                - 0.198 * 1 / x[uv2vis_indxs] ** 2
                + 0.011 * 1 / x[uv2vis_indxs] ** 3
            )
            + self.Rv
        )

        axEbv[nir_indxs] = 2.659 * (-1.857 + 1.040 * 1 / x[nir_indxs]) + self.Rv

        return _positive_klambda(axEbv)
Example #13
0
def _validate_with_unit(cosmology, param, value):
    """
    Default Parameter value validator.
    Adds/converts units if Parameter has a unit.
    """
    if param.unit is not None:
        with u.add_enabled_equivalencies(param.equivalencies):
            value = u.Quantity(value, param.unit)
    return value
Example #14
0
    def integrate(self, x):
        # TODO: Remove unit hardcoding when we use model with units natively.
        with u.add_enabled_equivalencies(u.spectral()):
            x = u.Quantity(x, u.AA)
            x_0 = u.Quantity(self.x_0, u.AA)
            amp = u.Quantity(self.amplitude, self._flux_unit)

        fac = 1 - self.alpha
        denom = x_0**-self.alpha * fac
        return amp * (max(x)**fac - min(x)**fac) / denom
Example #15
0
    def evaluate(x, Av):
        """
        C00 function

        Parameters
        ----------
        in_x: float
           expects either x in units of wavelengths or frequency
           or assumes wavelengths in [micron]

           internally microns are used

        Returns
        -------
        att: np array (float)
            Att(x) attenuation curve [mag]

        Raises
        ------
        ValueError
           Input x values outside of defined range
        """
        # convert to wavenumbers (1/micron) if x input in units
        # otherwise, assume x in appropriate wavenumber units
        with u.add_enabled_equivalencies(u.spectral()):
            x_quant = u.Quantity(x, u.micron, dtype=np.float64)

        # strip the quantity to avoid needing to add units to all the
        #    polynomical coefficients
        x = x_quant.value

        # check that the wavenumbers are within the defined range
        _test_valid_x_range(x, x_range_C00, 'C00')

        # setup the ax vectors
        n_x = len(x)
        axEbv = np.zeros(n_x)

        # Rv is fixed to 4.05
        Rv = 4.05

        # define the ranges
        uv2vis_indxs = np.where(np.logical_and(0.12 <= x, x < 0.63))
        nir_indxs = np.where(np.logical_and(0.63 <= x, x < 2.2))

        axEbv[uv2vis_indxs] = (2.659 * (-2.156 +
                                        1.509 * 1 / x[uv2vis_indxs] -
                                        0.198 * 1 / x[uv2vis_indxs] ** 2 +
                                        0.011 * 1 / x[uv2vis_indxs] ** 3) + Rv)

        axEbv[nir_indxs] = 2.659 * (-1.857 + 1.040 * 1 / x[nir_indxs]) + Rv

        ax = axEbv / Rv * Av

        return ax
Example #16
0
    def evaluate(self, in_x,
                 BKG_amp, BKG_lambda, BKG_b, BKG_n,
                 FUV_amp, FUV_lambda, FUV_b, FUV_n,
                 NUV_amp, NUV_lambda, NUV_b, NUV_n,
                 SIL1_amp, SIL1_lambda, SIL1_b, SIL1_n,
                 SIL2_amp, SIL2_lambda, SIL2_b, SIL2_n,
                 FIR_amp, FIR_lambda, FIR_b, FIR_n):
        """
        P92 function

        Parameters
        ----------
        in_x: float
           expects either x in units of wavelengths or frequency
           or assumes wavelengths in wavenumbers [1/micron]

           internally wavenumbers are used

        Returns
        -------
        axav: np array (float)
            A(x)/A(V) extinction curve [mag]

        Raises
        ------
        ValueError
           Input x values outside of defined range
        """
        # convert to wavenumbers (1/micron) if x input in units
        # otherwise, assume x in appropriate wavenumber units
        with u.add_enabled_equivalencies(u.spectral()):
            x_quant = u.Quantity(in_x, 1.0/u.micron, dtype=np.float64)

        # strip the quantity to avoid needing to add units to all the
        #    polynomical coefficients
        x = x_quant.value

        # check that the wavenumbers are within the defined range
        _test_valid_x_range(x, x_range_P92, 'P92')

        # calculate the terms
        lam = 1.0/x
        axav = (self._p92_single_term(lam, BKG_amp, BKG_lambda, BKG_b, BKG_n)
                + self._p92_single_term(lam, FUV_amp, FUV_lambda, FUV_b, FUV_n)
                + self._p92_single_term(lam, NUV_amp, NUV_lambda, NUV_b, NUV_n)
                + self._p92_single_term(lam, SIL1_amp, SIL1_lambda,
                                        SIL1_b, SIL1_n)
                + self._p92_single_term(lam, SIL2_amp, SIL2_lambda,
                                        SIL2_b, SIL2_n)
                + self._p92_single_term(lam, FIR_amp, FIR_lambda,
                                        FIR_b, FIR_n))

        # return A(x)/A(V)
        return axav
Example #17
0
        def wrapper(*func_args, **func_kwargs):
            # Bind the arguments to our new function to the signature of the original.
            bound_args = wrapped_signature.bind(*func_args, **func_kwargs)

            # Iterate through the parameters of the original signature
            for param in wrapped_signature.parameters.values():
                # We do not support variable arguments (*args,
                # **kwargs)
                if param.kind in (funcsigs.Parameter.VAR_KEYWORD,
                                  funcsigs.Parameter.VAR_POSITIONAL):
                    continue
                # Catch the (never triggered) case where bind relied on a default value.
                if param.name not in bound_args.arguments and param.default is not param.empty:
                    bound_args.arguments[param.name] = param.default

                # Get the value of this parameter (argument to new function)
                arg = bound_args.arguments[param.name]

                # Get target unit, either from decotrator kwargs or annotations
                if param.name in self.decorator_kwargs:
                    target_unit = self.decorator_kwargs[param.name]
                else:
                    target_unit = param.annotation

                # If the target unit is empty, then no unit was specified so we
                # move past it
                if target_unit is not funcsigs.Parameter.empty:
                    try:
                        equivalent = arg.unit.is_equivalent(
                            target_unit, equivalencies=self.equivalencies)

                        if not equivalent:
                            raise UnitsError("Argument '{0}' to function '{1}'"
                                             " must be in units convertable to"
                                             " '{2}'.".format(
                                                 param.name,
                                                 wrapped_function.__name__,
                                                 target_unit.to_string()))

                    # Either there is no .unit or no .is_equivalent
                    except AttributeError:
                        if hasattr(arg, "unit"):
                            error_msg = "a 'unit' attribute without an 'is_equivalent' method"
                        else:
                            error_msg = "no 'unit' attribute"
                        raise TypeError(
                            "Argument '{0}' to function has '{1}' {2}. "
                            "You may want to pass in an astropy Quantity instead."
                            .format(param.name, wrapped_function.__name__,
                                    error_msg))

            # Call the original function with any equivalencies in force.
            with add_enabled_equivalencies(self.equivalencies):
                return wrapped_function(*func_args, **func_kwargs)
Example #18
0
def blackbody_nu(in_x, temperature):
    """Calculate blackbody flux per steradian, :math:`B_{\\nu}(T)`.

    .. note::

        Use `numpy.errstate` to suppress Numpy warnings, if desired.

    .. warning::

        Output values might contain ``nan`` and ``inf``.

    Parameters
    ----------
    in_x : number, array-like, or `~astropy.units.Quantity`
        Frequency, wavelength, or wave number.
        If not a Quantity, it is assumed to be in Hz.

    temperature : number or `~astropy.units.Quantity`
        Blackbody temperature.
        If not a Quantity, it is assumed to be in Kelvin.

    Returns
    -------
    flux : `~astropy.units.Quantity`
        Blackbody monochromatic flux in
        :math:`erg \\; cm^{-2} s^{-1} Hz^{-1} sr^{-1}`.

    Raises
    ------
    ValueError
        Invalid temperature.

    ZeroDivisionError
        Wavelength is zero (when converting to frequency).

    """
    # Convert to units for calculations, also force double precision
    with u.add_enabled_equivalencies(u.spectral() + u.temperature()):
        freq = u.Quantity(in_x, u.Hz, dtype=np.float64)
        temp = u.Quantity(temperature, u.K, dtype=np.float64)

    # Check if input values are physically possible
    if temp < 0:
        raise ValueError('Invalid temperature {0}'.format(temp))
    if np.any(freq <= 0):  # pragma: no cover
        warnings.warn('Input contains invalid wavelength/frequency value(s)',
                      AstropyUserWarning)

    # Calculate blackbody flux
    bb_nu = (2.0 * const.h * freq**3 /
             (const.c**2 * np.expm1(const.h * freq / (const.k_B * temp))))
    flux = bb_nu.to(FNU, u.spectral_density(freq))

    return flux / u.sr  # Add per steradian to output flux unit
Example #19
0
    def integrate(self, x):
        # TODO: Remove unit hardcoding when we use model with units natively.
        with u.add_enabled_equivalencies(u.spectral()):
            x = u.Quantity(x, u.AA)
            x_0 = u.Quantity(self.x_0, u.AA)
            gamma = u.Quantity(self.fwhm, u.AA) * 0.5

        a1 = np.arctan((min(x) - x_0) / gamma)
        a2 = np.arctan((max(x) - x_0) / gamma)
        da = (a2 - a1).to(u.dimensionless_unscaled, u.dimensionless_angles())
        return self.amplitude * gamma * da
Example #20
0
def blackbody_nu(in_x, temperature):
    """Calculate blackbody flux per steradian, :math:`B_{\\nu}(T)`.

    .. note::

        Use `numpy.errstate` to suppress Numpy warnings, if desired.

    .. warning::

        Output values might contain ``nan`` and ``inf``.

    Parameters
    ----------
    in_x : number, array-like, or `~astropy.units.Quantity`
        Frequency, wavelength, or wave number.
        If not a Quantity, it is assumed to be in Hz.

    temperature : number or `~astropy.units.Quantity`
        Blackbody temperature.
        If not a Quantity, it is assumed to be in Kelvin.

    Returns
    -------
    flux : `~astropy.units.Quantity`
        Blackbody monochromatic flux in
        :math:`erg \\; cm^{-2} s^{-1} Hz^{-1} sr^{-1}`.

    Raises
    ------
    ValueError
        Invalid temperature.

    ZeroDivisionError
        Wavelength is zero (when converting to frequency).

    """
    # Convert to units for calculations, also force double precision
    with u.add_enabled_equivalencies(u.spectral() + u.temperature()):
        freq = u.Quantity(in_x, u.Hz, dtype=np.float64)
        temp = u.Quantity(temperature, u.K, dtype=np.float64)

    # Check if input values are physically possible
    if temp < 0:
        raise ValueError('Invalid temperature {0}'.format(temp))
    if np.any(freq <= 0):  # pragma: no cover
        warnings.warn('Input contains invalid wavelength/frequency value(s)',
                      AstropyUserWarning)

    # Calculate blackbody flux
    bb_nu = (2.0 * const.h * freq ** 3 /
             (const.c ** 2 * np.expm1(const.h * freq / (const.k_B * temp))))
    flux = bb_nu.to(FNU, u.spectral_density(freq))

    return flux / u.sr  # Add per steradian to output flux unit
Example #21
0
    def integrate(self, x):
        # TODO: Remove unit hardcoding when we use model with units natively.
        # TODO: We do not handle wav_unit as wave number nor energy for now.
        if 'wav' in self._flux_unit.physical_type:
            wav_unit = u.AA
        else:
            wav_unit = u.Hz
        with u.add_enabled_equivalencies(u.spectral()):
            x = u.Quantity(x, wav_unit)
            amp = u.Quantity(self.amplitude, self._flux_unit)

        return (max(x) - min(x)) * amp
Example #22
0
def blackbody_nu(in_x, temperature):
    """Calculate blackbody flux per steradian, :math:`B_{\\nu}(T)`.

    .. note::

        Use `numpy.errstate` to suppress Numpy warnings, if desired.

    .. warning::

        Output values might contain ``nan`` and ``inf``.

    Parameters

    in_x : number, array-like, or `~astropy.units.Quantity`
        Frequency, wavelength, or wave number.
        If not a Quantity, it is assumed to be in Hz.

    temperature : number, array-like, or `~astropy.units.Quantity`
        Blackbody temperature.
        If not a Quantity, it is assumed to be in Kelvin.

    Returns

    flux : `~astropy.units.Quantity`
        Blackbody monochromatic flux in
        :math:`erg \\; cm^{-2} s^{-1} Hz^{-1} sr^{-1}`.


    Raises

    ValueError
        Invalid temperature.

    ZeroDivisionError
        Wavelength is zero (when converting to frequency).

    """
    FNU = u.erg / (u.cm**2 * u.s * u.Hz)
    FLAM = u.erg / (u.cm**2 * u.s * u.AA)

    # Convert to units for calculations, also force double precision
    with u.add_enabled_equivalencies(u.spectral() + u.temperature()):
        freq = u.Quantity(in_x, u.Hz, dtype=np.float64)
        temp = u.Quantity(temperature, u.K, dtype=np.float64)

    log_boltz = const.h * freq / (const.k_B * temp)
    boltzm1 = np.expm1(log_boltz)

    # Calculate blackbody flux
    bb_nu = (2.0 * const.h * freq**3 / (const.c**2 * boltzm1))
    flux = bb_nu.to(FNU, u.spectral_density(freq))

    return flux / u.sr  # Add per steradian to output flux unit
Example #23
0
    def evaluate(in_x, RvA, fA):
        """
        G16 function

        Parameters
        ----------
        in_x: float
           expects either x in units of wavelengths or frequency
           or assumes wavelengths in wavenumbers [1/micron]

           internally wavenumbers are used

        Returns
        -------
        axav: np array (float)
            A(x)/A(V) extinction curve [mag]

        Raises
        ------
        ValueError
           Input x values outside of defined range
        """
        # convert to wavenumbers (1/micron) if x input in units
        # otherwise, assume x in appropriate wavenumber units
        with u.add_enabled_equivalencies(u.spectral()):
            x_quant = u.Quantity(in_x, 1.0/u.micron, dtype=np.float64)

        # strip the quantity to avoid needing to add units to all the
        #    polynomical coefficients
        x = x_quant.value

        # check that the wavenumbers are within the defined range
        _test_valid_x_range(x, x_range_G16, 'G16')

        # ensure Rv is a single element, not numpy array
        RvA = RvA[0]

        # get the A component extinction model
        extA_model = F99(Rv=RvA)
        alav_A = extA_model(x)

        # get the B component extinction model
        extB_model = G03_SMCBar()
        alav_B = extB_model(x)

        # create the mixture model
        alav = fA*alav_A + (1.0 - fA)*alav_B

        # return A(x)/A(V)
        return alav
Example #24
0
    def evaluate(in_x, C1, C2, C3, C4, xo, gamma):
        """
        FM90 function

        Parameters
        ----------
        in_x: float
           expects either x in units of wavelengths or frequency
           or assumes wavelengths in wavenumbers [1/micron]

           internally wavenumbers are used

        Returns
        -------
        exvebv: np array (float)
            E(x-V)/E(B-V) extinction curve [mag]

        Raises
        ------
        ValueError
           Input x values outside of defined range
        """
        # convert to wavenumbers (1/micron) if x input in units
        # otherwise, assume x in appropriate wavenumber units
        with u.add_enabled_equivalencies(u.spectral()):
            x_quant = u.Quantity(in_x, 1.0/u.micron, dtype=np.float64)

        # strip the quantity to avoid needing to add units to all the
        #    polynomical coefficients
        x = x_quant.value

        # check that the wavenumbers are within the defined range
        _test_valid_x_range(x, x_range_FM90, 'FM90')

        # linear term
        exvebv = C1 + C2*x

        # bump term
        x2 = x**2
        exvebv += C3*(x2/((x2 - xo**2)**2 + x2*(gamma**2)))

        # FUV rise term
        fnuv_indxs = np.where(x >= 5.9)
        if len(fnuv_indxs) > 0:
            y = x[fnuv_indxs] - 5.9
            exvebv[fnuv_indxs] += C4*(0.5392*(y**2) + 0.05644*(y**3))

        # return E(x-V)/E(B-V)
        return exvebv
Example #25
0
    def test_one_argument_ufunc_at(self):
        q = np.arange(10.) * u.m
        i = np.array([1, 2])
        qv = q.value.copy()
        np.negative.at(q, i)
        np.negative.at(qv, i)
        assert np.all(q.value == qv)
        assert q.unit is u.m

        # cannot change from quantity to bool array
        with pytest.raises(TypeError):
            np.isfinite.at(q, i)

        # for selective in-place, cannot change the unit
        with pytest.raises(u.UnitsError):
            np.square.at(q, i)

        # except if the unit does not change (i.e., dimensionless)
        d = np.arange(10.) * u.dimensionless_unscaled
        dv = d.value.copy()
        np.square.at(d, i)
        np.square.at(dv, i)
        assert np.all(d.value == dv)
        assert d.unit is u.dimensionless_unscaled

        d = np.arange(10.) * u.dimensionless_unscaled
        dv = d.value.copy()
        np.log.at(d, i)
        np.log.at(dv, i)
        assert np.all(d.value == dv)
        assert d.unit is u.dimensionless_unscaled

        # also for sine it doesn't work, even if given an angle
        a = np.arange(10.) * u.radian
        with pytest.raises(u.UnitsError):
            np.sin.at(a, i)

        # except, for consistency, if we have made radian equivalent to
        # dimensionless (though hopefully it will never be needed)
        av = a.value.copy()
        with u.add_enabled_equivalencies(u.dimensionless_angles()):
            np.sin.at(a, i)
            np.sin.at(av, i)
            assert_allclose(a.value, av)

            # but we won't do double conversion
            ad = np.arange(10.) * u.degree
            with pytest.raises(u.UnitsError):
                np.sin.at(ad, i)
Example #26
0
    def test_one_argument_ufunc_at(self):
        q = np.arange(10.) * u.m
        i = np.array([1, 2])
        qv = q.value.copy()
        np.negative.at(q, i)
        np.negative.at(qv, i)
        assert np.all(q.value == qv)
        assert q.unit is u.m

        # cannot change from quantity to bool array
        with pytest.raises(TypeError):
            np.isfinite.at(q, i)

        # for selective in-place, cannot change the unit
        with pytest.raises(u.UnitsError):
            np.square.at(q, i)

        # except if the unit does not change (i.e., dimensionless)
        d = np.arange(10.) * u.dimensionless_unscaled
        dv = d.value.copy()
        np.square.at(d, i)
        np.square.at(dv, i)
        assert np.all(d.value == dv)
        assert d.unit is u.dimensionless_unscaled

        d = np.arange(10.) * u.dimensionless_unscaled
        dv = d.value.copy()
        np.log.at(d, i)
        np.log.at(dv, i)
        assert np.all(d.value == dv)
        assert d.unit is u.dimensionless_unscaled

        # also for sine it doesn't work, even if given an angle
        a = np.arange(10.) * u.radian
        with pytest.raises(u.UnitsError):
            np.sin.at(a, i)

        # except, for consistency, if we have made radian equivalent to
        # dimensionless (though hopefully it will never be needed)
        av = a.value.copy()
        with u.add_enabled_equivalencies(u.dimensionless_angles()):
            np.sin.at(a, i)
            np.sin.at(av, i)
            assert_allclose(a.value, av)

            # but we won't do double conversion
            ad = np.arange(10.) * u.degree
            with pytest.raises(u.UnitsError):
                np.sin.at(ad, i)
    def evaluate(self, x, tau_V):
        """
        WG00 function

        Parameters
        ----------
        x: float
           expects either x in units of wavelengths or frequency
           or assumes wavelengths in [micron]

           internally microns are used

        tau_V: float
           optical depth in V band

        Returns
        -------
        Attx: np array (float)
            Att(x) attenuation curve [mag]

        Raises
        ------
        ValueError
           Input x values outside of defined range
        """
        # convert to wavenumbers (1/micron) if x input in units
        # otherwise, assume x in appropriate wavenumber units
        with u.add_enabled_equivalencies(u.spectral()):
            x_quant = u.Quantity(x, u.micron, dtype=np.float64)

        # strip the quantity to avoid needing to add units to all the
        #    polynomical coefficients
        x = x_quant.value

        # check that the wavenumbers are within the defined range
        _test_valid_x_range(x, x_range_WG00, 'WG00')

        # setup the ax vectors
        n_x = len(x)

        xinterp = 1e4 * x
        yinterp = tau_V * np.ones(n_x)

        taux = self.model(xinterp, yinterp)

        # Convert optical depth to attenuation
        Attx = 1.086 * taux

        return Attx
    def get_fesc(self, x, tau_V):
        """
        Return the total escaping flux fraction  at a given wavelength and
        V-band optical depth.

        Parameters
        ----------
        x: float
           expects either x in units of wavelengths or frequency
           or assumes wavelengths in [micron]

           internally microns are used

        tau_V: float
           optical depth in V band

        Returns
        -------
        fsca: np array (float)
            fsca(x) scattered flux fraction

        Raises
        ------
        ValueError
           Input x values outside of defined range
        """
        # convert to wavenumbers (1/micron) if x input in units
        # otherwise, assume x in appropriate wavenumber units
        with u.add_enabled_equivalencies(u.spectral()):
            x_quant = u.Quantity(x, u.micron, dtype=np.float64)

        # strip the quantity to avoid needing to add units to all the
        #    polynomical coefficients
        x = x_quant.value

        # check that the wavenumbers are within the defined range
        _test_valid_x_range(x, x_range_WG00, 'WG00')

        # setup the ax vectors
        x = np.atleast_1d(x)
        n_x = len(x)

        xinterp = 1e4 * x
        yinterp = tau_V * np.ones(n_x)

        return self.fesc(xinterp, yinterp)
Example #29
0
    def test_ilshift_magnitude(self):
        # test in-place operation and conversion
        mag_fnu_cgs = u.mag(u.erg/u.s/u.cm**2/u.Hz)
        m = np.arange(10.0) * u.mag(u.Jy)
        jy = m.physical
        m2 = m << mag_fnu_cgs
        assert np.all(m2 == m.to(mag_fnu_cgs))
        m2 = m
        m <<= mag_fnu_cgs
        assert m is m2  # Check it was done in-place!
        assert np.all(m.value == m2.value)
        assert m.unit == mag_fnu_cgs
        # Check it works if equivalencies are in-place.
        with u.add_enabled_equivalencies(u.spectral_density(5500*u.AA)):
            st = jy.to(u.ST)
            m <<= u.STmag

        assert m is m2
        assert_quantity_allclose(m.physical, st)
        assert m.unit == u.STmag
Example #30
0
    def test_ilshift_magnitude(self):
        # test in-place operation and conversion
        mag_fnu_cgs = u.mag(u.erg / u.s / u.cm**2 / u.Hz)
        m = np.arange(10.0) * u.mag(u.Jy)
        jy = m.physical
        m2 = m << mag_fnu_cgs
        assert np.all(m2 == m.to(mag_fnu_cgs))
        m2 = m
        m <<= mag_fnu_cgs
        assert m is m2  # Check it was done in-place!
        assert np.all(m.value == m2.value)
        assert m.unit == mag_fnu_cgs
        # Check it works if equivalencies are in-place.
        with u.add_enabled_equivalencies(u.spectral_density(5500 * u.AA)):
            st = jy.to(u.ST)
            m <<= u.STmag

        assert m is m2
        assert_quantity_allclose(m.physical, st)
        assert m.unit == u.STmag
Example #31
0
    def __call__(self, t):
        """Compute the apparent phase at one or more times.

        Parameters
        ----------
        t : `~astropy.time.Time`
            The input time stamps.

        Returns
        -------
        phase : `~baseband_tasks.phases.Phase`
            The apparent pulse phase at time ``t``, using a 2-part double of
            the integer cycle and the fractional phase.  The latter is
            between -0.5 and 0.5.
        """
        toas = self.toa_maker(t)
        ph = self.model.phase(toas)
        shape = getattr(toas, 'shape', ())
        # TODO: Once PINT uses the Phase class, we can return the
        # result directly.
        with u.add_enabled_equivalencies([(u.dimensionless_unscaled, u.cy)]):
            return Phase(ph.int, ph.frac).reshape(shape)
Example #32
0
    def k_lambda(self, x):
        """ Compute the starburst reddening curve of Leitherer et al. (2002)
            k'(λ)=A(λ)/E(B-V)

         Parameters
         ----------
         in_x: float
            expects either x in units of wavelengths or frequency
            or assumes wavelengths in [micron]

            internally microns are used

         Returns
         -------
         k_lambda: np array (float)
             k_lambda(x) reddening curve

         Raises
         ------
         ValueError
            Input x values outside of defined range

        """
        # convert to wavenumbers (1/micron) if x input in units
        # otherwise, assume x in appropriate wavenumber units
        with u.add_enabled_equivalencies(u.spectral()):
            x_quant = u.Quantity(x, u.micron, dtype=np.float64)

        # strip the quantity to avoid needing to add units to all the
        #    polynomical coefficients
        x = x_quant.value

        # check that the wavenumbers are within the defined range
        _test_valid_x_range(x, x_range_L02, 'L02')

        axEbv = (5.472 +
                 (0.671 * 1 / x - 9.218 * 1e-3 / x**2 + 2.620 * 1e-3 / x**3))

        return axEbv
Example #33
0
    def evaluate(self, x, Av):
        """
        Returns the attenuation curve, A(λ), following the recipe of
        Leitherer et al. (2002), assuming Rv=4.05

        Parameters
        ----------
        in_x: float
           expects either x in units of wavelengths or frequency
           or assumes wavelengths in [micron]

           internally microns are used

        Returns
        -------
        att: np array (float)
            Att(x) attenuation curve [mag]

        Raises
        ------
        ValueError
           Input x values outside of defined range
        """
        # convert to wavenumbers (1/micron) if x input in units
        # otherwise, assume x in appropriate wavenumber units
        with u.add_enabled_equivalencies(u.spectral()):
            x_quant = u.Quantity(x, u.micron, dtype=np.float64)

        # strip the quantity to avoid needing to add units to all the
        #    polynomical coefficients
        x = x_quant.value

        # check that the wavenumbers are within the defined range
        _test_valid_x_range(x, self.x_range, "L02")

        ax = self.k_lambda(x) / self.Rv * Av

        return ax
Example #34
0
    Returns
    -------
    equivalency : list
        The returned list contains one tuple with the equivalency.
    '''
    return [(
        apu.uV / apu.m,
        (apu.uV / apu.m) ** 2,
        lambda x: x ** 2,
        lambda x: x ** 0.5
        )]


# apu.add_enabled_equivalencies(apu.logarithmic())
apu.add_enabled_equivalencies(efield_equivalency())

# define some useful constants
R0 = (
    1. * (con.mu0 / con.eps0) ** 0.5
    ).to(apu.Ohm)
Erx_unit = (
    (1 * apu.W / 4. / np.pi * R0) ** 0.5 / (1 * apu.km)
    ).to(apu.uV / apu.m)
C_VALUE = con.c.to(apu.m / apu.s).value
R0_VALUE = R0.to(apu.Ohm).value
KB_VALUE = con.k_B.to(apu.J / apu.K).value
ERX_VALUE = Erx_unit.to(apu.V / apu.m).value


@utils.ranged_quantity_input(
Example #35
0
        `None` (default), use the ``H0`` attribute from
        :mod:`~astropy.cosmology.default_cosmology`.

    References
    ----------
    For an illuminating discussion on why you may or may not want to use
    little-h at all, see https://arxiv.org/pdf/1308.4150.pdf
    """
    if H0 is None:
        from .realizations import default_cosmology
        H0 = default_cosmology.get().H0

    h100_val_unit = u.Unit(100 / (H0.to_value(u.km / u.s / u.Mpc)) * littleh)

    return u.Equivalency([(h100_val_unit, None)], "with_H0", kwargs={"H0": H0})


# ===================================================================
# Enable the set of default equivalencies.
# If the cosmology package is imported, this is added to the list astropy-wide.

u.add_enabled_equivalencies(dimensionless_redshift())

# =============================================================================
# DOCSTRING

# This generates a docstring for this module that describes all of the
# standard units defined here.
if __doc__ is not None:
    __doc__ += _generate_unit_summary(_ns)
Example #36
0
def blackbody_nu(in_x, temperature):
    """Calculate blackbody flux per steradian, :math:`B_{\\nu}(T)`.

    .. note::

        Use `numpy.errstate` to suppress Numpy warnings, if desired.

    .. warning::

        Output values might contain ``nan`` and ``inf``.

    Parameters
    ----------
    in_x : number, array-like, or `~astropy.units.Quantity`
        Frequency, wavelength, or wave number.
        If not a Quantity, it is assumed to be in Hz.

    temperature : number, array-like, or `~astropy.units.Quantity`
        Blackbody temperature.
        If not a Quantity, it is assumed to be in Kelvin.

    Returns
    -------
    flux : `~astropy.units.Quantity`
        Blackbody monochromatic flux in
        :math:`erg \\; cm^{-2} s^{-1} Hz^{-1} sr^{-1}`.

    Raises
    ------
    ValueError
        Invalid temperature.

    ZeroDivisionError
        Wavelength is zero (when converting to frequency).

    """
    # Convert to units for calculations, also force double precision
    with u.add_enabled_equivalencies(u.spectral() + u.temperature()):
        freq = u.Quantity(in_x, u.Hz, dtype=np.float64)
        temp = u.Quantity(temperature, u.K, dtype=np.float64)

    # Check if input values are physically possible
    if np.any(temp < 0):
        raise ValueError(f'Temperature should be positive: {temp}')
    if not np.all(np.isfinite(freq)) or np.any(freq <= 0):
        warnings.warn('Input contains invalid wavelength/frequency value(s)',
                      AstropyUserWarning)

    log_boltz = const.h * freq / (const.k_B * temp)
    boltzm1 = np.expm1(log_boltz)

    if _has_buggy_expm1:
        # Replace incorrect nan results with infs--any result of 'nan' is
        # incorrect unless the input (in log_boltz) happened to be nan to begin
        # with.  (As noted in #4393 ideally this would be replaced by a version
        # of expm1 that doesn't have this bug, rather than fixing incorrect
        # results after the fact...)
        boltzm1_nans = np.isnan(boltzm1)
        if np.any(boltzm1_nans):
            if boltzm1.isscalar and not np.isnan(log_boltz):
                boltzm1 = np.inf
            else:
                boltzm1[np.where(~np.isnan(log_boltz) & boltzm1_nans)] = np.inf

    # Calculate blackbody flux
    bb_nu = (2.0 * const.h * freq ** 3 / (const.c ** 2 * boltzm1))
    flux = bb_nu.to(FNU, u.spectral_density(freq))

    return flux / u.sr  # Add per steradian to output flux unit
Example #37
0
def blackbody_nu(in_x, temperature):
    """Calculate blackbody flux per steradian, :math:`B_{\\nu}(T)`.

    .. note::

        Use `numpy.errstate` to suppress Numpy warnings, if desired.

    .. warning::

        Output values might contain ``nan`` and ``inf``.

    Parameters
    ----------
    in_x : number, array-like, or `~astropy.units.Quantity`
        Frequency, wavelength, or wave number.
        If not a Quantity, it is assumed to be in Hz.

    temperature : number, array-like, or `~astropy.units.Quantity`
        Blackbody temperature.
        If not a Quantity, it is assumed to be in Kelvin.

    Returns
    -------
    flux : `~astropy.units.Quantity`
        Blackbody monochromatic flux in
        :math:`erg \\; cm^{-2} s^{-1} Hz^{-1} sr^{-1}`.

    Raises
    ------
    ValueError
        Invalid temperature.

    ZeroDivisionError
        Wavelength is zero (when converting to frequency).

    """
    # Convert to units for calculations, also force double precision
    with u.add_enabled_equivalencies(u.spectral() + u.temperature()):
        freq = u.Quantity(in_x, u.Hz, dtype=np.float64)
        temp = u.Quantity(temperature, u.K, dtype=np.float64)

    # Check if input values are physically possible
    if np.any(temp < 0):
        raise ValueError('Temperature should be positive: {0}'.format(temp))
    if not np.all(np.isfinite(freq)) or np.any(freq <= 0):
        warnings.warn('Input contains invalid wavelength/frequency value(s)',
                      AstropyUserWarning)

    log_boltz = const.h * freq / (const.k_B * temp)
    boltzm1 = np.expm1(log_boltz)

    if _has_buggy_expm1:
        # Replace incorrect nan results with infs--any result of 'nan' is
        # incorrect unless the input (in log_boltz) happened to be nan to begin
        # with.  (As noted in #4393 ideally this would be replaced by a version
        # of expm1 that doesn't have this bug, rather than fixing incorrect
        # results after the fact...)
        boltzm1_nans = np.isnan(boltzm1)
        if np.any(boltzm1_nans):
            if boltzm1.isscalar and not np.isnan(log_boltz):
                boltzm1 = np.inf
            else:
                boltzm1[np.where(~np.isnan(log_boltz) & boltzm1_nans)] = np.inf

    # Calculate blackbody flux
    bb_nu = (2.0 * const.h * freq ** 3 / (const.c ** 2 * boltzm1))
    flux = bb_nu.to(FNU, u.spectral_density(freq))

    return flux / u.sr  # Add per steradian to output flux unit
Example #38
0
    def __init__(self, uvfitsfile, telescope=None, vsys=0, distance=0, endian=None, **kwargs):
        """

        Reads the uvfits and calculates useful things, e.g. u,v,w,
        phase and amplitude

        .byteswap().newbyteorder() is applied in various places to
        convert to little endian

        """
        f = pfopen(uvfitsfile, **kwargs)
        self.loadendian = endian
        if f[0].header['NAXIS1'] != 0:
            print "error: this file may not be a UV FITS."
            raise FileError('File format error.')
        #~ f.info()
        try:
            self.hdu = f[0]
        except:
            print "error: cannot open uv data HDU."
        self.hdr = self.hdu.header
        self.data = self.hdu.data
        if self.hdr['NAXIS4'] > 1:
            self.datatype = ('CUBE', 3)
        else:
            self.datatype = ('IMAGE', 2)
        
        # find spectral axis
        axis_types = self.WCS.get_axis_types()
        ax_types = np.array([i['coordinate_type'] for i in axis_types])
        try:
            spec_axis = ('spectral' == ax_types).nonzero()[0][0]
            freq = self.hdu.header['CRVAL{0}'.format(spec_axis+1)]
            # assumes the frequency given in Hz
            self.freq = freq * un.Hz
        except (IndexError):
            print('No spectral axis in header.')
            spec_axis = -1
            self.freq = None
        
        
        if 'RESTFREQ' in self.hdu.header.keys():
            self.restfreq = self.hdu.header['RESTFREQ']
            self.restfreq_unit = self.hdu.header['RESTFREQ'] * u.Hz
        else:
            raise StandardError('No restfrequency found, NEED it!')
        #TODO : Read in velocity and frequency array if present
        """
        The standard unit is to give UU and VV in seconds (??!?)
        So we have to convert to whatever we want.
        """
        # standard storing unit here is kilo-lambdas
        # save a million lines of code!
        u.add_enabled_equivalencies(lambdas_equivalencies(self.restfreq_unit))
        self.u = (self.data.par('UU') * u.s).to(klambdas)
        self.v = (self.data.par('VV') * u.s).to(klambdas)
        self.w = (self.data.par('WW') * u.s).to(klambdas)
        self.uvdist = sqrt(self.u.value**2 + self.v.value**2) * klambdas


        # BASELINE
        self.baseline = self.hdu.data.par('BASELINE').byteswap().newbyteorder()
        # DATES
        self.jdate = self.hdu.data.par('DATE')
        # set date to 1900, Jan, 01, 01:00:00 if date before before this
        self.jdate =self.jdate.clip(2415020.5)
        self.date = _sp.array([jd2gd(i) for i in self.jdate])
        self.date0 = self.date.transpose()
        fields = ['year', 'month', 'day', 'hour', 'minute', 'sec']
        self.date1 = {key:value for key,value in zip(fields, self.date0)}
        # convert to datetime objects
        # LOSES the sub-second resolution
        self.date2 = [_dt(int(i[0]), int(i[1]), int(i[2]), int(i[3]), int(i[4]), int(i[5])) for i in self.date]
        # get number of tracks
        # TODO : rough hack, separate track if diff day is >1
        tmp = _sp.where(_sp.diff(_sp.unique(self.jdate.round(0)))>1)[0]
        self.ntracks = len(tmp)+1
        
        ################################################################
        # NB : need to streamline this.
        # only load the complex visibilities, into a complex array
        # AND then work on that
        
        
        # COMPLEX VISIBILITY
        visi_index = len(self.data.parnames)
        if self.hdu.header['NAXIS']  == 7:
            self.visdata = self.data.par(visi_index)[:,0,0,0,0,0,:].byteswap().newbyteorder()
        #~ self.visdata = self.hdu.data.data[:,0,0,0,0,0,:]
        elif self.hdu.header['NAXIS']  == 6:
            self.visdata = self.data.par(visi_index)[:,0,0,0,0,:].byteswap().newbyteorder()
        # load the re, im and weight arrays
        self.re, self.im, self.wt = self.visdata[:,:].T
        #~ self.re = self.visdata[:,0][:]
        #~ self.im = self.visdata[:,1][:]
        #~ self.wt = self.visdata[:,2][:]
        # complex numbers
        #~ self.comp = self.visdata[:,:2].astype(_np.float64).view(_np.complexfloating)
        #~ self.comp = 1j*self.visdata[:,1][:]
        #~ self.comp += self.visdata[:,0][:]
        #~ self.comp = self.visdata[:,:2].astype(_np.float).view(_np.complex)
        
        # below seems a bit dependent...
        self.cvisi = self.visdata[:,:2].astype(_np.float).view(_np.complex).T[0]
        """
        with complex array, you can do
        amp = np.abs(vis)
        np.angle(vis)   
        vis.real
        vis.imag
        
        """
        # the data is not shifted
        self.isshifted = (False, [0,0])
        # AMPLITUDE 
        self.amp = sqrt(self.re**2 + self.im**2)
        # PHASE
        self.pha = arctan2(self.im, self.re)
        self.pha_deg = self.pha / pi * 180.
        # ERROR / SIGMA
        #TODO : check
        # following 1.0e6 is just for GILDAS, change if needed
        #~ print('NB : Error calculated from weights assuming GILDAS '
        #~ 'data (i.e. frequencies in MHz).')
        self.sigma_alt = 1/sqrt(self.wt*1.0e6)
        # Daniels way of calculating sigma
        # test this first
        self.sigma = _sp.sqrt(0.5 / ( self.wt * float(self.amp.shape[0]) ) )