def predict(self, hillas_dict, inst, pointing_alt, pointing_az):
        '''
        The function you want to call for the reconstruction of the
        event. It takes care of setting up the event and consecutively
        calls the functions for the direction and core position
        reconstruction.  Shower parameters not reconstructed by this
        class are set to np.nan

        Parameters
        -----------
        hillas_dict: dict
            dictionary with telescope IDs as key and
            HillasParametersContainer instances as values
        inst : ctapipe.io.InstrumentContainer
            instrumental description
        pointing_alt: dict[astropy.coordinates.Angle]
            dict mapping telescope ids to pointing altitude
        pointing_az: dict[astropy.coordinates.Angle]
            dict mapping telescope ids to pointing azimuth

        Raises
        ------
        TooFewTelescopesException
            if len(hillas_dict) < 2
        '''

        # filter warnings for missing obs time. this is needed because MC data has no obs time
        warnings.filterwarnings(action='ignore', category=MissingFrameAttributeWarning)
        
        # stereoscopy needs at least two telescopes
        if len(hillas_dict) < 2:
            raise TooFewTelescopesException(
                "need at least two telescopes, have {}"
                .format(len(hillas_dict)))

        self.initialize_hillas_planes(
            hillas_dict,
            inst.subarray,
            pointing_alt,
            pointing_az
        )

        # algebraic direction estimate
        direction, err_est_dir = self.estimate_direction()

        alt = u.Quantity(list(pointing_alt.values()))
        az = u.Quantity(list(pointing_az.values()))
        if np.any(alt != alt[0]) or np.any(az != az[0]):
            warnings.warn('Divergent pointing not supported')

        telescope_pointing = SkyCoord(alt=alt[0], az=az[0], frame=AltAz())
        # core position estimate using a geometric approach
        core_pos = self.estimate_core_position(hillas_dict, telescope_pointing)

        # container class for reconstructed showers
        result = ReconstructedShowerContainer()
        _, lat, lon = cartesian_to_spherical(*direction)

        # estimate max height of shower
        h_max = self.estimate_h_max()

        # astropy's coordinates system rotates counter-clockwise.
        # Apparently we assume it to be clockwise.
        result.alt, result.az = lat, -lon
        result.core_x = core_pos[0]
        result.core_y = core_pos[1]
        result.core_uncert = np.nan

        result.tel_ids = [h for h in hillas_dict.keys()]
        result.average_intensity = np.mean([h.intensity for h in hillas_dict.values()])
        result.is_valid = True

        result.alt_uncert = err_est_dir
        result.az_uncert = np.nan

        result.h_max = h_max
        result.h_max_uncert = np.nan

        result.goodness_of_fit = np.nan

        return result
Exemplo n.º 2
0
    def transform(self, matrix):
        """
        Transform the cartesian coordinates using a 3x3 matrix.

        This returns a new representation and does not modify the original one.

        Parameters
        ----------
        matrix : `~numpy.ndarray`
            A 3x3 transformation matrix, such as a rotation matrix.

        Examples
        --------

        We can start off by creating a cartesian representation object:

            >>> from astropy import units as u
            >>> from astropy.coordinates import CartesianRepresentation
            >>> rep = CartesianRepresentation([1, 2] * u.pc,
            ...                               [2, 3] * u.pc,
            ...                               [3, 4] * u.pc)

        We now create a rotation matrix around the z axis:

            >>> from astropy.coordinates.matrix_utilities import rotation_matrix
            >>> rotation = rotation_matrix(30 * u.deg, axis='z')

        Finally, we can apply this transformation:

            >>> rep_new = rep.transform(rotation)
            >>> rep_new.xyz  # doctest: +FLOAT_CMP
            <Quantity [[ 1.8660254 , 3.23205081],
                       [ 1.23205081, 1.59807621],
                       [ 3.        , 4.        ]] pc>
        """
        # Avoid doing gratuitous np.array for things that look like arrays.
        try:
            matrix_shape = matrix.shape
        except AttributeError:
            matrix = np.array(matrix)
            matrix_shape = matrix.shape

        if matrix_shape[-2:] != (3, 3):
            raise ValueError("tried to do matrix multiplication with an array "
                             "that doesn't end in 3x3")

        # TODO: since this is likely to be a widely used function in coordinate
        # transforms, it should be optimized (for example in Cython).

        # Get xyz once since it's an expensive operation
        oldxyz = self.xyz
        # Note that neither dot nor einsum handles Quantity properly, so we use
        # the arrays and put the unit back in the end.
        if self.isscalar and not matrix_shape[:-2]:
            # a fast path for scalar coordinates.
            newxyz = matrix.dot(oldxyz.value)
        else:
            # Matrix multiply all pmat items and coordinates, broadcasting the
            # remaining dimensions.
            newxyz = np.einsum('...ij,j...->i...', matrix, oldxyz.value)

        newxyz = u.Quantity(newxyz, oldxyz.unit, copy=False)
        return self.__class__(*newxyz, copy=False)
Exemplo n.º 3
0
    def __init__(self, fit=None, h5file=None, redshift=None, lumdist=None,
                 cosmo_type='WMAP9'):
        """
        Parameters
        ----------
        fit : mbb_fitter
          Fit object

        h5file : string
          Name of HDF5 file to load from previously saved fit.  You can't
          provide this in combination with any of the other variables.

        redshift : float
          Redshift of source.  Necessary if you plan to compute
          dustmass, L_IR, or L_AGN

        lumdist : float or astropy.units.Quantity
          Luminosity distance to object, in Mpc if units not specified.

        cosmo_type : string
          Name of cosmology to use if needed.  The pre-loaded
          cosmologies from astropy.cosmology are supported (e.g.,
          'WMAP9', 'Planck13').  This is used if lumdist is not provided
        """

        # Make sure user isn't trying to specify too much
        if not h5file is None:
            if not fit is None:
                raise Exception("It doesn't make sense to provide h5file"
                                " and a fit to process")
            if not redshift is None:
                raise Exception("It doesn't make sense to provide h5file"
                                " and the redshift")
            if not lumdist is None:
                raise Exception("It doesn't make sense to provide h5file"
                                " and the lumdist")

        self._fitset = False
        self._has_lir = False
        self._lir_min = None
        self._lir_max = None
        self._has_dustmass = False
        self._kappa = None
        self._kappa_wave = None
        self._has_peaklambda = False

        if not h5file is None:
            self.readFromHDF5(h5file)
        else:
            if redshift is None:
                self._z = None
            else:
                self._z = float(redshift)

            if lumdist is None:
                self._has_lumdist = False
            else:
                self._has_lumdist = True
                if isinstance(lumdist, u.Quantity):
                    self._lumdist = lumdist.to(u.Mpc)
                else:
                    self._lumdist = u.Quantity(float(lumdist), u.Mpc)
            if cosmo_type is None:
                raise ValueError("Cosmology type must not be none -- "
                                 "maybe you should just use the default")
            self._cosmo_type = cosmo_type

            if not fit is None:
                self.process_fit(fit)
Exemplo n.º 4
0
from datetime import timedelta

import pytest

import astropy.units as u
from astropy.time import Time, TimeDelta
from astropy.utils.exceptions import ErfaWarning

import sunpy.time
from sunpy.time import is_time_equal

tbegin_str = '2012/1/1'
tfin_str = '2012/1/2'
dt = u.Quantity(24 * 60 * 60, 's')

start = sunpy.time.parse_time(tbegin_str)
end = sunpy.time.parse_time(tfin_str)
delta = end - start


@pytest.mark.parametrize("inputs", [(tbegin_str, tfin_str), (tbegin_str, dt),
                                    (tbegin_str, TimeDelta(1 * u.day)),
                                    (tbegin_str, timedelta(days=1))])
def test_timerange_inputs(inputs):
    timerange = sunpy.time.TimeRange(*inputs)
    assert isinstance(timerange, sunpy.time.TimeRange)
    assert timerange.start == start
    assert timerange.end == end
    assert timerange.dt == delta

Exemplo n.º 5
0
def test_minutes(timerange_a):
    assert timerange_a.minutes == u.Quantity(24 * 60, 'min')
Exemplo n.º 6
0
pictureDir = Dir + 'picture/'
scriptDir = Dir + 'script/'
image_12CO10 = 'NGC5258_12CO10_combine_smooth_masked'
image_13CO10 = 'NGC5258_13CO10_12m_smooth_masked'
image_ratio = imageDir + 'NGC5258_1213_ratio_pbcor'

