Amateur astronomical computations: rise and set times and azimuths,coordinates, distances, angular sizes and other parametersof the Sun, the Moon, planets and stars.
[Index] [Quick Jump]
For package maintainers and hackage trustees
Candidates
| Versions[RSS] | 0.4.1.0,0.4.1.1,0.4.1.2,0.4.1.3,0.4.2.0,0.4.2.1,0.4.3.0 (info) |
|---|---|
| Dependencies | base (>=4.7 && <5),matrix (>=0.3.4.4),time [details] |
| License | BSD-3-Clause |
| Copyright | 2016-2021 Alexander Ignatyev |
| Author | Alexander Ignatyev |
| Maintainer | Alexander Ignatyev |
| Uploaded | byaignatyev17 at2021-05-23T23:17:04Z |
| Category | Science |
| Home page | https://github.com/aligusnet/astro |
| Source repo | head: git clonehttps://github.com/aligusnet/astro.git |
| Distributions | LTSHaskell:0.4.3.0, Stackage:0.4.3.0 |
| Reverse Dependencies | 1 direct, 0 indirect [details] |
| Downloads | 5194 total (17 in the last 30 days) |
| Rating | 2.25 (votes: 2)[estimated byBayesian average] |
| Your Rating |
|
| Status | Docs available[build log] Last success reported on 2021-05-23[all 1 reports] |
It will take care of everything.
stack buildstack testTypes to represent hours (used in celestial coordinate systems and as time zone) and degrees (used in coordinate systems).
import Data.Astro.Types-- 10h 15m 19.7sdh :: DecimalHoursdh = fromHMS 10 15 19.7-- DH 10.255472222222222(h, m, s) = toHMS dh-- (10,15,19.699999999999562)-- 51°28′40″dd :: DecimalDegreesdd = fromDMS 51 28 40-- DD 51.477777777777774(d, m, s) = toDMS dd-- (51,28,39.999999999987494)import Data.Astro.Types-- the Royal Observatory, Greenwichro :: GeographicCoordinatesro = GeoC (fromDMS 51 28 40) (-(fromDMS 0 0 5))-- GeoC {geoLatitude = DD 51.4778, geoLongitude = DD (-0.0014)}The main time datetime type used in the library isJulianDate defined inData.Astro.Time.JulianDate. JulianDate is just a number of days since noon of 1 January 4713 BC:
import Data.Astro.Time.JulianDate-- 2017-06-25 9:29:00 (GMT)jd :: JulianDatejd = fromYMDHMS 2017 6 25 9 29 0-- JD 2457929.895138889LocalCiviTime andLocalCivilDate are Julian dates with time zones:
import Data.Astro.Time.JulianDateimport Data.Astro.Types-- 2017-06-25 10:29:00 +0100 (BST)lct :: LocalCivilTimelct = lctFromYMDHMS (DH 1) 2017 6 25 10 29 0-- 2017-06-25 10:29:00.0000 +1.0lctJD :: JulianDatelctJD = lctUniversalTime lct-- JD 2457929.895138889lctTZ :: DecimalHourslctTZ = lctTimeZone lct-- DH 1.0lcd :: LocalCivilDatelcd = lcdFromYMD (DH 1) 2017 6 25lcdJD :: JulianDatelcdJD = lcdDate lcd-- JD 2457929.5lcdTZ :: DecimalHourslcdTZ = lcdTimeZone lcd-- DH 1.0The celestical coordinate systems are defined inData.Astro.Coordinate.
If you would like to locate Sirius in the sky you need to know the altitude or 'how far up' angle in the sky and azimuth - 'how far round' angle from the north direction to the east. this describes theHorizontal coordinate system:
import Data.Astro.Coordinateimport Data.Astro.Typeshc :: HorizonCoordinateshc = HC (DD 30.5) (DD 180)-- HC {hAltitude = DD 30.0, hAzimuth = DD 180.0}Unfortunately the Horizontal coordinate system values depend on the position of the observer. And it's not handy when you need to share coordinates of some celestial object with your friend in Japan.
The second coordinate system is theEquatorial coordinate system. This coordinate system uses the location of the centre of the Earth as the zero point so it does not depend on the observer's location.
We have two flavours of equatorial coordinates:
the first one uses thevernal equinox as a starting direction for the 'how far round' coordinate (right ascension, α),
the second one uses themeridian instead of the vernal equinox (hour angle).
We can consider the second one as a transition coordinate system between the horizontal one and the 'true' equatorial one.
import Data.Astro.Coordinateimport Data.Astro.Typesec1 :: EquatorialCoordinates1ec1 = EC1 (DD 71.7) (DH 8)-- EC1 {e1Declination = DD 71.7, e1RightAscension = DH 8.0}ec2 :: EquatorialCoordinates2ec2 = EC1 (DD 77.7) (DH 11)-- EC2 {e2Declination = DD 77.7, e2HoursAngle = DH 11.0}Say, now is 2017-06-25 10:29 BST and we are somewhere near the Royal Observatory, Greenwich.
Let convert the current location of the Sun in horizon coordinates (altitude: 49°18′21.77″, azimuth: 118°55′19.53″) to equatorial coordinates and back to horizon ones:
import Data.Astro.Time.JulianDateimport Data.Astro.Coordinateimport Data.Astro.Typesro :: GeographicCoordinatesro = GeoC (fromDMS 51 28 40) (-(fromDMS 0 0 5))dt :: LocalCivilTimedt = lctFromYMDHMS (DH 1) 2017 6 25 10 29 0sunHC :: HorizonCoordinatessunHC = HC (fromDMS 49 18 21.77) (fromDMS 118 55 19.53)-- HC {hAltitude = DD 49.30604722222222, hAzimuth = DD 118.92209166666666}sunEC2 :: EquatorialCoordinates2sunEC2 = horizonToEquatorial (geoLatitude ro) sunHC-- EC2 {e2Declination = DD 23.378295912623855, e2HoursAngle = DH 21.437117068873537}sunEC1 :: EquatorialCoordinates1sunEC1 = EC1 (e2Declination sunEC2) (haToRA (e2HoursAngle sunEC2) (geoLongitude ro) (lctUniversalTime dt))-- EC1 {e1Declination = DD 23.378295912623855, e1RightAscension = DH 6.29383725890224}sunEC2' :: EquatorialCoordinates2sunEC2' = EC2 (e1Declination sunEC1) (raToHA (e1RightAscension sunEC1) (geoLongitude ro) (lctUniversalTime dt))-- EC2 {e2Declination = DD 23.378295912623855, e2HoursAngle = DH 21.437117068873537}sunHC' :: HorizonCoordinatessunHC' = equatorialToHorizon (geoLatitude ro) sunEC2'-- HC {hAltitude = DD 49.30604722222222, hAzimuth = DD 118.92209166666666}You can use function-shortcuts to simplify transformation EquatorialCoordinates1 <-> HorizonCoordinates:ec1ToHC andhcToEC1:
import Data.Astro.Time.JulianDateimport Data.Astro.Coordinateimport Data.Astro.Typesro :: GeographicCoordinatesro = GeoC (fromDMS 51 28 40) (-(fromDMS 0 0 5))dt :: LocalCivilTimedt = lctFromYMDHMS (DH 1) 2017 6 25 10 29 0sunHC :: HorizonCoordinatessunHC = HC (fromDMS 49 18 21.77) (fromDMS 118 55 19.53)-- HC {hAltitude = DD 49.30604722222222, hAzimuth = DD 118.92209166666666}sunEC1 :: EquatorialCoordinates1sunEC1 = hcToEC1 ro (lctUniversalTime dt) sunHC-- EC1 {e1Declination = DD 23.378295912623855, e1RightAscension = DH 6.29383725890224}sunHC' :: HorizonCoordinatessunHC' = ec1ToHC ro (lctUniversalTime dt) sunEC1-- HC {hAltitude = DD 49.30604722222222, hAzimuth = DD 118.92209166666666}The ancient astronomers noted that there were 2 types of stars: some of them were fixed, travelling the same way across the sky every sidereal day and another were wanderers (planetai in ancient Greek).
Of course, stars are not fixed, they are travelling with high speeds but distances to them are so high that their movement is very difficult to note. So we can assume that they are fixed for our purposes.
Given the "fixed" equatorial coordinates of the star we only need to transform them to the horizon coordinates to find out where the star in the sky.
In the example below we will useData.Astro.Star module which defines equatorial coordinates of some stars:
import Data.Astro.Time.JulianDateimport Data.Astro.Coordinateimport Data.Astro.Typesimport Data.Astro.Starro :: GeographicCoordinatesro = GeoC (fromDMS 51 28 40) (-(fromDMS 0 0 5))dt :: LocalCivilTimedt = lctFromYMDHMS (DH 1) 2017 6 25 10 29 0-- Calculate location of BetelgeusebetelgeuseEC1 :: EquatorialCoordinates1betelgeuseEC1 = starCoordinates Betelgeuse-- EC1 {e1Declination = DD 7.407064, e1RightAscension = DH 5.919529}betelgeuseHC :: HorizonCoordinatesbetelgeuseHC = ec1ToHC ro (lctUniversalTime dt) betelgeuseEC1-- HC {hAltitude = DD 38.30483892505852, hAzimuth = DD 136.75755644642248}Data.Astro.CelestialObject.RiseSet module definesRiseSet type to represent time and azimuth of rise and set.
Let calculate rise and set time of Rigel:
import Data.Astro.Time.JulianDateimport Data.Astro.Coordinateimport Data.Astro.Typesimport Data.Astro.Effectsimport Data.Astro.CelestialObject.RiseSetimport Data.Astro.Starro :: GeographicCoordinatesro = GeoC (fromDMS 51 28 40) (-(fromDMS 0 0 5))today :: LocalCivilDatetoday = lcdFromYMD (DH 1) 2017 6 25-- Calculate location of BetelgeuserigelEC1 :: EquatorialCoordinates1rigelEC1 = starCoordinates RigelverticalShift :: DecimalDegreesverticalShift = refract (DD 0) 12 1012-- DD 0.5660098245614035rigelRiseSet :: RiseSetLCTrigelRiseSet = riseAndSetLCT ro today verticalShift rigelEC1-- RiseSet (2017-06-25 06:38:18.4713 +1.0,DD 102.51249855335433) (2017-06-25 17:20:33.4902 +1.0,DD 257.48750144664564)As we can see Rigel rose today at 06:38:18 and will set at 17:20:33, azimuths of rise and set 102.51° and 257.49° correspondingly.
We usedrefract function ofData.Astro.Effects module with reasonable default parameters to calculate vertical shift.
The planets is completely different story. We cannot assume that the planets have "fixed" location in equatorial coordinates like stars.
What we can do is to describe details of the planets' orbit and calculate their positions at any given moment.
Planets and planet details are defined inData.Astro.Planet module.j2010PlanetDetails returns details for the given planet.This module also definesplanetPosition,planetDistance1 andplanetAngularDiameter to calculate position of the given planet, distance to the planet and angular size of the planet correspondingly.
1 at the end of theplanetDistance1 means that this function uses not very precise method to do calculations. Sometimes there are2-methods available in the library, but not always.
Let us do some planets-related calculations.
Do some initialisation:
import Data.Astro.Time.JulianDateimport Data.Astro.Coordinateimport Data.Astro.Typesimport Data.Astro.Effectsimport Data.Astro.CelestialObject.RiseSetimport Data.Astro.Planetro :: GeographicCoordinatesro = GeoC (fromDMS 51 28 40) (-(fromDMS 0 0 5))dt :: LocalCivilTimedt = lctFromYMDHMS (DH 1) 2017 6 25 10 29 0today :: LocalCivilDatetoday = lcdFromYMD (DH 1) 2017 6 25jupiterDetails :: PlanetDetailsjupiterDetails = j2010PlanetDetails JupiterearthDetails :: PlanetDetailsearthDetails = j2010PlanetDetails EarthjupiterPosition :: JulianDate -> EquatorialCoordinates1jupiterPosition = planetPosition planetTrueAnomaly1 jupiterDetails earthDetailsCalculate Jupiter's coordinates:
jupiterEC1 :: EquatorialCoordinates1jupiterEC1 = jupiterPosition (lctUniversalTime dt)-- EC1 {e1Declination = DD (-4.104626810672402), e1RightAscension = DH 12.863365504382228}jupiterHC :: HorizonCoordinatesjupiterHC = ec1ToHC ro (lctUniversalTime dt) jupiterEC1-- HC {hAltitude = DD (-30.67914598469227), hAzimuth = DD 52.29376845044007}As be can see Jupiter is below the horizon now (the altitude is negative), that's unfortunate.
Now let us calculate distance to Jupiter:
jupiterDistance :: AstronomicalUnitsjupiterDistance = planetDistance1 jupiterDetails earthDetails (lctUniversalTime dt)-- AU 5.1934358725210391 Astronomical Unit is an average distance from the Earth to the Sun.
and calculate an angular size now:
jupiterAngularSize :: DecimalDegreesjupiterAngularSize = planetAngularDiameter jupiterDetails jupiterDistance-- DD 1.052289877865987e-2toDMS jupiterAngularSize-- (0,0,37.88243560317554)Calculate rise and set times of planets are not easy task, because planets change their equatorial coordinates during the day.
riseAndSet2 function ofData.Astro.CelestialObject.RiseSet module applies iterative approach: calculates rise and set date for midday coordinates and then recalculates rise time for rise coordinates and set for set coordinates obtained from the previous step:
verticalShift :: DecimalDegreesverticalShift = refract (DD 0) 12 1012-- DD 0.5660098245614035jupiterRiseSet :: RiseSetMBjupiterRiseSet = riseAndSet2 0.000001 jupiterPosition ro verticalShift today-- RiseSet-- (Just (2017-06-25 13:53:27.3109 +1.0,DD 95.88943953535569))-- (Just (2017-06-25 01:21:23.5835 +1.0,DD 264.1289033612776))We can see now why at 10 am Jupiter is below horizon because it will rise only at 1:53 pm.
Some examples of doing the Sun's related calculations:
import Data.Astro.Time.JulianDateimport Data.Astro.Coordinateimport Data.Astro.Typesimport Data.Astro.Sunro :: GeographicCoordinatesro = GeoC (fromDMS 51 28 40) (-(fromDMS 0 0 5))dt :: LocalCivilTimedt = lctFromYMDHMS (DH 1) 2017 6 25 10 29 0today :: LocalCivilDatetoday = lcdFromYMD (DH 1) 2017 6 25jd :: JulianDatejd = lctUniversalTime dtverticalShift :: DecimalDegreesverticalShift = refract (DD 0) 12 1012-- distance from the Earth to the Sun in kilometresdistance :: Doubledistance = sunDistance jd-- 1.5206375976421073e8-- Angular SizeangularSize :: DecimalDegreesangularSize = sunAngularSize jd-- DD 0.5244849215333616-- The Sun's coordinatesec1 :: EquatorialCoordinates1ec1 = sunPosition2 jd-- EC1 {e1Declination = DD 23.37339098989099, e1RightAscension = DH 6.29262026252748}hc :: HorizonCoordinateshc = ec1ToHC ro jd ec1-- HC {hAltitude = DD 49.312050979507404, hAzimuth = DD 118.94723825710143}-- Rise and SetriseSet :: RiseSetMBriseSet = sunRiseAndSet ro 0.833333 today-- RiseSet-- (Just (2017-06-25 04:44:04.3304 +1.0,DD 49.043237261724215))-- (Just (2017-06-25 21:21:14.4565 +1.0,DD 310.91655607595595))The Moon's related calculations.Data.Astro.Moon module defines 2 new types of functions we haven't seen before:moonPhase andmoonBrightLimbPositionAngle which calculate the phase (the area of the visible segment expressed as a fraction of the whole disk) and the position-angle which is the angle of the midpoint of the illuminated limb measured eastwards from the north point of the disk.
import Data.Astro.Time.JulianDateimport Data.Astro.Coordinateimport Data.Astro.Typesimport Data.Astro.Effectsimport Data.Astro.CelestialObject.RiseSetimport Data.Astro.Moonro :: GeographicCoordinatesro = GeoC (fromDMS 51 28 40) (-(fromDMS 0 0 5))dt :: LocalCivilTimedt = lctFromYMDHMS (DH 1) 2017 6 25 10 29 0today :: LocalCivilDatetoday = lcdFromYMD (DH 1) 2017 6 25jd :: JulianDatejd = lctUniversalTime dt-- distance from the Earth to the Moon in kilometresmdu :: MoonDistanceUnitsmdu = moonDistance1 j2010MoonDetails jd-- MDU 0.9550170577020396distance :: Doubledistance = mduToKm mdu-- 367109.51199772174-- Angular SizeangularSize :: DecimalDegreesangularSize = moonAngularSize mdu-- DD 0.5425033990980761-- The Moon's coordinatesposition :: JulianDate -> EquatorialCoordinates1position = moonPosition1 j2010MoonDetailsec1 :: EquatorialCoordinates1ec1 = position jd-- EC1 {e1Declination = DD 18.706180658927323, e1RightAscension = DH 7.56710547682055}hc :: HorizonCoordinateshc = ec1ToHC ro jd ec1-- HC {hAltitude = DD 34.57694951316064, hAzimuth = DD 103.91119101451832}-- Rise and SetriseSet :: RiseSetMBriseSet = riseAndSet2 0.000001 position ro verticalShift today-- RiseSet-- (Just (2017-06-25 06:22:51.4858 +1.0,DD 57.81458864497365))-- (Just (2017-06-25 22:28:20.3023 +1.0,DD 300.4168238905249))-- Phasephase :: Doublephase = moonPhase j2010MoonDetails jd-- 2.4716141948212922e-2sunEC1 :: EquatorialCoordinates1sunEC1 = sunPosition2 jd-- EC1 {e1Declination = DD 23.37339098989099, e1RightAscension = DH 6.29262026252748}limbAngle :: DecimalDegreeslimbAngle = moonBrightLimbPositionAngle ec1 sunEC1-- DD 287.9869373767473