<?xml version="1.0" encoding="utf-8"?>

<resource schema="apfs">
	<meta name="title">Computation of GAST, GMST, and ERA</meta>
	<meta name="creationDate">2008-10-08T12:05:00Z</meta>
	<meta name="schema-rank">100</meta>
	<meta name="description" format="plain">
		Computation of Greenwich Apparent Sidereal Time, Greenwich
		Mean Sidereal Time, and the Earth Rotation Angle
	</meta>
	<meta name="_related" title="APFS ephemeris">/apfs/res/apfs_new/catquery/form</meta>
	<meta name="source">2000IAUJD...2E...5W</meta>
	<meta name="isSupplementTo"
		ivoId="ivo://org.gavo.dc/apfs/res/apfs_new/catquery">
		Apparent Places for Fundamental Stars
	</meta>

	<meta name="_intro" format="rst"><![CDATA[
		This service computes GAST (Greenwich Apparent Sidereal Time),
		GMST (Greenwich Mean Sidereal Time), and
		ERA (Earth Rotation Angle), time-related quantities
		required for, e.g., many uses of our
		\RSTservicelink{apfs/res/apfs_new/catquery/form}{APFS service}.  To learn
		more, see the `service info <info>`_ or the
		`web page of the IERS <http://www.iers.org/>`_.

		To compute the current values, leave the form empty.  Otherwise,
		enter a
		`date expression <\internallink{/static/help_vizier.shtml#dates}>`_
		(for UT1; only a subset of the available operators is supported)
		and an interval (in seconds) for how often a date should
		be computed.

		Examples:

		* ``2008-10-04T10:30:23`` gets you the values for that date
		* ``2008-10-04 .. 2008-10-05`` gets you values for the entire
		  fourth of october.
		* ``2008-10-04T10:30:23 .. 2008-10-05T10:30:23`` gets you values
		  between the two dates every interval seconds.
		* ``2008-10-04T10:30:23 +/- 1`` gets you values for one day before
		  and after the given date.
	]]></meta>
	<meta name="_longdoc" format="rst"><![CDATA[
Intermediate and apparent places of stars are usually required
for geodetic purposes, like determining a position (longitude, latitude on
the Earth's surface)
or an azimuth (which is the angle between the geographic north direction
and an arbitrary terrestrial object visible from the observation site).
A variety of corresponding tasks is treated in any
textbook of positional geodesy and cannot be addressed here.

Nevertheless, many of these tasks make use of the
"nautical triangle": this can be imagined as a spherical triangle  located
on the celestial sphere.
The nautical triangle is formed by three points:

#. the zenith - i.e. the point where the projection of the theodolite's
   plumb line intersects the celestial
   sphere -,
#. the north pole of the celestial sphere - now
   called Celestial Intermediate Pole (CIP) -, and
#. a  selected star entering via its intermediate or apparent place.

One parameter of the nautical triangle is immediately given
by the declination of the star (or its complement to 90 degree, respectively).

The local hour angle "t"
is frequently determined as second parameter; "t" is the angle between
these two lines of the triangle which emanate from
the CIP.

The local hour angle using right ascensions referred to the
"Celestial Intermediate Origin (CIO)" can be determined by:

  t = ERA + longitude - intermediate right ascension

where  ERA stands for the Earth Rotation Angle and
longitude means the geographic east longitude of the observer.
Traditionally, the local hour angle has been determined by

  t = GAST + longitude - apparent right ascension

where  GAST stands for Greenwich Apparent Sidereal Time, and with
apparent right ascensions referred to the equinox.
Both procedures yield the same hour angle, apart from negligible differences
which are of the order of one milliarcsecond or below.
BUT:  either ERA and INTERMEDIATE (CIO-based) right ascensions or
GAST and APPARENT (equinox-based) right ascensions have to be used
consistently.

An additional line or angle has yet to be provided by the
observer as third parameter in the nautical
triangle. This may be a zenith distance or an azimuth.
Then the nautical triangle is completely determined and
can be applied for the specific geodetic task.

Note the different time arguments for intermediate and apparent places
(Terrestrial Time TT) and UT1 for ERA and GAST. UT1 and UTC do not differ by more
than 1 second. The actual difference UT1 - UTC is published
by the International Earth Rotation Service (IERS)
- Bulletin D - and can be accessed via the `IERS web-pages <http://www.iers.org>`_
where also a useful glossary can be found.
For detailed information we recommend the printed version of the
Astronomical Almanac, or the `Astronomical Almanac Online <http://asa.usno.navy.mil/>`_.

GAST and GMST are
consistent with IAU 2006 precession.

Software Routines from the IAU SOFA Collection were used. Copyright ©
International Astronomical Union Standards of Fundamental Astronomy
(http://www.iausofa.org); actually, we are using ERFA in the meantime,
but SOFA credit is still due.
	]]></meta>

	<meta name="subject">astrometry</meta>
	<meta name="subject">geodesics</meta>

	<meta name="_news" author="MD" date="2021-03-25">No longer
		using a C wrapper around SOFA but instead going for ERFA
		through astropy.  We have confirmed that results are identical
		up to the precision we give.</meta>
	<meta name="_news" author="MD" date="2011-04-04">We
		now actually pass TT to the SOFA routines where
		required rather than approximate it by
		UT1 as before.  This will affect the results given
		here only in rare cases, and even then only by changing
		the last figure due to rounding.
	</meta>

	<table id="times">
		<column name="ut1" type="timestamp" tablehead="UT1"
			ucd="time.epoch;meta.main" verbLevel="1"
			description="Time and date (UT1)" displayHint="type=humanDate"/>
		<column name="gmst" type="double precision" tablehead="GMST"
			unit="deg"
			verbLevel="1" description="Greenwich mean sidereal time"
			displayHint="type=hms,sf=4"/>
		<column name="gast" type="double precision" tablehead="GAST"
			unit="deg"
			verbLevel="1" description="Greenwich apparent sidereal time"
			displayHint="type=hms,sf=4"/>
		<column name="era" type="double precision" tablehead="ERA"
			unit="deg"
			verbLevel="1" description="Earth rotation angle"
			displayHint="type=dms,sf=3"/>
	</table>

	<data id="build_result" auto="False">
		<reGrammar>
			<names>ut1,gmst,gast,era</names>
		</reGrammar>
		<make table="times">
			<rowmaker>
				<map dest="gmst">parseWithNull(@gmst, parseTime, "None")</map>
				<map dest="gast">parseWithNull(@gast, parseTime, "None")</map>
				<map dest="ut1">parseWithNull(@ut1, parseTimestamp, "None")</map>
				<map dest="era">parseWithNull(@era, float, "None")</map>
				<apply name="addWarning">
					<code><![CDATA[
						year = int(@ut1.split("-")[0])
						if year<1960:
							targetTable.addMeta("_warning", "These results depend"
								" on the definition of UTC, which does not really exist"
								" before 1960. Hence, the data given here is"
								" questionable and at least slightly inaccurate.")

						elif year>datetime.date.today().year+5:
							targetTable.addMeta("_warning", "The change in the"
								" Earth's rotation rate affects these results.  Since"
								" these results lie far in the future and predictions"
								" of the rotation may be incorrect, these results may"
								" be slightly inaccurate.")
					]]></code>
				</apply>
			</rowmaker>
		</make>
	</data>
	
<!-- SOAP disabled below while Debian t.w doesn't have t.w.soap -->
	<service id="q" allowed="form,api">
		<meta name="shortName">times_series</meta>
		<customCore module="res/timescore"/>

		<publish sets="ivo_managed,local" render="form"/>
		<publish sets="ivo_managed" render="api"/>
	</service>


	<regSuite id="tests">
		<regTest id="test1" title="Times service delivers expected values">
			<url parSet="form"
				ut1="2008-10-04T10:30:23 .. 2008-10-05T10:30:23"
				interval="3600">q/form</url>
			<code>
				self.assertHasStrings("Greenwich Mean Sidereal",
					"12 24 29.3052", "+306 20 18.341", "04 27 07.6839")
			</code>
		</regTest>

		<regTest title="Times service delivers nice error message for
			malformed vexprs">
			<url parSet="form" ut1="wirres Zeug" interval="3600">q/form</url>
			<code>
				self.assertHasStrings("wirres Zeug", "Invalid date expression (at 0)")
			</code>
		</regTest>

		<regTest title="GAST CSV output works">
			<url parSet="form" _FORMAT="CSV" ut1="2020-01-01 .. 2020-01-05"
				interval="14440">/apfs/times/q/form</url>
			<code>
				self.assertHasStrings("ut1,gmst,gast,era\r\n",
					"2020-01-02T08:05:20,222.77298995121694,"
					"222.76876933683172,222.51671035020607")
			</code>
		</regTest>

		<regTest title="GAST API works">
			<url RESPONSEFORMAT="votable"
				ut1="2020-01-01T12:00:00 .. 2020-01-02T12:00:00"
				interval="3600">/apfs/times/q/api</url>
			<code>
				rows = self.getVOTableRows()
				self.assertEqual(rows[0]["ut1"].day, 1)
				self.assertAlmostEqual(rows[3]["gmst"], 325.73783918610945)
				self.assertAlmostEqual(rows[4]["gast"], 340.7746968714495)
				self.assertAlmostEqual(rows[5]["era"], 355.5637191110078)
			</code>
		</regTest>
	</regSuite>
</resource>
