The Sight Reduction module provides functions for performing celestial navigation sight reductions, including calculating intercepts and azimuths based on celestial observations with atmospheric corrections.
from src.sight_reduction import (
calculate_intercept,
calculate_refraction_correction,
calculate_dip_correction,
calculate_limb_correction,
apply_refraction_correction,
get_total_observation_correction,
get_celestial_body,
format_position,
validate_altitude,
validate_temperature,
validate_pressure,
validate_observer_height,
validate_celestial_body_name,
validate_limb
)Perform a sight reduction to calculate the intercept (distance and direction) and azimuth with atmospheric corrections.
def calculate_intercept(
observed_altitude,
celestial_body,
assumed_position,
observation_time,
apply_refraction=True,
temperature=10.0,
pressure=1010.0,
observer_height=0.0,
celestial_body_name=None,
limb='center'
):- observed_altitude (
float): Observed altitude of the celestial body (degrees) - celestial_body (
astropy.coordinates.SkyCoord): Astropy SkyCoord object for the celestial body - assumed_position (
astropy.coordinates.EarthLocation): EarthLocation object for the assumed observer position - observation_time (
astropy.time.Time): Astropy Time object for the observation time - apply_refraction (
bool, optional): Whether to apply atmospheric refraction correction (default True) - temperature (
float, optional): Atmospheric temperature in degrees Celsius (default 10°C) - pressure (
float, optional): Atmospheric pressure in hPa (default 1010 hPa) - observer_height (
float, optional): Height of observer above sea level in meters (default 0) - celestial_body_name (
str, optional): Name of the celestial body ('sun', 'moon', etc.) for limb correction - limb (
str, optional): Which part of the celestial body to observe ('center', 'upper', 'lower') (default 'center')
- intercept (
float): Distance between observed and calculated altitude (nautical miles) - azimuth (
float): Calculated azimuth of the celestial body (degrees)
from astropy.time import Time
from astropy.coordinates import EarthLocation
import astropy.units as u
from src.sight_reduction import calculate_intercept, get_celestial_body
observation_time = Time("2023-06-15T12:00:00")
celestial_body = get_celestial_body("sun", observation_time)
assumed_position = EarthLocation(lat=40.0*u.deg, lon=-74.0*u.deg, height=0*u.m)
intercept, azimuth = calculate_intercept(
observed_altitude=45.0,
celestial_body=celestial_body,
assumed_position=assumed_position,
observation_time=observation_time
)Calculate atmospheric refraction correction for celestial observations.
def calculate_refraction_correction(
observed_altitude: float,
temperature: float = 10.0,
pressure: float = 1010.0
) -> float:- observed_altitude (
float): The observed altitude of the celestial body in degrees - temperature (
float, optional): Atmospheric temperature in degrees Celsius (default 10°C) - pressure (
float, optional): Atmospheric pressure in hPa (default 1010 hPa)
- refraction_correction (
float): Refraction correction in degrees to be subtracted from observed altitude
correction = calculate_refraction_correction(
observed_altitude=30.0,
temperature=15.0,
pressure=1020.0
)Apply atmospheric refraction correction to convert observed altitude to true altitude.
def apply_refraction_correction(
observed_altitude: float,
temperature: float = 10.0,
pressure: float = 1010.0
) -> float:- observed_altitude (
float): The raw altitude measured with the sextant in degrees - temperature (
float, optional): Atmospheric temperature in degrees Celsius (default 10°C) - pressure (
float, optional): Atmospheric pressure in hPa (default 1010 hPa)
- true_altitude (
float): True altitude in degrees (after refraction correction)
true_alt = apply_refraction_correction(
observed_altitude=30.0,
temperature=15.0,
pressure=1020.0
)Calculate the dip of the horizon correction for an elevated observer.
def calculate_dip_correction(observer_height: float) -> float:- observer_height (
float): Height of observer above sea level in meters
- dip_correction (
float): Dip correction in degrees (always positive, represents how much higher the horizon appears)
dip_corr = calculate_dip_correction(observer_height=10.0) # 10 meters above sea levelCalculate limb correction for observations of the Sun and Moon.
def calculate_limb_correction(celestial_body_name: str, limb: str = "center") -> float:- celestial_body_name (
str): Name of the celestial body ('sun' or 'moon') - limb (
str, optional): Which part of the body to observe ('center', 'upper', 'lower') (default 'center')
- limb_correction (
float): Limb correction in degrees
# For lower limb of the sun
sun_lower_limb_corr = calculate_limb_correction('sun', 'lower')
# For upper limb of the moon
moon_upper_limb_corr = calculate_limb_correction('moon', 'upper')Calculate all corrections for a celestial observation.
def get_total_observation_correction(
observed_altitude: float,
temperature: float = 10.0,
pressure: float = 1010.0,
observer_height: float = 0.0,
celestial_body_name: str = None,
limb: str = 'center'
) -> dict:- observed_altitude (
float): Raw observed altitude in degrees - temperature (
float, optional): Atmospheric temperature in degrees Celsius (default 10°C) - pressure (
float, optional): Atmospheric pressure in hPa (default 1010 hPa) - observer_height (
float, optional): Height of observer above sea level in meters (default 0) - celestial_body_name (
str, optional): Name of celestial body for limb correction - limb (
str, optional): Which part of the body to observe ('center', 'upper', 'lower') (default 'center')
- corrections (
dict): Dictionary with all corrections and final altitudeobserved_altitude: Original observed altituderefraction_correction: Amount to subtract for refractiondip_correction: Amount to add for dip of horizonlimb_correction: Amount to add for limb correctiontotal_correction: Total correction appliedcorrected_altitude: Final corrected altitude
corrections = get_total_observation_correction(
observed_altitude=45.0,
temperature=15.0,
pressure=1020.0,
observer_height=10.0,
celestial_body_name='sun',
limb='lower'
)
print(f"Corrected altitude: {corrections['corrected_altitude']:.2f}°")Get the appropriate celestial body based on name.
def get_celestial_body(name: str, observation_time) -> astropy.coordinates.SkyCoord:- name (
str): Name of the celestial body ('sun', 'moon', or 'star') - observation_time (
astropy.time.Time): Astropy Time object for the observation time
- celestial_body (
astropy.coordinates.SkyCoord): Astropy SkyCoord object for the celestial body
from astropy.time import Time
time = Time("2023-06-15T12:00:00")
sun = get_celestial_body("sun", time)Format latitude and longitude in degrees, minutes, and seconds.
def format_position(lat: float, lon: float) -> str:- lat (
float): Latitude in degrees - lon (
float): Longitude in degrees
- formatted_position (
str): Formatted position string
position = format_position(40.7128, -74.0060)
print(position) # Output: "40°42'46.08"N, 74°00'21.60"W"Validate that altitude is within reasonable range (-1° to 90°).
Validate temperature is within reasonable range (-100°C to +100°C).
Validate pressure is within reasonable range (800 to 1200 hPa).
Validate observer height is non-negative.
Validate celestial body name is supported ('sun' or 'moon').
Validate limb value is supported ('center', 'upper', or 'lower').
The module uses the following constants for calculations:
- Angular radius of Sun/Moon: Approximately 16 minutes of arc (16/60 degrees)
The module raises the following exceptions:
ValueError: Raised when input parameters are outside valid ranges- Invalid altitude: less than -1° or greater than 90°
- Invalid temperature: less than -100°C or greater than 100°C
- Invalid pressure: less than 800 hPa or greater than 1200 hPa
- Invalid observer height: negative values
- Invalid celestial body name: not 'sun' or 'moon'
- Invalid limb value: not 'center', 'upper', or 'lower'