Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

iterating over time with DateTime to obtain values with Astro::Coords

by Aldebaran (Curate)
on Oct 13, 2021 at 00:53 UTC ( [id://11137457]=perlquestion: print w/replies, xml ) Need Help??

Aldebaran has asked for the wisdom of the Perl Monks concerning the following question:

Been a while since I have posted as OP with the Perlpocalypse and all. I took a tour "out there" to see what else was going on. I worked a bit with python, but, as a guy who started comp sci in the punchcard era, I can't look at fixed form source and call it "progress." (Do they have pythontidy like we have perltidy?)

I also took a gander at Usenet. It was nice to see some old names, but it has the same cooties of spammers and pornographers that mutate faster than one's killfile. comp.unix.programmer was still viable, as well as comp.lang.fortran, but I couldn't figure out the proprietary client the provider wanted me to use, so that fizzled out. (That's a nice way of saying I got locked out of my own account with failed attempts.)

I've had several scripts that I've been fiddling with in the meantime. This one came up in the context of Moon phase on historical events. I present attempts to iterate over the closed interval of a lunar cycle within the methodology of DateTime. It's not complete, but I've got output I don't understand, so I want to put it up for review. Let me just get source out there first:

#!/usr/bin/perl use v5.030; use warnings; use Astro::Coords; use Astro::MoonPhase; use DateTime; use DateTime::Format::ISO8601; use Log::Log4perl; my $file = '/home/hogan/Documents/hogan/logs/3.log4perl.txt'; unlink $file or warn "Could not unlink $file: $!"; my $log_conf4 = "/home/hogan/Documents/hogan/logs/conf_files/3.conf"; Log::Log4perl::init($log_conf4); #info my $logger = Log::Log4perl->get_logger(); ## time program my $now = DateTime->now( time_zone => 'UTC' ); $logger->info("$0 executed at $now"); # or, create a DateTime object from an ISO timestring my $isostr = '2021-10-09T11:13:57'; # jd 2459496.96802 my $dt = DateTime::Format::ISO8601->parse_datetime($isostr); my @phases = phasehunt($dt); $logger->info("@phases"); my $start_epoch = $phases[0]; my $end_epoch = $phases[4]; my $diff = $end_epoch - $start_epoch; my $hard_bottom = int($start_epoch); $logger->info("integer bottom is $hard_bottom"); $logger->info( "lunation is " . $diff / ( 24 * 60 * 60 ) . " days" ); $logger->info( "degrees covered per day is " . 360 / ( $diff / ( 24 * 60 * 60 ) ) . " degrees" ); ## end prelims for moonphase ## prelims for planets my $traveler1 = Astro::Coords->new( planet => 'Moon' ); my $traveler2 = Astro::Coords->new( planet => 'Venus' ); my $traveler3 = Astro::Coords->new( planet => 'Jupiter' ); my $moon_ra = 4.15; # values make initial while condition true my $venus_ra = 4.2; # values make initial while condition true my $jup_ra = 7; # values make initial while condition true while ( $moon_ra < $venus_ra ) { ## moon $traveler1->datetime($dt); $moon_ra = $traveler1->ra( format => q/deg/ ); ## venus $traveler2->datetime($dt); $venus_ra = $traveler2->ra( format => q/deg/ ); my $random = rand(); if ( $random > .99 ) { $logger->info("dt is $dt"); $logger->info("Moon ra is $moon_ra"); $logger->info("venus ra is $venus_ra"); } ## add a second to what $dt currently holds $dt->add( seconds => 1 ); } my $et = $dt->clone->subtract( seconds => 1 ); my $et_julian = $et->jd; $logger->info("dt is $dt"); $logger->info("et is $et"); $logger->info("Moon ra is $moon_ra"); $logger->info("venus ra is $venus_ra"); $logger->info("Julian equality is $et_julian"); my $later = DateTime->now( time_zone => 'UTC' ); my $seconds_dur = $later->subtract_datetime_absolute($now); $logger->info("Program duration is $seconds_dur seconds"); __END__

Typical abridged output:

2021/10/12 17:44:15 INFO ./2.vj.pl executed at 2021-10-12T23:44:15 2021/10/12 17:44:15 INFO -1952337.6024127 -1378241.1266014 -714314.659 +416676 -4036.13566160202 592540.73432833 2021/10/12 17:44:15 INFO integer bottom is -1952337 2021/10/12 17:44:15 INFO lunation is 29.4546103789471 days 2021/10/12 17:44:15 INFO degrees covered per day is 12.222195281772 de +grees 2021/10/12 17:44:15 INFO dt is 2021-10-09T11:20:59 2021/10/12 17:44:15 INFO Moon ra is 235.845969901601 2021/10/12 17:44:15 INFO venus ra is 239.201830385495 2021/10/12 17:44:16 INFO dt is 2021-10-09T11:23:42 2021/10/12 17:44:16 INFO Moon ra is 235.865530833331 2021/10/12 17:44:16 INFO venus ra is 239.203970696164 ... 2021/10/12 17:45:02 INFO venus ra is 239.628594527327 2021/10/12 17:45:02 INFO dt is 2021-10-09T20:25:16 2021/10/12 17:45:02 INFO Moon ra is 239.625074172142 2021/10/12 17:45:02 INFO venus ra is 239.629628154514 2021/10/12 17:45:02 INFO dt is 2021-10-09T20:25:47 2021/10/12 17:45:02 INFO et is 2021-10-09T20:25:46 2021/10/12 17:45:02 INFO Moon ra is 239.630096069291 2021/10/12 17:45:02 INFO venus ra is 239.630025731277 2021/10/12 17:45:02 INFO Julian equality is 2459497.35122685 2021/10/12 17:45:02 INFO Program duration is DateTime::Duration=HASH(0 +x5642bb935d40) seconds

$et is to be the second at which the moon and venus conjoin, ie, have the same right ascension. The problem is that I check the data with John Walker's Fourmilab ephemeris and use the option for univeral time. The time defined in perl thus:

my $isostr = '2021-10-09T11:13:57';

is inputed without the T, and with the radio button activated, thus:

2021-10-09 11:13:57

But that's not our value to check, which should be $et, namely:

2021-10-09 20:25:46

It would seem that the moon is well past Venus by the margin of almost 2 hours. I tried to spitball if it might be using a different idea of coincidence with non-point masses. The full moon is about a half a degree. It's certainly not half full, and the dark edge hits venus first. In the prelims, I calculated that angle the moon moves through in a day to be 12.2 degrees. A quarter of a degree takes the moon about a half hour. Our answer seems to be at least 3 times out of this range as fourmilab has the conjunction between this interval, I:

2021-10-09 18:30:00

And this time:

2021-10-09 18:40:00

Q1) Do these bodies conjoin at $et or in the interval I? How does perl represent the moon in Astro::Coords? (For example, is the right ascension that of the center?}

I didn't expect $phases[0] to be negative. Given that it was defined by

my @phases = phasehunt($dt);

Q2) How do I take $dt and $phases[0] and get epoch time?

Q3) How do I get the duration of the program run to display correctly? I thought I followed Dave Rolsky's example.

