diff options
-rw-r--r-- | info/blueshift.texinfo | 32 | ||||
-rw-r--r-- | src/solar.py | 117 |
2 files changed, 134 insertions, 15 deletions
diff --git a/info/blueshift.texinfo b/info/blueshift.texinfo index 23d810e..a19d0f4 100644 --- a/info/blueshift.texinfo +++ b/info/blueshift.texinfo @@ -216,11 +216,11 @@ high night and 6500 K during the high day. Specify your geographical coordinates. This is used to determine how dark it is outside. @env{LAT} is the latitude, floating point -measured in degrees from the equator to the -north. It is negative if you are on the +measured in degrees celestial northwards from +the equator. It is negative if you are on the southern hemisphere. @env{LON} is the longitude, floating point measured in degrees -from Greenwich to the east. Negative if you +eastwards from Greenwich. Negative if you are on the west side of the Earth. @item -r @@ -753,12 +753,12 @@ point. It has three optional parameters: The time in Julian Centuries. @item low = -6.0 -The suns elevation at the limit to high night, that +The Suns elevation at the limit to high night, that is, the highest possible position (measured in degrees) -of the sun before it becomes visible. +of the Sun before it becomes visible. @item high = 3.0 -The suns elevation at the limit to high day, that is, +The Suns elevation at the limit to high day, that is, the lowest possible position (measured in degrees) of the before it starts becoming less visible (twilight.) @end table @@ -817,13 +817,27 @@ Converts from radians to degrees. @item corrected_mean_ecliptic_obliquity(t) @item solar_declination(t) @item equation_of_time(t) -@item hour_angle_from_elevation(latitude, declinaton, elevation) -@item elevation_from_hour_angle(latitude, declinaton, hour_angle) +@item hour_angle_from_elevation(latitude, declination, elevation) +Calculates the solar hour angle from the Sun's elevation. + +@item elevation_from_hour_angle(latitude, declination, hour_angle) +Calculates the Sun's elevation from the solar hour angle. + @item time_of_solar_noon(t, longitude) +Calculates the time of the closest solar noon. + @item time_of_solar_elevation(t, noon, latitude, longitude, elevation) +Calculates the time the Sun has the apparent elevation +@code{elevation}, in degrees, at the geographical position +(@code{latitude}, @code{longitude}). @code{noon} is the +time the closest the solar noon. + @item solar_elevation_from_time(t, latitude, longitude) +Calculates the Suns elevation, in degrees, as apparent from the +geographical position (@code{latitude}, @code{longitude}). + @item solar_elevation(latitude, longitude, t = None) -Does the same thing as @code{solar_elevation_from_time}, +Calculates the same thing as @code{solar_elevation_from_time}, except the time is optional and defaults to the current time. @end table diff --git a/src/solar.py b/src/solar.py index c8d7677..b418b41 100644 --- a/src/solar.py +++ b/src/solar.py @@ -44,45 +44,99 @@ def sun(latitude, longitude, t = None, low = -6.0, high = 3.0): def julian_day_to_epoch(t): + ''' + Converts a Julian Day timestamp to a POSIX time timestamp + + @param t:float The time in Julian Days + @return :float The time in POSIX time + ''' return (jd - 2440587.5) * 86400.0 def epoch_to_julian_day(t): + ''' + Converts a POSIX time timestamp to a Julian Day timestamp + + @param t:float The time in POSIX time + @return :float The time in Julian Days + ''' return t / 86400.0 + 2440587.5 def julian_day_to_julian_centuries(t): + ''' + Converts a Julian Day timestamp to a Julian Centuries timestamp + + @param t:float The time in Julian Days + @return :float The time in Julian Centuries + ''' return (t - 2451545.0) / 36525.0 def julian_centuries_to_julian_day(t): + ''' + Converts a Julian Centuries timestamp to a Julian Day timestamp + + @param t:float The time in Julian Centuries + @return :float The time in Julian Days + ''' return t * 36525.0 + 2451545.0 def epoch_to_julian_centuries(t): + ''' + Converts a POSIX time timestamp to a Julian Centuries timestamp + + @param t:float The time in POSIX time + @return :float The time in Julian Centuries + ''' return julian_day_to_julian_centuries(epoch_to_julian_day(t)) def julian_centuries_to_epoch(t): + ''' + Converts a Julian Centuries timestamp to a POSIX time timestamp + + @param t:float The time in Julian Centuries + @return :float The time in POSIX time + ''' return julian_day_to_epoch(julian_centuries_to_julian_day(t)) def epoch(): ''' Get current POSIX time + + @return :float The current POSIX time ''' return time.time() def julian_day(): ''' Get current Julian Day time + + @return :float The current Julian Day time ''' return epoch_to_julian_day(epoch()) def julian_centuries(): ''' Get current Julian Centuries time + + @return :float The current Julian Centuries time ''' return epoch_to_julian_centuries(epoch()) def radians(deg): + ''' + Convert an angle from degrees to radians + + @param deg:float The angle in degrees + @return :float The angle in radians + ''' return deg * math.pi / 180 def degrees(rad): + ''' + Convert an angle from radians to degrees + + @param rad:float The angle in radians + @return :float The angle in degrees + ''' return rad * 180 / math.pi def sun_geometric_mean_longitude(t): @@ -139,22 +193,45 @@ def equation_of_time(t): rc -= 1.25 * e ** 2 * math.sin(2 * m) return 4 * degrees(rc) -def hour_angle_from_elevation(latitude, declinaton, elevation): +def hour_angle_from_elevation(latitude, declination, elevation): + ''' + Calculates the solar hour angle from the Sun's elevation + + @param longitude:float The longitude in degrees eastwards from Greenwich, negative for westwards + @param declination:float The declination, in degrees + @param hour_angle:float The suns elevation, in degrees + @return :float The solar hour angle, in degrees + ''' if elevation == 0: return 0 rc = math.cos(abs(elevation)) - rc -= math.sin(radians(latitude)) * math.sin(declinaton) - rc /= math.cos(radians(latitude)) * math.cos(declinaton) + rc -= math.sin(radians(latitude)) * math.sin(declination) + rc /= math.cos(radians(latitude)) * math.cos(declination) rc = math.acos(rc) return -rc if (rc < 0) == (elevation < 0) else rc; -def elevation_from_hour_angle(latitude, declinaton, hour_angle): +def elevation_from_hour_angle(latitude, declination, hour_angle): + ''' + Calculates the Sun's elevation from the solar hour angle + + @param longitude:float The longitude in degrees eastwards from Greenwich, negative for westwards + @param declination:float The declination, in degrees + @param hour_angle:float The solar hour angle, in degrees + @return :float The suns elevation, in degrees + ''' rc = math.cos(radians(latitude)) - rc *= math.cos(hour_angle) * math.cos(declinaton) - rc += math.sin(radians(latitude)) * math.sin(declinaton) + rc *= math.cos(hour_angle) * math.cos(declination) + rc += math.sin(radians(latitude)) * math.sin(declination) return math.asin(rc) def time_of_solar_noon(t, longitude): + ''' + Calculates the time of the closest solar noon + + @param t:float A time close to the seeked time, in Julian Centuries + @param longitude:float The longitude in degrees eastwards from Greenwich, negative for westwards + @return :float The time, in Julian Centuries, of the closest solar noon + ''' t, rc = julian_centuries_to_julian_day(t), longitude for (k, m) in ((-360, 0), (1440, -0.5)): rc = julian_day_to_julian_centuries(t + m + rc / k) @@ -162,6 +239,16 @@ def time_of_solar_noon(t, longitude): return rc def time_of_solar_elevation(t, noon, latitude, longitude, elevation): + ''' + Calculates the time the Sun has a specified apparent elevation at a geographical position + + @param t:float A time close to the seeked time, in Julian Centuries + @param noon:float The time of the closest solar noon + @param latitude:float The latitude in degrees northwards from the equator, negative for southwards + @param longitude:float The longitude in degrees eastwards from Greenwich, negative for westwards + @param elevation:float The solar elevation, in degrees + @return :float The time, in Julian Centuries, of the specified elevation + ''' rc = noon rc, et = solar_declination(rc), equation_of_time(rc) rc = hour_angle_from_elevation(latitude, rc, elevation) @@ -174,6 +261,15 @@ def time_of_solar_elevation(t, noon, latitude, longitude, elevation): return rc def solar_elevation_from_time(t, latitude, longitude): + ''' + Calculates the Suns elevation as apparent from a geographical position + + @param t:float The time in Julian Centuries + @param latitude:float The latitude in degrees northwards from the equator, negative for southwards + @param longitude:float The longitude in degrees eastwards from Greenwich, negative for westwards + @return :float The suns apparent at the specified time as seen from the specified position, + measured in degrees + ''' rc = julian_centuries_to_julian_day(t) rc = (rc - float(int(rc + 0.5)) - 0.5) * 1440 rc = 720 - rc - equation_of_time(t) @@ -181,6 +277,15 @@ def solar_elevation_from_time(t, latitude, longitude): return elevation_from_hour_angle(latitude, solar_declination(t), rc) def solar_elevation(latitude, longitude, t = None): + ''' + Calculates the Suns elevation as apparent from a geographical position + + @param latitude:float The latitude in degrees northwards from the equator, negative for southwards + @param longitude:float The longitude in degrees eastwards from Greenwich, negative for westwards + @param t:float? The time in Julian Centuries, `None` for the current time + @return :float The suns apparent at the specified time as seen from the specified position, + measured in degrees + ''' rc = julian_centuries() if t is None else t rc = solar_elevation_from_time(rc, latitude, longitude) return degrees(rc) |