![]() |
SuperNOVAS v1.3
The NOVAS C library, made better
|
All notable changes to the SuperNOVAS library will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Changes for the upcoming feature release, expected around 1 May 2025. It brings many new convenience functions, such as for handling times and angles as strings; calculating rise, set, transit times; and other common astrometric calculations.
transform_cat()
to update parallax to the recalculated value when precessing or changing epochs. (This was a NOVAS C 3.1 bug.)transform_cat()
had insufficient string length checking of out_id
parameter. Prior to the fix it checked for the longer object name size instead of the catalog name size. However, even if longer than expected input names were left uncaught, only the appropriatre number of characters were used – hence it broke nothing, only failed to remind the caller (with an error) when the supplied name was too long.solarsystem()
/ solarsystem_hp()
provider modules was blocked by solsys-ephem.c
inadvertently definining these functions when BUILTIN_SOLSYS_EPHEM
was set to 1 (default) during the build, even though it was not supposed to.novas_frame_lst()
convenience function to readily return the Local (apparent) Sidereal Time for a given Earth-based observing frame.novas_hms_hours()
and novas_dms_degrees()
convenience functions to make it easier to parse HMS or DMS based time or angle values, returning the result in units of hours or degrees, appropriately for use in SuperNOVAS.novas_rises_above()
and novas_sets_below()
functions to return the date/time a source rises above or sets below a specific elevation on a given date, and novas_transit_time()
to calculate the time a source transits over the local meridian. (For Earth-based observers only). #140: Further fixes to these calculations after the v1.3.0-rc4 release candidate [thanks to valeriy-sokoloff].novas_helio_dist()
function to calculate the heliocentric distance of a Solar-system body on a given date. The novas_solar_power()
function can be used to estimate the incident Solar power on a Solar-system body, while novas_solar_illum()
can be used to calculate the fraction of a spherical body that is illuminated by the Sun seen from the observer location.novas_hpa()
and novas_epa()
functions to calculate the parallactic angle (a.k.a. vertical position angle) for a given location on sky, using the local horizontal coordinates, or else the equatorial position, respectively. The parallactic angle (PA) can be useful to convert local Cartesian offsets (e.g. from a flat image or detector array) between the local horizontal and equatorial orientations, e.g. via the newly added novas_h2e_offset()
or novas_e2h_offset()
functions. The conversion between offsets and absolute coordinates usually requires a WCS projections, such as described in Calabretta & Greisen 2002.novas_sep()
, novas_equ_sep()
, and novas_object_sep()
functions can be used to calculate the precise apparent distance between to spherical or equatorial locations, or between two sources, respectively. novas_sun_angle()
and novas_moon_angle()
can be used to calculate the apparent angular distance of sources from the Sun and Moon, respectively.novas_observable
and novas_track
data structures to provide second order Taylor series expansion of the apparent horizontal or equatorial positions, distances, and redshifts for sources. They can be calculated with the newly added novas_hor_track()
or novas_equ_track()
functions. Such tracking values, including rates and accelerations, can be directly useful for controlling telescope drives in horizontal or equatorial mounts to track sources (hence the name). You can also obtain instantaneous projected (extrapolated) positions from the tracking parameters via novas_track_pos()
at low computational cost.novas_los_to_xyz()
and novas_xyz_to_los()
functions to convert between line-of-sight (δφ, δθ, δr) vectors and rectangular equatorial (δx, δy, δz) vectors.novas_xyz_to_uvw()
function to convert ITRS Earth locations (absolute or differential) to equatorial projections along a line of sight in the direction of a source. Such projections are oft used in interferometry.novas_lsr_to_ssb_vel()
can be used to convert velocity vectors referenced to the LSR to Solar-System Barycentric velocities. And, novas_ssb_to_lsr_vel()
to provide the inverse conversion.benchmark/
folder, for SuperNOVAS as well as equivalent benchmarks for astropy. To run the SuperNOVAS benchmarks, simply make benchmark
in the distribution directory.novas_parse_date()
/ novas_parse_date_format()
to parse date/time specifications, novas_parse_dms()
and novas_parse_hms()
to return hours and degrees for HMS and DMS specifications, as well as the updated parse position.novas_timescale_for_string()
to match timescale constants to string representations, such as "UTC", or "TAI", and novas_print_timescale()
to convert to string representation.novas_iso_timestamp()
to print UTC timestamps in ISO date format with millisecond precision, and novas_timestamp()
to print timestamps in specific timescales.novas_jd_to_date()
, and novas_jd_from_date()
which convert between JD day and calendar dates using the specific type of calendar: Gregorian, Roman/Julian, or the conventional calendar of date.novas_date()
and novas_date_scale()
for the simplest conversion of string times to Julian days, and in case of the latter also to a corresponding timescale (without returning a parse position).novas_parse_timescale()
to parse a timescale from a string specification, and return the updated parse position after also.novas_parse_hours()
and novas_parse_degrees()
to convert strings in decimal or HMS/DMS formats to floating point values for SuperNOVAS, and return the parse position after the time/angle specification.novas_str_hours()
and novas_str_degrees()
for the simplest conversion of strings in decimal or HMS/DMS formats to floating point values for SuperNOVAS (without retruning a parse position).novas_epoch()
to convert string coordinate system specifications to the Julian date of the corresponding epoch, and new make_cat_object_sys()
and make_redshifted_object_sys()
to make it simpler to define ICRS catalog sources in the coordinate system of choice.FORTIFY
build configuration setting to enable gcc source code fortification checking by setting the _FORTIFY_SOURCE
macro to the specified value. It is now used with a value of 3 in the build and test CIs.example-time.c
and example-rise-set.c
under examples/
, for demonstrating date/time handling functions and rise, set, and transit time calculations.restrict
keyword to prevent pointer argument aliasing. Modern compilers will warn if restricted pointer arguments are aliased. At the least, it is a hint to users that pointer arguments marked as such should be distinct from (not overlapping with) the other pointer arguments.legacy/
folder, and installed into $(DESTDIR)$(docdir)/legacy/
.place()
and novas_sky_pos()
are significantly faster.julian_date()
to add range checking for month and day arguments, and return NAN (with errno
set to EINVAL
) if the input values are invalid.julian_date()
and cal_date()
now use astronomical calendar dates instead of the fixed Gregorian dates of before. Astronomical dates are Julian/Roman calendar dates prior to the Gregorian calendar reform of 1582.SIZE_OF_OBJ_NAME
and SIZE_OF_CAT_NAME
instead of sizeof(obj->starname)
and sizeof(obj->catalog)
internally for improved portability.README.md
for v1.3 and benchmarks, including comparisons to astropy.THREAD_LOCAL
definition extended to C23 thread_local
keyword also.Feature release. New easy to use adapter modules for CALCEPH or the NAIF CSPICE Toolkit to provide precise positions for Solar-system sources. Also, added support for Keplerian orbitals, such as the ones published by the IAU Minor Planet Center (MPC) for asteroids, comets, and Near-Earth-Objects (NEOs). And, many more fixes and improvements.
readeph()
implementation in readeph0.c
, and the use of DEFAULT_READEPH
in config.mk
. readeph0.c
is not linked by default, and was not linked in prior releases either.clang
compiler warnings, in tests and examples also.novas_v2z()
, novas_z2v()
.make_redshifted_cat_entry()
and make_redshifted_object()
to simplify the creation of distant catalog sources that are characterized with a redshift measure rather than a radial velocity value.grav_redshift()
, redhift_vrad()
, unredshift_vrad()
, novas_z_add()
, and novas_z_inv()
.novas_use_calceph()
and/or novas_use_calceph_planets()
to specify and use ephemeris data via CALCEPH for Solar-system sources in general, and for major planets specifically; and novas_calceph_use_ids()
to specify whether object.number
in NOVAS_EPHEM_OBJECT
type objects is a NAIF ID (default) or else a CALCEPH ID number of the Solar-system body. These functions are provided by the libsolsys-calceph.so[.1]
and/or .a
plugin libraries, which are built contingent on the CALCEPH_SUPPORT
variable being set to 1 prior to the build. The build of the plugin module requires an accessible installation of the CALCEPH development files (C headers and unversioned static or shared libraries depending on the needs of the build).novas_use_cspice()
, novas_use_cspice_planets()
, novas_use_cspice_ephem()
to use the NAIF CSPICE library for all Solar-system sources, major planets only, or for other bodies only. NOVAS_EPHEM_OBJECTS
should use NAIF IDs with CSPICE (or else -1 for name-based lookup). Also provides cspice_add_kernel()
and cspice_remove_kernel()
functions for convenience to manage the set of active kernels (#89). These functions are provided by the libsolsys-cspice.so[.1]
and/or .a
plugin libraries, which are built contingent on the CSPICE_SUPPORT
variable being set to 1 prior to the build. The build of the plugin module requires an accessible installation of the CSPICE development files (C headers and unversioned static or shared libraries depending on the needs of the build).novas_planet_for_name()
function to return the NOVAS planet ID for a given (case insensitive) name.novas_to_naif_planet()
(planet centers), novas_to_dexxx_planet()
(mixed planet center/barycenter for DExxx ephemeris files), and the inverse naif_to_novas_planet()
.get_planet_provider()
and get_planet_provider_hp()
functions for convenience to return the solarsystem()
/ solarsystem_hp()
type custom planet ephemeris provider functions currently configured, so they may be used directly, outside of ephemeris()
calls.make install
with prefix
and DESTDIR
support (e.g. make prefix="/opt" install
to install under /opt
, and/or make DESTDIR="/tmp/stage" install
to stage install under /tmp/stage
). You can also set other standard directory variables, as prescribed by the GNU standard to further customize the install locations.object.type
can now be set to NOVAS_ORBITAL_OBJECT
, whose orbit can be defined by the set of novas_orbital
, relative to a novas_orbital_system
. You can initialize an object
with a set of orbital elements using make_orbital_object()
, and for planetary satellite orbits you might use novas_set_orbsys_pole()
. For orbital objects, ephemeris()
will call on the new novas_orbit_posvel()
to calculate positions. While orbital elements do not always yield precise positions, they can for shorter periods, provided that the orbital elements are up-to-date. For example, the Minor Planer Center (MPC) publishes accurate orbital elements for all known asteroids and comets regularly. For newly discovered objects, this may be the only and/or most accurate information available anywhere.NOVAS_EMB
(Earth-Moon Barycenter) and NOVAS_PLUTO_BARYCENTER
to enum novas_planets
to distinguish from the planet center in calculations.gcrs_to_tod()
/ tod_to_gcrs()
and gcrs_to_mod()
/ mod_to_gcrs()
vector conversion functions for convenience.examples/
demonstrating the recommended approach for using SuperNOVAS to calculate positions for various types of object.object
initializer macros in novas.h
for the major planets, Sun, Moon, and barycenters, e.g. NOVAS_EARTH_INIT
or NOVAS_SSB_INIT
. These wrap the parametric NOVAS_PLANET_INIT(num, name)
macro, and can be used to simplify the initialization of NOVAS object
s.novas.h
and a corresponding section in the README on how these may be used to convert to/from NOVAS conventional quantities.Makefile
too.README
.Makefile
.infer
make target for running Facebook's infer
static analysis tool.nutation()
.README.md
Figure 1, to clarify relation of coordinate systems and (Super)NOVAS function to convert vectors among them.object
structure to include novas_orbital
for NOVAS_ORBITAL_OBJECT
types. To keep ABI compatibility to earlier SuperNOVAS releases, make_object()
will not initialize the new .orbit
field unless type
is set to NOVAS_ORBITAL_OBJECT
(which was not available before).NOVAS_PLANETS
, NOVAS_PLANET_NAMES_INIT
, and NOVAS_RMASS_INIT
macros to include the added planet constants.make check
now runs both static analysis by cppcheck (new analysis
target) and regression tests (test
target), in closer conformance to GNU Makefile standards.-g
to default CFLAGS
as a matter of GNU best practice.ibsupernovas.a
, which is symlinked to libnovas.a
for back compatibility.readeph0.c
moved to examples/
. It's a dummy legacy NOVAS C implementation that is not really needed in SuperNOVAS.README.md
and API documentation.Bug fix release. Nothing too scary, mainly just a collection of smaller fixes and improvements.
NOVAS_TAI_TO_TT
definition had wrong decimal in last place, thus was 3 ms off from what it should have been. (thanks to kiranshila)readeph_dummy()
dummy implementation in readeph0.c
called non existing error handler function.rad_vel()
, rad_vel2()
, place()
, and novas_sky_pos()
will include gravitational corrections to radial velocity for light originating at the surface, and observed near Earth or else at a large distance away. These corrections, along with those for the Solar potential at the source, may be skipped for rad_vel()
/ rad_vel2()
by setting d_src_sun
negative.super.c
module to alleviate the bloating of novas.c
, which can still be used as a self-contained, standalone, NOVAS C replacement for legacy applications if need be.tod_to_cirs()
. (thanks to kiranshila)Makefile
, and .mk
snippets, with added make
configurability.Feature release. Introducing a more efficient and elegant approach to position and velocity calculations using observer frames; versatile handling of astronomical timescales; and support for further observer locations, coordinate reference systems, and atmospheric refraction models. The release also fixes a number of bugs, of varying severity, which affected prior SuperNOVAS releases.
char
for storing small integer coefficients, assuming char
was signed. However, on some platforms like ARM and PowerPC char
is unsigned, which broke calculations badly. As of now, we use the explicit platform independent signed int8_t
storage type for these coefficients.gcrs_to_j2000()
transformed in the wrong direction in v1.0.tod_to_itrs()
used wrong Earth rotation measure (NOVAS_ERA
instead of NOVAS_GST
) in v1.0.cel2ter()
invalid output in v1.0 with CIRS input coordinates (erot
= EROT_ERA
and class
= NOVAS_DYNAMICAL_CLASS
) if output vector was distinct from input vector. Affects cirs_to_itrs()
also.tt2tdb()
Had a wrong scaling in sinusoidal period in v1.0, resulting in an error of up to +/- 1.7 ms.gcrs_to_cirs()
did not handle well if input and output vectors were the same in v1.0.d_light()
(since NOVAS C 3.1) if the first position argument is the ephemeris reference position (e.g. the Sun for solsys3.c
). The bug affects for example grav_def()
, where it effectively results in the gravitational deflection due to the Sun being skipped. See Issue #28.grav_def()
gravitating body position antedated somewhat incorrectly (in v1.0) when observed source is a Solar-system object between the observer and the gravitating body. The resulting positional error is typically small at below 10 uas.rad_vel()
applied relativistic corrections for a moving observer conditional on applying relativistic gravitational corrections (for Sun and/or Earth potential) for the observer. However, it seems more reasonable that the corrections for a moving observer should be applied always and independently of the (optional) gravitational corrections.place()
radial velocities were not quite correct in prior SuperNOVAS releases. The radial velocity calculation now precedes aberration, since the radial velocity that is observed is in the geometric direction towards the source (unaffected by aberration). As for gravitational deflection, the geometric direction is the correct direction in which light was emitted from the source for sidereal objects. For Solar system sources we now reverse trace the deflected light to calculate the direction in which it was emitted from the source. As such, the radial velocities calculated should now be precise under all conditions. The typical errors of the old calculations were up to tens of m/s because of aberration, and a few m/s due to the wrong gravitational deflection calculation.SUPERNOVAS_VERSION_STRING
in novas.h
in v1.0.NOVAS_OBSERVER_PLACES
in novas.h
in v1.0.frames.c
). A novas_frame
object uniquely defines both the place and time of observation, with a set of pre-calculated transformations and constants. Once the frame is defined it can be used very efficiently to calculate positions for multiple celestial objects with minimum additional computational cost. The frames API is also more elegant and more versatile than the low-level NOVAS C approach for performing the same kind of calculations. And, frames are inherently thread-safe since post-creation their internal state is never modified during the calculations. The following new functions were added: novas_make_frame()
, novas_change_observer()
, novas_geom_posvel()
, novas_geom_to_app()
, novas_sky_pos()
, novas_app_to_hor()
, novas_app_to_geom()
, novas_hor_to_app()
.novas_transform
structure. You may use these transforms to express position / velocity vectors, calculated for a given observer and time, in the coordinate reference system of choice.The following new functions were added: novas_make_transform()
, novas_invert_transform()
, novas_transform_vector()
, and novas_transform_sky_pos()
.novas_timespec
structure for the self-contained definition of precise astronomical time (timescale.c
). You can set the time via novas_set_time()
or novas_set_split_time()
to a JD date in the timescale of choice (UTC, UT1, GPS, TAI, TT, TCG, TDB, or TCB), or to a UNIX time with novas_set_unix_time()
. Once set, you can obtain an expression of that time in any timescale of choice via novas_get_time()
, novas_get_split_time()
or novas_get_unix_time()
. And, you can create a new time specification by incrementing an existing one, using novas_increment_time()
, or measure time differences via novas_diff_time()
, novas_diff_tcg()
, or novas_diff_tcb()
.novas_planet_bundle
structure to handle planet positions and velocities more elegantly (e.g. for gravitational deflection calculations).grav_undef()
to undo gravitational bending of the observed light to obtain geometric positions from observed ones.obs_posvel()
to calculate the observer position and velocity relative to the Solar System Barycenter (SSB).obs_planets()
to calculate apparent planet positions (relative to observer) and velocities (w.r.t. SSB).NOVAS_AIRBORNE_OBSERVER
for an observer moving relative to the surface of Earth e.g. in an aircraft or balloon based telescope platform, and NOVAS_SOLAR_SYSTEM_OBSERVER
for spacecraft orbiting the Sun. Both of these use the observer.near_earth
strcture to define (positions and) velocities as appropriate. Hence the 'near_earth
name is a bit misleading, but remains for back compatibility.NOVAS_MOD
(Mean of Date) which includes precession by not nutation and NOVAS_J2000
for the J2000 dynamical reference system.NOVAS_AIRBORNE_OBSERVER
and NOVAS_SOLAR_SYSTEM_OBSERVER
, and corresponding make_airborne_observer()
and make_solar_system_observer()
functions. Airborne observers have an Earth-fixed momentary location, defined by longitude, latitude, and altitude, the same way as for a stationary observer on Earth, but are moving relative to the surface, such as in an aircraft or balloon based observatory. Solar-system observers are similar to observers in Earth-orbit but their momentary position and velocity is defined relative to the Solar System Barycenter (SSB), instead of the geocenter.on_surface
structure, e.g. for refraction calculations at radio wavelengths. The make_on_surface()
function will set humidity to 0.0, but the user can set the field appropriately afterwards.novas_app_to_hor()
/ novas_hor_to_app()
functions. The models novas_standard_refraction()
and novas_optical_refraction()
implement the same refraction model as refract()
in NOVAS C 3.1, with NOVAS_STANDARD_ATMOSPHERE
and NOVAS_WEATHER_AT_LOCATION
respectively, including the reversed direction provided by refract_astro()
. The user may supply their own custom refraction also, and may make use of the generic reversal function novas_inv_refract()
to calculate refraction in the reverse direction (observer vs astrometric elevations) as needed.novas_radio_refraction()
based on the formulae by Berman & Rockwell 1976.cirs_to_tod()
and tod_to_cirs()
functions for efficient tranformation between True of Date (TOD) and Celestial Intermediate Reference System (CIRS), and vice versa.make_cat_object()
function to create a NOVAS celestial object
structure from existing cat_entry
data.rad_vel2()
to calculate radial velocities precisely in the presense of gravitational deflection i.e., when the direction in which light was emitted is different from the direction it is detected by the observer. This new function is now used by both place()
and novas_sky_pos()
.make help
to provide a brief list and explanation of the available build targets. (Thanks to @teuben
for suggesting this.)armv7
, aarch64
, riscv64
, ppc64le
. Thus, we should avoid misphaps, like the platform specific bug Issue #29, in the future.cio_array()
can now parse the original ASCII CIO locator data file (data/CIO_RA.TXT
) efficiently also, thus no longer requiring a platform-specific binary translation via the cio_file
tool.rad_vel()
has ignored this redshifting when the Sun was being observed. From now on, we shall gravitationally reference radial velocities when observing the Sun to its photosphere.cio_file
tool parses interval from header rather than the less precise differencing of the first two record timestamps. This leads to cio_array()
being more accurately centered on matching date entries, e.g. J2000.grav_def()
estimation of light time to where light passes nearest to gravitating body is improved by starting with the body position already antedated for light-time for the gravitating mass. The change typically improves the grativational deflection calculations at the few uas level.grav_def()
is simplified. It no longer uses the location type argument. Instead it will skip deflections due to any body, if the observer is within ~1500 km of its center.place()
now returns an error 3 if and only if the observer is at (or very close, to within ~1.5m) of the observed Solar-system object.era()
, fund_args()
, and planet_lon()
by being more careful about the order in which terms are accumulated and combined, resulting in a small improvement on the few uas (micro-arcsecond) level.vector2radec()
: ra
or dec
arguments may now be NULL if not required.tt2tdb()
Now uses the same, slightly more precise series as the original NOVAS C tdb2tt()
.rad_vel()
You can use negative values for the distances to skip particular gravitational corrections to the radial velocity measure. The value 0.0 also continues to have the same effect as before, except if the observed source is the Sun. Then d_src_sun
being 0.0 takes on a different meaning than before: rather than skipping gravitational redshift corrections for the Solar potential (as before) we will apply gravitational corrections for light originating at the Sun's photosphere.PSI_COR
and EPS_COR
made globally visible again, thus improving NOVAS C 3.1 compatibility.novas_inv_max_iter
variable declared in novas.c
to specify the maximum number of iterations before inverse functions return with an error (with errno set to ECANCELED
). Users may adjust this limit, if they prefer some other maximum value.nan
and -nan
effectively the same. They both represent an equally invalid result regardless of the sign.distro
. It's similar to the deprecated api
target from before except that it skips building static
libraries and cio_ra.bin
.make
now generates .so
shared libraries with SONAME
set to lib<name>.so.1
where the .1
indicates that it is major version 1 of the ABI
. All 1.x.x releases are expected to be ABI compatible with earlier releases.lib/*.so
files are now just symlinks to the actual versioned libraries lib/*.so.1
. This conforms more closely to what Linux distros expect.make
skips local-dox
target unless doxygen
is available (either in the default PATH
or else specified via the DOXYGEN
variable, e.g. in config.mk
). This way the default build does not have unexpected dependencies. (see Issue #22, thanks to @teuben
).make
can be configured without editing config.mk
simply by setting the appropriate shell variables (the same ones as in config.mk
) prior to invoking make
. Standard CC
, CPPFLAGS
, CFLAGS
and LDFLAGS
will also be used if defined externally.make shared
now also builds lib/libsolsys1.so.1
and lib/libsolsys2.so.1
shared libraries that can be used by programs that need solsys1 (via eph_manager
) or solsys2 (via jplint
) functionality.make solsys
now generates only the solarsystem()
implementation objects that are external (not built in).cio_file
(used typically at build time only to generate cio_ra.bin
).jplint.f
is moved to examples/
since it provides only a default implementation that typically needs to be tweaked for the particualr JPL PLEPH library one intends to use.supernovas.tag
for consistency.Bug fix release with minor changes.
cirs_to_itrs()
, itrs_to_cirs()
, tod_to_itrs()
, and itrs_to_tod()
all had a unit conversion bug in using the ut1_to_tt
argument [s] when converting TT-based Julian date to UT1-based JD [day] internally. (thanks to hannorein)example.c
[by hannorein].cirs_to_app_ra()
and app_to_cirs_ra()
for convenience to convert between right ascensions measured from the CIO (for CIRS) vs measured from the true equinox of date, on the same true equator of date.NOVAS_AU
to the IAU definition of exactly 1.495978707e+11 m. The old definition is also available as DE405_AU
. (thanks to hannorein)This is the initial release of the SuperNOVAS library. Changes are indicated w.r.t. the upstream NOVAS C 3.1 library from which SuperNOVAS is forked from.
sidereal_time()
function had an incorrect unit cast.ephemeris()
. When getting positions and velocities for Solar-system sources, it is important to use the values from the time light originated from the observed body rather than at the time that light arrives to the observer. This correction was done properly for positions, but not for velocities or distances, resulting in incorrect observed radial velocities or apparent distances being reported for spectroscopic observations or for angular-physical size conversions.ira_equinox()
which may return the result for the wrong type of equinox (mean vs. true) if the equinox
argument was changing from 1 to 0, and back to 1 again with the date being held the same. This affected NOVAS C 3.1 routines downstream also, such as sidereal_time()
.cio_basis()
, cio_location()
, ecl2equ()
, equ2ecl_vec()
, ecl2equ_vec()
, geo_posvel()
, place()
, and sidereal_time()
. All these functions returned a cached value for the other accuracy if the other input parameters are the same as a prior call, except the accuracy.cio_basis()
with alternating CIO location reference systems. This affected many CIRS-based position calculations downstream.equ2ecl_vec()
and ecl2equ_vec()
whereby a query with coord_sys = 2
(GCRS) has overwritten the cached mean obliquity value for coord_sys = 0
(mean equinox of date). As a result, a subsequent call with coord_sys = 0
and the same date as before would return the results GCRS coordinates instead of the requested mean equinox of date coordinates.fmod()
unchecked, which resulted in angles outside of the expected [0:2π] range and was also the reason why cal_date()
did not work for negative JD values.aberration()
returning NaN vectors if the ve
argument is 0. It now returns the unmodified input vector appropriately instead.az
output value in equ2hor()
at zenith in NOVAS C 3.1. While any azimuth is acceptable really, it results in unpredictable behavior. Hence, we set az
to 0.0 for zenith to be consistent.ephem_close()
in eph_manager.c
did not reset the EPHFILE
pointer to NULL.novas_debug(NOVAS_DEBUG_ON)
or novas_debug(NOVAS_DEBUG_EXTRA)
to enable. When enabled, any error conditions (such as NULL pointer arguments, or invalid input values etc.) will be reported to the standard error, complete with call tracing within the SuperNOVAS library, s.t. users can have a better idea of what exactly did not go to plan (and where). The debug messages can be disabled by passing NOVAS_DEBUF_OFF
(0) as the argument to the same call.novas.h
to promote consistent usage and easier to read code.ephemeris()
can be set at runtime via set_planet_provider()
, and set_planet_provider_hp()
(for high precision calculations). Similarly, if planet_ephem_provider()
or planet_ephem_provider_hp()
(defined in solsys-ephem.c
) are set as the planet calculator functions, then set_ephem_provider()
can set the user-specified function to use with these to actually read ephemeris data (e.g. from a JPL ephemeris file).set_cio_locator_file()
at runtime to specify the location of the binary CIO interpolation table (e.g. cio_ra.bin
) to use, even if the library was compiled with the different default CIO locator path.nu2000k()
can be replaced by another suitable IAU 2006 nutation approximation via set_nutation_lp_provider()
. For example, the user may want to use the iau2000b()
model instead or some custom algorithm instead.gcrs_to_cirs()
, cirs_to_itrs()
, and itrs_to_cirs()
, cirs_to_gcrs()
.gcrs_to_j2000()
, j2000_to_tod()
, tod_to_itrs()
, and itrs_to_tod()
, tod_to_j2000()
, j2000_to_gcrs()
.itrs_to_hor()
and hor_to_itrs()
functions to convert Earth-fixed ITRS coordinates to astrometric azimuth and elevation or back. Whereas tod_to_itrs()
followed by itrs_to_hor()
is effectively a just a more explicit 2-step version of the existing equ2hor()
for converting from TOD to to local horizontal (old methodology), the cirs_to_itrs()
followed by itrs_to_hor()
does the same from CIRS (new IAU standard methodology), and had no prior equivalent in NOVAS C 3.1.ecl2equ()
for converting ecliptic coordinates to equatorial, complementing existing equ2ecl()
.gal2equ()
for converting galactic coordinates to ICRS equatorial, complementing existing equ2gal()
.refract_astro()
complements the existing refract()
but takes an unrefracted (astrometric) zenith angle as its argument.place()
for simpler specific use: place_star()
, place_icrs()
, place_gcrs()
, place_cirs()
, and place_tod()
.radec_star()
and radec_planet()
as the common point for existing functions such as astro_star()
local_star()
, virtual_planet()
, topo_planet()
etc.tt2tdb()
, get_utc_to_tt()
, and get_ut1_to_tt()
make it simpler to convert between UTC, UT1, TT, and TDB time scales, and to supply ut1_to_tt
arguments to place()
or topocentric calculations.solarsystem()
variants. It is possible to use the different solarsystem()
implementations provided by solsys1.c
, solsys2.c
, solsys3.c
and/or solsys-ephem.c
side-by-side, as they define their functionalities with distinct, non-conflicting names, e.g. earth_sun_calc()
vs planet_jplint()
vs planet_eph_manager()
vs planet_ephem_provider()
.novas_case_sensitive(int)
to enable (or disable) case-sensitive processing of object names. (By default NOVAS object
names are converted to upper-case, making them effectively case-insensitive.)make_planet()
and make_ephem_object()
to make it simpler to configure Solar-system objects._Thread_local
or else the earlier GNU C >= 3.3 standard __thread
modifier. You can also set the preferred thread-local keyword for your compiler by passing it via -DTHREAD_LOCAL=...
in config.mk
to ensure that your build is thread-safe. And, if your compiler has no support whatsoever for thread_local variables, then SuperNOVAS will not be thread-safe, just as NOVAS C isn't.enum
s as their option arguments instead of the raw integers in NOVAS C 3.1. These enums are defined in novas.h
. The same header also defines a number of useful constants. The enums allow for some compiler checking, and make for more readable code that is easier to debug. They also make it easy to see what choices are available for each function argument, without having to consult the documentation each and every time.errno
set, usually to EINVAL
) if the arguments supplied are invalid (unless the NOVAS C API already defined a different return value for specific cases. If so, the NOVAS C error code is returned for compatibility). There were no such checks performed in NOVAS C 3.1.errno
so that users can track the source of the error in the standard C way and use functions such as perror()
and strerror()
to print human-readable error messages. (NOVAS C 3.1 did not set errno
).NAN
so that even if the caller forgets to check the error code, it becomes obvious that the values returned should not be used as if they were valid. (No more sneaky silent errors, which were common in NOVAS C 3.1.)NULL
arguments (unlike NOVAS C 3.1), both for optional input values as well as outputs that are not required (see the API Documentation for specifics). This eliminates the need to declare dummy variables in your application code for quantities you do not require.frame_tie(pos, J2000_TO_ICRS, pos)
using the same pos
vector both as the input and the output. In this case the pos
vector is modified in place by the call. This can greatly simplify usage, and can eliminate extraneous declarations, when intermediates are not required.const
whenever the function does not modify the data content being referenced. This supports better programming practices that generally aim to avoid unintended data modifications. (The passing of const
arguments to NOVAS C 3.1 calls would result in compiler warnings.)struct
layouts the same as NOVAS C thanks to alignment, thus allowing cross-compatible binary exchange of cat_entry
records with NOVAS C 3.1.long
instead of short
(in NOVAS C 3.1) to accommodate NAIF IDs, which require minimum 32-bit integers.precession()
can now take arbitrary input and output epochs. Unlike NOVAS C 3.1, it is not required that either of those epochs be J2000.cel2ter()
and ter2cel()
can now process 'option'/'class' = 1 (NOVAS_REFERENCE_CLASS
) regardless of the methodology (EROT_ERA
or EROT_GST
) used to input or output coordinates in GCRS (unlike in NOVAS C 3.1).make_object()
to retain the specified number argument (which can be different from the starnumber
value in the supplied cat_entry
structure), in contrast to NOVAS C 3.1, which set object->number
to 0 for cat_entry
arguments.cio_location()
will always return a valid value as long as neither output pointer argument is NULL. (NOVAS C 3.1 would return an error if a CIO locator file was previously opened but cannot provide the data for whatever reason).sun_eph()
in solsysl3.c
evaluates the series in reverse order compared to NOVAS C 3.1, accumulating the least significant terms first, and thus resulting in higher precision result in the end.vector2radec()
to return NAN values if the input is a null-vector (i.e. all components are zero), as opposed to NOVAS C 3.1, which left the input vector argument unchanged.fund_args()
, instead of the linear model in NOVAS C 3.1.cio_array()
vs NOVAS C 3.1, including I/O error checking.novascon.h
/ novascon.c
: These definitions of constants in NOVAS C 3.1 was troublesome for two reasons: (1) They were primarily meant for use internally within the library itself. As the library clearly defines in what units input and output quantities are expressed, the user code can apply its own appropriate conversions that need not match the internal system used by the library. Hence exposing these constants to users was half baked. (2) The naming of constants was too simplistic (with names such as C
or F
) that it was rather prone to naming conflicts in user code. As a result, the constants have been moved to novas.h
with more unique names (such as NOVAS_C
and NOVAS_EARTH_FLATTENING
. New code should rely on these definitions instead of the troubled constants of novascon.c
/ .h
if at all necessary.equ2hor()
: It's name does not make it clear that this function is suitable only for converting TOD (old methodology) to horizontal but not CIRS to horizontal (IAU 2000 standard). You should use the equivalent but more specific tod_to_itrs()
or the newly added cirs_to_itrs()
, followed by itrs_to_hor()
instead.cel2ter()
/ ter2cel()
: These NOVAS C 3.1 function can be somewhat confusing to use. You are likely better off with tod_to_itrs()
and cirs_to_itrs()
instead, and possibly followed by further conversions if desired.app_star()
, app_planet()
, topo_star()
and topo_planet()
: These NOVAS C 3.1 function use the old (pre IAU 2000) methodology, which isn't clear from their naming. Use place()
or place_star()
with NOVAS_TOD
or NOVAS_CIRS
as the system instead, as appropriate.readeph()
: This NOVAS C 3.1 function is prone to memory leaks, and not flexible with its origin (necessarily at the barycenter). Instead, use a similar novas_ephem_provider
implementation and set_ephem_provider()
for a more flexible and less troublesome equivalent, which also does not need to be baked into the library and can be configured at runtime.tdb2tt()
. Use tt2tdb()
instead. It's both more intuitive to use (returning the time difference as a double) and faster to calculate than the NOVAS C function, not to mention that it implements the more standard approach.