Skip to content

Commit 2280a54

Browse files
committed
Improve Syndyne(s) Synchrone(s)
to_ephem: * Remove coords column from to_ephem due to problem vstacking SkyCoords columns when frame contains obstime * Use StateBase's to_ephem for most of the work. plot() * Fix cosine correction * Allow spherical coords other than RA/Dec Fix SourceOrbit.epoch SynCollection: * __getitem__ should return SynCollections for tuples and slices * Use Ephem's vstack in to_ephem
1 parent 7b31bba commit 2280a54

1 file changed

Lines changed: 44 additions & 52 deletions

File tree

sbpy/dynamics/syndynes.py

Lines changed: 44 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import astropy.units as u
3636
from astropy.wcs import WCS
3737
from astropy.time import Time
38-
from astropy.table import vstack
3938
from astropy.coordinates import SkyCoord
4039

4140
from ..data import Ephem
@@ -107,11 +106,14 @@ def to_ephem(self) -> Ephem:
107106
t, as `Quantity` t_relative
108107
:math:`|r|` r
109108
:math:`|v \cdot \hat{r}|` rdot
110-
coords coords
111109
coords.ra ra
112110
coords.dec dec
111+
coords.pm_ra_cosdec ra*cos(dec)_rate
112+
coords.pm_dec dec_rate
113113
coords.lon lon
114114
coords.lat lat
115+
coords.pm_lon_coslat lon*cos(lat)_rate
116+
coords.pm_lat lat_rate
115117
coords.distance delta
116118
coords.radial_velocity deltadot
117119
x x
@@ -131,59 +133,36 @@ def to_ephem(self) -> Ephem:
131133
132134
"""
133135

134-
data: dict = {}
135-
data["beta_rad"] = self.betas
136-
data["age"] = self.ages
136+
eph = super().to_ephem(observer=self.observer)
137137

138-
if isinstance(self.t, Time):
139-
data["date"] = self.t
140-
else:
141-
data["t_relative"] = self.t
142-
143-
data["r"] = abs(self)[0]
144-
data["rdot"] = np.sum(self.r * self.v, 1) / np.sqrt(np.sum(self.r * self.r, 1))
145-
146-
if self.observer is not None:
147-
for k, v in self.coords.representation_component_names.items():
148-
if v in ("lon", "lat"):
149-
data[k] = getattr(self.coords, k)
150-
elif v == "distance":
151-
data["delta"] = getattr(self.coords, k)
152-
data["deltadot"] = self.coords.radial_velocity
153-
data["coords"] = self.coords
154-
155-
data["x"] = self.x
156-
data["y"] = self.y
157-
data["z"] = self.z
158-
data["vx"] = self.v_x
159-
data["vy"] = self.v_y
160-
data["vz"] = self.v_z
161-
data["x initial"] = self.initial.x
162-
data["y initial"] = self.initial.y
163-
data["z initial"] = self.initial.z
164-
data["vx initial"] = self.initial.v_x
165-
data["vy initial"] = self.initial.v_y
166-
data["vz initial"] = self.initial.v_z
167-
data["t initial"] = self.initial.t
168-
169-
meta: dict = {}
170-
meta["source"] = {
138+
eph["beta_rad"] = self.betas
139+
eph["age"] = self.ages
140+
141+
eph["x initial"] = self.initial.x
142+
eph["y initial"] = self.initial.y
143+
eph["z initial"] = self.initial.z
144+
eph["vx initial"] = self.initial.v_x
145+
eph["vy initial"] = self.initial.v_y
146+
eph["vz initial"] = self.initial.v_z
147+
eph["t initial"] = self.initial.t
148+
149+
eph.meta["source"] = {
171150
"r": self.source.r,
172151
"v": self.source.v,
173152
"t": self.source.t,
174153
"frame": self.source.frame,
175154
}
176155
if self.observer is None:
177-
meta["observer"] = None
156+
eph.meta["observer"] = None
178157
else:
179-
meta["observer"] = {
158+
eph.meta["observer"] = {
180159
"r": self.observer.r,
181160
"v": self.observer.v,
182161
"t": self.observer.t,
183162
"frame": self.observer.frame,
184163
}
185164

186-
return Ephem.from_dict(data, meta=meta)
165+
return eph
187166

188167
@requires("matplotlib")
189168
def plot(
@@ -224,10 +203,17 @@ def plot(
224203

225204
coords0 = self.observer.observe(self.source)
226205

227-
dRA = self.coords.ra - coords0.ra
228-
dDec = self.coords.dec - coords0.dec
229-
x = dRA.to(unit) / np.cos(self.coords.dec)
230-
y = dDec.to(unit)
206+
# lon could be coords.ra or coords.lon
207+
# lat could be coords.dec or coords.lat
208+
for name, component in coords0.get_representation_component_names().items():
209+
if component == "lon":
210+
dlon = getattr(self.coords, name) - getattr(coords0, name)
211+
elif component == "lat":
212+
lat0 = getattr(coords0, name)
213+
dlat = getattr(self.coords, name) - lat0
214+
215+
x = dlon.to(unit) * np.cos(lat0)
216+
y = dlat.to(unit)
231217
else:
232218
# convert coordinates to plot units with the WCS object (avoid
233219
# passing a masked object, or wcs will complain)
@@ -386,7 +372,7 @@ def dt(self) -> u.Quantity:
386372
@property
387373
def epoch(self) -> Time:
388374
"""Epoch of each orbit point."""
389-
return self.source.t - self.ages[0]
375+
return self.source.t + self.dt
390376

391377

392378
class SynCollection:
@@ -426,9 +412,12 @@ def __len__(self) -> int:
426412
return len(self._data)
427413

428414
def __getitem__(self, k: int | tuple | slice) -> SynStates | SynCollectionType:
429-
# return a SynStates object
430415
if isinstance(k, int):
416+
# return a SynStates object
431417
return self._data[k]
418+
elif isinstance(k, tuple):
419+
# return a SynCollection
420+
return type(self)([self._data[i] for i in k])
432421

433422
# return a SynCollection
434423
return type(self)(self._data[k])
@@ -443,12 +432,15 @@ def to_ephem(self) -> Ephem:
443432
if len(self) == 0:
444433
return Ephem()
445434

446-
tables: list[Ephem] = [s.to_ephem().table for s in self]
435+
result = self[0].to_ephem()
436+
for syn in self[1:]:
437+
# remove metadata or else it will be appended to the tables[0]'s
438+
# metadata
439+
eph = syn.to_ephem()
440+
eph.table.meta = {}
441+
result.vstack(eph)
447442

448-
return Ephem.from_table(
449-
vstack(tables, metadata_conflicts="error"),
450-
meta=tables[0].meta,
451-
)
443+
return result
452444

453445
@requires("matplotlib")
454446
def plot(

0 commit comments

Comments
 (0)