skyfielders / python-skyfield

Elegant astronomy for Python
MIT License
1.38k stars 208 forks source link

Geocentric ecliptic longitude "object" #883

Closed hgrecco closed 11 months ago

hgrecco commented 11 months ago

Is there a simple way to find out at which time a certain geocentric ecliptic longitude transits the meridian at a given location?

brandon-rhodes commented 11 months ago

Trying to imagine the geometry in my head: wouldn't a given geocentric ecliptic longitude spend 12 hours of each day touching the meridian at a given location? Maybe a quick diagram would help me understand the circumstance you're wanting to catch.

hgrecco commented 11 months ago

Take a look at the following screenshots from Stellarium in which I have sequentially selected 3 objects.

imagen imagen imagen

Each has a different ecliptic longitude (but none of them is on transit through the meridian at this point in time). It is rather easy with skyfield to find at which time any of them will transit the meridian. I would like to do the same for an arbitrary ecliptic longitude.

brandon-rhodes commented 11 months ago

Can Stellarium show an ecliptic grid instead of the RA-dec grid that your screenshots display? If you could display one of the above images but with an ecliptic lat-lon grid instead — or better yet, have both lat-lon and RA-dec showing at once — then I think we'll be able to talk better about the geometry. Thanks!

hgrecco commented 11 months ago

I am not an expert in stellarium but there is an ecliptic grid (red) and an azimuthal grid (green).

imagen
brandon-rhodes commented 11 months ago

Excellent, thank you! With that image, we can now return to the question:

at which time a certain geocentric ecliptic longitude transits the meridian

Let's look at the longitude of the Northern i-Aquariids, which looks to be right around +345° ecliptic longitude, if I'm reading the diagram correctly. So we can make your question more specific for this case:

"at what time does the geocentric ecliptic longitude +345° transit the meridian?"

Taking the meridian as the line that goes straight up from the letter "N", it looks to me like as of the very moment of this diagram, the ecliptic longitude +345° is on the meridian, because the two lines intersect. But they haven't suddenly intersected; it looks like they've been touching for maybe a few hours already, and will be touching for several more. You'll have to adjust the time in Stellarium to learn at which moment the +345° line starts touching the meridian, and to find the time — which I'm guessing is 12h later — when they stop touching. But, do you agree that the two lines don't have merely a single moment of contact, but that the "transit" during which the two lines are touching will last at least for many hours? Try letting time flow forward and back in Stellarium and you can probably animate the period of time during which they touch.

hgrecco commented 11 months ago

True, you would need to specify an extra value (e.g. ecliptic latitud 0 to track the ecliptic, or when that particular longitude passes through a particular altitude).

brandon-rhodes commented 11 months ago

True, you would need to specify an extra value (e.g. ecliptic latitud 0 to track the ecliptic, or when that particular longitude passes through a particular altitude).

If you have a coordinate specified by an ecliptic latitude-longitude, you'll want to read about ecliptic coordinates:

https://rhodesmill.org/skyfield/coordinates.html#ecliptic-coordinates

and then jump down to the section on how to enter coordinates and get a position back:

https://rhodesmill.org/skyfield/coordinates.html#turning-coordinates-into-a-position

It mentions ecliptic coordinates at the end. Let me know if the examples give you enough information — if they don't help you get all the pieces put together, then maybe I'll need to do some more writing, like maybe expanding each section so that not only does the Ecliptic section show you how to print coordinates, but how to build a new position if given fresh coordinates.

hgrecco commented 11 months ago

I was hoping something along the lines of

obj = Ecliptic(lat, lon)

and then just reuse your code

zone = timezone('US/Eastern')
now = zone.localize(dt.datetime.now())
midnight = now.replace(hour=0, minute=0, second=0, microsecond=0)
next_midnight = midnight + dt.timedelta(days=1)

ts = load.timescale()
t0 = ts.from_datetime(midnight)
t1 = ts.from_datetime(next_midnight)
eph = load('de421.bsp')
bluffton = wgs84.latlon(40.8939 * N, 83.8917 * W)

f = almanac.meridian_transits(eph, obj, bluffton)
times, events = almanac.find_discrete(t0, t1, f)