############################################################
# basic information
galaxy = 'NGC5258'
rationame = '12CO/13CO 1-0'
ratiolabel = '1213'
freq12 = 112
freq13 = 107

center = SkyCoord(dec=0.8319 * u.degree, ra=204.9908 * u.degree, frame='icrs')
size = u.Quantity((54, 42), u.arcsec)

stat12 = {}
stat13 = {}
stat = {}
apertures = {}
regions = ['center', 'ring around center', 'northarm', 'southarm']
values = ['flux', 'uncertainty']
ratio = ['ratio', 'uncertainty']
type = ['sky', 'pix']
stat12 = dict.fromkeys(regions, {})
stat13 = dict.fromkeys(regions, {})
apertures = apertures.fromkeys(regions, {})
stat = dict.fromkeys(regions, {})
for region in regions:
    stat12[region] = dict.fromkeys(values)
Exemplo n.º 7
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
Exemplo n.º 8
0
    param3 = uvp.UVParameter(name="p3", value=np.array([0, 1]))
    assert param1 != param3


def test_array_equality_nans():
    """Test array equality with nans present."""
    param1 = uvp.UVParameter(name="p1", value=np.array([0, 1, np.nan]))
    param2 = uvp.UVParameter(name="p2", value=np.array([0, 1, np.nan]))
    assert param1 == param2


@pytest.mark.parametrize("atol", [0.001, 1 * units.mm])
@pytest.mark.parametrize(
    "vals",
    (
        units.Quantity([0 * units.cm, 100 * units.cm, 3000 * units.mm]),
        units.Quantity([0.09 * units.cm, 100.09 * units.cm, 2999.1 * units.mm
                        ]),
        np.array([0, 1000, 3000]) * units.mm,
    ),
)
def test_quantity_equality(atol, vals):
    """Test equality for different quantity values."""
    param1 = uvp.UVParameter(name="p1",
                             value=np.array([0, 1, 3]) * units.m,
                             tols=atol)
    param2 = uvp.UVParameter(name="p2", value=vals, tols=atol)
    assert param1 == param2


def test_quantity_equality_error():
Exemplo n.º 9
0
vmag = -99.
bmag = -99.
vmage = -99.
bmage = -99.
jmags = -99.
hmags = -99.
kmags = -99.
jmagse = -99.
hmagse = -99.
kmagse = -99.
ra = -99.
dec = -99.

print('querying Gaia ...')
try:
    width = u.Quantity(0.01, u.deg)
    height = u.Quantity(0.01, u.deg)
    gaiaq = Gaia.query_object_async(coordinate=coord[0],
                                    width=width,
                                    height=height)
    plx = gaiaq['parallax'][0] + 0.05
    plxe = gaiaq['parallax_error'][0]
    bpmags = gaiaq['phot_bp_mean_mag'][0]
    bpmagse = 0.01
    rpmags = gaiaq['phot_rp_mean_mag'][0]
    rpmagse = 0.01
    print('done')
except:
    gaiaq = 0
    print('failed')
Exemplo n.º 10
0
from astropy.units.quantity import QuantityInfoBase
from astropy.utils.exceptions import AstropyUserWarning
from .angles import Longitude, Latitude
from .representation import CartesianRepresentation, CartesianDifferential
from .errors import UnknownSiteException
from astropy.utils import data
from astropy import _erfa as erfa

__all__ = ['EarthLocation']

GeodeticLocation = collections.namedtuple('GeodeticLocation', ['lon', 'lat', 'height'])

# Available ellipsoids (defined in erfam.h, with numbers exposed in erfa).
ELLIPSOIDS = ('WGS84', 'GRS80', 'WGS72')

OMEGA_EARTH = u.Quantity(7.292115855306589e-5, 1./u.s)
"""
Rotational velocity of Earth. In UT1 seconds, this would be 2 pi / (24 * 3600),
but we need the value in SI seconds.
See Explanatory Supplement to the Astronomical Almanac, ed. P. Kenneth Seidelmann (1992),
University Science Books.
"""


def _check_ellipsoid(ellipsoid=None, default='WGS84'):
    if ellipsoid is None:
        ellipsoid = default
    if ellipsoid not in ELLIPSOIDS:
        raise ValueError('Ellipsoid {} not among known ones ({})'
                         .format(ellipsoid, ELLIPSOIDS))
    return ellipsoid
Exemplo n.º 11
0
def is_quantity(instance):
    try:
        _ = u.Quantity(instance)
        return True
    except ValueError:
        return False
Exemplo n.º 12
0
Arquivo: spo.py Projeto: hamogu/ARCUS
from .. import config

# factor 2.3545 converts from FWHM to sigma
perpplanescatter = 1.5 / 2.3545 * u.arcsec
# 2 * 0.68 converts HPD to sigma
inplanescatter = 7. / (2 * 0.68) * u.arcsec

focallength = 12000.


spogeom = load_table('spos', 'petallayout')
spogeom['r_mid'] = (spogeom['outer_radius'] + spogeom['inner_radius']) / 2
spo_pos4d = []
# Convert angle to quantity here to make sure that unit is taken into account
for row, ang in zip(spogeom,
                    u.Quantity(spogeom['clocking_angle']).to(u.rad).value):
    spo_pos4d.append(compose([0,  # focallength,  # - spogeom[i]['d_from_12m']
                              row['r_mid'] * np.sin(ang),
                              row['r_mid'] * np.cos(ang)],
                             euler2mat(-ang, 0., 0.),
                             # In detail this should be (primary_length + gap + secondary_length) / 2
                             # but the gap is somewhat complicated and this is only used
                             # for display, we'll ignore that for now.
                             [row['primary_length'],
                              row['azwidth'] / 2.,
                              (row['outer_radius'] - row['inner_radius']) / 2.]))

spo_pos4d = [np.dot(xyz2zxy, s) for s in spo_pos4d]

reflectivity = load_table2d(os.path.join(config['data']['caldb_inputdata'],
                                         'spos', 'coated_reflectivity.csv'))
Exemplo n.º 13
0
def exposure(geom_true):
    m = Map.from_geom(geom_true)
    m.quantity = np.ones(geom_true.data_shape) * u.Quantity("100 m2 s")
    m.data[1] *= 10
    return m
Exemplo n.º 14
0
    def __init__(self, rad, psf_value, interp_kwargs=None):
        self.rad = Angle(rad).to("rad")
        self.psf_value = u.Quantity(psf_value).to("sr^-1")

        self._interp_kwargs = interp_kwargs or {}
Exemplo n.º 15
0
    def function(self, lamb, Av=1.0, Rv=3.1, Alambda=True, **kwargs):
        """
        Cardelli89 extinction Law

        Parameters
        ----------
        lamb: float or ndarray(dtype=float)
            wavelength [in Angstroms] at which to evaluate the law.

        Av: float
            desired A(V) (default: 1.0)

        Rv: float
            desired R(V) (default: 3.1)

        Alambda: bool
            if set returns +2.5*1./log(10.)*tau, tau otherwise

        Returns
        -------
        r: float or ndarray(dtype=float)
            attenuation as a function of wavelength
            depending on Alambda option +2.5*1./log(10.)*tau,  or tau
        """
        # ensure the units are in angstrom
        _lamb = units.Quantity(lamb, units.angstrom).value

        if isinstance(_lamb, float) or isinstance(_lamb, np.float_):
            _lamb = np.asarray([lamb])
        else:
            _lamb = lamb[:]

        # convert to wavenumbers
        x = 1.0e4 / _lamb

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

        # init variables
        a = np.zeros(np.size(x))
        b = np.zeros(np.size(x))
        # Infrared (Eq 2a,2b)
        ind = np.where((x >= 0.3) & (x < 1.1))
        a[ind] = 0.574 * x[ind]**1.61
        b[ind] = -0.527 * x[ind]**1.61
        # Optical & Near IR
        # Eq 3a, 3b
        ind = np.where((x >= 1.1) & (x < 3.3))
        y = x[ind] - 1.82
        a[ind] = (1.0 + 0.17699 * y - 0.50447 * y**2 - 0.02427 * y**3 +
                  0.72085 * y**4 + 0.01979 * y**5 - 0.77530 * y**6 +
                  0.32999 * y**7)
        b[ind] = (1.41338 * y + 2.28305 * y**2 + 1.07233 * y**3 -
                  5.38434 * y**4 - 0.62251 * y**5 + 5.30260 * y**6 -
                  2.09002 * y**7)
        # UV
        # Eq 4a, 4b
        ind = np.where((x >= 3.3) & (x <= 8.0))
        a[ind] = 1.752 - 0.316 * x[ind] - 0.104 / ((x[ind] - 4.67)**2 + 0.341)
        b[ind] = -3.090 + 1.825 * x[ind] + 1.206 / ((x[ind] - 4.62)**2 + 0.263)

        ind = np.where((x >= 5.9) & (x <= 8.0))
        y = x[ind] - 5.9
        Fa = -0.04473 * y**2 - 0.009779 * y**3
        Fb = 0.21300 * y**2 + 0.120700 * y**3
        a[ind] = a[ind] + Fa
        b[ind] = b[ind] + Fb
        # Far UV
        # Eq 5a, 5b
        ind = np.where((x > 8.0) & (x <= 10.0))
        # Fa = Fb = 0
        y = x[ind] - 8.0
        a[ind] = -1.073 - 0.628 * y + 0.137 * y**2 - 0.070 * y**3
        b[ind] = 13.670 + 4.257 * y - 0.420 * y**2 + 0.374 * y**3

        # Case of -values x out of range [0.289,10.0]
        ind = np.where((x > 10.0) | (x < 0.3))
        a[ind] = 0.0
        b[ind] = 0.0

        # Return Extinction vector
        # Eq 1
        if Alambda:
            return (a + b / Rv) * Av
        else:
            # return( 1./(2.5 * 1. / np.log(10.)) * ( a + b / Rv ) * Av)
            return 0.4 * np.log(10.0) * (a + b / Rv) * Av
