@@ -294,6 +294,103 @@ def to_skycoord(self) -> SkyCoord:
294294 else :
295295 return SkyCoord (self ._data , obstime = self .t , representation_type = "cartesian" )
296296
297+ def to_ephem (self , observer : StateType | None = None ) -> Ephem :
298+ r"""Convert to an sbpy ephemeris object.
299+
300+
301+ Parameters
302+ ----------
303+ observer : `State`, optional
304+ Calculate RA/longitude, Dec/latitude, distance, etc for this
305+ observer.
306+
307+
308+ Returns
309+ -------
310+ eph : Ephem
311+
312+
313+ Notes
314+ -----
315+
316+ Observer state is stored in the `Ephem.meta` attribute. ``coords`` is
317+ calculated for the given observer.
318+
319+ ========================= ====================
320+ Attribute or quantity ``Ephem`` field name
321+ ========================= ====================
322+ t, as `Time` date
323+ t, as `Quantity` t_relative
324+ :math:`|r|` r
325+ :math:`|v \cdot \hat{r}|` rdot
326+ coords.ra ra
327+ coords.dec dec
328+ coords.pm_ra_cosdec ra*cos(dec)_rate
329+ coords.pm_dec dec_rate
330+ coords.lon lon
331+ coords.lat lat
332+ coords.pm_lon_coslat lon*cos(lat)_rate
333+ coords.pm_lat lat_rate
334+ coords.distance delta
335+ coords.radial_velocity deltadot
336+ x x
337+ y y
338+ z z
339+ v_x vx
340+ v_y vy
341+ v_z vz
342+ ========================= ====================
343+
344+ """
345+
346+ data : dict = {}
347+
348+ if isinstance (self .t , Time ):
349+ data ["date" ] = self .t
350+ else :
351+ data ["t_relative" ] = self .t
352+
353+ data ["r" ] = abs (self )[0 ]
354+ data ["rdot" ] = np .sum (self .r * self .v , 1 ) / np .sqrt (np .sum (self .r * self .r , 1 ))
355+
356+ data ["x" ] = self .x
357+ data ["y" ] = self .y
358+ data ["z" ] = self .z
359+ data ["vx" ] = self .v_x
360+ data ["vy" ] = self .v_y
361+ data ["vz" ] = self .v_z
362+
363+ meta = {"frame" : self .frame }
364+
365+ if observer is not None :
366+ meta ["observer" ] = {
367+ "r" : self .observer .r ,
368+ "v" : self .observer .v ,
369+ "t" : self .observer .t ,
370+ "frame" : self .observer .frame ,
371+ }
372+
373+ coords = observer .observe (self )
374+
375+ # use SkyCoords's to_table() method, which will account for when
376+ # RA/Dec vs lon/lat are used.
377+ tab = coords .to_table ()
378+
379+ # convert SkyCoords's column names to Ephem's field names
380+ skycoords_to_ephem = {
381+ "pm_ra_cosdec" : "ra*cos(dec)_rate" ,
382+ "pm_lon_coslat" : "lon*cos(lat)_rate" ,
383+ "pm_dec" : "dec_rate" ,
384+ "pm_lat" : "lat_rate" ,
385+ "distance" : "delta" ,
386+ "radial_velocity" : "deltadot" ,
387+ }
388+ for col in tab .colnames :
389+ field = skycoords_to_ephem .get (col , col )
390+ data [field ] = tab [col ]
391+
392+ return Ephem .from_dict (data , meta = meta )
393+
297394 def transform_to (self , frame : FrameInputTypes ) -> StateBaseType :
298395 """Transform state into another reference frame.
299396
@@ -435,30 +532,6 @@ def from_ephem(
435532 " velocity fields."
436533 )
437534
438- def to_ephem (self ) -> Ephem :
439- """Convert to an ephemeris object.
440-
441-
442- Returns
443- -------
444- eph : `~sbpy.data.ephem.Ephem`
445-
446- """
447-
448- time_field = "dt" if self .arbitrary_time else "date"
449-
450- eph = {
451- time_field : self .t ,
452- "x" : self .x ,
453- "y" : self .y ,
454- "z" : self .z ,
455- "vx" : self .v_x ,
456- "vy" : self .v_y ,
457- "vz" : self .v_z ,
458- }
459-
460- return Ephem .from_dict (eph , meta = {"frame" : self .frame })
461-
462535 def observe (self , target : StateType ) -> SkyCoord :
463536 """Project a target's position onto the sky.
464537
0 commit comments