but maybe is too specific. Thanks for your time, I think I can put it together from there.

brandon-rhodes commented 11 months ago

I was hoping something along the lines of obj = Ecliptic(lat, lon)

That's an interesting suggestion — instead of having to give the position class an ecliptic lat, lon, and a time, so that a position can be created, the user would first create an intermediate kind of object that's a lat/lon pair but without a time. Then presumably that lat+lon+frame object could be asked "where are you pointing at time t?" and return a position object.

I suppose Skyfield already has at least one example of something like that: a Star object is an RA and a dec that are referenced to either the ICRS frame or to an equinox-of-date frame. Then its .at(t) method returns a position object by combining those coordinates with a time.

Oh, and, I guess a GeographicPosition takes a lat/lon referenced to WGS84, and its .at(t) returns a position.

In each case the class also does other interesting things specific to those kinds of object, but at their core they store an intermediate coordinate pair that need a time t to be turned into a position.

But for other frames, so far the design of Skyfield has avoided the complexity of having to define a separate coordinate class for every single one — so there's no classes Ecliptic, Ecliptic2000, Galactic, or B1950. Instead, the caller has to bring together the frame, the coordinates, and the time t all at once and hand them to the position method .from_time_and_frame_latlon()

— oh, wait —

— there's no such method. I forgot. There's .from_time_and_frame_vectors() that accepts x,y,z but — and, yes, this is what the Coordinates docs say but I'm just now re-reading them myself — you have to make the x,y,z yourself from Ecliptic latitude and longitude. Which is a bit inconvenient, isn't it?

Hmm.

So there are at least three ways we could make this more obvious.

  1. Give Skyfield lots of new coordinate classes, one for each kind of frame.
  2. Give Skyfield something like a Coordinate class which puts together a frame and latitude and longitude and distance and would have an .at(t) method.
  3. Add a method like .from_time_and_frame_latlon() that would do the angle transform on the user's behalf.

Given that Skyfield has always handled coordinates ‘lightly’ — considering them simple numbers, and not objects — I think that option 3 might make the most sense. Since calls like .altaz() simply return two angles and a distance, not a big Coordinate object with .alt and .az attributes, it would be a bit incongruous to submit coordinates using a big object, when that's now how they get delivered back.

Hmm.

Except — actually, it would be possible for (running with the above example) .altaz() to actually return a Coordinate object, so long as that object correctly unpacked itself into three coordinates alt, az, distance when iterated over. It would in fact, I think, be invisible to all existing Skyfield code that coordinate triples were now objects of their own. But it would create symmetry with the case you're asking for: Coordinate objects could be used to create positions, and position objects would return Coordinate objects everywhere they currently return simple tuples of skyfield.units objects.

Hmm.

My goal has always been to keep Skyfield sleek, fast, and easy to reason about. My guess is that a new Coordinate class, with all the mechanics it would involve, would not be worth the trouble, if instead we add a method to better support things like “create a position from an ecliptic latitude and longitude.” But let me think through the idea this week; maybe I should read through Skyfield's code, asking whether a Coordinate class would make its own code simpler anywhere.

We can close this issue when I either decide to add a Coordinate for you, or instead implement a .from_time_and_frame_latlon() method. Feel free to weigh in with any thoughts of your own! As you can tell from my long rambling reply, the questions of wanting to input things like ecliptic coordinates happens to touch a big design issue.

Another topic: why not write down the RA and dec of your meteor showers, and then use the .from_radec() method?

hgrecco commented 11 months ago

Thanks for sharing your thoughts. While I have look at the Skyfield code, and followed the math behinds it, I am not so familiar with that API as to say what is the best approach. I do have to say that I found the API easy to use and intuitive, and documentation was very helpful for those aspects which are not trivial. The only thing that it took me a little longer was to understand (for this purpose) was which objects "can be observed". i.e. understanding _observe_from_bcrs in ChebyshevPosition and Star.

I am not trying to track these meteor showers but specific points within the ecliptic. I was about to do all the math but then I thought that if there was a way to build them as an "Skyfield Celestial Object" I could reuse everything I (and you) have done; as well as make sure that I am not making a mistake with all corrections.