Exemplo n.º 16
0
 def __init__(self, maps, temperature: u.K, responses, **kwargs):
     self.temperature = temperature
     wvl = u.Quantity([m.meta['wavelnth']*u.Unit(m.meta['waveunit']) for m in maps])
     self.maps = [maps[i] for i in np.argsort(wvl)]
     self.response = [responses[i] for i in np.argsort(wvl)]
     self.wavelength = np.sort(wvl)
Exemplo n.º 17
0
    def __init__(
            self,
            geometry,
            image=None,
            ax=None,
            title="Camera",
            norm="lin",
            cmap="hot",
            allow_pick=False,
            autoupdate=True,
            autoscale=True,
            antialiased=True,
            ):
        self.axes = ax if ax is not None else plt.gca()
        self.geom = geometry
        self.pixels = None
        self.colorbar = None
        self.autoupdate = autoupdate
        self.autoscale = autoscale
        self._active_pixel = None
        self._active_pixel_label = None

        # initialize the plot and generate the pixels as a
        # RegularPolyCollection

        patches = []

        if not hasattr(self.geom, "mask"):
            self.geom.mask = np.ones_like(self.geom.pix_x.value, dtype=bool)

        for xx, yy, aa in zip(
            u.Quantity(self.geom.pix_x[self.geom.mask]).value,
            u.Quantity(self.geom.pix_y[self.geom.mask]).value,
            u.Quantity(np.array(self.geom.pix_area)[self.geom.mask]).value):

            if self.geom.pix_type.startswith("hex"):
                rr = sqrt(aa * 2 / 3 / sqrt(3))
                poly = RegularPolygon(
                    (xx, yy), 6, radius=rr,
                    orientation=self.geom.pix_rotation.rad,
                    fill=True,
                )
            else:
                rr = sqrt(aa)
                poly = Rectangle(
                    (xx-rr/2., yy-rr/2.),
                    width=rr,
                    height=rr,
                    angle=self.geom.pix_rotation.deg,
                    fill=True,
                )

            patches.append(poly)

        self.pixels = PatchCollection(patches, cmap=cmap, linewidth=0)
        self.axes.add_collection(self.pixels)

        self.pixel_highlighting = copy.copy(self.pixels)
        self.pixel_highlighting.set_facecolor('none')
        self.pixel_highlighting.set_linewidth(0)
        self.axes.add_collection(self.pixel_highlighting)

        # Set up some nice plot defaults

        self.axes.set_aspect('equal', 'datalim')
        self.axes.set_title(title)
        self.axes.set_xlabel("X position ({})".format(self.geom.pix_x.unit))
        self.axes.set_ylabel("Y position ({})".format(self.geom.pix_y.unit))
        self.axes.autoscale_view()

        # set up a patch to display when a pixel is clicked (and
        # pixel_picker is enabled):

        self._active_pixel = copy.copy(patches[0])
        self._active_pixel.set_facecolor('r')
        self._active_pixel.set_alpha(0.5)
        self._active_pixel.set_linewidth(2.0)
        self._active_pixel.set_visible(False)
        self.axes.add_patch(self._active_pixel)

        self._active_pixel_label = self.axes.text(self._active_pixel.xy[0],
                                                  self._active_pixel.xy[1],
                                                  "0",
                                                  horizontalalignment='center',
                                                  verticalalignment='center')
        self._active_pixel_label.set_visible(False)

        # enable ability to click on pixel and do something (can be
        # enabled on-the-fly later as well:

        if allow_pick:
            self.enable_pixel_picker()

        if image is not None:
            self.image = image
        else:
            self.image = np.zeros_like(self.geom.pix_id, dtype=np.float)

        self.norm = norm
Exemplo n.º 18
0
def test_angle_to_quantity():
    with pytest.warns(IllegalSecondWarning):
        a = Angle('00:00:60', u.deg)
    q = u.Quantity(a)
    assert isinstance(q, u.Quantity)
    assert q.unit is u.deg
Exemplo n.º 19
0
def test_spectraldensity4():
    """PHOTLAM and PHOTNU conversions."""
    flam = u.erg / (u.cm ** 2 * u.s * u.AA)
    fnu = u.erg / (u.cm ** 2 * u.s * u.Hz)
    photlam = u.photon / (u.cm ** 2 * u.s * u.AA)
    photnu = u.photon / (u.cm ** 2 * u.s * u.Hz)

    wave = u.Quantity([4956.8, 4959.55, 4962.3], u.AA)
    flux_photlam = [9.7654e-3, 1.003896e-2, 9.78473e-3]
    flux_photnu = [8.00335589e-14, 8.23668949e-14, 8.03700310e-14]
    flux_flam = [3.9135e-14, 4.0209e-14, 3.9169e-14]
    flux_fnu = [3.20735792e-25, 3.29903646e-25, 3.21727226e-25]
    flux_jy = [3.20735792e-2, 3.29903646e-2, 3.21727226e-2]
    flux_stmag = [12.41858665, 12.38919182, 12.41764379]
    flux_abmag = [12.63463143, 12.60403221, 12.63128047]

    # PHOTLAM <--> FLAM
    assert_allclose(photlam.to(
        flam, flux_photlam, u.spectral_density(wave)), flux_flam, rtol=1e-6)
    assert_allclose(flam.to(
        photlam, flux_flam, u.spectral_density(wave)), flux_photlam, rtol=1e-6)

    # PHOTLAM <--> FNU
    assert_allclose(photlam.to(
        fnu, flux_photlam, u.spectral_density(wave)), flux_fnu, rtol=1e-6)
    assert_allclose(fnu.to(
        photlam, flux_fnu, u.spectral_density(wave)), flux_photlam, rtol=1e-6)

    # PHOTLAM <--> Jy
    assert_allclose(photlam.to(
        u.Jy, flux_photlam, u.spectral_density(wave)), flux_jy, rtol=1e-6)
    assert_allclose(u.Jy.to(
        photlam, flux_jy, u.spectral_density(wave)), flux_photlam, rtol=1e-6)

    # PHOTLAM <--> PHOTNU
    assert_allclose(photlam.to(
        photnu, flux_photlam, u.spectral_density(wave)), flux_photnu, rtol=1e-6)
    assert_allclose(photnu.to(
        photlam, flux_photnu, u.spectral_density(wave)), flux_photlam, rtol=1e-6)

    # PHOTNU <--> FNU
    assert_allclose(photnu.to(
        fnu, flux_photnu, u.spectral_density(wave)), flux_fnu, rtol=1e-6)
    assert_allclose(fnu.to(
        photnu, flux_fnu, u.spectral_density(wave)), flux_photnu, rtol=1e-6)

    # PHOTNU <--> FLAM
    assert_allclose(photnu.to(
        flam, flux_photnu, u.spectral_density(wave)), flux_flam, rtol=1e-6)
    assert_allclose(flam.to(
        photnu, flux_flam, u.spectral_density(wave)), flux_photnu, rtol=1e-6)

    # PHOTLAM <--> STMAG
    assert_allclose(photlam.to(
        u.STmag, flux_photlam, u.spectral_density(wave)), flux_stmag, rtol=1e-6)
    assert_allclose(u.STmag.to(
        photlam, flux_stmag, u.spectral_density(wave)), flux_photlam, rtol=1e-6)

    # PHOTLAM <--> ABMAG
    assert_allclose(photlam.to(
        u.ABmag, flux_photlam, u.spectral_density(wave)), flux_abmag, rtol=1e-6)
    assert_allclose(u.ABmag.to(
        photlam, flux_abmag, u.spectral_density(wave)), flux_photlam, rtol=1e-6)