I wanted to be able to calculate the duration of the transit of the moon from venus to jupiter before it happened.

Thanks for comments,

Replies are listed 'Best First'.
Re: &Astro::MoonPhase::phasehunt argument - number of second since 19700101
by parv (Parson) on Oct 13, 2021 at 08:20 UTC

    You should have mentioned "phasehunt" function is from "Astro::MoonPhase" module explicitly for anyone casually following the questions. I found it on a first guess.

    phasehunt() is documented to accept ...

    ... the time, expressed as a time returned by the time function. If $seconds_since_1970 is omitted, it does phasehunt(time).

    ... does not list argument of DateTime object. So get the epoch from it to pass to &phasehunt. Can't say if that would actually solve any of your issues.

    Updated much later. Adjusted code in case anybody else care to run the original logic|algorithm without Log::Log4perl or its configuration not supplied in OP ...

Re: iterating over time with DateTime to obtain values with Astro::Coords
by karlgoethebier (Abbot) on Oct 13, 2021 at 20:38 UTC

    Disclaimer: I’m not an expert in spherical astronomy. But I wonder why you don‘t do such stuff with some funny astronomy software. Example: ♀ transit today 16:12:20 RA 16h 17.0m Dek. -24° 21'. Same procedure for ☾ and ♃.

    I used Sky Safari Pro for these simple things.

    I guess that you might prefer Stellarium as it can be scripted.

    Best regards, Karl

    Update: See also. But I guess you know this already. And I hope the math mentioned ibidem is O.K. 🤪😎

    «The Crux of the Biscuit is the Apostrophe»

