<?php
/*
###########################################################################
TEST/DEMO FUNCTION: App_Geocent_T_List_Ephem()
This program requires an Internet connection to access the JPL Horizons API.
AUTHOR : Jay Tanner - 2025
LANGUAGE : PHP v8.2.12
This function returns a simple apparent geocentric ephemeris based on a
list of Julian Dates.
---------------------------------------------------------------------
Edit and run the source code to experiment with different parameters.
More quantities can easily be added to the ephemeris and the order of
the columns can be arranged in just about any way you wish.
NO DEPENDENCIES
###########################################################################
*/
/* --------------------------------------------------
Define random NASA/JPL body ID for this test/demo.
A random solar system body will be selected.
Refresh page for new randomized selection.
*/
$BodyID = Random_Int(1, 11);
$BodyID = Str_Replace('1099', '10',(($BodyID == 11)? '301':$BodyID.'99'));
$BodyID = Str_Replace('399', '301', $BodyID);
$BodyID .= (MT_Rand() % 8 == 0)? ';' : '';
if (MT_Rand() % 5 == 0) {$BodyID = Random_Int(1, 50000).';';}
// ---------------------
// Define asteroid note.
$AsteroidNoteText = (StrPos($BodyID, ';') !== FALSE)? '(asteroid)' : '';
// --------------------------------------------------------
// Define date span, time and zone variables for ephemeris.
// $BodyID = '301'; // Un-comment for Moon to override random selection above.
$TimeZone = '-05:00'; // +Positive = East
$TimeScale = 'UT'; // 'UT|TT'
// -----------------------------------------------
// Define example list of JD (Julian Date) values
// for which to compute the ephemeris.
$TList =
"
'2433056.5'
'2437892.184365723'
'2441505.322565431'
'2442133.739790178'
'2449031.573128554'";
// ---------------------------------
// Use Daylight Saving/Summer Time ?
$DSSTYN = 'No'; // 'Yes|No'
/* -------------------------------------------------------------
Define angular output mode.
HMS = Return hour angles and declinations as HMS/DMS strings.
DEG = Return hour angles and declinations in decimal hours/degrees.
*/
$DEGorHMS = 'HMS'; // 'DEG|HMS'
// ---------------------------------------------------------
// Call the custom function to generate the ephemeris table.
$AppGeoEphemListText = App_Geocent_T_List_Ephem ($BodyID,$TList,$TimeZone,
$TimeScale,$DSSTYN,
$DEGorHMS);
// --------------------------------------------------------
// Generate a client web page to display the returned text.
print <<< _HTML
<!DOCTYPE HTML>
<br>
<!-- Top yellow source code view link. --->
<br>
<table width="800" align="bottom" cellspacing="1" cellpadding="3">
<tr>
<td colspan="1" style="font-size:10pt; color:black;
background:white;text-align:left;">
<b><a href='View-Source-Code.php' target='_blank'
style='font-family:Verdana; color:black; background:yellow;
text-decoration:none; border:1px solid black; padding:4px;'>
View Source Code </a></b>
</td></tr>
</table>
<b><pre style='font-size:11pt;'>
TEST/DEMO FUNCTION: App_Geocent_T_List_Ephem()
App_Geocent_T_List_Ephem (BodyID,TList,TimeZone,TimeScale,DSSTYN,DEGorHMS)
This function returns an apparent geocentric ephemeris for a series of Julian
Dates.
Refresh page for a new random Body ID selection.
##############################################################################
NASA/JPL Body ID = $BodyID $AsteroidNoteText
Time Scale = $TimeScale
Time Zone = UT$TimeZone (Ignored when using TT Scale)
Daylight/Summer Time ? = $DSSTYN
Output DEG or HMS ? = $DEGorHMS
-------------------------------------
List of Julian Dates to be processed:
$TList
##############################################################################
$AppGeoEphemListText
</pre></b>
<!-- For extra scroll space at bottom of page --->
<br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br>
_HTML;
/* ###########################################################################
This function sends a user-defined Internet query to the NASA/JPL Horizons
API in Pasadena, California.
In this function, the query is supposed to be the Body ID or record #.
This function returns a simple apparent geocentric ephemeris for the
specified BodyID and a given list of Julian dates to which the compu-
tations apply.
Internal to Horizons, the list is called the 'TLIST' as shown in the
code below.
------------------------
Example JD TLIST format:
'2437892.184365723'
'2441505.322565431'
'2442133.739790178'
'2449031.573128554'
The ephemeris values returned are:
COLUMN CONTENTS
------ -----------------------------------------------------
1 Date and Time UT/ZONE/TT
2 Solar presence symbol
3 Lunar presence symbol
4 Right Ascension DEG/HMS
5 Declination DEG/DMS
6 Distance AU/KM
7 Angular diameter in arc seconds
8 Apparent visual magnitude
9 Surface brightness of 1 square arc second of disc
--------------------------------------------------------------
These two columns are appended to the table ONLY for the moon.
They can be used to determine the simple lunar phase angle.
11 ... SOT = Sun-Observer-Target(Moon) angle in degrees.
12 ... Moon relative to sun: /L = Leading; /T = Trailing
NOTE: For the simple lunar phase angle from 0 to 360 degrees:
PhaseAng = (LorT == 'L')? 360-SOT : SOT
When parsing the returned text, the type of text needs to be determined
so we know whether it was an ephemeris, an error or some other message
that came back.
An ephemeris will be identified by special starting and endpoint markers
and the table columns will be in linear CSV (spreadsheet) format for easy
parsing and re-formatting. The ephemeris Start/End markers are:
$$SOE = Start Of Ephemeris
and
$$EOE = End Of Ephemeris
If there are no ephemeris markers, then whatever text was returned was not
an ephemeris table and must be parsed differently.
###########################################################################
*/
function App_Geocent_T_List_Ephem ($BodyID,$TList,$TimeZone,$TimeScale,$DSSTYN,
$DEGorHMS)
{
// ---------------
// Read arguments.
$BodyID = StrToUpper(trim($BodyID));
if ($BodyID == 'Q' or $BodyID == 'X') {return '';}
$Command = URLEncode(trim($BodyID));
$TList = URLEncode(trim($TList));
/* -----------------------------------------------------------
Adjust for Daylight/Summer Time, if indicated. This assumes
that the Time Zone string is given in the standard +-HH:mm
format or an error may occur.
*/
$DSSTYN = substr(StrToUpper(trim($DSSTYN)),0,1);
$DSSTAdj = ($DSSTYN == 'N')? 0:1;
list($TZHH, $TZmm) = PReg_Split("[\:]", $TimeZone);
$TZSign = substr($TZHH,0,1);
$TZHours = (($TZSign == '-')? -1:1)*(abs($TZHH) + $TZmm/60) + $DSSTAdj;
$i = StrPos($TZHours, '.'); if ($i == FALSE) {$TZHours .= '.00';}
$i = StrPos($TZHours, '.');
$TZHH = $TZSign.SPrintF("%02d", abs(substr($TZHours,0,$i)));
$TimeZone = "$TZHH:$TZmm";
$TimeScale = (StrToUpper(substr(trim($TimeScale),0,1)) == 'T')? 'TT':'UT';
$DEGorHMS = (StrToUpper(substr(trim($DEGorHMS),0,1)) == 'D')? 'DEG':'HMS';
// ---------------------------------------------------------------------
// Handle special case of moon to include SOT,/r columns at end of line
// and to use km instead of AUs as the distance units.
$SOT = ''; $DistUnits = 'AU';
if ($BodyID == '301') {$SOT = ',23'; $DistUnits = 'KM';}
/* =======================================================================
CONSTRUCT CALLING URL FOR JPL HORIZONS API. IN THE CASE OF THE MOON,
KILOMETERS (KM) ARE SET AS THE RANGE (DISTANCE) UNITS, RATHER THAN AUs.
THIS IS A LUNAR CUSTOMIZATION, THE DEFAULT DISTANCE UNITS ARE AUs.
For angles in Deg Min Sec format use: &ANG_FORMAT='HMS'
=======================================================================
*/
$From_Horizons_API =
"https://ssd.jpl.nasa.gov/api/horizons.api?format=text" .
"&COMMAND='$Command'" .
"&MAKE_EPHEM='YES'" .
"&OBJ_DATA='YES'" .
"&EPHEM_TYPE='OBSERVER'" .
"&REF_SYSTEM='ICRF'" .
"&CENTER='500@399'" .
"&CAL_FORMAT='BOTH'" .
"&TIME_TYPE='UT'" .
"&TIME_ZONE='$TimeZone'" .
"&TIME_DIGITS='SECONDS'" .
"&TLIST_TYPE='JD'" .
"&TLIST='$TList'" .
"&ANG_FORMAT='$DEGorHMS'" .
"&APPARENT='AIRLESS'" .
"&RANGE_UNITS='$DistUnits'" .
"&SUPPRESS_RANGE_RATE='YES'" .
"&EXTRA_PREC='YES'" .
"&QUANTITIES='2,20,13,9$SOT'" .
"&CSV_FORMAT='YES'" ;
// ======================================================================
/* ------------------------------------------------------------------------
Send query to JPL Horizons API to get raw ephemeris as large text block.
This text can later be parsed and its contents selectively extracted.
It is possible that an error message could be returned, so this should
be taken into account.
*/
$W = Str_Replace(",\n", " \n", trim(File_Get_Contents($From_Horizons_API)));
return $W;
} // End of App_Geocent_T_List_Ephem (...)
?>