def make_rprof(regions, ploteach=False):
    names = [r.attr[1]['text'] for r in regions]
    center_positions = coordinates.SkyCoord([r.coord_list for r in regions],
                                            unit=(u.deg, u.deg),
                                            frame='fk5')

    size = u.Quantity([1.25, 1.25], u.arcsec)

    if ploteach:
        nplots = len(names)
        for ii in range(nplots):
            pl.figure(ii).clf()
            pl.figure(nplots + ii).clf()
            pl.figure(nplots * 2 + ii).clf()

        linestyles = {
            name: itertools.cycle(['-'] + ['--'] + [':'] + ['-.'])
            for name in names
        }

        for fn in ffiles:
            fh = fits.open(paths.dpath("12m/continuum/" + fn))
            mywcs = wcs.WCS(fh[0].header)

            if 'BMAJ' not in fh[0].header:
                #print("File {0} does not have BMAJ".format(fn))
                continue
            try:
                beam = radio_beam.Beam.from_fits_header(fh[0].header)
            except KeyError:
                #print("File {0} doesn't have beam info in the header".format(fn))
                continue

            pixscale = (mywcs.pixel_scale_matrix.diagonal()**2).sum()**0.5
            ppbeam = (beam.sr /
                      (pixscale**2 * u.deg**2)).decompose().value / u.beam
            #print("fn  {0} ppbeam={1:0.2f}".format(fn, ppbeam))

            for ii, (name, position) in enumerate(zip(names,
                                                      center_positions)):
                cutout = Cutout2D(fh[0].data, position, size, wcs=mywcs)

                nr, bins, rprof = azimuthalAverage(cutout.data,
                                                   binsize=1.0,
                                                   return_nr=True)

                linestyle = next(linestyles[name])

                pl.figure(ii)
                pl.title(name)
                pl.plot(bins * pixscale * 3600.,
                        rprof / ppbeam,
                        label=fn.split(".")[0],
                        linestyle=linestyle)
                pl.ylabel("Azimuthally Averaged Flux (Jy)")
                pl.xlabel("Radius [arcsec]")

                cumul_rprof = np.nan_to_num(rprof * nr / ppbeam).cumsum()

                pl.figure(nplots + ii)
                pl.title(name)
                pl.plot(bins * pixscale * 3600.,
                        cumul_rprof,
                        label=fn.split(".")[0],
                        linestyle=linestyle)
                pl.ylabel("Cumulative Flux (Jy)")
                pl.xlabel("Radius [arcsec]")
                if ii == 0:
                    ax = pl.gca()
                    ax2 = ax.twiny()
                    ax3 = ax.twinx()

                    def tick_function(old_x):
                        newx = (old_x * u.arcsec * masscalc.distance).to(
                            u.pc, u.dimensionless_angles()).value
                        return ["%.1f" % z for z in newx]

                    new_tick_locations = [0.005, 0.01, 0.015, 0.02, 0.025
                                          ] * u.pc
                    new_tick_locs_as = (new_tick_locations /
                                        masscalc.distance).to(
                                            u.arcsec, u.dimensionless_angles())
                    ax2.set_xlim(ax.get_xlim())
                    ax2.set_xticks(new_tick_locs_as.value)
                    ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
                    ax2.set_xlabel(r"Radius (pc)")
                    ax3.set_ylim(ax.get_ylim())
                    yticks_mass = np.arange(0, 6000, 1000)
                    yticks_Jy = yticks_mass / masscalc.mass_conversion_factor(
                    ).value
                    ax3.set_yticks(yticks_Jy)
                    ax3.set_yticklabels(yticks_mass)
                    ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=20$ K)")

                pl.figure(nplots * 2 + ii)
                pl.title(name)
                pl.plot(((bins * pixscale * u.deg) * masscalc.distance).to(
                    u.pc, u.dimensionless_angles()),
                        cumul_rprof * masscalc.mass_conversion_factor(),
                        label=fn.split(".")[0],
                        linestyle=linestyle)
                pl.ylabel("Cumulative Mass (M$_\\odot$, $T=20$ K)")
                pl.xlabel("Radius (pc)")

        for ii in range(nplots):
            for xtra in (0, nplots * 2):
                ax = pl.figure(ii + xtra).gca()
                box = ax.get_position()
                ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

                # Put a legend to the right of the current axis
                ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
    else:
        nplots = 0

    pl.matplotlib.rc_file('pubfiguresrc')
    for jj in range(nplots * 3 + 1, nplots * 3 + 11):
        pl.figure(jj).clf()
    # $ find ~/work/w51/alma/FITS/ -samefile ~/work/w51/alma/FITS/W51_te_continuum_best.fits
    # /Users/adam/work/w51/alma/FITS//12m/continuum/selfcal_allspw_selfcal_3_mfs_deeper.image.pbcor.fits
    # /Users/adam/work/w51/alma/FITS//W51_te_continuum_best.fits
    fn = "selfcal_allspw_selfcal_3_mfs_deeper.image.pbcor.fits"
    fh = fits.open(paths.dpath("12m/continuum/" + fn))
    mywcs = wcs.WCS(fh[0].header)
    beam = radio_beam.Beam.from_fits_header(fh[0].header)
    pixscale = (mywcs.pixel_scale_matrix.diagonal()**2).sum()**0.5
    ppbeam = (beam.sr / (pixscale**2 * u.deg**2)).decompose().value / u.beam
    for ii, (name, position) in enumerate(zip(names, center_positions)):
        cutout = Cutout2D(fh[0].data, position, size, wcs=mywcs)

        nr, bins, rprof = azimuthalAverage(cutout.data,
                                           binsize=1.0,
                                           return_nr=True)

        pl.figure(nplots * 3 + 1)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins * pixscale * 3600., rprof / ppbeam, label=name)
        pl.ylabel("Azimuthally Averaged Flux (Jy)")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        cumul_rprof = np.nan_to_num(rprof * nr / ppbeam).cumsum()

        pl.figure(nplots * 3 + 2)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins * pixscale * 3600., cumul_rprof, label=name)
        pl.ylabel("Cumulative Flux (Jy)")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax2 = ax.twiny()
            ax3 = ax.twinx()

            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")
            ax3.set_ylim(ax.get_ylim())
            yticks_mass = np.arange(0, 6000, 1000)
            yticks_Jy = yticks_mass / masscalc.mass_conversion_factor(
                TK=40).value
            ax3.set_yticks(yticks_Jy)
            ax3.set_yticklabels(yticks_mass)
            ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")

        radii = ((bins * pixscale * u.deg) * masscalc.distance).to(
            u.pc, u.dimensionless_angles())
        mass_40k_profile = (cumul_rprof *
                            masscalc.mass_conversion_factor(TK=40) /
                            u.beam).to(u.M_sun)

        pl.figure(nplots * 3 + 3)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(radii, mass_40k_profile, label=name)
        pl.ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")
        pl.xlabel("Radius (pc)")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        density_40k_profile = (mass_40k_profile / (4 / 3. * np.pi * radii**3) /
                               (2.8 * u.Da)).to(u.cm**-3)
        #print(density_40k_profile)
        #print(radii)

        pl.figure(nplots * 3 + 4)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.semilogy(radii, density_40k_profile, label=name)
        pl.ylabel("Cumulative Density [n(H$_2$), $T=40$ K]")
        pl.xlabel("Radius (pc)")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        angular_radii = bins * pixscale * 3600.
        azimuthal_average_flux = rprof / ppbeam
        azimuthal_average_mass = azimuthal_average_flux * masscalc.mass_conversion_factor(
            TK=40) / u.beam
        bindiff_as = np.diff(bins).mean() * pixscale * 3600.
        bindiff_cm = bindiff_as * masscalc.distance / 206265.
        bins_cm = (angular_radii * masscalc.distance / 206265.).to(u.cm)
        sqdiffbins_cm = u.Quantity([bins_cm[0].to(u.cm).value**2] +
                                   (bins_cm.to(u.cm)[1:]**2 -
                                    bins_cm.to(u.cm)[:-1]**2).value.tolist(),
                                   u.cm**2)
        cudiffbins_cm = u.Quantity([bins_cm[0].to(u.cm).value**3] +
                                   (bins_cm.to(u.cm)[1:]**3 -
                                    bins_cm.to(u.cm)[:-1]**3).value.tolist(),
                                   u.cm**3)
        sqdiffbins_pix = [bins[0]**2] + (bins[1:]**2 - bins[:-1]**2).tolist()
        azimuthal_average_density = (azimuthal_average_mass * sqdiffbins_pix /
                                     (2.8 * u.Da) / (4 / 3. * np.pi *
                                                     (cudiffbins_cm))).to(
                                                         u.cm**-3)

        pl.figure(nplots * 3 + 5)
        pl.semilogy(angular_radii, azimuthal_average_density, label=name)
        pl.ylabel("Azimuthally Averaged Density [cm$^{-3}$]")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()

            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")
            #ax3.set_ylim(ax.get_ylim())
            #yticks_mass = np.arange(0,6000,1000)
            #yticks_Jy = yticks_mass/masscalc.mass_conversion_factor(TK=40).value
            #ax3.set_yticks(yticks_Jy)
            #ax3.set_yticklabels(yticks_mass)
            #ax3.set_ylabel("Cumulative Mass (M$_\\odot$, $T=40$ K)")

        c_s_40k = ((constants.k_B * 40 * u.K / (2.4 * u.Da))**0.5).to(u.km /
                                                                      u.s)
        azimuthal_average_MJ_40k = (
            np.pi / 6. * c_s_40k**3 /
            (constants.G**1.5 *
             (2.8 * u.Da * azimuthal_average_density)**0.5)).to(u.M_sun)

        pl.figure(nplots * 3 + 6)
        pl.semilogy(angular_radii, azimuthal_average_MJ_40k, label=name)
        pl.ylabel("Azimuthally Averaged $M_J$ at $T=40$K")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            #ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()

            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")

        source = 'e2' if name == 'e2e' else name
        temperature_map_fn = paths.dpath(
            '12m/moments/CH3OH_{0}_cutout_temperaturemap.fits'.format(source))
        temperature_map_fh = fits.open(temperature_map_fn)

        # this whole section is copied from overlay_contours_on_ch3oh
        ch3ohN_hdul = fits.open(
            paths.dpath(
                '12m/moments/CH3OH_{0}_cutout_columnmap.fits'.format(source)))
        ch3ohT_hdul = fits.open(
            paths.dpath(
                '12m/moments/CH3OH_{0}_cutout_temperaturemap.fits'.format(
                    source)))
        bigwcs = wcs.WCS(ch3ohT_hdul[0].header)
        bigpixscale = (bigwcs.pixel_scale_matrix.diagonal()**
                       2).sum()**0.5 * u.deg
        ch3ohN = ch3ohN_hdul[0].data
        ch3ohT = ch3ohT_hdul[0].data
        dust_brightness, wts = reproject.reproject_interp(
            fits.open(paths.dpath('W51_te_continuum_best.fits')),
            ch3ohN_hdul[0].header)
        bm = radio_beam.Beam.from_fits_header(
            paths.dpath("W51_te_continuum_best.fits"))

        yy, xx = np.indices(ch3ohN.shape)
        if source == 'north':
            center = [84., 38.]
        else:
            center = [ch3ohN.shape[0] / 2., ch3ohN.shape[1] / 2.]
        yyc = (yy - center[0])
        xxc = (xx - center[1])
        rr = (yyc**2 + xxc**2)**0.5
        rr_as = (rr * bigpixscale).to(u.arcsec)
        theta = np.arctan2(yyc, xxc) * u.rad

        dust_column = dust_emissivity.dust.colofsnu(225 * u.GHz,
                                                    dust_brightness * u.Jy,
                                                    beamomega=bm,
                                                    temperature=ch3ohT * u.K)
        ch3oh_abundance = ch3ohN / dust_column.value
        mask = (ch3oh_abundance > 1e-10) & (ch3oh_abundance < 1e-5)
        if source == 'e2':
            mask = mask & (((theta > 15 * u.deg) & (theta < 345 * u.deg)) |
                           (theta < -15 * u.deg))
        mask = mask & np.isfinite(ch3oh_abundance)
        # exclude high-abundance, low-column regions: likely to be div-by-zero zones
        mask = mask & (~((ch3ohN < 1e18) & (ch3oh_abundance > 5e-6)))
        mask = mask & (~((dust_brightness < 1e-2) & (ch3ohT > 500) &
                         (ch3oh_abundance > 1e-6)))

        #mask = mask & (~((ch3ohT > 250) &
        #                 (ch3ohN < 1e18) &
        #                 (rr_as>1.5*u.arcsec))
        #               )# these are low-column,

        temwcs = wcs.WCS(temperature_map_fh[0].header)

        temcutout = Cutout2D(temperature_map_fh[0].data,
                             position,
                             size,
                             wcs=temwcs)
        maskcutout = Cutout2D(mask.astype('float'), position, size, wcs=bigwcs)

        tem_nr, tem_bins, tem_rprof = azimuthalAverage(
            temcutout.data,
            weights=(maskcutout.data > 0).astype('float'),
            binsize=1.0,
            return_nr=True,
            interpnan=True,
        )

        mass_profile = (cumul_rprof *
                        masscalc.mass_conversion_factor(TK=tem_rprof) /
                        u.beam).to(u.M_sun)
        density_profile = (mass_profile / (4 / 3. * np.pi * radii**3) /
                           (2.8 * u.Da)).to(u.cm**-3)

        c_s = ((constants.k_B * tem_rprof * u.K / (2.4 * u.Da))**0.5).to(u.km /
                                                                         u.s)
        azimuthal_average_MJ = (
            np.pi / 6. * c_s**3 /
            (constants.G**1.5 *
             (2.8 * u.Da * azimuthal_average_density)**0.5)).to(u.M_sun)

        pl.figure(nplots * 3 + 7)
        pl.plot(angular_radii, azimuthal_average_MJ, label=name)
        pl.ylabel(
            "Azimuthally Averaged $M_J$ at $T(\\mathrm{CH}_3\\mathrm{OH})$")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            #ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()

            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")

        pl.figure(nplots * 3 + 8)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins * pixscale * 3600., mass_profile, label=name)
        pl.ylabel("Cumulative Mass at T(CH$_3$OH)")
        pl.xlabel("Radius [arcsec]")
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            ax2 = ax.twiny()

            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")

        pl.figure(nplots * 3 + 9)
        #pl.title(fn.replace(".image.pbcor.fits",""))
        pl.plot(bins * pixscale * 3600., tem_rprof, label=name)
        pl.legend(loc='best')
        pl.ylabel("CH$_3$OH temperature")
        pl.xlabel("Radius (as)")

        azimuthal_average_RJ = (
            c_s**1 / (constants.G**0.5 *
                      (2.8 * u.Da * azimuthal_average_density)**0.5)).to(u.au)

        pl.figure(nplots * 3 + 10)
        pl.plot(angular_radii, azimuthal_average_RJ, label=name)
        pl.plot([
            0, (7000 * u.au / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles()).value
        ], [0, 7000],
                'k--',
                alpha=0.5)
        pl.ylabel(
            "Azimuthally Averaged $R_J$ at $T(\\mathrm{CH}_3\\mathrm{OH})$ [au]"
        )
        pl.xlabel("Radius [arcsec]")
        pl.ylim(0, 3000)
        if len(names) < 5:
            pl.legend(loc='best')
        elif ii == len(names) - 1:
            ax = pl.gca()
            box = ax.get_position()
            ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])

            # Put a legend to the right of the current axis
            ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

        if ii == len(names) - 1:
            ax = pl.gca()
            #ax.set_ylim(1e7, 5e10)
            ax2 = ax.twiny()

            #ax3 = ax.twinx()
            def tick_function(old_x):
                newx = (old_x * u.arcsec * masscalc.distance).to(
                    u.au, u.dimensionless_angles()).value
                return ["%.1f" % z for z in newx]

            new_tick_locations = np.arange(0, 8000, 1000) * u.au
            new_tick_locs_as = (new_tick_locations / masscalc.distance).to(
                u.arcsec, u.dimensionless_angles())
            ax2.set_xlim(ax.get_xlim())
            ax2.set_xticks(new_tick_locs_as.value)
            ax2.set_xticklabels(tick_function(new_tick_locs_as.value))
            ax2.set_xlabel(r"Radius [au]")