Re: Display of DateTime::Duration object in human readable string
by parv (Parson) on Oct 13, 2021 at 07:07 UTC

    Get the duration in units of months, days, minutes, seconds from DateTime::Duration object; then convert (to other units or to a string) as you please. See the pod of the module for caveats.

    (update) As you are calling subtract_datetime_absolute, you only need to get second (and nanosecond if you care) from the *::Duration object.

    I personally did not care for any of the caveats about a day not being strictly 24 hour, etc. when I wanted to estimate finish time of transfer of ~40 TB of data. So, I did ...

    # Conversion to day unit. my ( $day, $min, $sec ) = map { $duration->in_units( $_ ) } qw[ days m +inutes seconds ]; $day_duration = $day + ( $min/60 + $sec/3600 ) /24;
      (update) As you are calling subtract_datetime_absolute, you only need to get second (and nanosecond if you care) from the *::Duration object.

      My script is far from polished, but I wanted to get it out there before this thing goes down.

      Again one faces questions of validity. A typical value for the conjunction of the moon and jupiter is

      2021-10-15T09:26:57

      At Fourmilab's site , this happens 34-39 minutes later, between:

      2021-10-15 10:00:00

      , and:

      2021-10-15 10:05:00

      I tried to work it up in python, but it could not find the ephem module after I had snapd it in, so I don't know how to check it other than waiting for the values in Stellarium. (Thx karlgoethebier)

      Q1) Have we agreed that I'm gonna end up with seconds from DateTime::Duration*, and I might as well roll my own days, hours, minutes, seconds from that? I don't think DateTime can do it because of the vagaries of losing a second in the 70's, for example. (?)

      I will be traveling under this moon tomorrow, and I love to watch it from different perspectives as I cross mountian ranges. It rose and set a couple times relative to me the last time I drove this stretch, like a yoyo....

      Happy skywatching!

        I do not know enough, or care enough to find out currently, about the predicted motions of Moon & Venus. My interest in this thread is due to issues of and with DateTime*.

        Q1) Have we agreed that I'm gonna end up with seconds from DateTime::Duration*, and I might as well roll my own days, hours, minutes, seconds from that?

        Looks so: I suggested to convert human readable string based on *::Duration documentation; you seem to want to do so.

Re: iterating over time with DateTime to obtain values with Astro::Coords
by parv (Parson) on Oct 14, 2021 at 08:01 UTC
    Q2) How do I take $dt and $phases[0] and get epoch time?

    Could you explain what do you mean by "get epoch time" (as &Astro::MoonPhase::phasehunt already returns a list of 5 epochs for 5 phases)?

      Could you explain what do you mean by "get epoch time"

      This is what I meant.

      # create a DateTime object from an ISO timestring my $isostr = '2021-10-09T11:13:57'; # jd 2459496.96802 my $dt = DateTime::Format::ISO8601->parse_datetime($isostr); my @phases = phasehunt($dt->epoch); $logger->info("@phases"); my $start_epoch = $phases[0]; my $end_epoch = $phases[4]; my $diff = $end_epoch - $start_epoch; my $hard_bottom = int($start_epoch); $logger->info("integer bottom is $hard_bottom");

      Output:

      2021/10/14 13:49:52 INFO 1633518344.15928 1634095655.87543 1634741861. +07993 1635451604.37235 1636060526.50686 2021/10/14 13:49:52 INFO integer bottom is 1633518344

      Anything numerical happens over an interval, and paying special attention to the bounds has a profound bearing on whether results are valid. I like to bound an interval with lub and glb integers to check results with familiar tools.

      Thanks for your comments, I'm trying to get this written before before the interval has elapsed....

Re: iterating over time with DateTime to obtain values with Astro::Coords
by perlfan (Vicar) on Oct 13, 2021 at 20:17 UTC
    I rarely need to go beyond strftime and it's friend, POSIX::strptime to meeting my D/T needs. Time::Piece (which implements it's own strftime and strptime) also seems nice, though I've been warned it has edge cases - not sure what they are, so idk if that's true or not.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11137457]
Approved by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (2)
As of 2024-04-24 23:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found