|
|
| |
Astro::Coord::ECI::Utils(3) |
User Contributed Perl Documentation |
Astro::Coord::ECI::Utils(3) |
Astro::Coord::ECI::Utils - Utility routines for astronomical calculations
use Astro::Coord::ECI::Utils qw{ :all };
my $now = time ();
print "The current Julian day is ", julianday ($now);
This module was written to provide a home for all the constants and utility
subroutines used by Astro::Coord::ECI and its descendants. What ended
up here was anything that was essentially a subroutine, not a method.
Because figuring out how to convert to and from Perl time bids
fair to become complicated, this module is also responsible for figuring out
how that is done, and exporting whatever is needful to export. See
":time" below for the gory details.
This package exports nothing by default. But all the constants,
variables, and subroutines documented below are exportable, and the
following export tags may be used:
- :all
- This imports everything exportable into your name space.
- :greg_time
- This imports all time routines except the discouraged routines
"time_gm()" and
"time_local()".
- :mainstream
- This imports everything not deprecated into your name space.
- :params
- This imports the parameter validation routines
"__classisa" and
"__instance".
- :ref
- This imports all the *_REF constants.
- :time
- This imports the time routines into your name space. If Time::y2038 is
available, it will be loaded, and both this tag and
":all" will import
"gmtime",
"localtime",
"time_gm",
"time_local",
"greg_time_gm", and
"greg_time_local" into your name space.
Otherwise, "Time::Local|Time::Local"
will be loaded, and both this tag and
":all" will import
"time_gm",
"time_local",
"greg_time_gm", and
"greg_time_local" into your name
space.
- :vector
- This imports the vector arithmetic routines. It includes anything whose
name begins with 'vector_'.
Under Perl 5.6 you may find that, if you use any of the above
tags, you need to specify them first in your import list.
AU = number of kilometers in an astronomical unit
JD_OF_EPOCH = the Julian Day of Perl epoch 0
LIGHTYEAR = number of kilometers in a light year
PARSEC = number of kilometers in a parsec
PERL2000 = January 1 2000, 12 noon universal, in Perl time
PI = the circle ratio, computed as atan2 (0, -1)
PIOVER2 = half the circle ratio
SECSPERDAY = the number of seconds in a day
SECS_PER_SIDERIAL_DAY = seconds in a siderial day
SPEED_OF_LIGHT = speed of light in kilometers per second
TWOPI = twice the circle ratio
ARRAY_REF = 'ARRAY'
CODE_REF = 'CODE'
HASH_REF = 'HASH'
SCALAR_REF = 'SCALAR'
$DATETIMEFORMAT
This variable represents the POSIX::strftime format used to
convert times to strings. The default value is '%a
%b %d
%Y %H:%M:%S' to be
consistent with the behavior of gmtime (or, to be precise, the behavior of
ctime as documented on my system).
$JD_GREGORIAN
This variable represents the Julian Day of the switch from Julian
to Gregorian calendars. This is used by date2jd(), jd2date(),
and the routines which depend on them, for deciding whether the date is to
be interpreted as in the Julian or Gregorian calendar. Its initial setting
is 2299160.5, which represents midnight October 15 1582 in the Gregorian
calendar, which is the date that calendar was first adopted. This is
slightly different than the value of 2299161 (noon of the same day) used by
Jean Meeus.
If you are interested in historical calculations, you may wish to
reset this appropriately. If you use date2jd to calculate the new value, be
aware of the effect the current setting of
$JD_GREGORIAN has on the interpretation of the date
you give.
- $angle = acos ($value)
- This subroutine calculates the arc in radians whose cosine is the given
value.
- $mag = add_magnitudes( $mag1, $mag2, ... );
- This subroutine computes the total magnitude of a list of individual
magnitudes. The algorithm comes from Jean Meeus' "Astronomical
Algorithms", Second Edition, Chapter 56, Page 393.
- $angle = asin ($value)
- This subroutine calculates the arc in radians whose sine is the given
value.
- $magnitude = atmospheric_extinction ($elevation, $height);
- This subroutine calculates the typical atmospheric extinction in
magnitudes at the given elevation above the horizon in radians and the
given height above sea level in kilometers.
The algorithm comes from Daniel W. E. Green's article
"Magnitude Corrections for Atmospheric Extinction", which was
published in the July 1992 issue of "International Comet
Quarterly", and is available online at
<http://www.icq.eps.harvard.edu/ICQExtinct.html>. The text of this
article makes it clear that the actual value of the atmospheric
extinction can vary greatly from the typical values given even in the
absence of cloud cover.
- $jd = date2jd ($sec, $min, $hr, $day, $mon, $yr)
- This subroutine converts the given date to the corresponding Julian day.
The inputs are a Perl date and time; $mon is in
the range 0 - 11, and $yr is from 1900, with
earlier years being negative. The year 1 BC is represented as -1900.
If less than 6 arguments are provided, zeroes will be
prepended to the argument list as needed.
The date is presumed to be in the Gregorian calendar. If the
resultant Julian Day is before $JD_GREGORIAN,
the date is reinterpreted as being from the Julian calendar.
The only validation is that the month be between 0 and 11
inclusive, and that the year be not less than -6612 (4713 BC).
Fractional days are accepted.
The algorithm is from Jean Meeus' "Astronomical
Algorithms", second edition, chapter 7 ("Julian Day"),
pages 60ff, but the month is zero-based, not 1-based, and years are
1900-based.
- $epoch = date2epoch ($sec, $min, $hr, $day, $mon, $yr)
- This is a convenience routine that converts the given date to seconds
since the epoch, going through date2jd() to do so. The arguments
are the same as those of date2jd().
If less than 6 arguments are provided, zeroes will be
prepended to the argument list as needed.
The functionality is the same as Time::Local::timegm,
but this function lacks timegm's limited date range under Perls before
5.12.0. If you have Perl 5.12.0 or better, the core Time::Local
"timegm()" will probably do what you
want. If you have an earlier Perl, Time::y2038
"timegm()" may do what you want.
- $time = decode_space_track_json_time( $string )
- This subroutine decodes a time in the format Space Track uses in their
JSON code. This is ISO-8601-ish, but with a possible fractional part and
no zone.
- $rad = deg2rad ($degr)
- This subroutine converts degrees to radians. If the argument is
"undef",
"undef" will be returned.
- $value = distsq (\@coord1, \@coord2)
- This subroutine calculates the square of the distance between the two sets
of Cartesian coordinates. We do not take the square root here because of
cases (e.g. the law of cosines) where we would just have to square the
result again.
Notice that the subroutine does not assume
three-dimensional coordinates. If @coord1 and
@coord2 have six entries, you will get a
six-dimensional distance.
- $seconds = dynamical_delta ($time);
- This method returns the difference between dynamical and universal time at
the given universal time. That is,
$dynamical = $time + dynamical_delta ($time)
if $time is universal time.
The algorithm is from Jean Meeus' "Astronomical
Algorithms", 2nd Edition, Chapter 10, page 78. Meeus notes that
this is actually an observed quantity, and the algorithm is an
approximation.
- $boolean = embodies ($thingy, $class)
- This subroutine represents a safe way to call the 'represents' method on
$thingy. You get back true if and only if
$thingy->can('represents') does not throw an
exception and returns true, and
$thingy->represents($class) returns true.
Otherwise it returns false. Any exception is trapped and dismissed.
This subroutine is called 'embodies' because it was too
confusing to call it 'represents', both for the author and for the Perl
interpreter.
- ($sec, $min, $hr, $day, $mon, $yr, $wday, $yday, 0) = epoch2datetime
($epoch)
- This convenience subroutine converts the given time in seconds from the
system epoch to the corresponding date and time. It is implemented in
terms of jd2date (), with the year and month returned from that
subroutine. The day is a whole number, with the fractional part converted
to hours, minutes, and seconds. The $wday is the
day of the week, with Sunday being 0. The $yday is
the day of the year, with January 1 being 0. The trailing 0 is the summer
time (or daylight saving time) indicator which is always 0 to be
consistent with gmtime.
If called in scalar context, it returns the date formatted by
POSIX::strftime, using the format string in
$DATETIMEFORMAT.
The functionality is the same as the core
"gmtime()", but this function lacks
gmtime's limited date range under Perls before 5.12.0. If you have Perl
5.12.0 or better, the core "gmtime()"
will probably do what you want. If you have an earlier Perl, Time::y2038
"gmtime()" may do what you want.
The input must convert to a non-negative Julian date. The
exact lower limit depends on the system, but is computed by
-(JD_OF_EPOCH * 86400). For Unix systems with an epoch of January 1
1970, this is -210866760000.
Additional algorithms for day of week and day of year come
from Jean Meeus' "Astronomical Algorithms", 2nd Edition,
Chapter 7 (Julian Day), page 65.
- $time = find_first_true ($start, $end, \&test, $limit);
- This function finds the first time between $start
and $end for which test ($time) is true. The
resolution is $limit, which defaults to 1 if not
specified. If the times are reversed (i.e. the start time is after the end
time) the time returned is the last time test ($time) is true.
The "test()" function is
called with the Perl time as its only argument. It is assumed to be
false for the first part of the interval, and true for the rest. If this
assumption is violated, the result of this subroutine should be
considered meaningless.
The calculation is done by, essentially, a binary search; the
interval is repeatedly split, the function is evaluated at the midpoint,
and a new interval selected based on whether the result is true or
false.
Actually, nothing in this function says the independent
variable has to be time.
- $folded = fold_case( $text );
- This function folds the case of its input, kinda sorta. It maps to
"CORE::fc" if that is available,
otherwise it maps to "CORE::lc".
- $fmtd = format_space_track_json_time( time() )
- This function takes as input a Perl time, and returns that time in a
format consistent with the Space Track JSON data. This is ISO-8601-ish, in
Universal time, but without the zone indicated.
- $epoch = greg_time_gm( $sec, $min, $hr, $day, $mon, $yr );
- This exportable subroutine is a wrapper for either
"Time::y2038::timegm()" (if that module
is installed),
"Time::Local::timegm_modern()" (if that
is available), or
"Time::Local::timegm()" (if not.)
This subroutine interprets years as Gregorian years.
The difference between this and
"time_gm()" is that
"time_gm()" interprets the year the
way "Time::Local::timegm()" does. For
that reason, this subroutine is preferred over
c<time_gm()>.
This wrapper is needed because the routines have subtly
different signatures. Time::y2038
"timegm()" interprets years strictly
as Perl years. Time::Local
"timegm_modern()" interprets them
strictly as Gregorian years. Time::Local
"timegm()" interprets them differently
depending on the value of the year. Years greater than or equal to 1000
are Gregorian years, but all others are Perl years, except for the range
0 to 99 inclusive, which are within 50 years of the current year.
If you are doing historical calculations, see Historical
Calculations in the Astro::Coord::ECI::Sun documentation for a
discussion of input and output time conversion.
- $epoch = greg_time_local( $sec, $min, $hr, $day, $mon, $yr );
- This exportable subroutine is a wrapper for either
"Time::y2038::timelocal()" (if that
module is installed),
"Time::Local::timelocal_modern()" (if
that is available), or
"Time::Local::timelocal()" (if not.)
This subroutine interprets years as Gregorian years.
The difference between this and c<time_local()>
is that "time_local()" interprets the
year the way
"Time::Local::timelocal()" does. For
that reason, this subroutine is preferred over
c<time_local()>.
This wrapper is needed for the same reason
"greg_time_gm()" is needed.
If you are doing historical calculations, see Historical
Calculations in the Astro::Coord::ECI::Sun documentation for a
discussion of input and output time conversion.
- $difference = intensity_to_magnitude ($ratio)
- This function converts a ratio of light intensities to a difference in
stellar magnitudes. The algorithm comes from Jean Meeus'
"Astronomical Algorithms", Second Edition, Chapter 56, Page 395.
Note that, because of the way magnitudes work (a more negative
number represents a brighter star) you get back a positive result for an
intensity ratio less than 1, and a negative result for an intensity
ratio greater than 1.
- ($day, $mon, $yr, $greg, $leap) = jd2date ($jd)
- This subroutine converts the given Julian day to the corresponding date.
The returns are year - 1900, month (0 to 11), day (which may have a
fractional part), a Gregorian calendar indicator which is true if the date
is in the Gregorian calendar and false if it is in the Julian calendar,
and a leap (or bissextile) year indicator which is true if the year is a
leap year and false otherwise. The year 1 BC is returned as -1900 (i.e. as
year 0), and so on. The date will probably have a fractional part (e.g.
2006 1 1.5 for noon January first 2006).
If the $jd is before
$JD_GREGORIAN, the date will be in the Julian
calendar; otherwise it will be in the Gregorian calendar.
The input may not be less than 0.
The algorithm is from Jean Meeus' "Astronomical
Algorithms", second edition, chapter 7 ("Julian Day"),
pages 63ff, but the month is zero-based, not 1-based, and the year is
1900-based.
- ($sec, $min, $hr, $day, $mon, $yr, $wday, $yday, 0) = jd2datetime
($jd)
- This convenience subroutine converts the given Julian day to the
corresponding date and time. All this really does is converts its argument
to seconds since the system epoch, and pass off to
epoch2datetime().
The input may not be less than 0.
- $century = jcent2000 ($time);
- Several of the algorithms in Jean Meeus' "Astronomical
Algorithms" are expressed in terms of the number of Julian centuries
from epoch J2000.0 (e.g equations 12.1, 22.1). This subroutine
encapsulates that calculation.
- $jd = jday2000 ($time);
- This subroutine converts a Perl date to the number of Julian days (and
fractions thereof) since Julian 2000.0. This quantity is used in a number
of the algorithms in Jean Meeus' "Astronomical Algorithms".
The computation makes use of information from Jean Meeus'
"Astronomical Algorithms", 2nd Edition, Chapter 7, page
62.
- $jd = julianday ($time);
- This subroutine converts a Perl date to a Julian day number.
The computation makes use of information from Jean Meeus'
"Astronomical Algorithms", 2nd Edition, Chapter 7, page
62.
- $ea = keplers_equation( $M, $e, $prec );
- This subroutine solves Kepler's equation for the given mean anomaly
$M in radians, eccentricity
$e and precision $prec in
radians. It returns the eccentric anomaly in radians, to the given
precision.
The $prec argument is optional, and
defaults to the radian equivalent of 0.001 degrees.
The algorithm is Meeus' equation 30.7, with John M. Steele's
amendment for large values for the correction, given on page 205 of
Meeus' book,
This subroutine is not used in the computation of
satellite orbits, since the models have their own implementation.
- $rslt = load_module ($module_name)
- This convenience method loads the named module (using 'require'), throwing
an exception if the load fails. If the load succeeds, it returns the
result of the 'require' built-in, which is required to be true for a
successful load. Results are cached, and subsequent attempts to load the
same module simply give the cached results.
- $boolean = looks_like_number ($string);
- This subroutine returns true if the input looks like a number. It uses
Scalar::Util::looks_like_number if that is available, otherwise it uses
its own code, which is lifted verbatim from Scalar::Util 1.19, which in
turn leans heavily on perlfaq4.
- $maximum = max (...);
- This subroutine returns the maximum of its arguments. If List::Util can be
loaded and 'max' imported, that's what you get. Otherwise you get a pure
Perl implementation.
- $minimum = min (...);
- This subroutine returns the minimum of its arguments. If List::Util can be
loaded and 'min' imported, that's what you get. Otherwise you get a pure
Perl implementation.
- $theta = mod2pi ($theta)
- This subroutine reduces the given angle in radians to the range 0 <=
$theta < TWOPI.
- $radians = omega ($time);
- This subroutine calculates the ecliptic longitude of the ascending node of
the Moon's mean orbit at the given dynamical time.
The algorithm comes from Jean Meeus' "Astronomical
Algorithms", 2nd Edition, Chapter 22, pages 143ff.
- $pa = position_angle( $alpha1, $delta1, $alpha2, $delta2 );
- This low-level subroutine calculates the position angle in right ascension
of the second body with respect to the first, given the first body's right
ascension and declination and the second body's right ascension and
declination in that order, in radians.
The return is the position angle in radians, in the
range "-PI <= $pa < PI".
The algorithm comes from Jean Meeus' "Astronomical
Algorithms", 2nd Edition, page 116, but his algorithm is for the
position angle of the first body with respect to the second (i.e. the
roles of the two bodies are reversed). The order of arguments for this
subroutine is consistent with The IDL Astronomy User's Library at
<https://idlastro.gsfc.nasa.gov/>, function
"posang()".
This is exposed because in principal you could calculate the
position angle in any spherical coordinate system, you would just need
to get the order of arguments right (e.g. azimuth, elevation or
longitude, latitude).
- $degrees = rad2deg ($radians)
- This subroutine converts the given angle in radians to its equivalent in
degrees. If the argument is "undef",
"undef" will be returned.
- $deg_min_sec = rad2dms( $radians, $decimals )
- This subroutine converts the given angle in radians to its equivalent in
degrees, minutes and seconds, represented as a string. Degrees will be
suppressed if zero, and minutes will be suppressed if both degrees and
minutes are zero. If degrees are present the delimiter will be a degree
sign (""\N{DEGREE SIGN}", a.k.a.
"\N{U+00B0}"). The delimiters for
minutes and seconds are "'" and
""" respectively, with the
""" appearing before the decimal
point.
The optional $decimals argument
specifies the number of decimal places in the seconds value, and
defaults to 3.
- $hr_min_sec = rad2hms( $radians, $decimals )
- This subroutine converts the given angle in radians to its equivalent in
hours, minutes and seconds (presumably of right ascension), represented as
a string. Hours will be suppressed if zero, and minutes will be suppressed
if both hours and minutes are zero. The delimiters for hours, minutes, and
seconds are 'h', 'm', and
's' respectively, with the
's' appearing before the decimal point.
The optional $decimals argument
specifies the number of decimal places in the seconds value, and
defaults to 3.
- $value = tan ($angle)
- This subroutine computes the tangent of the given angle in radians.
- $value = theta0 ($time);
- This subroutine returns the Greenwich hour angle of the mean equinox at 0
hours universal on the day whose time is given (i.e. the argument is a
standard Perl time).
- $value = thetag ($time);
- This subroutine returns the Greenwich hour angle of the mean equinox at
the given time.
The algorithm comes from Jean Meeus' "Astronomical
Algorithms", 2nd Edition, equation 12.4, page 88.
- $epoch = time_gm( $sec, $min, $hr, $day, $mon, $yr );
- This exportable subroutine is a wrapper for either
"Time::y2038::timegm()" (if that module
is installed), or
"Time::Local::timegm()" (if not.)
This subroutine interprets years the same way
"Time::Local::timegm()" does.
This wrapper is needed because the routines have subtly
different signatures. Time::y2038
"timegm()" interprets years strictly
as Perl years. Time::Local "timegm()"
interprets years differently depending on the value of the year; greater
than 999 as Gregorian years, but other years are Perl years, except for
the years 0 to 99 inclusive, which are interpreted as within 50 years of
the current year.
This subroutine is discouraged in favor of
"greg_time_gm()", which always
interprets years as Gregorian years.
- $epoch = time_local( $sec, $min, $hr, $day, $mon, $yr );
- This exportable subroutine is a wrapper for either
"Time::y2038::timelocal()" (if that
module is installed), or
"Time::Local::timelocal()" (if not.)
This subroutine interprets years the same way
"Time::Local::timelocal()" does.
This wrapper is needed for the same reason
"time_gm()" is needed.
This subroutine is discouraged in favor of
"greg_time_local()", which always
interprets years as Gregorian years.
- $a = vector_cross_product( $b, $c );
- This subroutine computes and returns the vector cross product of
$b and $c. Vectors are
represented by array references. The cross product is only defined if both
arrays have 3 elements.
- $a = vector_dot_product( $b, $c );
- This subroutine computes and returns the vector dot product of
$b and $c. Vectors are
represented by array references. The dot product is only defined if both
arrays have the same number of elements.
- $m = vector_magnitude( $x );
- This subroutine computes and returns the magnitude of vector
$x. The vector is represented by an array
reference.
- $u = vector_unitize( $x );
- This subroutine computes and returns a unit vector pointing in the same
direction as $x. The vectors are represented by
array references.
- $year = __tle_year_to_Gregorian_year( $year )
- The TLE data contain the year in two-digit form. NORAD decided to deal
with Y2K by decreeing that year numbers lower than 57 (the launch of
Sputnik 1) are converted to Gregorian by adding 2000. Years numbers of 57
or greater are still converted to Gregorian by adding 1900. This
subroutine encapsulates this logic. Years of 100 or greater are returned
unmodified.
This subroutine is private to this package, and can be
changed or revoked without notice.
The author wishes to acknowledge Jean Meeus, whose book "Astronomical
Algorithms" (second edition) published by Willmann-Bell Inc provided
several of the algorithms implemented herein. Willmann-Bell ceased to be a
separate entity in 2021, but their publications, including Dr. Meeus' book,
are still available through Sky and Telescope's Willmann-Bell imprint at
<https://shopatsky.com/collections/willmann-bell>.
Support is by the author. Please file bug reports at
<https://rt.cpan.org/Public/Dist/Display.html?Name=Astro-satpass>,
<https://github.com/trwyant/perl-Astro-Coord-ECI/issues>, or in
electronic mail to the author.
Thomas R. Wyant, III (wyant at cpan dot org)
Copyright (C) 2005-2021 by Thomas R. Wyant, III
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl 5.10.0. For more details, see the
full text of the licenses in the directory LICENSES.
This program is distributed in the hope that it will be useful,
but without any warranty; without even the implied warranty of
merchantability or fitness for a particular purpose.
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc. |