def get_solar_params_from_string(arg): """Return Galactocentric solar parameters given string names for the parameter sets. """ # Resolve the meaning of 'latest': The latest parameter set is from v4.0 # - update this as newer parameter choices are added if arg == 'latest': arg = 'v4.0' params = dict() references = dict() # Currently, all versions use the same sky position for Sgr A*: params['galcen_coord'] = ICRS(ra=266.4051*u.degree, dec=-28.936175*u.degree) references['galcen_coord'] = \ 'http://adsabs.harvard.edu/abs/2004ApJ...616..872R' # The roll angle is the same for both frames: params['roll'] = 0 * u.deg if arg == 'pre-v4.0': params['galcen_distance'] = 8.3 * u.kpc references['galcen_distance'] = \ 'https://ui.adsabs.harvard.edu/#abs/2009ApJ...692.1075G' params['galcen_v_sun'] = r.CartesianDifferential([11.1, 220+12.24, 7.25]*u.km/u.s) references['galcen_v_sun'] = \ ['https://ui.adsabs.harvard.edu/#abs/2010MNRAS.403.1829S', 'https://ui.adsabs.harvard.edu/#abs/2015ApJS..216...29B'] params['z_sun'] = 27.0 * u.pc references['z_sun'] = \ 'https://ui.adsabs.harvard.edu/#abs/2001ApJ...553..184C' elif arg == 'v4.0': params['galcen_distance'] = 8.122 * u.kpc references['galcen_distance'] = \ 'https://ui.adsabs.harvard.edu/abs/2018A%26A...615L..15G' params['galcen_v_sun'] = r.CartesianDifferential([12.9, 245.6, 7.78]*u.km/u.s) references['galcen_v_sun'] = \ ['https://ui.adsabs.harvard.edu/abs/2018RNAAS...2..210D', 'https://ui.adsabs.harvard.edu/abs/2018A%26A...615L..15G', 'https://ui.adsabs.harvard.edu/abs/2004ApJ...616..872R'] params['z_sun'] = 20.8 * u.pc references['z_sun'] = \ 'https://ui.adsabs.harvard.edu/abs/2019MNRAS.482.1417B' else: raise ValueError('Invalid string input to retrieve solar ' 'parameters for Galactocentric frame: "{}"' .format(arg)) return params, references
def test_representation_with_multiple_differentials(): from astropy.coordinates.builtin_frames import ICRS dif1 = r.CartesianDifferential([1, 2, 3]*u.km/u.s) dif2 = r.CartesianDifferential([1, 2, 3]*u.km/u.s**2) rep = r.CartesianRepresentation([1, 2, 3]*u.pc, differentials={'s': dif1, 's2': dif2}) # check warning is raised for a scalar with pytest.raises(ValueError): ICRS(rep)
def test_vel_transformation_obstime_err(): # TODO: replace after a final decision on PR #6280 from astropy.coordinates.sites import get_builtin_sites diff = r.CartesianDifferential([.1, .2, .3]*u.km/u.s) rep = r.CartesianRepresentation([1, 2, 3]*u.au, differentials=diff) loc = get_builtin_sites()['example_site'] aaf = AltAz(obstime='J2010', location=loc) aaf2 = AltAz(obstime=aaf.obstime + 3*u.day, location=loc) aaf3 = AltAz(obstime=aaf.obstime + np.arange(3)*u.day, location=loc) aaf4 = AltAz(obstime=aaf.obstime, location=loc) aa = aaf.realize_frame(rep) with pytest.raises(NotImplementedError) as exc: aa.transform_to(aaf2) assert 'cannot transform' in exc.value.args[0] with pytest.raises(NotImplementedError) as exc: aa.transform_to(aaf3) assert 'cannot transform' in exc.value.args[0] aa.transform_to(aaf4) aa.transform_to(ICRS())
def test_differentialattribute(): from astropy.coordinates import BaseCoordinateFrame from astropy.coordinates.attributes import DifferentialAttribute # Test logic of passing input through to allowed class vel = [1, 2, 3] * u.km / u.s dif = r.CartesianDifferential(vel) class TestFrame(BaseCoordinateFrame): attrtest = DifferentialAttribute( default=dif, allowed_classes=[r.CartesianDifferential]) frame1 = TestFrame() frame2 = TestFrame(attrtest=dif) frame3 = TestFrame(attrtest=vel) assert np.all(frame1.attrtest.d_xyz == frame2.attrtest.d_xyz) assert np.all(frame1.attrtest.d_xyz == frame3.attrtest.d_xyz) # This shouldn't work if there is more than one allowed class: class TestFrame2(BaseCoordinateFrame): attrtest = DifferentialAttribute(default=dif, allowed_classes=[ r.CartesianDifferential, r.CylindricalDifferential ]) frame1 = TestFrame2() frame2 = TestFrame2(attrtest=dif) with pytest.raises(TypeError): TestFrame2(attrtest=vel)
class transfunc: rep = r.CartesianRepresentation(np.arange(3)*u.pc) dif = r.CartesianDifferential(*np.arange(3, 6)*u.pc/u.Myr) rep0 = r.CartesianRepresentation(np.zeros(3)*u.pc) @classmethod def both(cls, coo, fr): # exchange x <-> z and offset M = np.array([[0., 0., 1.], [0., 1., 0.], [1., 0., 0.]]) return M, cls.rep.with_differentials(cls.dif) @classmethod def just_matrix(cls, coo, fr): # exchange x <-> z and offset M = np.array([[0., 0., 1.], [0., 1., 0.], [1., 0., 0.]]) return M, None @classmethod def no_matrix(cls, coo, fr): return None, cls.rep.with_differentials(cls.dif) @classmethod def no_pos(cls, coo, fr): return None, cls.rep0.with_differentials(cls.dif) @classmethod def no_vel(cls, coo, fr): return None, cls.rep
def test_too_many_differentials(): dif1 = r.CartesianDifferential(*np.arange(3, 6)*u.pc/u.Myr) dif2 = r.CartesianDifferential(*np.arange(3, 6)*u.pc/u.Myr**2) rep = r.CartesianRepresentation(np.arange(3)*u.pc, differentials={'s': dif1, 's2': dif2}) with pytest.raises(ValueError): c = TCoo1(rep) # register and do the transformation and check against expected trans = t.AffineTransform(transfunc.both, TCoo1, TCoo2) trans.register(frame_transform_graph) # Check that if frame somehow gets through to transformation, multiple # differentials are caught c = TCoo1(rep.without_differentials()) c._data = c._data.with_differentials({'s': dif1, 's2': dif2}) with pytest.raises(ValueError): c.transform_to(TCoo2()) trans.unregister(frame_transform_graph)
def __init__(self, *args, **kwargs): # based on Luri et al 2020 including "main" line in table 5 default_params = { 'gal_coord': ICRS(ra=81.28 * u.degree, dec=-69.78 * u.degree), "gal_distance": 49.5 * u.kpc, "galvel_heliocentric": r.CartesianDifferential([439.0, 91.7, 262.2] * (u.km / u.s)), "inclination": 34.08 * u.degree, "PA": 309.9 * u.degree, } kwds = dict() kwds.update(default_params) kwds.update(kwargs) super().__init__(*args, **kwds)
def __init__(self, *args, **kwargs): # these values for comparison with vdm12 transformation - not necessarily current default_params = { 'gal_coord': ICRS(ra=10.68470833 * u.degree, dec=41.26875 * u.degree), "gal_distance": 770.0 * u.kpc, "galvel_heliocentric": r.CartesianDifferential([178.9, -138.8, -301.] * (u.km / u.s)), "inclination": (-77.) * u.degree, "PA": 37. * u.degree, } kwds = dict() kwds.update(default_params) kwds.update(kwargs) super().__init__(*args, **kwds)
def test_affine_transform_fail(transfunc): diff = r.CartesianDifferential(8, 9, 10, unit=u.pc/u.Myr) rep = r.CartesianRepresentation(5, 6, 7, unit=u.pc, differentials=diff) c = TCoo1(rep) # register and do the transformation and check against expected trans = t.AffineTransform(transfunc, TCoo1, TCoo2) trans.register(frame_transform_graph) with pytest.raises(ValueError): c.transform_to(TCoo2()) trans.unregister(frame_transform_graph)
def __init__(self, *args, **kwargs): # these values for comparison with vdm12 transformation - not necessarily current default_params = { 'gal_coord': ICRS(ra=23.4621 * u.degree, dec=30.65994167 * u.degree), "gal_distance": 794.0 * u.kpc, # "gal_distance": 810.0 * u.kpc, "galvel_heliocentric": r.CartesianDifferential([87.3, 28.2, -180.] * (u.km / u.s)), "inclination": (-55.) * u.degree, "PA": 23. * u.degree, } kwds = dict() kwds.update(default_params) kwds.update(kwargs) super().__init__(*args, **kwds)
def test_shorthand_representations(): from astropy.coordinates.builtin_frames import ICRS rep = r.CartesianRepresentation([1, 2, 3] * u.pc) dif = r.CartesianDifferential([1, 2, 3] * u.km / u.s) rep = rep.with_differentials(dif) icrs = ICRS(rep) sph = icrs.spherical assert isinstance(sph, r.SphericalRepresentation) assert isinstance(sph.differentials['s'], r.SphericalDifferential) sph = icrs.sphericalcoslat assert isinstance(sph, r.SphericalRepresentation) assert isinstance(sph.differentials['s'], r.SphericalCosLatDifferential)
def __init__(self, *args, skyalign=False, **kwargs): # left some example code for subclasses in here default_params = { 'gal_coord': ICRS(ra=10.68470833 * u.degree, dec=41.26875 * u.degree), "gal_distance": 780.0 * u.kpc, "galvel_heliocentric": r.CartesianDifferential([125.2, -73.8, -300.] * (u.km / u.s)), "inclination": (-77.) * u.degree, "PA": 37. * u.degree, } kwds = dict() kwds.update(default_params) if skyalign: kwds['inclination'] = 0. * u.deg kwds['PA'] = 0. * u.deg kwds.update(kwargs) super().__init__(*args, **kwds)
def get_galvel(pmra, pmdec, radial_velocity, distance): """Utility routine to retrieve a CartesianDifferential from proper motion, velocity, and distance. This is useful to initialize an ExternalGalaxyFrame, by passing the keyword galvel_heliocentric=get_galvel( 1.0*u.mas/u.yr, 2.0*u.mas/u.yr, radial_velocity=250.*u.km/u.s, distance=400.*u.kpc) Parameters: pmra, pmdec: Quantity dimension of angle/time Proper motion in RA, dec directions. Here pmra means metric and not coordinate velocity (i.e., cos factor should be included) radial_velocity: Quantity, dimension of velocity Heliocentric radial velocity distance: Quantity, dimension of length Heliocentric distance """ v_x = (pmra * distance / u.rad).to(u.km / u.s) v_y = (pmdec * distance / u.rad).to(u.km / u.s) v_z = radial_velocity.to(u.km / u.s) return r.CartesianDifferential(v_x, v_y, v_z)
from astropy.coordinates import representation as r from astropy.coordinates.baseframe import (BaseCoordinateFrame, RepresentationMapping, frame_transform_graph, base_doc) from astropy.coordinates.transformations import AffineTransform from astropy.coordinates.attributes import DifferentialAttribute from .baseradec import BaseRADecFrame, doc_components as doc_components_radec from .icrs import ICRS from .galactic import Galactic from .fk4 import FK4 # For speed J2000 = Time('J2000') v_bary_Schoenrich2010 = r.CartesianDifferential([11.1, 12.24, 7.25]*u.km/u.s) __all__ = ['LSR', 'GalacticLSR', 'LSRK', 'LSRD'] doc_footer_lsr = """ Other parameters ---------------- v_bary : `~astropy.coordinates.representation.CartesianDifferential` The velocity of the solar system barycenter with respect to the LSR, in Galactic cartesian velocity components. """ @format_doc(base_doc, components=doc_components_radec, footer=doc_footer_lsr) class LSR(BaseRADecFrame):
class galactocentric_frame_defaults(ScienceState): """This class controls the global setting of default values for the frame attributes in the `~astropy.coordinates.Galactocentric` frame, which may be updated in future versions of ``astropy``. Note that when using `~astropy.coordinates.Galactocentric`, changing values here will not affect any attributes that are set explicitly by passing values in to the `~astropy.coordinates.Galactocentric` initializer. Modifying these defaults will only affect the frame attribute values when using the frame as, e.g., ``Galactocentric`` or ``Galactocentric()`` with no explicit arguments. This class controls the parameter settings by specifying a string name, with the following pre-specified options: - 'pre-v4.0': The current default value, which sets the default frame attribute values to their original (pre-astropy-v4.0) values. - 'v4.0': The attribute values as updated in Astropy version 4.0. - 'latest': An alias of the most recent parameter set (currently: 'v4.0') Alternatively, user-defined parameter settings may be registered, with :meth:`~astropy.coordinates.galactocentric_frame_defaults.register`, and used identically as pre-specified parameter sets. At minimum, registrations must have unique names and a dictionary of parameters with keys "galcen_coord", "galcen_distance", "galcen_v_sun", "z_sun", "roll". See examples below. This class also tracks the references for all parameter values in the attribute ``references``, as well as any further information the registry. The pre-specified options can be extended to include similar state information as user-defined parameter settings -- for example, to add parameter uncertainties. The preferred method for getting a parameter set and metadata, by name, is :meth:`~galactocentric_frame_defaults.get_from_registry` since it ensures the immutability of the registry. See :ref:`astropy:astropy-coordinates-galactocentric-defaults` for more information. Examples -------- The default `~astropy.coordinates.Galactocentric` frame parameters can be modified globally:: >>> from astropy.coordinates import galactocentric_frame_defaults >>> _ = galactocentric_frame_defaults.set('v4.0') # doctest: +SKIP >>> Galactocentric() # doctest: +SKIP <Galactocentric Frame (galcen_coord=<ICRS Coordinate: (ra, dec) in deg (266.4051, -28.936175)>, galcen_distance=8.122 kpc, galcen_v_sun=(12.9, 245.6, 7.78) km / s, z_sun=20.8 pc, roll=0.0 deg)> >>> _ = galactocentric_frame_defaults.set('pre-v4.0') # doctest: +SKIP >>> Galactocentric() # doctest: +SKIP <Galactocentric Frame (galcen_coord=<ICRS Coordinate: (ra, dec) in deg (266.4051, -28.936175)>, galcen_distance=8.3 kpc, galcen_v_sun=(11.1, 232.24, 7.25) km / s, z_sun=27.0 pc, roll=0.0 deg)> The default parameters can also be updated by using this class as a context manager:: >>> with galactocentric_frame_defaults.set('pre-v4.0'): ... print(Galactocentric()) # doctest: +FLOAT_CMP <Galactocentric Frame (galcen_coord=<ICRS Coordinate: (ra, dec) in deg (266.4051, -28.936175)>, galcen_distance=8.3 kpc, galcen_v_sun=(11.1, 232.24, 7.25) km / s, z_sun=27.0 pc, roll=0.0 deg)> Again, changing the default parameter values will not affect frame attributes that are explicitly specified:: >>> import astropy.units as u >>> with galactocentric_frame_defaults.set('pre-v4.0'): ... print(Galactocentric(galcen_distance=8.0*u.kpc)) # doctest: +FLOAT_CMP <Galactocentric Frame (galcen_coord=<ICRS Coordinate: (ra, dec) in deg (266.4051, -28.936175)>, galcen_distance=8.0 kpc, galcen_v_sun=(11.1, 232.24, 7.25) km / s, z_sun=27.0 pc, roll=0.0 deg)> Additional parameter sets may be registered, for instance to use the Dehnen & Binney (1998) measurements of the solar motion. We can also add metadata, such as the 1-sigma errors. In this example we will modify the required key "parameters", change the recommended key "references" to match "parameters", and add the extra key "error" (any key can be added):: >>> state = galactocentric_frame_defaults.get_from_registry("v4.0") >>> state["parameters"]["galcen_v_sun"] = (10.00, 225.25, 7.17) * (u.km / u.s) >>> state["references"]["galcen_v_sun"] = "https://ui.adsabs.harvard.edu/full/1998MNRAS.298..387D" >>> state["error"] = {"galcen_v_sun": (0.36, 0.62, 0.38) * (u.km / u.s)} >>> galactocentric_frame_defaults.register(name="DB1998", **state) Just as in the previous examples, the new parameter set can be retrieved with:: >>> state = galactocentric_frame_defaults.get_from_registry("DB1998") >>> print(state["error"]["galcen_v_sun"]) # doctest: +FLOAT_CMP [0.36 0.62 0.38] km / s """ _latest_value = 'v4.0' _value = None _references = None _state = dict() # all other data # Note: _StateProxy() produces read-only view of enclosed mapping. _registry = { "v4.0": { "parameters": _StateProxy( { "galcen_coord": ICRS( ra=266.4051 * u.degree, dec=-28.936175 * u.degree ), "galcen_distance": 8.122 * u.kpc, "galcen_v_sun": r.CartesianDifferential( [12.9, 245.6, 7.78] * (u.km / u.s) ), "z_sun": 20.8 * u.pc, "roll": 0 * u.deg, } ), "references": _StateProxy( { "galcen_coord": "https://ui.adsabs.harvard.edu/abs/2004ApJ...616..872R", "galcen_distance": "https://ui.adsabs.harvard.edu/abs/2018A%26A...615L..15G", "galcen_v_sun": [ "https://ui.adsabs.harvard.edu/abs/2018RNAAS...2..210D", "https://ui.adsabs.harvard.edu/abs/2018A%26A...615L..15G", "https://ui.adsabs.harvard.edu/abs/2004ApJ...616..872R", ], "z_sun": "https://ui.adsabs.harvard.edu/abs/2019MNRAS.482.1417B", "roll": None, } ), }, "pre-v4.0": { "parameters": _StateProxy( { "galcen_coord": ICRS( ra=266.4051 * u.degree, dec=-28.936175 * u.degree ), "galcen_distance": 8.3 * u.kpc, "galcen_v_sun": r.CartesianDifferential( [11.1, 220 + 12.24, 7.25] * (u.km / u.s) ), "z_sun": 27.0 * u.pc, "roll": 0 * u.deg, } ), "references": _StateProxy( { "galcen_coord": "https://ui.adsabs.harvard.edu/abs/2004ApJ...616..872R", "galcen_distance": "https://ui.adsabs.harvard.edu/#abs/2009ApJ...692.1075G", "galcen_v_sun": [ "https://ui.adsabs.harvard.edu/#abs/2010MNRAS.403.1829S", "https://ui.adsabs.harvard.edu/#abs/2015ApJS..216...29B", ], "z_sun": "https://ui.adsabs.harvard.edu/#abs/2001ApJ...553..184C", "roll": None, } ), }, } @classproperty # read-only def parameters(cls): return cls._value @classproperty # read-only def references(cls): return cls._references @classmethod def get_from_registry(cls, name: str): """ Return Galactocentric solar parameters and metadata given string names for the parameter sets. This method ensures the returned state is a mutable copy, so any changes made do not affect the registry state. Returns ------- state : dict Copy of the registry for the string name. Should contain, at minimum: - "parameters": dict Galactocentric solar parameters - "references" : Dict[str, Union[str, Sequence[str]]] References for "parameters". Fields are str or sequence of str. Raises ------ KeyError If invalid string input to registry to retrieve solar parameters for Galactocentric frame. """ # Resolve the meaning of 'latest': latest parameter set is from v4.0 # - update this as newer parameter choices are added if name == 'latest': name = cls._latest_value # Get the state from the registry. # Copy to ensure registry is immutable to modifications of "_value". # Raises KeyError if `name` is invalid string input to registry # to retrieve solar parameters for Galactocentric frame. state = copy.deepcopy(cls._registry[name]) # ensure mutable return state @deprecated("v4.2", alternative="`get_from_registry`") @classmethod def get_solar_params_from_string(cls, arg): """ Return Galactocentric solar parameters given string names for the parameter sets. Returns ------- parameters : dict Copy of Galactocentric solar parameters from registry Raises ------ KeyError If invalid string input to registry to retrieve solar parameters for Galactocentric frame. """ return cls.get_from_registry(arg)["parameters"] @classmethod def validate(cls, value): if value is None: value = cls._latest_value if isinstance(value, str): state = cls.get_from_registry(value) cls._references = state["references"] cls._state = state parameters = state["parameters"] elif isinstance(value, dict): parameters = value elif isinstance(value, Galactocentric): # turn the frame instance into a dict of frame attributes parameters = dict() for k in value.frame_attributes: parameters[k] = getattr(value, k) cls._references = value.frame_attribute_references.copy() cls._state = dict(parameters=parameters, references=cls._references) else: raise ValueError("Invalid input to retrieve solar parameters for " "Galactocentric frame: input must be a string, " "dict, or Galactocentric instance") return parameters @classmethod def register(cls, name: str, parameters: dict, references=None, **meta: dict): """Register a set of parameters. Parameters ---------- name : str The registration name for the parameter and metadata set. parameters : dict The solar parameters for Galactocentric frame. references : dict or None, optional References for contents of `parameters`. None becomes empty dict. **meta : dict, optional Any other properties to register. """ # check on contents of `parameters` must_have = {"galcen_coord", "galcen_distance", "galcen_v_sun", "z_sun", "roll"} missing = must_have.difference(parameters) if missing: raise ValueError(f"Missing parameters: {missing}") references = references or {} # None -> {} state = dict(parameters=parameters, references=references) state.update(meta) # meta never has keys "parameters" or "references" cls._registry[name] = state
class Galactocentric(BaseCoordinateFrame): r""" A coordinate or frame in the Galactocentric system. This frame requires specifying the Sun-Galactic center distance, and optionally the height of the Sun above the Galactic midplane. The position of the Sun is assumed to be on the x axis of the final, right-handed system. That is, the x axis points from the position of the Sun projected to the Galactic midplane to the Galactic center -- roughly towards :math:`(l,b) = (0^\circ,0^\circ)`. For the default transformation (:math:`{\rm roll}=0^\circ`), the y axis points roughly towards Galactic longitude :math:`l=90^\circ`, and the z axis points roughly towards the North Galactic Pole (:math:`b=90^\circ`). The default position of the Galactic Center in ICRS coordinates is taken from Reid et al. 2004, http://adsabs.harvard.edu/abs/2004ApJ...616..872R. .. math:: {\rm RA} = 17:45:37.224~{\rm hr}\\ {\rm Dec} = -28:56:10.23~{\rm deg} The default distance to the Galactic Center is 8.3 kpc, e.g., Gillessen et al. (2009), https://ui.adsabs.harvard.edu/#abs/2009ApJ...692.1075G/abstract The default height of the Sun above the Galactic midplane is taken to be 27 pc, as measured by Chen et al. (2001), https://ui.adsabs.harvard.edu/#abs/2001ApJ...553..184C/abstract The default solar motion relative to the Galactic center is taken from a combination of Schönrich et al. (2010) [for the peculiar velocity] and Bovy (2015) [for the circular velocity at the solar radius], https://ui.adsabs.harvard.edu/#abs/2010MNRAS.403.1829S/abstract https://ui.adsabs.harvard.edu/#abs/2015ApJS..216...29B/abstract For a more detailed look at the math behind this transformation, see the document :ref:`coordinates-galactocentric`. The frame attributes are listed under **Other Parameters**. """ default_representation = r.CartesianRepresentation default_differential = r.CartesianDifferential # frame attributes galcen_coord = CoordinateAttribute(default=ICRS(ra=266.4051 * u.degree, dec=-28.936175 * u.degree), frame=ICRS) galcen_distance = QuantityAttribute(default=8.3 * u.kpc) galcen_v_sun = DifferentialAttribute( default=r.CartesianDifferential([11.1, 220 + 12.24, 7.25] * u.km / u.s), allowed_classes=[r.CartesianDifferential]) z_sun = QuantityAttribute(default=27. * u.pc) roll = QuantityAttribute(default=0. * u.deg) def __init__(self, *args, **kwargs): # backwards-compatibility if ('galcen_ra' in kwargs or 'galcen_dec' in kwargs): warnings.warn( "The arguments 'galcen_ra', and 'galcen_dec' are " "deprecated in favor of specifying the sky coordinate" " as a CoordinateAttribute using the 'galcen_coord' " "argument", AstropyDeprecationWarning) galcen_kw = dict() galcen_kw['ra'] = kwargs.pop('galcen_ra', self.galcen_coord.ra) galcen_kw['dec'] = kwargs.pop('galcen_dec', self.galcen_coord.dec) kwargs['galcen_coord'] = ICRS(**galcen_kw) super().__init__(*args, **kwargs) @property def galcen_ra(self): warnings.warn( "The attribute 'galcen_ra' is deprecated. Use " "'.galcen_coord.ra' instead.", AstropyDeprecationWarning) return self.galcen_coord.ra @property def galcen_dec(self): warnings.warn( "The attribute 'galcen_dec' is deprecated. Use " "'.galcen_coord.dec' instead.", AstropyDeprecationWarning) return self.galcen_coord.dec @classmethod def get_roll0(cls): """ The additional roll angle (about the final x axis) necessary to align the final z axis to match the Galactic yz-plane. Setting the ``roll`` frame attribute to -this method's return value removes this rotation, allowing the use of the `Galactocentric` frame in more general contexts. """ # note that the actual value is defined at the module level. We make at # a property here because this module isn't actually part of the public # API, so it's better for it to be accessable from Galactocentric return _ROLL0
def test_concatenate_representations(): from astropy.coordinates.funcs import concatenate_representations from astropy.coordinates import representation as r reps = [r.CartesianRepresentation([1, 2, 3.]*u.kpc), r.SphericalRepresentation(lon=1*u.deg, lat=2.*u.deg, distance=10*u.pc), r.UnitSphericalRepresentation(lon=1*u.deg, lat=2.*u.deg), r.CartesianRepresentation(np.ones((3, 100)) * u.kpc), r.CartesianRepresentation(np.ones((3, 16, 8)) * u.kpc)] reps.append(reps[0].with_differentials( r.CartesianDifferential([1, 2, 3.] * u.km/u.s))) reps.append(reps[1].with_differentials( r.SphericalCosLatDifferential(1*u.mas/u.yr, 2*u.mas/u.yr, 3*u.km/u.s))) reps.append(reps[2].with_differentials( r.SphericalCosLatDifferential(1*u.mas/u.yr, 2*u.mas/u.yr, 3*u.km/u.s))) reps.append(reps[2].with_differentials( r.UnitSphericalCosLatDifferential(1*u.mas/u.yr, 2*u.mas/u.yr))) reps.append(reps[2].with_differentials( {'s': r.RadialDifferential(1*u.km/u.s)})) reps.append(reps[3].with_differentials( r.CartesianDifferential(*np.ones((3, 100)) * u.km/u.s))) reps.append(reps[4].with_differentials( r.CartesianDifferential(*np.ones((3, 16, 8)) * u.km/u.s))) # Test that combining all of the above with itself succeeds for rep in reps: if not rep.shape: expected_shape = (2, ) else: expected_shape = (2 * rep.shape[0], ) + rep.shape[1:] tmp = concatenate_representations((rep, rep)) assert tmp.shape == expected_shape if 's' in rep.differentials: assert tmp.differentials['s'].shape == expected_shape # Try combining 4, just for something different for rep in reps: if not rep.shape: expected_shape = (4, ) else: expected_shape = (4 * rep.shape[0], ) + rep.shape[1:] tmp = concatenate_representations((rep, rep, rep, rep)) assert tmp.shape == expected_shape if 's' in rep.differentials: assert tmp.differentials['s'].shape == expected_shape # Test that combining pairs fails with pytest.raises(TypeError): concatenate_representations((reps[0], reps[1])) with pytest.raises(ValueError): concatenate_representations((reps[0], reps[5])) # Check that passing in a single object fails with pytest.raises(TypeError): concatenate_representations(reps[0])
from astropy.time import Time from astropy.coordinates import representation as r from astropy.coordinates.baseframe import (BaseCoordinateFrame, RepresentationMapping, frame_transform_graph, base_doc) from astropy.coordinates.transformations import AffineTransform from astropy.coordinates.attributes import DifferentialAttribute from .baseradec import BaseRADecFrame, doc_components as doc_components_radec from .icrs import ICRS from .galactic import Galactic # For speed J2000 = Time('J2000') v_bary_Schoenrich2010 = r.CartesianDifferential([11.1, 12.24, 7.25] * u.km / u.s) __all__ = ['LSR', 'GalacticLSR'] doc_footer_lsr = """ Other parameters ---------------- v_bary : `~astropy.coordinates.representation.CartesianDifferential` The velocity of the solar system barycenter with respect to the LSR, in Galactic cartesian velocity components. """ @format_doc(base_doc, components=doc_components_radec, footer=doc_footer_lsr) class LSR(BaseRADecFrame): r"""A coordinate or frame in the Local Standard of Rest (LSR).
@classmethod def no_pos(cls, coo, fr): return None, cls.rep0.with_differentials(cls.dif) @classmethod def no_vel(cls, coo, fr): return None, cls.rep @pytest.mark.parametrize('transfunc', [transfunc.both, transfunc.no_matrix, transfunc.no_pos, transfunc.no_vel, transfunc.just_matrix]) @pytest.mark.parametrize('rep', [ r.CartesianRepresentation(5, 6, 7, unit=u.pc), r.CartesianRepresentation(5, 6, 7, unit=u.pc, differentials=r.CartesianDifferential(8, 9, 10, unit=u.pc/u.Myr)), r.CartesianRepresentation(5, 6, 7, unit=u.pc, differentials=r.CartesianDifferential(8, 9, 10, unit=u.pc/u.Myr)) .represent_as(r.CylindricalRepresentation, r.CylindricalDifferential) ]) def test_affine_transform_succeed(transfunc, rep): c = TCoo1(rep) # compute expected output M, offset = transfunc(c, TCoo2) _rep = rep.to_cartesian() diffs = {k: diff.represent_as(r.CartesianDifferential, rep) for k, diff in rep.differentials.items()} expected_rep = _rep.with_differentials(diffs)