Exemplo n.º 21
0
import astropy.units as u
from astropy.time import Time

from ... import exceptions as sbe
from .. import orbit as sbo
from ..orbit import Orbit

try:
    import pyoorb  # noqa
except ImportError:
    pyoorb = None

# CERES and CERES2 retrieved from Horizons on 24 Sep 2021
CERES = {
    'targetname': '1 Ceres (A801 AA)',
    'H': u.Quantity(3.53, 'mag'),
    'G': 0.12,
    'e': 0.07842518340409492,
    'q': u.Quantity(2.548847914875325, 'au'),
    'incl': u.Quantity(10.58812123343471, 'deg'),
    'Omega': u.Quantity(80.26788752671405, 'deg'),
    'w': u.Quantity(73.70547052298863, 'deg'),
    'n': u.Quantity(0.21428120879034, 'deg / d'),
    'M': u.Quantity(266.0066794881785, 'deg'),
    'nu': u.Quantity(257.137950098325, 'deg'),
    'a': u.Quantity(2.765752567209041, 'AU'),
    'Q': u.Quantity(2.982657219542757, 'AU'),
    'P': u.Quantity(1680.035323826441, 'd'),
    'epoch': Time(2459482.454237461, scale='tdb', format='jd'),
    'Tp': Time(2459921.098955971, scale='tdb', format='jd'),
    'orbtype': 'KEP',
Exemplo n.º 22
0
def vgal_to_hel(coordinate,
                vxyz,
                vcirc=VCIRC,
                vlsr=VLSR,
                galactocentric_frame=None):
    r"""
    Convert a Galactocentric, cartesian velocity to a Heliocentric velocity in
    spherical coordinates (e.g., proper motion and radial velocity).

    The frame of the input coordinate determines the output frame of the proper motions.
    For example, if the input coordinate is in the ICRS frame, the proper motions
    returned will be  :math:`(\mu_\alpha\cos\delta,\mu_delta)`. This function also
    handles array inputs (see examples below).

    Examples
    --------

        >>> import astropy.units as u
        >>> import astropy.coordinates as coord
        >>> c = coord.Galactocentric(x=15.*u.kpc, y=13.*u.kpc, z=2.*u.kpc)
        >>> vxyz = [-115., 100., 95.]*u.km/u.s
        >>> icrs = c.transform_to(coord.ICRS)
        >>> vgal_to_hel(icrs, vxyz)
        (<Quantity -0.876885123328934 mas / yr>, <Quantity 0.024501209459030334 mas / yr>, <Quantity -163.24449462243052 km / s>)

        >>> c = coord.Galactocentric([[15.,11.],[13,21.],[2.,-7]]*u.kpc)
        >>> vxyz = [[-115.,11.], [100.,-21.], [95.,103]]*u.km/u.s
        >>> icrs = c.transform_to(coord.ICRS)
        >>> vgal_to_hel(icrs, vxyz)
        (<Quantity [-0.87688512,-0.91157482] mas / yr>, <Quantity [ 0.02450121,-0.86124895] mas / yr>, <Quantity [-163.24449462,-198.31241148] km / s>)

    Parameters
    ----------
    coordinate : :class:`~astropy.coordinates.SkyCoord`, :class:`~astropy.coordinates.BaseCoordinateFrame`
        This is most commonly a :class:`~astropy.coordinates.SkyCoord` object, but
        alternatively, it can be any coordinate frame object that is transformable to the
        Galactocentric frame.
    vxyz : :class:`~astropy.units.Quantity`, iterable
        Cartesian velocity components :math:`(v_x,v_y,v_z)`. This should either be a single
        :class:`~astropy.units.Quantity` object with shape (3,N), or an iterable
        object with 3 :class:`~astropy.units.Quantity` objects as elements.
    vcirc : :class:`~astropy.units.Quantity` (optional)
        Circular velocity of the Sun.
    vlsr : :class:`~astropy.units.Quantity` (optional)
        Velocity of the Sun relative to the local standard
        of rest (LSR).
    galactocentric_frame : :class:`~astropy.coordinates.Galactocentric` (optional)
        An instantiated :class:`~astropy.coordinates.Galactocentric` frame object with
        custom parameters for the Galactocentric coordinates. For example, if you want
        to set your own position of the Galactic center, you can pass in a frame with
        custom `galcen_ra` and `galcen_dec`.

    Returns
    -------
    pmv : tuple
        A tuple containing the proper motions (in Galactic coordinates) and
        radial velocity, all as :class:`~astropy.units.Quantity` objects.

    """

    if galactocentric_frame is None:
        galactocentric_frame = coord.Galactocentric

    # so I don't accidentally modify in place
    vxyz = vxyz.copy()

    # make sure this is a coordinate and get the frame for later use
    c = coord.SkyCoord(coordinate)
    coord_frame = c.frame

    R = _icrs_gctc_velocity_matrix(galactocentric_frame)

    # remove circular and LSR velocities
    vxyz[1] = vxyz[1] - vcirc
    for i in range(3):
        vxyz[i] = vxyz[i] - vlsr[i]

    orig_shape = vxyz.shape
    v_icrs = np.linalg.inv(R).dot(
        vxyz.reshape(vxyz.shape[0],
                     np.prod(vxyz.shape[1:]))).reshape(orig_shape)

    # get cartesian galactocentric
    x_icrs = c.icrs.cartesian.xyz
    d = np.sqrt(np.sum(x_icrs**2, axis=0))
    dxy = np.sqrt(x_icrs[0]**2 + x_icrs[1]**2)

    vr = np.sum(x_icrs * v_icrs, axis=0) / d
    with u.set_enabled_equivalencies(u.dimensionless_angles()):
        mua = ((x_icrs[0] * v_icrs[1] - v_icrs[0] * x_icrs[1]) / dxy**2).to(
            u.mas / u.yr)
        mua_cosd = (mua * dxy / d).to(u.mas / u.yr)
        mud = (-(x_icrs[2] * (x_icrs[0] * v_icrs[0] + x_icrs[1] * v_icrs[1]) -
                 dxy**2 * v_icrs[2]) / d**2 / dxy).to(u.mas / u.yr)

    pm_radec = (mua_cosd, mud)

    if coord_frame.name == 'icrs':
        pm = u.Quantity(map(np.atleast_1d, pm_radec))

    elif coord_frame.name == 'galactic':
        # transform to ICRS proper motions
        pm = pm_icrs_to_gal(c, pm_radec)

    else:
        raise NotImplementedError("Proper motions in the {} system are not "
                                  "currently supported.".format(
                                      coord_frame.name))

    if c.isscalar:
        vr = vr.reshape(())
        pm = (pm[0].reshape(()), pm[1].reshape(()))

    return tuple(pm) + (vr, )
Exemplo n.º 23
0
def test_days(timerange_a):
    assert timerange_a.days == u.Quantity(1, 'd')
Exemplo n.º 24
0
def vhel_to_gal(coordinate,
                pm,
                rv,
                vcirc=VCIRC,
                vlsr=VLSR,
                galactocentric_frame=None):
    r"""
    Convert a Heliocentric velocity in spherical coordinates (e.g., proper motion
    and radial velocity) in the ICRS or Galactic frame to a Galactocentric, cartesian
    velocity.

    The frame of the input coordinate determines how to interpret the given
    proper motions. For example, if the input coordinate is in the ICRS frame, the
    proper motions are assumed to be :math:`(\mu_\alpha\cos\delta,\mu_\delta)`. This
    function also handles array inputs (see examples below).

    Examples
    --------

        >>> import astropy.units as u
        >>> import astropy.coordinates as coord
        >>> c = coord.SkyCoord(ra=196.5*u.degree, dec=-10.33*u.deg, distance=16.2*u.kpc)
        >>> pm = [-1.53, 3.5]*u.mas/u.yr
        >>> rv = 161.4*u.km/u.s
        >>> vhel_to_gal(c, pm=pm, rv=rv)
        <Quantity [-137.29984564, 262.64052249, 305.50786499] km / s>

        >>> c = coord.SkyCoord(ra=[196.5,51.3]*u.degree, dec=[-10.33,2.1]*u.deg, distance=[16.2,11.]*u.kpc)
        >>> pm = [[-1.53,4.5], [3.5,10.9]]*u.mas/u.yr
        >>> rv = [161.4,-210.2]*u.km/u.s
        >>> vhel_to_gal(c, pm=pm, rv=rv)
        <Quantity [[-137.29984564,-212.10415701],
                   [ 262.64052249, 496.85687803],
                   [ 305.50786499, 554.16562628]] km / s>

    Parameters
    ----------
    coordinate : :class:`~astropy.coordinates.SkyCoord`, :class:`~astropy.coordinates.BaseCoordinateFrame`
        This is most commonly a :class:`~astropy.coordinates.SkyCoord` object, but
        alternatively, it can be any coordinate frame object that is transformable to the
        Galactocentric frame.
    pm : :class:`~astropy.units.Quantity` or iterable of :class:`~astropy.units.Quantity` objects
        Proper motion in the same frame as the coordinate. For example, if your input
        coordinate is in :class:`~astropy.coordinates.ICRS`, then the proper motion is
        assumed to be in this frame as well. The order of elements should always be
        proper motion in (longitude, latitude), and should have shape (2,N). The longitude
        component is assumed to have the cosine of the latitude already multiplied in, so
        that in ICRS, for example, this would be :math:`\mu_\alpha\cos\delta`.
    rv : :class:`~astropy.units.Quantity`
        Barycentric radial velocity. Should have shape (1,N) or (N,).
    vcirc : :class:`~astropy.units.Quantity` (optional)
        Circular velocity of the Sun.
    vlsr : :class:`~astropy.units.Quantity` (optional)
        Velocity of the Sun relative to the local standard
        of rest (LSR).
    galactocentric_frame : :class:`~astropy.coordinates.Galactocentric` (optional)
        An instantiated :class:`~astropy.coordinates.Galactocentric` frame object with
        custom parameters for the Galactocentric coordinates. For example, if you want
        to set your own position of the Galactic center, you can pass in a frame with
        custom `galcen_ra` and `galcen_dec`.

    Returns
    -------
    vxyz : :class:`~astropy.units.Quantity` (optional)
        Cartesian velocity components (U,V,W). A :class:`~astropy.units.Quantity`
        object with shape (3,N).
    """

    if galactocentric_frame is None:
        galactocentric_frame = coord.Galactocentric

    # make sure this is a coordinate and get the frame for later use
    c = coord.SkyCoord(coordinate)
    coord_frame = c.frame

    if coord_frame.name == 'icrs':
        pm_radec = u.Quantity(map(np.atleast_1d, pm))

    elif coord_frame.name == 'galactic':
        # transform to ICRS proper motions
        pm_radec = pm_gal_to_icrs(c, pm)

    else:
        raise NotImplementedError("Proper motions in the {} system are not "
                                  "currently supported.".format(
                                      coord_frame.name))

    # proper motion components: longitude, latitude
    mura_cosdec, mudec = pm_radec

    # Adrian, you're fired
    a, d, D = c.icrs.ra, c.icrs.dec, c.distance
    with u.set_enabled_equivalencies(u.dimensionless_angles()):
        v_icrs = [
            rv * np.cos(a) * np.cos(d) - D * np.sin(a) * mura_cosdec -
            D * np.cos(a) * np.sin(d) * mudec, rv * np.sin(a) * np.cos(d) +
            D * np.cos(a) * mura_cosdec - D * np.sin(a) * np.sin(d) * mudec,
            rv * np.sin(d) + D * np.cos(d) * mudec
        ]
    v_icrs = np.array([v.to(u.km / u.s).value for v in v_icrs]) * u.km / u.s

    R = _icrs_gctc_velocity_matrix(galactocentric_frame)

    orig_shape = v_icrs.shape
    v_gc = R.dot(v_icrs.reshape(v_icrs.shape[0],
                                np.prod(v_icrs.shape[1:]))).reshape(orig_shape)

    # remove circular and LSR velocities
    v_gc[1] = v_gc[1] + vcirc
    for i in range(3):
        v_gc[i] = v_gc[i] + vlsr[i]

    if c.isscalar:
        return v_gc.reshape((3, ))
    else:
        return v_gc
Exemplo n.º 25
0
def test_hours(timerange_a):
    assert timerange_a.hours == u.Quantity(24, 'hour')
Exemplo n.º 26
0
    def function(self, lamb, Av=1, Rv=3.1, Alambda=True, **kwargs):
        """
        Fitzpatrick99 extinction Law

        Parameters
        ----------
        lamb: float or ndarray(dtype=float)
            wavelength [in Angstroms] at which to evaluate the law.

        Av: float
            desired A(V) (default 1.0)

        Rv: float
            desired R(V) (default 3.1)

        Alambda: bool
            if set returns +2.5*1./log(10.)*tau, tau otherwise

        Returns
        -------
        r: float or ndarray(dtype=float)
            attenuation as a function of wavelength
            depending on Alambda option +2.5*1./log(10.)*tau,  or tau
        """
        # ensure the units are in angstrom
        _lamb = units.Quantity(lamb, units.angstrom).value

        if isinstance(_lamb, float) or isinstance(_lamb, np.float_):
            _lamb = np.asarray([lamb])
        else:
            _lamb = lamb[:]

        # convert to wavenumbers
        x = 1.0e4 / _lamb

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

        # initialize values
        c2 = -0.824 + 4.717 / Rv
        c1 = 2.030 - 3.007 * c2
        c3 = 3.23
        c4 = 0.41
        x0 = 4.596
        gamma = 0.99

        k = np.zeros(np.size(x))

        # compute the UV portion of A(lambda)/E(B-V)
        xcutuv = 10000.0 / 2700.0
        xspluv = 10000.0 / np.array([2700.0, 2600.0])
        ind = np.where(x >= xcutuv)

        if np.size(ind) > 0:
            k[ind] = (c1 + (c2 * x[ind]) + c3 * ((x[ind])**2) /
                      (((x[ind])**2 - (x0**2))**2 + (gamma**2) *
                       ((x[ind])**2)))
            yspluv = (c1 + (c2 * xspluv) + c3 * ((xspluv)**2) /
                      (((xspluv)**2 - (x0**2))**2 + (gamma**2) *
                       ((xspluv)**2)))

            # FUV portion
            fuvind = np.where(x >= 5.9)
            k[fuvind] += c4 * (0.5392 * ((x[fuvind] - 5.9)**2) + 0.05644 *
                               ((x[fuvind] - 5.9)**3))

            k[ind] += Rv
            yspluv += Rv

        # Optical/NIR portion

        ind = np.where(x < xcutuv)
        if np.size(ind) > 0:
            xsplopir = np.zeros(7)
            xsplopir[0] = 0.0
            xsplopir[1:7] = 10000.0 / np.array(
                [26500.0, 12200.0, 6000.0, 5470.0, 4670.0, 4110.0])

            ysplopir = np.zeros(7)
            ysplopir[0:3] = np.array([0.0, 0.26469, 0.82925]) * Rv / 3.1

            ysplopir[3:7] = np.array([
                np.poly1d([2.13572e-04, 1.00270, -4.22809e-01])(Rv),
                np.poly1d([-7.35778e-05, 1.00216, -5.13540e-02])(Rv),
                np.poly1d([-3.32598e-05, 1.00184, 7.00127e-01])(Rv),
                np.poly1d([
                    1.19456, 1.01707, -5.46959e-03, 7.97809e-04, -4.45636e-05
                ][::-1])(Rv),
            ])

            tck = interpolate.splrep(np.hstack([xsplopir, xspluv]),
                                     np.hstack([ysplopir, yspluv]),
                                     k=3)
            k[ind] = interpolate.splev(x[ind], tck)

        # convert from A(lambda)/E(B-V) to A(lambda)/A(V)
        k /= Rv

        # setup the output
        if Alambda:
            return k * Av
        else:
            return k * Av * (np.log(10.0) * 0.4)
Exemplo n.º 27
0
    def readFromHDF5(self, filename):
        """ Restores from an HDF 5 file"""

        import h5py
        f = h5py.File(filename, 'r')

        if "z" in f.attrs:
            self._z = f.attrs["z"]
        else:
            self._z = None

        self._noalpha = f.attrs["Noalpha"]
        self._opthin = f.attrs["Opthin"]
        self._nwalkers = f.attrs["Nwalkers"]
        self._wavenorm = f.attrs["Wavenorm"]
        self._lowlim = f.attrs["Lowlim"]
        self._has_uplim = f.attrs["HasUplim"]
        self._uplim = f.attrs["Uplim"]
        self._has_gprior = f.attrs["HasGaussianPrior"]
        self._gprior_mean = f.attrs["GaussianPriorMean"]
        self._gprior_sigma = f.attrs["GaussianPriorSigma"]
        self._gprior_ivar = f.attrs["GaussianPriorIVar"]
        self._response_integrate = f.attrs["ResponseIntegrate"]
        self._fixed = f.attrs["Fixed"]
        self._ndata = f.attrs["Ndata"]

        if self._response_integrate:
            if not "Responses" in f:
                errmsg = "Didn't find expected responses in {:s}"
                raise ValueError(errmsg.format(filename))
            self._responsewheel = response_set()
            self._responsewheel.readFromHDF5(f["Responses"])

        gd = f["Data"]
        self._data_wave = gd["Wave"][...]
        self._data_flux = gd["FluxDensity"][...]
        self._data_flux_unc = gd["FluxDensityUnc"][...]
        if "Covmatrix" in gd:
            self._has_covmatrix = True
            self._covmatrix = gd["Covmatrix"][...]
            self._invcovmatrix = gd["InvCovmatrix"][...]
        else:
            self._has_covmatrix = False
            if hasattr(self, "_covmatrix"):
                del self._covmatrix
            if hasattr(self, "_invcovmatrix"):
                del self._invcovmatrix

        gc = f["Chain"]
        self.par_central_values = gc["ParamCentralValues"][...]
        self.chain = gc["Chain"][...]
        self.lnprobability = gc["LogLike"][...]
        self._best_fit = (gc["BestFitParams"][...],
                          gc["BestFitLogLike"][()],
                          gc["BestFitIndex"][()])

        ga = f["Ancillary"]

        if "cosmo_type" in ga.attrs:
            self._cosmo_type = ga.attrs["cosmo_type"]
        if "lumdist" in ga.attrs:
            self._has_lumdist = True
            self._lumdist = u.Quantity(ga.attrs["lumdist"], u.Mpc)
        else:
            self._has_lumdist = False

        if "Lir" in ga:
            self._lir_min = ga.attrs["LirMin"]
            self._lir_max = ga.attrs["LirMax"]
            self.lir = ga["Lir"][...]
            self._has_lir = True
        else:
            self._has_lir = False
            self._lir_min = None
            self._lir_max = None
            if hasattr(self, 'lir'):
                del self.lir

        if "Dustmass" in ga:
            self._kappa = ga.attrs["Kappa"]
            self._kappa_wave = ga.attrs["KappaWave"]
            self.dustmass = ga["Dustmass"][...]
            self._has_dustmass = True
        else:
            self._has_dustmass = False
            self._kappa = None
            self._kappa_wave = None
            if hasattr(self, 'dustmass'):
                del self.dustmass

        if "PeakLambda" in ga:
            self._has_peaklambda = True
            self.peaklambda = ga["PeakLambda"][...]
        else:
            self._has_peaklambda = False
            if hasattr(self, 'peaklambda'):
                del self.peaklambda

        self._fitset = True

        f.close()
Exemplo n.º 28
0
    def function(self, lamb, Av=1, Rv=2.74, Alambda=True, **kwargs):
        """
        Gordon03_SMCBar extinction law

        Parameters
        ----------
        lamb: float or ndarray(dtype=float)
            wavelength [in Angstroms] at which to evaluate the law.

        Av: float
            desired A(V) (default 1.0)

        Rv: float
            desired R(V) (default 2.74)

        Alambda: bool
            if set returns +2.5*1./log(10.)*tau, tau otherwise

        Returns
        -------
        r: float or ndarray(dtype=float)
            attenuation as a function of wavelength
            depending on Alambda option +2.5*1./log(10.)*tau,  or tau
        """
        # ensure the units are in angstrom
        _lamb = units.Quantity(lamb, units.angstrom).value

        if isinstance(_lamb, float) or isinstance(_lamb, np.float_):
            _lamb = np.asarray([lamb])
        else:
            _lamb = lamb[:]

        # convert to wavenumbers
        x = 1.0e4 / _lamb

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

        # set Rv explicitly to the fixed value
        Rv = self.Rv

        c1 = -4.959 / Rv
        c2 = 2.264 / Rv
        c3 = 0.389 / Rv
        c4 = 0.461 / Rv
        x0 = 4.6
        gamma = 1.0

        k = np.zeros(np.size(x))

        # UV part
        xcutuv = 10000.0 / 2700.0
        xspluv = 10000.0 / np.array([2700.0, 2600.0])

        ind = np.where(x >= xcutuv)
        if np.size(ind) > 0:
            k[ind] = (1.0 + c1 + (c2 * x[ind]) + c3 * ((x[ind])**2) /
                      (((x[ind])**2 - (x0**2))**2 + (gamma**2) *
                       ((x[ind])**2)))
            yspluv = (1.0 + c1 + (c2 * xspluv) + c3 * ((xspluv)**2) /
                      (((xspluv)**2 - (x0**2))**2 + (gamma**2) *
                       ((xspluv)**2)))

        # FUV portion
        ind = np.where(x >= 5.9)
        if np.size(ind) > 0:
            k[ind] += c4 * (0.5392 * ((x[ind] - 5.9)**2) + 0.05644 *
                            ((x[ind] - 5.9)**3))

        # Opt/NIR part
        ind = np.where(x < xcutuv)
        if np.size(ind) > 0:
            xsplopir = np.zeros(9)
            xsplopir[0] = 0.0
            xsplopir[1:10] = 1.0 / np.array(
                [2.198, 1.65, 1.25, 0.81, 0.65, 0.55, 0.44, 0.37])

            # Values directly from Gordon et al. (2003)
            # ysplopir =  np.array([0.0,0.016,0.169,0.131,0.567,0.801,
            #                      1.00,1.374,1.672])
            # K & J values adjusted to provide a smooth,
            #      non-negative cubic spline interpolation
            ysplopir = np.array(
                [0.0, 0.11, 0.169, 0.25, 0.567, 0.801, 1.00, 1.374, 1.672])

            tck = interpolate.splrep(np.hstack([xsplopir, xspluv]),
                                     np.hstack([ysplopir, yspluv]),
                                     k=3)
            k[ind] = interpolate.splev(x[ind], tck)

        if Alambda:
            return k * Av
        else:
            return k * Av * (np.log(10.0) * 0.4)
Exemplo n.º 29
0
##############################################################################
# It's sometimes useful to specify the solar motion using the `proper motion
# of Sgr A* <https://arxiv.org/abs/astro-ph/0408107>`_ instead of Cartesian
# velocity components. With an assumed distance, we can convert proper motion
# components to Cartesian velocity components using `astropy.units`:

galcen_distance = 8 * u.kpc
pm_gal_sgrA = [-6.379, -0.202] * u.mas / u.yr  # from Reid & Brunthaler 2004
vy, vz = -(galcen_distance * pm_gal_sgrA).to(u.km / u.s,
                                             u.dimensionless_angles())

##############################################################################
# We still have to assume a line-of-sight velocity for the Galactic center,
# which we will again take to be 11 km/s:
vx = 11.1 * u.km / u.s
v_sun2 = u.Quantity([vx, vy, vz])  # List of Quantity -> a single Quantity

gc_frame2 = coord.Galactocentric(galcen_distance=galcen_distance,
                                 galcen_v_sun=v_sun2,
                                 z_sun=0 * u.pc)
gc3 = c1.transform_to(gc_frame2)
print(gc3.v_x, gc3.v_y, gc3.v_z)

##############################################################################
# The transformations also work in the opposite direction. This can be useful
# for transforming simulated or theoretical data to observable quantities. As
# an example, we'll generate 4 theoretical circular orbits at different
# Galactocentric radii with the same circular velocity, and transform them to
# Heliocentric coordinates:

ring_distances = np.arange(10, 25 + 1, 5) * u.kpc
Exemplo n.º 30
0
# Licensed under a 3-clause BSD style license - see LICENSE.rst
import pytest
import astropy.units as u
from ...utils.testing import assert_quantity_allclose
from ...spectrum import create_crab_spectral_model

CRAB_SPECTRA = [
    dict(
        name="meyer",
        dnde=u.Quantity(5.572437502365652e-12, "cm-2 s-1 TeV-1"),
        flux=u.Quantity(2.0744425607240974e-11, "cm-2 s-1"),
        index=2.631535530090332,
    ),
    dict(
        name="hegra",
        dnde=u.Quantity(4.60349681e-12, "cm-2 s-1 TeV-1"),
        flux=u.Quantity(1.74688947e-11, "cm-2 s-1"),
        index=2.62000000,
    ),
    dict(
        name="hess_pl",
        dnde=u.Quantity(5.57327158e-12, "cm-2 s-1 TeV-1"),
        flux=u.Quantity(2.11653715e-11, "cm-2 s-1"),
        index=2.63000000,
    ),
    dict(
        name="hess_ecpl",
        dnde=u.Quantity(6.23714253e-12, "cm-2 s-1 TeV-1"),
        flux=u.Quantity(2.267957713046026e-11, "cm-2 s-1"),
        index=2.529860258102417,
    ),