From 29568e2cc3150c634132398b40f261f7740c029a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 28 May 2023 15:11:21 +0200 Subject: [PATCH 01/46] WIP: remove JLD dependency --- Artifacts.toml | 16 --- Project.toml | 2 - dev/generate_artifacts.jl | 18 ++- src/NEOs.jl | 40 +++--- src/observations/jpl_eph.jl | 24 ++-- src/observations/process_radar.jl | 82 ++++++------ src/observations/process_radec.jl | 200 +++++++++++++++--------------- 7 files changed, 179 insertions(+), 203 deletions(-) diff --git a/Artifacts.toml b/Artifacts.toml index da10c0f2..2590f438 100644 --- a/Artifacts.toml +++ b/Artifacts.toml @@ -1,11 +1,3 @@ -[TTmTDBde430] -git-tree-sha1 = "de3fba2237359dc941a057d492c305afeccba133" -lazy = true - - [[TTmTDBde430.download]] - sha256 = "c599efe597200055c27cec38ddc769f5d3b3e301a481b9dcd8b9640d745508a1" - url = "https://raw.githubusercontent.com/PerezHz/jpleph/main/TTmTDBde430.tar.gz" - [a99942] git-tree-sha1 = "7cdf1265a22c52329651c4a71a9835d1b90f568e" lazy = true @@ -69,11 +61,3 @@ lazy = true [[sseph_p100.download]] sha256 = "7a5886729bbd85d68417f8d69fb2d7e8f4390376a49c9bcda1b580116f8ed11b" url = "https://github.com/LuEdRaMo/sseph/raw/main/sseph343ast016_p100y_et.tar.gz" - -[ttmtdb_DE430_1995_2030] -git-tree-sha1 = "9e0c56a8987df7426aad09829332f04b014e6264" -lazy = true - - [[ttmtdb_DE430_1995_2030.download]] - sha256 = "19f2a3136a81755746795466b4d4d01bfd962b5b1f6f877af0377a21126d99e1" - url = "https://raw.githubusercontent.com/PerezHz/jpleph/main/ttmtdb_DE430_1995_2030_20221103.tar.gz" diff --git a/Project.toml b/Project.toml index 38e402b9..ba31a104 100644 --- a/Project.toml +++ b/Project.toml @@ -17,7 +17,6 @@ Healpix = "9f4e344d-96bc-545a-84a3-ae6b9e1b672b" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" IntervalArithmetic = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253" IntervalRootFinding = "d2bf35a9-74e0-55ec-b149-d360ff49b807" -JLD = "4138dd39-2aa7-5051-a626-17a0bb65d9c8" JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" LazyArtifacts = "4af54fe1-eca0-43a8-85a7-787d91b784e3" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" @@ -44,7 +43,6 @@ HTTP = "1.9.5" Healpix = "4" IntervalArithmetic = "0.20" IntervalRootFinding = "0.5.11" -JLD = "0.13" JLD2 = "0.4" PlanetaryEphemeris = "0.6" Quadmath = "0.5" diff --git a/dev/generate_artifacts.jl b/dev/generate_artifacts.jl index e7634047..8996f1f8 100644 --- a/dev/generate_artifacts.jl +++ b/dev/generate_artifacts.jl @@ -1,7 +1,7 @@ # This script generates Julia artifacts for NEOs.jl, including # - debiasing tables from Chesley et al. (2010), Farnocchia et al. (2015) and Eggl et al. (2020) -# - JPL lsk and spk -# - PlanetaryEphemeris.jl Solar System ephemeris +# - JPL lsk and spk +# - PlanetaryEphemeris.jl Solar System ephemeris # TO DO: adapt script for julia1.6+ # TO DO: adapt script for 2010 debiasing tables (requires extra unpacking) @@ -16,28 +16,26 @@ Pkg.PlatformEngines.probe_platform_engines!() # This is the path to the Artifacts.toml we will manipulate const artifact_toml = joinpath(dirname(@__DIR__), "Artifacts.toml") -# JPL FTP URL +# JPL FTP URL const ftp_jpl = "ftp://ssd.jpl.nasa.gov/pub/ssd/debias/" -# Debiasing tables names and URLs +# Debiasing tables names and URLs const names_debias = ["debias", "debias_2014", "debias_2018", "debias_hires2018"] const urls_debias = ftp_jpl .* names_debias .* ".tgz" -# JPL lsk and spk names and URLs -const names_lsk_spk = ["naif0012", "de430", "TTmTDBde430", "a99942", "ttmtdb_DE430_1995_2030"] +# JPL lsk and spk names and URLs +const names_lsk_spk = ["naif0012", "de430", "a99942"] const urls_lsk_spk = [ "https://raw.githubusercontent.com/PerezHz/jpleph/main/naif0012.tar.gz", "https://raw.githubusercontent.com/PerezHz/jpleph/main/de430.tar.gz", - "https://raw.githubusercontent.com/PerezHz/jpleph/main/TTmTDBde430.tar.gz", "https://raw.githubusercontent.com/PerezHz/jpleph/main/a99942.tar.gz", - "https://raw.githubusercontent.com/PerezHz/jpleph/main/ttmtdb_DE430_1995_2030_20221103.tar.gz" ] -# PlanetaryEphemeris.jl Solar System ephemeris name and URL +# PlanetaryEphemeris.jl Solar System ephemeris name and URL const name_sseph = "sseph_p100" const url_sseph = "https://github.com/LuEdRaMo/sseph/raw/main/sseph343ast016_p100y_et.tar.gz" -# Collect names and URLs +# Collect names and URLs const urls_ = vcat(urls_lsk_spk, urls_debias, url_sseph) const names_ = vcat(names_lsk_spk, names_debias, name_sseph) diff --git a/src/NEOs.jl b/src/NEOs.jl index 0ac67c72..b7a4e577 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -6,54 +6,54 @@ import Base: hash, ==, show, isless, isnan, convert import ReferenceFrameRotations: orthonormalize import PlanetaryEphemeris, SatelliteToolbox -using Distributed, JLD, JLD2, TaylorIntegration, Printf, DelimitedFiles, Test, LinearAlgebra, +using Distributed, JLD2, TaylorIntegration, Printf, DelimitedFiles, Test, LinearAlgebra, Dates, EarthOrientation, SPICE, Quadmath, LazyArtifacts, DataFrames, TaylorSeries, InteractiveUtils, AutoHashEquals -using PlanetaryEphemeris: daysec, su, ea, α_p_sun, δ_p_sun, t2c_jpl_de430, pole_rotation, - au, c_au_per_day, R_sun, c_cm_per_sec, c_au_per_sec, yr, RE, TaylorInterpolant, Rx, - Ry, Rz, semimajoraxis, eccentricity, inclination, longascnode, argperi, timeperipass, +using PlanetaryEphemeris: daysec, su, ea, α_p_sun, δ_p_sun, t2c_jpl_de430, pole_rotation, + au, c_au_per_day, R_sun, c_cm_per_sec, c_au_per_sec, yr, RE, TaylorInterpolant, Rx, + Ry, Rz, semimajoraxis, eccentricity, inclination, longascnode, argperi, timeperipass, nbodyind, PE, ordpres_differentiate, numberofbodies, kmsec2auday using Healpix: ang2pixRing, Resolution -using SatelliteToolbox: nutation_fk5, J2000toGMST, rECEFtoECI, get_ΔAT, JD_J2000, EOPData_IAU1980, +using SatelliteToolbox: nutation_fk5, J2000toGMST, rECEFtoECI, get_ΔAT, JD_J2000, EOPData_IAU1980, rECItoECI, DCM, TOD, GCRF, ITRF, rECItoECI, PEF, satsv, EOPData_IAU2000A, get_iers_eop_iau_1980, get_iers_eop_iau_2000A using StaticArrays: SVector, SArray, @SVector -using Dates: format +using Dates: format using HTTP: get -using IntervalRootFinding: roots, interval, Interval, mid +using IntervalRootFinding: roots, interval, Interval, mid # Constants export d_EM_km, d_EM_au # CatalogueMPC -export unknowncat, isunknown, read_catalogues_mpc, parse_catalogues_mpc, write_catalogues_mpc, update_catalogues_mpc, +export unknowncat, isunknown, read_catalogues_mpc, parse_catalogues_mpc, write_catalogues_mpc, update_catalogues_mpc, search_cat_code -# ObservatoryMPC -export unknownobs, hascoord, read_observatories_mpc, parse_observatories_mpc, write_observatories_mpc, +# ObservatoryMPC +export unknownobs, hascoord, read_observatories_mpc, parse_observatories_mpc, write_observatories_mpc, update_observatories_mpc, search_obs_code # RadecMPC -export num, tmpdesig, discovery, publishnote, obstech, ra, dec, info1, mag, band, catalogue, info2, observatory, +export num, tmpdesig, discovery, publishnote, obstech, ra, dec, info1, mag, band, catalogue, info2, observatory, read_radec_mpc, parse_radec_mpc, search_circulars_mpc, write_radec_mpc # RadarJPL -export hasdelay, hasdoppler, ismonostatic, date, delay, delay_sigma, delay_units, doppler, doppler_sigma, +export hasdelay, hasdoppler, ismonostatic, date, delay, delay_sigma, delay_units, doppler, doppler_sigma, doppler_units, freq, rcvr, xmit, bouncepoint, read_radar_jpl, write_radar_jpl -# Units +# Units export julian2etsecs, etsecs2julian, datetime2et, et_to_200X, days_to_200X, datetime_to_200X, datetime2days, days2datetime, rad2arcsec, arcsec2rad, mas2rad -# JPL Ephemerides +# JPL Ephemerides export loadjpleph, sunposvel, earthposvel, moonposvel, apophisposvel197, apophisposvel199, loadpeeph -# Osculating +# Osculating export pv2kep, yarkp2adot # Topocentric export obs_pos_ECEF, obsposvelECI, t2c_rotation_iau_76_80 -# Process radec +# Process radec export compute_radec, debiasing, w8sveres17, radec_astrometry, residuals -# Process radar +# Process radar export compute_delay, radar_astrometry -# Gauss method +# Gauss method export gauss_method -# Asteroid dynamical models +# Asteroid dynamical models export RNp1BP_pN_A_J23E_J2S_ng_eph!, RNp1BP_pN_A_J23E_J2S_ng_eph_threads!, RNp1BP_pN_A_J23E_J2S_eph_threads! -# Propagate +# Propagate export propagate, propagate_lyap, propagate_root, save2jldandcheck export valsecchi_circle, nrms, chi2, newtonls, newtonls_6v, diffcorr, newtonls_Q, bopik diff --git a/src/observations/jpl_eph.jl b/src/observations/jpl_eph.jl index 14d68a01..6e3afa9b 100644 --- a/src/observations/jpl_eph.jl +++ b/src/observations/jpl_eph.jl @@ -1,9 +1,7 @@ -# Load TT-TDB (ttmtdb) as a TaylorInterpolant saved in .jld file -const ttmtdb_artifact_path = joinpath(artifact"ttmtdb_DE430_1995_2030", "ttmtdb_DE430_1995_2030_20221103.jld") -const ttmtdb_t0 = JLD.load(ttmtdb_artifact_path, "t0") -const ttmtdb_t = JLD.load(ttmtdb_artifact_path, "t") -const ttmtdb_x_coeffs = JLD.load(ttmtdb_artifact_path, "x_coeffs") -const ttmtdb = TaylorInterpolant(ttmtdb_t0, ttmtdb_t, Taylor1.(ttmtdb_x_coeffs)) +# Load TT-TDB (ttmtdb) from jld2 file +const peeph_artifact_path = joinpath(artifact"sseph_p100", "sseph343ast016_p100y_et.jld2") +const peeph = JLD2.load(peeph_artifact_path, "ss16ast_eph") +const ttmtdb = TaylorInterpolant(peeph.t0, peeph.t, peeph.x[:,end]) @doc raw""" loadjpleph() @@ -16,8 +14,6 @@ function loadjpleph() furnsh( # NAIF IDs joinpath(artifact"naif0012", "naif0012.tls"), - # JPL DE430 TT-TDB - joinpath(artifact"TTmTDBde430", "TTmTDB.de430.19feb2015.bsp"), # JPL DE430 ephemerides joinpath(artifact"de430", "de430_1850-2150.bsp"), # JPL #197 solution for Apophis @@ -128,15 +124,15 @@ dtt_tdb(et) = getposvel(1000000001, 1000000000, cte(et))[4] # units: seconds/sec Load Solar System ephemeris produced by `PlanetaryEphemeris.jl` from Jan 1st 2000 up to `et > 0` [ephemeris seconds since J2000]. -**Caution**: running this function for the first time will download the `sseph_p100` artifact (∼554 MB) which can take several minutes. +**Caution**: running this function for the first time will download the `sseph_p100` artifact (∼554 MB) which can take several minutes. """ function loadpeeph(et::Union{Nothing, Real} = nothing) - # Load Solar System 2000-2100 ephemeris + # Load Solar System 2000-2100 ephemeris eph = JLD2.load(joinpath(artifact"sseph_p100", "sseph343ast016_p100y_et.jld2"), "ss16ast_eph") if isnothing(et) - return eph - else + return eph + else idxs = findall(x -> x <= et, eph.t) return TaylorInterpolant(eph.t0, eph.t[idxs], eph.x[idxs[1:end-1], :]) - end -end \ No newline at end of file + end +end \ No newline at end of file diff --git a/src/observations/process_radar.jl b/src/observations/process_radar.jl index 7ba36d03..132eb770 100644 --- a/src/observations/process_radar.jl +++ b/src/observations/process_radar.jl @@ -240,9 +240,9 @@ function tropo_delay(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Numbe end @doc raw""" - compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, t_offset::Real, niter::Int = 10; eo::Bool = true, + compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, t_offset::Real, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, xva = apophisposvel197) where {T <: AbstractFloat} - compute_delay(radar::RadarJPL{T}, t_offset::Real, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, + compute_delay(radar::RadarJPL{T}, t_offset::Real, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, xva = apophisposvel197) where {T <: AbstractFloat} Compute radar-astrometric round-trip time (``\mu``s). @@ -253,7 +253,7 @@ See https://doi.org/10.1086/116062. - `observatory::ObservatoryMPC{T}`: observing station. - `t_r_utc::DateTime`: UTC time of echo reception. -- `radar::RadarJPL{T}`: radar observation. +- `radar::RadarJPL{T}`: radar observation. - `t_offset::Real`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). - `niter::Int`: number of light-time solution iterations. - `eo::Bool`: compute corrections due to Earth orientation, LOD, polar motion. @@ -261,7 +261,7 @@ See https://doi.org/10.1086/116062. - `xvs`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ -function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, t_offset::Real, niter::Int = 10; eo::Bool = true, +function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, t_offset::Real, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, xva = apophisposvel197) where {T <: AbstractFloat} # Transform receiving time from UTC to TDB seconds since j2000 et_r_secs = datetime2et(t_r_utc) + t_offset @@ -460,15 +460,15 @@ function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, t_offs # Total signal delay (μs) return 1e6τ end -function compute_delay(radar::RadarJPL{T}, t_offset::Real, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, +function compute_delay(radar::RadarJPL{T}, t_offset::Real, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, xva = apophisposvel197) where {T <: AbstractFloat} return compute_delay(radar.rcvr, radar.date, t_offset, niter; eo = eo, xve = xve, xvs = xvs, xva = xva) -end +end @doc raw""" - compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 10; eo::Bool = true, xve::TaylorInterpolant = earthposvel, + compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 10; eo::Bool = true, xve::TaylorInterpolant = earthposvel, xvs::TaylorInterpolant = sunposvel, xva::TaylorInterpolant = apophisposvel197, tord::Int = xva.x[1].order) where {T <: AbstractFloat} - compute_delay(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, xve::TaylorInterpolant = earthposvel, + compute_delay(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, xve::TaylorInterpolant = earthposvel, xvs::TaylorInterpolant = sunposvel, xva::TaylorInterpolant = apophisposvel197, tord::Int = xva.x[1].order) where {T <: AbstractFloat} Compute Taylor series expansion of time-delay observable around echo reception time. This @@ -487,7 +487,7 @@ See https://doi.org/10.1086/116062. - `observatory::ObservatoryMPC{T}`: observing station. - `t_r_utc::DateTime`: UTC time of echo reception. -- `radar::RadarJPL{T}`: radar observation. +- `radar::RadarJPL{T}`: radar observation. - `niter::Int`: number of light-time solution iterations. - `eo::Bool`: compute corrections due to Earth orientation, LOD, polar motion. - `xve::TaylorInterpolant`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. @@ -495,7 +495,7 @@ See https://doi.org/10.1086/116062. - `xva::TaylorInterpolant`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `tord::Int`: order of Taylor expansions. """ -function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 10; eo::Bool = true, xve::TaylorInterpolant = earthposvel, +function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 10; eo::Bool = true, xve::TaylorInterpolant = earthposvel, xvs::TaylorInterpolant = sunposvel, xva::TaylorInterpolant = apophisposvel197, tord::Int = xva.x[1].order) where {T <: AbstractFloat} # Auxiliary to evaluate JT ephemeris @@ -695,19 +695,19 @@ function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter: return 1e6τ end -function compute_delay(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, xve::TaylorInterpolant = earthposvel, +function compute_delay(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, xve::TaylorInterpolant = earthposvel, xvs::TaylorInterpolant = sunposvel, xva::TaylorInterpolant = apophisposvel197, tord::Int = xva.x[1].order) where {T <: AbstractFloat} return compute_delay(radar.rcvr, radar.date, niter; eo = eo, xve = xve, xvs = xvs, xva = xva, tord = tord) -end +end @doc raw""" radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real, niter::Int = 10; eo::Bool = true, tc::Real = 1.0, xve = earthposvel, xvs = sunposvel, xva = apophisposvel197, autodiff::Bool = true, tord::Int = 10) where {T <: AbstractFloat} - radar_astrometry(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, tc::Real = 1.0, xve = earthposvel, + radar_astrometry(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, tc::Real = 1.0, xve = earthposvel, xvs = sunposvel, xva = apophisposvel197, autodiff::Bool = true, tord::Int = 10) where {T <: AbstractFloat} - radar_astrometry(astradarfile::String, niter::Int = 10; eo::Bool = true, tc::Real = 1.0, xve = earthposvel, xvs = sunposvel, + radar_astrometry(astradarfile::String, niter::Int = 10; eo::Bool = true, tc::Real = 1.0, xve = earthposvel, xvs = sunposvel, xva = apophisposvel197, autodiff::Bool = true, tord::Int=10) - radar_astrometry(outfilename::String, radarobsfile::String, asteph::TaylorInterpolant, ss16asteph::TaylorInterpolant; tc::Real=1.0, autodiff::Bool=true, + radar_astrometry(outfilename::String, radarobsfile::String, asteph::TaylorInterpolant, ss16asteph::TaylorInterpolant; tc::Real=1.0, autodiff::Bool=true, tord::Int=10, niter::Int=5) Return time-delay and Doppler shift. @@ -716,9 +716,9 @@ Return time-delay and Doppler shift. - `observatory::ObservatoryMPC{T}`: observing station. - `t_r_utc::DateTime`: UTC time of echo reception. -- `radar::RadarJPL{T}`: radar observation. -- `astradarfile/radarobsfile::String`: file where to retrieve radar observations. -- `outfilename::String`: file where to save radar observations. +- `radar::RadarJPL{T}`: radar observation. +- `astradarfile/radarobsfile::String`: file where to retrieve radar observations. +- `outfilename::String`: file where to save radar observations. - `F_tx::Real`: transmitter frequency (MHz). - `niter::Int`: number of light-time solution iterations. - `eo::Bool`: wheter to use `EarthOrientation` or not. @@ -726,8 +726,8 @@ Return time-delay and Doppler shift. - `xve`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xvs`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `asteph::TaylorInterpolant`: asteroid's ephemeris. -- `ss16asteph::TaylorInterpolant`: solar system ephemeris. +- `asteph::TaylorInterpolant`: asteroid's ephemeris. +- `ss16asteph::TaylorInterpolant`: solar system ephemeris. - `autodiff::Bool`: whether to use the automatic differentiation method of [`compute_delay`](@ref) or not. - `tord::Int`: order of Taylor expansions. """ @@ -751,15 +751,15 @@ function radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_t end -function radar_astrometry(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, tc::Real = 1.0, xve = earthposvel, +function radar_astrometry(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, tc::Real = 1.0, xve = earthposvel, xvs = sunposvel, xva = apophisposvel197, autodiff::Bool = true, tord::Int = 10) where {T <: AbstractFloat} return radar_astrometry(radar.rcvr, radar.date, radar.freq, niter; eo = eo, tc = tc, xve = xve, xvs = xvs, xva = xva, autodiff = autodiff, tord = tord) -end +end function radar_astrometry(astradarfile::String, niter::Int=10; eo::Bool=true, tc::Real=1.0, xve=earthposvel, xvs=sunposvel, xva=apophisposvel197, autodiff::Bool=true, tord::Int=10) - # Check that astradarfile is a file + # Check that astradarfile is a file @assert isfile(astradarfile) "Cannot open file: $astradarfile" # Read radar measurements astradardata = read_radar_jpl(astradarfile) @@ -770,7 +770,7 @@ function radar_astrometry(astradarfile::String, niter::Int=10; eo::Bool=true, tc et1 = datetime2et(utc1) # Asteroid ephemeris at et1 a1_et1 = xva(et1)[1] - # Type of asteroid ephemeris + # Type of asteroid ephemeris S = typeof(a1_et1) # Time delays @@ -788,7 +788,7 @@ function radar_astrometry(astradarfile::String, niter::Int=10; eo::Bool=true, tc delay_index = map(x-> x.Δτ_units == "us", astradardata) # Rows with Doppler shifts doppler_index = map(x -> x.Δν_units == "Hz", astradardata) - + dt_utc_obs = date.(astradardata) # UTC time Δτ_obs = delay.(astradardata) # Observed time delay Δν_obs = doppler.(astradardata) # Observed Doppler shift @@ -798,18 +798,18 @@ function radar_astrometry(astradarfile::String, niter::Int=10; eo::Bool=true, tc ν_units = doppler_units.(astradardata) # Doppler shift units freq_ = freq.(astradardata) # Frequency rcvr_ = rcvr.(astradardata) # Reciever antenna - xmit_ = xmit.(astradardata) # Emission antenna + xmit_ = xmit.(astradardata) # Emission antenna bouncepoint_ = bouncepoint.(astradardata) # Bounce point # Return time delays / Doppler shifts table return dt_utc_obs, Δτ_obs, Δν_obs, vdelay, vdoppler, Δτ_σ, Δν_σ, τ_units, ν_units, freq_, rcvr_, xmit_, bouncepoint_, delay_index, - doppler_index + doppler_index end @doc raw""" - radar_astrometry_yeomansetal92(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real, niter::Int = 10; eo::Bool = true, + radar_astrometry_yeomansetal92(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, xva = apophisposvel197) where {T <: AbstractFloat} - radar_astrometry_yeomansetal92(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, + radar_astrometry_yeomansetal92(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, xva = apophisposvel197) where {T <: AbstractFloat} Compute round-trip time (in ``\mu``s) and Doppler shift (Hz) radar astrometry. Dopplers are computed following https://doi.org/10.1086/116062. @@ -818,7 +818,7 @@ Compute round-trip time (in ``\mu``s) and Doppler shift (Hz) radar astrometry. D - `observatory::ObservatoryMPC{T}`: observing station. - `t_r_utc::DateTime`: UTC time of echo reception. -- `radar::RadarJPL{T}`: radar observation. +- `radar::RadarJPL{T}`: radar observation. - `F_tx::Real`: transmitter frequency (MHz). - `niter::Int`: number of light-time solution iterations. - `eo::Bool`: wheter to use `EarthOrientation` or not. @@ -826,7 +826,7 @@ Compute round-trip time (in ``\mu``s) and Doppler shift (Hz) radar astrometry. D - `xvs`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ -function radar_astrometry_yeomansetal92(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real, niter::Int = 10; eo::Bool = true, +function radar_astrometry_yeomansetal92(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, xva = apophisposvel197) where {T <: AbstractFloat} # Transform receiving time from UTC to TDB seconds since j2000 et_r_secs = datetime2et(t_r_utc) @@ -1071,28 +1071,28 @@ function radar_astrometry_yeomansetal92(observatory::ObservatoryMPC{T}, t_r_utc: return 1e6τ, 1e6ν end -function radar_astrometry_yeomansetal92(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, +function radar_astrometry_yeomansetal92(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, xva = apophisposvel197) where {T <: AbstractFloat} return radar_astrometry_yeomansetal92(radar.observatory, radar.date, radar.freq, niter, eo = eo, xve = xve, xvs = xvs, xva = xva) -end +end -function radar_astrometry(outfilename::String, radarobsfile::String, asteph::TaylorInterpolant, ss16asteph::TaylorInterpolant; +function radar_astrometry(outfilename::String, radarobsfile::String, asteph::TaylorInterpolant, ss16asteph::TaylorInterpolant; tc::Real = 1.0, autodiff::Bool = true, tord::Int = 10, niter::Int = 5) - # Check that radarobsfile is a file + # Check that radarobsfile is a file @assert isfile(radarobsfile) "Cannot open file: $radarobsfile" radar = read_radar_jpl(radarobsfile) # Check that first and last observation times are within interpolation interval - Δt_0 = datetime2julian(radar[1].date) - JD_J2000 - asteph.t0 + Δt_0 = datetime2julian(radar[1].date) - JD_J2000 - asteph.t0 Δt_f = datetime2julian(radar[end].date) - JD_J2000 - asteph.t0 - t_min, t_max = minmax(asteph.t[1], asteph.t[end]) + t_min, t_max = minmax(asteph.t[1], asteph.t[end]) @assert t_min ≤ Δt_0 ≤ Δt_f ≤ t_max "First and/or last observation times are outside interpolation interval" - # Number of massive bodies + # Number of massive bodies Nm1 = (size(ss16asteph.x)[2]-13) ÷ 6 # Number of bodies, including NEA N = Nm1 + 1 - + # NEO # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec asteph_ord = asteph.x[1].order @@ -1126,8 +1126,8 @@ function radar_astrometry(outfilename::String, radarobsfile::String, asteph::Tay # Save data to file println("Saving data to file: $outfilename") JLD2.jldopen(outfilename, "w") do file - # Write variables to jld file - JLD.write(file, + # Write variables to jld2 file + JLD2.write(file, "dt_utc_obs", dt_utc_obs, "Δτ_obs", Δτ_obs, "Δν_obs", Δν_obs, diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index cc09439e..c49457f5 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -1,14 +1,14 @@ @doc raw""" - compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 10; eo::Bool = true, + compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 10; eo::Bool = true, xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} - compute_radec(obs::RadecMPC{T}, niter::Int = 10; eo::Bool = true, xve::Function = earthposvel, xvs::Function = sunposvel, - xva::Function = apophisposvel197) where {T <: AbstractFloat} - compute_radec(obs::Vector{RadecMPC{T}}, niter::Int=10; eo::Bool=true, xve::Function=earthposvel, xvs::Function=sunposvel, + compute_radec(obs::RadecMPC{T}, niter::Int = 10; eo::Bool = true, xve::Function = earthposvel, xvs::Function = sunposvel, + xva::Function = apophisposvel197) where {T <: AbstractFloat} + compute_radec(obs::Vector{RadecMPC{T}}, niter::Int=10; eo::Bool=true, xve::Function=earthposvel, xvs::Function=sunposvel, xva::Function=apophisposvel197) where {T <: AbstractFloat} Compute astrometric right ascension and declination (both in arcsec) for a set of MPC-formatted observations. -# Arguments +# Arguments - `observatory::ObservatoryMPC{T}`: observation site. - `t_r_utc::DateTime`: UTC time of astrometric observation. @@ -19,7 +19,7 @@ Compute astrometric right ascension and declination (both in arcsec) for a set o - `xvs::Function`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xva::Function`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ -function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 10; eo::Bool = true, +function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 10; eo::Bool = true, xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} # Transform receiving time from UTC to TDB seconds since J2000 et_r_secs = datetime2et(t_r_utc) @@ -40,21 +40,21 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter: # Sun barycentric position and velocity at receive time rv_s_t_r = xvs(et_r_secs) r_s_t_r = rv_s_t_r[1:3] - + # Down-leg iteration # τ_D first approximation # See equation (1) of https://doi.org/10.1086/116062 ρ_vec_r = r_a_t_r - r_r_t_r ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) # -R_b/c, but delay is wrt asteroid Center (Brozovic et al., 2018) - τ_D = ρ_r/clightkms # (seconds) + τ_D = ρ_r/clightkms # (seconds) # Bounce time, new estimate # See equation (2) of https://doi.org/10.1086/116062 et_b_secs = et_r_secs - τ_D - # Allocate memmory for time-delays + # Allocate memmory for time-delays Δτ_D = zero(τ_D) # Total time delay - Δτ_rel_D = zero(τ_D) # Shapiro delay + Δτ_rel_D = zero(τ_D) # Shapiro delay # Δτ_corona_D = zero(τ_D) # Delay due to Solar corona Δτ_tropo_D = zero(τ_D) # Delay due to Earth's troposphere @@ -63,7 +63,7 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter: rv_a_t_b = xva(et_b_secs) r_a_t_b = rv_a_t_b[1:3] v_a_t_b = rv_a_t_b[4:6] - # Estimated position of the asteroid's center of mass relative to the recieve point + # Estimated position of the asteroid's center of mass relative to the recieve point # See equation (3) of https://doi.org/10.1086/116062 ρ_vec_r = r_a_t_b - r_r_t_r # Magnitude of ρ_vec_r @@ -71,22 +71,22 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter: ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) # Compute down-leg Shapiro delay - # NOTE: when using PPN, substitute 2 -> 1+γ in expressions for Shapiro delay, + # NOTE: when using PPN, substitute 2 -> 1+γ in expressions for Shapiro delay, # Δτ_rel_[D|U] # Earth's position at t_r e_D_vec = r_r_t_r - r_s_t_r # Heliocentric distance of Earth at t_r - e_D = sqrt(e_D_vec[1]^2 + e_D_vec[2]^2 + e_D_vec[3]^2) + e_D = sqrt(e_D_vec[1]^2 + e_D_vec[2]^2 + e_D_vec[3]^2) # Barycentric position of Sun at estimated bounce time - rv_s_t_b = xvs(et_b_secs) + rv_s_t_b = xvs(et_b_secs) r_s_t_b = rv_s_t_b[1:3] # Heliocentric position of asteroid at t_b p_D_vec = r_a_t_b - r_s_t_b # Heliocentric distance of asteroid at t_b - p_D = sqrt(p_D_vec[1]^2 + p_D_vec[2]^2 + p_D_vec[3]^2) + p_D = sqrt(p_D_vec[1]^2 + p_D_vec[2]^2 + p_D_vec[3]^2) # Signal path distance (down-leg) - q_D = ρ_r + q_D = ρ_r # Shapiro correction to time-delay Δτ_rel_D = shapiro_delay(e_D, p_D, q_D) # seconds @@ -97,13 +97,13 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter: # Total time-delay Δτ_D = Δτ_rel_D # + Δτ_tropo_D #+ Δτ_corona_D # seconds - # New estimate + # New estimate p_dot_23 = dot(ρ_vec_r, v_a_t_b)/ρ_r # Time delay correction Δt_2 = (τ_D - ρ_r/clightkms - Δτ_rel_D)/(1.0-p_dot_23/clightkms) - # Time delay new estimate + # Time delay new estimate τ_D = τ_D - Δt_2 - # Bounce time, new estimate + # Bounce time, new estimate # See equation (2) of https://doi.org/10.1086/116062 et_b_secs = et_r_secs - τ_D end @@ -111,7 +111,7 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter: rv_a_t_b = xva(et_b_secs) r_a_t_b = rv_a_t_b[1:3] v_a_t_b = rv_a_t_b[4:6] - # Estimated position of the asteroid's center of mass relative to the recieve point + # Estimated position of the asteroid's center of mass relative to the recieve point # See equation (3) of https://doi.org/10.1086/116062 ρ_vec_r = r_a_t_b - r_r_t_r # Magnitude of ρ_vec_r @@ -127,17 +127,17 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter: U_norm = ρ_r # sqrt(U_vec[1]^2 + U_vec[2]^2 + U_vec[3]^2) u_vec = U_vec/U_norm # Barycentric position and velocity of Sun at converged bounce time - rv_s_t_b = xvs(et_b_secs) + rv_s_t_b = xvs(et_b_secs) r_s_t_b = rv_s_t_b[1:3] Q_vec = r_a_t_b - r_s_t_b # ESAA 2014, equation (7.113) q_vec = Q_vec/sqrt(Q_vec[1]^2 + Q_vec[2]^2 + Q_vec[3]^2) E_H = sqrt(E_H_vec[1]^2 + E_H_vec[2]^2 + E_H_vec[3]^2) e_vec = E_H_vec/E_H # See ESAA 2014, equation (7.115) - g1 = (2μ_DE430[su]/(c_au_per_day^2))/(E_H/au) + g1 = (2μ_DE430[su]/(c_au_per_day^2))/(E_H/au) g2 = 1 + dot(q_vec, e_vec) # See ESAA 2014, equation (7.116) - u1_vec = U_norm*( u_vec + (g1/g2)*( dot(u_vec,q_vec)*e_vec - dot(e_vec,u_vec)*q_vec ) ) + u1_vec = U_norm*( u_vec + (g1/g2)*( dot(u_vec,q_vec)*e_vec - dot(e_vec,u_vec)*q_vec ) ) u1_norm = sqrt(u1_vec[1]^2 + u1_vec[2]^2 + u1_vec[3]^2) # Compute right ascension, declination angles @@ -151,14 +151,14 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter: return α_as, δ_as # right ascension, declination both in arcsec end -function compute_radec(obs::RadecMPC{T}, niter::Int = 10; eo::Bool = true, xve::Function = earthposvel, xvs::Function = sunposvel, +function compute_radec(obs::RadecMPC{T}, niter::Int = 10; eo::Bool = true, xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} return compute_radec(obs.observatory, obs.date, niter; eo = eo, xve = xve, xvs = xvs, xva = xva) -end +end -function compute_radec(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = true, xve::Function = earthposvel, xvs::Function = sunposvel, +function compute_radec(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = true, xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} - + # Number of observations n_optical_obs = length(obs) # UTC time of first astrometric observation @@ -167,7 +167,7 @@ function compute_radec(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = tru et1 = datetime2et(utc1) # Asteroid ephemeris at et1 a1_et1 = xva(et1)[1] - # Type of asteroid ephemeris + # Type of asteroid ephemeris S = typeof(a1_et1) # Right ascension @@ -188,17 +188,17 @@ const mpc_catalogue_codes_2014 = ["a", "b", "c", "d", "e", "g", "i", "j", "l", " "u", "v", "w", "L", "N"] # MPC catalogues corresponding to debiasing tables included in https://doi.org/10.1016/j.icarus.2019.113596 -const mpc_catalogue_codes_2018 = ["a", "b", "c", "d", "e", "g", "i", "j", "l", "m", "n", "o", "p", "q", +const mpc_catalogue_codes_2018 = ["a", "b", "c", "d", "e", "g", "i", "j", "l", "m", "n", "o", "p", "q", "r", "t", "u", "v", "w", "L", "N", "Q", "R", "S", "U", "W"] @doc raw""" select_debiasing_table(debias_table::String = "2018") -Return the catalogue codes, truth catalogue, resolution and bias matrix of the corresponding debias table. The possible values -for `debias_table` are: +Return the catalogue codes, truth catalogue, resolution and bias matrix of the corresponding debias table. The possible values +for `debias_table` are: - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, -- `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. +- `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. """ function select_debiasing_table(debias_table::String = "2018") # Debiasing tables are loaded "lazily" via Julia artifacts, according to rules in Artifacts.toml @@ -206,41 +206,41 @@ function select_debiasing_table(debias_table::String = "2018") debias_path = artifact"debias_2018" mpc_catalogue_codes_201X = mpc_catalogue_codes_2018 # The healpix tesselation resolution of the bias map from https://doi.org/10.1016/j.icarus.2019.113596 - NSIDE = 64 + NSIDE = 64 # In 2018 debias table Gaia DR2 catalogue is regarded as the truth - truth = "V" + truth = "V" elseif debias_table == "hires2018" debias_path = artifact"debias_hires2018" mpc_catalogue_codes_201X = mpc_catalogue_codes_2018 # The healpix tesselation resolution of the high-resolution bias map from https://doi.org/10.1016/j.icarus.2019.113596 - NSIDE = 256 + NSIDE = 256 # In 2018 debias table Gaia DR2 catalogue is regarded as the truth - truth = "V" + truth = "V" elseif debias_table == "2014" debias_path = artifact"debias_2014" mpc_catalogue_codes_201X = mpc_catalogue_codes_2014 # The healpix tesselation resolution of the bias map from https://doi.org/10.1016/j.icarus.2014.07.033 - NSIDE= 64 + NSIDE= 64 # In 2014 debias table PPMXL catalogue is regarded as the truth - truth = "t" + truth = "t" else @error "Unknown bias map: $(debias_table). Possible values are `2014`, `2018` and `hires2018`." end - # Debias table file + # Debias table file bias_file = joinpath(debias_path, "bias.dat") - # Read bias matrix + # Read bias matrix bias_matrix = readdlm(bias_file, comment_char='!', comments=true) # Initialize healpix Resolution variable - resol = Resolution(NSIDE) - # Compatibility between bias matrix and resolution + resol = Resolution(NSIDE) + # Compatibility between bias matrix and resolution @assert size(bias_matrix) == (resol.numOfPixels, 4length(mpc_catalogue_codes_201X)) "Bias table file $bias_file dimensions do not match expected parameter NSIDE=$NSIDE and/or number of catalogs in table." return mpc_catalogue_codes_201X, truth, resol, bias_matrix end @doc raw""" - debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, truth::String, resol::Resolution, + debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, truth::String, resol::Resolution, bias_matrix::Matrix{T}) where {T <: AbstractFloat} Return total debiasing correction in right ascension and declination (both in arcsec). @@ -249,28 +249,28 @@ Return total debiasing correction in right ascension and declination (both in ar - `obs::RadecMPC{T}`: optical observation. - `mpc_catalogue_codes_201X::Vector{String}`: catalogues present in debiasing table. -- `truth::String`: truth catalogue of debiasing table. +- `truth::String`: truth catalogue of debiasing table. - `resol::Resolution`: resolution. -- `bias_matrix::Matrix{T}`: debiasing table. +- `bias_matrix::Matrix{T}`: debiasing table. """ -function debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, truth::String, resol::Resolution, +function debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, truth::String, resol::Resolution, bias_matrix::Matrix{T}) where {T <: AbstractFloat} - + # Catalogue code catcode = obs.catalogue.code # If star catalogue is not present in debiasing table, then set corrections equal to zero if (catcode ∉ mpc_catalogue_codes_201X) && catcode != "Y" - # Catalogue exists in mpc_catalogues[] + # Catalogue exists in mpc_catalogues[] if !isunknown(obs.catalogue) # Truth catalogue is not present in debiasing table but it does not send a warning if catcode != truth @warn "Catalogue $(obs.catalogue.name) not found in debiasing table. Setting debiasing corrections equal to zero." end - # Unknown catalogue + # Unknown catalogue elseif catcode == "" @warn "Catalog information not available in observation record. Setting debiasing corrections equal to zero." - # Catalogue code is not empty but it does not match an MPC catalogue code either + # Catalogue code is not empty but it does not match an MPC catalogue code either else @warn "Catalog code $catcode does not correspond to MPC catalogue code. Setting debiasing corrections equal to zero." end @@ -283,14 +283,14 @@ function debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, t # not substracting 1 from the returned value of `ang2pixRing` corresponds to 1-based indexing, as in Julia. # Since we use pix_ind to get the corresponding row number in `bias.dat`, it's not necessary to substract 1. pix_ind = ang2pixRing(resol, π/2 - obs.δ, obs.α) - + # Handle edge case: in new MPC catalogue nomenclature, "UCAC-5"->"Y"; but in debias tables "UCAC-5"->"W" if catcode == "Y" cat_ind = findfirst(x -> x == "W", mpc_catalogue_codes_201X) else cat_ind = findfirst(x -> x == catcode, mpc_catalogue_codes_201X) end - + # Read dRA, pmRA, dDEC, pmDEC data from bias.dat # dRA: position correction in RA * cos(DEC) at epoch J2000.0 [arcsec] # dDEC: position correction in DEC at epoch J2000.0 [arcsec] @@ -304,27 +304,27 @@ function debiasing(obs::RadecMPC{T}, mpc_catalogue_codes_201X::Vector{String}, t # Years since J2000 yrs_J2000_tt = tt_secs_i/(daysec*yr) # Total debiasing correction in right ascension (arcsec) - α_corr = dRA + yrs_J2000_tt*pmRA/1_000 + α_corr = dRA + yrs_J2000_tt*pmRA/1_000 # Total debiasing correction in declination (arcsec) - δ_corr = dDEC + yrs_J2000_tt*pmDEC/1_000 + δ_corr = dDEC + yrs_J2000_tt*pmDEC/1_000 end return α_corr, δ_corr -end +end @doc raw""" w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} -Return the statistical weight from Veres et al. (2017) corresponding to `obs`. +Return the statistical weight from Veres et al. (2017) corresponding to `obs`. """ function w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} - + obscode = obs.observatory.code dt_utc_obs = obs.date catalogue = obs.catalogue.code # Unit weight (arcseconds) - w = 1.0 + w = 1.0 # Table 2: epoch-dependent astrometric residuals if obscode == "703" return Date(dt_utc_obs) < Date(2014,1,1) ? w : 0.8w @@ -386,48 +386,48 @@ function w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} end @doc raw""" - radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = true, debias_table::String = "2018", + radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = true, debias_table::String = "2018", xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} radec_astrometry(outfilename::String, opticalobsfile::String, asteph::TaylorInterpolant, ss16asteph::TaylorInterpolant, niter::Int = 5; eo::Bool = true, debias_table::String = "2018") -Compute optical astrometry, i.e. dates of observation plus observed, computed, debiasing corrections and statistical weights for +Compute optical astrometry, i.e. dates of observation plus observed, computed, debiasing corrections and statistical weights for right ascension and declination (in arcsec). -See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and [`Healpix.ang2pixRing`](@ref). +See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and [`Healpix.ang2pixRing`](@ref). # Arguments - `obs::Vector{RadecMPC{T}}`: vector of observations. -- `outfilename::String`: file where to save the results (.jld2). -- `opticalobsfile::String`: file where to retrieve optical observations. -- `asteph::TaylorInterpolant`: NEO's ephemeris. -- `ss16asteph::TaylorInterpolant`: solar system ephemeris. +- `outfilename::String`: file where to save the results (.jld2). +- `opticalobsfile::String`: file where to retrieve optical observations. +- `asteph::TaylorInterpolant`: NEO's ephemeris. +- `ss16asteph::TaylorInterpolant`: solar system ephemeris. - `niter::Int`: number of light-time solution iterations. - `eo::Bool`: compute corrections due to Earth orientation, LOD, polar motion. - `debias_table::String`: possible values are: - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, - - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. + - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. - `xve::Function`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xvs::Function`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xva::Function`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ -function radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = true, debias_table::String = "2018", +function radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = true, debias_table::String = "2018", xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} - # Number of observations + # Number of observations n_optical_obs = length(obs) # UTC time of first astrometric observation - utc1 = obs[1].date + utc1 = obs[1].date # TDB seconds since J2000.0 for first astrometric observation et1 = datetime2et(utc1) # Asteroid ephemeris at et1 a1_et1 = xva(et1)[1] - # Type of asteroid ephemeris + # Type of asteroid ephemeris S = typeof(a1_et1) - + # Observed right ascension α_obs = Array{Float64}(undef, n_optical_obs) # Observed declination @@ -437,35 +437,35 @@ function radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = α_comp = Array{S}(undef, n_optical_obs) # Computed declination δ_comp = Array{S}(undef, n_optical_obs) - + # Total debiasing correction in right ascension (arcsec) α_corr = Array{Float64}(undef, n_optical_obs) # Total debiasing correction in declination (arcsec) δ_corr = Array{Float64}(undef, n_optical_obs) - - # Times of observations + + # Times of observations datetime_obs = Array{DateTime}(undef, n_optical_obs) # Statistical weights w8s = Array{Float64}(undef, n_optical_obs) - # Select debias table + # Select debias table mpc_catalogue_codes_201X, truth, resol, bias_matrix = select_debiasing_table(debias_table) - # Iterate over the observations + # Iterate over the observations for i in 1:n_optical_obs - # Time of observation + # Time of observation datetime_obs[i] = obs[i].date - + # Observed ra/dec - # Note: ra is multiplied by a metric factor cos(dec) to match the format of debiasing corrections + # Note: ra is multiplied by a metric factor cos(dec) to match the format of debiasing corrections δ_obs[i] = rad2arcsec(obs[i].δ) # arcsec α_obs[i] = rad2arcsec(obs[i].α) * cos(obs[i].δ) # arcsec # Computed ra/dec α_comp_as, δ_comp_as = compute_radec(obs[i], niter, eo=eo, xve=xve, xvs=xvs, xva=xva) # Multiply by metric factor cos(dec) - α_comp[i] = α_comp_as * cos(obs[i].δ) # arcsec + α_comp[i] = α_comp_as * cos(obs[i].δ) # arcsec δ_comp[i] = δ_comp_as # arcsec # Debiasing corrections @@ -473,7 +473,7 @@ function radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = # Statistical weights from Veres et al. (2017) w8s[i] = w8sveres17(obs[i]) - + end # Return time of observation, observed ra/dec, computed ra/dec, total debiasing correction in ra/dec and statistical weights @@ -483,31 +483,31 @@ end function radec_astrometry(outfilename::String, opticalobsfile::String, asteph::TaylorInterpolant, ss16asteph::TaylorInterpolant, niter::Int = 5; eo::Bool = true, debias_table::String = "2018") - # Read optical observations + # Read optical observations radec = read_radec_mpc(opticalobsfile) # Check that first and last observation times are within interpolation interval - Δt_0 = datetime2julian(radec[1].date) - JD_J2000 - asteph.t0 + Δt_0 = datetime2julian(radec[1].date) - JD_J2000 - asteph.t0 Δt_f = datetime2julian(radec[end].date) - JD_J2000 - asteph.t0 - t_min, t_max = minmax(asteph.t[1], asteph.t[end]) + t_min, t_max = minmax(asteph.t[1], asteph.t[end]) @assert t_min ≤ Δt_0 ≤ Δt_f ≤ t_max "First and/or last observation times are outside interpolation interval" # Number of massive bodies Nm1 = (size(ss16asteph.x)[2]-13) ÷ 6 # Number of bodies, including NEA - N = Nm1 + 1 + N = Nm1 + 1 # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec - # NEO + # NEO function asteph_et(et) return auday2kmsec(asteph(et/daysec)[1:6]) end - # Earth + # Earth function earth_et(et) return auday2kmsec(ss16asteph(et)[union(3*4-2:3*4,3*(N-1+4)-2:3*(N-1+4))]) end - # Sun + # Sun function sun_et(et) return auday2kmsec(ss16asteph(et)[union(3*1-2:3*1,3*(N-1+1)-2:3*(N-1+1))]) end @@ -519,12 +519,12 @@ function radec_astrometry(outfilename::String, opticalobsfile::String, asteph::T # Save data to file println("Saving data to file: $outfilename") JLD2.jldopen(outfilename, "w") do file - # Write variables to jld file - JLD2.write(file, + # Write variables to jld2 file + JLD2.write(file, "datetime_obs", datetime_obs, - "α_obs", α_obs, + "α_obs", α_obs, "δ_obs", δ_obs, - "α_comp", α_comp, + "α_comp", α_comp, "δ_comp", δ_comp, "α_corr", α_corr, "δ_corr", δ_corr, @@ -541,7 +541,7 @@ end Compute optical O-C residuals. -See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and [`radec_astrometry`](@ref). +See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and [`radec_astrometry`](@ref). # Arguments @@ -551,7 +551,7 @@ See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and - `debias_table::String`: possible values are: - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, - - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. + - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. - `xvs::Function`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xve::Function`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xva::Function`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. @@ -561,14 +561,14 @@ function residuals(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = true, d # Optical astrometry (dates + observed + computed + debiasing + weights) x_jt = radec_astrometry(obs, niter; eo = eo, debias_table = debias_table, xvs = xvs, xve = xve, xva = xva) - # Right ascension residuals + # Right ascension residuals res_α = x_jt[2] .- x_jt[6] .- x_jt[4] - # Declination residuals + # Declination residuals res_δ = x_jt[3] .- x_jt[7] .- x_jt[5] - # Total residuals + # Total residuals res = vcat(res_α, res_δ) - # Weights + # Weights w = repeat(1 ./ x_jt[end].^2, 2) - return res, w -end \ No newline at end of file + return res, w +end \ No newline at end of file From 438685f8ec4fb323062e577d0989b838313c809a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Mon, 29 May 2023 18:10:17 +0200 Subject: [PATCH 02/46] Update Artifacts.toml --- Artifacts.toml | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/Artifacts.toml b/Artifacts.toml index 2590f438..6f98a6a9 100644 --- a/Artifacts.toml +++ b/Artifacts.toml @@ -1,3 +1,11 @@ +[TTmTDBde430] +git-tree-sha1 = "de3fba2237359dc941a057d492c305afeccba133" +lazy = true + + [[TTmTDBde430.download]] + sha256 = "a8e09c3d2f68f77c641eed0b41d2441b11a7b4f12daed8144638fdca02eb4d5d" + url = "https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/TTmTDB.de430.19feb2015.bsp" + [a99942] git-tree-sha1 = "7cdf1265a22c52329651c4a71a9835d1b90f568e" lazy = true @@ -11,8 +19,8 @@ git-tree-sha1 = "db3e3a765712a792a7f4a73634213d53fc0561ec" lazy = true [[de430.download]] - sha256 = "25458f6fc0219be7ff9fbd893a4cd6ed9927316824cb5c4062b642414884790d" - url = "https://raw.githubusercontent.com/PerezHz/jpleph/main/de430.tar.gz" + sha256 = "b70b72fde86923475fac6cec1e0887040bb80ffe159f153aab647cdfdf897351" + url = "https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/de430_1850-2150.bsp" [debias] git-tree-sha1 = "cfd0d2615770087d3c564b7f6143f01930ccb45e" @@ -20,7 +28,7 @@ lazy = true [[debias.download]] sha256 = "8b107db9506ec45c8cad78d0981c48693c6e5957912df95f4a3df826c7736227" - url = "ftp://ssd.jpl.nasa.gov/pub/ssd/debias/debias.tgz" + url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias.tgz" [debias_2014] git-tree-sha1 = "1b6a82575ac74386b893f8c51361d19d350bd234" @@ -28,7 +36,7 @@ lazy = true [[debias_2014.download]] sha256 = "1d44c6443d08f83c79017afd218c3b4e326c573d84842c88713e4b6c8d6d5b03" - url = "ftp://ssd.jpl.nasa.gov/pub/ssd/debias/debias_2014.tgz" + url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_2014.tgz" [debias_2018] git-tree-sha1 = "ea7915a243ea4c8e0960817f50677598076beeaa" @@ -36,7 +44,7 @@ lazy = true [[debias_2018.download]] sha256 = "288132cefea7f1bdf0989782db1173948dd7dfef7da31910be90b16b73cfea6c" - url = "ftp://ssd.jpl.nasa.gov/pub/ssd/debias/debias_2018.tgz" + url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_2018.tgz" [debias_hires2018] git-tree-sha1 = "cebf83360f68870a628805aea9b4261d0d6b4545" @@ -44,20 +52,20 @@ lazy = true [[debias_hires2018.download]] sha256 = "2b292fc79c202d38dfab386783fee10d422f6919afc58348c72059710dd6cd92" - url = "ftp://ssd.jpl.nasa.gov/pub/ssd/debias/debias_hires2018.tgz" + url = "https://ssd.jpl.nasa.gov/ftp/ssd/debias/debias_hires2018.tgz" [naif0012] git-tree-sha1 = "8fa307fe9da2a63ed0cf9d681540d94a619a0995" lazy = true [[naif0012.download]] - sha256 = "d9b1c3d944f671eca8177e29384accbdb5f4b3fbe4603a4bb2e0bdbf7a900fb4" - url = "https://raw.githubusercontent.com/PerezHz/jpleph/main/naif0012.tar.gz" + sha256 = "678e32bdb5a744117a467cd9601cd6b373f0e9bc9bbde1371d5eee39600a039b" + url = "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls" [sseph_p100] -git-tree-sha1 = "63a7429f64436a92016962f1fab2d70262120f6c" +git-tree-sha1 = "6fb49d939d8cc8675acbb8d64d9014e918c1569c" lazy = true [[sseph_p100.download]] - sha256 = "7a5886729bbd85d68417f8d69fb2d7e8f4390376a49c9bcda1b580116f8ed11b" + sha256 = "5051b43a30e33b3bde2388d7bf48dcdfefffd1dc3c139b37042b94b2f877baee" url = "https://github.com/LuEdRaMo/sseph/raw/main/sseph343ast016_p100y_et.tar.gz" From 062f28467f7cd245f04d53714247a1f938adee5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Mon, 29 May 2023 18:10:37 +0200 Subject: [PATCH 03/46] Update artifacts generation script --- dev/generate_artifacts.jl | 56 ++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/dev/generate_artifacts.jl b/dev/generate_artifacts.jl index 8996f1f8..0ae842c3 100644 --- a/dev/generate_artifacts.jl +++ b/dev/generate_artifacts.jl @@ -7,27 +7,25 @@ # TO DO: adapt script for 2010 debiasing tables (requires extra unpacking) using Pkg.Artifacts -using Pkg.PlatformEngines -using Pkg.PlatformEngines: sha256 -using Pkg -# using Downloads: download -Pkg.PlatformEngines.probe_platform_engines!() +using Pkg.PlatformEngines: sha256, unpack +using Downloads # This is the path to the Artifacts.toml we will manipulate const artifact_toml = joinpath(dirname(@__DIR__), "Artifacts.toml") # JPL FTP URL -const ftp_jpl = "ftp://ssd.jpl.nasa.gov/pub/ssd/debias/" +const ftp_jpl = "https://ssd.jpl.nasa.gov/ftp/" # Debiasing tables names and URLs const names_debias = ["debias", "debias_2014", "debias_2018", "debias_hires2018"] -const urls_debias = ftp_jpl .* names_debias .* ".tgz" +const urls_debias = ftp_jpl .* "ssd/debias/" .* names_debias .* ".tgz" # JPL lsk and spk names and URLs -const names_lsk_spk = ["naif0012", "de430", "a99942"] +const names_lsk_spk = ["naif0012", "de430", "TTmTDBde430", "a99942"] const urls_lsk_spk = [ - "https://raw.githubusercontent.com/PerezHz/jpleph/main/naif0012.tar.gz", - "https://raw.githubusercontent.com/PerezHz/jpleph/main/de430.tar.gz", + "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls", + ftp_jpl*"eph/planets/bsp/de430_1850-2150.bsp", + ftp_jpl*"eph/planets/bsp/TTmTDB.de430.19feb2015.bsp", "https://raw.githubusercontent.com/PerezHz/jpleph/main/a99942.tar.gz", ] @@ -36,35 +34,45 @@ const name_sseph = "sseph_p100" const url_sseph = "https://github.com/LuEdRaMo/sseph/raw/main/sseph343ast016_p100y_et.tar.gz" # Collect names and URLs -const urls_ = vcat(urls_lsk_spk, urls_debias, url_sseph) -const names_ = vcat(names_lsk_spk, names_debias, name_sseph) +const urls = vcat(urls_lsk_spk, urls_debias, url_sseph) +const names = vcat(names_lsk_spk, names_debias, name_sseph) -for (url, name) in map((x,y)->(x,y), urls_, names_) +for (url, name) in zip(urls, names) # Query the `Artifacts.toml` file for the hash bound to the name # (returns `nothing` if no such binding exists) artfct_hash = artifact_hash(name, artifact_toml) - # If the name was not bound, or the hash it was bound to does not exist, create it! if isnothing(artfct_hash) || !artifact_exists(artfct_hash) tb = Tuple[] # create_artifact() returns the content-hash of the artifact directory once we're finished creating it artfct_hash = create_artifact() do artifact_dir # We create the artifact by simply downloading a few files into the new artifact directory - @show url + @show url name tmp_dir = mktempdir() - tarball = download(url, joinpath(tmp_dir, basename(url))) - # @show tarball tmp_dir - try - tarball_hash = open(tarball) do file + basename_url = basename(url) + @show basename_url + dot_idx = findlast(isequal('.'), basename_url) + ext = basename_url[dot_idx+1:end] + if ext in ["gz", "tgz"] # If artifact is a tarball with many files + tarball = Downloads.download(url, joinpath(tmp_dir, basename(url))) + try + tarball_hash = open(tarball) do file + bytes2hex(sha256(file)) + end + unpack(tarball, artifact_dir) + tb = [(url, tarball_hash)] + finally + rm(tarball) + end + else # url containing a single non-tarball file + fpath = Downloads.download(url, joinpath(artifact_dir, basename(url))) + file_hash = open(fpath) do file bytes2hex(sha256(file)) end - @show tarball_hash - tb = [(url, tarball_hash)] - unpack(tarball, artifact_dir) - finally - rm(tarball) + tb = [(url, file_hash)] end end + @show artfct_hash typeof(artfct_hash) # Now bind that hash within our `Artifacts.toml`. `force = true` means that if it already exists, # just overwrite the corresponding entry in `Artifacts.toml` with the new content-hash. # Unless the source files change, we do not expect the content hash to From 4acbb70f28d149d8861c9f799abdd088d2edc2b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Mon, 29 May 2023 18:28:58 +0200 Subject: [PATCH 04/46] Bring back JPL DE430 TT-TDB ephemeris artifact --- src/observations/jpl_eph.jl | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/observations/jpl_eph.jl b/src/observations/jpl_eph.jl index 6e3afa9b..814ccb98 100644 --- a/src/observations/jpl_eph.jl +++ b/src/observations/jpl_eph.jl @@ -1,8 +1,4 @@ # Load TT-TDB (ttmtdb) from jld2 file -const peeph_artifact_path = joinpath(artifact"sseph_p100", "sseph343ast016_p100y_et.jld2") -const peeph = JLD2.load(peeph_artifact_path, "ss16ast_eph") -const ttmtdb = TaylorInterpolant(peeph.t0, peeph.t, peeph.x[:,end]) - @doc raw""" loadjpleph() @@ -14,6 +10,8 @@ function loadjpleph() furnsh( # NAIF IDs joinpath(artifact"naif0012", "naif0012.tls"), + # JPL DE430 TT-TDB + joinpath(artifact"TTmTDBde430", "TTmTDB.de430.19feb2015.bsp"), # JPL DE430 ephemerides joinpath(artifact"de430", "de430_1850-2150.bsp"), # JPL #197 solution for Apophis @@ -119,6 +117,11 @@ See also [`getposvel`](@ref). """ dtt_tdb(et) = getposvel(1000000001, 1000000000, cte(et))[4] # units: seconds/seconds +# Load Solar System 2000-2100 ephemeris +const sseph_artifact_path = joinpath(artifact"sseph_p100", "sseph343ast016_p100y_et.jld2") +const sseph = JLD2.load(sseph_artifact_path, "ss16ast_eph") +const ttmtdb = TaylorInterpolant(sseph.t0, sseph.t, sseph.x[:,end]) + @doc raw""" loadpeeph(et::Union{Nothing, Real} = nothing) @@ -127,12 +130,11 @@ Load Solar System ephemeris produced by `PlanetaryEphemeris.jl` from Jan 1st 200 **Caution**: running this function for the first time will download the `sseph_p100` artifact (∼554 MB) which can take several minutes. """ function loadpeeph(et::Union{Nothing, Real} = nothing) - # Load Solar System 2000-2100 ephemeris - eph = JLD2.load(joinpath(artifact"sseph_p100", "sseph343ast016_p100y_et.jld2"), "ss16ast_eph") + 1 + 1 if isnothing(et) - return eph + return sseph else - idxs = findall(x -> x <= et, eph.t) - return TaylorInterpolant(eph.t0, eph.t[idxs], eph.x[idxs[1:end-1], :]) + idxs = findall(x -> x <= et, sseph.t) + return TaylorInterpolant(sseph.t0, sseph.t[idxs], sseph.x[idxs[1:end-1], :]) end -end \ No newline at end of file +end From 96c39aaa89856976a69e8bb26709510deb4f0d17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Mon, 29 May 2023 18:36:35 +0200 Subject: [PATCH 05/46] Use solution a la PlatformEngines.jl to handle failing downloads --- dev/generate_artifacts.jl | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/dev/generate_artifacts.jl b/dev/generate_artifacts.jl index 0ae842c3..49fbce1f 100644 --- a/dev/generate_artifacts.jl +++ b/dev/generate_artifacts.jl @@ -53,8 +53,21 @@ for (url, name) in zip(urls, names) @show basename_url dot_idx = findlast(isequal('.'), basename_url) ext = basename_url[dot_idx+1:end] - if ext in ["gz", "tgz"] # If artifact is a tarball with many files - tarball = Downloads.download(url, joinpath(tmp_dir, basename(url))) + if ext in ["gz", "tgz"] # If artifact is a tarball with many files + # the following code block was adapted from PlatformEngines.jl, MIT licensed + # https://github.com/JuliaLang/Pkg.jl/blob/048b0e86deba0c5f491eb1a3af2f3c97cac675b3/src/PlatformEngines.jl#L348 + dest = joinpath(tmp_dir, basename(url)) + tarball = "" + f = retry(delays = fill(1.0, 3)) do + try + tarball = Downloads.download(url, dest) + catch err + @debug "download and verify failed" url dest err + rethrow() + end + end + f() + # tarball = Downloads.download(url, joinpath(tmp_dir, basename(url))) try tarball_hash = open(tarball) do file bytes2hex(sha256(file)) From 05e822a386e100ba398af43bbec283b1916f706d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Mon, 29 May 2023 18:38:47 +0200 Subject: [PATCH 06/46] Remove dummy recompilation trigger --- src/observations/jpl_eph.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/observations/jpl_eph.jl b/src/observations/jpl_eph.jl index 814ccb98..7839c417 100644 --- a/src/observations/jpl_eph.jl +++ b/src/observations/jpl_eph.jl @@ -130,7 +130,6 @@ Load Solar System ephemeris produced by `PlanetaryEphemeris.jl` from Jan 1st 200 **Caution**: running this function for the first time will download the `sseph_p100` artifact (∼554 MB) which can take several minutes. """ function loadpeeph(et::Union{Nothing, Real} = nothing) - 1 + 1 if isnothing(et) return sseph else From f114278af934efdc5aef42cd7d833a13bce0788a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Mon, 29 May 2023 19:26:06 +0200 Subject: [PATCH 07/46] Remove StaticArrays dep; add StaticArraysCore dep --- Project.toml | 4 ++-- src/NEOs.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index ba31a104..908db7ad 100644 --- a/Project.toml +++ b/Project.toml @@ -27,7 +27,7 @@ Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" ReferenceFrameRotations = "74f56ac7-18b3-5285-802d-d4bd4f104033" SPICE = "5bab7191-041a-5c2e-a744-024b9c3a5062" SatelliteToolbox = "6ac157d9-b43d-51bb-8fab-48bf53814f4a" -StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" +StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42" @@ -50,7 +50,7 @@ Query = "1.0" ReferenceFrameRotations = "3" SPICE = "0.2" SatelliteToolbox = "0.10" -StaticArrays = "1.2" +StaticArraysCore = "1.4" StatsBase = "0.34" TaylorIntegration = "0.13" TaylorSeries = "0.15" diff --git a/src/NEOs.jl b/src/NEOs.jl index b7a4e577..492af4ce 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -17,7 +17,7 @@ using Healpix: ang2pixRing, Resolution using SatelliteToolbox: nutation_fk5, J2000toGMST, rECEFtoECI, get_ΔAT, JD_J2000, EOPData_IAU1980, rECItoECI, DCM, TOD, GCRF, ITRF, rECItoECI, PEF, satsv, EOPData_IAU2000A, get_iers_eop_iau_1980, get_iers_eop_iau_2000A -using StaticArrays: SVector, SArray, @SVector +using StaticArraysCore: SArray using Dates: format using HTTP: get using IntervalRootFinding: roots, interval, Interval, mid From 410681ac629804dc0164e50a107c257d6e48e140 Mon Sep 17 00:00:00 2001 From: LuEdRaMo Date: Mon, 29 May 2023 13:08:55 -0600 Subject: [PATCH 08/46] Update StatsBase compat entry --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 908db7ad..c9b086cc 100644 --- a/Project.toml +++ b/Project.toml @@ -51,7 +51,7 @@ ReferenceFrameRotations = "3" SPICE = "0.2" SatelliteToolbox = "0.10" StaticArraysCore = "1.4" -StatsBase = "0.34" +StatsBase = "0.33, 0.34" TaylorIntegration = "0.13" TaylorSeries = "0.15" julia = "1.6" From f1a6b610a4eea88bdc8c793ace75e128ccb23e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Wed, 31 May 2023 21:44:19 +0200 Subject: [PATCH 09/46] Remove StaticArraysCore dep --- Project.toml | 2 - src/observations/topocentric.jl | 146 +++++++++++++++++++------------- 2 files changed, 87 insertions(+), 61 deletions(-) diff --git a/Project.toml b/Project.toml index c9b086cc..06ee004c 100644 --- a/Project.toml +++ b/Project.toml @@ -27,7 +27,6 @@ Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" ReferenceFrameRotations = "74f56ac7-18b3-5285-802d-d4bd4f104033" SPICE = "5bab7191-041a-5c2e-a744-024b9c3a5062" SatelliteToolbox = "6ac157d9-b43d-51bb-8fab-48bf53814f4a" -StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42" @@ -50,7 +49,6 @@ Query = "1.0" ReferenceFrameRotations = "3" SPICE = "0.2" SatelliteToolbox = "0.10" -StaticArraysCore = "1.4" StatsBase = "0.33, 0.34" TaylorIntegration = "0.13" TaylorSeries = "0.15" diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl index 4a15689d..27a868d5 100644 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -12,7 +12,7 @@ Return the observer's geocentric `[x, y, z]` position vector in Earth-Centered E """ function obs_pos_ECEF(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - # Make sure observatory has coordinates + # Make sure observatory has coordinates @assert !isunknown(observatory) "Cannot compute position for unknown observatory." @assert hascoord(observatory) "Cannot compute position for observatory [$(observatory.code)] without coordinates" @@ -22,9 +22,9 @@ function obs_pos_ECEF(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} # where ϕ' is the geocentric latitude and ρ is the geocentric distance in km # Cilindrical components of Earth-Centered Earth-Fixed position of observer - λ_deg = observatory.long # deg - u = observatory.cos * RE # km - v = observatory.sin * RE # km + λ_deg = observatory.long # deg + u = observatory.cos * RE # km + v = observatory.sin * RE # km # Cartesian components of Earth-Centered Earth-Fixed position of observer λ_rad = deg2rad(λ_deg) # rad @@ -32,7 +32,7 @@ function obs_pos_ECEF(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} y_gc = u * sin(λ_rad) # km z_gc = v # km - # Earth-Centered Earth-Fixed position position of observer + # Earth-Centered Earth-Fixed position position of observer pos_ECEF = [x_gc, y_gc, z_gc] # km return pos_ECEF @@ -42,34 +42,37 @@ obs_pos_ECEF(x::RadecMPC{T}) where {T <: AbstractFloat} = obs_pos_ECEF(x.observa obs_pos_ECEF(x::RadarJPL{T}) where {T <: AbstractFloat} = obs_pos_ECEF(x.rcvr) @doc raw""" - obsposvelECI(observatory::ObservatoryMPC{T}, et::T; eo::Bool=true, + obsposvelECI(observatory::ObservatoryMPC{T}, et::T; eo::Bool=true, eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU1980) where {T <: AbstractFloat} obsposvelECI(x::RadecMPC{T}; eo::Bool=true, eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU1980) where {T <: AbstractFloat} obsposvelECI(x::RadarJPL{T}; eo::Bool=true, eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU1980) where {T <: AbstractFloat} Return the observer's geocentric `[x, y, z, v_x, v_y, v_z]` "state" vector in Earth-Centered Inertial (ECI) reference frame. -See also [`SatelliteToolbox.satsv`](@ref) and [`SatelliteToolbox.svECEFtoECI`](@ref). +See also [`SatelliteToolbox.orbsv`](@ref) and [`SatelliteToolbox.svECEFtoECI`](@ref). -# Arguments +# Arguments - `observatory::ObservatoryMPC{T}`: observation site. - `et::T`: ephemeris time (TDB seconds since J2000.0 epoch). -- `eo::Bool`: whether to use Earth Orientation Parameters (eop) or not. +- `eo::Bool`: whether to use Earth Orientation Parameters (eop) or not. - `eop::Union{EOPData_IAU1980, EOPData_IAU2000A}`: Earth Orientation Parameters (eop). """ -function obsposvelECI(observatory::ObservatoryMPC{T}, et::T; eo::Bool=true, +function obsposvelECI(observatory::ObservatoryMPC{T}, et::Union{T,Taylor1{T}}; eo::Bool=true, eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU1980) where {T <: AbstractFloat} - # Earth-Centered Earth-Fixed position position of observer - pos_ECEF = obs_pos_ECEF(observatory) + # auxiliary to compute time-derivatives via autodiff + one_et = one(et) + + # Earth-Centered Earth-Fixed position position of observer + pos_ECEF = obs_pos_ECEF(observatory)*one_et - # UTC seconds + # UTC seconds utc_secs = et - tdb_utc(et) - # Julian days UTC + # Julian days UTC jd_utc = JD_J2000 + utc_secs/daysec - # State vector - pv_ECEF = SatelliteToolbox.satsv(jd_utc, pos_ECEF, zeros(3), zeros(3)) + # State vector + pv_ECEF = SatelliteToolbox.orbsv(jd_utc, pos_ECEF, one_et*zeros(3), one_et*zeros(3)) # Transform position/velocity from Earth-Centered Earth-fixed (ECEF) frame to Earth-Centered Inertial (ECI) frame # ITRF: International Terrestrial Reference Frame @@ -77,55 +80,80 @@ function obsposvelECI(observatory::ObservatoryMPC{T}, et::T; eo::Bool=true, # Use earth orientation parameters if eo - pv_ECI = SatelliteToolbox.svECEFtoECI(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc, eop) - # Not use earth orientation parameters + pv_ECI = SatelliteToolbox.sv_ecef_to_eci(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc, eop) + # Not use earth orientation parameters else - pv_ECI = SatelliteToolbox.svECEFtoECI(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc) + pv_ECI = SatelliteToolbox.sv_ecef_to_eci(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc) end - # Inertial position + # Inertial position p_ECI = convert(Vector{eltype(pv_ECI.r)}, pv_ECI.r) # Inertial velocity v_ECI = convert(Vector{eltype(pv_ECI.v)}, pv_ECI.v) - # Concat position and velocity + # Concat position and velocity return vcat(p_ECI, v_ECI) end function obsposvelECI(x::RadecMPC{T}; eo::Bool = true, eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU1980) where {T <: AbstractFloat} return obsposvelECI(x.observatory, datetime2et(x.date); eo = eo, eop = eop) -end -function obsposvelECI(x::RadarJPL{T}; eo::Bool = true, eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU1980) where {T <: AbstractFloat} +end +function obsposvelECI(x::RadarJPL{T}; eo::Bool = true, eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU1980) where {T <: AbstractFloat} return obsposvelECI(x.rcvr, datetime2et(x.date); eo = eo, eop = eop) -end - -# This method extends orthonormalize to handle Taylor1 and TaylorN -# The ReferenceFrameRotations.jl package is licensed under the MIT "Expat" License -# Copyright (c) 2014-2019: Ronan Arraes Jardim Chagas. -# See https://github.com/JuliaSpace/ReferenceFrameRotations.jl -function orthonormalize(dcm::SArray{Tuple{3,3},T,2,9} where {T<:Union{Taylor1,TaylorN}}) - e₁ = dcm[:,1] - e₂ = dcm[:,2] - e₃ = dcm[:,3] - - en₁ = e₁/norm(e₁) - enj₂ = e₂ - (en₁⋅e₂)*en₁ - en₂ = enj₂ / norm(enj₂) - enj₃ = e₃ - (en₁⋅e₃)*en₁ - enj₃ = enj₃ - (en₂⋅enj₃)*en₂ - en₃ = enj₃ / norm(enj₃) - - SArray( hcat(hcat(en₁, en₂), en₃) ) +end + +function smallangle_to_rot( + ::Type{DCM}, + θx::Taylor1, + θy::Taylor1, + θz::Taylor1; + normalize = true +) + return smallangle_to_dcm(θx, θy, θz; normalize = normalize) +end + +function smallangle_to_dcm( + θx::Taylor1{T}, + θy::Taylor1{T}, + θz::Taylor1{T}; + normalize = true +) where {T<:Number} + # # Since we might orthonormalize `D`, we need to get the float to avoid type + # # instabilities. + # T = float(promote_type(T1, T2, T3)) + + D = DCM{Taylor1{T}}( + 1, +θz, -θy, + -θz, 1, +θx, + +θy, -θx, 1 + )' + + if normalize + return orthonormalize(D) + else + return D + end +end + +function r_itrf_to_pef_fk5( + T::Type, + x_p::Taylor1, + y_p::Taylor1 +) + # Notice that `x_p` and `y_p` are displacements in X and Y directions and + # **not** rotation angles. Hence, a displacement in X is a rotation in Y and + # a displacement in Y is a rotation in X. + return smallangle_to_rot(T, +y_p, +x_p, zero(x_p)) end @doc raw""" - nupr7680mat(tt, Δϵ_1980, ΔΨ_1980, dde80, ddp80) + nupr7680mat(tt, Δϵ_1980, ΔΨ_1980, dde80, ddp80) -Return IAU 1976/1980 nutation-precession matrix. +Return IAU 1976/1980 nutation-precession matrix. -# Arguments +# Arguments -- `tt`: days since J2000.0 (TT). +- `tt`: days since J2000.0 (TT). - `Δϵ_1980, ΔΨ_1980`: IAU 1980 nutation angles Δψ (nutation in longitude), Δϵ (nutation in obliquity), both in radians. - `dde80, ddp80`: nutation corrections wrt IAU 1976/1980 (in radians). """ @@ -135,7 +163,7 @@ function nupr7680mat(tt, Δϵ_1980, ΔΨ_1980, dde80, ddp80) # Add nutation corrections dpsi = ΔΨ_1980 + ddp80 # rad deps = Δϵ_1980 + dde80 # rad - # IAU 1980 nutation matrix + # IAU 1980 nutation matrix # See Explanatory Supplement to the Astronomical Almanac 1992 # See equation (5-152) in page (5-60) of https://doi.org/10.1002/0471728470 # ϵ0 (rad): mean obliquity of the ecliptic @@ -146,7 +174,7 @@ function nupr7680mat(tt, Δϵ_1980, ΔΨ_1980, dde80, ddp80) Δψ = dpsi # ϵ (rad): true obliquity of date ϵ = ϵ0 + Δϵ - # Nutation matrix + # Nutation matrix rn = Rx(-ϵ)*Rz(-Δψ)*Rx(ϵ0) # Combine the matrices: PN = N x P (with frame-bias B included) return rn*rp @@ -157,9 +185,9 @@ end Return the polar motion matrix in radians (TIRS->ITRS, IERS 1996). -See also [`EarthOrientation.polarmotion`](@ref). +See also [`EarthOrientation.polarmotion`](@ref). -# Arguments +# Arguments - `tt`: days since J2000.0. - `eo::Bool`: wheter to use Earth orientation corrections from IERS or not. @@ -184,7 +212,7 @@ Return the angular velocity of the earth in units of rad/sec ```math \omega = (72921151.467064 - 0.843994809\text{LOD})\times 10^{-12}, ``` -where LOD is the length of the day in milliseconds. +where LOD is the length of the day in milliseconds. See https://www.iers.org/IERS/EN/Science/EarthRotation/UT1LOD.html. """ @@ -193,12 +221,12 @@ omega(lod) = (1e-12)*(72921151.467064 - 0.843994809lod) @doc raw""" t2c_rotation_iau_76_80(et::T; eo::Bool = true) where {T <: Number} -Return the terrestrial-to-celestial rotation matrix (including polar motion) +Return the terrestrial-to-celestial rotation matrix (including polar motion) using 1976/1980 Earth orientation/rotation model. See also [`EarthOrientation.precession_nutation80`](@ref), [`SatelliteToolbox.nutation_fk5`](@ref), [`EarthOrientation.getΔUT1`](@ref), [`SatelliteToolbox.J2000toGMST`](@ref), -[`EarthOrientation.getlod`](@ref), [`polarmotionmat`](@ref) and [`nupr7680mat`](@ref). +[`EarthOrientation.getlod`](@ref), [`polarmotionmat`](@ref) and [`nupr7680mat`](@ref). # Arguments @@ -208,16 +236,16 @@ See also [`EarthOrientation.precession_nutation80`](@ref), [`SatelliteToolbox.nu function t2c_rotation_iau_76_80(et::T; eo::Bool = true) where {T <: Number} # UTC (JD) utc_secs = et - tdb_utc(et) # seconds - t_utc = JD_J2000 + utc_secs/daysec # days - t_utc_00 = constant_term(constant_term(t_utc)) # days + t_utc = JD_J2000 + utc_secs/daysec # days + t_utc_00 = constant_term(constant_term(t_utc)) # days # TT t0_tt = et + ttmtdb(et) # seconds - tt = t0_tt/daysec # days + tt = t0_tt/daysec # days # Nutation corrections wrt IAU 1976/1980 # Output of `EarthOrientation.precession_nutation80` is in milli-arcseconds: # https://github.com/JuliaAstro/EarthOrientation.jl/blob/529f12425a6331b133f989443aeb3fbbafd8f324/src/EarthOrientation.jl#L413 - + # Use Earth orientation corrections from IERS if eo ddp80_mas, dde80_mas = EarthOrientation.precession_nutation80(t_utc_00) @@ -229,7 +257,7 @@ function t2c_rotation_iau_76_80(et::T; eo::Bool = true) where {T <: Number} ddp80 = mas2rad(ddp80_mas) dde80 = mas2rad(dde80_mas) # TDB days since J2000.0 - et_days = et/daysec + et_days = et/daysec # Mean obliquity (output in radians) epsa = PE.ϵ̄(et_days) # rad # Lunar longitude of ascending node (measured from ecliptic) @@ -261,7 +289,7 @@ function t2c_rotation_iau_76_80(et::T; eo::Bool = true) where {T <: Number} gast = mod2pi( gmst82 + ee ) β_dot = eo ? omega(EarthOrientation.getlod(t_utc_00)) : ω - # For more details, see Explanatory Supplement to the Astronomical Almanac 2014, + # For more details, see Explanatory Supplement to the Astronomical Almanac 2014, # p. 295, Sec. 7.4.3.3, Eqs. 7.137-7.140 Rz_minus_GAST = [ cos(gast) -sin(gast) zero(gast); From 720ccc3a774769ab762ad7f0e925689d0373dc16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Wed, 31 May 2023 21:45:13 +0200 Subject: [PATCH 10/46] Update NEOs.jl --- src/NEOs.jl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 492af4ce..4424e06b 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -3,7 +3,7 @@ module NEOs # __precompile__(false) import Base: hash, ==, show, isless, isnan, convert -import ReferenceFrameRotations: orthonormalize +import ReferenceFrameRotations: orthonormalize, smallangle_to_dcm, smallangle_to_rot import PlanetaryEphemeris, SatelliteToolbox using Distributed, JLD2, TaylorIntegration, Printf, DelimitedFiles, Test, LinearAlgebra, @@ -12,12 +12,12 @@ using Distributed, JLD2, TaylorIntegration, Printf, DelimitedFiles, Test, Linear using PlanetaryEphemeris: daysec, su, ea, α_p_sun, δ_p_sun, t2c_jpl_de430, pole_rotation, au, c_au_per_day, R_sun, c_cm_per_sec, c_au_per_sec, yr, RE, TaylorInterpolant, Rx, Ry, Rz, semimajoraxis, eccentricity, inclination, longascnode, argperi, timeperipass, - nbodyind, PE, ordpres_differentiate, numberofbodies, kmsec2auday + nbodyind, PE, ordpres_differentiate, numberofbodies, kmsec2auday, auday2kmsec using Healpix: ang2pixRing, Resolution using SatelliteToolbox: nutation_fk5, J2000toGMST, rECEFtoECI, get_ΔAT, JD_J2000, EOPData_IAU1980, - rECItoECI, DCM, TOD, GCRF, ITRF, rECItoECI, PEF, satsv, EOPData_IAU2000A, get_iers_eop_iau_1980, + rECItoECI, DCM, TOD, GCRF, ITRF, rECItoECI, PEF, orbsv, EOPData_IAU2000A, get_iers_eop_iau_1980, get_iers_eop_iau_2000A -using StaticArraysCore: SArray +import SatelliteToolbox.r_itrf_to_pef_fk5 using Dates: format using HTTP: get using IntervalRootFinding: roots, interval, Interval, mid @@ -40,7 +40,8 @@ export hasdelay, hasdoppler, ismonostatic, date, delay, delay_sigma, delay_units export julian2etsecs, etsecs2julian, datetime2et, et_to_200X, days_to_200X, datetime_to_200X, datetime2days, days2datetime, rad2arcsec, arcsec2rad, mas2rad # JPL Ephemerides -export loadjpleph, sunposvel, earthposvel, moonposvel, apophisposvel197, apophisposvel199, loadpeeph +export loadjpleph, sunposvel, earthposvel, moonposvel, apophisposvel197, apophisposvel199, + loadpeeph, bwdfwdeph # Osculating export pv2kep, yarkp2adot # Topocentric From 18a5859e40a556df939c4d17ec3293c0534d133f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Wed, 31 May 2023 22:16:30 +0200 Subject: [PATCH 11/46] Add bwdfwdeph function --- src/observations/jpl_eph.jl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/observations/jpl_eph.jl b/src/observations/jpl_eph.jl index 7839c417..c09a62d2 100644 --- a/src/observations/jpl_eph.jl +++ b/src/observations/jpl_eph.jl @@ -137,3 +137,17 @@ function loadpeeph(et::Union{Nothing, Real} = nothing) return TaylorInterpolant(sseph.t0, sseph.t[idxs], sseph.x[idxs[1:end-1], :]) end end + +function bwdfwdeph(et::T, + bwd::TaylorInterpolant{T,U,2}, + fwd::TaylorInterpolant{T,U,2} + ) where {T<:AbstractFloat, U<:Union{T,TaylorN{T}}} + @assert bwd.t0 == fwd.t0 "Backward and forward TaylorInterpolant initial times must match" + t = et/daysec + t0 = bwd.t0 + if t <= t0 + return auday2kmsec(bwd(t)) + else + return auday2kmsec(fwd(t)) + end +end From 748ca11ca881500fbd4172bca9a22d031cf7ef4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Wed, 31 May 2023 22:28:17 +0200 Subject: [PATCH 12/46] Add residuals method for Vector{RadarJPL} --- src/observations/process_radar.jl | 95 ++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 34 deletions(-) diff --git a/src/observations/process_radar.jl b/src/observations/process_radar.jl index 132eb770..028e966e 100644 --- a/src/observations/process_radar.jl +++ b/src/observations/process_radar.jl @@ -495,15 +495,15 @@ See https://doi.org/10.1086/116062. - `xva::TaylorInterpolant`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `tord::Int`: order of Taylor expansions. """ -function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 10; eo::Bool = true, xve::TaylorInterpolant = earthposvel, - xvs::TaylorInterpolant = sunposvel, xva::TaylorInterpolant = apophisposvel197, tord::Int = xva.x[1].order) where {T <: AbstractFloat} +function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 10; eo::Bool = true, xve::Function = earthposvel, + xvs::Function = sunposvel, xva::Function = apophisposvel197, tord::Int = xva.x[1].order) where {T <: AbstractFloat} - # Auxiliary to evaluate JT ephemeris - q1 = xva.x[1] # Transform receiving time from UTC to TDB seconds since j2000 et_r_secs_0 = datetime2et(t_r_utc) - # et_r_secs_0 a a Taylor polynomial - et_r_secs = Taylor1([et_r_secs_0,1.0].*one(q1[0]), tord) + # Auxiliary to evaluate JT ephemeris + xva1et0 = xva(et_r_secs_0)[1] + # et_r_secs_0 as a Taylor polynomial + et_r_secs = Taylor1([et_r_secs_0,1.0].*one(xva1et0), tord) # Compute geocentric position/velocity of receiving antenna in inertial frame (au, au/day) RV_r = obsposvelECI(observatory, et_r_secs, eo = eo) R_r = RV_r[1:3] @@ -756,13 +756,16 @@ function radar_astrometry(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, return radar_astrometry(radar.rcvr, radar.date, radar.freq, niter; eo = eo, tc = tc, xve = xve, xvs = xvs, xva = xva, autodiff = autodiff, tord = tord) end -function radar_astrometry(astradarfile::String, niter::Int=10; eo::Bool=true, tc::Real=1.0, xve=earthposvel, xvs=sunposvel, - xva=apophisposvel197, autodiff::Bool=true, tord::Int=10) - +function radar_astrometry(astradarfile::String, niter::Int=10; kwargs...) # Check that astradarfile is a file @assert isfile(astradarfile) "Cannot open file: $astradarfile" # Read radar measurements astradardata = read_radar_jpl(astradarfile) + return radar_astrometry(astradardata, niter; kwargs...) +end + +function radar_astrometry(astradardata::Vector{RadarJPL{T}}, niter::Int=10; eo::Bool=true, tc::Real=1.0, xve=earthposvel, xvs=sunposvel, + xva=apophisposvel197, autodiff::Bool=true, tord::Int=10) where {T <: AbstractFloat} # UTC time of first radar observation utc1 = astradardata[1].date @@ -797,7 +800,7 @@ function radar_astrometry(astradarfile::String, niter::Int=10; eo::Bool=true, tc τ_units = delay_units.(astradardata) # Time delay units ν_units = doppler_units.(astradardata) # Doppler shift units freq_ = freq.(astradardata) # Frequency - rcvr_ = rcvr.(astradardata) # Reciever antenna + rcvr_ = rcvr.(astradardata) # Receiver antenna xmit_ = xmit.(astradardata) # Emission antenna bouncepoint_ = bouncepoint.(astradardata) # Bounce point @@ -1080,6 +1083,7 @@ function radar_astrometry(outfilename::String, radarobsfile::String, asteph::Tay tc::Real = 1.0, autodiff::Bool = true, tord::Int = 10, niter::Int = 5) # Check that radarobsfile is a file @assert isfile(radarobsfile) "Cannot open file: $radarobsfile" + # Read optical observations radar = read_radar_jpl(radarobsfile) # Check that first and last observation times are within interpolation interval @@ -1095,32 +1099,17 @@ function radar_astrometry(outfilename::String, radarobsfile::String, asteph::Tay # NEO # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec - asteph_ord = asteph.x[1].order - asteph_t0 = asteph.t0*daysec - asteph_t = asteph.t*daysec - asteph_r = au*map(x->x(Taylor1(asteph_ord)/daysec), asteph.x[:,1:3]) - asteph_v = (au/daysec)*map(x->x(Taylor1(asteph_ord)/daysec), asteph.x[:,4:6]) - asteph_x = hcat(asteph_r, asteph_v) - asteph_et = TaylorInterpolant(asteph_t0, asteph_t, asteph_x) - - # Sun (su = 1) + asteph_et(et) = auday2kmsec(asteph(et/daysec)[1:6]) + # Earth # Change x, v units, resp., from au, au/day to km, km/sec - sseph_t0 = ss16asteph.t0 - sseph_t = ss16asteph.t - sseph_x = ss16asteph.x - sun_r = au*sseph_x[:,nbodyind(Nm1,su)[1:3]] - sun_v = (au/daysec)*sseph_x[:,nbodyind(Nm1,su)[4:6]] - sun_x = hcat(sun_r, sun_v) - sun_et = TaylorInterpolant(sseph_t0, sseph_t, sun_x) - - # Earth (ea = 4) + eph_ea = selecteph(ss16asteph, ea) + xve(et) = auday2kmsec(eph_ea(et)) + # Sun # Change x, v units, resp., from au, au/day to km, km/sec - earth_r = au*sseph_x[:,nbodyind(Nm1,ea)[1:3]] - earth_v = (au/daysec)*sseph_x[:,nbodyind(Nm1,ea)[4:6]] - earth_x = hcat(earth_r, earth_v) - earth_et = TaylorInterpolant(sseph_t0, sseph_t, earth_x) + eph_su = selecteph(ss16asteph, su) + xvs(et) = auday2kmsec(eph_su(et)) - # Compute ra/dec astrometry + # Compute radar astrometry dt_utc_obs, Δτ_obs, Δν_obs, vdelay, vdoppler, Δτ_σ, Δν_σ, τ_units, ν_units, freq, rcvr, xmit, bouncepoint, delay_index, doppler_index = radar_astrometry(radarobsfile, niter, xve = earth_et, xvs = sun_et, xva = asteph_et, tc = tc, tord = tord, autodiff = autodiff) # Save data to file @@ -1147,4 +1136,42 @@ function radar_astrometry(outfilename::String, radarobsfile::String, asteph::Tay end return nothing -end \ No newline at end of file +end + +@doc raw""" + residuals(obs::Vector{RadarJPL{T}}, niter::Int = 10; eo::Bool = true, debias_table::String = "2018", + xvs::Function = sunposvel, xve::Function = earthposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} + +Compute O-C residuals for radar astrometry. + +See also [`compute_delay`](@ref) and [`radar_astrometry`](@ref). + +# Arguments + +- `obs::Vector{RadarJPL{T}}`: vector of observations. +- `niter::Int`: number of light-time solution iterations. +- `eo::Bool`: compute corrections due to Earth orientation, LOD, polar motion. +- `tc::Real`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). +- `autodiff::Bool`: whether to use the automatic differentiation method of [`compute_delay`](@ref) or not. +- `tord::Int`: order of Taylor expansions. +- `xvs::Function`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xve::Function`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xva::Function`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +""" +function residuals(obs::Vector{RadarJPL{T}}, niter::Int = 10; eo::Bool = true, tc::Real = 1.0, autodiff::Bool = true, tord::Int = 10, + xvs::Function = sunposvel, xve::Function = earthposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} + # Radar delay/Doppler astrometric data + x_jt = radar_astrometry(obs, niter; eo = eo, tc=tc, autodiff = autodiff, tord = tord, xvs = xvs, xve = xve, xva = xva) + # Time-delay residuals + res_τ = x_jt[2][x_jt[14]] .- x_jt[4][x_jt[14]] + # Doppler-shift residuals + res_ν = x_jt[3][x_jt[15]] .- x_jt[5][x_jt[15]] + # Total residuals + res = vcat(res_τ, res_ν) + # Weights + w_τ = repeat(1 ./ x_jt[6][x_jt[14]].^2, 2) + w_ν = repeat(1 ./ x_jt[7][x_jt[15]].^2, 2) + w = vcat(w_τ, w_ν) + + return res, w +end From dd8af7f9dd719d4798b0f877396095f35002227c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Wed, 31 May 2023 22:30:29 +0200 Subject: [PATCH 13/46] Update radar_jpl.jl --- src/observations/radar_jpl.jl | 174 +++++++++++++++++----------------- 1 file changed, 87 insertions(+), 87 deletions(-) diff --git a/src/observations/radar_jpl.jl b/src/observations/radar_jpl.jl index 7bdcedda..293511f7 100644 --- a/src/observations/radar_jpl.jl +++ b/src/observations/radar_jpl.jl @@ -6,17 +6,17 @@ A radar measurement in JPL format. # Fields - `id::String`: object's name and number. -- `date::DateTime`: date of observation. +- `date::DateTime`: date of observation. - `τ::T`: time-delay. - `τ_σ::T`: time-delay uncertainty. -- `τ_units::String`: units of time delay. +- `τ_units::String`: units of time delay. - `Δν::T`: Doppler shift. - `Δν_σ::T`: Doppler shift uncertainty. - `Δν_units::String`: units of Doppler shift. - `freq::T`: frequency of the measurement. - `rcvr::ObservatoryMPC{T}`: reciever antenna. -- `xmit::ObservatoryMPC{T}`: emission antenna. -- `bouncepoint::String`: bounce point. +- `xmit::ObservatoryMPC{T}`: emission antenna. +- `bouncepoint::String`: bounce point. --- @@ -25,8 +25,8 @@ A radar measurement in JPL format. RadarJPL(delay::Val{false}, doppler::RegexMatch) RadarJPL(delay::Val{false}, doppler::Val{false}) -Convert a match of `NEOs.jpl_radar_regex` to `RadarJPL`. A `Val{false}` indicates that one or both of the measurements -(time delay or Doppler shift) are missing. +Convert a match of `NEOs.jpl_radar_regex` to `RadarJPL`. A `Val{false}` indicates that one or both of the measurements +(time delay or Doppler shift) are missing. """ @auto_hash_equals struct RadarJPL{T <: AbstractFloat} <: AbstractAstrometry id::String @@ -42,14 +42,14 @@ Convert a match of `NEOs.jpl_radar_regex` to `RadarJPL`. A `Val{false}` indicate xmit::ObservatoryMPC{T} bouncepoint::String # Inner constructor - function RadarJPL{T}(id::String, date::DateTime, Δτ::T, Δτ_σ::T, Δτ_units::String, Δν::T, Δν_σ::T, Δν_units::String, + function RadarJPL{T}(id::String, date::DateTime, Δτ::T, Δτ_σ::T, Δτ_units::String, Δν::T, Δν_σ::T, Δν_units::String, freq::T, rcvr::ObservatoryMPC{T}, xmit::ObservatoryMPC{T}, bouncepoint::String) where {T <: AbstractFloat} return new{T}(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, xmit, bouncepoint) end end # Outer constructor -function RadarJPL(id::String, date::DateTime, Δτ::T, Δτ_σ::T, Δτ_units::String, Δν::T, Δν_σ::T, Δν_units::String, freq::T, +function RadarJPL(id::String, date::DateTime, Δτ::T, Δτ_σ::T, Δτ_units::String, Δν::T, Δν_σ::T, Δν_units::String, freq::T, rcvr::ObservatoryMPC{T}, xmit::ObservatoryMPC{T}, bouncepoint::String) where {T <: AbstractFloat} return RadarJPL{T}(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, xmit, bouncepoint) end @@ -68,15 +68,15 @@ Check whether `r` has a non `NaN` Doppler shift. """ hasdoppler(r::RadarJPL{T}) where {T <: AbstractFloat} = !isnan(r.Δν) -# Order in RadecMPC and RadarJPL is given by date +# Order in RadecMPC and RadarJPL is given by date isless(a::T, b::T) where {T <: AbstractAstrometry} = a.date < b.date # Print method for RadarJPL -# Examples: +# Examples: # 99942 Apophis (2004 MN4) Δτ: 1.9202850713e8 us Δν: -102512.9059 Hz t: 2005-01-29T00:00:00 # 99942 Apophis (2004 MN4) Δν: -100849.1434 Hz t: 2005-01-27T23:31:00 # 99942 Apophis (2004 MN4) Δτ: 9.743930871e7 us t: 2013-01-03T10:00:00 -function show(io::IO, r::RadarJPL{T}) where {T <: AbstractFloat} +function show(io::IO, r::RadarJPL{T}) where {T <: AbstractFloat} delay = hasdelay(r) doppler = hasdoppler(r) @@ -87,15 +87,15 @@ function show(io::IO, r::RadarJPL{T}) where {T <: AbstractFloat} measurement_s = join([" Δτ: ", string(r.Δτ), " ", r.Δτ_units]) elseif doppler measurement_s = join([" Δν: ", string(r.Δν), " ", r.Δν_units]) - else + else measurement_s = " No measurements " - end + end print(io, r.id, measurement_s, " t: ", r.date, " obs: ", r.rcvr.name) end -# Functions to get specific fields of a RadarJPL object +# Functions to get specific fields of a RadarJPL object date(r::T) where {T <: AbstractAstrometry} = r.date delay(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δτ delay_sigma(r::RadarJPL{T}) where {T <: AbstractFloat} = r.Δτ_σ @@ -111,30 +111,30 @@ bouncepoint(r::RadarJPL{T}) where {T <: AbstractFloat} = r.bouncepoint @doc raw""" ismonostatic(rdata::RadarJPL) -Check whether the setup is monostatic, i.e., receiver and transmitter are the same. +Check whether a radar astrometric observation is monostatic, i.e., receiver and transmitter are the same. """ ismonostatic(r::RadarJPL{T}) where {T <: AbstractFloat} = r.rcvr == r.xmit @doc raw""" issband(f_MHz::T) where {T<:Real} -Check whether the transmission frequency `f_MHz` (in MHz) belongs to the S band -(IEEE nomenclature). +Check whether the transmission frequency `f_MHz` (in MHz) belongs to the S band +(IEEE nomenclature). """ issband(f_MHz::T) where {T<:Real} = 2000.0 ≤ f_MHz ≤ 4000.0 @doc raw""" isxband(f_MHz::T) where {T<:Real} -Check whether the transmission frequency `f_MHz` (in MHz) belongs to the X band -(IEEE nomenclature). +Check whether the transmission frequency `f_MHz` (in MHz) belongs to the X band +(IEEE nomenclature). """ isxband(f_MHz::T) where {T<:Real} = 8000.0 ≤ f_MHz ≤ 12000.0 # Regular expression to parse a radar measurement in JPL format const jpl_radar_regex = Regex(join( [ - # ID regex + tab + # ID regex + tab raw"(?P.*)\t", # Date regex + tab raw"(?P.*)\t", @@ -150,59 +150,59 @@ const jpl_radar_regex = Regex(join( raw"(?P.*)\t", # Emitter regex + tab raw"(?P.*)\t", - # Bouncepoint regex + end of line + # Bouncepoint regex + end of line raw"(?P.*)" ] )) -# Format of date in JPL radar data files +# Format of date in JPL radar data files const jpl_radar_dateformat = "yyyy-mm-dd HH:MM:SS" for (X, Y) in Iterators.product( (:(Val{false}), :(RegexMatch)), (:(Val{false}), :(RegexMatch)) ) - @eval begin + @eval begin function RadarJPL(delay::$X, doppler::$Y) if $X == RegexMatch id = string(delay["id"]) elseif $Y == RegexMatch id = string(doppler["id"]) - else + else id = "" - end + end if $X == RegexMatch date = DateTime(delay["date"], jpl_radar_dateformat) elseif $Y == RegexMatch date = DateTime(doppler["date"], jpl_radar_dateformat) - else + else date = DateTime(2000, 1, 1) - end + end if $X == RegexMatch Δτ = Meta.parse(delay["measurement"]) Δτ_σ = Meta.parse(delay["uncertainty"]) Δτ_units = string(delay["units"]) - else + else Δτ = NaN Δτ_σ = NaN Δτ_units = "" - end + end if $Y == RegexMatch Δν = Meta.parse(doppler["measurement"]) Δν_σ = Meta.parse(doppler["uncertainty"]) Δν_units = string(doppler["units"]) - else + else Δν = NaN Δν_σ = NaN Δν_units = "" - end + end if $X == RegexMatch freq = Float64(Meta.parse(delay["freq"])) elseif $Y == RegexMatch freq = Float64(Meta.parse(doppler["freq"])) - else + else freq = NaN end @@ -210,7 +210,7 @@ for (X, Y) in Iterators.product( (:(Val{false}), :(RegexMatch)), (:(Val{false}), rcvr = search_obs_code(string(delay["rcvr"])) elseif $Y == RegexMatch rcvr = search_obs_code(string(doppler["rcvr"])) - else + else rcvr = unknownobs() end @@ -218,7 +218,7 @@ for (X, Y) in Iterators.product( (:(Val{false}), :(RegexMatch)), (:(Val{false}), xmit = search_obs_code(string(delay["xmit"])) elseif $Y == RegexMatch xmit = search_obs_code(string(doppler["xmit"])) - else + else xmit = unknownobs() end @@ -226,138 +226,138 @@ for (X, Y) in Iterators.product( (:(Val{false}), :(RegexMatch)), (:(Val{false}), bouncepoint = string(delay["bouncepoint"]) elseif $Y == RegexMatch bouncepoint = string(doppler["bouncepoint"]) - else + else bouncepoint = "" end - + return RadarJPL(id, date, Δτ, Δτ_σ, Δτ_units, Δν, Δν_σ, Δν_units, freq, rcvr, xmit, bouncepoint) end - end -end + end +end @doc raw""" read_radar_jpl(filename::String) -Return the matches of `NEOs.jpl_radar_regex` in `filename` as `RadarJPL`. +Return the matches of `NEOs.jpl_radar_regex` in `filename` as `Vector{RadarJPL}`. """ function read_radar_jpl(filename::String) - # Read lines of jpl formatted file + # Read lines of jpl formatted file lines = readlines(filename) # Apply regular expressions matches = match.(jpl_radar_regex, lines) # Eliminate nothings filter!(!isnothing, matches) - # Number of matches + # Number of matches m = length(matches) # Dates of observation (as string) dates = getindex.(matches, "date") - # Eliminate repeated dates + # Eliminate repeated dates unique!(dates) - # Number of dates + # Number of dates m_dates = length(dates) - # Time delays + # Time delays delay = filter(x -> x["units"] == "us", matches) - # Number of time delays + # Number of time delays m_Δτ = length(delay) # Doppler shifts doppler = filter(x -> x["units"] == "Hz", matches) # Number of Doppler shifts m_Δν = length(doppler) - # Check if there were observations with unknown units + # Check if there were observations with unknown units if m > m_Δτ + m_Δν @warn("""$(m - m_Δτ - m_Δν) observations have units other than us (time delay) or Hz (doppler shift)""") - end + end # Vector of radar observations radar = Vector{RadarJPL{Float64}}(undef, m_dates) # Time delay index i_τ = 1 - # Doppler shift index + # Doppler shift index i_ν = 1 - # Iterate over the dates + # Iterate over the dates for i in eachindex(dates) - # The i_τ-th time delay has the i-th date + # The i_τ-th time delay has the i-th date if (i_τ <= m_Δτ) && (delay[i_τ]["date"] == dates[i]) Δτ = delay[i_τ] - i_τ += 1 - flag_τ = true - else - flag_τ = false - end + i_τ += 1 + flag_τ = true + else + flag_τ = false + end - # The i_ν-th Doppler shift has the i-th date + # The i_ν-th Doppler shift has the i-th date if (i_ν <= m_Δν) && (doppler[i_ν]["date"] == dates[i]) Δν = doppler[i_ν] - i_ν += 1 - flag_ν = true - else - flag_ν = false - end + i_ν += 1 + flag_ν = true + else + flag_ν = false + end if flag_τ && flag_ν radar[i] = RadarJPL(Δτ, Δν) - elseif flag_τ + elseif flag_τ radar[i] = RadarJPL(Δτ, Val(false)) elseif flag_ν radar[i] = RadarJPL(Val(false), Δν) - else + else @warn("""Date $(dates[i]) has no time delay nor Doppler shift measurements""") radar[i] = RadarJPL(Val(false), Val(false)) end - end + end - # Sort radar measurements by date + # Sort radar measurements by date sort!(radar) - return radar -end + return radar +end @doc raw""" jpl_radar_str(radar::RadarJPL{T}) where {T <: AbstractFloat} -Return an observation in JPL format. +Return an observation in JPL format. """ function jpl_radar_str(radar::RadarJPL{T}) where {T <: AbstractFloat} if hasdelay(radar) delay_s = join([ - radar.id, - Dates.format(radar.date, jpl_radar_dateformat), - @sprintf("%.2f", radar.Δτ), + radar.id, + Dates.format(radar.date, jpl_radar_dateformat), + @sprintf("%.2f", radar.Δτ), @sprintf("%1.3f", radar.Δτ_σ), radar.Δτ_units, @sprintf("%.0f", radar.freq), - radar.rcvr.code, - radar.xmit.code, - radar.bouncepoint, + radar.rcvr.code, + radar.xmit.code, + radar.bouncepoint, "" ], "\t", "\n") - else + else delay_s = "" - end + end if hasdoppler(radar) doppler_s = join([ - radar.id, - Dates.format(radar.date, jpl_radar_dateformat), + radar.id, + Dates.format(radar.date, jpl_radar_dateformat), @sprintf("%.4f", radar.Δν), - @sprintf("%1.3f", radar.Δν_σ), + @sprintf("%1.3f", radar.Δν_σ), radar.Δν_units, @sprintf("%.0f", radar.freq), - radar.rcvr.code, - radar.xmit.code, - radar.bouncepoint, + radar.rcvr.code, + radar.xmit.code, + radar.bouncepoint, "" ], "\t", "\n") - else + else doppler_s = "" - end + end # Join everything radar_s = join([delay_s, doppler_s]) @@ -368,13 +368,13 @@ end @doc raw""" write_radar_jpl(radar::Vector{RadarJPL{T}}, filename::String) where {T <: AbstractFloat} -Write `radar` to `filename` in JPL format. +Write `radar` to `filename` in JPL format. """ function write_radar_jpl(radar::Vector{RadarJPL{T}}, filename::String) where {T <: AbstractFloat} open(filename, "w") do file for i in eachindex(radar) line = jpl_radar_str(radar[i]) write(file, line) - end + end end -end \ No newline at end of file +end From f17aace3f57c0862e1738a29943cada47079f920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Wed, 31 May 2023 22:31:44 +0200 Subject: [PATCH 14/46] Update process_radec.jl --- src/observations/process_radec.jl | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index c49457f5..47dda4d7 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -482,7 +482,8 @@ end function radec_astrometry(outfilename::String, opticalobsfile::String, asteph::TaylorInterpolant, ss16asteph::TaylorInterpolant, niter::Int = 5; eo::Bool = true, debias_table::String = "2018") - + # Check that opticalobsfile is a file + @assert isfile(opticalobsfile) "Cannot open file: $opticalobsfile" # Read optical observations radec = read_radec_mpc(opticalobsfile) @@ -497,20 +498,17 @@ function radec_astrometry(outfilename::String, opticalobsfile::String, asteph::T # Number of bodies, including NEA N = Nm1 + 1 - # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec - # NEO - function asteph_et(et) - return auday2kmsec(asteph(et/daysec)[1:6]) - end + # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec + asteph_et(et) = auday2kmsec(asteph(et/daysec)[1:6]) # Earth - function earth_et(et) - return auday2kmsec(ss16asteph(et)[union(3*4-2:3*4,3*(N-1+4)-2:3*(N-1+4))]) - end + # Change x, v units, resp., from au, au/day to km, km/sec + eph_ea = selecteph(ss16asteph, ea) + xve(et) = auday2kmsec(eph_ea(et)) # Sun - function sun_et(et) - return auday2kmsec(ss16asteph(et)[union(3*1-2:3*1,3*(N-1+1)-2:3*(N-1+1))]) - end + # Change x, v units, resp., from au, au/day to km, km/sec + eph_su = selecteph(ss16asteph, su) + xvs(et) = auday2kmsec(eph_su(et)) # Compute ra/dec astrometry datetime_obs, α_obs, δ_obs, α_comp, δ_comp, α_corr, δ_corr, w8s = radec_astrometry(radec, niter; eo = eo, debias_table = debias_table, @@ -539,7 +537,7 @@ end residuals(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = true, debias_table::String = "2018", xvs::Function = sunposvel, xve::Function = earthposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} -Compute optical O-C residuals. +Compute O-C residuals for optical astrometry. See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and [`radec_astrometry`](@ref). @@ -571,4 +569,4 @@ function residuals(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = true, d w = repeat(1 ./ x_jt[end].^2, 2) return res, w -end \ No newline at end of file +end From 9dbb0e092556dbc53fcfead2123cb4fcda63eeef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Wed, 31 May 2023 22:32:04 +0200 Subject: [PATCH 15/46] Update ObsCodes.txt --- src/observations/ObsCodes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/observations/ObsCodes.txt b/src/observations/ObsCodes.txt index f1163858..5f5130e0 100644 --- a/src/observations/ObsCodes.txt +++ b/src/observations/ObsCodes.txt @@ -2321,6 +2321,7 @@ X90 312.132080.963322-0.268189Carina Observatory, Brasilia X93 313.604700.923630-0.382440Munhoz Observatory Y00 315.215040.935906-0.351562SONEAR Observatory, Oliveira Y01 316.015800.940890-0.337985SONEAR 2 Observatory, Belo Horizonte +Y05 316.310000.941254-0.337051SONEAR Wykrota-CEAMIG, Serra da Piedade Y16 318.687940.929268-0.368170ROCG, Campos dos Goytacazes Y28 321.312600.988400-0.151790OASI, Nova Itacuruba Y40 324.038890.989706-0.143217Discovery Observatory, Caruaru From d284978d1152b756268cd13b8424f96a5598b861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 15:00:17 +0200 Subject: [PATCH 16/46] Update Project.toml - Remove ReferenceFramesRotations, Statistics as deps - Use test/Project.toml for test env; remove extras and targets sections in Project.toml --- Project.toml | 15 --------------- test/Project.toml | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) create mode 100644 test/Project.toml diff --git a/Project.toml b/Project.toml index 06ee004c..eeb864f4 100644 --- a/Project.toml +++ b/Project.toml @@ -24,10 +24,8 @@ PlanetaryEphemeris = "d83715d0-7e5f-11e9-1a59-4137b20d8363" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Quadmath = "be4d8f0f-7fa4-5f49-b795-2f01399ab2dd" Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" -ReferenceFrameRotations = "74f56ac7-18b3-5285-802d-d4bd4f104033" SPICE = "5bab7191-041a-5c2e-a744-024b9c3a5062" SatelliteToolbox = "6ac157d9-b43d-51bb-8fab-48bf53814f4a" -Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42" TaylorSeries = "6aa5eb33-94cf-58f4-a9d0-e4b2c4fc25ea" @@ -46,22 +44,9 @@ JLD2 = "0.4" PlanetaryEphemeris = "0.6" Quadmath = "0.5" Query = "1.0" -ReferenceFrameRotations = "3" SPICE = "0.2" SatelliteToolbox = "0.10" StatsBase = "0.33, 0.34" TaylorIntegration = "0.13" TaylorSeries = "0.15" julia = "1.6" - -[extras] -Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" -DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" -Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[targets] -test = ["LinearAlgebra", "Test"] diff --git a/test/Project.toml b/test/Project.toml new file mode 100644 index 00000000..5d90b3ee --- /dev/null +++ b/test/Project.toml @@ -0,0 +1,16 @@ +[deps] +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" +Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" +InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +PlanetaryEphemeris = "d83715d0-7e5f-11e9-1a59-4137b20d8363" +Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +# [compat] +# TaylorIntegration = "0.13" +# PlanetaryEphemeris = "0.6" From 7feb698e93c9d156bfdc819741eb8e81b942bbbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 15:03:05 +0200 Subject: [PATCH 17/46] Add 2023DW observation data file for tests --- test/data/RADEC_2023_DW.dat | 123 ++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 test/data/RADEC_2023_DW.dat diff --git a/test/data/RADEC_2023_DW.dat b/test/data/RADEC_2023_DW.dat new file mode 100644 index 00000000..78794849 --- /dev/null +++ b/test/data/RADEC_2023_DW.dat @@ -0,0 +1,123 @@ + K23D00W*KC2023 02 26.12762 10 41 50.04 -10 23 20.0 18.2 GV~6ErWW94 + K23D00W KC2023 02 26.13393 10 41 44.54 -10 22 57.3 19.2 GV~6ErWW94 + K23D00W KC2023 02 26.14029 10 41 38.99 -10 22 33.9 19.5 GV~6ErWW94 + K23D00W KC2023 02 26.21229 10 40 36.05 -10 18 10.5 20.0 GV~6ErWW95 + K23D00W KC2023 02 26.21785 10 40 31.20 -10 17 50.3 20.0 GV~6ErWW95 + K23D00W KC2023 02 26.22336 10 40 26.36 -10 17 29.8 20.2 GV~6ErWW95 + K23D00W KC2023 02 26.29905010 39 23.74 -10 14 50.8 19.6 GV~6ErWH21 + K23D00W KC2023 02 26.30072610 39 22.31 -10 14 44.6 19.5 GV~6ErWH21 + K23D00W KC2023 02 26.30268310 39 20.64 -10 14 37.5 19.4 GV~6ErWH21 + K23D00W KC2023 02 26.51483810 36 31.98 -09 59 04.9 19.8 GV~6ErW474 + K23D00W KC2023 02 26.51607410 36 30.95 -09 59 00.8 19.4 GV~6ErW474 + K23D00W KC2023 02 26.51669210 36 30.39 -09 58 58.4 19.3 GV~6ErW474 + K23D00W KC2023 02 26.51792810 36 29.37 -09 58 53.8 19.4 GV~6ErW474 + K23D00W KC2023 02 26.99237710 30 19.04 -09 33 13.0 17.8 GX~6ErW958 + K23D00W KC2023 02 26.99624310 30 15.97 -09 33 00.0 18.3 GX~6ErW958 + K23D00W KC2023 02 27.00003610 30 12.92 -09 32 47.1 18.3 GX~6ErW958 + K23D00W KC2023 02 27.01955810 29 57.533-09 31 45.01 19.1 GV~6ErWJ95 + K23D00W KC2023 02 27.02274710 29 54.974-09 31 34.21 19.5 GV~6ErWJ95 + K23D00W KC2023 02 27.02670610 29 51.854-09 31 19.81 19.2 GV~6ErWJ95 + K23D00W |C2023 02 27.09047 10 29 08.49 -09 25 07.5 19.8 Vu~6ErW807 + K23D00W |C2023 02 27.09529 10 29 04.64 -09 24 50.4 19.8 Vu~6ErW807 + K23D00W |C2023 02 27.10011 10 29 00.88 -09 24 33.8 19.8 Vu~6ErW807 + K23D00W KC2023 02 27.37331910 25 38.34 -09 08 10.1 19.9 GV~6ErW474 + K23D00W KC2023 02 27.37513610 25 36.96 -09 08 04.3 19.8 GV~6ErW474 + K23D00W KC2023 02 27.37604510 25 36.31 -09 08 01.0 19.6 GV~6ErW474 + K23D00W KC2023 02 27.37786310 25 34.92 -09 07 54.8 20.1 GV~6ErW474 + K23D00W KC2023 02 27.84406510 20 00.514-08 43 47.28 19.8 rZ~6IqML34 + K23D00W KC2023 02 28.08327810 17 08.954-08 30 39.56 19.8 GV~6ErWJ95 + K23D00W KC2023 02 28.09127410 17 03.338-08 30 12.56 19.7 GV~6ErWJ95 + K23D00W KC2023 02 28.09176410 17 02.46 -08 30 03.4 20.0 GX~6ErWI93 + K23D00W KC2023 02 28.09557210 16 59.74 -08 29 50.8 19.3 GX~6ErWI93 + K23D00W KC2023 02 28.09926010 16 57.11 -08 29 38.3 20.0 GX~6ErWI93 + K23D00W KC2023 02 28.10219610 16 55.567-08 29 36.02 19.7 GV~6ErWJ95 + K23D00W KC2023 02 28.15117 10 16 28.89 -08 26 37.5 19.6 Vq~6ErWH36 + K23D00W KC2023 02 28.15916 10 16 23.19 -08 26 10.6 19.6 Vq~6ErWH36 + K23D00W mC2023 02 28.16844010 16 18.232-08 25 29.46 19.78GV~6ErWI52 + K23D00W mC2023 02 28.17101110 16 16.399-08 25 21.61 19.99GV~6ErWI52 + K23D00W mC2023 02 28.17381110 16 14.419-08 25 11.57 19.53GV~6ErWI52 + K23D00W mC2023 02 28.17638210 16 12.673-08 25 03.54 19.74GV~6ErWI52 + K23D00W KC2023 02 28.30056 10 14 44.76 -08 18 16.0 19.1 RV~6ErW691 + K23D00W KC2023 02 28.31214 10 14 36.61 -08 17 37.9 19.2 RV~6ErW691 + K23D00W KC2023 02 28.88605510 08 28.10 -07 46 58.9 19.5 GU~6IqML06 + K23D00W KC2023 02 28.88633110 08 27.87 -07 46 58.4 19.6 GU~6IqML06 + K23D00W KC2023 03 01.09750210 06 14.926-07 34 04.87 19.7 GX~6ErWY00 + K23D00W KC2023 03 01.11043910 06 06.437-07 33 23.88 20.0 GX~6ErWY00 + K23D00W KC2023 03 01.12317910 05 58.113-07 32 44.46 20.4 GX~6ErWY00 + K23D00W |C2023 03 01.21364 10 05 02.22 -07 27 46.4 19.8 Vu~6IqM807 + K23D00W |C2023 03 01.21720 10 04 59.98 -07 27 34.9 20.1 Vu~6IqM807 + K23D00W |C2023 03 01.22452 10 04 55.23 -07 27 12.2 19.8 Vu~6IqM807 + K23D00W KC2023 03 01.29513 10 04 14.27 -07 25 22.0 19.9 RV~6ErW691 + K23D00W KC2023 03 01.30289 10 04 09.32 -07 24 57.7 19.2 RV~6ErW691 + K23D00W KC2023 03 01.31066 10 04 04.34 -07 24 34.5 19.6 RV~6ErW691 + K23D00W .C2023 03 02.03196 09 57 07.53 -06 48 20.8 19.1 RV~6IqM950 + K23D00W .C2023 03 02.04667 09 56 58.80 -06 47 37.6 19.1 RV~6IqM950 + K23D00W .C2023 03 02.06140 09 56 50.06 -06 46 54.4 19.1 RV~6IqM950 + K23D00W 1C2023 03 02.85549909 49 52.127-06 09 26.45 20.2 GV~6IqMZ84 + K23D00W 1C2023 03 02.85820109 49 50.695-06 09 19.44 20.3 GV~6IqMZ84 + K23D00W 1C2023 03 02.86090109 49 49.235-06 09 11.73 19.9 GV~6IqMZ84 + K23D00W KC2023 03 04.24171 09 38 50.70 -05 08 48.6 20.3 RV~6IqM291 + K23D00W KC2023 03 04.26765 09 38 38.43 -05 07 44.0 V~6IqM291 + K23D00W KC2023 03 04.97492809 33 37.19 -04 39 30.8 20.2 GU~6IqML06 + K23D00W KC2023 03 04.97633409 33 36.56 -04 39 27.6 19.9 GU~6IqML06 + K23D00W 4C2023 03 09.05679509 11 01.665-02 20 50.12 20.9 GV~6VNlW85 + K23D00W 4C2023 03 09.06694609 10 58.684-02 20 32.84 20.8 GV~6VNlW85 + K23D00W 4C2023 03 09.07580009 10 56.116-02 20 17.70 21.2 GV~6VNlW85 + K23D00W KC2023 03 10.07650409 06 42.51 -01 54 07.0 X~6VNlW62 + K23D00W KC2023 03 10.09679709 06 37.17 -01 53 34.7 20.5 GX~6VNlW62 + K23D00W KC2023 03 10.11709909 06 31.85 -01 53 02.4 20.6 GX~6VNlW62 + K23D00W KC2023 03 10.87422 09 03 36.955-01 32 20.90 21.2 GX~6VNlL87 + K23D00W KC2023 03 10.88471 09 03 34.411-01 32 06.36 20.4 GX~6VNlL87 + K23D00W KC2023 03 11.21539 09 02 23.09 -01 24 58.1 21.5 Ro~6VNl291 + K23D00W KC2023 03 11.23274 09 02 18.97 -01 24 33.0 o~6VNl291 + K23D00W 2C2023 03 11.88641909 00 03.510-01 07 48.54 21.7 GV~6VNlK92 + K23D00W 2C2023 03 11.89503709 00 01.624-01 07 37.03 21.4 GV~6VNlK92 + K23D00W 2C2023 03 11.90366008 59 59.712-01 07 24.83 21.6 GV~6VNlK92 + K23D00W KC2023 03 11.93841 08 59 52.205-01 06 45.32 20.3 GX~6VNlL87 + K23D00W KC2023 03 11.93961 08 59 51.926-01 06 44.03 20.2 GX~6VNlL87 + K23D00W KC2023 03 12.81534 08 57 08.904-00 47 05.10 X~6VNlL87 + K23D00W KC2023 03 12.82659 08 57 06.610-00 46 49.94 20.4 GX~6VNlL87 + K23D00W KC2023 03 12.83793 08 57 04.255-00 46 35.08 20.0 GX~6VNlL87 + K23D00W 2C2023 03 13.05856408 56 25.317-00 41 43.43 21.8 GV~6VNlW86 + K23D00W 2C2023 03 13.07094308 56 22.864-00 41 27.63 21.8 GV~6VNlW86 + K23D00W 2C2023 03 13.08487308 56 20.082-00 41 09.71 21.6 GV~6VNlW86 + K23D00W KC2023 03 13.11090 08 56 16.38 -00 41 45.8 21.8 Vq~6VNlH36 + K23D00W KC2023 03 13.12641 08 56 13.38 -00 41 26.3 22.0 Vq~6VNl734 + K23D00W C2023 03 13.13945608 56 11.493-00 41 05.78 21.4 GV~6VNlH01 + K23D00W KC2023 03 13.14195 08 56 10.32 -00 41 06.7 q~6VNlH36 + K23D00W C2023 03 13.14286308 56 10.830-00 41 01.42 21.6 GV~6VNlH01 + K23D00W KC2023 03 13.14821 08 56 09.06 -00 40 58.7 21.8 Vq~6VNl734 + K23D00W C2023 03 13.15637208 56 08.190-00 40 44.18 21.4 GV~6VNlH01 + K23D00W KC2023 03 13.16090 08 56 07.59 -00 40 36.8 o~6VNl291 + K23D00W C2023 03 13.16255608 56 06.979-00 40 36.27 21.3 GV~6VNlH01 + K23D00W KC2023 03 13.17151 08 56 05.48 -00 40 22.8 21.4 Ro~6VNl291 + K23D00W KC2023 03 13.18212 08 56 03.40 -00 40 09.8 21.4 Ro~6VNl291 + K23D00W KC2023 03 13.89706 08 54 01.882-00 24 25.13 20.4 GX~6VNlL87 + K23D00W KC2023 03 13.90587 08 54 00.266-00 24 14.65 21.0 GX~6VNlL87 + K23D00W KC2023 03 13.91447 08 53 58.646-00 24 04.61 20.3 GX~6VNlL87 + K23D00W LC2023 03 14.04842008 53 39.687-00 21 17.57 21.3 GX~6VNl807 + K23D00W LC2023 03 14.05993108 53 37.550-00 21 02.85 21.6 GX~6VNl807 + K23D00W KC2023 03 14.17439 08 53 19.48 -00 19 48.1 21.8 Ro~6VNl291 + K23D00W KC2023 03 14.21103 08 53 13.00 -00 19 04.8 o~6VNl291 + K23D00W 2C2023 03 15.04936308 51 08.796-00 01 58.62 21.9 GV~6VNlW86 + K23D00W 2C2023 03 15.05826008 51 07.335-00 01 48.69 22.0 GV~6VNlW86 + K23D00W KC2023 03 15.06387908 51 07.24 -00 02 48.0 21.9 GV~6VNlH21 + K23D00W 2C2023 03 15.06716808 51 05.881-00 01 38.66 21.7 GV~6VNlW86 + K23D00W KC2023 03 15.06822008 51 06.55 -00 02 43.0 22.0 GV~6VNlH21 + K23D00W (C2023 03 15.55940908 49 55.602+00 07 22.75 22.4 GV~6VNlE10 + K23D00W (C2023 03 15.56530608 49 54.700+00 07 29.00 21.9 GV~6VNlE10 + K23D00W (C2023 03 15.57051908 49 53.913+00 07 34.74 22.1 GV~6VNlE10 + K23D00W 1C2023 03 15.89724 08 49 11.91 +00 12 11.0 22.1 VX~6VNl033 + K23D00W 1C2023 03 15.90083 08 49 11.41 +00 12 15.2 22.2 VX~6VNl033 + K23D00W 1C2023 03 15.90441 08 49 10.88 +00 12 18.9 22.0 VX~6VNl033 + K23D00W KC2023 03 16.06829508 48 51.01 +00 15 17.4 21.2 GX~6VNlW62 + K23D00W KC2023 03 16.07698908 48 49.78 +00 15 26.7 21.3 GX~6VNlW62 + K23D00W KC2023 03 16.08568908 48 48.49 +00 15 35.8 X~6VNlW62 + K23D00W 0C2023 03 18.45831608 44 21.170+00 54 05.97 22.54GV~6VNlT12 + K23D00W 0C2023 03 18.46207108 44 20.761+00 54 09.28 22.60GV~6VNlT12 + K23D00W 0C2023 03 18.46589808 44 20.354+00 54 12.69 22.53GV~6VNlT12 + K23D00W &C2023 03 19.00066008 43 34.315+01 02 40.16 22.8 GV~6VNl309 + K23D00W &C2023 03 19.00265708 43 34.098+01 02 41.96 22.5 GV~6VNl309 + K23D00W &C2023 03 19.00472108 43 33.876+01 02 43.68 22.7 GV~6VNl309 + K23D00W &C2023 03 19.00688808 43 33.639+01 02 45.50 22.6 GV~6VNl309 + K23D00W &C2023 03 19.00888608 43 33.425+01 02 47.29 22.7 GV~6VNl309 From eab9e1a738cfe5c46aed110af1ff51cb68337784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 15:03:28 +0200 Subject: [PATCH 18/46] Test only on julia 1.9+ --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c6b4b9f1..ab3c6112 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -18,8 +18,8 @@ jobs: fail-fast: false matrix: version: - - '1.6' - - '1' + - '1.9' + # - '1' - 'nightly' os: - ubuntu-latest From 7a10deeea7ce704c8d41a163b32a7cc265c230a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 15:05:15 +0200 Subject: [PATCH 19/46] Update src/NEOs.jl --- src/NEOs.jl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 4424e06b..7e41669e 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -3,21 +3,19 @@ module NEOs # __precompile__(false) import Base: hash, ==, show, isless, isnan, convert -import ReferenceFrameRotations: orthonormalize, smallangle_to_dcm, smallangle_to_rot -import PlanetaryEphemeris, SatelliteToolbox +import PlanetaryEphemeris using Distributed, JLD2, TaylorIntegration, Printf, DelimitedFiles, Test, LinearAlgebra, Dates, EarthOrientation, SPICE, Quadmath, LazyArtifacts, DataFrames, TaylorSeries, InteractiveUtils, AutoHashEquals +import PlanetaryEphemeris as PE using PlanetaryEphemeris: daysec, su, ea, α_p_sun, δ_p_sun, t2c_jpl_de430, pole_rotation, au, c_au_per_day, R_sun, c_cm_per_sec, c_au_per_sec, yr, RE, TaylorInterpolant, Rx, Ry, Rz, semimajoraxis, eccentricity, inclination, longascnode, argperi, timeperipass, - nbodyind, PE, ordpres_differentiate, numberofbodies, kmsec2auday, auday2kmsec + nbodyind, ordpres_differentiate, numberofbodies, kmsec2auday, auday2kmsec using Healpix: ang2pixRing, Resolution -using SatelliteToolbox: nutation_fk5, J2000toGMST, rECEFtoECI, get_ΔAT, JD_J2000, EOPData_IAU1980, - rECItoECI, DCM, TOD, GCRF, ITRF, rECItoECI, PEF, orbsv, EOPData_IAU2000A, get_iers_eop_iau_1980, - get_iers_eop_iau_2000A -import SatelliteToolbox.r_itrf_to_pef_fk5 +using SatelliteToolbox: get_iers_eop_iau_2000A, EOPData_IAU1980, EOPData_IAU2000A, JD_J2000, + orbsv, sv_ecef_to_eci, get_ΔAT, nutation_fk5 using Dates: format using HTTP: get using IntervalRootFinding: roots, interval, Interval, mid From 3af543e4eabf276ae85090e635663dd7b8717b3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 15:16:01 +0200 Subject: [PATCH 20/46] Set niter=5 by default, and remove eo kwarg --- src/observations/process_radec.jl | 96 ++++++------------------------- 1 file changed, 19 insertions(+), 77 deletions(-) diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index 47dda4d7..232734e0 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -1,12 +1,13 @@ @doc raw""" - compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 10; eo::Bool = true, + compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 5; xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} - compute_radec(obs::RadecMPC{T}, niter::Int = 10; eo::Bool = true, xve::Function = earthposvel, xvs::Function = sunposvel, + compute_radec(obs::RadecMPC{T}, niter::Int = 5; xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} - compute_radec(obs::Vector{RadecMPC{T}}, niter::Int=10; eo::Bool=true, xve::Function=earthposvel, xvs::Function=sunposvel, + compute_radec(obs::Vector{RadecMPC{T}}, niter::Int=5; xve::Function=earthposvel, xvs::Function=sunposvel, xva::Function=apophisposvel197) where {T <: AbstractFloat} Compute astrometric right ascension and declination (both in arcsec) for a set of MPC-formatted observations. +Corrections due to Earth orientation, LOD, polar motion are considered in computations. # Arguments @@ -14,26 +15,22 @@ Compute astrometric right ascension and declination (both in arcsec) for a set o - `t_r_utc::DateTime`: UTC time of astrometric observation. - `obs::RadecMPC{T}/Vector{RadecMPC{T}}`: observations. - `niter::Int`: number of light-time solution iterations. -- `eo::Bool`: compute corrections due to Earth orientation, LOD, polar motion. - `xve::Function`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xvs::Function`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xva::Function`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ -function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 10; eo::Bool = true, +function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 5; xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} # Transform receiving time from UTC to TDB seconds since J2000 et_r_secs = datetime2et(t_r_utc) # Compute geocentric position/velocity of receiving antenna in inertial frame [km, km/s] - RV_r = obsposvelECI(observatory, et_r_secs, eo = eo) + RV_r = obsposvelECI(observatory, et_r_secs) R_r = RV_r[1:3] - V_r = RV_r[4:6] # Earth's barycentric position and velocity at receive time rv_e_t_r = xve(et_r_secs) r_e_t_r = rv_e_t_r[1:3] - v_e_t_r = rv_e_t_r[4:6] # Receiver barycentric position and velocity at receive time r_r_t_r = r_e_t_r + R_r - v_r_t_r = v_e_t_r + V_r # Asteroid barycentric position and velocity at receive time rv_a_t_r = xva(et_r_secs) r_a_t_r = rv_a_t_r[1:3] @@ -151,12 +148,12 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter: return α_as, δ_as # right ascension, declination both in arcsec end -function compute_radec(obs::RadecMPC{T}, niter::Int = 10; eo::Bool = true, xve::Function = earthposvel, xvs::Function = sunposvel, +function compute_radec(obs::RadecMPC{T}, niter::Int = 5; xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} - return compute_radec(obs.observatory, obs.date, niter; eo = eo, xve = xve, xvs = xvs, xva = xva) + return compute_radec(obs.observatory, obs.date, niter; xve = xve, xvs = xvs, xva = xva) end -function compute_radec(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = true, xve::Function = earthposvel, xvs::Function = sunposvel, +function compute_radec(obs::Vector{RadecMPC{T}}, niter::Int = 5; xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} # Number of observations @@ -177,7 +174,7 @@ function compute_radec(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = tru # Iterate over the number of observations for i in 1:n_optical_obs - vra[i], vdec[i] = compute_radec(obs[i], niter, eo = eo, xve = xve, xvs = xvs, xva = xva) + vra[i], vdec[i] = compute_radec(obs[i], niter, xve = xve, xvs = xvs, xva = xva) end return vra, vdec # arcsec, arcsec @@ -386,13 +383,13 @@ function w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} end @doc raw""" - radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = true, debias_table::String = "2018", + radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 5; debias_table::String = "2018", xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} radec_astrometry(outfilename::String, opticalobsfile::String, asteph::TaylorInterpolant, ss16asteph::TaylorInterpolant, - niter::Int = 5; eo::Bool = true, debias_table::String = "2018") + niter::Int = 5; debias_table::String = "2018") Compute optical astrometry, i.e. dates of observation plus observed, computed, debiasing corrections and statistical weights for -right ascension and declination (in arcsec). +right ascension and declination (in arcsec). Corrections to Earth orientation parameters provided by IERS are computed by default. See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and [`Healpix.ang2pixRing`](@ref). @@ -404,7 +401,6 @@ See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and - `asteph::TaylorInterpolant`: NEO's ephemeris. - `ss16asteph::TaylorInterpolant`: solar system ephemeris. - `niter::Int`: number of light-time solution iterations. -- `eo::Bool`: compute corrections due to Earth orientation, LOD, polar motion. - `debias_table::String`: possible values are: - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, @@ -413,7 +409,7 @@ See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and - `xvs::Function`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xva::Function`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ -function radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = true, debias_table::String = "2018", +function radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 5; debias_table::String = "2018", xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} # Number of observations @@ -463,7 +459,7 @@ function radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = α_obs[i] = rad2arcsec(obs[i].α) * cos(obs[i].δ) # arcsec # Computed ra/dec - α_comp_as, δ_comp_as = compute_radec(obs[i], niter, eo=eo, xve=xve, xvs=xvs, xva=xva) + α_comp_as, δ_comp_as = compute_radec(obs[i], niter, xve=xve, xvs=xvs, xva=xva) # Multiply by metric factor cos(dec) α_comp[i] = α_comp_as * cos(obs[i].δ) # arcsec δ_comp[i] = δ_comp_as # arcsec @@ -480,64 +476,11 @@ function radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = return datetime_obs, α_obs, δ_obs, α_comp, δ_comp, α_corr, δ_corr, w8s end -function radec_astrometry(outfilename::String, opticalobsfile::String, asteph::TaylorInterpolant, ss16asteph::TaylorInterpolant, - niter::Int = 5; eo::Bool = true, debias_table::String = "2018") - # Check that opticalobsfile is a file - @assert isfile(opticalobsfile) "Cannot open file: $opticalobsfile" - # Read optical observations - radec = read_radec_mpc(opticalobsfile) - - # Check that first and last observation times are within interpolation interval - Δt_0 = datetime2julian(radec[1].date) - JD_J2000 - asteph.t0 - Δt_f = datetime2julian(radec[end].date) - JD_J2000 - asteph.t0 - t_min, t_max = minmax(asteph.t[1], asteph.t[end]) - @assert t_min ≤ Δt_0 ≤ Δt_f ≤ t_max "First and/or last observation times are outside interpolation interval" - - # Number of massive bodies - Nm1 = (size(ss16asteph.x)[2]-13) ÷ 6 - # Number of bodies, including NEA - N = Nm1 + 1 - - # NEO - # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec - asteph_et(et) = auday2kmsec(asteph(et/daysec)[1:6]) - # Earth - # Change x, v units, resp., from au, au/day to km, km/sec - eph_ea = selecteph(ss16asteph, ea) - xve(et) = auday2kmsec(eph_ea(et)) - # Sun - # Change x, v units, resp., from au, au/day to km, km/sec - eph_su = selecteph(ss16asteph, su) - xvs(et) = auday2kmsec(eph_su(et)) - - # Compute ra/dec astrometry - datetime_obs, α_obs, δ_obs, α_comp, δ_comp, α_corr, δ_corr, w8s = radec_astrometry(radec, niter; eo = eo, debias_table = debias_table, - xve = earth_et, xvs = sun_et, xva = asteph_et) - - # Save data to file - println("Saving data to file: $outfilename") - JLD2.jldopen(outfilename, "w") do file - # Write variables to jld2 file - JLD2.write(file, - "datetime_obs", datetime_obs, - "α_obs", α_obs, - "δ_obs", δ_obs, - "α_comp", α_comp, - "δ_comp", δ_comp, - "α_corr", α_corr, - "δ_corr", δ_corr, - "w8s", w8s - ) - end - - return nothing -end - @doc raw""" - residuals(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = true, debias_table::String = "2018", + residuals(obs::Vector{RadecMPC{T}}, niter::Int = 5; debias_table::String = "2018", xvs::Function = sunposvel, xve::Function = earthposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} -Compute O-C residuals for optical astrometry. +Compute O-C residuals for optical astrometry. Corrections due to Earth orientation, LOD, polar motion are computed by default. See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and [`radec_astrometry`](@ref). @@ -545,7 +488,6 @@ See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and - `obs::Vector{RadecMPC{T}}`: vector of observations. - `niter::Int`: number of light-time solution iterations. -- `eo::Bool`: compute corrections due to Earth orientation, LOD, polar motion. - `debias_table::String`: possible values are: - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, @@ -554,11 +496,11 @@ See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and - `xve::Function`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xva::Function`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ -function residuals(obs::Vector{RadecMPC{T}}, niter::Int = 10; eo::Bool = true, debias_table::String = "2018", +function residuals(obs::Vector{RadecMPC{T}}, niter::Int = 5; debias_table::String = "2018", xvs::Function = sunposvel, xve::Function = earthposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} # Optical astrometry (dates + observed + computed + debiasing + weights) - x_jt = radec_astrometry(obs, niter; eo = eo, debias_table = debias_table, xvs = xvs, xve = xve, xva = xva) + x_jt = radec_astrometry(obs, niter; debias_table = debias_table, xvs = xvs, xve = xve, xva = xva) # Right ascension residuals res_α = x_jt[2] .- x_jt[6] .- x_jt[4] # Declination residuals From 51ea39bee70f379aa8dc711b0dad2181f9dadd3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 15:28:58 +0200 Subject: [PATCH 21/46] Update src/observations/process_radar.jl - Use IAU200A Earth orientation model by default - Remove `eo` kwarg - Pass `niter` and `tord` as kwargs - Remove one unused method of `compute_delay` - Remove Yeomans et al. (1992) method to compute time-delay and Doppler shift - Set `tord` by default to 10 - Avoid ::Function type assertions to help creation of specialized methods - Update residuals method --- src/observations/process_radar.jl | 667 +++--------------------------- 1 file changed, 52 insertions(+), 615 deletions(-) diff --git a/src/observations/process_radar.jl b/src/observations/process_radar.jl index 028e966e..47e5b3a5 100644 --- a/src/observations/process_radar.jl +++ b/src/observations/process_radar.jl @@ -240,236 +240,10 @@ function tropo_delay(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Numbe end @doc raw""" - compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, t_offset::Real, niter::Int = 10; eo::Bool = true, - xve = earthposvel, xvs = sunposvel, xva = apophisposvel197) where {T <: AbstractFloat} - compute_delay(radar::RadarJPL{T}, t_offset::Real, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, - xva = apophisposvel197) where {T <: AbstractFloat} - -Compute radar-astrometric round-trip time (``\mu``s). - -See https://doi.org/10.1086/116062. - -# Arguments - -- `observatory::ObservatoryMPC{T}`: observing station. -- `t_r_utc::DateTime`: UTC time of echo reception. -- `radar::RadarJPL{T}`: radar observation. -- `t_offset::Real`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). -- `niter::Int`: number of light-time solution iterations. -- `eo::Bool`: compute corrections due to Earth orientation, LOD, polar motion. -- `xve`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xvs`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -""" -function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, t_offset::Real, niter::Int = 10; eo::Bool = true, - xve = earthposvel, xvs = sunposvel, xva = apophisposvel197) where {T <: AbstractFloat} - # Transform receiving time from UTC to TDB seconds since j2000 - et_r_secs = datetime2et(t_r_utc) + t_offset - # Compute geocentric position/velocity of receiving antenna in inertial frame (au, au/day) - RV_r = obsposvelECI(observatory, et_r_secs, eo = eo) - R_r = RV_r[1:3] - V_r = RV_r[4:6] - # Earth's barycentric position and velocity at receive time - rv_e_t_r = xve(et_r_secs) - r_e_t_r = rv_e_t_r[1:3] - v_e_t_r = rv_e_t_r[4:6] - # Receiver barycentric position and velocity at receive time - r_r_t_r = r_e_t_r + R_r - # Asteroid barycentric position and velocity at receive time - rv_a_t_r = xva(et_r_secs) - r_a_t_r = rv_a_t_r[1:3] - # Sun barycentric position and velocity at receive time - rv_s_t_r = xvs(et_r_secs) - r_s_t_r = rv_s_t_r[1:3] - - # Down-leg iteration - # τ_D first approximation - # See equation (1) of https://doi.org/10.1086/116062 - ρ_vec_r = r_a_t_r - r_r_t_r - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) - # -R_b/c, but delay is wrt asteroid Center (Brozovic et al., 2018) - τ_D = ρ_r/clightkms # (seconds) - # Bounce time, new estimate - # See equation (2) of https://doi.org/10.1086/116062 - et_b_secs = et_r_secs - τ_D - - # Allocate memmory for time delays - Δτ_D = zero(τ_D) # Total time delay - Δτ_rel_D = zero(τ_D) # Shapiro delay - # Δτ_corona_D = zero(τ_D) # Delay due to Solar corona - Δτ_tropo_D = zero(τ_D) # Delay due to Earth's troposphere - - for i in 1:niter - # Asteroid barycentric position (in au) and velocity (in au/day) at bounce time (TDB) - rv_a_t_b = xva(et_b_secs) - r_a_t_b = rv_a_t_b[1:3] - v_a_t_b = rv_a_t_b[4:6] - # Estimated position of the asteroid's center of mass relative to the recieve point - # See equation (3) of https://doi.org/10.1086/116062. - ρ_vec_r = r_a_t_b - r_r_t_r - # Magnitude of ρ_vec_r - # See equation (4) of https://doi.org/10.1086/116062. - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) - - # Compute down-leg Shapiro delay - # NOTE: when using PPN, substitute 2 -> 1+γ in expressions for Shapiro delay, - # Δτ_rel_[D|U] - - # Earth's position at t_r - e_D_vec = r_r_t_r - r_s_t_r - # Heliocentric distance of Earth at t_r - e_D = sqrt(e_D_vec[1]^2 + e_D_vec[2]^2 + e_D_vec[3]^2) - # Barycentric position and velocity of Sun at estimated bounce time - rv_s_t_b = xvs(et_b_secs) - r_s_t_b = rv_s_t_b[1:3] - # Heliocentric position of asteroid at t_b - p_D_vec = r_a_t_b - r_s_t_b - # Heliocentric distance of asteroid at t_b - p_D = sqrt(p_D_vec[1]^2 + p_D_vec[2]^2 + p_D_vec[3]^2) - # Signal path distance (down-leg) - q_D = ρ_r - - # Shapiro correction to time-delay - Δτ_rel_D = shapiro_delay(e_D, p_D, q_D) # seconds - # Troposphere correction to time-delay - Δτ_tropo_D = tropo_delay(R_r, ρ_vec_r) # seconds - # Δτ_corona_D = corona_delay(constant_term.(r_a_t_b), r_r_t_r, r_s_t_r, F_tx, station_code) # seconds - # Total time-delay - Δτ_D = Δτ_rel_D # + Δτ_tropo_D #+ Δτ_corona_D # seconds - - # New estimate - p_dot_23 = dot(ρ_vec_r, v_a_t_b)/ρ_r - # Time delay correction - Δt_2 = (τ_D - ρ_r/clightkms - Δτ_rel_D)/(1.0-p_dot_23/clightkms) - # Time delay new estimate - τ_D = τ_D - Δt_2 - # Bounce time, new estimate - # See equation (2) of https://doi.org/10.1086/116062 - et_b_secs = et_r_secs - τ_D - - end - # Asteroid's barycentric position and velocity at bounce time t_b - rv_a_t_b = xva(et_b_secs) - r_a_t_b = rv_a_t_b[1:3] - v_a_t_b = rv_a_t_b[4:6] - - # Up-leg iteration - # τ_U first estimation - # See equation (5) of https://doi.org/10.1086/116062 - τ_U = τ_D - # Transmit time, 1st estimate - # See equation (6) of https://doi.org/10.1086/116062 - et_t_secs = et_b_secs - τ_U - # Geocentric position and velocity of transmitting antenna in inertial frame (au, au/day) - RV_t = obsposvelECI(observatory, et_t_secs, eo = eo) - R_t = RV_t[1:3] - V_t = RV_t[4:6] - # Barycentric position and velocity of the Earth at transmit time - rv_e_t_t = xve(et_t_secs) - r_e_t_t = rv_e_t_t[1:3] - v_e_t_t = rv_e_t_t[4:6] - # Transmitter barycentric position and velocity of at transmit time - r_t_t_t = r_e_t_t + R_t - # Up-leg vector at transmit time - # See equation (7) of https://doi.org/10.1086/116062 - ρ_vec_t = r_a_t_b - r_t_t_t - # Magnitude of up-leg vector - ρ_t = sqrt(ρ_vec_t[1]^2 + ρ_vec_t[2]^2 + ρ_vec_t[3]^2) - - # Allocate memmory for time delays - Δτ_U = zero(τ_U) # Total time delay - Δτ_rel_U = zero(τ_U) # Shapiro delay - # Δτ_corona_U = zero(τ_U) # Delay due to Solar corona - Δτ_tropo_U = zero(τ_U) # Delay due to Earth's troposphere - - for i in 1:niter - # Geocentric position and velocity of transmitting antenna in inertial frame (au, au/day) - # TODO: remove `constant_term` to take into account dependency of R_t, V_t wrt initial - # conditions variations via et_t_secs - RV_t = obsposvelECI(observatory, et_t_secs, eo = eo) - R_t = RV_t[1:3] - V_t = RV_t[4:6] - # Earth's barycentric position and velocity at the transmit time - rv_e_t_t = xve(et_t_secs) - r_e_t_t = rv_e_t_t[1:3] - v_e_t_t = rv_e_t_t[4:6] - # Barycentric position and velocity of the transmitter at the transmit time - r_t_t_t = r_e_t_t + R_t - v_t_t_t = v_e_t_t + V_t - # Up-leg vector and its magnitude at transmit time - # See equation (7) of https://doi.org/10.1086/116062 - ρ_vec_t = r_a_t_b - r_t_t_t - ρ_t = sqrt(ρ_vec_t[1]^2 + ρ_vec_t[2]^2 + ρ_vec_t[3]^2) - - # Compute up-leg Shapiro delay - - # Sun barycentric position and velocity (in au, au/day) at transmit time (TDB) - rv_s_t_t = xvs(et_t_secs) - r_s_t_t = rv_s_t_t[1:3] - # Heliocentric position of Earth at t_t - e_U_vec = r_t_t_t - r_s_t_t - # Heliocentric distance of Earth at t_t - e_U = sqrt(e_U_vec[1]^2 + e_U_vec[2]^2 + e_U_vec[3]^2) - # Barycentric position/velocity of Sun at bounce time - rv_s_t_b = xvs(et_b_secs) - r_s_t_b = rv_s_t_b[1:3] - # Heliocentric position of asteroid at t_b - p_U_vec = r_a_t_b - r_s_t_b - # Heliocentric distance of asteroid at t_b - p_U = sqrt(p_U_vec[1]^2 + p_U_vec[2]^2 + p_U_vec[3]^2) - - q_U_vec = r_a_t_b - r_e_t_t - # Signal path distance (up-leg) - q_U = ρ_t - # Shapiro correction to time-delay - Δτ_rel_U = shapiro_delay(e_U, p_U, q_U) # seconds - # Troposphere correction to time-delay - Δτ_tropo_U = tropo_delay(R_t, ρ_vec_t) # seconds - # Delay due to Solar corona - # Δτ_corona_U = corona_delay(constant_term.(r_t_t_t), constant_term.(r_a_t_b), constant_term.(r_s_t_b), F_tx, station_code) # seconds - # Total time delay - Δτ_U = Δτ_rel_U # + Δτ_tropo_U #+ Δτ_corona_U # seconds - - # New estimate - p_dot_12 = -dot(ρ_vec_t, v_t_t_t)/ρ_t - # Time-delay correction - Δt_1 = (τ_U - ρ_t/clightkms - Δτ_rel_U)/(1.0-p_dot_12/clightkms) - # Time delay new estimate - τ_U = τ_U - Δt_1 - # Transmit time, new estimate - # See equation (6) of https://doi.org/10.1086/116062 - et_t_secs = et_b_secs - τ_U - end - - # Compute TDB-UTC at transmit time - # Corrections to TT-TDB from Moyer (2003) / Folkner et al. (2014) due to position - # of measurement station on Earth are of order 0.01μs - # Δtt_tdb_station_t = - dot(v_e_t_t, r_t_t_t-r_e_t_t)/clightkms^2 - tdb_utc_t = tdb_utc(et_t_secs) # + Δtt_tdb_station_t - - # Compute TDB-UTC at receive time - # Corrections to TT-TDB from Moyer (2003) / Folkner et al. (2014) due to position - # of measurement station on Earth are of order 0.01μs - # Δtt_tdb_station_r = - dot(v_e_t_r, r_r_t_r-r_e_t_r)/clightkms^2 - tdb_utc_r = tdb_utc(et_r_secs) # + Δtt_tdb_station_r - - # Compute total time delay (UTC seconds); relativistic delay is already included in τ_D, τ_U - # See equation (9) of https://doi.org/10.1086/116062 - τ = (τ_D + τ_U) + (Δτ_tropo_D + Δτ_tropo_U) + (tdb_utc_t - tdb_utc_r) # seconds - - # Total signal delay (μs) - return 1e6τ -end -function compute_delay(radar::RadarJPL{T}, t_offset::Real, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, - xva = apophisposvel197) where {T <: AbstractFloat} - return compute_delay(radar.rcvr, radar.date, t_offset, niter; eo = eo, xve = xve, xvs = xvs, xva = xva) -end - -@doc raw""" - compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 10; eo::Bool = true, xve::TaylorInterpolant = earthposvel, - xvs::TaylorInterpolant = sunposvel, xva::TaylorInterpolant = apophisposvel197, tord::Int = xva.x[1].order) where {T <: AbstractFloat} - compute_delay(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, xve::TaylorInterpolant = earthposvel, - xvs::TaylorInterpolant = sunposvel, xva::TaylorInterpolant = apophisposvel197, tord::Int = xva.x[1].order) where {T <: AbstractFloat} + compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; tord::Int = 5, niter::Int = 10, xve::TaylorInterpolant = earthposvel, + xvs::TaylorInterpolant = sunposvel, xva::TaylorInterpolant = apophisposvel197) where {T <: AbstractFloat} + compute_delay(radar::RadarJPL{T}; tord::Int = 5, niter::Int = 10, xve::TaylorInterpolant = earthposvel, + xvs::TaylorInterpolant = sunposvel, xva::TaylorInterpolant = apophisposvel197) where {T <: AbstractFloat} Compute Taylor series expansion of time-delay observable around echo reception time. This allows to compute dopplers via automatic differentiation using @@ -477,7 +251,8 @@ allows to compute dopplers via automatic differentiation using \nu = -f\frac{d\tau}{dt}, ``` where ``f`` is the transmitter frequency (MHz) and ``\tau`` is the time-delay at reception -time ``t``. +time ``t``. Computed values include corrections due to Earth orientation, LOD and polar +motion. See https://doi.org/10.1086/116062. @@ -487,25 +262,23 @@ See https://doi.org/10.1086/116062. - `observatory::ObservatoryMPC{T}`: observing station. - `t_r_utc::DateTime`: UTC time of echo reception. -- `radar::RadarJPL{T}`: radar observation. +- `tord::Int`: order of Taylor expansions. - `niter::Int`: number of light-time solution iterations. -- `eo::Bool`: compute corrections due to Earth orientation, LOD, polar motion. - `xve::TaylorInterpolant`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xvs::TaylorInterpolant`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xva::TaylorInterpolant`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `tord::Int`: order of Taylor expansions. """ -function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 10; eo::Bool = true, xve::Function = earthposvel, - xvs::Function = sunposvel, xva::Function = apophisposvel197, tord::Int = xva.x[1].order) where {T <: AbstractFloat} +function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; tord::Int = 5, niter::Int = 10, + xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph = apophisposvel197) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} # Transform receiving time from UTC to TDB seconds since j2000 et_r_secs_0 = datetime2et(t_r_utc) # Auxiliary to evaluate JT ephemeris xva1et0 = xva(et_r_secs_0)[1] # et_r_secs_0 as a Taylor polynomial - et_r_secs = Taylor1([et_r_secs_0,1.0].*one(xva1et0), tord) + et_r_secs = Taylor1([et_r_secs_0,one(et_r_secs_0)].*one(xva1et0), tord) # Compute geocentric position/velocity of receiving antenna in inertial frame (au, au/day) - RV_r = obsposvelECI(observatory, et_r_secs, eo = eo) + RV_r = obsposvelECI(observatory, et_r_secs) R_r = RV_r[1:3] # Earth's barycentric position and velocity at receive time r_e_t_r = xve(et_r_secs)[1:3] @@ -596,7 +369,7 @@ function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter: # See equation (6) of https://doi.org/10.1086/116062 et_t_secs = et_b_secs - τ_U # Geocentric position and velocity of transmitting antenna in inertial frame (au, au/day) - RV_t = obsposvelECI(observatory, et_t_secs, eo = eo) + RV_t = obsposvelECI(observatory, et_t_secs) R_t = RV_t[1:3] V_t = RV_t[4:6] # Barycentric position and velocity of the Earth at transmit time @@ -621,7 +394,7 @@ function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter: # Geocentric position and velocity of transmitting antenna in inertial frame (au, au/day) # TODO: remove `constant_term` to take into account dependency of R_t, V_t wrt initial # conditions variations via et_t_secs - RV_t = obsposvelECI(observatory, et_t_secs, eo = eo) + RV_t = obsposvelECI(observatory, et_t_secs) R_t = RV_t[1:3] V_t = RV_t[4:6] # Earth's barycentric position and velocity at transmit time @@ -695,20 +468,15 @@ function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter: return 1e6τ end -function compute_delay(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, xve::TaylorInterpolant = earthposvel, - xvs::TaylorInterpolant = sunposvel, xva::TaylorInterpolant = apophisposvel197, tord::Int = xva.x[1].order) where {T <: AbstractFloat} - return compute_delay(radar.rcvr, radar.date, niter; eo = eo, xve = xve, xvs = xvs, xva = xva, tord = tord) -end - @doc raw""" - radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real, niter::Int = 10; eo::Bool = true, tc::Real = 1.0, - xve = earthposvel, xvs = sunposvel, xva = apophisposvel197, autodiff::Bool = true, tord::Int = 10) where {T <: AbstractFloat} - radar_astrometry(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, tc::Real = 1.0, xve = earthposvel, - xvs = sunposvel, xva = apophisposvel197, autodiff::Bool = true, tord::Int = 10) where {T <: AbstractFloat} - radar_astrometry(astradarfile::String, niter::Int = 10; eo::Bool = true, tc::Real = 1.0, xve = earthposvel, xvs = sunposvel, - xva = apophisposvel197, autodiff::Bool = true, tord::Int=10) + radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, + xve = earthposvel, xvs = sunposvel, xva = apophisposvel197, autodiff::Bool = true) where {T <: AbstractFloat} + radar_astrometry(radar::RadarJPL{T}; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, xve = earthposvel, + xvs = sunposvel, xva = apophisposvel197, autodiff::Bool = true) where {T <: AbstractFloat} + radar_astrometry(astradarfile::String; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, xve = earthposvel, xvs = sunposvel, + xva = apophisposvel197, autodiff::Bool = true) radar_astrometry(outfilename::String, radarobsfile::String, asteph::TaylorInterpolant, ss16asteph::TaylorInterpolant; tc::Real=1.0, autodiff::Bool=true, - tord::Int=10, niter::Int=5) + tord::Int = 5, niter::Int = 5) Return time-delay and Doppler shift. @@ -721,51 +489,48 @@ Return time-delay and Doppler shift. - `outfilename::String`: file where to save radar observations. - `F_tx::Real`: transmitter frequency (MHz). - `niter::Int`: number of light-time solution iterations. -- `eo::Bool`: wheter to use `EarthOrientation` or not. -- `tc::Real`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). +- `tc::Real`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). Offsets will be rounded to the nearest millisecond. - `xve`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xvs`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `asteph::TaylorInterpolant`: asteroid's ephemeris. -- `ss16asteph::TaylorInterpolant`: solar system ephemeris. -- `autodiff::Bool`: whether to use the automatic differentiation method of [`compute_delay`](@ref) or not. +- `ss16asteph::TaylorInterpolant`: Solar System ephemeris. +- `autodiff::Bool`: whether to compute Doppler shift via automatic diff of [`compute_delay`](@ref) or not. - `tord::Int`: order of Taylor expansions. """ -function radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real, niter::Int = 10; eo::Bool = true, tc::Real = 1.0, - xve = earthposvel, xvs = sunposvel, xva = apophisposvel197, autodiff::Bool = true, tord::Int = 10) where {T <: AbstractFloat} - - # Automatic differentiation method of delay +function radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real; tc::Real = 1.0, autodiff::Bool=true, kwargs...) where {T <: AbstractFloat} + # Compute Doppler shift via automatic differentiation of time-delay if autodiff # Time delay - τ = compute_delay(observatory, t_r_utc, niter, eo=eo, xve=xve, xvs=xvs, xva=xva, tord=tord) + τ = compute_delay(observatory, t_r_utc; kwargs...) # Time delay, Doppler shift return τ[0], -F_tx*τ[1] - # No automatic differentiation method of delay + # Compute Doppler shift via numerical differentiation of time-delay else - τe = compute_delay(observatory, t_r_utc, tc/2, niter, eo=eo, xve=xve, xvs=xvs, xva=xva) - τn = compute_delay(observatory, t_r_utc, 0.0, niter, eo=eo, xve=xve, xvs=xvs, xva=xva) - τs = compute_delay(observatory, t_r_utc, -tc/2, niter, eo=eo, xve=xve, xvs=xvs, xva=xva) + offset = Dates.Millisecond(1000round(tc/2, digits=3)) + τe = compute_delay(observatory, t_r_utc+offset; kwargs...) + τn = compute_delay(observatory, t_r_utc ; kwargs...) + τs = compute_delay(observatory, t_r_utc-offset; kwargs...) # Time delay, Doppler shift - return τn, -F_tx*((τe-τs)/tc) + return τn[0], -F_tx*((τe[0]-τs[0])/tc) end end -function radar_astrometry(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, tc::Real = 1.0, xve = earthposvel, - xvs = sunposvel, xva = apophisposvel197, autodiff::Bool = true, tord::Int = 10) where {T <: AbstractFloat} - return radar_astrometry(radar.rcvr, radar.date, radar.freq, niter; eo = eo, tc = tc, xve = xve, xvs = xvs, xva = xva, autodiff = autodiff, tord = tord) +function radar_astrometry(radar::RadarJPL{T}; kwargs...) where {T <: AbstractFloat} + return radar_astrometry(radar.rcvr, radar.date, radar.freq; kwargs...) end -function radar_astrometry(astradarfile::String, niter::Int=10; kwargs...) +function radar_astrometry(astradarfile::String; kwargs...) # Check that astradarfile is a file @assert isfile(astradarfile) "Cannot open file: $astradarfile" # Read radar measurements astradardata = read_radar_jpl(astradarfile) - return radar_astrometry(astradardata, niter; kwargs...) + return radar_astrometry(astradardata; kwargs...) end -function radar_astrometry(astradardata::Vector{RadarJPL{T}}, niter::Int=10; eo::Bool=true, tc::Real=1.0, xve=earthposvel, xvs=sunposvel, - xva=apophisposvel197, autodiff::Bool=true, tord::Int=10) where {T <: AbstractFloat} +function radar_astrometry(astradardata::Vector{RadarJPL{T}}; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, xve = earthposvel, xvs = sunposvel, + xva=apophisposvel197, autodiff::Bool=true) where {T <: AbstractFloat} # UTC time of first radar observation utc1 = astradardata[1].date @@ -783,9 +548,10 @@ function radar_astrometry(astradardata::Vector{RadarJPL{T}}, niter::Int=10; eo:: # Iterate over the measurements for i in eachindex(astradardata) + @show astradardata[i] # Compute time delay and doppler shift - vdelay[i], vdoppler[i] = radar_astrometry(astradardata[i], niter; eo = eo, tc = tc, xve = xve, xvs = xvs, xva = xva, - autodiff = autodiff, tord = tord) + vdelay[i], vdoppler[i] = radar_astrometry(astradardata[i], tord = tord, niter = niter, tc = tc, xve = xve, xvs = xvs, xva = xva, + autodiff = autodiff) end # Rows with time delays delay_index = map(x-> x.Δτ_units == "us", astradardata) @@ -810,339 +576,11 @@ function radar_astrometry(astradardata::Vector{RadarJPL{T}}, niter::Int=10; eo:: end @doc raw""" - radar_astrometry_yeomansetal92(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real, niter::Int = 10; eo::Bool = true, - xve = earthposvel, xvs = sunposvel, xva = apophisposvel197) where {T <: AbstractFloat} - radar_astrometry_yeomansetal92(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, - xva = apophisposvel197) where {T <: AbstractFloat} - -Compute round-trip time (in ``\mu``s) and Doppler shift (Hz) radar astrometry. Dopplers are computed following https://doi.org/10.1086/116062. - -# Arguments - -- `observatory::ObservatoryMPC{T}`: observing station. -- `t_r_utc::DateTime`: UTC time of echo reception. -- `radar::RadarJPL{T}`: radar observation. -- `F_tx::Real`: transmitter frequency (MHz). -- `niter::Int`: number of light-time solution iterations. -- `eo::Bool`: wheter to use `EarthOrientation` or not. -- `xve`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xvs`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -""" -function radar_astrometry_yeomansetal92(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real, niter::Int = 10; eo::Bool = true, - xve = earthposvel, xvs = sunposvel, xva = apophisposvel197) where {T <: AbstractFloat} - # Transform receiving time from UTC to TDB seconds since j2000 - et_r_secs = datetime2et(t_r_utc) - # Compute geocentric position/velocity of receiving antenna in inertial frame (au, au/day) - RV_r = obsposvelECI(observatory, et_r_secs, eo = eo) - R_r = RV_r[1:3] - V_r = RV_r[4:6] - # Earth's barycentric position and velocity at receive time - rv_e_t_r = xve(et_r_secs) - r_e_t_r = rv_e_t_r[1:3] - v_e_t_r = rv_e_t_r[4:6] - # Receiver barycentric position and velocity at receive time - r_r_t_r = r_e_t_r + R_r - v_r_t_r = v_e_t_r + V_r - # Asteroid barycentric position and velocity at receive time - rv_a_t_r = xva(et_r_secs) - r_a_t_r = rv_a_t_r[1:3] - v_a_t_r = rv_a_t_r[4:6] - # Sun barycentric position and velocity at receive time - rv_s_t_r = xvs(et_r_secs) - r_s_t_r = rv_s_t_r[1:3] - v_s_t_r = rv_s_t_r[4:6] - - # Down-leg iteration - # τ_D first approximation - # See equation (1) of https://doi.org/10.1086/116062 - ρ_vec_r = r_a_t_r - r_r_t_r - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) - # -R_b/c, but delay is wrt asteroid center (Brozovic et al., 2018) - τ_D = ρ_r/clightkms # (seconds) - # Bounce time, 1st estimate - # See equation (2) of https://doi.org/10.1086/116062 - et_b_secs = et_r_secs - τ_D - # Asteroid barycentric position (in au) at bounce time (TDB) - rv_a_t_b = xva(et_b_secs) - r_a_t_b = rv_a_t_b[1:3] - v_a_t_b = rv_a_t_b[4:6] - - # Allocate memmory for time delays - Δτ_D = zero(τ_D) # Total time delay - Δτ_rel_D = zero(τ_D) # Shapiro delay - # Δτ_corona_D = zero(τ_D) # Delay due to Solar corona - Δτ_tropo_D = zero(τ_D) # Delay due to Earth's troposphere - - for i in 1:niter - # Estimated position of the asteroid's center of mass relative to the recieve point - # See equation (3) of https://doi.org/10.1086/116062. - ρ_vec_r = r_a_t_b - r_r_t_r - ρ_vec_dot_r = v_a_t_b - v_r_t_r - # Magnitude of ρ_vec_r - # See equation (4) of https://doi.org/10.1086/116062. - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) - - # -R_b/c (COM correction) + Δτ_D (relativistic, tropo, iono...) - τ_D = ρ_r/clightkms # (seconds) - # Bounce time, new estimate - # See equation (2) of https://doi.org/10.1086/116062. - et_b_secs = et_r_secs - τ_D - # Asteroid barycentric position (in au) at bounce time (TDB) - rv_a_t_b = xva(et_b_secs) - r_a_t_b = rv_a_t_b[1:3] - v_a_t_b = rv_a_t_b[4:6] - - # Compute down-leg Shapiro delay - # NOTE: when using PPN, substitute 2 -> 1+γ in expressions for Shapiro delay, - # Δτ_rel_[D|U] - - # Earth's position at t_r - e_D_vec = r_e_t_r - r_s_t_r - de_D_vec = v_e_t_r - v_s_t_r - # Heliocentric distance of Earth at t_r - e_D = sqrt(e_D_vec[1]^2 + e_D_vec[2]^2 + e_D_vec[3]^2) - # Barycentric position and velocity of Sun at estimated bounce time - rv_s_t_b = xvs(et_b_secs) - r_s_t_b = rv_s_t_b[1:3] - v_s_t_b = rv_s_t_b[4:6] - # Heliocentric position and velocity of asteroid at t_b - p_D_vec = constant_term.(r_a_t_b - r_s_t_b) - dp_D_vec = constant_term.(v_a_t_b - v_s_t_b) - # Heliocentric distance of asteroid at t_b - p_D = sqrt(p_D_vec[1]^2 + p_D_vec[2]^2 + p_D_vec[3]^2) - # Signal path distance (down-leg) - q_D_vec = constant_term.(r_a_t_b - r_e_t_r) - dq_D_vec = constant_term.(v_a_t_b - v_e_t_r) - q_D = sqrt(q_D_vec[1]^2 + q_D_vec[2]^2 + q_D_vec[3]^2) - - # Shapiro correction to time-delay - Δτ_rel_D = shapiro_delay(e_D, p_D, q_D) # seconds - # Troposphere correction to time-delay - Δτ_tropo_D = tropo_delay(R_r, ρ_vec_r) # seconds - # Solar corona correction to time-delay - # Δτ_corona_D = corona_delay(constant_term.(r_a_t_b), r_r_t_r, r_s_t_r, F_tx, station_code) # seconds - # Total time-delay - Δτ_D = Δτ_rel_D + Δτ_tropo_D #+ Δτ_corona_D # seconds - - end - # Total time delay - τ_D = τ_D + Δτ_D - # Get latest estimates of ρ_vec_r and ρ_r - # See equation (3) of https://doi.org/10.1086/116062 - ρ_vec_r = r_a_t_b - r_r_t_r - # See equation (4) of https://doi.org/10.1086/116062 - ρ_r = sqrt(ρ_vec_r[1]^2 + ρ_vec_r[2]^2 + ρ_vec_r[3]^2) - - # Up-leg iteration - # τ_U first estimation - # See equation (5) of https://doi.org/10.1086/116062 - τ_U = τ_D - # Transmit time, 1st estimate - # See equation (6) of https://doi.org/10.1086/116062 - et_t_secs = et_r_secs - (τ_U+τ_D) - # Geocentric position and velocity of transmitting antenna in inertial frame (au, au/day) - RV_t = obsposvelECI(observatory, constant_term(et_t_secs), eo = eo) - R_t = RV_t[1:3] - V_t = RV_t[4:6] - # Barycentric position and velocity of the Earth at transmit time - rv_e_t_t = xve(et_t_secs) - r_e_t_t = rv_e_t_t[1:3] - v_e_t_t = rv_e_t_t[4:6] - # Transmitter barycentric position and velocity at transmit time - r_t_t_t = r_e_t_t + R_t - v_t_t_t = v_e_t_t + V_t - # See equation (7) of https://doi.org/10.1086/116062 - ρ_vec_t = r_a_t_b - r_t_t_t - ρ_vec_dot_t = v_a_t_b - v_t_t_t - ρ_t = sqrt(ρ_vec_t[1]^2 + ρ_vec_t[2]^2 + ρ_vec_t[3]^2) - - # Allocate memmory for time delays - Δτ_U = zero(τ_U) # Total time delay - Δτ_rel_U = zero(τ_U) # Shapiro delay - # Δτ_corona_U = zero(τ_U) # Delay due to Solar corona - Δτ_tropo_U = zero(τ_U) # Delay due to Earth's troposphere - - for i in 1:niter - # See equation (8) of https://doi.org/10.1086/116062 - # -R_b/c (COM correction) + Δτ_U (relativistic, tropo, iono...) - τ_U = ρ_t/clightkms # (seconds) - # Transmit time, new estimate - # See equation (6) of https://doi.org/10.1086/116062 - et_t_secs = et_r_secs-(τ_U+τ_D) - # Geocentric position and velocity of transmitting antenna in inertial frame (au, au/day) - RV_t = obsposvelECI(observatory, constant_term(et_t_secs), eo = eo) - R_t = RV_t[1:3] - V_t = RV_t[4:6] - # Earth's barycentric position and velocity at the transmit time - rv_e_t_t = xve(et_t_secs) - r_e_t_t = rv_e_t_t[1:3] - v_e_t_t = rv_e_t_t[4:6] - # Barycentric position and velocity of the transmitter at the transmit time - r_t_t_t = r_e_t_t + R_t - v_t_t_t = v_e_t_t + V_t - # See equation (7) of https://doi.org/10.1086/116062 - ρ_vec_t = r_a_t_b - r_t_t_t - ρ_vec_dot_t = v_a_t_b - v_t_t_t - ρ_t = sqrt(ρ_vec_t[1]^2 + ρ_vec_t[2]^2 + ρ_vec_t[3]^2) - - # Compute up-leg Shapiro delay - - # Sun barycentric position and velocity (in au, au/day) at transmit time (TDB) - rv_s_t_t = xvs( et_t_secs ) - r_s_t_t = rv_s_t_t[1:3] - v_s_t_t = rv_s_t_t[4:6] - # Earth barycentric position and velocity at transmit time - e_U_vec = constant_term.(r_e_t_t - r_s_t_t) - de_U_vec = constant_term.(v_e_t_t - v_s_t_t) - # Heliocentric distance of Earth at t_t - e_U = sqrt(e_U_vec[1]^2 + e_U_vec[2]^2 + e_U_vec[3]^2) - # Barycentric position/velocity of Sun at bounce time - rv_s_t_b = xvs(et_b_secs) - r_s_t_b = rv_s_t_b[1:3] - v_s_t_b = rv_s_t_b[4:6] - # Heliocentric position and velocity of the asteroid at bounce time - p_U_vec = constant_term.(r_a_t_b - r_s_t_b) - dp_U_vec = constant_term.(v_a_t_b - v_s_t_b) - # Heliocentric distance of asteroid at t_b - p_U = sqrt(p_U_vec[1]^2 + p_U_vec[2]^2 + p_U_vec[3]^2) - # Signal path (up-leg) - q_U_vec = constant_term.(r_a_t_b - r_e_t_t) - dq_U_vec = constant_term.(v_a_t_b - v_e_t_t) - q_U = sqrt(q_U_vec[1]^2 + q_U_vec[2]^2 + q_U_vec[3]^2) - - # Time-delays - # Shapiro delay - Δτ_rel_U = shapiro_delay(e_U, p_U, q_U) # seconds - # Troposphere correction to time delay - Δτ_tropo_U = tropo_delay(R_t, ρ_vec_t) # seconds - # Solar corona correctino to time delay - # Δτ_corona_U = corona_delay(constant_term.(r_t_t_t), constant_term.(r_a_t_b), constant_term.(r_s_t_b), F_tx, station_code) # seconds - # Total time delay - Δτ_U = Δτ_rel_U + Δτ_tropo_U #+ Δτ_corona_U # seconds - end - # Sun barycentric position (in au) at transmit time (TDB) - r_s_t_t = xvs(et_t_secs)[1:3] - # Total time delay - τ_U = τ_U + Δτ_U - - # Compute TDB-UTC at transmit time - # Corrections to TT-TDB from Moyer (2003) / Folkner et al. (2014) due to position - # of measurement station on Earth are of order 0.01μs - # Δtt_tdb_station_t = - dot(v_e_t_t/daysec, r_t_t_t-r_e_t_t)/c_au_per_sec^2 - tdb_utc_t = tdb_utc(constant_term(et_t_secs)) #+ Δtt_tdb_station_t - - # Compute TDB-UTC at receive time - # Corrections to TT-TDB from Moyer (2003) / Folkner et al. (2014) due to position - # of measurement station on Earth are of order 0.01μs - # Δtt_tdb_station_r = dot(v_e_t_r/daysec, r_r_t_r-r_e_t_r)/c_au_per_sec^2 - tdb_utc_r = tdb_utc(et_r_secs) #+ Δtt_tdb_station_r - - # Compute total time delay (UTC seconds) - # See equation (9) of https://doi.org/10.1086/116062 - τ = (τ_U + τ_D) + (tdb_utc_t - tdb_utc_r) - - # Compute Doppler shift ν - # See equation (10) of https://doi.org/10.1086/116062 - ρ_vec_dot_t = v_a_t_b - v_t_t_t - ρ_vec_dot_r = v_a_t_b - v_r_t_r - # See equation (11) of https://doi.org/10.1086/116062 - ρ_dot_t = dot(ρ_vec_t, ρ_vec_dot_t)/ρ_t - ρ_dot_r = dot(ρ_vec_r, ρ_vec_dot_r)/ρ_r - - # See equation (12) of https://doi.org/10.1086/116062 - # Order 1, only term - doppler_c = (ρ_dot_t+ρ_dot_r)/clightkms - # Order 1/c^2, first three terms - p_t = dot(ρ_vec_t, v_t_t_t)/ρ_t - p_r = dot(ρ_vec_r, v_r_t_r)/ρ_r - doppler_c2_t1 = ρ_dot_t*p_t - ρ_dot_r*p_r - ρ_dot_t*ρ_dot_r - # Order 1/c^2, GM_S terms - r_ts_vec = r_t_t_t - r_s_t_t - r_ts = sqrt(r_ts_vec[1]^2+r_ts_vec[2]^2+r_ts_vec[3]^2) - r_rs_vec = r_r_t_r - r_s_t_r - r_rs = sqrt(r_rs_vec[1]^2+r_rs_vec[2]^2+r_rs_vec[3]^2) - doppler_c2_t2 = (μ_DE430[su]*((au^3)/(daysec^2)))*( (1/r_ts) - (1/r_rs) ) - # Order 1/c^2, last term - doppler_c2_t3 = ( dot(v_t_t_t, v_t_t_t) - dot(v_r_t_r, v_r_t_r) )/2 - - # Total Doppler shift - doppler_c2 = (doppler_c2_t1 + doppler_c2_t2 + doppler_c2_t3)/(clightkms^2) - ν = -F_tx*(doppler_c) # + doppler_c2) - - # Total signal delay (μs) and Doppler shift (Hz) - return 1e6τ, 1e6ν -end - -function radar_astrometry_yeomansetal92(radar::RadarJPL{T}, niter::Int = 10; eo::Bool = true, xve = earthposvel, xvs = sunposvel, - xva = apophisposvel197) where {T <: AbstractFloat} - return radar_astrometry_yeomansetal92(radar.observatory, radar.date, radar.freq, niter, eo = eo, xve = xve, xvs = xvs, xva = xva) -end - -function radar_astrometry(outfilename::String, radarobsfile::String, asteph::TaylorInterpolant, ss16asteph::TaylorInterpolant; - tc::Real = 1.0, autodiff::Bool = true, tord::Int = 10, niter::Int = 5) - # Check that radarobsfile is a file - @assert isfile(radarobsfile) "Cannot open file: $radarobsfile" - # Read optical observations - radar = read_radar_jpl(radarobsfile) - - # Check that first and last observation times are within interpolation interval - Δt_0 = datetime2julian(radar[1].date) - JD_J2000 - asteph.t0 - Δt_f = datetime2julian(radar[end].date) - JD_J2000 - asteph.t0 - t_min, t_max = minmax(asteph.t[1], asteph.t[end]) - @assert t_min ≤ Δt_0 ≤ Δt_f ≤ t_max "First and/or last observation times are outside interpolation interval" - - # Number of massive bodies - Nm1 = (size(ss16asteph.x)[2]-13) ÷ 6 - # Number of bodies, including NEA - N = Nm1 + 1 - - # NEO - # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec - asteph_et(et) = auday2kmsec(asteph(et/daysec)[1:6]) - # Earth - # Change x, v units, resp., from au, au/day to km, km/sec - eph_ea = selecteph(ss16asteph, ea) - xve(et) = auday2kmsec(eph_ea(et)) - # Sun - # Change x, v units, resp., from au, au/day to km, km/sec - eph_su = selecteph(ss16asteph, su) - xvs(et) = auday2kmsec(eph_su(et)) - - # Compute radar astrometry - dt_utc_obs, Δτ_obs, Δν_obs, vdelay, vdoppler, Δτ_σ, Δν_σ, τ_units, ν_units, freq, rcvr, xmit, bouncepoint, delay_index, - doppler_index = radar_astrometry(radarobsfile, niter, xve = earth_et, xvs = sun_et, xva = asteph_et, tc = tc, tord = tord, autodiff = autodiff) - # Save data to file - println("Saving data to file: $outfilename") - JLD2.jldopen(outfilename, "w") do file - # Write variables to jld2 file - JLD2.write(file, - "dt_utc_obs", dt_utc_obs, - "Δτ_obs", Δτ_obs, - "Δν_obs", Δν_obs, - "vdelay", vdelay, - "vdoppler", vdoppler, - "Δτ_σ", Δτ_σ, - "Δν_σ", Δν_σ, - "τ_units", τ_units, - "ν_units", ν_units, - "freq", freq, - "rcvr", rcvr, - "xmit", xmit, - "bouncepoint", bouncepoint, - "delay_index", delay_index, - "doppler_index", doppler_index, - ) - end - - return nothing -end - -@doc raw""" - residuals(obs::Vector{RadarJPL{T}}, niter::Int = 10; eo::Bool = true, debias_table::String = "2018", - xvs::Function = sunposvel, xve::Function = earthposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} + residuals(obs::Vector{RadarJPL{T}}, niter::Int = 10; debias_table::String = "2018", + xvs::SunEph = sunposvel, xve::EarthEph = earthposvel, xva::AstEph = apophisposvel197) where {T <: AbstractFloat} -Compute O-C residuals for radar astrometry. +Compute O-C residuals for radar astrometry, including corrections due to Earth orientation, +LOD and polar motion. See also [`compute_delay`](@ref) and [`radar_astrometry`](@ref). @@ -1150,18 +588,17 @@ See also [`compute_delay`](@ref) and [`radar_astrometry`](@ref). - `obs::Vector{RadarJPL{T}}`: vector of observations. - `niter::Int`: number of light-time solution iterations. -- `eo::Bool`: compute corrections due to Earth orientation, LOD, polar motion. - `tc::Real`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). - `autodiff::Bool`: whether to use the automatic differentiation method of [`compute_delay`](@ref) or not. - `tord::Int`: order of Taylor expansions. -- `xvs::Function`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xve::Function`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xva::Function`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xvs::SunEph`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xve::EarthEph`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xva::AstEph`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ -function residuals(obs::Vector{RadarJPL{T}}, niter::Int = 10; eo::Bool = true, tc::Real = 1.0, autodiff::Bool = true, tord::Int = 10, - xvs::Function = sunposvel, xve::Function = earthposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} +function residuals(obs::Vector{RadarJPL{T}}; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, autodiff::Bool = true, + xvs::SunEph = sunposvel, xve::EarthEph = earthposvel, xva::AstEph = apophisposvel197) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} # Radar delay/Doppler astrometric data - x_jt = radar_astrometry(obs, niter; eo = eo, tc=tc, autodiff = autodiff, tord = tord, xvs = xvs, xve = xve, xva = xva) + x_jt = radar_astrometry(obs; tord = tord, niter=niter, tc=tc, autodiff = autodiff, xvs = xvs, xve = xve, xva = xva) # Time-delay residuals res_τ = x_jt[2][x_jt[14]] .- x_jt[4][x_jt[14]] # Doppler-shift residuals @@ -1173,5 +610,5 @@ function residuals(obs::Vector{RadarJPL{T}}, niter::Int = 10; eo::Bool = true, t w_ν = repeat(1 ./ x_jt[7][x_jt[15]].^2, 2) w = vcat(w_τ, w_ν) - return res, w + return res_τ, w_τ, res_ν, w_ν end From 4c930576265b874ceebea9e63927b239c3b80b03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 15:35:47 +0200 Subject: [PATCH 22/46] Update src/observations/topocentric.jl - Remove `eop_IAU1980` const - Set `eop_IAU2000A` as default Earth orientation model - Update `obsposvelECI` - Remove RFRJL and STJL method overloads for Taylor1/TaylorN (type-piracy) --- src/observations/topocentric.jl | 94 ++++++++------------------------- 1 file changed, 22 insertions(+), 72 deletions(-) diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl index 27a868d5..2023f974 100644 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -1,7 +1,7 @@ # Earth orientation parameters (eop) 1980 -const eop_IAU1980 = get_iers_eop_iau_1980() # get_eop_iau1980() +# const eop_IAU1980 = ST.get_iers_eop_iau_1980() # Earth orientation parameters (eop) 2000 -const eop_IAU2000A = get_iers_eop_iau_2000A() # get_eop_iau2000a() +const eop_IAU2000A = get_iers_eop_iau_2000A() @doc raw""" obs_pos_ECEF(observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} @@ -42,49 +42,43 @@ obs_pos_ECEF(x::RadecMPC{T}) where {T <: AbstractFloat} = obs_pos_ECEF(x.observa obs_pos_ECEF(x::RadarJPL{T}) where {T <: AbstractFloat} = obs_pos_ECEF(x.rcvr) @doc raw""" - obsposvelECI(observatory::ObservatoryMPC{T}, et::T; eo::Bool=true, - eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU1980) where {T <: AbstractFloat} - obsposvelECI(x::RadecMPC{T}; eo::Bool=true, eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU1980) where {T <: AbstractFloat} - obsposvelECI(x::RadarJPL{T}; eo::Bool=true, eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU1980) where {T <: AbstractFloat} + obsposvelECI(observatory::ObservatoryMPC{T}, et::T; + eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU2000A) where {T <: AbstractFloat} + obsposvelECI(x::RadecMPC{T}; eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU2000A) where {T <: AbstractFloat} + obsposvelECI(x::RadarJPL{T}; eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU2000A) where {T <: AbstractFloat} -Return the observer's geocentric `[x, y, z, v_x, v_y, v_z]` "state" vector in Earth-Centered Inertial (ECI) reference frame. +Return the observer's geocentric `[x, y, z, v_x, v_y, v_z]` "state" vector in Earth-Centered +Inertial (ECI) reference frame. By default, the IAU200A Earth orientation model is used to +transform from Earth-centered, Earth-fixed (ECEF) frame to ECI frame. Other Earth orientation +models, such as the IAU1976/80 model can be used by importing the `SatelliteToolbox.EOPData_IAU1980` +type and passing it to the `eop` keyword argument in the function call. -See also [`SatelliteToolbox.orbsv`](@ref) and [`SatelliteToolbox.svECEFtoECI`](@ref). +See also [`SatelliteToolbox.orbsv`](@ref) and [`SatelliteToolbox.sv_ecef_to_eci`](@ref). # Arguments - `observatory::ObservatoryMPC{T}`: observation site. - `et::T`: ephemeris time (TDB seconds since J2000.0 epoch). -- `eo::Bool`: whether to use Earth Orientation Parameters (eop) or not. - `eop::Union{EOPData_IAU1980, EOPData_IAU2000A}`: Earth Orientation Parameters (eop). """ -function obsposvelECI(observatory::ObservatoryMPC{T}, et::Union{T,Taylor1{T}}; eo::Bool=true, - eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU1980) where {T <: AbstractFloat} - - # auxiliary to compute time-derivatives via autodiff - one_et = one(et) - +function obsposvelECI(observatory::ObservatoryMPC{T}, et::ET; + eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU2000A) where {T <: AbstractFloat, ET<:Union{T,Taylor1{T},Taylor1{TaylorN{T}}}} # Earth-Centered Earth-Fixed position position of observer - pos_ECEF = obs_pos_ECEF(observatory)*one_et + pos_ECEF = obs_pos_ECEF(observatory) # UTC seconds utc_secs = et - tdb_utc(et) # Julian days UTC jd_utc = JD_J2000 + utc_secs/daysec # State vector - pv_ECEF = SatelliteToolbox.orbsv(jd_utc, pos_ECEF, one_et*zeros(3), one_et*zeros(3)) + pv_ECEF = orbsv(jd_utc, pos_ECEF, zeros(3), zeros(3)) # Transform position/velocity from Earth-Centered Earth-fixed (ECEF) frame to Earth-Centered Inertial (ECI) frame # ITRF: International Terrestrial Reference Frame # GCRF: Geocentric Celestial Reference Frame # Use earth orientation parameters - if eo - pv_ECI = SatelliteToolbox.sv_ecef_to_eci(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc, eop) - # Not use earth orientation parameters - else - pv_ECI = SatelliteToolbox.sv_ecef_to_eci(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc) - end + pv_ECI = sv_ecef_to_eci(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc, eop) # Inertial position p_ECI = convert(Vector{eltype(pv_ECI.r)}, pv_ECI.r) @@ -95,55 +89,11 @@ function obsposvelECI(observatory::ObservatoryMPC{T}, et::Union{T,Taylor1{T}}; e return vcat(p_ECI, v_ECI) end -function obsposvelECI(x::RadecMPC{T}; eo::Bool = true, eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU1980) where {T <: AbstractFloat} - return obsposvelECI(x.observatory, datetime2et(x.date); eo = eo, eop = eop) -end -function obsposvelECI(x::RadarJPL{T}; eo::Bool = true, eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU1980) where {T <: AbstractFloat} - return obsposvelECI(x.rcvr, datetime2et(x.date); eo = eo, eop = eop) +function obsposvelECI(x::RadecMPC{T}; eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU2000A) where {T <: AbstractFloat} + return obsposvelECI(x.observatory, datetime2et(x.date); eop = eop) end - -function smallangle_to_rot( - ::Type{DCM}, - θx::Taylor1, - θy::Taylor1, - θz::Taylor1; - normalize = true -) - return smallangle_to_dcm(θx, θy, θz; normalize = normalize) -end - -function smallangle_to_dcm( - θx::Taylor1{T}, - θy::Taylor1{T}, - θz::Taylor1{T}; - normalize = true -) where {T<:Number} - # # Since we might orthonormalize `D`, we need to get the float to avoid type - # # instabilities. - # T = float(promote_type(T1, T2, T3)) - - D = DCM{Taylor1{T}}( - 1, +θz, -θy, - -θz, 1, +θx, - +θy, -θx, 1 - )' - - if normalize - return orthonormalize(D) - else - return D - end -end - -function r_itrf_to_pef_fk5( - T::Type, - x_p::Taylor1, - y_p::Taylor1 -) - # Notice that `x_p` and `y_p` are displacements in X and Y directions and - # **not** rotation angles. Hence, a displacement in X is a rotation in Y and - # a displacement in Y is a rotation in X. - return smallangle_to_rot(T, +y_p, +x_p, zero(x_p)) +function obsposvelECI(x::RadarJPL{T}; eop::Union{EOPData_IAU1980, EOPData_IAU2000A} = eop_IAU2000A) where {T <: AbstractFloat} + return obsposvelECI(x.rcvr, datetime2et(x.date); eop = eop) end @doc raw""" @@ -263,7 +213,7 @@ function t2c_rotation_iau_76_80(et::T; eo::Bool = true) where {T <: Number} # Lunar longitude of ascending node (measured from ecliptic) Ω_M = PE.Ω(et_days) # rad # IAU 1980 nutation angles - _, Δϵ_1980, ΔΨ_1980 = nutation_fk5(JD_J2000 + et_days) + _, Δϵ_1980, ΔΨ_1980 = ST.nutation_fk5(JD_J2000 + et_days) # Equation of the equinoxes `ee = GAST - GMST`, including nutation correction # See equation (5-184) in page (5-70) of https://doi.org/10.1002/0471728470: # Δθ = ∆ψ cosϵ̄ + 0''.00264 sinΩ + 0''.000063 sin2Ω From 80d6dee75105e18a75e2eecaa3b72f54f0581131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 15:37:44 +0200 Subject: [PATCH 23/46] Minor updates in units.jl --- src/observations/units.jl | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/observations/units.jl b/src/observations/units.jl index 7b3e39e9..eb769480 100644 --- a/src/observations/units.jl +++ b/src/observations/units.jl @@ -23,7 +23,7 @@ end @doc raw""" datetime2et(x::DateTime) datetime2et(x::T) where {T <: AbstractAstrometry} - + Retun the TDB seconds past the J2000 epoch. See also [`SPICE.str2et`](@ref). @@ -37,35 +37,35 @@ datetime2et(x::T) where {T <: AbstractAstrometry} = datetime2et(x.date) @doc raw""" et_to_200X(et::T) where {T <: Number} -Convert `et` ephemeris seconds since J2000 to years `200X`. +Convert `et` ephemeris seconds since J2000 to years `200X`. """ et_to_200X(et::T) where {T <: Number} = 2000 + et/daysec/yr @doc raw""" days_to_200X(d::T) where {T <: Number} -Convert `d` days since J2000 to years `200X`. +Convert `d` days since J2000 to years `200X`. """ days_to_200X(d::T) where {T <: Number} = 2000 + d/yr @doc raw""" datetime_to_200X(x::DateTime) -Convert `DateTime` `x` to years `200X`. +Convert `DateTime` `x` to years `200X`. """ datetime_to_200X(x::DateTime) = et_to_200X(datetime2et(x)) @doc raw""" datetime2days(x::DateTime) -Convert `DateTime` `x` to days since J2000. +Convert `DateTime` `x` to days since J2000. """ datetime2days(x::DateTime) = datetime2julian(x) - JD_J2000 @doc raw""" days2datetime(d::T) where {T <: Number} -Convert `d` days since J2000 to `DateTime`. +Convert `d` days since J2000 to `DateTime`. """ days2datetime(d::T) where {T <: Number} = julian2datetime(d + JD_J2000) @@ -83,7 +83,7 @@ TDB-UTC & = (TDB-TAI) + (TAI-UTC) \\ where TDB is the Solar System barycentric ephemeris time, TT is the Terrestrial time, TAI is the International Atomic Time, and UTC is the Coordinated Universal Time. -This function is useful to convert TDB to UTC via UTC + (TDB-UTC) and viceversa. It does +This function is useful to convert TDB to UTC via UTC + (TDB-UTC) and viceversa. It does not include the correction due to the position of the measurement station ``v_E.(r_S-r_E)/c^2`` (Folkner et al. 2014; Moyer, 2003). @@ -97,7 +97,7 @@ function tdb_utc(et::T) where {T<:Number} # TT-TAI tt_tai = 32.184 - et_00 = constant_term(constant_term(et)) + et_00 = cte(cte(et)) # Used only to determine ΔAT; no high-precision needed utc_secs = et_00 - deltet(et_00, "ET") # ΔAT @@ -122,7 +122,7 @@ end @doc raw""" rad2arcsec(x) -Convert radians to arcseconds. +Convert radians to arcseconds. See also [`arcsec2rad`](@ref) and [`mas2rad`](@ref). """ @@ -131,7 +131,7 @@ rad2arcsec(x) = 3600 * rad2deg(x) # rad2deg(rad) -> deg; 3600 * deg -> arcsec @doc raw""" arcsec2rad(x) -Convert arcseconds to radians. +Convert arcseconds to radians. See also [`rad2arcsec`](@ref) and [`mas2rad`](@ref). """ @@ -140,7 +140,7 @@ arcsec2rad(x) = deg2rad(x / 3600) # arcsec/3600 -> deg; deg2rad(deg) -> rad @doc raw""" mas2rad(x) -Convert milli-arcseconds to radians. +Convert milli-arcseconds to radians. See also [`rad2arcsec`](@ref) and [`arcsec2rad`](@ref). """ From cc6d55720cb19dbdda04e3865039bc746fe273f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 15:39:01 +0200 Subject: [PATCH 24/46] Minor fix in bwdfwdeph --- src/observations/jpl_eph.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/observations/jpl_eph.jl b/src/observations/jpl_eph.jl index c09a62d2..d8fede85 100644 --- a/src/observations/jpl_eph.jl +++ b/src/observations/jpl_eph.jl @@ -138,7 +138,7 @@ function loadpeeph(et::Union{Nothing, Real} = nothing) end end -function bwdfwdeph(et::T, +function bwdfwdeph(et::Union{T,TaylorN{T}}, bwd::TaylorInterpolant{T,U,2}, fwd::TaylorInterpolant{T,U,2} ) where {T<:AbstractFloat, U<:Union{T,TaylorN{T}}} From 8863c0e8faceb5139b98282ca760979ffe333f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 15:39:36 +0200 Subject: [PATCH 25/46] Update Apophis scripts --- pha/apophis.jl | 139 ++++++++++++++++++++++++++++++++---------------- scripts/main.jl | 2 +- 2 files changed, 93 insertions(+), 48 deletions(-) diff --git a/pha/apophis.jl b/pha/apophis.jl index a1521757..8626e809 100644 --- a/pha/apophis.jl +++ b/pha/apophis.jl @@ -1,15 +1,16 @@ using ArgParse, NEOs, PlanetaryEphemeris, Dates, TaylorIntegration, JLD2 +# using Revise, NEOs, PlanetaryEphemeris, Dates, TaylorIntegration, JLD2 -# Load JPL ephemeris +# Load JPL ephemeris loadjpleph() function parse_commandline() s = ArgParseSettings() # Program name (for usage & help screen) - s.prog = "apophis.jl" + s.prog = "apophis.jl" # Desciption (for help screen) - s.description = "Propagates Apophis orbit via jet transport" + s.description = "Propagates Apophis orbit via jet transport" @add_arg_table! s begin "--jd0" @@ -17,21 +18,21 @@ function parse_commandline() arg_type = DateTime default = DateTime(2020, 12, 17) "--varorder" - help = "Order of the jet transport perturbation" + help = "Order of the jet transport perturbation" arg_type = Int default = 5 "--maxsteps" help = "Maximum number of steps during integration" arg_type = Int - default = 10_000 + default = 10_000 "--nyears_bwd" help = "Years in backward integration" arg_type = Float64 - default = -18.0 + default = -17.0 "--nyears_fwd" help = "Years in forward integration" arg_type = Float64 - default = 9.0 + default = 9.0 "--order" help = "Order of Taylor polynomials expansions during integration" arg_type = Int @@ -43,11 +44,11 @@ function parse_commandline() "--parse_eqs" help = "Whether to use the taylorized method of jetcoeffs or not" arg_type = Bool - default = true + default = true "--ss_eph_file" - help = "Path to local Solar System ephemeris file" - arg_type = String - default = "./sseph343ast016_p31y_et.jld2" + help = "Path to local Solar System ephemeris file (loaded via artifact by default)" + arg_type = Union{String,Nothing} + default = nothing end s.epilog = """ @@ -69,75 +70,118 @@ function print_header(header::String) println(repeat("-", L)) println(header) println(repeat("-", L)) -end +end -function main(dynamics::Function, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, nyears_fwd::T, +function main(dynamics::Function, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, nyears_fwd::T, ss16asteph_et::TaylorInterpolant, order::Int, varorder::Int, abstol::T, parse_eqs::Bool) where {T <: Real} - - # Perturbation to nominal initial condition (Taylor1 jet transport) - # vcat(fill(1e-8, 6), 1e-14, 1e-13) are the scaling factors for jet transport perturbation, - # these are needed to ensure expansion coefficients remain small. - # The magnitudes correspond to the typical order of magnitude of errors in - # position/velocity (1e-8), Yarkovsky (1e-13) and radiation pressure (1e-14) - dq = NEOs.scaled_variables("δx", vcat(fill(1e-8, 6), 1e-14, 1e-13), order = varorder) # Initial conditions from Apophis JPL solution #197 q00 = kmsec2auday(apophisposvel197(datetime2et(jd0_datetime))) - q0 = vcat(q00, 0.0, 0.0) .+ dq + + # Perturbation to nominal initial condition (Taylor1 jet transport) + # vcat(fill(1e-8, 6), 1e-14, 1e-13) are the scaling factors for jet transport perturbation, + # these are needed to ensure expansion coefficients remain small. + # The magnitudes correspond to the typical order of magnitude of errors in + # position/velocity (1e-8), Yarkovsky (1e-13) and radiation pressure (1e-14) + if varorder == 0 + dq = zeros(8) + else + dq = NEOs.scaled_variables("δx", vcat(fill(1e-8, 6), 1e-14), order = varorder) + end + + q0 = vcat(q00, 0.0, 0.0) .+ vcat(dq, zero(dq[1])) # Initial date (in julian days) jd0 = datetime2julian(jd0_datetime) print_header("Integrator warmup") - sol = NEOs.propagate(dynamics, 1, jd0, nyears_fwd, ss16asteph_et, q0, Val(true); - order = order, abstol = abstol, parse_eqs = parse_eqs) - + # sol_bwd = NEOs.propagate(dynamics, 1, jd0, nyears_fwd, ss16asteph_et, q0, Val(true); + # order = order, abstol = abstol, parse_eqs = parse_eqs) + print_header("Main integration") - tmax = nyears_bwd*yr + tmax = nyears_bwd*yr println("• Initial time of integration: ", string(jd0_datetime)) println("• Final time of integration: ", julian2datetime(jd0 + tmax)) - sol = NEOs.propagate(dynamics, maxsteps, jd0, nyears_bwd, ss16asteph_et, q0, Val(true); + sol_bwd = NEOs.propagate(dynamics, maxsteps, jd0, nyears_bwd, ss16asteph_et, q0, Val(true); order = order, abstol = abstol, parse_eqs = parse_eqs) - save2jldandcheck("Apophis_bwd", (asteph = sol,)) + PlanetaryEphemeris.save2jld2andcheck("Apophis_bwd.jld2", (asteph = sol_bwd,)) - tmax = nyears_fwd*yr + tmax = nyears_fwd*yr println("• Initial time of integration: ", string(jd0_datetime)) println("• Final time of integration: ", julian2datetime(jd0 + tmax)) - sol = NEOs.propagate(dynamics, maxsteps, jd0, nyears_fwd, ss16asteph_et, q0, Val(true), + sol_fwd = NEOs.propagate(dynamics, maxsteps, jd0, nyears_fwd, ss16asteph_et, q0, Val(true), order = order, abstol = abstol, parse_eqs = parse_eqs) - save2jldandcheck("Apophis_fwd", (asteph = sol,)) - - nothing - -end + PlanetaryEphemeris.save2jld2andcheck("Apophis_fwd.jld2", (asteph = sol_fwd,)) + + # NEO + # Change t, x, v units, resp., from days, au, au/day to sec, km, km/sec + xva_bwd(et) = auday2kmsec(sol_bwd(et/daysec)[1:6]) + xva_fwd(et) = auday2kmsec(sol_fwd(et/daysec)[1:6]) + xva(et) = bwdfwdeph(et, sol_bwd, sol_fwd) + # Earth + # Change x, v units, resp., from au, au/day to km, km/sec + eph_ea = selecteph(ss16asteph_et, ea) + xve(et) = auday2kmsec(eph_ea(et)) + # Sun + # Change x, v units, resp., from au, au/day to km, km/sec + eph_su = selecteph(ss16asteph_et, su) + xvs(et) = auday2kmsec(eph_su(et)) + + + radec_2004_2020 = read_radec_mpc("/Users/Jorge/projects/NEOs/data/99942_2004_2020.dat") + radec_2020_2021 = read_radec_mpc("/Users/Jorge/projects/NEOs/data/99942_2020_2021.dat") + radec = vcat(radec_2004_2020,radec_2020_2021) + + deldop_2005_2013 = read_radar_jpl("/Users/Jorge/projects/NEOs/data/99942_RADAR_2005_2013.dat") + deldop_2021 = read_radar_jpl("/Users/Jorge/projects/NEOs/data/99942_RADAR_2021.dat") + # TODO: make radar astrometry residuals work with functions!!! + # deldop = vcat(deldop_2005_2013,deldop_2021) + + # Compute optical residuals + print_header("Compute residuals") + res_radec, w_radec = residuals(radec, xvs = xvs, xve = xve, xva = xva) + + # Compute radar residuals + #### TODO: make radar astrometry residuals work with functions!!! + #### res_deldop, w_deldop = residuals(deldop, xvs = xvs, xve = xve, xva = xva_bwd) + res_del_bwd, w_del_bwd, res_dop_bwd, w_dop_bwd = residuals(deldop_2005_2013, xvs = xvs, xve = xve, xva = xva_bwd, niter=5) + res_del_fwd, w_del_fwd, res_dop_fwd, w_dop_fwd = residuals(deldop_2021, xvs = xvs, xve = xve, xva = xva_fwd, niter=5) + + PlanetaryEphemeris.save2jld2andcheck("resw_radec.jld2", (;res_radec,w_radec,res_del_bwd,w_del_bwd,res_dop_bwd,w_dop_bwd,res_del_fwd,w_del_fwd,res_dop_fwd,w_dop_fwd)) + + @show NEOs.cte(res) NEOs.cte(w) + + nothing + +end function main() - # Parse arguments from commandline + # Parse arguments from commandline parsed_args = parse_commandline() - + print_header("Asteroid Apophis") print_header("General parameters") - # Number of threads + # Number of threads N_threads = Threads.nthreads() println("• Number of threads: ", N_threads) - # Dynamical function + # Dynamical function if N_threads == 1 dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph! - else + else dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! - end + end println("• Dynamical function: ", dynamics) - # Maximum number of steps + # Maximum number of steps maxsteps = parsed_args["maxsteps"] println("• Maximum number of steps: ", maxsteps) - # Initial date + # Initial date jd0_datetime = parsed_args["jd0"] # Number of years in backward integration @@ -146,9 +190,10 @@ function main() # Number of years in forward integration nyears_fwd = parsed_args["nyears_fwd"] - # Solar system ephemeris + # Solar system ephemeris print("• Loading Solar System ephemeris... ") - ss16asteph_et = JLD2.load(parsed_args["ss_eph_file"], "ss16ast_eph") + ss_eph_file = parsed_args["ss_eph_file"] + ss16asteph_et = ss_eph_file === nothing ? NEOs.sseph : JLD2.load(ss_eph_file, "ss16asteph_et") println("Done") # Order of Taylor polynomials @@ -163,12 +208,12 @@ function main() abstol = parsed_args["abstol"] println("• Absolute tolerance: ", abstol) - # Wheter to use @taylorize or not + # Whether to use @taylorize or not parse_eqs = parsed_args["parse_eqs"] println("• Use @taylorize: ", parse_eqs) - main(dynamics, maxsteps, jd0_datetime, nyears_bwd, nyears_fwd, ss16asteph_et, + main(dynamics, maxsteps, jd0_datetime, nyears_bwd, nyears_fwd, ss16asteph_et, order, varorder, abstol, parse_eqs) -end +end main() diff --git a/scripts/main.jl b/scripts/main.jl index 17af63a4..3d9e8d67 100644 --- a/scripts/main.jl +++ b/scripts/main.jl @@ -5,7 +5,7 @@ using NEOs using Dates using TaylorIntegration -using JLD +using JLD2 using SPICE: furnsh @show Threads.nthreads() From 1aa6745f3132448bebf8f159b283462e197a23e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 15:40:23 +0200 Subject: [PATCH 26/46] Update tests --- test/observations.jl | 416 ++++++++++++++++++++++--------------------- test/propagation.jl | 106 +++++++++-- 2 files changed, 305 insertions(+), 217 deletions(-) diff --git a/test/observations.jl b/test/observations.jl index 229423c0..3b86aaea 100644 --- a/test/observations.jl +++ b/test/observations.jl @@ -3,212 +3,218 @@ using NEOs using Test -using NEOs: mpc_catalogue_regex, CatalogueMPC, CatalogueCodes_path, observations_path - -@testset "CatalogueMPC" begin - - # Check that local catalogues file exists - @test isfile(joinpath(observations_path, "CatalogueCodes.txt")) - - # Check global variable NEOs.mpc_catalogues[] - @test allunique(NEOs.mpc_catalogues[]) - @test isa(NEOs.mpc_catalogues[], Vector{CatalogueMPC}) - - # Parse CatalogueMPC - gaia_s = " 6 Gaia2016" - gaia_m = match(mpc_catalogue_regex, gaia_s) - gaia = CatalogueMPC(gaia_m) - @test gaia.code == "6" - @test gaia.name == "Gaia2016" - - # Unknown catalogue - unkcat = unknowncat() - @test isunknown(unkcat) - @test !isunknown(gaia) - - # Catalogue equality - @test unkcat == unkcat - @test gaia == gaia - @test gaia != unkcat - - # Read/write catalogues file - source_cat = read_catalogues_mpc(CatalogueCodes_path) - check_file = joinpath(observations_path, "CatalogueCodes_.txt") - write_catalogues_mpc(source_cat, check_file) - check_cat = read_catalogues_mpc(check_file) - rm(check_file) - @test source_cat == check_cat - - # Update catalogues file - update_catalogues_mpc() - @test allunique(NEOs.mpc_catalogues[]) - @test isa(NEOs.mpc_catalogues[], Vector{CatalogueMPC}) - - # Search catalogue code - cat = search_cat_code("6") - @test cat == gaia -end - -using NEOs: mpc_observatory_regex, ObservatoryMPC, ObsCodes_path - -@testset "ObservatoryMPC" begin - - # Check that local observatories file exists - @test isfile(joinpath(observations_path, "ObsCodes.txt")) - - # Check global variable NEOs.mpc_observatories[] - @test allunique(NEOs.mpc_observatories[]) - @test isa(NEOs.mpc_observatories[], Vector{ObservatoryMPC{Float64}}) - - # Parse ObservatoryMPC - arecibo_s = "251 293.246920.949577+0.312734Arecibo" - arecibo_m = match(mpc_observatory_regex, arecibo_s) - arecibo = ObservatoryMPC(arecibo_m) - @test arecibo.code == "251" - @test arecibo.long == 293.24692 - @test arecibo.cos == 0.949577 - @test arecibo.sin == +0.312734 - @test arecibo.name == "Arecibo" - - hubble_s = "250 Hubble Space Telescope" - hubble_m = match(mpc_observatory_regex, hubble_s) - hubble = ObservatoryMPC(hubble_m) - @test hubble.code == "250" - @test isnan(hubble.long) - @test isnan(hubble.cos) - @test isnan(hubble.sin) - @test hubble.name == "Hubble Space Telescope" - - # Unknown observatory - unkobs = unknownobs() - @test isunknown(unkobs) - @test !isunknown(arecibo) - @test !isunknown(hubble) - - # hascoord - @test hascoord(arecibo) - @test !hascoord(hubble) - @test !hascoord(unkobs) - - # Catalogue equality - @test unkobs == unkobs - @test arecibo == arecibo - @test hubble == hubble - @test arecibo != unkobs - @test hubble != unkobs - @test arecibo != hubble - - # Read/write observatories file - source_obs = read_observatories_mpc(ObsCodes_path) - check_file = joinpath(observations_path, "ObsCodes_.txt") - write_observatories_mpc(source_obs, check_file) - check_obs = read_observatories_mpc(check_file) - rm(check_file) - @test source_obs == check_obs - - # Update observatories file - update_observatories_mpc() - @test allunique(NEOs.mpc_observatories[]) - @test isa(NEOs.mpc_observatories[], Vector{ObservatoryMPC{Float64}}) - - # Search observatory code - obs = search_obs_code("250") - @test obs == hubble - obs = search_obs_code("251") - @test obs == arecibo -end +@testset "Observations" begin + + @testset "CatalogueMPC" begin + + using NEOs: mpc_catalogue_regex, CatalogueMPC, CatalogueCodes_path, observations_path + + # Check that local catalogues file exists + @test isfile(joinpath(observations_path, "CatalogueCodes.txt")) + + # Check global variable NEOs.mpc_catalogues[] + @test allunique(NEOs.mpc_catalogues[]) + @test isa(NEOs.mpc_catalogues[], Vector{CatalogueMPC}) + + # Parse CatalogueMPC + gaia_s = " 6 Gaia2016" + gaia_m = match(mpc_catalogue_regex, gaia_s) + gaia = CatalogueMPC(gaia_m) + @test gaia.code == "6" + @test gaia.name == "Gaia2016" + + # Unknown catalogue + unkcat = unknowncat() + @test isunknown(unkcat) + @test !isunknown(gaia) + + # Catalogue equality + @test unkcat == unkcat + @test gaia == gaia + @test gaia != unkcat + + # Read/write catalogues file + source_cat = read_catalogues_mpc(CatalogueCodes_path) + check_file = joinpath(observations_path, "CatalogueCodes_.txt") + write_catalogues_mpc(source_cat, check_file) + check_cat = read_catalogues_mpc(check_file) + rm(check_file) + @test source_cat == check_cat + + # Update catalogues file + update_catalogues_mpc() + @test allunique(NEOs.mpc_catalogues[]) + @test isa(NEOs.mpc_catalogues[], Vector{CatalogueMPC}) + + # Search catalogue code + cat = search_cat_code("6") + @test cat == gaia + end -using NEOs: mpc_radec_regex, RadecMPC, src_path -using Dates - -@testset "RadecMPC" begin - # Parse RadecMPC - apophis_s = "99942K04M04N C2004 03 15.10789 04 06 08.08 +16 55 04.6 om6394691" - apophis_m = match(mpc_radec_regex, apophis_s) - apophis = RadecMPC(apophis_m) - @test apophis.num == "99942" - @test apophis.tmpdesig == "K04M04N" - @test apophis.discovery == " " - @test apophis.publishnote == " " - @test apophis.obstech == "C" - @test apophis.date == DateTime("2004-03-15T02:35:21.696") - @test apophis.α == 1.0739650841580173 - @test apophis.δ == 0.2952738332250385 - @test apophis.info1 == " " - @test apophis.mag == " " - @test apophis.band == " " - @test apophis.catalogue == search_cat_code("o") - @test apophis.info2 == "m6394" - @test apophis.observatory == search_obs_code("691") - - # RadecMPC equality - @test apophis == apophis - - # Read/write radec file - source_file = joinpath(dirname(src_path), "data/99942.dat") - source_radec = read_radec_mpc(source_file) - check_file = joinpath(dirname(src_path), "data/99942_.dat") - write_radec_mpc(source_radec, check_file) - check_radec = read_radec_mpc(check_file) - rm(check_file) - - @test source_radec == check_radec - - # Search MPC circulars - function search_apophis(m::RegexMatch) - if (m["num"] == "99942") || (m["tmpdesig"] == "N00hp15") - return true - else - return false + @testset "ObservatoryMPC" begin + + using NEOs: mpc_observatory_regex, ObservatoryMPC, ObsCodes_path + + # Check that local observatories file exists + @test isfile(joinpath(observations_path, "ObsCodes.txt")) + + # Check global variable NEOs.mpc_observatories[] + @test allunique(NEOs.mpc_observatories[]) + @test isa(NEOs.mpc_observatories[], Vector{ObservatoryMPC{Float64}}) + + # Parse ObservatoryMPC + arecibo_s = "251 293.246920.949577+0.312734Arecibo" + arecibo_m = match(mpc_observatory_regex, arecibo_s) + arecibo = ObservatoryMPC(arecibo_m) + @test arecibo.code == "251" + @test arecibo.long == 293.24692 + @test arecibo.cos == 0.949577 + @test arecibo.sin == +0.312734 + @test arecibo.name == "Arecibo" + + hubble_s = "250 Hubble Space Telescope" + hubble_m = match(mpc_observatory_regex, hubble_s) + hubble = ObservatoryMPC(hubble_m) + @test hubble.code == "250" + @test isnan(hubble.long) + @test isnan(hubble.cos) + @test isnan(hubble.sin) + @test hubble.name == "Hubble Space Telescope" + + # Unknown observatory + unkobs = unknownobs() + @test isunknown(unkobs) + @test !isunknown(arecibo) + @test !isunknown(hubble) + + # hascoord + @test hascoord(arecibo) + @test !hascoord(hubble) + @test !hascoord(unkobs) + + # Catalogue equality + @test unkobs == unkobs + @test arecibo == arecibo + @test hubble == hubble + @test arecibo != unkobs + @test hubble != unkobs + @test arecibo != hubble + + # Read/write observatories file + source_obs = read_observatories_mpc(ObsCodes_path) + check_file = joinpath(observations_path, "ObsCodes_.txt") + write_observatories_mpc(source_obs, check_file) + check_obs = read_observatories_mpc(check_file) + rm(check_file) + @test source_obs == check_obs + + # Update observatories file + update_observatories_mpc() + @test allunique(NEOs.mpc_observatories[]) + @test isa(NEOs.mpc_observatories[], Vector{ObservatoryMPC{Float64}}) + + # Search observatory code + obs = search_obs_code("250") + @test obs == hubble + obs = search_obs_code("251") + @test obs == arecibo + end + + @testset "RadecMPC" begin + + using NEOs: mpc_radec_regex, RadecMPC, src_path + using Dates + + # Parse RadecMPC + apophis_s = "99942K04M04N C2004 03 15.10789 04 06 08.08 +16 55 04.6 om6394691" + apophis_m = match(mpc_radec_regex, apophis_s) + apophis = RadecMPC(apophis_m) + @test apophis.num == "99942" + @test apophis.tmpdesig == "K04M04N" + @test apophis.discovery == " " + @test apophis.publishnote == " " + @test apophis.obstech == "C" + @test apophis.date == DateTime("2004-03-15T02:35:21.696") + @test apophis.α == 1.0739650841580173 + @test apophis.δ == 0.2952738332250385 + @test apophis.info1 == " " + @test apophis.mag == " " + @test apophis.band == " " + @test apophis.catalogue == search_cat_code("o") + @test apophis.info2 == "m6394" + @test apophis.observatory == search_obs_code("691") + + # RadecMPC equality + @test apophis == apophis + + # Read/write radec file + source_file = joinpath(dirname(src_path), "data/99942.dat") + source_radec = read_radec_mpc(source_file) + check_file = joinpath(dirname(src_path), "data/99942_.dat") + write_radec_mpc(source_radec, check_file) + check_radec = read_radec_mpc(check_file) + rm(check_file) + + @test source_radec == check_radec + + # Search MPC circulars + function search_apophis(m::RegexMatch) + if (m["num"] == "99942") || (m["tmpdesig"] == "N00hp15") + return true + else + return false + end end + + obs = search_circulars_mpc( + search_apophis, + "https://minorplanetcenter.net/mpec/K20/K20YA9.html", + "https://minorplanetcenter.net/mpec/K21/K21JL0.html"; + max_iter = 10 + ) + + @test isa(obs, Vector{RadecMPC{Float64}}) + @test issorted(obs) + @test allunique(obs) + @test all( (getfield.(obs, :num) .== "99942") .| (getfield.(obs, :tmpdesig) .== "N00hp15") ) + end + + @testset "RadarJPL" begin + + using NEOs: jpl_radar_regex, RadarJPL, jpl_radar_dateformat + + # Parse RadarJPL + apophis_s = "99942 Apophis (2004 MN4) 2005-01-27 23:31:00 -100849.1434 0.250 Hz 2380 251 251 C" + apophis_m = match(jpl_radar_regex, apophis_s) + apophis = RadarJPL(Val(false), apophis_m) + @test apophis.id == "99942 Apophis (2004 MN4)" + @test apophis.date == DateTime("2005-01-27 23:31:00", jpl_radar_dateformat) + @test isnan(apophis.Δτ) + @test isnan(apophis.Δτ_σ) + @test apophis.Δτ_units == "" + @test apophis.Δν == -100849.1434 + @test apophis.Δν_σ == 0.250 + @test apophis.Δν_units == "Hz" + @test apophis.freq == 2380.0 + @test apophis.rcvr == search_obs_code("251") + @test apophis.xmit == search_obs_code("251") + @test apophis.bouncepoint == "C" + @test ismonostatic(apophis) + @test !hasdelay(apophis) + @test hasdoppler(apophis) + + # RadarJPL equality + @test apophis == apophis + + # Read/write radar file + source_file = joinpath(dirname(src_path), "data/99942_RADAR_2005_2013.dat") + source_radar = read_radar_jpl(source_file) + check_file = joinpath(dirname(src_path), "data/99942_RADAR_2005_2013_.dat") + write_radar_jpl(source_radar, check_file) + check_radar = read_radar_jpl(check_file) + rm(check_file) + + @test source_radar == check_radar end - - obs = search_circulars_mpc( - search_apophis, - "https://minorplanetcenter.net/mpec/K20/K20YA9.html", - "https://minorplanetcenter.net/mpec/K21/K21JL0.html"; - max_iter = 10 - ) - - @test isa(obs, Vector{RadecMPC{Float64}}) - @test issorted(obs) - @test allunique(obs) - @test all( (getfield.(obs, :num) .== "99942") .| (getfield.(obs, :tmpdesig) .== "N00hp15") ) -end -using NEOs: jpl_radar_regex, RadarJPL, jpl_radar_dateformat - -@testset "RadarJPL" begin - # Parse RadarJPL - apophis_s = "99942 Apophis (2004 MN4) 2005-01-27 23:31:00 -100849.1434 0.250 Hz 2380 251 251 C" - apophis_m = match(jpl_radar_regex, apophis_s) - apophis = RadarJPL(Val(false), apophis_m) - @test apophis.id == "99942 Apophis (2004 MN4)" - @test apophis.date == DateTime("2005-01-27 23:31:00", jpl_radar_dateformat) - @test isnan(apophis.Δτ) - @test isnan(apophis.Δτ_σ) - @test apophis.Δτ_units == "" - @test apophis.Δν == -100849.1434 - @test apophis.Δν_σ == 0.250 - @test apophis.Δν_units == "Hz" - @test apophis.freq == 2380.0 - @test apophis.rcvr == search_obs_code("251") - @test apophis.xmit == search_obs_code("251") - @test apophis.bouncepoint == "C" - @test ismonostatic(apophis) - @test !hasdelay(apophis) - @test hasdoppler(apophis) - - # RadarJPL equality - @test apophis == apophis - - # Read/write radar file - source_file = joinpath(dirname(src_path), "data/99942_RADAR_2005_2013.dat") - source_radar = read_radar_jpl(source_file) - check_file = joinpath(dirname(src_path), "data/99942_RADAR_2005_2013_.dat") - write_radar_jpl(source_radar, check_file) - check_radar = read_radar_jpl(check_file) - rm(check_file) - - @test source_radar == check_radar -end \ No newline at end of file +end diff --git a/test/propagation.jl b/test/propagation.jl index aaae4e02..3f86fcfd 100644 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -7,15 +7,97 @@ using Test using InteractiveUtils: methodswith -@testset "Integration methods" begin - - @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph!}, TaylorIntegration.jetcoeffs!)) - @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph!}, TaylorIntegration._allocate_jetcoeffs!)) - - @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, TaylorIntegration.jetcoeffs!)) - @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, TaylorIntegration._allocate_jetcoeffs!)) - - @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorIntegration.jetcoeffs!)) - @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorIntegration._allocate_jetcoeffs!)) - -end \ No newline at end of file +@testset "Orbit propagation" begin + + @testset "Integration methods" begin + + @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph!}, TaylorIntegration.jetcoeffs!)) + @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph!}, TaylorIntegration._allocate_jetcoeffs!)) + + @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, TaylorIntegration.jetcoeffs!)) + @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_ng_eph_threads!}, TaylorIntegration._allocate_jetcoeffs!)) + + @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorIntegration.jetcoeffs!)) + @test !isempty(methodswith(Val{RNp1BP_pN_A_J23E_J2S_eph_threads!}, TaylorIntegration._allocate_jetcoeffs!)) + + end + + @testset "Orbit propagation without nongravs: 2023 DW" begin + + using PlanetaryEphemeris: selecteph, ea, su, daysec, auday2kmsec + using Statistics + + objname = "2023DW" + maxsteps = 1000 + nyears = 0.2 + dense = true + quadmath = false # use quadruple precision + dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! + jd0 = datetime2julian(DateTime(2023,2,25,0,0,0)) #Julian date of integration initial time + q0 = [-9.759018085743707E-01, 3.896554445697074E-01, 1.478066121706831E-01, -9.071450085084557E-03, -9.353197026254517E-03, -5.610023032269034E-03] + sseph = NEOs.sseph + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + + NEOs.propagate( + dynamics, + 1, + jd0, + nyears, + sseph, + q0, + Val(true), + order = 25, + abstol = 1e-20, + parse_eqs = true + ) + + sol = NEOs.propagate( + dynamics, + maxsteps, + jd0, + nyears, + sseph, + q0, + Val(true), + order = 25, + abstol = 1e-20, + parse_eqs = true + ) + + # Read optical astrometry file + + obs_radec_mpc_2023DW = NEOs.read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) + nobs = length(obs_radec_mpc_2023DW) + + # Compute residuals + loadjpleph() # load JPL ephemeris + @time res, w = NEOs.residuals( + obs_radec_mpc_2023DW, + xve=t->auday2kmsec(eph_ea(t)), + xvs=t->auday2kmsec(eph_su(t)), + xva=t->auday2kmsec(sol(t/daysec)) + ) + + @test mean(res) ≈ -0.6667868924169593 + @test std(res) ≈ 0.7360918596772479 + # pre-fit normalized RMS using Veres et al. (2017) weights + @test nrms(res, w) ≈ 1.656629515975594 + # pre-fit normalized RMS using ESA/NEOCC/NEODyS weights + rms_NEOCC = [0.600,0.600,0.600,0.600,0.600,0.600,0.600,0.600,0.600,0.600,0.600,0.600,0.600, + 0.600,0.600,0.600,0.600,0.600,0.600,1.000,1.000,1.000,0.600,0.600,0.600,0.600,1.000, + 0.600,0.600,0.600,0.600,0.600,0.600,1.000,1.000,0.600,0.600,0.600,0.600,0.500,0.500, + 0.600,0.600,0.600,0.600,0.600,1.000,1.000,1.000,0.500,0.500,0.500,0.500,0.500,0.500, + 0.130,0.150,0.160,0.500,0.500,0.600,0.600,0.400,0.400,0.400,0.600,0.600,0.600,0.600, + 0.600,0.500,0.500,0.400,0.400,0.400,0.600,0.600,0.600,0.600,0.600,0.400,0.400,0.400, + 1.000,1.000,0.300,1.000,0.300,1.000,0.300,0.500,0.300,0.500,0.500,0.600,0.600,0.600, + 0.600,0.600,0.500,0.500,0.400,0.400,0.600,0.400,0.600,0.060,0.090,0.400,0.600,0.600, + 0.600,0.600,0.600,0.600,0.100,0.100,0.100,0.060,0.050,0.050,0.060,0.050] + w_NEOCC = repeat(1.0./rms_NEOCC.^2, 2) + @test nrms(res, w_NEOCC) ≈ 3.5579681705883575 + + end + +end From 1a706323632ac7d1157afc449c8d129c8ad0c5b0 Mon Sep 17 00:00:00 2001 From: LuEdRaMo Date: Sun, 4 Jun 2023 11:10:03 -0600 Subject: [PATCH 27/46] Fix deprecation warning --- src/NEOs.jl | 2 +- src/observations/ObsCodes.txt | 1 + src/observations/units.jl | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index 7e41669e..e2fb34a9 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -15,7 +15,7 @@ using PlanetaryEphemeris: daysec, su, ea, α_p_sun, δ_p_sun, t2c_jpl_de430, pol nbodyind, ordpres_differentiate, numberofbodies, kmsec2auday, auday2kmsec using Healpix: ang2pixRing, Resolution using SatelliteToolbox: get_iers_eop_iau_2000A, EOPData_IAU1980, EOPData_IAU2000A, JD_J2000, - orbsv, sv_ecef_to_eci, get_ΔAT, nutation_fk5 + orbsv, sv_ecef_to_eci, get_Δat, nutation_fk5 using Dates: format using HTTP: get using IntervalRootFinding: roots, interval, Interval, mid diff --git a/src/observations/ObsCodes.txt b/src/observations/ObsCodes.txt index 5f5130e0..a50c5ac6 100644 --- a/src/observations/ObsCodes.txt +++ b/src/observations/ObsCodes.txt @@ -2023,6 +2023,7 @@ M51 9.226970.655500+0.752709Robert Mayer Sternwarte, Heilbronn M52 8.578500.758941+0.649052Sassari M53 10.282190.585977+0.807623CAS Observatory, Preetz M54 7.077810.725140+0.686335Observatoire Albireo de Biot +M55 19.987000.656685+0.751814Luckystar Observatory, Vazec M90 65.428600.546720+0.834520Chervishevo N27 73.725300.578470+0.812980Omsk-Yogik Observatory N30 74.369400.853690+0.519090Zeds Astronomical Observatory, Lahore diff --git a/src/observations/units.jl b/src/observations/units.jl index eb769480..fd6a0408 100644 --- a/src/observations/units.jl +++ b/src/observations/units.jl @@ -102,7 +102,7 @@ function tdb_utc(et::T) where {T<:Number} utc_secs = et_00 - deltet(et_00, "ET") # ΔAT jd_utc = JD_J2000 + utc_secs/daysec - tai_utc = get_ΔAT(jd_utc) + tai_utc = get_Δat(jd_utc) # TDB-UTC = (TDB-TT) + (TT-TAI) + (TAI-UTC) = (TDB-TT) + 32.184 s + ΔAT return (tt_tai + tai_utc) - tt_tdb_et end From a33808b1054752fd39beca34f0ace967d3591371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 21:02:10 +0200 Subject: [PATCH 28/46] Move Tholen et al. (2013) astrometry file to test/data; Remove compat entries from test/Project.toml --- test/Project.toml | 4 - test/data/99942_Tholen_etal_2013.dat | 432 +++++++++++++++++++++++++++ 2 files changed, 432 insertions(+), 4 deletions(-) create mode 100644 test/data/99942_Tholen_etal_2013.dat diff --git a/test/Project.toml b/test/Project.toml index 5d90b3ee..2b612384 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -10,7 +10,3 @@ Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -# [compat] -# TaylorIntegration = "0.13" -# PlanetaryEphemeris = "0.6" diff --git a/test/data/99942_Tholen_etal_2013.dat b/test/data/99942_Tholen_etal_2013.dat new file mode 100644 index 00000000..36b71a75 --- /dev/null +++ b/test/data/99942_Tholen_etal_2013.dat @@ -0,0 +1,432 @@ +99942 'C2004 06 19.17015009 44 29.677+13 18 50.67 L~09vB695 +99942 'C2004 06 19.17486109 44 30.604+13 18 46.81 L~09vB695 +99942 'C2004 06 19.17967609 44 31.507+13 18 42.91 L~09vB695 +99942 'C2004 06 20.15951409 47 41.116+13 05 24.49 L~09vB695 +99942 'C2004 06 20.16431709 47 42.006+13 05 20.50 L~09vB695 +99942 'C2004 06 20.16906309 47 42.926+13 05 16.74 L~09vB695 +99942 'C2005 07 09.17600210 34 38.149+16 12 41.50 L~09vB695 +99942 'C2005 07 09.18080710 34 38.288+16 12 42.68 L~09vB695 +99942 'C2005 07 10.17554310 35 10.909+16 18 25.82 L~09vB695 +99942 'C2005 07 10.17819210 35 10.983+16 18 26.48 L~09vB695 +99942 'C2005 07 11.16972710 35 36.698+16 24 46.68 L~09vB695 +99942 2C2005 09 04.63519408 25 00.085+22 18 13.02 L~09vB568 +99942 2C2005 09 04.63627008 25 00.075+22 18 12.36 L~09vB568 +99942 2C2005 12 31.64597612 46 28.407-11 49 33.02 L~09vB568 +99942 2C2005 12 31.64713112 46 28.583-11 49 34.23 L~09vB568 +99942 2C2005 12 31.64800212 46 28.708-11 49 35.16 L~09vB568 +99942 2C2006 03 05.54636616 20 49.786-26 34 29.32 L~09vB568 +99942 2C2006 03 05.61052316 21 07.957-26 34 51.45 L~09vB568 +99942 2C2006 03 05.65266816 21 19.828-26 35 04.75 L~09vB568 +99942 2C2006 03 06.51985316 25 39.350-26 39 07.23 L~09vB568 +99942 2C2006 03 06.52154416 25 39.838-26 39 07.85 L~09vB568 +99942 2C2006 03 06.52319016 25 40.319-26 39 08.38 L~09vB568 +99942 2C2006 03 06.52483716 25 40.802-26 39 08.75 L~09vB568 +99942 2C2006 03 06.52649816 25 41.288-26 39 09.42 L~09vB568 +99942 2C2006 03 06.53152916 25 42.744-26 39 11.09 L~09vB568 +99942 2C2006 03 06.53317516 25 43.230-26 39 11.64 L~09vB568 +99942 2C2006 03 06.53785116 25 44.576-26 39 13.17 L~09vB568 +99942 2C2006 03 06.53950516 25 45.058-26 39 13.71 L~09vB568 +99942 2C2006 03 06.54114016 25 45.528-26 39 14.25 L~09vB568 +99942 2C2006 03 06.54279516 25 46.018-26 39 14.75 L~09vB568 +99942 2C2006 03 06.54460416 25 46.542-26 39 15.35 L~09vB568 +99942 2C2006 03 06.54622816 25 47.020-26 39 15.82 L~09vB568 +99942 2C2006 03 06.54788716 25 47.487-26 39 16.37 L~09vB568 +99942 2C2006 03 06.54963916 25 48.001-26 39 16.97 L~09vB568 +99942 2C2006 03 06.55128516 25 48.473-26 39 17.49 L~09vB568 +99942 2C2006 03 06.55294416 25 48.954-26 39 18.02 L~09vB568 +99942 2C2006 03 06.58062516 25 56.956-26 39 26.69 L~09vB568 +99942 2C2006 03 06.58226716 25 57.429-26 39 27.19 L~09vB568 +99942 2C2006 03 06.58390316 25 57.889-26 39 27.56 L~09vB568 +99942 2C2006 03 06.58565516 25 58.403-26 39 28.25 L~09vB568 +99942 2C2006 03 06.58729516 25 58.884-26 39 28.74 L~09vB568 +99942 2C2006 03 06.58894616 25 59.356-26 39 29.24 L~09vB568 +99942 2C2006 03 06.59071316 25 59.860-26 39 29.79 L~09vB568 +99942 2C2006 03 06.59240616 26 00.342-26 39 30.29 L~09vB568 +99942 2C2006 03 06.59416916 26 00.854-26 39 30.79 L~09vB568 +99942 2C2006 03 06.59581316 26 01.332-26 39 31.30 L~09vB568 +99942 2C2006 03 06.59986316 26 02.494-26 39 32.45 L~09vB568 +99942 2C2006 03 06.60160616 26 02.993-26 39 33.01 L~09vB568 +99942 2C2006 03 06.60323516 26 03.457-26 39 33.48 L~09vB568 +99942 2C2006 03 06.60488216 26 03.930-26 39 34.00 L~09vB568 +99942 2C2006 03 06.60655416 26 04.414-26 39 34.45 L~09vB568 +99942 2C2006 03 06.60819916 26 04.891-26 39 34.94 L~09vB568 +99942 2C2006 03 06.60994916 26 05.388-26 39 35.44 L~09vB568 +99942 2C2006 03 06.61161916 26 05.870-26 39 35.93 L~09vB568 +99942 2C2006 03 06.61340316 26 06.381-26 39 36.46 L~09vB568 +99942 2C2006 03 06.61522116 26 06.900-26 39 36.96 L~09vB568 +99942 2C2006 03 06.61779416 26 07.648-26 39 37.74 L~09vB568 +99942 2C2006 03 06.61944816 26 08.129-26 39 38.22 L~09vB568 +99942 2C2006 03 06.62108316 26 08.593-26 39 38.68 L~09vB568 +99942 2C2006 03 06.62287816 26 09.105-26 39 39.17 L~09vB568 +99942 2C2006 03 06.62453816 26 09.584-26 39 39.65 L~09vB568 +99942 2C2006 03 06.62634316 26 10.112-26 39 40.15 L~09vB568 +99942 2C2006 03 06.62962316 26 11.039-26 39 41.09 L~09vB568 +99942 2C2006 03 06.63137516 26 11.530-26 39 41.57 L~09vB568 +99942 2C2006 03 06.63303116 26 12.016-26 39 42.05 L~09vB568 +99942 2C2006 03 06.63501716 26 12.589-26 39 42.58 L~09vB568 +99942 2C2006 03 06.63831016 26 13.532-26 39 43.51 L~09vB568 +99942 2C2006 03 06.63998416 26 14.033-26 39 43.93 L~09vB568 +99942 2C2006 03 06.64177816 26 14.532-26 39 44.44 L~09vB568 +99942 2C2006 03 06.64342816 26 15.007-26 39 44.91 L~09vB568 +99942 2C2006 03 06.64522616 26 15.513-26 39 45.40 L~09vB568 +99942 2C2006 03 06.64689116 26 16.000-26 39 45.85 L~09vB568 +99942 2C2006 03 06.64869616 26 16.534-26 39 46.31 L~09vB568 +99942 2C2006 03 06.65033416 26 16.985-26 39 46.76 L~09vB568 +99942 2C2006 03 08.52450916 35 51.633-26 46 44.58 L~09vB568 +99942 2C2006 03 08.52614416 35 52.139-26 46 45.02 L~09vB568 +99942 2C2006 03 08.52778416 35 52.632-26 46 45.44 L~09vB568 +99942 2C2006 03 08.52940616 35 53.122-26 46 45.81 L~09vB568 +99942 2C2006 03 08.53118916 35 53.668-26 46 46.23 L~09vB568 +99942 2C2006 03 08.53282516 35 54.145-26 46 46.74 L~09vB568 +99942 2C2006 03 08.53446116 35 54.645-26 46 47.05 L~09vB568 +99942 2C2006 03 08.53622516 35 55.161-26 46 47.51 L~09vB568 +99942 2C2006 03 08.53952316 35 56.166-26 46 48.34 L~09vB568 +99942 2C2006 03 08.54821816 35 58.785-26 46 50.43 L~09vB568 +99942 2C2006 03 08.54987016 35 59.291-26 46 50.85 L~09vB568 +99942 2C2006 03 08.55150916 35 59.779-26 46 51.19 L~09vB568 +99942 2C2006 03 08.55327516 36 00.314-26 46 51.64 L~09vB568 +99942 2C2006 03 08.55494116 36 00.797-26 46 52.06 L~09vB568 +99942 2C2006 03 08.55657116 36 01.305-26 46 52.45 L~09vB568 +99942 2C2006 03 08.55820316 36 01.809-26 46 52.76 L~09vB568 +99942 2C2006 03 08.55999116 36 02.337-26 46 53.31 L~09vB568 +99942 2C2006 03 08.56165316 36 02.824-26 46 53.65 L~09vB568 +99942 2C2006 03 08.56331116 36 03.321-26 46 54.00 L~09vB568 +99942 2C2006 03 08.56529216 36 03.925-26 46 54.53 L~09vB568 +99942 2C2006 03 08.56705816 36 04.447-26 46 54.94 L~09vB568 +99942 2C2006 03 08.56870116 36 04.934-26 46 55.29 L~09vB568 +99942 2C2006 03 08.57034116 36 05.423-26 46 55.67 L~09vB568 +99942 2C2006 03 08.57210416 36 05.964-26 46 56.10 L~09vB568 +99942 2C2006 03 08.57374816 36 06.447-26 46 56.43 L~09vB568 +99942 2C2006 03 08.57878216 36 07.950-26 46 57.62 L~09vB568 +99942 2C2006 03 08.58043616 36 08.453-26 46 57.97 L~09vB568 +99942 2C2006 03 08.59506416 36 12.824-26 47 01.24 L~09vB568 +99942 2C2006 03 08.59679916 36 13.342-26 47 01.59 L~09vB568 +99942 2C2006 03 08.59842816 36 13.834-26 47 01.97 L~09vB568 +99942 2C2006 03 08.60007616 36 14.327-26 47 02.20 L~09vB568 +99942 2C2006 03 08.60176516 36 14.819-26 47 02.62 L~09vB568 +99942 2C2006 03 08.60342016 36 15.335-26 47 03.00 L~09vB568 +99942 2C2006 03 08.60506016 36 15.804-26 47 03.30 L~09vB568 +99942 2C2006 03 08.60672516 36 16.308-26 47 03.66 L~09vB568 +99942 2C2006 03 08.60840016 36 16.812-26 47 04.07 L~09vB568 +99942 2C2006 03 08.61019116 36 17.347-26 47 04.43 L~09vB568 +99942 2C2006 03 08.61180216 36 17.821-26 47 04.73 L~09vB568 +99942 2C2006 03 08.61356016 36 18.338-26 47 05.15 L~09vB568 +99942 2C2006 03 08.61522616 36 18.848-26 47 05.46 L~09vB568 +99942 2C2006 03 08.61702416 36 19.384-26 47 05.80 L~09vB568 +99942 2C2006 03 08.61880916 36 19.911-26 47 06.18 L~09vB568 +99942 2C2006 03 08.62044116 36 20.397-26 47 06.50 L~09vB568 +99942 2C2006 03 08.62209616 36 20.893-26 47 06.83 L~09vB568 +99942 2C2006 03 08.62373616 36 21.391-26 47 07.18 L~09vB568 +99942 2C2006 03 08.62551916 36 21.915-26 47 07.56 L~09vB568 +99942 2C2006 03 08.62716816 36 22.403-26 47 07.90 L~09vB568 +99942 2C2006 03 08.62914916 36 23.003-26 47 08.29 L~09vB568 +99942 2C2006 03 08.63083816 36 23.503-26 47 08.58 L~09vB568 +99942 2C2006 03 08.63248116 36 23.992-26 47 08.94 L~09vB568 +99942 2C2006 03 08.63410316 36 24.477-26 47 09.24 L~09vB568 +99942 2C2006 03 08.63588516 36 24.997-26 47 09.59 L~09vB568 +99942 2C2006 03 08.63752916 36 25.500-26 47 09.91 L~09vB568 +99942 2C2006 03 08.63917116 36 25.991-26 47 10.23 L~09vB568 +99942 2C2006 03 08.64083116 36 26.480-26 47 10.54 L~09vB568 +99942 2C2006 03 08.64263816 36 27.008-26 47 10.89 L~09vB568 +99942 2C2006 03 08.64430016 36 27.506-26 47 11.22 L~09vB568 +99942 2C2006 03 08.64589016 36 27.988-26 47 11.49 L~09vB568 +99942 2C2006 03 08.64751516 36 28.476-26 47 11.82 L~09vB568 +99942 2C2006 03 08.64930316 36 29.008-26 47 12.13 L~09vB568 +99942 2C2006 03 08.65095316 36 29.492-26 47 12.45 L~09vB568 +99942 2C2006 03 08.66103116 36 32.496-26 47 14.31 L~09vB568 +99942 2C2006 05 01.62736922 43 36.580-01 20 46.01 L~09vB568 +99942 2C2006 05 01.62821822 43 36.869-01 20 44.02 L~09vB568 +99942 2C2006 06 01.60681201 12 41.522+14 14 31.91 L~09vB568 +99942 2C2006 06 01.60868801 12 41.959+14 14 34.24 L~09vB568 +99942 2C2006 06 02.59935901 16 48.755+14 34 20.07 L~09vB568 +99942 2C2006 06 02.60078001 16 49.108+14 34 21.72 L~09vB568 +99942 2C2006 06 02.60224201 16 49.478+14 34 23.59 L~09vB568 +99942 2C2006 07 27.61254105 06 37.958+23 53 27.72 L~09vB568 +99942 2C2006 07 27.61447305 06 38.465+23 53 27.83 L~09vB568 +99942 2C2006 08 15.61852106 26 52.404+22 57 47.52 L~09vB568 +99942 2C2006 08 15.62233206 26 53.348+22 57 46.02 L~09vB568 +99942 2C2006 08 16.62183606 31 00.059+22 51 14.54 L~09vB568 +99942 2C2006 08 16.62441906 31 00.629+22 51 13.69 L~09vB568 +99942 2C2006 08 16.62695406 31 01.254+22 51 12.76 L~09vB568 +99942 2C2006 09 04.59915907 45 57.632+19 48 13.43 L~09vB568 +99942 2C2006 09 04.60174207 45 58.282+19 48 11.30 L~09vB568 +99942 2C2006 09 04.60702707 45 59.441+19 48 07.57 L~09vB568 +99942 2C2006 09 04.60960407 46 00.032+19 48 05.65 L~09vB568 +99942 2C2006 09 04.61217807 46 00.596+19 48 03.81 L~09vC568 +99942 2C2006 09 04.61475007 46 01.189+19 48 01.98 L~09vC568 +99942 2C2006 09 04.61733207 46 01.771+19 48 00.12 L~09vC568 +99942 2C2006 09 04.61991607 46 02.330+19 47 58.33 L~09vC568 +99942 2C2006 09 04.62259307 46 02.963+19 47 56.27 L~09vC568 +99942 2C2006 09 04.62517107 46 03.533+19 47 54.35 L~09vC568 +99942 2C2006 09 04.62774407 46 04.120+19 47 52.46 L~09vC568 +99942 2C2006 10 25.59993210 38 53.805+05 37 27.51 L~09vC568 +99942 2C2006 10 25.60369210 38 54.499+05 37 23.28 L~09vC568 +99942 2C2006 10 25.60744010 38 55.203+05 37 18.89 L~09vC568 +99942 2C2006 10 25.61132210 38 55.912+05 37 14.36 L~09vC568 +99942 2C2006 10 25.61506310 38 56.601+05 37 10.09 L~09vC568 +99942 2C2006 10 25.61879910 38 57.275+05 37 05.78 L~09vC568 +99942 2C2006 10 25.62267810 38 58.014+05 37 01.23 L~09vC568 +99942 2C2006 10 25.62640510 38 58.696+05 36 56.87 L~09vC568 +99942 2C2006 10 25.63014810 38 59.377+05 36 52.66 L~09vC568 +99942 2C2006 10 25.63403010 39 00.098+05 36 48.23 L~09vC568 +99942 2C2006 10 25.63779510 39 00.816+05 36 43.85 L~09vC568 +99942 2C2006 11 28.59593412 23 24.533-05 33 25.55 L~09vC568 +99942 2C2006 11 28.59911212 23 25.116-05 33 29.23 L~09vC568 +99942 2C2006 11 28.60196112 23 25.630-05 33 32.60 L~09vC568 +99942 2C2006 11 28.60444112 23 26.110-05 33 35.60 L~09vC568 +99942 2C2006 11 28.60694712 23 26.572-05 33 38.57 L~09vC568 +99942 2C2006 11 28.60930612 23 27.008-05 33 41.28 L~09vC568 +99942 2C2006 11 28.61175812 23 27.455-05 33 44.13 L~09vC568 +99942 2C2006 11 28.61410412 23 27.900-05 33 47.02 L~09vC568 +99942 2C2006 11 28.61644012 23 28.333-05 33 49.76 L~09vC568 +99942 2C2006 11 28.61881912 23 28.750-05 33 52.52 L~09vC568 +99942 2C2006 11 28.62122512 23 29.200-05 33 55.26 L~09vC568 +99942 2C2006 11 28.62509412 23 29.918-05 33 59.86 L~09vC568 +99942 2C2006 11 28.62744612 23 30.356-05 34 02.67 L~09vC568 +99942 2C2006 11 28.62980412 23 30.783-05 34 05.39 L~09vC568 +99942 2C2006 11 28.63229412 23 31.243-05 34 08.35 L~09vC568 +99942 2C2006 11 28.63463812 23 31.694-05 34 11.18 L~09vC568 +99942 2C2006 11 28.63699212 23 32.122-05 34 13.96 L~09vC568 +99942 2C2006 11 28.63939612 23 32.559-05 34 16.72 L~09vC568 +99942 2C2006 11 28.64191212 23 33.023-05 34 19.79 L~09vC568 +99942 2C2006 11 28.64780312 23 34.102-05 34 26.64 L~09vC568 +99942 2C2006 12 25.61583813 51 22.763-13 59 56.70 L~09vC568 +99942 2C2006 12 25.61784113 51 23.174-13 59 58.77 L~09vC568 +99942 2C2006 12 25.61998413 51 23.614-14 00 01.00 L~09vC568 +99942 2C2006 12 25.62212713 51 24.048-14 00 03.19 L~09vC568 +99942 2C2006 12 25.62426613 51 24.483-14 00 05.46 L~09vC568 +99942 2C2006 12 25.62626013 51 24.897-14 00 07.57 L~09vC568 +99942 2C2006 12 25.62826013 51 25.303-14 00 09.63 L~09vC568 +99942 2C2006 12 25.63026913 51 25.727-14 00 11.91 L~09vC568 +99942 2C2006 12 25.63226613 51 26.111-14 00 13.98 L~09vC568 +99942 2C2006 12 25.63432513 51 26.550-14 00 16.10 L~09vC568 +99942 2C2006 12 25.63633713 51 26.944-14 00 18.32 L~09vC568 +99942 2C2006 12 25.63845413 51 27.397-14 00 20.54 L~09vC568 +99942 2C2006 12 25.64046913 51 27.795-14 00 22.50 L~09vC568 +99942 2C2006 12 25.64260413 51 28.243-14 00 24.79 L~09vC568 +99942 2C2006 12 25.64459413 51 28.632-14 00 26.91 L~09vC568 +99942 2C2006 12 25.64658913 51 29.049-14 00 28.99 L~09vC568 +99942 2C2006 12 25.64859613 51 29.453-14 00 31.11 L~09vC568 +99942 2C2006 12 25.65072813 51 29.887-14 00 33.30 L~09vC568 +99942 2C2006 12 25.65277913 51 30.308-14 00 35.48 L~09vC568 +99942 2C2006 12 25.65477513 51 30.727-14 00 37.66 L~09vC568 +99942 2C2006 12 26.61927413 54 51.077-14 17 22.37 L~09vC568 +99942 2C2006 12 26.62186713 54 51.617-14 17 25.10 L~09vC568 +99942 2C2006 12 26.62443413 54 52.140-14 17 27.76 L~09vC568 +99942 2C2006 12 26.62701613 54 52.676-14 17 30.47 L~09vC568 +99942 2C2006 12 26.62959313 54 53.203-14 17 33.18 L~09vC568 +99942 2C2006 12 26.63231513 54 53.784-14 17 36.02 L~09vC568 +99942 2C2006 12 26.63489013 54 54.277-14 17 38.64 L~09vC568 +99942 2C2006 12 26.63746513 54 54.814-14 17 41.38 L~09vC568 +99942 2C2006 12 26.64003713 54 55.344-14 17 44.03 L~09vC568 +99942 2C2006 12 26.64443813 54 56.257-14 17 48.70 L~09vC568 +99942 2C2006 12 26.64702413 54 56.800-14 17 51.38 L~09vC568 +99942 2C2006 12 26.64960613 54 57.317-14 17 54.00 L~09vC568 +99942 2C2006 12 26.65233913 54 57.885-14 17 56.94 L~09vC568 +99942 2C2006 12 26.65491313 54 58.410-14 17 59.59 L~09vC568 +99942 2C2006 12 26.65764213 54 58.975-14 18 02.42 L~09vC568 +99942 2C2006 12 26.66021313 54 59.492-14 18 05.09 L~09vC568 +99942 2C2006 12 26.66295113 55 00.066-14 18 08.04 L~09vC568 +99942 2C2006 12 27.61377913 58 18.687-14 34 30.21 L~09vC568 +99942 2C2006 12 27.61612413 58 19.180-14 34 32.59 L~09vC568 +99942 2C2006 12 27.61846613 58 19.669-14 34 35.08 L~09vC568 +99942 2C2006 12 27.62092113 58 20.171-14 34 37.59 L~09vC568 +99942 2C2006 12 27.62343213 58 20.692-14 34 40.16 L~09vC568 +99942 2C2006 12 27.62813013 58 21.676-14 34 45.11 L~09vC568 +99942 2C2006 12 27.63047513 58 22.157-14 34 47.55 L~09vC568 +99942 2C2006 12 27.63283013 58 22.638-14 34 49.94 L~09vC568 +99942 2C2006 12 27.63536613 58 23.164-14 34 52.56 L~09vC568 +99942 2C2006 12 27.63772213 58 23.654-14 34 55.02 L~09vC568 +99942 2C2006 12 27.64018213 58 24.160-14 34 57.58 L~09vC568 +99942 2C2006 12 27.64251713 58 24.633-14 34 59.93 L~09vC568 +99942 2C2006 12 27.64486213 58 25.128-14 35 02.41 L~09vC568 +99942 2C2006 12 27.64733813 58 25.643-14 35 05.02 L~09vC568 +99942 2C2006 12 27.64968213 58 26.118-14 35 07.34 L~09vC568 +99942 2C2006 12 27.65219913 58 26.645-14 35 10.02 L~09vC568 +99942 2C2006 12 27.65454513 58 27.136-14 35 12.46 L~09vC568 +99942 2C2006 12 27.65693913 58 27.617-14 35 14.94 L~09vC568 +99942 2C2006 12 27.65923513 58 28.080-14 35 17.27 L~09vC568 +99942 2C2006 12 27.66161613 58 28.593-14 35 19.73 L~09vC568 +99942 2C2006 12 28.59892614 01 45.532-14 51 20.18 L~09vC568 +99942 2C2006 12 28.60127214 01 45.990-14 51 22.22 L~09vC568 +99942 2C2006 12 28.60361214 01 46.474-14 51 24.86 L~09vC568 +99942 2C2006 12 28.60595614 01 46.965-14 51 27.09 L~09vC568 +99942 2C2006 12 28.60834814 01 47.466-14 51 29.59 L~09vC568 +99942 2C2006 12 28.61068214 01 47.954-14 51 31.93 L~09vC568 +99942 2C2006 12 28.61313714 01 48.465-14 51 34.53 L~09vC568 +99942 2C2006 12 28.61548314 01 48.954-14 51 36.90 L~09vC568 +99942 2C2006 12 28.61782414 01 49.441-14 51 39.29 L~09vC568 +99942 2C2006 12 28.62048314 01 49.989-14 51 42.06 L~09vC568 +99942 2C2006 12 28.62284414 01 50.480-14 51 44.43 L~09vC568 +99942 2C2006 12 28.62521914 01 50.990-14 51 46.97 L~09vC568 +99942 2C2006 12 28.62755814 01 51.480-14 51 49.37 L~09vC568 +99942 2C2006 12 28.62989814 01 51.941-14 51 51.72 L~09vC568 +99942 2C2006 12 28.63223614 01 52.447-14 51 54.12 L~09vC568 +99942 2C2006 12 28.63472114 01 52.958-14 51 56.69 L~09vC568 +99942 2C2006 12 28.63709614 01 53.453-14 51 59.27 L~09vC568 +99942 2C2006 12 28.63958114 01 53.965-14 52 01.62 L~09vC568 +99942 2C2006 12 28.64222114 01 54.514-14 52 04.38 L~09vC568 +99942 2C2006 12 28.64470914 01 55.039-14 52 06.96 L~09vC568 +99942 2C2006 12 28.64705014 01 55.531-14 52 09.35 L~09vC568 +99942 2C2006 12 28.64938714 01 55.996-14 52 11.67 L~09vC568 +99942 2C2006 12 28.65175514 01 56.494-14 52 14.11 L~09vC568 +99942 2C2006 12 28.65410114 01 57.003-14 52 16.60 L~09vC568 +99942 2C2006 12 28.65644714 01 57.472-14 52 18.98 L~09vC568 +99942 2C2006 12 28.65879714 01 57.960-14 52 21.42 L~09vC568 +99942 2C2007 01 21.58245615 32 42.616-20 42 32.51 L~09vC568 +99942 2C2007 01 21.58477315 32 43.182-20 42 34.17 L~09vC568 +99942 2C2007 01 21.58711715 32 43.754-20 42 35.81 L~09vC568 +99942 2C2007 01 21.58959315 32 44.371-20 42 37.63 L~09vC568 +99942 2C2007 01 21.59195815 32 44.938-20 42 39.26 L~09vC568 +99942 2C2007 01 21.59430315 32 45.499-20 42 40.83 L~09vC568 +99942 2C2007 01 21.59664515 32 46.078-20 42 42.56 L~09vC568 +99942 2C2007 01 21.59911315 32 46.703-20 42 44.34 L~09vC568 +99942 2C2007 01 21.60382415 32 47.848-20 42 47.67 L~09vC568 +99942 2C2007 01 21.60630415 32 48.443-20 42 49.39 L~09vC568 +99942 2C2007 01 21.60865515 32 49.033-20 42 51.06 L~09vC568 +99942 2C2007 01 21.61111115 32 49.620-20 42 52.79 L~09vC568 +99942 2C2007 01 21.61348815 32 50.198-20 42 54.45 L~09vC568 +99942 2C2007 01 21.61596315 32 50.816-20 42 56.26 L~09vC568 +99942 2C2007 01 21.61830115 32 51.395-20 42 57.88 L~09vC568 +99942 2C2007 01 21.62065315 32 51.961-20 42 59.57 L~09vC568 +99942 2C2007 01 21.62537515 32 53.108-20 43 02.86 L~09vC568 +99942 2C2007 01 21.63384715 32 55.168-20 43 08.85 L~09vC568 +99942 2C2007 01 21.63855815 32 56.312-20 43 12.14 L~09vC568 +99942 2C2007 01 21.64091415 32 56.911-20 43 13.89 L~09vC568 +99942 2C2007 01 21.64325715 32 57.478-20 43 15.48 L~09vC568 +99942 2C2007 01 21.65294215 32 59.821-20 43 22.32 L~09vC568 +99942 2C2007 01 21.65549215 33 00.470-20 43 24.16 L~09vC568 +99942 2C2007 01 21.65785015 33 01.030-20 43 25.75 L~09vC568 +99942 2C2007 01 21.66020015 33 01.605-20 43 27.43 L~09vC568 +99942 2C2007 01 21.66256215 33 02.171-20 43 29.04 L~09vC568 +99942 2C2007 01 21.66506015 33 02.793-20 43 30.82 L~09vC568 +99942 2C2007 01 21.66740615 33 03.361-20 43 32.52 L~09vC568 +99942 2C2007 01 21.66975715 33 03.947-20 43 34.16 L~09vC568 +99942 2C2007 01 22.57214015 36 47.728-20 53 51.02 L~09vC568 +99942 2C2007 01 22.57654615 36 48.815-20 53 53.82 L~09vC568 +99942 2C2007 01 22.58476015 36 50.845-20 53 59.54 L~09vC568 +99942 2C2007 01 22.58756915 36 51.544-20 54 01.48 L~09vC568 +99942 2C2007 01 22.59237415 36 52.723-20 54 04.90 L~09vC568 +99942 2C2007 01 22.59473715 36 53.296-20 54 06.42 L~09vC568 +99942 2C2007 01 22.59708115 36 53.865-20 54 07.99 L~09vC568 +99942 2C2007 01 22.59954915 36 54.479-20 54 09.82 L~09vC568 +99942 2C2007 01 22.60189015 36 55.064-20 54 11.36 L~09vC568 +99942 2C2007 01 22.60423615 36 55.637-20 54 12.96 L~09vC568 +99942 2C2007 01 22.60669315 36 56.236-20 54 14.69 L~09vC568 +99942 2C2007 01 22.60915215 36 56.845-20 54 16.36 L~09vC568 +99942 2C2007 01 22.61163715 36 57.473-20 54 18.12 L~09vC568 +99942 2C2007 01 22.61397715 36 58.034-20 54 19.83 L~09vC568 +99942 2C2007 01 22.61632415 36 58.619-20 54 21.25 L~09vC568 +99942 2C2007 01 22.61878615 36 59.210-20 54 22.97 L~09vC568 +99942 2C2007 01 22.62113415 36 59.808-20 54 24.59 L~09vC568 +99942 2C2007 01 22.62347015 37 00.364-20 54 26.20 L~09vC568 +99942 2C2007 01 22.62593415 37 00.969-20 54 27.89 L~09vC568 +99942 2C2007 01 22.62827215 37 01.551-20 54 29.50 L~09vC568 +99942 2C2007 01 22.63124215 37 02.296-20 54 31.56 L~09vC568 +99942 2C2007 01 22.63360515 37 02.858-20 54 33.24 L~09vC568 +99942 2C2007 01 22.63609015 37 03.468-20 54 34.88 L~09vC568 +99942 2C2007 01 22.63845815 37 04.044-20 54 36.49 L~09vC568 +99942 2C2007 01 22.64095315 37 04.663-20 54 38.24 L~09vC568 +99942 2C2007 01 22.64329615 37 05.241-20 54 39.79 L~09vC568 +99942 2C2007 01 22.64563215 37 05.805-20 54 41.42 L~09vC568 +99942 2C2007 01 22.64797215 37 06.399-20 54 43.05 L~09vC568 +99942 2C2007 01 22.65031215 37 06.975-20 54 44.58 L~09vC568 +99942 2C2007 01 22.65520515 37 08.177-20 54 48.01 L~09vC568 +99942 2C2007 01 22.65766615 37 08.765-20 54 49.68 L~09vC568 +99942 2C2007 01 22.66000615 37 09.346-20 54 51.23 L~09vC568 +99942 2C2007 01 22.66233915 37 09.914-20 54 52.83 L~09vC568 +99942 2C2007 01 24.57992215 45 10.267-21 15 47.20 L~09vC568 +99942 2C2007 01 24.58237315 45 10.845-21 15 48.76 L~09vC568 +99942 2C2007 01 24.58473515 45 11.459-21 15 50.79 L~09vC568 +99942 2C2007 01 24.58708115 45 12.051-21 15 52.00 L~09vC568 +99942 2C2007 01 24.58943115 45 12.639-21 15 53.62 L~09vC568 +99942 2C2007 01 24.59180315 45 13.201-21 15 55.01 L~09vC568 +99942 2C2007 01 24.59415315 45 13.810-21 15 56.62 L~09vC568 +99942 2C2007 01 24.59649815 45 14.398-21 15 58.15 L~09vC568 +99942 2C2007 01 24.59884615 45 14.981-21 15 59.67 L~09vC568 +99942 2C2007 01 24.60130815 45 15.601-21 16 01.20 L~09vC568 +99942 2C2007 01 24.60397015 45 16.258-21 16 02.96 L~09vC568 +99942 2C2007 01 24.60631615 45 16.864-21 16 04.53 L~09vC568 +99942 2C2007 01 24.60865915 45 17.437-21 16 06.03 L~09vC568 +99942 2C2007 01 24.61100715 45 18.015-21 16 07.64 L~09vC568 +99942 2C2007 01 24.61337815 45 18.617-21 16 09.04 L~09vC568 +99942 2C2007 01 24.61572015 45 19.205-21 16 10.60 L~09vC568 +99942 2C2007 01 24.61806315 45 19.787-21 16 12.11 L~09vC568 +99942 2C2007 01 24.62052215 45 20.394-21 16 13.80 L~09vC568 +99942 2C2007 01 24.62288015 45 20.996-21 16 15.28 L~09vC568 +99942 2C2007 01 24.62536915 45 21.610-21 16 16.86 L~09vC568 +99942 2C2007 01 24.62770915 45 22.184-21 16 18.37 L~09vC568 +99942 2C2007 01 24.63004715 45 22.784-21 16 19.89 L~09vC568 +99942 2C2007 01 24.63253115 45 23.400-21 16 21.47 L~09vC568 +99942 2C2007 01 24.63488415 45 23.956-21 16 22.98 L~09vC568 +99942 2C2007 01 24.63722615 45 24.576-21 16 24.46 L~09vC568 +99942 2C2007 01 24.63968615 45 25.180-21 16 26.08 L~09vC568 +99942 2C2007 01 24.64206015 45 25.765-21 16 27.61 L~09vC568 +99942 2C2007 01 24.64453715 45 26.385-21 16 29.24 L~09vC568 +99942 2C2007 01 24.64749315 45 27.120-21 16 31.13 L~09vC568 +99942 2C2007 01 24.64984515 45 27.716-21 16 32.67 L~09vD568 +99942 2C2007 01 24.65218915 45 28.295-21 16 34.14 L~09vD568 +99942 2C2007 01 24.65453715 45 28.875-21 16 35.68 L~09vD568 +99942 2C2007 01 24.65700115 45 29.476-21 16 37.24 L~09vD568 +99942 2C2007 01 24.65933815 45 30.069-21 16 38.76 L~09vD568 +99942 2C2007 01 24.66186915 45 30.702-21 16 40.35 L~09vD568 +99942 2C2007 01 24.66421415 45 31.282-21 16 41.89 L~09vD568 +99942 2C2007 01 24.66673715 45 31.913-21 16 43.52 L~09vD568 +99942 2C2007 01 24.66915915 45 32.521-21 16 45.04 L~09vD568 +99942 2C2007 01 25.57819315 49 22.787-21 26 10.76 L~09vD568 +99942 2C2007 01 25.58054715 49 23.382-21 26 12.24 L~09vD568 +99942 2C2007 01 25.58288715 49 24.005-21 26 13.93 L~09vD568 +99942 2C2007 01 25.58538115 49 24.619-21 26 15.27 L~09vD568 +99942 2C2007 01 25.58871815 49 25.448-21 26 17.35 L~09vD568 +99942 2C2007 01 25.59107515 49 26.056-21 26 18.94 L~09vD568 +99942 2C2007 01 25.59341915 49 26.638-21 26 20.34 L~09vD568 +99942 2C2007 01 25.59578215 49 27.232-21 26 21.81 L~09vD568 +99942 2C2007 01 25.59814815 49 27.836-21 26 23.28 L~09vD568 +99942 2C2007 01 25.60048815 49 28.426-21 26 24.78 L~09vD568 +99942 2C2007 01 25.60298015 49 29.040-21 26 26.32 L~09vD568 +99942 2C2007 01 25.60533815 49 29.635-21 26 27.79 L~09vD568 +99942 2C2007 01 25.60768815 49 30.217-21 26 29.23 L~09vD568 +99942 2C2007 01 25.61044415 49 30.921-21 26 30.98 L~09vD568 +99942 2C2007 01 25.61280315 49 31.515-21 26 32.50 L~09vD568 +99942 2C2007 01 25.61514615 49 32.099-21 26 33.92 L~09vD568 +99942 2C2007 01 25.61763015 49 32.743-21 26 35.57 L~09vD568 +99942 2C2007 01 25.62004115 49 33.333-21 26 37.04 L~09vD568 +99942 2C2007 01 25.62238915 49 33.920-21 26 38.54 L~09vD568 +99942 2C2007 01 25.62486615 49 34.551-21 26 40.09 L~09vD568 +99942 2C2007 01 25.62721115 49 35.141-21 26 41.54 L~09vD568 +99942 2C2007 01 25.62955615 49 35.721-21 26 42.96 L~09vD568 +99942 2C2007 01 25.63218615 49 36.378-21 26 44.65 L~09vD568 +99942 2C2007 01 25.63452915 49 36.980-21 26 46.10 L~09vD568 +99942 2C2007 01 25.63686715 49 37.574-21 26 47.55 L~09vD568 +99942 2C2007 01 25.63935415 49 38.186-21 26 49.11 L~09vD568 +99942 2C2007 01 25.64171915 49 38.758-21 26 50.54 L~09vD568 +99942 2C2007 01 25.64421215 49 39.407-21 26 52.14 L~09vD568 +99942 2C2007 01 25.64655615 49 39.998-21 26 53.60 L~09vD568 +99942 2C2007 01 25.64907615 49 40.623-21 26 54.91 L~09vD568 +99942 2C2007 03 09.65417619 16 36.695-21 11 06.90 L~09vD568 +99942 2C2007 03 09.65641119 16 37.371-21 11 04.96 L~09vD568 +99942 2C2007 12 13.66071314 26 35.206-15 26 51.52 L~09vD568 +99942 2C2008 01 06.63895716 03 51.245-20 51 51.34 L~09vD568 +99942 2C2008 01 06.64603616 03 53.080-20 51 55.60 L~09vD568 +99942 2C2008 01 06.64949016 03 53.986-20 51 57.69 L~09vD568 +99942 2C2008 01 06.65292016 03 54.887-20 51 59.83 L~09vD568 +99942 2C2008 01 06.65654416 03 55.801-20 52 01.94 L~09vD568 +99942 2C2008 01 06.66000516 03 56.765-20 52 04.16 L~09vD568 +99942 2C2008 01 06.66349216 03 57.618-20 52 06.04 L~09vD568 +99942 2C2008 01 07.64179316 08 14.721-21 01 32.09 L~09vD568 +99942 2C2008 01 07.64518616 08 15.608-21 01 33.99 L~09vD568 +99942 2C2008 01 07.65285816 08 17.617-21 01 38.46 L~09vD568 +99942 2C2008 01 07.65670716 08 18.608-21 01 40.57 L~09vD568 +99942 2C2008 01 08.65407416 12 42.234-21 10 54.03 L~09vD568 +99942 2C2008 01 08.65691716 12 42.968-21 10 55.80 L~09vD568 +99942 2C2008 01 08.65923516 12 43.584-21 10 56.95 L~09vD568 +99942 2C2008 01 08.66382416 12 44.803-21 10 59.64 L~09vD568 +99942 2C2008 01 08.66575916 12 45.323-21 11 00.64 L~09vD568 +99942 2C2008 01 09.64923016 17 06.855-21 19 43.21 L~09vD568 +99942 2C2008 01 09.65116616 17 07.315-21 19 44.16 L~09vD568 +99942 2C2008 01 09.65314116 17 07.868-21 19 45.05 L~09vD568 +99942 2C2008 01 09.65508216 17 08.370-21 19 46.22 L~09vD568 +99942 2C2008 01 09.65908916 17 09.415-21 19 48.28 L~09vD568 +99942 2C2008 01 09.66102716 17 09.953-21 19 49.41 L~09vD568 +99942 2C2008 01 09.66312516 17 10.506-21 19 50.39 L~09vD568 +99942 2C2008 01 09.66508816 17 11.010-21 19 51.46 L~09vD568 From 2ded002562a10ee845a9a3dfa771b9a935b8812d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 21:03:33 +0200 Subject: [PATCH 29/46] Remove Tholen et al. (2013) astrometry data file from previous location --- data/tholen13_mpc_formatted.dat | 432 -------------------------------- 1 file changed, 432 deletions(-) delete mode 100644 data/tholen13_mpc_formatted.dat diff --git a/data/tholen13_mpc_formatted.dat b/data/tholen13_mpc_formatted.dat deleted file mode 100644 index 36b71a75..00000000 --- a/data/tholen13_mpc_formatted.dat +++ /dev/null @@ -1,432 +0,0 @@ -99942 'C2004 06 19.17015009 44 29.677+13 18 50.67 L~09vB695 -99942 'C2004 06 19.17486109 44 30.604+13 18 46.81 L~09vB695 -99942 'C2004 06 19.17967609 44 31.507+13 18 42.91 L~09vB695 -99942 'C2004 06 20.15951409 47 41.116+13 05 24.49 L~09vB695 -99942 'C2004 06 20.16431709 47 42.006+13 05 20.50 L~09vB695 -99942 'C2004 06 20.16906309 47 42.926+13 05 16.74 L~09vB695 -99942 'C2005 07 09.17600210 34 38.149+16 12 41.50 L~09vB695 -99942 'C2005 07 09.18080710 34 38.288+16 12 42.68 L~09vB695 -99942 'C2005 07 10.17554310 35 10.909+16 18 25.82 L~09vB695 -99942 'C2005 07 10.17819210 35 10.983+16 18 26.48 L~09vB695 -99942 'C2005 07 11.16972710 35 36.698+16 24 46.68 L~09vB695 -99942 2C2005 09 04.63519408 25 00.085+22 18 13.02 L~09vB568 -99942 2C2005 09 04.63627008 25 00.075+22 18 12.36 L~09vB568 -99942 2C2005 12 31.64597612 46 28.407-11 49 33.02 L~09vB568 -99942 2C2005 12 31.64713112 46 28.583-11 49 34.23 L~09vB568 -99942 2C2005 12 31.64800212 46 28.708-11 49 35.16 L~09vB568 -99942 2C2006 03 05.54636616 20 49.786-26 34 29.32 L~09vB568 -99942 2C2006 03 05.61052316 21 07.957-26 34 51.45 L~09vB568 -99942 2C2006 03 05.65266816 21 19.828-26 35 04.75 L~09vB568 -99942 2C2006 03 06.51985316 25 39.350-26 39 07.23 L~09vB568 -99942 2C2006 03 06.52154416 25 39.838-26 39 07.85 L~09vB568 -99942 2C2006 03 06.52319016 25 40.319-26 39 08.38 L~09vB568 -99942 2C2006 03 06.52483716 25 40.802-26 39 08.75 L~09vB568 -99942 2C2006 03 06.52649816 25 41.288-26 39 09.42 L~09vB568 -99942 2C2006 03 06.53152916 25 42.744-26 39 11.09 L~09vB568 -99942 2C2006 03 06.53317516 25 43.230-26 39 11.64 L~09vB568 -99942 2C2006 03 06.53785116 25 44.576-26 39 13.17 L~09vB568 -99942 2C2006 03 06.53950516 25 45.058-26 39 13.71 L~09vB568 -99942 2C2006 03 06.54114016 25 45.528-26 39 14.25 L~09vB568 -99942 2C2006 03 06.54279516 25 46.018-26 39 14.75 L~09vB568 -99942 2C2006 03 06.54460416 25 46.542-26 39 15.35 L~09vB568 -99942 2C2006 03 06.54622816 25 47.020-26 39 15.82 L~09vB568 -99942 2C2006 03 06.54788716 25 47.487-26 39 16.37 L~09vB568 -99942 2C2006 03 06.54963916 25 48.001-26 39 16.97 L~09vB568 -99942 2C2006 03 06.55128516 25 48.473-26 39 17.49 L~09vB568 -99942 2C2006 03 06.55294416 25 48.954-26 39 18.02 L~09vB568 -99942 2C2006 03 06.58062516 25 56.956-26 39 26.69 L~09vB568 -99942 2C2006 03 06.58226716 25 57.429-26 39 27.19 L~09vB568 -99942 2C2006 03 06.58390316 25 57.889-26 39 27.56 L~09vB568 -99942 2C2006 03 06.58565516 25 58.403-26 39 28.25 L~09vB568 -99942 2C2006 03 06.58729516 25 58.884-26 39 28.74 L~09vB568 -99942 2C2006 03 06.58894616 25 59.356-26 39 29.24 L~09vB568 -99942 2C2006 03 06.59071316 25 59.860-26 39 29.79 L~09vB568 -99942 2C2006 03 06.59240616 26 00.342-26 39 30.29 L~09vB568 -99942 2C2006 03 06.59416916 26 00.854-26 39 30.79 L~09vB568 -99942 2C2006 03 06.59581316 26 01.332-26 39 31.30 L~09vB568 -99942 2C2006 03 06.59986316 26 02.494-26 39 32.45 L~09vB568 -99942 2C2006 03 06.60160616 26 02.993-26 39 33.01 L~09vB568 -99942 2C2006 03 06.60323516 26 03.457-26 39 33.48 L~09vB568 -99942 2C2006 03 06.60488216 26 03.930-26 39 34.00 L~09vB568 -99942 2C2006 03 06.60655416 26 04.414-26 39 34.45 L~09vB568 -99942 2C2006 03 06.60819916 26 04.891-26 39 34.94 L~09vB568 -99942 2C2006 03 06.60994916 26 05.388-26 39 35.44 L~09vB568 -99942 2C2006 03 06.61161916 26 05.870-26 39 35.93 L~09vB568 -99942 2C2006 03 06.61340316 26 06.381-26 39 36.46 L~09vB568 -99942 2C2006 03 06.61522116 26 06.900-26 39 36.96 L~09vB568 -99942 2C2006 03 06.61779416 26 07.648-26 39 37.74 L~09vB568 -99942 2C2006 03 06.61944816 26 08.129-26 39 38.22 L~09vB568 -99942 2C2006 03 06.62108316 26 08.593-26 39 38.68 L~09vB568 -99942 2C2006 03 06.62287816 26 09.105-26 39 39.17 L~09vB568 -99942 2C2006 03 06.62453816 26 09.584-26 39 39.65 L~09vB568 -99942 2C2006 03 06.62634316 26 10.112-26 39 40.15 L~09vB568 -99942 2C2006 03 06.62962316 26 11.039-26 39 41.09 L~09vB568 -99942 2C2006 03 06.63137516 26 11.530-26 39 41.57 L~09vB568 -99942 2C2006 03 06.63303116 26 12.016-26 39 42.05 L~09vB568 -99942 2C2006 03 06.63501716 26 12.589-26 39 42.58 L~09vB568 -99942 2C2006 03 06.63831016 26 13.532-26 39 43.51 L~09vB568 -99942 2C2006 03 06.63998416 26 14.033-26 39 43.93 L~09vB568 -99942 2C2006 03 06.64177816 26 14.532-26 39 44.44 L~09vB568 -99942 2C2006 03 06.64342816 26 15.007-26 39 44.91 L~09vB568 -99942 2C2006 03 06.64522616 26 15.513-26 39 45.40 L~09vB568 -99942 2C2006 03 06.64689116 26 16.000-26 39 45.85 L~09vB568 -99942 2C2006 03 06.64869616 26 16.534-26 39 46.31 L~09vB568 -99942 2C2006 03 06.65033416 26 16.985-26 39 46.76 L~09vB568 -99942 2C2006 03 08.52450916 35 51.633-26 46 44.58 L~09vB568 -99942 2C2006 03 08.52614416 35 52.139-26 46 45.02 L~09vB568 -99942 2C2006 03 08.52778416 35 52.632-26 46 45.44 L~09vB568 -99942 2C2006 03 08.52940616 35 53.122-26 46 45.81 L~09vB568 -99942 2C2006 03 08.53118916 35 53.668-26 46 46.23 L~09vB568 -99942 2C2006 03 08.53282516 35 54.145-26 46 46.74 L~09vB568 -99942 2C2006 03 08.53446116 35 54.645-26 46 47.05 L~09vB568 -99942 2C2006 03 08.53622516 35 55.161-26 46 47.51 L~09vB568 -99942 2C2006 03 08.53952316 35 56.166-26 46 48.34 L~09vB568 -99942 2C2006 03 08.54821816 35 58.785-26 46 50.43 L~09vB568 -99942 2C2006 03 08.54987016 35 59.291-26 46 50.85 L~09vB568 -99942 2C2006 03 08.55150916 35 59.779-26 46 51.19 L~09vB568 -99942 2C2006 03 08.55327516 36 00.314-26 46 51.64 L~09vB568 -99942 2C2006 03 08.55494116 36 00.797-26 46 52.06 L~09vB568 -99942 2C2006 03 08.55657116 36 01.305-26 46 52.45 L~09vB568 -99942 2C2006 03 08.55820316 36 01.809-26 46 52.76 L~09vB568 -99942 2C2006 03 08.55999116 36 02.337-26 46 53.31 L~09vB568 -99942 2C2006 03 08.56165316 36 02.824-26 46 53.65 L~09vB568 -99942 2C2006 03 08.56331116 36 03.321-26 46 54.00 L~09vB568 -99942 2C2006 03 08.56529216 36 03.925-26 46 54.53 L~09vB568 -99942 2C2006 03 08.56705816 36 04.447-26 46 54.94 L~09vB568 -99942 2C2006 03 08.56870116 36 04.934-26 46 55.29 L~09vB568 -99942 2C2006 03 08.57034116 36 05.423-26 46 55.67 L~09vB568 -99942 2C2006 03 08.57210416 36 05.964-26 46 56.10 L~09vB568 -99942 2C2006 03 08.57374816 36 06.447-26 46 56.43 L~09vB568 -99942 2C2006 03 08.57878216 36 07.950-26 46 57.62 L~09vB568 -99942 2C2006 03 08.58043616 36 08.453-26 46 57.97 L~09vB568 -99942 2C2006 03 08.59506416 36 12.824-26 47 01.24 L~09vB568 -99942 2C2006 03 08.59679916 36 13.342-26 47 01.59 L~09vB568 -99942 2C2006 03 08.59842816 36 13.834-26 47 01.97 L~09vB568 -99942 2C2006 03 08.60007616 36 14.327-26 47 02.20 L~09vB568 -99942 2C2006 03 08.60176516 36 14.819-26 47 02.62 L~09vB568 -99942 2C2006 03 08.60342016 36 15.335-26 47 03.00 L~09vB568 -99942 2C2006 03 08.60506016 36 15.804-26 47 03.30 L~09vB568 -99942 2C2006 03 08.60672516 36 16.308-26 47 03.66 L~09vB568 -99942 2C2006 03 08.60840016 36 16.812-26 47 04.07 L~09vB568 -99942 2C2006 03 08.61019116 36 17.347-26 47 04.43 L~09vB568 -99942 2C2006 03 08.61180216 36 17.821-26 47 04.73 L~09vB568 -99942 2C2006 03 08.61356016 36 18.338-26 47 05.15 L~09vB568 -99942 2C2006 03 08.61522616 36 18.848-26 47 05.46 L~09vB568 -99942 2C2006 03 08.61702416 36 19.384-26 47 05.80 L~09vB568 -99942 2C2006 03 08.61880916 36 19.911-26 47 06.18 L~09vB568 -99942 2C2006 03 08.62044116 36 20.397-26 47 06.50 L~09vB568 -99942 2C2006 03 08.62209616 36 20.893-26 47 06.83 L~09vB568 -99942 2C2006 03 08.62373616 36 21.391-26 47 07.18 L~09vB568 -99942 2C2006 03 08.62551916 36 21.915-26 47 07.56 L~09vB568 -99942 2C2006 03 08.62716816 36 22.403-26 47 07.90 L~09vB568 -99942 2C2006 03 08.62914916 36 23.003-26 47 08.29 L~09vB568 -99942 2C2006 03 08.63083816 36 23.503-26 47 08.58 L~09vB568 -99942 2C2006 03 08.63248116 36 23.992-26 47 08.94 L~09vB568 -99942 2C2006 03 08.63410316 36 24.477-26 47 09.24 L~09vB568 -99942 2C2006 03 08.63588516 36 24.997-26 47 09.59 L~09vB568 -99942 2C2006 03 08.63752916 36 25.500-26 47 09.91 L~09vB568 -99942 2C2006 03 08.63917116 36 25.991-26 47 10.23 L~09vB568 -99942 2C2006 03 08.64083116 36 26.480-26 47 10.54 L~09vB568 -99942 2C2006 03 08.64263816 36 27.008-26 47 10.89 L~09vB568 -99942 2C2006 03 08.64430016 36 27.506-26 47 11.22 L~09vB568 -99942 2C2006 03 08.64589016 36 27.988-26 47 11.49 L~09vB568 -99942 2C2006 03 08.64751516 36 28.476-26 47 11.82 L~09vB568 -99942 2C2006 03 08.64930316 36 29.008-26 47 12.13 L~09vB568 -99942 2C2006 03 08.65095316 36 29.492-26 47 12.45 L~09vB568 -99942 2C2006 03 08.66103116 36 32.496-26 47 14.31 L~09vB568 -99942 2C2006 05 01.62736922 43 36.580-01 20 46.01 L~09vB568 -99942 2C2006 05 01.62821822 43 36.869-01 20 44.02 L~09vB568 -99942 2C2006 06 01.60681201 12 41.522+14 14 31.91 L~09vB568 -99942 2C2006 06 01.60868801 12 41.959+14 14 34.24 L~09vB568 -99942 2C2006 06 02.59935901 16 48.755+14 34 20.07 L~09vB568 -99942 2C2006 06 02.60078001 16 49.108+14 34 21.72 L~09vB568 -99942 2C2006 06 02.60224201 16 49.478+14 34 23.59 L~09vB568 -99942 2C2006 07 27.61254105 06 37.958+23 53 27.72 L~09vB568 -99942 2C2006 07 27.61447305 06 38.465+23 53 27.83 L~09vB568 -99942 2C2006 08 15.61852106 26 52.404+22 57 47.52 L~09vB568 -99942 2C2006 08 15.62233206 26 53.348+22 57 46.02 L~09vB568 -99942 2C2006 08 16.62183606 31 00.059+22 51 14.54 L~09vB568 -99942 2C2006 08 16.62441906 31 00.629+22 51 13.69 L~09vB568 -99942 2C2006 08 16.62695406 31 01.254+22 51 12.76 L~09vB568 -99942 2C2006 09 04.59915907 45 57.632+19 48 13.43 L~09vB568 -99942 2C2006 09 04.60174207 45 58.282+19 48 11.30 L~09vB568 -99942 2C2006 09 04.60702707 45 59.441+19 48 07.57 L~09vB568 -99942 2C2006 09 04.60960407 46 00.032+19 48 05.65 L~09vB568 -99942 2C2006 09 04.61217807 46 00.596+19 48 03.81 L~09vC568 -99942 2C2006 09 04.61475007 46 01.189+19 48 01.98 L~09vC568 -99942 2C2006 09 04.61733207 46 01.771+19 48 00.12 L~09vC568 -99942 2C2006 09 04.61991607 46 02.330+19 47 58.33 L~09vC568 -99942 2C2006 09 04.62259307 46 02.963+19 47 56.27 L~09vC568 -99942 2C2006 09 04.62517107 46 03.533+19 47 54.35 L~09vC568 -99942 2C2006 09 04.62774407 46 04.120+19 47 52.46 L~09vC568 -99942 2C2006 10 25.59993210 38 53.805+05 37 27.51 L~09vC568 -99942 2C2006 10 25.60369210 38 54.499+05 37 23.28 L~09vC568 -99942 2C2006 10 25.60744010 38 55.203+05 37 18.89 L~09vC568 -99942 2C2006 10 25.61132210 38 55.912+05 37 14.36 L~09vC568 -99942 2C2006 10 25.61506310 38 56.601+05 37 10.09 L~09vC568 -99942 2C2006 10 25.61879910 38 57.275+05 37 05.78 L~09vC568 -99942 2C2006 10 25.62267810 38 58.014+05 37 01.23 L~09vC568 -99942 2C2006 10 25.62640510 38 58.696+05 36 56.87 L~09vC568 -99942 2C2006 10 25.63014810 38 59.377+05 36 52.66 L~09vC568 -99942 2C2006 10 25.63403010 39 00.098+05 36 48.23 L~09vC568 -99942 2C2006 10 25.63779510 39 00.816+05 36 43.85 L~09vC568 -99942 2C2006 11 28.59593412 23 24.533-05 33 25.55 L~09vC568 -99942 2C2006 11 28.59911212 23 25.116-05 33 29.23 L~09vC568 -99942 2C2006 11 28.60196112 23 25.630-05 33 32.60 L~09vC568 -99942 2C2006 11 28.60444112 23 26.110-05 33 35.60 L~09vC568 -99942 2C2006 11 28.60694712 23 26.572-05 33 38.57 L~09vC568 -99942 2C2006 11 28.60930612 23 27.008-05 33 41.28 L~09vC568 -99942 2C2006 11 28.61175812 23 27.455-05 33 44.13 L~09vC568 -99942 2C2006 11 28.61410412 23 27.900-05 33 47.02 L~09vC568 -99942 2C2006 11 28.61644012 23 28.333-05 33 49.76 L~09vC568 -99942 2C2006 11 28.61881912 23 28.750-05 33 52.52 L~09vC568 -99942 2C2006 11 28.62122512 23 29.200-05 33 55.26 L~09vC568 -99942 2C2006 11 28.62509412 23 29.918-05 33 59.86 L~09vC568 -99942 2C2006 11 28.62744612 23 30.356-05 34 02.67 L~09vC568 -99942 2C2006 11 28.62980412 23 30.783-05 34 05.39 L~09vC568 -99942 2C2006 11 28.63229412 23 31.243-05 34 08.35 L~09vC568 -99942 2C2006 11 28.63463812 23 31.694-05 34 11.18 L~09vC568 -99942 2C2006 11 28.63699212 23 32.122-05 34 13.96 L~09vC568 -99942 2C2006 11 28.63939612 23 32.559-05 34 16.72 L~09vC568 -99942 2C2006 11 28.64191212 23 33.023-05 34 19.79 L~09vC568 -99942 2C2006 11 28.64780312 23 34.102-05 34 26.64 L~09vC568 -99942 2C2006 12 25.61583813 51 22.763-13 59 56.70 L~09vC568 -99942 2C2006 12 25.61784113 51 23.174-13 59 58.77 L~09vC568 -99942 2C2006 12 25.61998413 51 23.614-14 00 01.00 L~09vC568 -99942 2C2006 12 25.62212713 51 24.048-14 00 03.19 L~09vC568 -99942 2C2006 12 25.62426613 51 24.483-14 00 05.46 L~09vC568 -99942 2C2006 12 25.62626013 51 24.897-14 00 07.57 L~09vC568 -99942 2C2006 12 25.62826013 51 25.303-14 00 09.63 L~09vC568 -99942 2C2006 12 25.63026913 51 25.727-14 00 11.91 L~09vC568 -99942 2C2006 12 25.63226613 51 26.111-14 00 13.98 L~09vC568 -99942 2C2006 12 25.63432513 51 26.550-14 00 16.10 L~09vC568 -99942 2C2006 12 25.63633713 51 26.944-14 00 18.32 L~09vC568 -99942 2C2006 12 25.63845413 51 27.397-14 00 20.54 L~09vC568 -99942 2C2006 12 25.64046913 51 27.795-14 00 22.50 L~09vC568 -99942 2C2006 12 25.64260413 51 28.243-14 00 24.79 L~09vC568 -99942 2C2006 12 25.64459413 51 28.632-14 00 26.91 L~09vC568 -99942 2C2006 12 25.64658913 51 29.049-14 00 28.99 L~09vC568 -99942 2C2006 12 25.64859613 51 29.453-14 00 31.11 L~09vC568 -99942 2C2006 12 25.65072813 51 29.887-14 00 33.30 L~09vC568 -99942 2C2006 12 25.65277913 51 30.308-14 00 35.48 L~09vC568 -99942 2C2006 12 25.65477513 51 30.727-14 00 37.66 L~09vC568 -99942 2C2006 12 26.61927413 54 51.077-14 17 22.37 L~09vC568 -99942 2C2006 12 26.62186713 54 51.617-14 17 25.10 L~09vC568 -99942 2C2006 12 26.62443413 54 52.140-14 17 27.76 L~09vC568 -99942 2C2006 12 26.62701613 54 52.676-14 17 30.47 L~09vC568 -99942 2C2006 12 26.62959313 54 53.203-14 17 33.18 L~09vC568 -99942 2C2006 12 26.63231513 54 53.784-14 17 36.02 L~09vC568 -99942 2C2006 12 26.63489013 54 54.277-14 17 38.64 L~09vC568 -99942 2C2006 12 26.63746513 54 54.814-14 17 41.38 L~09vC568 -99942 2C2006 12 26.64003713 54 55.344-14 17 44.03 L~09vC568 -99942 2C2006 12 26.64443813 54 56.257-14 17 48.70 L~09vC568 -99942 2C2006 12 26.64702413 54 56.800-14 17 51.38 L~09vC568 -99942 2C2006 12 26.64960613 54 57.317-14 17 54.00 L~09vC568 -99942 2C2006 12 26.65233913 54 57.885-14 17 56.94 L~09vC568 -99942 2C2006 12 26.65491313 54 58.410-14 17 59.59 L~09vC568 -99942 2C2006 12 26.65764213 54 58.975-14 18 02.42 L~09vC568 -99942 2C2006 12 26.66021313 54 59.492-14 18 05.09 L~09vC568 -99942 2C2006 12 26.66295113 55 00.066-14 18 08.04 L~09vC568 -99942 2C2006 12 27.61377913 58 18.687-14 34 30.21 L~09vC568 -99942 2C2006 12 27.61612413 58 19.180-14 34 32.59 L~09vC568 -99942 2C2006 12 27.61846613 58 19.669-14 34 35.08 L~09vC568 -99942 2C2006 12 27.62092113 58 20.171-14 34 37.59 L~09vC568 -99942 2C2006 12 27.62343213 58 20.692-14 34 40.16 L~09vC568 -99942 2C2006 12 27.62813013 58 21.676-14 34 45.11 L~09vC568 -99942 2C2006 12 27.63047513 58 22.157-14 34 47.55 L~09vC568 -99942 2C2006 12 27.63283013 58 22.638-14 34 49.94 L~09vC568 -99942 2C2006 12 27.63536613 58 23.164-14 34 52.56 L~09vC568 -99942 2C2006 12 27.63772213 58 23.654-14 34 55.02 L~09vC568 -99942 2C2006 12 27.64018213 58 24.160-14 34 57.58 L~09vC568 -99942 2C2006 12 27.64251713 58 24.633-14 34 59.93 L~09vC568 -99942 2C2006 12 27.64486213 58 25.128-14 35 02.41 L~09vC568 -99942 2C2006 12 27.64733813 58 25.643-14 35 05.02 L~09vC568 -99942 2C2006 12 27.64968213 58 26.118-14 35 07.34 L~09vC568 -99942 2C2006 12 27.65219913 58 26.645-14 35 10.02 L~09vC568 -99942 2C2006 12 27.65454513 58 27.136-14 35 12.46 L~09vC568 -99942 2C2006 12 27.65693913 58 27.617-14 35 14.94 L~09vC568 -99942 2C2006 12 27.65923513 58 28.080-14 35 17.27 L~09vC568 -99942 2C2006 12 27.66161613 58 28.593-14 35 19.73 L~09vC568 -99942 2C2006 12 28.59892614 01 45.532-14 51 20.18 L~09vC568 -99942 2C2006 12 28.60127214 01 45.990-14 51 22.22 L~09vC568 -99942 2C2006 12 28.60361214 01 46.474-14 51 24.86 L~09vC568 -99942 2C2006 12 28.60595614 01 46.965-14 51 27.09 L~09vC568 -99942 2C2006 12 28.60834814 01 47.466-14 51 29.59 L~09vC568 -99942 2C2006 12 28.61068214 01 47.954-14 51 31.93 L~09vC568 -99942 2C2006 12 28.61313714 01 48.465-14 51 34.53 L~09vC568 -99942 2C2006 12 28.61548314 01 48.954-14 51 36.90 L~09vC568 -99942 2C2006 12 28.61782414 01 49.441-14 51 39.29 L~09vC568 -99942 2C2006 12 28.62048314 01 49.989-14 51 42.06 L~09vC568 -99942 2C2006 12 28.62284414 01 50.480-14 51 44.43 L~09vC568 -99942 2C2006 12 28.62521914 01 50.990-14 51 46.97 L~09vC568 -99942 2C2006 12 28.62755814 01 51.480-14 51 49.37 L~09vC568 -99942 2C2006 12 28.62989814 01 51.941-14 51 51.72 L~09vC568 -99942 2C2006 12 28.63223614 01 52.447-14 51 54.12 L~09vC568 -99942 2C2006 12 28.63472114 01 52.958-14 51 56.69 L~09vC568 -99942 2C2006 12 28.63709614 01 53.453-14 51 59.27 L~09vC568 -99942 2C2006 12 28.63958114 01 53.965-14 52 01.62 L~09vC568 -99942 2C2006 12 28.64222114 01 54.514-14 52 04.38 L~09vC568 -99942 2C2006 12 28.64470914 01 55.039-14 52 06.96 L~09vC568 -99942 2C2006 12 28.64705014 01 55.531-14 52 09.35 L~09vC568 -99942 2C2006 12 28.64938714 01 55.996-14 52 11.67 L~09vC568 -99942 2C2006 12 28.65175514 01 56.494-14 52 14.11 L~09vC568 -99942 2C2006 12 28.65410114 01 57.003-14 52 16.60 L~09vC568 -99942 2C2006 12 28.65644714 01 57.472-14 52 18.98 L~09vC568 -99942 2C2006 12 28.65879714 01 57.960-14 52 21.42 L~09vC568 -99942 2C2007 01 21.58245615 32 42.616-20 42 32.51 L~09vC568 -99942 2C2007 01 21.58477315 32 43.182-20 42 34.17 L~09vC568 -99942 2C2007 01 21.58711715 32 43.754-20 42 35.81 L~09vC568 -99942 2C2007 01 21.58959315 32 44.371-20 42 37.63 L~09vC568 -99942 2C2007 01 21.59195815 32 44.938-20 42 39.26 L~09vC568 -99942 2C2007 01 21.59430315 32 45.499-20 42 40.83 L~09vC568 -99942 2C2007 01 21.59664515 32 46.078-20 42 42.56 L~09vC568 -99942 2C2007 01 21.59911315 32 46.703-20 42 44.34 L~09vC568 -99942 2C2007 01 21.60382415 32 47.848-20 42 47.67 L~09vC568 -99942 2C2007 01 21.60630415 32 48.443-20 42 49.39 L~09vC568 -99942 2C2007 01 21.60865515 32 49.033-20 42 51.06 L~09vC568 -99942 2C2007 01 21.61111115 32 49.620-20 42 52.79 L~09vC568 -99942 2C2007 01 21.61348815 32 50.198-20 42 54.45 L~09vC568 -99942 2C2007 01 21.61596315 32 50.816-20 42 56.26 L~09vC568 -99942 2C2007 01 21.61830115 32 51.395-20 42 57.88 L~09vC568 -99942 2C2007 01 21.62065315 32 51.961-20 42 59.57 L~09vC568 -99942 2C2007 01 21.62537515 32 53.108-20 43 02.86 L~09vC568 -99942 2C2007 01 21.63384715 32 55.168-20 43 08.85 L~09vC568 -99942 2C2007 01 21.63855815 32 56.312-20 43 12.14 L~09vC568 -99942 2C2007 01 21.64091415 32 56.911-20 43 13.89 L~09vC568 -99942 2C2007 01 21.64325715 32 57.478-20 43 15.48 L~09vC568 -99942 2C2007 01 21.65294215 32 59.821-20 43 22.32 L~09vC568 -99942 2C2007 01 21.65549215 33 00.470-20 43 24.16 L~09vC568 -99942 2C2007 01 21.65785015 33 01.030-20 43 25.75 L~09vC568 -99942 2C2007 01 21.66020015 33 01.605-20 43 27.43 L~09vC568 -99942 2C2007 01 21.66256215 33 02.171-20 43 29.04 L~09vC568 -99942 2C2007 01 21.66506015 33 02.793-20 43 30.82 L~09vC568 -99942 2C2007 01 21.66740615 33 03.361-20 43 32.52 L~09vC568 -99942 2C2007 01 21.66975715 33 03.947-20 43 34.16 L~09vC568 -99942 2C2007 01 22.57214015 36 47.728-20 53 51.02 L~09vC568 -99942 2C2007 01 22.57654615 36 48.815-20 53 53.82 L~09vC568 -99942 2C2007 01 22.58476015 36 50.845-20 53 59.54 L~09vC568 -99942 2C2007 01 22.58756915 36 51.544-20 54 01.48 L~09vC568 -99942 2C2007 01 22.59237415 36 52.723-20 54 04.90 L~09vC568 -99942 2C2007 01 22.59473715 36 53.296-20 54 06.42 L~09vC568 -99942 2C2007 01 22.59708115 36 53.865-20 54 07.99 L~09vC568 -99942 2C2007 01 22.59954915 36 54.479-20 54 09.82 L~09vC568 -99942 2C2007 01 22.60189015 36 55.064-20 54 11.36 L~09vC568 -99942 2C2007 01 22.60423615 36 55.637-20 54 12.96 L~09vC568 -99942 2C2007 01 22.60669315 36 56.236-20 54 14.69 L~09vC568 -99942 2C2007 01 22.60915215 36 56.845-20 54 16.36 L~09vC568 -99942 2C2007 01 22.61163715 36 57.473-20 54 18.12 L~09vC568 -99942 2C2007 01 22.61397715 36 58.034-20 54 19.83 L~09vC568 -99942 2C2007 01 22.61632415 36 58.619-20 54 21.25 L~09vC568 -99942 2C2007 01 22.61878615 36 59.210-20 54 22.97 L~09vC568 -99942 2C2007 01 22.62113415 36 59.808-20 54 24.59 L~09vC568 -99942 2C2007 01 22.62347015 37 00.364-20 54 26.20 L~09vC568 -99942 2C2007 01 22.62593415 37 00.969-20 54 27.89 L~09vC568 -99942 2C2007 01 22.62827215 37 01.551-20 54 29.50 L~09vC568 -99942 2C2007 01 22.63124215 37 02.296-20 54 31.56 L~09vC568 -99942 2C2007 01 22.63360515 37 02.858-20 54 33.24 L~09vC568 -99942 2C2007 01 22.63609015 37 03.468-20 54 34.88 L~09vC568 -99942 2C2007 01 22.63845815 37 04.044-20 54 36.49 L~09vC568 -99942 2C2007 01 22.64095315 37 04.663-20 54 38.24 L~09vC568 -99942 2C2007 01 22.64329615 37 05.241-20 54 39.79 L~09vC568 -99942 2C2007 01 22.64563215 37 05.805-20 54 41.42 L~09vC568 -99942 2C2007 01 22.64797215 37 06.399-20 54 43.05 L~09vC568 -99942 2C2007 01 22.65031215 37 06.975-20 54 44.58 L~09vC568 -99942 2C2007 01 22.65520515 37 08.177-20 54 48.01 L~09vC568 -99942 2C2007 01 22.65766615 37 08.765-20 54 49.68 L~09vC568 -99942 2C2007 01 22.66000615 37 09.346-20 54 51.23 L~09vC568 -99942 2C2007 01 22.66233915 37 09.914-20 54 52.83 L~09vC568 -99942 2C2007 01 24.57992215 45 10.267-21 15 47.20 L~09vC568 -99942 2C2007 01 24.58237315 45 10.845-21 15 48.76 L~09vC568 -99942 2C2007 01 24.58473515 45 11.459-21 15 50.79 L~09vC568 -99942 2C2007 01 24.58708115 45 12.051-21 15 52.00 L~09vC568 -99942 2C2007 01 24.58943115 45 12.639-21 15 53.62 L~09vC568 -99942 2C2007 01 24.59180315 45 13.201-21 15 55.01 L~09vC568 -99942 2C2007 01 24.59415315 45 13.810-21 15 56.62 L~09vC568 -99942 2C2007 01 24.59649815 45 14.398-21 15 58.15 L~09vC568 -99942 2C2007 01 24.59884615 45 14.981-21 15 59.67 L~09vC568 -99942 2C2007 01 24.60130815 45 15.601-21 16 01.20 L~09vC568 -99942 2C2007 01 24.60397015 45 16.258-21 16 02.96 L~09vC568 -99942 2C2007 01 24.60631615 45 16.864-21 16 04.53 L~09vC568 -99942 2C2007 01 24.60865915 45 17.437-21 16 06.03 L~09vC568 -99942 2C2007 01 24.61100715 45 18.015-21 16 07.64 L~09vC568 -99942 2C2007 01 24.61337815 45 18.617-21 16 09.04 L~09vC568 -99942 2C2007 01 24.61572015 45 19.205-21 16 10.60 L~09vC568 -99942 2C2007 01 24.61806315 45 19.787-21 16 12.11 L~09vC568 -99942 2C2007 01 24.62052215 45 20.394-21 16 13.80 L~09vC568 -99942 2C2007 01 24.62288015 45 20.996-21 16 15.28 L~09vC568 -99942 2C2007 01 24.62536915 45 21.610-21 16 16.86 L~09vC568 -99942 2C2007 01 24.62770915 45 22.184-21 16 18.37 L~09vC568 -99942 2C2007 01 24.63004715 45 22.784-21 16 19.89 L~09vC568 -99942 2C2007 01 24.63253115 45 23.400-21 16 21.47 L~09vC568 -99942 2C2007 01 24.63488415 45 23.956-21 16 22.98 L~09vC568 -99942 2C2007 01 24.63722615 45 24.576-21 16 24.46 L~09vC568 -99942 2C2007 01 24.63968615 45 25.180-21 16 26.08 L~09vC568 -99942 2C2007 01 24.64206015 45 25.765-21 16 27.61 L~09vC568 -99942 2C2007 01 24.64453715 45 26.385-21 16 29.24 L~09vC568 -99942 2C2007 01 24.64749315 45 27.120-21 16 31.13 L~09vC568 -99942 2C2007 01 24.64984515 45 27.716-21 16 32.67 L~09vD568 -99942 2C2007 01 24.65218915 45 28.295-21 16 34.14 L~09vD568 -99942 2C2007 01 24.65453715 45 28.875-21 16 35.68 L~09vD568 -99942 2C2007 01 24.65700115 45 29.476-21 16 37.24 L~09vD568 -99942 2C2007 01 24.65933815 45 30.069-21 16 38.76 L~09vD568 -99942 2C2007 01 24.66186915 45 30.702-21 16 40.35 L~09vD568 -99942 2C2007 01 24.66421415 45 31.282-21 16 41.89 L~09vD568 -99942 2C2007 01 24.66673715 45 31.913-21 16 43.52 L~09vD568 -99942 2C2007 01 24.66915915 45 32.521-21 16 45.04 L~09vD568 -99942 2C2007 01 25.57819315 49 22.787-21 26 10.76 L~09vD568 -99942 2C2007 01 25.58054715 49 23.382-21 26 12.24 L~09vD568 -99942 2C2007 01 25.58288715 49 24.005-21 26 13.93 L~09vD568 -99942 2C2007 01 25.58538115 49 24.619-21 26 15.27 L~09vD568 -99942 2C2007 01 25.58871815 49 25.448-21 26 17.35 L~09vD568 -99942 2C2007 01 25.59107515 49 26.056-21 26 18.94 L~09vD568 -99942 2C2007 01 25.59341915 49 26.638-21 26 20.34 L~09vD568 -99942 2C2007 01 25.59578215 49 27.232-21 26 21.81 L~09vD568 -99942 2C2007 01 25.59814815 49 27.836-21 26 23.28 L~09vD568 -99942 2C2007 01 25.60048815 49 28.426-21 26 24.78 L~09vD568 -99942 2C2007 01 25.60298015 49 29.040-21 26 26.32 L~09vD568 -99942 2C2007 01 25.60533815 49 29.635-21 26 27.79 L~09vD568 -99942 2C2007 01 25.60768815 49 30.217-21 26 29.23 L~09vD568 -99942 2C2007 01 25.61044415 49 30.921-21 26 30.98 L~09vD568 -99942 2C2007 01 25.61280315 49 31.515-21 26 32.50 L~09vD568 -99942 2C2007 01 25.61514615 49 32.099-21 26 33.92 L~09vD568 -99942 2C2007 01 25.61763015 49 32.743-21 26 35.57 L~09vD568 -99942 2C2007 01 25.62004115 49 33.333-21 26 37.04 L~09vD568 -99942 2C2007 01 25.62238915 49 33.920-21 26 38.54 L~09vD568 -99942 2C2007 01 25.62486615 49 34.551-21 26 40.09 L~09vD568 -99942 2C2007 01 25.62721115 49 35.141-21 26 41.54 L~09vD568 -99942 2C2007 01 25.62955615 49 35.721-21 26 42.96 L~09vD568 -99942 2C2007 01 25.63218615 49 36.378-21 26 44.65 L~09vD568 -99942 2C2007 01 25.63452915 49 36.980-21 26 46.10 L~09vD568 -99942 2C2007 01 25.63686715 49 37.574-21 26 47.55 L~09vD568 -99942 2C2007 01 25.63935415 49 38.186-21 26 49.11 L~09vD568 -99942 2C2007 01 25.64171915 49 38.758-21 26 50.54 L~09vD568 -99942 2C2007 01 25.64421215 49 39.407-21 26 52.14 L~09vD568 -99942 2C2007 01 25.64655615 49 39.998-21 26 53.60 L~09vD568 -99942 2C2007 01 25.64907615 49 40.623-21 26 54.91 L~09vD568 -99942 2C2007 03 09.65417619 16 36.695-21 11 06.90 L~09vD568 -99942 2C2007 03 09.65641119 16 37.371-21 11 04.96 L~09vD568 -99942 2C2007 12 13.66071314 26 35.206-15 26 51.52 L~09vD568 -99942 2C2008 01 06.63895716 03 51.245-20 51 51.34 L~09vD568 -99942 2C2008 01 06.64603616 03 53.080-20 51 55.60 L~09vD568 -99942 2C2008 01 06.64949016 03 53.986-20 51 57.69 L~09vD568 -99942 2C2008 01 06.65292016 03 54.887-20 51 59.83 L~09vD568 -99942 2C2008 01 06.65654416 03 55.801-20 52 01.94 L~09vD568 -99942 2C2008 01 06.66000516 03 56.765-20 52 04.16 L~09vD568 -99942 2C2008 01 06.66349216 03 57.618-20 52 06.04 L~09vD568 -99942 2C2008 01 07.64179316 08 14.721-21 01 32.09 L~09vD568 -99942 2C2008 01 07.64518616 08 15.608-21 01 33.99 L~09vD568 -99942 2C2008 01 07.65285816 08 17.617-21 01 38.46 L~09vD568 -99942 2C2008 01 07.65670716 08 18.608-21 01 40.57 L~09vD568 -99942 2C2008 01 08.65407416 12 42.234-21 10 54.03 L~09vD568 -99942 2C2008 01 08.65691716 12 42.968-21 10 55.80 L~09vD568 -99942 2C2008 01 08.65923516 12 43.584-21 10 56.95 L~09vD568 -99942 2C2008 01 08.66382416 12 44.803-21 10 59.64 L~09vD568 -99942 2C2008 01 08.66575916 12 45.323-21 11 00.64 L~09vD568 -99942 2C2008 01 09.64923016 17 06.855-21 19 43.21 L~09vD568 -99942 2C2008 01 09.65116616 17 07.315-21 19 44.16 L~09vD568 -99942 2C2008 01 09.65314116 17 07.868-21 19 45.05 L~09vD568 -99942 2C2008 01 09.65508216 17 08.370-21 19 46.22 L~09vD568 -99942 2C2008 01 09.65908916 17 09.415-21 19 48.28 L~09vD568 -99942 2C2008 01 09.66102716 17 09.953-21 19 49.41 L~09vD568 -99942 2C2008 01 09.66312516 17 10.506-21 19 50.39 L~09vD568 -99942 2C2008 01 09.66508816 17 11.010-21 19 51.46 L~09vD568 From 61218059f4cf1c2f72e4f641dfe7dd1f08dfe72f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 21:05:05 +0200 Subject: [PATCH 30/46] Add mean anomaly to osculating elements --- src/orbit_determination/osculating.jl | 110 ++++++++++++++------------ 1 file changed, 58 insertions(+), 52 deletions(-) diff --git a/src/orbit_determination/osculating.jl b/src/orbit_determination/osculating.jl index ecc49238..3e86c7c3 100644 --- a/src/orbit_determination/osculating.jl +++ b/src/orbit_determination/osculating.jl @@ -1,16 +1,17 @@ @doc raw""" OsculatingElements{T <: Number} -Osculating orbital elements of a NEO. +Osculating orbital elements of a NEO. -# Fields +# Fields - `e::T`: eccentricity. - `q::T`: perihelion distance [au]. -- `tp::T`: time of pericenter passage [jd]. +- `tp::T`: time of pericenter passage [jd]. +- `M::T`: mean anomaly [deg]. - `Ω::T`: longitude of ascending node [deg]. - `ω::T`: argument of pericentre [deg]. -- `i::T`: inclination [deg]. +- `i::T`: inclination [deg]. - `a::T`: semimajor axis [au]. """ @auto_hash_equals struct OsculatingElements{T <: Number} @@ -20,132 +21,137 @@ Osculating orbital elements of a NEO. Ω::T ω::T i::T + M::T a::T - # Inner constructor - function OsculatingElements{T}(e::T, q::T, tp::T, Ω::T, ω::T, i::T, a::T) where {T <: Number} - return new{T}(e, q, tp, Ω, ω, i, a) + # Inner constructor + function OsculatingElements{T}(e::T, q::T, tp::T, Ω::T, ω::T, i::T, M::T, a::T) where {T <: Number} + return new{T}(e, q, tp, Ω, ω, i, M, a) end end # Outer constructors -function OsculatingElements(e::T, q::T, tp::T, Ω::T, ω::T, i::T, a::T) where {T <: Number} - return OsculatingElements{T}(e, q, tp, Ω, ω, i, a) +function OsculatingElements(e::T, q::T, tp::T, Ω::T, ω::T, i::T, M::T, a::T) where {T <: Number} + return OsculatingElements{T}(e, q, tp, Ω, ω, i, M, a) end function OsculatingElements() - return OsculatingElements(NaN, NaN, NaN, NaN, NaN, NaN, NaN) + return OsculatingElements(NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN) end -# A OsculatingElements is NaN if all its fields are NaN -function isnan(osc::OsculatingElements{T}) where {T <: Number} - return isnan(osc.e) && isnan(osc.q) && isnan(osc.tp) && isnan(osc.Ω) && isnan(osc.ω) && isnan(osc.i) && isnan(osc.a) +# A OsculatingElements is NaN if all its fields are NaN +function isnan(osc::OsculatingElements{T}) where {T <: Number} + return isnan(osc.e) && isnan(osc.q) && isnan(osc.tp) && isnan(osc.Ω) && isnan(osc.ω) && isnan(osc.i) && isnan(osc.M) && isnan(osc.a) end # Print method for OsculatingElements -# Example: -# Semimajor axis (a): 0.8717319220347314 au +# Example: # Eccentricity (e): 0.4231715487782969 -# Time of pericenter passage (tp): 2021-03-19T03:45:01.293 JDTDB # Pericenter distance (q): 0.5028397744678126 au +# Time of pericenter passage (tp): 2021-03-19T03:45:01.293 JDTDB +# Longitude of Ascending Node (Ω): 17.855086873010706 deg # Argument of pericenter (ω): 194.74654283451 deg # Inclination (i): 34.81327005431841 deg -# Longitude of Ascending Node (Ω): 17.855086873010706 deg -function show(io::IO, m::OsculatingElements{T}) where {T <: Number} - - print(io, rpad("Semimajor axis (a): ", 36), cte(m.a), " au\n") +# Mean anomaly (M): 118.87965684315387 deg +# Semimajor axis (a): 0.8717319220347314 au +function show(io::IO, m::OsculatingElements{T}) where {T <: Number} + print(io, rpad("Eccentricity (e): ", 36), cte(m.e), "\n") + print(io, rpad("Pericenter distance (q): ", 36), cte(m.q), " au\n") if isnan(m.tp) print(io, rpad("Time of pericenter passage (tp): ", 36), "NaN JDTDB\n") - else + else print(io, rpad("Time of pericenter passage (tp): ", 36), julian2datetime(cte(m.tp)), " JDTDB\n") - end - print(io, rpad("Pericenter distance (q): ", 36), cte(m.q), " au\n") + end + print(io, rpad("Longitude of Ascending Node (Ω): ", 36), cte(m.Ω), " deg\n") print(io, rpad("Argument of pericenter (ω): ", 36), cte(m.ω), " deg\n") print(io, rpad("Inclination (i): ", 36), cte(m.i), " deg\n") - print(io, rpad("Longitude of Ascending Node (Ω): ", 36), cte(m.Ω), " deg\n") + print(io, rpad("Mean anomaly (M): ", 36), cte(m.M), " deg\n") + print(io, rpad("Semimajor axis (a): ", 36), cte(m.a), " au\n") end @doc raw""" equatorial2ecliptic(xas::Vector{T}) where {T <: Number} -Rotate state vector `xas` from equatorial plane to the ecliptic. +Rotate state vector `xas` from equatorial plane to the ecliptic. """ function equatorial2ecliptic(xas::Vector{T}) where {T <: Number} # Rotation matrix (only positions) m_eq2ecl = Rx(deg2rad(ϵ0_deg)) # Rotational matrix (positions + velocities) m_xv_eq2ecl = hcat(vcat(m_eq2ecl, zeros(3,3)), vcat(zeros(3,3), m_eq2ecl)) - # Rotated state vector + # Rotated state vector return m_xv_eq2ecl*xas -end +end @doc raw""" pv2kep(xas, μ = μ_S, jd = JD_J2000, frame::Symbol = :equatorial) -Compute the orbital elements of the NEO with state vector `xas`. Return a `OsculatingElements` object. +Compute the orbital elements of the NEO with state vector `xas`. Return a `OsculatingElements` object. See also [`equatorial2ecliptic`](@ref), [`eccentricity`](@ref), [`semimajoraxis`](@ref), [`timeperipass`](@ref), [`longascnode`](@ref), [`argperi`](@ref) and [`inclination`](@ref). -# Arguments +# Arguments -- `xas`: State vector of the asteroid `[x, y, z, v_x, v_y, v_z]`. +- `xas`: State vector of the asteroid `[x, y, z, v_x, v_y, v_z]`. - `μ_S`: Mass parameter of the central body (Sun). -- `jd`: Orbit epoch of reference in julian days. +- `jd`: Orbit epoch of reference in julian days. - `frame::Symbol`: plane of reference (`:equatorial` or `:ecliptic`). """ -function pv2kep(xas, μ = μ_S, jd = JD_J2000, frame::Symbol = :equatorial) +function pv2kep(xas; μ = μ_S, jd = JD_J2000, frame::Symbol = :equatorial) if frame == :ecliptic xas = equatorial2ecliptic(xas) - end + end e = eccentricity(xas..., μ, 0.0) a = semimajoraxis(xas..., μ, 0.0) q = a * (1 - e) tp = timeperipass(jd, xas..., μ, 0.0) + n = meanmotion(μ,a) + M = rad2deg(meananomaly(n, jd, tp)) Ω = rad2deg(longascnode(xas...)) ω = rad2deg(argperi(xas..., μ, 0.0)) i = rad2deg(inclination(xas...)) - return OsculatingElements(e, q, tp, Ω, ω, i, a) + return OsculatingElements(e, q, tp, Ω, ω, i, M, a) end @doc raw""" (osc::OsculatingElements{T})(t::T) where {T <: Number} -Return cartesian state vector of orbit `osc` at time `t`. +Return cartesian state vector of orbit `osc` at time `t` (Julian day). """ function (osc::OsculatingElements{T})(t::T) where {T <: Number} - # Mean motion + # Mean motion n = PE.meanmotion(μ_S, osc.a) - # Mean anomaly + # Mean anomaly M = PE.meananomaly(n, t, osc.tp) # Eccentric anomaly E = PE.eccentricanomaly(osc.e, M) # True anomaly f = PE.trueanomaly(osc.e, E) - - # Distance to the central body + + # Distance to the central body r = osc.a * (1 - osc.e^2) / (1 + osc.e * cos(f)) - - # Obtain position and velocity in the orbital frame + + # Obtain position and velocity in the orbital frame r_o = r .* [cos(f), sin(f), 0.0] v_o = (sqrt(μ_S*osc.a)/r) .* [-sin(E), sqrt(1 - osc.e^2) * cos(E), 0.0] - - # Transform r_o and v_o to the inertial frame + + # Transform r_o and v_o to the inertial frame ω = deg2rad(osc.ω) i = deg2rad(osc.i) Ω = deg2rad(osc.Ω) - # Rotation from orbital to inertial frame + # Rotation from orbital to inertial frame A = Rz(-Ω) * Rx(-i) * Rz(-ω) r_i = A * r_o v_i = A * v_o - # State vector + # State vector pv_i = vcat(r_i, v_i) return pv_i -end +end @doc raw""" yarkp2adot(A2, a, e, μ_S) @@ -158,17 +164,17 @@ Return the average semimajor axis drift due to the Yarkovsky effect \end{align*} ``` where ``A_2`` is the Yarkovsky parameter, ``\mu_\odot = GM_\odot`` is the Sun's gravitational parameter, -``e`` is the eccentricity, ``n = \sqrt{\mu/a^3}`` is the mean motion, ``p = a(1-e^2)`` is the -semilatus rectum, and ``a`` is the semimajor axis. +``e`` is the eccentricity, ``n = \sqrt{\mu/a^3}`` is the mean motion, ``p = a(1-e^2)`` is the +semilatus rectum, and ``a`` is the semimajor axis. See https://doi.org/10.1016/j.icarus.2013.02.004. -# Arguments +# Arguments - `A2`: Yarkovsky parameter. -- `a`: semimajor axis. -- `e`: eccentricity. -- `μ_S`: mass parameter of the Sun. +- `a`: semimajor axis. +- `e`: eccentricity. +- `μ_S`: mass parameter of the Sun. """ function yarkp2adot(A2, a, e, μ_S) return 2A2/(sqrt(a)*(1-e^2)*sqrt(μ_S)) From be8e8e460bd94d42be004ec8b237d73dbc9aa267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 21:48:44 +0200 Subject: [PATCH 31/46] Add Keplerian osculating elements tests --- test/osculating.jl | 16 ++++++++++++++++ test/runtests.jl | 1 + 2 files changed, 17 insertions(+) create mode 100644 test/osculating.jl diff --git a/test/osculating.jl b/test/osculating.jl new file mode 100644 index 00000000..db0a3d25 --- /dev/null +++ b/test/osculating.jl @@ -0,0 +1,16 @@ +using NEOs +using Dates +using Test +using LinearAlgebra: norm + +@testset "Keplerian osculating elements" begin + q = [-9.759018085743707E-01, 3.896554445697074E-01, 1.478066121706831E-01, -9.071450085084557E-03, -9.353197026254517E-03, -5.610023032269034E-03] + kep = pv2kep(q) + jd2000 = datetime2julian(DateTime(2000,1,1,12)) + @test norm(kep(jd2000) - q, Inf) < 1e-10 + + qa = [-1.0506628055913627, -0.06064314196134998, -0.04997102228887035, 0.0029591421121582077, -0.01423233538611057, -0.005218412537773594] + jda = datetime2julian(DateTime(2004,6,1)) + kepa = pv2kep(qa) + @test norm(kep(jd2000) - q, Inf) < 1e-10 +end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 26af9608..b14ed89d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,6 +1,7 @@ # This file is part of the NEOs.jl package; MIT licensed testfiles = ( + "osculating.jl", "observations.jl", "propagation.jl" ) From 41df006277949b0ef05d1b2396bb7633b9225930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 21:51:18 +0200 Subject: [PATCH 32/46] Add Apophis radar astrometry data file --- test/data/99942_RADAR_2005_2013.dat | 46 +++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 test/data/99942_RADAR_2005_2013.dat diff --git a/test/data/99942_RADAR_2005_2013.dat b/test/data/99942_RADAR_2005_2013.dat new file mode 100644 index 00000000..864aa630 --- /dev/null +++ b/test/data/99942_RADAR_2005_2013.dat @@ -0,0 +1,46 @@ +99942 Apophis (2004 MN4) 2005-01-27 23:31:00 -100849.1434 0.250 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2005-01-29 00:00:00 192028507.13 4.000 us 2380 251 251 C +99942 Apophis (2004 MN4) 2005-01-29 00:00:00 -102512.9059 0.250 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2005-01-30 00:18:00 195808170.79 4.500 us 2380 251 251 C +99942 Apophis (2004 MN4) 2005-01-30 00:18:00 -103799.8178 0.150 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2005-08-07 17:07:00 8186.8 0.200 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2006-05-06 12:49:00 -118256.8 0.100 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2012-12-21 11:10:00 57992.443 0.250 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2012-12-22 11:00:00 57880.250 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2012-12-22 11:00:00 102682986.05 0.25 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-03 09:20:00 97449107.61 0.25 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-03 09:20:00 36629.285 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-03 10:00:00 97439308.71 3.000 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-03 10:50:00 97428425.46 0.25 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-05 08:40:00 30404.009 0.2 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-05 10:40:00 96911591.52 0.25 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-05 10:40:00 20031.160 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-05 10:50:00 96910218.03 3.000 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-06 08:20:00 26660.815 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-06 09:30:00 20775.144 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-08 08:10:00 15496.441 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-09 08:00:00 9670.119 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-09 08:00:00 96451449.73 0.2 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-09 09:20:00 2690.401 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-10 08:00:00 2590.857 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-10 08:00:00 96472652.72 0.20 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-10 09:40:00 96473924.8 0.20 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-11 07:20:00 -1589.599 0.2 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-14 08:10:00 97258343.56 0.20 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-14 08:10:00 -30561.776 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-14 09:50:00 97283037.17 0.20 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-15 06:30:00 -30666.291 0.10 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-16 06:30:00 -39582.277 0.20 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-16 06:30:00 98086754. 1.000 us 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-16 07:50:00 -46641.384 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-01-17 06:20:00 -47875.142 0.1 Hz 8560 253 253 C +99942 Apophis (2004 MN4) 2013-02-18 00:56:00 -76760.475 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-18 01:37:00 157906444.15 0.25 us 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-18 01:37:00 -78041.365 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-19 01:08:00 -78105.657 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-20 00:38:00 -78070.341 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-20 01:26:00 163578875.87 0.25 us 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-20 01:26:00 -79560.965 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-02-21 01:04:00 -79697.130 0.2 Hz 2380 251 251 C +99942 Apophis (2004 MN4) 2013-03-15 23:59:00 235220855.07 2.000 us 2380 251 251 C +99942 Apophis (2004 MN4) 2013-03-15 23:59:00 -80977.5254 0.238 Hz 2380 251 251 C From 07bc8cc2e7b655742c2e6d1bcc213d015b85a523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 21:52:38 +0200 Subject: [PATCH 33/46] Import meananomaly, meanmotion from PE --- src/NEOs.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/NEOs.jl b/src/NEOs.jl index e2fb34a9..43bfd74d 100644 --- a/src/NEOs.jl +++ b/src/NEOs.jl @@ -12,7 +12,8 @@ import PlanetaryEphemeris as PE using PlanetaryEphemeris: daysec, su, ea, α_p_sun, δ_p_sun, t2c_jpl_de430, pole_rotation, au, c_au_per_day, R_sun, c_cm_per_sec, c_au_per_sec, yr, RE, TaylorInterpolant, Rx, Ry, Rz, semimajoraxis, eccentricity, inclination, longascnode, argperi, timeperipass, - nbodyind, ordpres_differentiate, numberofbodies, kmsec2auday, auday2kmsec + nbodyind, ordpres_differentiate, numberofbodies, kmsec2auday, auday2kmsec, meanmotion, + meananomaly using Healpix: ang2pixRing, Resolution using SatelliteToolbox: get_iers_eop_iau_2000A, EOPData_IAU1980, EOPData_IAU2000A, JD_J2000, orbsv, sv_ecef_to_eci, get_Δat, nutation_fk5 From e7b3426c9a963df27ff9995cc563794980e8c90e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 21:53:53 +0200 Subject: [PATCH 34/46] Small comment fix --- src/observations/topocentric.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl index 2023f974..ff089737 100644 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -76,8 +76,6 @@ function obsposvelECI(observatory::ObservatoryMPC{T}, et::ET; # Transform position/velocity from Earth-Centered Earth-fixed (ECEF) frame to Earth-Centered Inertial (ECI) frame # ITRF: International Terrestrial Reference Frame # GCRF: Geocentric Celestial Reference Frame - - # Use earth orientation parameters pv_ECI = sv_ecef_to_eci(pv_ECEF, Val(:ITRF), Val(:GCRF), jd_utc, eop) # Inertial position From 927537868cef7c4ec8ee809792a744efbaa6bc7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 21:54:21 +0200 Subject: [PATCH 35/46] Add missing ST. prefix --- src/observations/topocentric.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/observations/topocentric.jl b/src/observations/topocentric.jl index ff089737..7c0749a5 100644 --- a/src/observations/topocentric.jl +++ b/src/observations/topocentric.jl @@ -233,7 +233,7 @@ function t2c_rotation_iau_76_80(et::T; eo::Bool = true) where {T <: Number} ut1_days = ut1/daysec # elapsed UT1 days since J2000.0 # Greenwich apparent sidereal time (IAU 1982/1994) # See equation (5-173) in page (5-67) of https://doi.org/10.1002/0471728470: - gmst82 = J2000toGMST(ut1_days) + gmst82 = ST.J2000toGMST(ut1_days) gast = mod2pi( gmst82 + ee ) β_dot = eo ? omega(EarthOrientation.getlod(t_utc_00)) : ω From ff85049878e345b9b8c4ef82e90d22f6f5cd5884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 23:36:00 +0200 Subject: [PATCH 36/46] Update tests --- test/propagation.jl | 112 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 91 insertions(+), 21 deletions(-) diff --git a/test/propagation.jl b/test/propagation.jl index 3f86fcfd..2857a348 100644 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -22,10 +22,10 @@ using InteractiveUtils: methodswith end - @testset "Orbit propagation without nongravs: 2023 DW" begin + using PlanetaryEphemeris: selecteph, ea, su, daysec, auday2kmsec + using Statistics - using PlanetaryEphemeris: selecteph, ea, su, daysec, auday2kmsec - using Statistics + @testset "Orbit propagation without nongravs: 2023 DW" begin objname = "2023DW" maxsteps = 1000 @@ -34,6 +34,7 @@ using InteractiveUtils: methodswith quadmath = false # use quadruple precision dynamics = RNp1BP_pN_A_J23E_J2S_eph_threads! jd0 = datetime2julian(DateTime(2023,2,25,0,0,0)) #Julian date of integration initial time + # unperturbed initial condition q0 = [-9.759018085743707E-01, 3.896554445697074E-01, 1.478066121706831E-01, -9.071450085084557E-03, -9.353197026254517E-03, -5.610023032269034E-03] sseph = NEOs.sseph # Sun's ephemeris @@ -41,6 +42,7 @@ using InteractiveUtils: methodswith # Earth's ephemeris eph_ea = selecteph(sseph, ea) + # warmup propagation NEOs.propagate( dynamics, 1, @@ -70,34 +72,102 @@ using InteractiveUtils: methodswith # Read optical astrometry file obs_radec_mpc_2023DW = NEOs.read_radec_mpc(joinpath("data", "RADEC_2023_DW.dat")) - nobs = length(obs_radec_mpc_2023DW) # Compute residuals loadjpleph() # load JPL ephemeris - @time res, w = NEOs.residuals( + res, _ = NEOs.residuals( obs_radec_mpc_2023DW, xve=t->auday2kmsec(eph_ea(t)), xvs=t->auday2kmsec(eph_su(t)), xva=t->auday2kmsec(sol(t/daysec)) ) - @test mean(res) ≈ -0.6667868924169593 - @test std(res) ≈ 0.7360918596772479 - # pre-fit normalized RMS using Veres et al. (2017) weights - @test nrms(res, w) ≈ 1.656629515975594 - # pre-fit normalized RMS using ESA/NEOCC/NEODyS weights - rms_NEOCC = [0.600,0.600,0.600,0.600,0.600,0.600,0.600,0.600,0.600,0.600,0.600,0.600,0.600, - 0.600,0.600,0.600,0.600,0.600,0.600,1.000,1.000,1.000,0.600,0.600,0.600,0.600,1.000, - 0.600,0.600,0.600,0.600,0.600,0.600,1.000,1.000,0.600,0.600,0.600,0.600,0.500,0.500, - 0.600,0.600,0.600,0.600,0.600,1.000,1.000,1.000,0.500,0.500,0.500,0.500,0.500,0.500, - 0.130,0.150,0.160,0.500,0.500,0.600,0.600,0.400,0.400,0.400,0.600,0.600,0.600,0.600, - 0.600,0.500,0.500,0.400,0.400,0.400,0.600,0.600,0.600,0.600,0.600,0.400,0.400,0.400, - 1.000,1.000,0.300,1.000,0.300,1.000,0.300,0.500,0.300,0.500,0.500,0.600,0.600,0.600, - 0.600,0.600,0.500,0.500,0.400,0.400,0.600,0.400,0.600,0.060,0.090,0.400,0.600,0.600, - 0.600,0.600,0.600,0.600,0.100,0.100,0.100,0.060,0.050,0.050,0.060,0.050] - w_NEOCC = repeat(1.0./rms_NEOCC.^2, 2) - @test nrms(res, w_NEOCC) ≈ 3.5579681705883575 + mean_radec0 = mean(res) + std_radec0 = std(res) + rms_radec0 = nrms(res,ones(length(res))) # un-normalized RMS + @test mean_radec0 ≈ -0.667 atol=1e-2 + @test std_radec0 ≈ 0.736 atol=1e-2 + @test rms_radec0 ≈ 0.992 atol=1e-2 + + # propagate orbit with perturbed initial conditions + q1 = q0 + vcat(1e-3randn(3), 1e-5randn(3)) + sol1 = NEOs.propagate( + dynamics, + maxsteps, + jd0, + nyears, + sseph, + q1, + Val(true), + order = 25, + abstol = 1e-20, + parse_eqs = true + ) + # compute residuals for orbit with perturbed initial conditions + res1, _ = NEOs.residuals( + obs_radec_mpc_2023DW, + xve=t->auday2kmsec(eph_ea(t)), + xvs=t->auday2kmsec(eph_su(t)), + xva=t->auday2kmsec(sol1(t/daysec)) + ) + mean_radec1 = mean(res1) + std_radec1 = std(res1) + rms_radec1 = nrms(res1,ones(length(res1))) + + @test abs(mean_radec1) ≥ abs(mean_radec0) + @test std_radec1 ≥ std_radec0 + @test rms_radec1 ≥ rms_radec0 + end + + @testset "Orbit propagation with nongravs: (99942) Apophis" begin + + # integration parameters + objname = "Apophis" + maxsteps = 2000 + nyears = 4.0 + dense = true + quadmath = false + dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! + jd0 = datetime2julian(DateTime(2004,6,1)) #Julian date of integration initial time + # JPL #199 solution for Apophis at June 1st, 2004 + q0 = [-1.0506628055913627, -0.06064314196134998, -0.04997102228887035, 0.0029591421121582077, -0.01423233538611057, -0.005218412537773594, -5.592839897872e-14, 0.0] + sseph = NEOs.sseph + # Sun's ephemeris + eph_su = selecteph(sseph, su) + # Earth's ephemeris + eph_ea = selecteph(sseph, ea) + + # propagate orbit + sol = NEOs.propagate( + dynamics, + maxsteps, + jd0, + nyears, + sseph, + q0, + Val(true), + order = 25, + abstol = 1e-20, + parse_eqs = true + ) + + # Read optical astrometry file + obs_radec_mpc_apophis = NEOs.read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) + + # Compute residuals + res, _ = NEOs.residuals( + obs_radec_mpc_apophis, + xve=t->auday2kmsec(eph_ea(t)), + xvs=t->auday2kmsec(eph_su(t)), + xva=t->auday2kmsec(sol(t/daysec)) + ) + mean_radec = mean(res) + std_radec = std(res) + rms_radec = nrms(res,ones(length(res))) + @test mean_radec ≈ 0.005 atol=1e-2 + @test std_radec ≈ 0.110 atol=1e-2 + @test rms_radec ≈ std_radec atol=1e-2 end end From a66d6d37a9141eb5d8ab13e4beae33f8b1b8c821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Sun, 4 Jun 2023 23:36:13 +0200 Subject: [PATCH 37/46] Remove comment --- dev/generate_artifacts.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/dev/generate_artifacts.jl b/dev/generate_artifacts.jl index 49fbce1f..26983ba7 100644 --- a/dev/generate_artifacts.jl +++ b/dev/generate_artifacts.jl @@ -67,7 +67,6 @@ for (url, name) in zip(urls, names) end end f() - # tarball = Downloads.download(url, joinpath(tmp_dir, basename(url))) try tarball_hash = open(tarball) do file bytes2hex(sha256(file)) From b71d5fa5a42d332a8882a01f4080edb536ed4fb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Mon, 5 Jun 2023 21:29:34 +0200 Subject: [PATCH 38/46] Add radar astrometry residuals tests --- test/propagation.jl | 52 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/test/propagation.jl b/test/propagation.jl index 2857a348..efe284c4 100644 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -123,8 +123,8 @@ using InteractiveUtils: methodswith # integration parameters objname = "Apophis" - maxsteps = 2000 - nyears = 4.0 + maxsteps = 5000 + nyears = 9.0 dense = true quadmath = false dynamics = RNp1BP_pN_A_J23E_J2S_ng_eph_threads! @@ -154,20 +154,54 @@ using InteractiveUtils: methodswith # Read optical astrometry file obs_radec_mpc_apophis = NEOs.read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) - # Compute residuals + # Compute optical astrometry residuals res, _ = NEOs.residuals( obs_radec_mpc_apophis, xve=t->auday2kmsec(eph_ea(t)), xvs=t->auday2kmsec(eph_su(t)), xva=t->auday2kmsec(sol(t/daysec)) ) + nobsopt = round(Int, length(res)) + + # Compute mean optical astrometric residual (right ascension and declination) + res_ra = res[1:round(Int,nobsopt/2)] + res_dec = res[round(Int,nobsopt/2)+1:end] + mean_ra = mean(res_ra) + mean_dec = mean(res_dec) + std_ra = std(res_ra) + std_dec = std(res_dec) + rms_ra = nrms(res_ra,ones(length(res_ra))) + rms_dec = nrms(res_dec,ones(length(res_dec))) + @show mean_ra, std_ra,rms_ra + @show mean_dec, std_dec,rms_dec + # @test mean_radec ≈ 0.005 atol=1e-2 + # @test std_radec ≈ 0.110 atol=1e-2 + # @test rms_radec ≈ std_radec atol=1e-2 + + # Read radar astrometry file + deldop_2005_2013 = NEOs.read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) + + # Compute mean radar (time-delay and Doppler-shift) residuals + println("Computing radar astrometric residuals") + @time res_del, w_del, res_dop, w_dop = residuals( + deldop_2005_2013, + xve=t->auday2kmsec(eph_ea(t)), + xvs=t->auday2kmsec(eph_su(t)), + xva=t->auday2kmsec(sol(t/daysec)) + niter=4, + tord=5 + ) + + mean_del = mean(res_del) + mean_dop = mean(res_dop) + std_del = std(res_del) + std_dop = std(res_dop) + rms_del = nrms(res_del,w_del) + rms_dop = nrms(res_dop,w_dop) + + @show res_del, w_del, res_dop, w_dop + @show mean_del, mean_dop, std_del, std_dop, rms_del, rms_dop - mean_radec = mean(res) - std_radec = std(res) - rms_radec = nrms(res,ones(length(res))) - @test mean_radec ≈ 0.005 atol=1e-2 - @test std_radec ≈ 0.110 atol=1e-2 - @test rms_radec ≈ std_radec atol=1e-2 end end From e0ea25db4173c56dedeee55f7e6658f7c3a84138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Mon, 5 Jun 2023 21:36:59 +0200 Subject: [PATCH 39/46] Fix missing comma --- test/propagation.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/propagation.jl b/test/propagation.jl index efe284c4..91a9a8fb 100644 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -187,7 +187,7 @@ using InteractiveUtils: methodswith deldop_2005_2013, xve=t->auday2kmsec(eph_ea(t)), xvs=t->auday2kmsec(eph_su(t)), - xva=t->auday2kmsec(sol(t/daysec)) + xva=t->auday2kmsec(sol(t/daysec)), niter=4, tord=5 ) From fcf89344a0dbd8b42996b8eb48916be6279a06b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Mon, 5 Jun 2023 22:07:04 +0200 Subject: [PATCH 40/46] Fix tests --- src/observations/process_radar.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/observations/process_radar.jl b/src/observations/process_radar.jl index 47e5b3a5..16442871 100644 --- a/src/observations/process_radar.jl +++ b/src/observations/process_radar.jl @@ -606,8 +606,8 @@ function residuals(obs::Vector{RadarJPL{T}}; tord::Int = 5, niter::Int = 10, tc: # Total residuals res = vcat(res_τ, res_ν) # Weights - w_τ = repeat(1 ./ x_jt[6][x_jt[14]].^2, 2) - w_ν = repeat(1 ./ x_jt[7][x_jt[15]].^2, 2) + w_τ = 1 ./ x_jt[6][x_jt[14]].^2 + w_ν = 1 ./ x_jt[7][x_jt[15]].^2 w = vcat(w_τ, w_ν) return res_τ, w_τ, res_ν, w_ν From 361544b66c5f97a2d5e6c2617c045e441f656206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Mon, 5 Jun 2023 22:44:15 +0200 Subject: [PATCH 41/46] Minor fixes; update tests --- src/observations/process_radar.jl | 8 ++------ test/propagation.jl | 30 +++++++++++++++++++----------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/observations/process_radar.jl b/src/observations/process_radar.jl index 16442871..a6afd1f7 100644 --- a/src/observations/process_radar.jl +++ b/src/observations/process_radar.jl @@ -548,7 +548,6 @@ function radar_astrometry(astradardata::Vector{RadarJPL{T}}; tord::Int = 5, nite # Iterate over the measurements for i in eachindex(astradardata) - @show astradardata[i] # Compute time delay and doppler shift vdelay[i], vdoppler[i] = radar_astrometry(astradardata[i], tord = tord, niter = niter, tc = tc, xve = xve, xvs = xvs, xva = xva, autodiff = autodiff) @@ -603,12 +602,9 @@ function residuals(obs::Vector{RadarJPL{T}}; tord::Int = 5, niter::Int = 10, tc: res_τ = x_jt[2][x_jt[14]] .- x_jt[4][x_jt[14]] # Doppler-shift residuals res_ν = x_jt[3][x_jt[15]] .- x_jt[5][x_jt[15]] - # Total residuals - res = vcat(res_τ, res_ν) # Weights - w_τ = 1 ./ x_jt[6][x_jt[14]].^2 - w_ν = 1 ./ x_jt[7][x_jt[15]].^2 - w = vcat(w_τ, w_ν) + w_τ = 1 ./ (x_jt[6][x_jt[14]].^2) + w_ν = 1 ./ (x_jt[7][x_jt[15]].^2) return res_τ, w_τ, res_ν, w_ν end diff --git a/test/propagation.jl b/test/propagation.jl index 91a9a8fb..9fc9adf3 100644 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -155,17 +155,17 @@ using InteractiveUtils: methodswith obs_radec_mpc_apophis = NEOs.read_radec_mpc(joinpath("data", "99942_Tholen_etal_2013.dat")) # Compute optical astrometry residuals - res, _ = NEOs.residuals( + res_radec, w_radec = NEOs.residuals( obs_radec_mpc_apophis, xve=t->auday2kmsec(eph_ea(t)), xvs=t->auday2kmsec(eph_su(t)), xva=t->auday2kmsec(sol(t/daysec)) ) - nobsopt = round(Int, length(res)) + nobsopt = round(Int, length(res_radec)) # Compute mean optical astrometric residual (right ascension and declination) - res_ra = res[1:round(Int,nobsopt/2)] - res_dec = res[round(Int,nobsopt/2)+1:end] + res_ra = res_radec[1:round(Int,nobsopt/2)] + res_dec = res_radec[round(Int,nobsopt/2)+1:end] mean_ra = mean(res_ra) mean_dec = mean(res_dec) std_ra = std(res_ra) @@ -174,9 +174,12 @@ using InteractiveUtils: methodswith rms_dec = nrms(res_dec,ones(length(res_dec))) @show mean_ra, std_ra,rms_ra @show mean_dec, std_dec,rms_dec - # @test mean_radec ≈ 0.005 atol=1e-2 - # @test std_radec ≈ 0.110 atol=1e-2 - # @test rms_radec ≈ std_radec atol=1e-2 + @test mean_ra ≈ 0.0224 atol=1e-2 + @test std_ra ≈ 0.136 atol=1e-2 + @test rms_ra ≈ std_ra atol=1e-2 + @test mean_dec ≈ -0.0124 atol=1e-2 + @test std_dec ≈ 0.0714 atol=1e-2 + @test rms_dec ≈ std_dec atol=1e-2 # Read radar astrometry file deldop_2005_2013 = NEOs.read_radar_jpl(joinpath("data", "99942_RADAR_2005_2013.dat")) @@ -196,12 +199,17 @@ using InteractiveUtils: methodswith mean_dop = mean(res_dop) std_del = std(res_del) std_dop = std(res_dop) - rms_del = nrms(res_del,w_del) - rms_dop = nrms(res_dop,w_dop) - @show res_del, w_del, res_dop, w_dop - @show mean_del, mean_dop, std_del, std_dop, rms_del, rms_dop + @test mean_del ≈ 0.281 atol=1e-2 + @test mean_dop ≈ -0.084 atol=1e-2 + @test std_del ≈ 1.246 atol=1e-2 + @test std_dop ≈ 0.286 atol=1e-2 + + res = vcat(res_radec, res_del, res_dop) + w = vcat(w_radec, w_del, w_dop) + # Total normalized RMS + @show nrms(res, w) end end From 46f004880ea47a1cb75b22b5950d2936c36e0f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Mon, 5 Jun 2023 23:01:39 +0200 Subject: [PATCH 42/46] Update propagation tests --- test/propagation.jl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/propagation.jl b/test/propagation.jl index 9fc9adf3..030dbf72 100644 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -172,8 +172,6 @@ using InteractiveUtils: methodswith std_dec = std(res_dec) rms_ra = nrms(res_ra,ones(length(res_ra))) rms_dec = nrms(res_dec,ones(length(res_dec))) - @show mean_ra, std_ra,rms_ra - @show mean_dec, std_dec,rms_dec @test mean_ra ≈ 0.0224 atol=1e-2 @test std_ra ≈ 0.136 atol=1e-2 @test rms_ra ≈ std_ra atol=1e-2 @@ -209,7 +207,7 @@ using InteractiveUtils: methodswith w = vcat(w_radec, w_del, w_dop) # Total normalized RMS - @show nrms(res, w) + @test nrms(res, w) ≈ 0.375 atol=1e-2 end end From 6c19d29da83bcc44a45b543d4740fb420892345c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Tue, 6 Jun 2023 21:19:45 +0200 Subject: [PATCH 43/46] Avoid use of ::Function throughout; pass `niters` as a kwarg in process_radec.jl --- pha/apophis.jl | 4 +- src/observations/process_radar.jl | 2 +- src/observations/process_radec.jl | 73 ++++--- src/observations/radec_mpc.jl | 208 +++++++++---------- src/orbit_determination/gauss_method.jl | 148 +++++++------- src/propagation/propagation.jl | 260 ++++++++++++------------ test/propagation.jl | 15 ++ 7 files changed, 360 insertions(+), 350 deletions(-) diff --git a/pha/apophis.jl b/pha/apophis.jl index 8626e809..0811a133 100644 --- a/pha/apophis.jl +++ b/pha/apophis.jl @@ -72,8 +72,8 @@ function print_header(header::String) println(repeat("-", L)) end -function main(dynamics::Function, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, nyears_fwd::T, - ss16asteph_et::TaylorInterpolant, order::Int, varorder::Int, abstol::T, parse_eqs::Bool) where {T <: Real} +function main(dynamics::D, maxsteps::Int, jd0_datetime::DateTime, nyears_bwd::T, nyears_fwd::T, + ss16asteph_et::TaylorInterpolant, order::Int, varorder::Int, abstol::T, parse_eqs::Bool) where {T <: Real, D} # Initial conditions from Apophis JPL solution #197 q00 = kmsec2auday(apophisposvel197(datetime2et(jd0_datetime))) diff --git a/src/observations/process_radar.jl b/src/observations/process_radar.jl index a6afd1f7..47c2dfb7 100644 --- a/src/observations/process_radar.jl +++ b/src/observations/process_radar.jl @@ -476,7 +476,7 @@ end radar_astrometry(astradarfile::String; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, xve = earthposvel, xvs = sunposvel, xva = apophisposvel197, autodiff::Bool = true) radar_astrometry(outfilename::String, radarobsfile::String, asteph::TaylorInterpolant, ss16asteph::TaylorInterpolant; tc::Real=1.0, autodiff::Bool=true, - tord::Int = 5, niter::Int = 5) + tord::Int = 5, niter::Int = 10) Return time-delay and Doppler shift. diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index 232734e0..27874171 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -1,10 +1,10 @@ @doc raw""" compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 5; - xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} - compute_radec(obs::RadecMPC{T}, niter::Int = 5; xve::Function = earthposvel, xvs::Function = sunposvel, - xva::Function = apophisposvel197) where {T <: AbstractFloat} - compute_radec(obs::Vector{RadecMPC{T}}, niter::Int=5; xve::Function=earthposvel, xvs::Function=sunposvel, - xva::Function=apophisposvel197) where {T <: AbstractFloat} + xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph = apophisposvel197) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} + compute_radec(obs::RadecMPC{T}, niter::Int = 5; xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, + xva::AstEph = apophisposvel197) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} + compute_radec(obs::Vector{RadecMPC{T}}, niter::Int=5; xve::EarthEph=earthposvel, xvs::SunEph=sunposvel, + xva::AstEph=apophisposvel197) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} Compute astrometric right ascension and declination (both in arcsec) for a set of MPC-formatted observations. Corrections due to Earth orientation, LOD, polar motion are considered in computations. @@ -13,14 +13,13 @@ Corrections due to Earth orientation, LOD, polar motion are considered in comput - `observatory::ObservatoryMPC{T}`: observation site. - `t_r_utc::DateTime`: UTC time of astrometric observation. -- `obs::RadecMPC{T}/Vector{RadecMPC{T}}`: observations. - `niter::Int`: number of light-time solution iterations. -- `xve::Function`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xvs::Function`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xva::Function`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xve`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xvs`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ -function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 5; - xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} +function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter::Int = 5, + xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph = apophisposvel197) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} # Transform receiving time from UTC to TDB seconds since J2000 et_r_secs = datetime2et(t_r_utc) # Compute geocentric position/velocity of receiving antenna in inertial frame [km, km/s] @@ -148,13 +147,11 @@ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter: return α_as, δ_as # right ascension, declination both in arcsec end -function compute_radec(obs::RadecMPC{T}, niter::Int = 5; xve::Function = earthposvel, xvs::Function = sunposvel, - xva::Function = apophisposvel197) where {T <: AbstractFloat} - return compute_radec(obs.observatory, obs.date, niter; xve = xve, xvs = xvs, xva = xva) +function compute_radec(obs::RadecMPC{T}; kwargs...) where {T <: AbstractFloat} + return compute_radec(obs.observatory, obs.date; kwargs...) end -function compute_radec(obs::Vector{RadecMPC{T}}, niter::Int = 5; xve::Function = earthposvel, xvs::Function = sunposvel, - xva::Function = apophisposvel197) where {T <: AbstractFloat} +function compute_radec(obs::Vector{RadecMPC{T}}; xva::AstEph=apophisposvel197, kwargs...) where {T <: AbstractFloat, AstEph} # Number of observations n_optical_obs = length(obs) @@ -174,7 +171,7 @@ function compute_radec(obs::Vector{RadecMPC{T}}, niter::Int = 5; xve::Function = # Iterate over the number of observations for i in 1:n_optical_obs - vra[i], vdec[i] = compute_radec(obs[i], niter, xve = xve, xvs = xvs, xva = xva) + vra[i], vdec[i] = compute_radec(obs[i]; kwargs...) end return vra, vdec # arcsec, arcsec @@ -383,10 +380,8 @@ function w8sveres17(obs::RadecMPC{T}) where {T <: AbstractFloat} end @doc raw""" - radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 5; debias_table::String = "2018", - xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} - radec_astrometry(outfilename::String, opticalobsfile::String, asteph::TaylorInterpolant, ss16asteph::TaylorInterpolant, - niter::Int = 5; debias_table::String = "2018") + radec_astrometry(obs::Vector{RadecMPC{T}}; niter::Int = 5, debias_table::String = "2018", + xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph = apophisposvel197) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} Compute optical astrometry, i.e. dates of observation plus observed, computed, debiasing corrections and statistical weights for right ascension and declination (in arcsec). Corrections to Earth orientation parameters provided by IERS are computed by default. @@ -396,21 +391,19 @@ See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and # Arguments - `obs::Vector{RadecMPC{T}}`: vector of observations. -- `outfilename::String`: file where to save the results (.jld2). -- `opticalobsfile::String`: file where to retrieve optical observations. -- `asteph::TaylorInterpolant`: NEO's ephemeris. -- `ss16asteph::TaylorInterpolant`: solar system ephemeris. + +# Keyword arguments + - `niter::Int`: number of light-time solution iterations. - `debias_table::String`: possible values are: - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. -- `xve::Function`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xvs::Function`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xva::Function`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xve`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xvs`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ -function radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 5; debias_table::String = "2018", - xve::Function = earthposvel, xvs::Function = sunposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} +function radec_astrometry(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva::AstEph=apophisposvel197, kwargs...) where {T <: AbstractFloat, AstEph} # Number of observations n_optical_obs = length(obs) @@ -459,7 +452,7 @@ function radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 5; debias_table α_obs[i] = rad2arcsec(obs[i].α) * cos(obs[i].δ) # arcsec # Computed ra/dec - α_comp_as, δ_comp_as = compute_radec(obs[i], niter, xve=xve, xvs=xvs, xva=xva) + α_comp_as, δ_comp_as = compute_radec(obs[i]; kwargs...) # Multiply by metric factor cos(dec) α_comp[i] = α_comp_as * cos(obs[i].δ) # arcsec δ_comp[i] = δ_comp_as # arcsec @@ -477,8 +470,8 @@ function radec_astrometry(obs::Vector{RadecMPC{T}}, niter::Int = 5; debias_table end @doc raw""" - residuals(obs::Vector{RadecMPC{T}}, niter::Int = 5; debias_table::String = "2018", - xvs::Function = sunposvel, xve::Function = earthposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} + residuals(obs::Vector{RadecMPC{T}}; niter::Int = 5, debias_table::String = "2018", + xvs::SunEph = sunposvel, xve::EarthEph = earthposvel, xva::AstEph = apophisposvel197) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} Compute O-C residuals for optical astrometry. Corrections due to Earth orientation, LOD, polar motion are computed by default. @@ -487,20 +480,22 @@ See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and # Arguments - `obs::Vector{RadecMPC{T}}`: vector of observations. + +# Keyword arguments + - `niter::Int`: number of light-time solution iterations. - `debias_table::String`: possible values are: - `2014` corresponds to https://doi.org/10.1016/j.icarus.2014.07.033, - `2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596, - `hires2018` corresponds to https://doi.org/10.1016/j.icarus.2019.113596. -- `xvs::Function`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xve::Function`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xva::Function`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xvs::EarthEph`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xve::SunEph`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xva::AstEph`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ -function residuals(obs::Vector{RadecMPC{T}}, niter::Int = 5; debias_table::String = "2018", - xvs::Function = sunposvel, xve::Function = earthposvel, xva::Function = apophisposvel197) where {T <: AbstractFloat} +function residuals(obs::Vector{RadecMPC{T}}; kwargs...) where {T <: AbstractFloat} # Optical astrometry (dates + observed + computed + debiasing + weights) - x_jt = radec_astrometry(obs, niter; debias_table = debias_table, xvs = xvs, xve = xve, xva = xva) + x_jt = radec_astrometry(obs; kwargs...) # Right ascension residuals res_α = x_jt[2] .- x_jt[6] .- x_jt[4] # Declination residuals diff --git a/src/observations/radec_mpc.jl b/src/observations/radec_mpc.jl index 8392fe33..deea5dee 100644 --- a/src/observations/radec_mpc.jl +++ b/src/observations/radec_mpc.jl @@ -6,9 +6,9 @@ abstract type AbstractAstrometry end An optical (α, δ) measurement in MPC format. The format is described in https://minorplanetcenter.net/iau/info/OpticalObs.html and discussed thoroughly in pages 158-181 of https://doi.org/10.1016/j.icarus.2010.06.003. -# Fields +# Fields -- `num::String`: object's number. +- `num::String`: object's number. - `tmpdesig::String`: provisional / temporary designation. - `discovery::String`: discovery asterisk. - `publishnote::String`: publishable note. @@ -16,15 +16,15 @@ and discussed thoroughly in pages 158-181 of https://doi.org/10.1016/j.icarus.20 - `date::DateTime`: date of observation. - `α::T`: right ascension [rad]. - `δ::T`: declination [rad]. -- `info1::String`: additional information. -- `mag::String`: observed magnitude. -- `band::String`: magnitude band. -- `catalogue::CatalogueMPC`: catalogue. -- `info2::String`: additional information. -- `observatory::ObservatoryMPC{T}`: observatory. +- `info1::String`: additional information. +- `mag::String`: observed magnitude. +- `band::String`: magnitude band. +- `catalogue::CatalogueMPC`: catalogue. +- `info2::String`: additional information. +- `observatory::ObservatoryMPC{T}`: observatory. """ @auto_hash_equals struct RadecMPC{T <: AbstractFloat} <: AbstractAstrometry - num::String + num::String tmpdesig::String discovery::String publishnote::String @@ -38,32 +38,32 @@ and discussed thoroughly in pages 158-181 of https://doi.org/10.1016/j.icarus.20 catalogue::CatalogueMPC info2::String observatory::ObservatoryMPC{T} - # Inner constructor - function RadecMPC{T}(num::String, tmpdesig::String, discovery::String, publishnote::String, - obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::String, + # Inner constructor + function RadecMPC{T}(num::String, tmpdesig::String, discovery::String, publishnote::String, + obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::String, band::String, catalogue::CatalogueMPC, info2::String, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} - new{T}(num, tmpdesig, discovery, publishnote, obstech, date, α, δ, info1, mag, band, + new{T}(num, tmpdesig, discovery, publishnote, obstech, date, α, δ, info1, mag, band, catalogue, info2, observatory) end end # Outer constructor -function RadecMPC(num::String, tmpdesig::String, discovery::String, publishnote::String, - obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::String, - band::String, catalogue::CatalogueMPC, info2::String, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} +function RadecMPC(num::String, tmpdesig::String, discovery::String, publishnote::String, + obstech::String, date::DateTime, α::T, δ::T, info1::String, mag::String, + band::String, catalogue::CatalogueMPC, info2::String, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} RadecMPC{T}(num, tmpdesig, discovery, publishnote, obstech, date, α, δ, info1, mag, band, catalogue, info2, observatory) end function RadecMPC(date::DateTime, α::T, δ::T, observatory::ObservatoryMPC{T}) where {T <: AbstractFloat} RadecMPC{T}("", "", "", "", "", date, α, δ, "", "", "", unknowncat(), "", observatory) -end +end # Print method for RadecMPC -# Examples: +# Examples: # N00hp15 α: 608995.65 δ: -25653.3 t: 2020-12-04T10:41:43.209 obs: 703 # 99942 α: 422475.3 δ: 97289.49 t: 2021-05-12T06:28:35.904 obs: F51 -function show(io::IO, m::RadecMPC{T}) where {T <: AbstractFloat} +function show(io::IO, m::RadecMPC{T}) where {T <: AbstractFloat} # If there is no number, use temporary designation id_str = filter(!isspace, m.num) == "" ? m.tmpdesig : m.num @@ -71,7 +71,7 @@ function show(io::IO, m::RadecMPC{T}) where {T <: AbstractFloat} " obs: ", m.observatory.name) end -# Functions to get specific fields of a RadecMPC object +# Functions to get specific fields of a RadecMPC object num(r::RadecMPC{T}) where {T <: AbstractFloat} = r.num tmpdesig(r::RadecMPC{T}) where {T <: AbstractFloat} = r.tmpdesig discovery(r::RadecMPC{T}) where {T <: AbstractFloat} = r.discovery @@ -105,7 +105,7 @@ const mpc_radec_regex = Regex(join( raw"(?P\d{2}) ", # Day regex (columns 24-25) raw"(?P\d{2})", - # Fraction of days regex (columns 26-32) + # Fraction of days regex (columns 26-32) raw"(?P\.[\d\s]{6})", # α hours regex + space (columns 33-35) raw"(?P<α_hrs>\d{2}) ", @@ -139,7 +139,7 @@ const mpc_radec_regex = Regex(join( @doc raw""" datetime(year::Int, month::Int, day::Int, utc::T) where {T <: Real} -Construct a `DateTime` type by parts. `utc` is the fraction of day. +Construct a `DateTime` type by parts. `utc` is the fraction of day. """ function datetime(year::Int, month::Int, day::Int, utc::T) where {T <: Real} return DateTime(year, month, day) + Microsecond( round(1e6*86_400*utc) ) @@ -149,14 +149,14 @@ end ra(hrs::Int, min::Int, sec::T) where {T <: Real} ra(obs::RadecMPC{T}) where {T <: AbstractFloat} -Return the right ascension in rad. +Return the right ascension in rad. """ function ra(hrs::Int, min::Int, sec::T) where {T <: Real} # Convert hours minutes seconds to deg α_deg = 15*(hrs + min/60 + sec/3_600) # Convert deg to rad α_rad = deg2rad(α_deg) - + return α_rad end @@ -165,7 +165,7 @@ end dec(sgn::String, deg::Int, min::Int, sec::T) where {T <: Real} dec(obs::RadecMPC{T}) where {T <: AbstractFloat} -Return the declination in rad. +Return the declination in rad. """ function dec(sgn::String, deg::Int, min::Int, sec::T) where {T <: Real} # Convert degrees minutes seconds to degrees @@ -187,36 +187,36 @@ Convert a match of `NEOs.mpc_radec_regex` to `RadecMPC`. """ function RadecMPC(m::RegexMatch) date = datetime( - Meta.parse(m["year"]), - Meta.parse(m["month"]), + Meta.parse(m["year"]), + Meta.parse(m["month"]), Meta.parse(m["day"]), Meta.parse(m["utc"]) ) α = ra( - Meta.parse(m["α_hrs"]), - Meta.parse(m["α_min"]), + Meta.parse(m["α_hrs"]), + Meta.parse(m["α_min"]), Meta.parse(m["α_sec"]) ) δ = dec( - string(m["δ_sgn"]), - Meta.parse(m["δ_deg"]), - Meta.parse(m["δ_min"]), + string(m["δ_sgn"]), + Meta.parse(m["δ_deg"]), + Meta.parse(m["δ_min"]), Meta.parse(m["δ_sec"]) ) - # Find catalogue in mpc_catalogues[] that matches catalogue + # Find catalogue in mpc_catalogues[] that matches catalogue catalogue = search_cat_code(string(m["catalogue"])) - # Find observatory in mpc_observatories[] that matches obscode + # Find observatory in mpc_observatories[] that matches obscode observatory = search_obs_code(string(m["obscode"])) - + return RadecMPC( string(m["num"]), string(m["tmpdesig"]), string(m["discovery"]), string(m["publishnote"]), string(m["obstech"]), - date, - α, - δ, + date, + α, + δ, string(m["info1"]), string(m["mag"]), string(m["band"]), @@ -232,9 +232,9 @@ end Return the matches of `NEOs.mpc_radec_regex` in `filename` as `RadecMPC`. """ function read_radec_mpc(filename::String) - # Check that filename is a file + # Check that filename is a file @assert isfile(filename) "Cannot open file: $filename" - # Read lines of mpc formatted file + # Read lines of mpc formatted file lines = readlines(filename) # Apply regular expressions matches = match.(mpc_radec_regex, lines) @@ -246,22 +246,22 @@ function read_radec_mpc(filename::String) sort!(obs) # Eliminate repeated observations unique!(obs) - + return obs end @doc raw""" parse_radec_mpc(text::String) - parse_radec_mpc(f::Function, text::String) + parse_radec_mpc(f::F, text::String) where F -Return the matches of `NEOs.mpc_radec_regex` in `text`. A function `f(m::RegexMatch) -> Bool` -can be passed to filter the matches. +Return the matches of `NEOs.mpc_radec_regex` in `text`. A function `f(m::RegexMatch) -> Bool` +can be passed to filter the matches. """ -function parse_radec_mpc(f::Function, text::String) +function parse_radec_mpc(f::F, text::String) where F - # Vector of observations + # Vector of observations radecs = Vector{RadecMPC{Float64}}(undef, 0) - # Iterate over the matches + # Iterate over the matches for m in eachmatch(mpc_radec_regex, text) # Filter by f if f(m) @@ -275,59 +275,59 @@ function parse_radec_mpc(f::Function, text::String) # Eliminate repeated observations unique!(radecs) end - + return radecs end parse_radec_mpc(text::String) = parse_radec_mpc(t -> true, text) -# MPC main page url +# MPC main page url const mpc_url = "https://minorplanetcenter.net" -# Regex for next circular url +# Regex for next circular url const next_circular_regex = r".*)\"> Bool` can be passed to filter the observations. If `url2` is not -reached before `max_iter` iterations, the function will print a warning and return the -matches found so far. +reached before `max_iter` iterations, the function will print a warning and return the +matches found so far. """ -function search_circulars_mpc(f::Function, url1::String, url2::String; max_iter::Int = 10_000) +function search_circulars_mpc(f::F, url1::String, url2::String; max_iter::Int = 10_000) where F # Vector of observations obs = Vector{RadecMPC{Float64}}(undef, 0) - - # Number of urls checked + + # Number of urls checked n = 0 - # First url + # First url u = url1 - while true + while true n += 1 if n > max_iter @warn("$n pages checked before getting to $url2") - break + break end - # Raw html text of webpage u + # Raw html text of webpage u text = get_raw_html(u) - # Observations found in text + # Observations found in text obs_ = parse_radec_mpc(f, text) - # Add new observations - obs = vcat(obs, obs_) - # Final url + # Add new observations + obs = vcat(obs, obs_) + # Final url if u == url2 break end - # Next circular url + # Next circular url next = match(next_circular_regex, text)["next"] u = mpc_url * next end # If there is at least one observation if length(obs) > 0 - # Sort observations by date + # Sort observations by date sort!(obs) # Eliminate repeated observations unique!(obs) @@ -341,27 +341,27 @@ search_circulars_mpc(url1::String, url2::String; max_iter::Int = 10_000) = searc @doc raw""" mpc_date_str(date::DateTime) -Return the date in MPC format. +Return the date in MPC format. """ function mpc_date_str(date::DateTime) - - # Year string + + # Year string year_s = lpad(Dates.year(date), 4) - # Month string + # Month string month_s = lpad(Dates.month(date), 2, "0") - # Hours [days] + # Hours [days] hrs = Dates.hour(date) / 24 - # Minutes [days] + # Minutes [days] min = Dates.minute(date) / 24 / 60 - # Seconds [days] + # Seconds [days] sec = Dates.second(date) / 24 / 60 / 60 - # Milliseconds [days] + # Milliseconds [days] mls = Dates.millisecond(date) / 24 / 60 / 60 / 1_000 - # Days + # Days day_val = Dates.day(date) + hrs + min + sec + mls - # Days string + # Days string day_s = @sprintf("%09.6f", day_val) - # Join everything + # Join everything date_s = join([ year_s, " ", @@ -376,24 +376,24 @@ end @doc raw""" mpc_α_str(α::T) where {T <: Number} -Return the right ascension [rad] in MPC format. +Return the right ascension [rad] in MPC format. """ function mpc_α_str(α::T) where {T <: Number} - # Convert rad to deg + # Convert rad to deg α_deg = rad2deg(α) - # Hours + # Hours hrs_, hrs = modf(α_deg / 15) hrs = Int(hrs) - # Hours string + # Hours string hrs_s = lpad(hrs, 2, "0") - # Minutes + # Minutes min_, min = modf(60 * hrs_) min = Int(min) - # Minutes string + # Minutes string min_s = lpad(min, 2, "0") - # Seconds + # Seconds sec = 60 * min_ - # Seconds string + # Seconds string sec_s = @sprintf("%06.3f", sec) # Join everything α_s = join([ @@ -404,32 +404,32 @@ function mpc_α_str(α::T) where {T <: Number} sec_s, ]) - return α_s + return α_s end @doc raw""" mpc_δ_str(δ::T) where {T <: Number} -Return the declination [rad] in MPC format. +Return the declination [rad] in MPC format. """ function mpc_δ_str(δ::T) where {T <: Number} - # Sign string + # Sign string sgn_s = δ >= 0 ? "+" : "-" - # Convert rad to deg + # Convert rad to deg δ_deg = abs(rad2deg(δ)) - # Degrees + # Degrees deg_, deg = modf(δ_deg) deg = Int(deg) - # Degrees string + # Degrees string deg_s = lpad(deg, 2, "0") - # Minutes + # Minutes min_, min = modf(60 * deg_) min = Int(min) - # Minutes string + # Minutes string min_s = lpad(min, 2, "0") # Seconds sec = 60 * min_ - # Seconds string + # Seconds string sec_s = @sprintf("%05.2f", sec) # Join everything δ_s = join([ @@ -441,24 +441,24 @@ function mpc_δ_str(δ::T) where {T <: Number} sec_s, ]) - return δ_s + return δ_s end @doc raw""" mpc_radec_str(obs::RadecMPC{T}) where {T <: AbstractFloat} -Return an observation in MPC format. +Return an observation in MPC format. """ function mpc_radec_str(obs::RadecMPC{T}) where {T <: AbstractFloat} - # Date string + # Date string date_s = mpc_date_str(obs.date) - # Right ascension string + # Right ascension string α_s = mpc_α_str(obs.α) - # Declination string + # Declination string δ_s = mpc_δ_str(obs.δ) - # Catalogue string + # Catalogue string catalogue_s = isunknown(obs.catalogue) ? " " : obs.catalogue.code - # Observatory string + # Observatory string obscode_s = isunknown(obs.observatory) ? " " : obs.observatory.code # Join everything obs_s = join([ @@ -485,13 +485,13 @@ end @doc raw""" write_radec_mpc(obs::Vector{RadecMPC{T}}, filename::String) where {T <: AbstractFloat} -Write `obs` to `filename` in MPC format. +Write `obs` to `filename` in MPC format. """ function write_radec_mpc(obs::Vector{RadecMPC{T}}, filename::String) where {T <: AbstractFloat} open(filename, "w") do file for i in eachindex(obs) line = mpc_radec_str(obs[i]) write(file, line) - end + end end end \ No newline at end of file diff --git a/src/orbit_determination/gauss_method.jl b/src/orbit_determination/gauss_method.jl index e3193f6c..85e3dde1 100644 --- a/src/orbit_determination/gauss_method.jl +++ b/src/orbit_determination/gauss_method.jl @@ -8,14 +8,14 @@ https://doi.org/10.1016/C2016-0-02107-1. See also [`gauss_method`](@ref). -# Fields - -- `statevect::Vector{U}`: state vector at middle observation. -- `D::Matrix{U}`: D matrix. -- `R_vec::Matrix{T}`: observer's heliocentric positions. -- `ρ_vec::Matrix{U}`: slant ranges. -- `τ_1::T`: time between first and second observations. -- `τ_3::T`: time between third and second observations. +# Fields + +- `statevect::Vector{U}`: state vector at middle observation. +- `D::Matrix{U}`: D matrix. +- `R_vec::Matrix{T}`: observer's heliocentric positions. +- `ρ_vec::Matrix{U}`: slant ranges. +- `τ_1::T`: time between first and second observations. +- `τ_3::T`: time between third and second observations. - `f_1, g_1, f_3, g_3::U`: Lagrange coefficients. - `status::Symbol`: the status of the solution (`:empty`, `:unkown` or `:unique`) """ @@ -24,30 +24,30 @@ See also [`gauss_method`](@ref). D::Matrix{U} R_vec::Matrix{T} ρ_vec::Matrix{U} - τ_1::T + τ_1::T τ_3::T f_1::U g_1::U - f_3::U - g_3::U + f_3::U + g_3::U status::Symbol - # Internal constructor - function GaussSolution{T, U}(statevect::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, ρ_vec::Matrix{U}, τ_1::T, τ_3::T, + # Internal constructor + function GaussSolution{T, U}(statevect::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, ρ_vec::Matrix{U}, τ_1::T, τ_3::T, f_1::U, g_1::U, f_3::U, g_3::U, status::Symbol) where {T <: Real, U <: Number} return new{T, U}(statevect, D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3, status) - end -end + end +end -# Outer constructor -function GaussSolution(statevect::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, ρ_vec::Matrix{U}, τ_1::T, τ_3::T, +# Outer constructor +function GaussSolution(statevect::Vector{U}, D::Matrix{U}, R_vec::Matrix{T}, ρ_vec::Matrix{U}, τ_1::T, τ_3::T, f_1::U, g_1::U, f_3::U, g_3::U, status::Symbol) where {T <: Real, U <: Number} return GaussSolution{T, U}(statevect, D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3, status) -end +end # Print method for GaussSolution -# Examples: +# Examples: # unique Gauss solution (r = 1.0800950907383229) -function show(io::IO, g::GaussSolution{T, U}) where {T <: Real, U <: Number} +function show(io::IO, g::GaussSolution{T, U}) where {T <: Real, U <: Number} print(io, g.status, " Gauss solution (r = ", norm(cte.(g.statevect[1:3])), ")") end @@ -58,7 +58,7 @@ end Return the topocentric unit vector. """ function topounit(α::T, δ::T) where {T <: Number} - + sin_α, cos_α = sincos(α) sin_δ, cos_δ = sincos(δ) @@ -74,7 +74,7 @@ topounit(obs::RadecMPC{T}) where {T <: AbstractFloat} = topounit(obs.α, obs.δ) @doc raw""" f_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} -Return the 1st order approximation to Lagrange's f function. +Return the 1st order approximation to Lagrange's f function. """ function f_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} return 1 - μ_S * (τ^2) / 2 / (r^3) @@ -82,7 +82,7 @@ end @doc raw""" g_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} - + Return the 1st order approximation to Lagrange's g function. """ function g_Lagrange(τ::T, r::U) where {T <: Real, U <: Number} @@ -107,87 +107,87 @@ function _format_Lagrange_equation(a::T, b::T, c::T) where {T <: AbstractFloat} c_sgn = c ≥ 0 ? "+" : "-" return join(["r⁸ ", a_sgn, " ", abs(a), " r⁶ ", b_sgn, " ", abs(b), " r³ ", c_sgn, " ", abs(c), " = 0"]) -end +end @doc raw""" lagrange(x::T, a::U, b::U, c::U) where {T, U <: Number} -Lagrange polynomial to be solved during Gauss method. +Lagrange polynomial to be solved during Gauss method. """ lagrange(x::T, a::U, b::U, c::U) where {T, U <: Number} = x^8 + a*x^6 + b*x^3 + c @doc raw""" lagrange_derivative(x::T, a::T, b::T) where {T <: Number} -Derivative of Lagrange polynomial to be solved during Gauss method. +Derivative of Lagrange polynomial to be solved during Gauss method. """ lagrange_derivative(x::T, a::U, b::U) where {T, U <: Number} = 8*x^7 + 6*a*x^5 + 3*b*x^2 -# TO DO: Allow to control interval over which to look for solutions +# TO DO: Allow to control interval over which to look for solutions # Currently we look between the radius of the Sun ((0.00465047 au) and the radius of the Solar System (40 au) @doc raw""" solve_lagrange(a::T, b::T, c::T; niter::Int = niter) where {T <: Real} solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int = niter) where {T <: Real} -Solve Lagrange polynomial. +Solve Lagrange polynomial. See also [`lagrange`](@ref). """ -function solve_lagrange(a::T, b::T, c::T; niter::Int = 5) where {T <: Real} +function solve_lagrange(a::T, b::T, c::T; niter::Int = 5) where {T <: Real} sol = roots(x -> lagrange(x, a, b, c), Interval(0.00465047, 40)) return mid.(interval.(sol)), getfield.(sol, :status) -end +end function solve_lagrange(a::TaylorN{T}, b::TaylorN{T}, c::TaylorN{T}; niter::Int = 5) where {T <: Real} - # 0-th order solution + # 0-th order solution sol_0, status = solve_lagrange(cte(a), cte(b), cte(c)) - # Discard empty solutions + # Discard empty solutions idxs = findall(x -> x != :empty, status) - # Vector of solutions + # Vector of solutions sol = Vector{TaylorN{T}}(undef, length(idxs)) # Iterate non-empty solutions for i in eachindex(sol) - # Newton's method - r_0 = sol_0[idxs[i]] - r_2 = sol_0[idxs[i]] + # Newton's method + r_0 = sol_0[idxs[i]] + r_2 = sol_0[idxs[i]] for j in 1:niter r_2 = r_0 - lagrange(r_0, a, b, c) / lagrange_derivative(r_0, a, b) r_0 = r_2 - end + end sol[i] = r_2 end return sol, status[idxs] -end +end @doc raw""" - gauss_method(obs::Vector{RadecMPC{T}}; xve::Function = et -> kmsec2auday(getposvel(399, 10, et)), - niter::Int = 10) where {T <: AbstractFloat} + gauss_method(obs::Vector{RadecMPC{T}}; xve::EarthEph = et -> kmsec2auday(getposvel(399, 10, et)), + niter::Int = 10) where {T <: AbstractFloat, EarthEph} gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, α::Vector{U}, δ::Vector{U}; - xve::Function = et -> kmsec2auday(getposvel(399, 10, et)), niter::Int = 5) where {T <: Real, U <: Number} + xve::EarthEph = et -> kmsec2auday(getposvel(399, 10, et)), niter::Int = 5) where {T <: Real, U <: Number, EarthEph} Core Gauss method of Initial Orbit determination (IOD). See Algorithm 5.5 in page 274 https://doi.org/10.1016/C2016-0-02107-1. -# Arguments +# Arguments - `obs::Vector{RadecMPC{T}}`: three observations. - `observatories::Vector{ObservatoryMPC{T}}`: sites of observation. - `dates::Vector{DateTime}`: times of observation. - `α::Vector{U}`: right ascension. -- `δ::Vector{U}`: declination. -- `xve::Function`: Earth's ephemeris [et -> au, au/day]. -- `niter::Int`: Number of iterations for Newton's method. +- `δ::Vector{U}`: declination. +- `xve::EarthEph`: Earth's ephemeris [et -> au, au/day]. +- `niter::Int`: Number of iterations for Newton's method. """ -function gauss_method(obs::Vector{RadecMPC{T}}; xve::Function = et -> kmsec2auday(getposvel(399, 10, et)), niter::Int = 5) where {T <: AbstractFloat} - - # Make sure observations are in temporal order +function gauss_method(obs::Vector{RadecMPC{T}}; xve::EarthEph = et -> kmsec2auday(getposvel(399, 10, et)), niter::Int = 5) where {T <: AbstractFloat, EarthEph} + + # Make sure observations are in temporal order sort!(obs) # Sites of observation observatories = observatory.(obs) - # Dates of observation + # Dates of observation dates = date.(obs) # Right ascension @@ -197,29 +197,29 @@ function gauss_method(obs::Vector{RadecMPC{T}}; xve::Function = et -> kmsec2auda δ = dec.(obs) return gauss_method(observatories, dates, α, δ; xve = xve, niter = niter) -end +end function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{DateTime}, α::Vector{U}, δ::Vector{U}; - xve::Function = et -> kmsec2auday(getposvel(399, 10, et)), niter::Int = 5) where {T <: Real, U <: Number} + xve::EarthEph = et -> kmsec2auday(getposvel(399, 10, et)), niter::Int = 5) where {T <: Real, U <: Number, EarthEph} - # Check we have exactly three observations + # Check we have exactly three observations @assert length(observatories) == length(dates) == length(α) == length(δ) == 3 "Gauss method requires exactly three observations" # Julian days of observation t_julian = datetime2julian.(dates) - # Time intervals + # Time intervals τ_1 = t_julian[1] - t_julian[2] τ_3 = t_julian[3] - t_julian[2] τ = τ_3 - τ_1 - # NEO's topocentric position unit vectors + # NEO's topocentric position unit vectors ρ_vec = vectors2matrix(topounit.(α, δ)) # Times of observation [et] t_et = datetime2et.(dates) - # Geocentric state vector of the observer [au, au/day] + # Geocentric state vector of the observer [au, au/day] g_vec = kmsec2auday.(obsposvelECI.(observatories, t_et)) # Heliocentric state vector of the Earth [au, au/day] @@ -228,28 +228,28 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da # Observer's heliocentric positions [au, au/day] R_vec = vectors2matrix(G_vec .+ g_vec)[:, 1:3] - # Cross products + # Cross products p_vec = zeros(U, 3, 3) p_vec[1, :] = cross(ρ_vec[2, :], ρ_vec[3, :]) p_vec[2, :] = cross(ρ_vec[1, :], ρ_vec[3, :]) - p_vec[3, :] = cross(ρ_vec[1, :], ρ_vec[2, :]) + p_vec[3, :] = cross(ρ_vec[1, :], ρ_vec[2, :]) - # Gauss scalar + # Gauss scalar D_0 = dot(ρ_vec[1, :], p_vec[1, :]) - # Matrix of triple products + # Matrix of triple products D = zeros(U, 3, 3) for i in 1:3 for j in 1:3 - D[i, j] = dot(R_vec[i, :], p_vec[j, :]) + D[i, j] = dot(R_vec[i, :], p_vec[j, :]) end - end + end - # A and B scalars + # A and B scalars A = (-D[1, 2]*τ_3/τ + D[2, 2] + D[3, 2]*τ_1/τ) / D_0 B = (D[1, 2]*(τ_3^2 - τ^2)*τ_3/τ + D[3, 2]*(τ^2 - τ_1^2)*τ_1/τ) / 6 / D_0 - # E and F scalars + # E and F scalars E = dot(R_vec[2, :], ρ_vec[2, :]) F = dot(R_vec[2, :], R_vec[2, :]) @@ -258,26 +258,26 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da b = -2*μ_S*B*(A + E) c = -(μ_S^2)*(B^2) - # Solve Lagrange equation + # Solve Lagrange equation sol, status = solve_lagrange(a, b, c; niter = niter) - # Number of solutions + # Number of solutions n_sol = length(sol) if n_sol == 0 - + @warn("""No solutions found for Lagrange equation $(_format_Lagrange_equation(cte(a), cte(b), cte(c)))""") return Vector{GaussSolution{T, U}}(undef, 0) - else + else sol_gauss = Vector{GaussSolution{T, U}}(undef, n_sol) for i in eachindex(sol_gauss) - # Heliocentric range + # Heliocentric range r_2 = sol[i] - # Slant ranges + # Slant ranges ρ = zeros(U, 3) num_1 = 6*(D[3, 1]*τ_1/τ_3 + D[2, 1]*τ/τ_3)*(r_2^3) + μ_S*D[3, 1]*(τ^2 - τ_1^2)*τ_1/τ_3 @@ -290,7 +290,7 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da den_3 = 6*(r_2^3) + μ_S*(τ^2 - τ_1^2) ρ[3] = (num_3 / den_3 - D[3, 3]) / D_0 - # Heliocentric position of the NEO + # Heliocentric position of the NEO r_vec = R_vec .+ ρ.*ρ_vec # f, g Lagrange coefficients @@ -300,14 +300,14 @@ function gauss_method(observatories::Vector{ObservatoryMPC{T}}, dates::Vector{Da g_1 = g_Lagrange(τ_1, r_2) g_3 = g_Lagrange(τ_3, r_2) - # Heliocentric velocity of the NEO + # Heliocentric velocity of the NEO v_2_vec = (- f_3 * r_vec[1, :] + f_1 * r_vec[3, :]) / (f_1*g_3 - f_3*g_1) sol_gauss[i] = GaussSolution{T, U}(vcat(r_vec[2, :], v_2_vec), D, R_vec, ρ_vec, τ_1, τ_3, f_1, g_1, f_3, g_3, status[i]) - end + end return sort!(sol_gauss, by = x -> norm(x.statevect[1:3])) - end - + end + end \ No newline at end of file diff --git a/src/propagation/propagation.jl b/src/propagation/propagation.jl index 983f0fce..1c491bb4 100644 --- a/src/propagation/propagation.jl +++ b/src/propagation/propagation.jl @@ -7,39 +7,39 @@ include("integration_methods.jl") Return `true` and the asteroid's radial velocity with respect to the Earth. -# Arguments +# Arguments -- `dx`: asteroid's velocities. -- `x`: asteroid's degrees of freedom. -- `eph`: ephemeris. -- `params`: parameters (ephemeris + accelerations + newtonian N body potential + julian date of start time + matrix of extended body interactions + number of bodies + mass parameters). +- `dx`: asteroid's velocities. +- `x`: asteroid's degrees of freedom. +- `eph`: ephemeris. +- `params`: parameters (ephemeris + accelerations + newtonian N body potential + julian date of start time + matrix of extended body interactions + number of bodies + mass parameters). - `t`: time. """ function rvelea(dx, x, eph, params, t) N = params[6] # Number of bodies in the ephemeris - xe = params[1][nbodyind(N-1,ea)] # Earth's ephemeris - + xe = params[1][nbodyind(N-1,ea)] # Earth's ephemeris + return true, (x[1]-xe[1])*(x[4]-xe[4]) + (x[2]-xe[2])*(x[5]-xe[5]) + (x[3]-xe[3])*(x[6]-xe[6]) end @doc raw""" loadeph(ss16asteph_::TaylorInterpolant, μ::Vector{T}) where {T <: Real} -Return the ephemeris in `ss16asteph_` with times converted from seconds to days, -the point-mass newtonian accelerations and the newtonian N body potential. +Return the ephemeris in `ss16asteph_` with times converted from seconds to days, +the point-mass newtonian accelerations and the newtonian N body potential. -# Arguments +# Arguments -- `ss16asteph_`: solar system ephemeris. -- `μ::Vector{T}`: vector of mass parameters. +- `ss16asteph_`: solar system ephemeris. +- `μ::Vector{T}`: vector of mass parameters. """ function loadeph(ss16asteph_::TaylorInterpolant, μ::Vector{T}) where {T <: Real} - + # Read Solar System ephemeris (Sun + 8 planets + Moon + Pluto + 16 main belt asteroids) ss16asteph_t0 = T(ss16asteph_.t0 / daysec) # Start time [days] - ss16asteph_t = T.(ss16asteph_.t ./ daysec) # Vector of times [days] - ephord = ss16asteph_.x[1].order # Order of the Taylor polynomials + ss16asteph_t = T.(ss16asteph_.t ./ daysec) # Vector of times [days] + ephord = ss16asteph_.x[1].order # Order of the Taylor polynomials ss16asteph_x = map(x -> x(Taylor1(T, ephord)*daysec), ss16asteph_.x) # Vector of Taylor polynomials [au, au/day] ss16asteph = TaylorInterpolant(ss16asteph_t0, ss16asteph_t, ss16asteph_x) # TaylorInterpolant ephemeris [au, au/day] @@ -49,18 +49,18 @@ function loadeph(ss16asteph_::TaylorInterpolant, μ::Vector{T}) where {T <: Real Nm1 = numberofbodies(ss16asteph_x) # Initialize a TaylorInterpolant for the point-mass Newtonian accelerations acc_eph = TaylorInterpolant(ss16asteph.t0, ss16asteph.t, Matrix{eltype(ss16asteph.x)}(undef, length(ss16asteph.t)-1, 3Nm1)) - # Initialize a TaylorInterpolant for the newtonian N body potential + # Initialize a TaylorInterpolant for the newtonian N body potential newtonianNb_Potential = TaylorInterpolant(ss16asteph.t0, ss16asteph.t, Matrix{eltype(ss16asteph.x)}(undef, length(ss16asteph.t)-1, Nm1)) # Fill TaylorInterpolant.x with zero polynomials fill!(acc_eph.x, zero(ss16asteph.x[1])) fill!(newtonianNb_Potential.x, zero(ss16asteph.x[1])) # Iterator over all bodies except asteroid - _1_to_Nm1 = Base.OneTo(Nm1) + _1_to_Nm1 = Base.OneTo(Nm1) for j in 1:Nm1 for i in 1:Nm1 if i == j - # + # else # Difference between two positions (\mathbf{r}_i - \mathbf{r}_j) X_ij = ss16asteph.x[:, 3i-2] .- ss16asteph.x[:, 3j-2] # X-axis component @@ -75,7 +75,7 @@ function loadeph(ss16asteph_::TaylorInterpolant, μ::Vector{T}) where {T <: Real end end - # Fill acelerations by differentiating velocities + # Fill acelerations by differentiating velocities acc_eph.x[:, 3j-2] .= ordpres_differentiate.(ss16asteph.x[:, 3(Nm1+j)-2]) # X-axis component acc_eph.x[:, 3j-1] .= ordpres_differentiate.(ss16asteph.x[:, 3(Nm1+j)-1]) # Y-axis component acc_eph.x[:, 3j ] .= ordpres_differentiate.(ss16asteph.x[:, 3(Nm1+j) ]) # Z-axis component @@ -87,12 +87,12 @@ end @doc raw""" save2jldandcheck(objname, sol) -Save `sol` in a file `objname_jt.jld2`. +Save `sol` in a file `objname_jt.jld2`. -See also [`__save2jldandcheck`](@ref). +See also [`__save2jldandcheck`](@ref). """ function save2jldandcheck(objname, sol) - # Name of the file + # Name of the file outfilename = string(objname, "_jt.jld2") # Save sol in outfilename return __save2jldandcheck(outfilename, sol) @@ -101,26 +101,26 @@ end @doc raw""" __save2jldandcheck(outfilename, sol) -Savs `sol` in `outfilename`. +Savs `sol` in `outfilename`. """ function __save2jldandcheck(outfilename, sol) println("Saving solution to file: $outfilename") - # Open file + # Open file JLD2.jldopen(outfilename, "w") do file # Loop over solution variables for ind in eachindex(sol) - # Name of the variable + # Name of the variable varname = string(ind) println("Saving variable: ", varname) - # Write the varaible + # Write the varaible write(file, varname, sol[ind]) end end - # Check that saved solution is equal to the original + # Check that saved solution is equal to the original println("Checking that all variables were saved correctly...") # Loop over solution variables for ind in eachindex(sol) - # Name of the variable + # Name of the variable varname = string(ind) # Read varname from files and assign recovered variable to recovered_sol_i recovered_sol_i = JLD2.load(outfilename, varname) @@ -135,19 +135,19 @@ end taylor_minimum(pol::Taylor1{T}, x0::T; niters::Int=10) where {T<:Real} Return the minimum of the Taylor polynomial `pol` computed via Newton's method. `x0` is the -initial guess and `niters` is the number of iterations. +initial guess and `niters` is the number of iterations. """ function taylor_minimum(pol::Taylor1{T}, x0::T; niters::Int=10) where {T<:Real} - # First derivative + # First derivative dpol = PE.ordpres_differentiate(pol) # Second derivative dpol2 = PE.ordpres_differentiate(dpol) # Initial guess xnewton::T = x0 #@show xnewton - # Newton iteration + # Newton iteration for i in 1:niters - # Newton update rule + # Newton update rule xnewton -= dpol(xnewton)/dpol2(xnewton) #@show xnewton, dpol(xnewton) end @@ -158,8 +158,8 @@ end @doc raw""" taylor_roots(pol::Taylor1{T}, x0::T; niters::Int=10) where {T<:Real} -Return the root of the Taylor polynomial `pol` computed via Newton's method. `x0` is the -initial guess and `niters` is the number of iterations. +Return the root of the Taylor polynomial `pol` computed via Newton's method. `x0` is the +initial guess and `niters` is the number of iterations. """ function taylor_roots(pol::Taylor1{T}, x0::T; niters::Int=10) where {T<:Real} # First derivative @@ -167,9 +167,9 @@ function taylor_roots(pol::Taylor1{T}, x0::T; niters::Int=10) where {T<:Real} # Initial guess xnewton::T = x0 #@show xnewton - # Newton iteration + # Newton iteration for i in 1:niters - # Newton update rule + # Newton update rule xnewton -= pol(xnewton)/dpol(xnewton) #@show xnewton, pol(xnewton) end @@ -179,7 +179,7 @@ end @doc raw""" scaled_variables(c::Vector{T} = fill(1e-6, 6), names::String = "δx"; order::Int = 5) where {T <: Real} -Equivalent to `TaylorSeries.set_variables` times a scaling given by `c`. +Equivalent to `TaylorSeries.set_variables` times a scaling given by `c`. """ function scaled_variables(names::String = "δx", c::Vector{T} = fill(1e-6, 6); order::Int = 5) where {T <: Real} # Set TaylorN variables @@ -188,32 +188,32 @@ function scaled_variables(names::String = "δx", c::Vector{T} = fill(1e-6, 6); o for i in eachindex(dq) dq[i][1][i] = c[i] end - return dq -end + return dq +end @doc raw""" - propagate_params(jd0::T, ss16asteph_et::TaylorInterpolant, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], + propagate_params(jd0::T, ss16asteph_et::TaylorInterpolant, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number} -Return the parameters needed for `propagate`, `propagate_lyap` and `propagate_root`. +Return the parameters needed for `propagate`, `propagate_lyap` and `propagate_root`. -# Arguments +# Arguments - `jd0::T`: initial Julian date. - `ss16asteph_et::TaylorInterpolant`: solar system ephemeris. - `q0::Vector{U}`: vector of initial conditions. -- `μ_ast::Vector`: vector of gravitational parameters. -- `order::Int`: order of the Taylor expansions to be used in the integration. +- `μ_ast::Vector`: vector of gravitational parameters. +- `order::Int`: order of the Taylor expansions to be used in the integration. - `abstol::T`: absolute tolerance. """ -function propagate_params(jd0::T, ss16asteph_et::TaylorInterpolant, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], +function propagate_params(jd0::T, ss16asteph_et::TaylorInterpolant, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number} # Number of massive bodies Nm1 = numberofbodies(ss16asteph_et.x) # Number of bodies, including NEA - N = Nm1 + 1 + N = Nm1 + 1 # Vector of G*m values μ = convert(Vector{T}, vcat( μ_DE430[1:11], μ_ast[1:Nm1-11], zero(T) ) ) @@ -228,34 +228,34 @@ function propagate_params(jd0::T, ss16asteph_et::TaylorInterpolant, q0::Vector{U # Interaction matrix with flattened bodies UJ_interaction = fill(false, N) - # Turn on Earth interaction + # Turn on Earth interaction UJ_interaction[ea] = true - # Initial time + # Initial time _t0 = zero(T) - # Time as Taylor variable + # Time as Taylor variable t = _t0 + Taylor1( T, order ) - # Days since J2000 + # Days since J2000 dsj2k = t + (jd0 - JD_J2000) - # Initial conditions + # Initial conditions _q0 = one(T) * q0 # Auxiliary variable (to know the type of evaleph) aux_q0 = Taylor1(eltype(_q0), order) # Ephemeris at dsj2k - ss16asteph_t = evaleph(ss16asteph_auday, dsj2k, aux_q0) + ss16asteph_t = evaleph(ss16asteph_auday, dsj2k, aux_q0) # Accelerations at dsj2k - acceph_t = evaleph(acc_eph, dsj2k, aux_q0) + acceph_t = evaleph(acc_eph, dsj2k, aux_q0) # Newtonian potentials at dsj2k - newtonianNb_Potential_t = evaleph(newtonianNb_Potential, dsj2k, aux_q0) + newtonianNb_Potential_t = evaleph(newtonianNb_Potential, dsj2k, aux_q0) - # Ephemeris vector + # Ephemeris vector _eph = (ss16asteph_auday, acc_eph, newtonianNb_Potential) # Vector of parameters for neosinteg @@ -263,127 +263,127 @@ function propagate_params(jd0::T, ss16asteph_et::TaylorInterpolant, q0::Vector{U return _q0, _t0, _eph, _params -end +end @doc raw""" - propagate(dynamics::Function, maxsteps::Int, jd0::T, tspan::T, ss16asteph_et::TaylorInterpolant, - q0::Vector{U}, ::$V_dense; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, - abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number} + propagate(dynamics::D, maxsteps::Int, jd0::T, tspan::T, ss16asteph_et::TaylorInterpolant, + q0::Vector{U}, ::$V_dense; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, + abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number, D} -Integrate the orbit of a NEO via the Taylor method. +Integrate the orbit of a NEO via the Taylor method. -# Arguments +# Arguments -- `dynamics::Function`: dynamical model function. +- `dynamics::D`: dynamical model function. - `maxsteps::Int`: maximum number of steps for the integration. - `jd0::T`: initial Julian date. -- `tspan::T`: time span of the integration [in Julian days]. +- `tspan::T`: time span of the integration [in Julian days]. - `ss16asteph_et::TaylorInterpolant`: solar system ephemeris. - `q0::Vector{U}`: vector of initial conditions. - `Val(true/false)`: whether to output the Taylor polynomials generated at each time step (`true`) or not. -- `μ_ast::Vector`: vector of gravitational parameters. -- `order::Int=order`: order of the Taylor expansions to be used in the integration. +- `μ_ast::Vector`: vector of gravitational parameters. +- `order::Int=order`: order of the Taylor expansions to be used in the integration. - `abstol::T`: absolute tolerance. -- `parse_eqs::Bool`: whether to use the specialized method of `jetcoeffs` (`true`) or not. +- `parse_eqs::Bool`: whether to use the specialized method of `jetcoeffs` (`true`) or not. """ propagate @doc raw""" - propagate_root(dynamics::Function, maxsteps::Int, jd0::T, tspan::T, ss16asteph_et::TaylorInterpolant, - q0::Vector{U}, ::$V_dense; parse_eqs::Bool = true, eventorder::Int = 0, newtoniter::Int = 10, - nrabstol::T = eps(T), μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, - abstol::T = abstol) where {T <: Real, U <: Number} + propagate_root(dynamics::D, maxsteps::Int, jd0::T, tspan::T, ss16asteph_et::TaylorInterpolant, + q0::Vector{U}, ::$V_dense; parse_eqs::Bool = true, eventorder::Int = 0, newtoniter::Int = 10, + nrabstol::T = eps(T), μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, + abstol::T = abstol) where {T <: Real, U <: Number, D} -Integrate the orbit of a NEO via the Taylor method while finding the zeros of `rvelea`. +Integrate the orbit of a NEO via the Taylor method while finding the zeros of `rvelea`. -# Arguments +# Arguments -- `dynamics::Function`: dynamical model function. +- `dynamics::D`: dynamical model function. - `maxsteps::Int`: maximum number of steps for the integration. - `jd0::T`: initial Julian date. -- `tspan::T`: time span of the integration [in Julian days]. +- `tspan::T`: time span of the integration [in Julian days]. - `ss16asteph_et::TaylorInterpolant`: solar system ephemeris. - `q0::Vector{U}`: vector of initial conditions. - `Val(true/false)`: whether to output the Taylor polynomials generated at each time step (`true`) or not. -- `parse_eqs::Bool`: whether to use the specialized method of `jetcoeffs` (`true`) or not. +- `parse_eqs::Bool`: whether to use the specialized method of `jetcoeffs` (`true`) or not. - `eventorder::Int`: order of the derivative of `rvelea` whose roots are computed. - `newtoniter::Int`: maximum Newton-Raphson iterations per detected root. - `nrabstol::T`: allowed tolerance for the Newton-Raphson process. -- `μ_ast::Vector`: vector of gravitational parameters. -- `order::Int`: order of the Taylor expansions to be used in the integration. +- `μ_ast::Vector`: vector of gravitational parameters. +- `order::Int`: order of the Taylor expansions to be used in the integration. - `abstol::T`: absolute tolerance. -""" propagate_root +""" propagate_root for V_dense in V_true_false @eval begin - function propagate(dynamics::Function, maxsteps::Int, jd0::T, tspan::T, sseph::TaylorInterpolant, q0::Vector{U}, - ::$V_dense; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol, - parse_eqs::Bool = true) where {T <: Real, U <: Number} + function propagate(dynamics::D, maxsteps::Int, jd0::T, tspan::T, sseph::TaylorInterpolant, q0::Vector{U}, + ::$V_dense; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol, + parse_eqs::Bool = true) where {T <: Real, U <: Number, D} - # Parameters for apophisinteg + # Parameters for apophisinteg _q0, _t0, _eph, _params = propagate_params(jd0, sseph, q0; μ_ast = μ_ast, order = order, abstol = abstol) # Final time of integration (days) - _tmax = _t0 + tspan*yr - + _tmax = _t0 + tspan*yr + # Propagate orbit # Dense output (save Taylor polynomials in each step) - @time sol = neosinteg(dynamics, _q0, _t0, _tmax, order, abstol, $V_dense(), _eph, _params; + @time sol = neosinteg(dynamics, _q0, _t0, _tmax, order, abstol, $V_dense(), _eph, _params; maxsteps = maxsteps, parse_eqs = parse_eqs) - - return sol + + return sol end - function propagate(dynamics::Function, maxsteps::Int, jd0::T1, tspan::T2, sseph::TaylorInterpolant, q0::Vector{U}, - ::$V_dense; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T3 = abstol, - parse_eqs::Bool = true) where {T1, T2, T3 <: Real, U <: Number} + function propagate(dynamics::D, maxsteps::Int, jd0::T1, tspan::T2, sseph::TaylorInterpolant, q0::Vector{U}, + ::$V_dense; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T3 = abstol, + parse_eqs::Bool = true) where {T1, T2, T3 <: Real, U <: Number, D} _jd0, _tspan, _abstol = promote(jd0, tspan, abstol) return propagate(dynamics, maxsteps, _jd0, _tspan, sseph, q0, $V_dense(); μ_ast = μ_ast, order = order, abstol = _abstol, parse_eqs = parse_eqs) - end + end - function propagate(dynamics::Function, maxsteps::Int, jd0::T, nyears_bwd::T, nyears_fwd::T, sseph::TaylorInterpolant, + function propagate(dynamics::D, maxsteps::Int, jd0::T, nyears_bwd::T, nyears_fwd::T, sseph::TaylorInterpolant, q0::Vector{U}, ::$V_dense; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol, - parse_eqs::Bool = true) where {T <: Real, U <: Number} + parse_eqs::Bool = true) where {T <: Real, U <: Number, D} # Backward integration - bwd = propagate(dynamics, maxsteps, jd0, nyears_bwd, sseph, q0, $V_dense(); μ_ast = μ_ast, order = order, + bwd = propagate(dynamics, maxsteps, jd0, nyears_bwd, sseph, q0, $V_dense(); μ_ast = μ_ast, order = order, abstol = abstol, parse_eqs = parse_eqs) - # Forward integration - fwd = propagate(dynamics, maxsteps, jd0, nyears_fwd, sseph, q0, $V_dense(); μ_ast = μ_ast, order = order, + # Forward integration + fwd = propagate(dynamics, maxsteps, jd0, nyears_fwd, sseph, q0, $V_dense(); μ_ast = μ_ast, order = order, abstol = abstol, parse_eqs = parse_eqs) - return bwd, fwd + return bwd, fwd - end + end - function propagate_root(dynamics::Function, maxsteps::Int, jd0::T, tspan::T, sseph::TaylorInterpolant, q0::Vector{U}, - ::$V_dense; parse_eqs::Bool = true, eventorder::Int = 0, newtoniter::Int = 10, nrabstol::T = eps(T), - μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number} + function propagate_root(dynamics::D, maxsteps::Int, jd0::T, tspan::T, sseph::TaylorInterpolant, q0::Vector{U}, + ::$V_dense; parse_eqs::Bool = true, eventorder::Int = 0, newtoniter::Int = 10, nrabstol::T = eps(T), + μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number, D} - # Parameters for apophisinteg + # Parameters for apophisinteg _q0, _t0, _eph, _params = propagate_params(jd0, sseph, q0; μ_ast = μ_ast, order = order, abstol = abstol) - + # Final time of integration (days) - _tmax = _t0 + tspan*yr - + _tmax = _t0 + tspan*yr + # Propagate orbit - @time sol = neosinteg(dynamics, rvelea, _q0, _t0, _tmax, order, abstol, $V_dense(), _eph, _params; - maxsteps = maxsteps, parse_eqs = parse_eqs, eventorder = eventorder, newtoniter = newtoniter, + @time sol = neosinteg(dynamics, rvelea, _q0, _t0, _tmax, order, abstol, $V_dense(), _eph, _params; + maxsteps = maxsteps, parse_eqs = parse_eqs, eventorder = eventorder, newtoniter = newtoniter, nrabstol = nrabstol) return sol end - function propagate_root(dynamics::Function, maxsteps::Int, jd0::T1, tspan::T2, sseph::TaylorInterpolant, q0::Vector{U}, - ::$V_dense; parse_eqs::Bool = true, eventorder::Int = 0, newtoniter::Int = 10, nrabstol::T3 = eps(T), - μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T4 = abstol) where {T1, T2, T3, T4 <: Real, U <: Number} + function propagate_root(dynamics::D, maxsteps::Int, jd0::T1, tspan::T2, sseph::TaylorInterpolant, q0::Vector{U}, + ::$V_dense; parse_eqs::Bool = true, eventorder::Int = 0, newtoniter::Int = 10, nrabstol::T3 = eps(T), + μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T4 = abstol) where {T1, T2, T3, T4 <: Real, U <: Number, D} _jd0, _tspan, _nrabstol, _abstol = promote(jd0, tspan, nrabstol, abstol) @@ -392,58 +392,58 @@ for V_dense in V_true_false order = order, abstol = _abstol) end - function propagate_root(dynamics::Function, maxsteps::Int, jd0::T, nyears_bwd::T, nyears_fwd::T, sseph::TaylorInterpolant, - q0::Vector{U}, ::$V_dense; parse_eqs::Bool = true, eventorder::Int = 0, newtoniter::Int = 10, - nrabstol::T = eps(T), μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number} + function propagate_root(dynamics::D, maxsteps::Int, jd0::T, nyears_bwd::T, nyears_fwd::T, sseph::TaylorInterpolant, + q0::Vector{U}, ::$V_dense; parse_eqs::Bool = true, eventorder::Int = 0, newtoniter::Int = 10, + nrabstol::T = eps(T), μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol) where {T <: Real, U <: Number, D} # Backward integration bwd, tvS_bwd, xvS_bwd, gvS_bwd = propagate_root(dynamics, maxsteps, jd0, nyears_bwd, sseph, q0, $V_dense(); parse_eqs = parse_eqs, eventorder = eventorder, newtoniter = newtoniter, nrabstol = nrabstol, μ_ast = μ_ast, order = order, abstol = abstol) - # Forward integration + # Forward integration fwd, tvS_fwd, xvS_fwd, gvS_fwd = propagate_root(dynamics, maxsteps, jd0, nyears_fwd, sseph, q0, $V_dense(); parse_eqs = parse_eqs, eventorder = eventorder, newtoniter = newtoniter, nrabstol = nrabstol, μ_ast = μ_ast, order = order, abstol = abstol) - return bwd, tvS_bwd, xvS_bwd, gvS_bwd, fwd, tvS_fwd, xvS_fwd, gvS_fwd + return bwd, tvS_bwd, xvS_bwd, gvS_bwd, fwd, tvS_fwd, xvS_fwd, gvS_fwd end end -end +end @doc raw""" - propagate_lyap(dynamics::Function, maxsteps::Int, jd0::T, tspan::T, ss16asteph_et::TaylorInterpolant, + propagate_lyap(dynamics::D, maxsteps::Int, jd0::T, tspan::T, ss16asteph_et::TaylorInterpolant, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number} -Compute the Lyapunov spectrum of a NEO. +Compute the Lyapunov spectrum of a NEO. -# Arguments +# Arguments -- `dynamics::Function`: dynamical model function. +- `dynamics::D`: dynamical model function. - `maxsteps::Int`: maximum number of steps for the integration. - `jd0::T`: initial Julian date. -- `tspan::T`: time span of the integration [in Julian days]. +- `tspan::T`: time span of the integration [in Julian days]. - `ss16asteph_et::TaylorInterpolant`: solar system ephemeris. - `q0::Vector{U}`: vector of initial conditions. -- `μ_ast::Vector`: vector of gravitational parameters. -- `order::Int=order`: order of the Taylor expansions to be used in the integration. +- `μ_ast::Vector`: vector of gravitational parameters. +- `order::Int=order`: order of the Taylor expansions to be used in the integration. - `abstol::T`: absolute tolerance. -- `parse_eqs::Bool`: whether to use the specialized method of `jetcoeffs` (`true`) or not. +- `parse_eqs::Bool`: whether to use the specialized method of `jetcoeffs` (`true`) or not. """ propagate_lyap -function propagate_lyap(dynamics::Function, maxsteps::Int, jd0::T, tspan::T, ss16asteph_et::TaylorInterpolant, +function propagate_lyap(dynamics::D, maxsteps::Int, jd0::T, tspan::T, ss16asteph_et::TaylorInterpolant, q0::Vector{U}; μ_ast::Vector = μ_ast343_DE430[1:end], order::Int = order, - abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number} + abstol::T = abstol, parse_eqs::Bool = true) where {T <: Real, U <: Number, D} - # Parameters for apophisinteg + # Parameters for apophisinteg _q0, _t0, _eph, _params = propagate_params(jd0, ss16asteph_et, q0; μ_ast = μ_ast, order = order, abstol = abstol) # Final time of integration (days) - _tmax = _t0 + tspan*yr - + _tmax = _t0 + tspan*yr + # Propagate orbit - @time sol = lyap_neosinteg(dynamics, _q0, _t0, _tmax, order, abstol, _eph, _params; + @time sol = lyap_neosinteg(dynamics, _q0, _t0, _tmax, order, abstol, _eph, _params; maxsteps = maxsteps, parse_eqs = parse_eqs) return sol diff --git a/test/propagation.jl b/test/propagation.jl index 030dbf72..670e0f8a 100644 --- a/test/propagation.jl +++ b/test/propagation.jl @@ -56,6 +56,7 @@ using InteractiveUtils: methodswith parse_eqs = true ) + # propagate orbit sol = NEOs.propagate( dynamics, maxsteps, @@ -137,6 +138,20 @@ using InteractiveUtils: methodswith # Earth's ephemeris eph_ea = selecteph(sseph, ea) + # warmup propagation + sol = NEOs.propagate( + dynamics, + 1, + jd0, + nyears, + sseph, + q0, + Val(true), + order = 25, + abstol = 1e-20, + parse_eqs = true + ) + # propagate orbit sol = NEOs.propagate( dynamics, From e57f43a89cc1394b0533f05f638f6fa69e78f2a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Wed, 7 Jun 2023 00:36:05 +0200 Subject: [PATCH 44/46] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 113df124..7634e331 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # NEOs.jl [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5152449.svg)](https://doi.org/10.5281/zenodo.5152449) +[![Coverage Status](https://coveralls.io/repos/github/PerezHz/NEOs.jl/badge.svg?branch=main)](https://coveralls.io/github/PerezHz/NEOs.jl?branch=main) +[![codecov](https://codecov.io/gh/PerezHz/NEOs.jl/branch/main/graph/badge.svg?token=F1IY79YP3J)](https://codecov.io/gh/PerezHz/NEOs.jl) `NEOs.jl` is a Near-Earth Object orbital propagator and fitter in Julia. `NEOs.jl` exploits jet transport techniques via From 75c987e58cca4afe5dbbb76668b7e05c5b5db622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20A=2E=20Pe=CC=81rez=20Herna=CC=81ndez?= Date: Wed, 7 Jun 2023 00:39:17 +0200 Subject: [PATCH 45/46] Update observational models --- src/observations/process_radar.jl | 41 ++++++++++++++----------------- src/observations/process_radec.jl | 24 +++++++++--------- 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/src/observations/process_radar.jl b/src/observations/process_radar.jl index 47c2dfb7..1ba3a396 100644 --- a/src/observations/process_radar.jl +++ b/src/observations/process_radar.jl @@ -240,10 +240,8 @@ function tropo_delay(r_antenna::Vector{T}, ρ_vec_ae::Vector{S}) where {T<:Numbe end @doc raw""" - compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; tord::Int = 5, niter::Int = 10, xve::TaylorInterpolant = earthposvel, - xvs::TaylorInterpolant = sunposvel, xva::TaylorInterpolant = apophisposvel197) where {T <: AbstractFloat} - compute_delay(radar::RadarJPL{T}; tord::Int = 5, niter::Int = 10, xve::TaylorInterpolant = earthposvel, - xvs::TaylorInterpolant = sunposvel, xva::TaylorInterpolant = apophisposvel197) where {T <: AbstractFloat} + compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; tord::Int = 5, niter::Int = 10, + xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} Compute Taylor series expansion of time-delay observable around echo reception time. This allows to compute dopplers via automatic differentiation using @@ -269,7 +267,7 @@ See https://doi.org/10.1086/116062. - `xva::TaylorInterpolant`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ function compute_delay(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; tord::Int = 5, niter::Int = 10, - xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph = apophisposvel197) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} + xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} # Transform receiving time from UTC to TDB seconds since j2000 et_r_secs_0 = datetime2et(t_r_utc) @@ -470,13 +468,13 @@ end @doc raw""" radar_astrometry(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, F_tx::Real; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, - xve = earthposvel, xvs = sunposvel, xva = apophisposvel197, autodiff::Bool = true) where {T <: AbstractFloat} - radar_astrometry(radar::RadarJPL{T}; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, xve = earthposvel, - xvs = sunposvel, xva = apophisposvel197, autodiff::Bool = true) where {T <: AbstractFloat} - radar_astrometry(astradarfile::String; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, xve = earthposvel, xvs = sunposvel, - xva = apophisposvel197, autodiff::Bool = true) - radar_astrometry(outfilename::String, radarobsfile::String, asteph::TaylorInterpolant, ss16asteph::TaylorInterpolant; tc::Real=1.0, autodiff::Bool=true, - tord::Int = 5, niter::Int = 10) + xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph, autodiff::Bool = true) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} + radar_astrometry(radar::RadarJPL{T}; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, xve::EarthEph = earthposvel, + xvs::SunEph = sunposvel, xva::AstEph, autodiff::Bool = true) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} + radar_astrometry(astradarfile::String; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, + xva::AstEph, autodiff::Bool = true) where {EarthEph, SunEph, AstEph} + radar_astrometry(astradardata::Vector{RadarJPL}; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, + xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph, autodiff::Bool = true) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} Return time-delay and Doppler shift. @@ -529,8 +527,7 @@ function radar_astrometry(astradarfile::String; kwargs...) return radar_astrometry(astradardata; kwargs...) end -function radar_astrometry(astradardata::Vector{RadarJPL{T}}; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, xve = earthposvel, xvs = sunposvel, - xva=apophisposvel197, autodiff::Bool=true) where {T <: AbstractFloat} +function radar_astrometry(astradardata::Vector{RadarJPL{T}}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} # UTC time of first radar observation utc1 = astradardata[1].date @@ -549,8 +546,7 @@ function radar_astrometry(astradardata::Vector{RadarJPL{T}}; tord::Int = 5, nite # Iterate over the measurements for i in eachindex(astradardata) # Compute time delay and doppler shift - vdelay[i], vdoppler[i] = radar_astrometry(astradardata[i], tord = tord, niter = niter, tc = tc, xve = xve, xvs = xvs, xva = xva, - autodiff = autodiff) + vdelay[i], vdoppler[i] = radar_astrometry(astradardata[i]; xva, kwargs...) end # Rows with time delays delay_index = map(x-> x.Δτ_units == "us", astradardata) @@ -576,7 +572,7 @@ end @doc raw""" residuals(obs::Vector{RadarJPL{T}}, niter::Int = 10; debias_table::String = "2018", - xvs::SunEph = sunposvel, xve::EarthEph = earthposvel, xva::AstEph = apophisposvel197) where {T <: AbstractFloat} + xvs = sunposvel, xve = earthposvel, xva) where {T <: AbstractFloat} Compute O-C residuals for radar astrometry, including corrections due to Earth orientation, LOD and polar motion. @@ -590,14 +586,13 @@ See also [`compute_delay`](@ref) and [`radar_astrometry`](@ref). - `tc::Real`: time offset wrt echo reception time, to compute Doppler shifts by range differences (seconds). - `autodiff::Bool`: whether to use the automatic differentiation method of [`compute_delay`](@ref) or not. - `tord::Int`: order of Taylor expansions. -- `xvs::SunEph`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xve::EarthEph`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. -- `xva::AstEph`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xvs::`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xve::`: Earth ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. +- `xva::`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ -function residuals(obs::Vector{RadarJPL{T}}; tord::Int = 5, niter::Int = 10, tc::Real = 1.0, autodiff::Bool = true, - xvs::SunEph = sunposvel, xve::EarthEph = earthposvel, xva::AstEph = apophisposvel197) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} +function residuals(obs::Vector{RadarJPL{T}}; kwargs...) where {T <: AbstractFloat} # Radar delay/Doppler astrometric data - x_jt = radar_astrometry(obs; tord = tord, niter=niter, tc=tc, autodiff = autodiff, xvs = xvs, xve = xve, xva = xva) + x_jt = radar_astrometry(obs; kwargs...) # Time-delay residuals res_τ = x_jt[2][x_jt[14]] .- x_jt[4][x_jt[14]] # Doppler-shift residuals diff --git a/src/observations/process_radec.jl b/src/observations/process_radec.jl index 27874171..448e5eb4 100644 --- a/src/observations/process_radec.jl +++ b/src/observations/process_radec.jl @@ -1,10 +1,10 @@ @doc raw""" - compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime, niter::Int = 5; - xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph = apophisposvel197) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} - compute_radec(obs::RadecMPC{T}, niter::Int = 5; xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, - xva::AstEph = apophisposvel197) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} - compute_radec(obs::Vector{RadecMPC{T}}, niter::Int=5; xve::EarthEph=earthposvel, xvs::SunEph=sunposvel, - xva::AstEph=apophisposvel197) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} + compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter::Int = 5, + xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} + compute_radec(obs::RadecMPC{T}; niter::Int = 5, xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, + xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} + compute_radec(obs::Vector{RadecMPC{T}}; niter::Int=5, xve::EarthEph=earthposvel, xvs::SunEph=sunposvel, + xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} Compute astrometric right ascension and declination (both in arcsec) for a set of MPC-formatted observations. Corrections due to Earth orientation, LOD, polar motion are considered in computations. @@ -19,7 +19,7 @@ Corrections due to Earth orientation, LOD, polar motion are considered in comput - `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ function compute_radec(observatory::ObservatoryMPC{T}, t_r_utc::DateTime; niter::Int = 5, - xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph = apophisposvel197) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} + xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, EarthEph, SunEph, AstEph} # Transform receiving time from UTC to TDB seconds since J2000 et_r_secs = datetime2et(t_r_utc) # Compute geocentric position/velocity of receiving antenna in inertial frame [km, km/s] @@ -151,7 +151,7 @@ function compute_radec(obs::RadecMPC{T}; kwargs...) where {T <: AbstractFloat} return compute_radec(obs.observatory, obs.date; kwargs...) end -function compute_radec(obs::Vector{RadecMPC{T}}; xva::AstEph=apophisposvel197, kwargs...) where {T <: AbstractFloat, AstEph} +function compute_radec(obs::Vector{RadecMPC{T}}; xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} # Number of observations n_optical_obs = length(obs) @@ -381,7 +381,7 @@ end @doc raw""" radec_astrometry(obs::Vector{RadecMPC{T}}; niter::Int = 5, debias_table::String = "2018", - xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph = apophisposvel197) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} + xve::EarthEph = earthposvel, xvs::SunEph = sunposvel, xva::AstEph) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} Compute optical astrometry, i.e. dates of observation plus observed, computed, debiasing corrections and statistical weights for right ascension and declination (in arcsec). Corrections to Earth orientation parameters provided by IERS are computed by default. @@ -403,7 +403,7 @@ See also [`compute_radec`](@ref), [`debiasing`](@ref), [`w8sveres17`](@ref) and - `xvs`: Sun ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. - `xva`: asteroid ephemeris [et seconds since J2000] -> [barycentric position in km and velocity in km/sec]. """ -function radec_astrometry(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva::AstEph=apophisposvel197, kwargs...) where {T <: AbstractFloat, AstEph} +function radec_astrometry(obs::Vector{RadecMPC{T}}; debias_table::String = "2018", xva::AstEph, kwargs...) where {T <: AbstractFloat, AstEph} # Number of observations n_optical_obs = length(obs) @@ -452,7 +452,7 @@ function radec_astrometry(obs::Vector{RadecMPC{T}}; debias_table::String = "2018 α_obs[i] = rad2arcsec(obs[i].α) * cos(obs[i].δ) # arcsec # Computed ra/dec - α_comp_as, δ_comp_as = compute_radec(obs[i]; kwargs...) + α_comp_as, δ_comp_as = compute_radec(obs[i]; xva, kwargs...) # Multiply by metric factor cos(dec) α_comp[i] = α_comp_as * cos(obs[i].δ) # arcsec δ_comp[i] = δ_comp_as # arcsec @@ -471,7 +471,7 @@ end @doc raw""" residuals(obs::Vector{RadecMPC{T}}; niter::Int = 5, debias_table::String = "2018", - xvs::SunEph = sunposvel, xve::EarthEph = earthposvel, xva::AstEph = apophisposvel197) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} + xvs::SunEph = sunposvel, xve::EarthEph = earthposvel, xva::AstEph) where {T <: AbstractFloat, SunEph, EarthEph, AstEph} Compute O-C residuals for optical astrometry. Corrections due to Earth orientation, LOD, polar motion are computed by default. From 050083e0a2c3af140b47d3fe22b58cef30be097e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20P=C3=A9rez?= Date: Wed, 7 Jun 2023 09:07:29 +0200 Subject: [PATCH 46/46] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index eeb864f4..853f2fab 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "NEOs" uuid = "b41c07a2-2abb-11e9-070a-c3c1b239e7df" authors = ["Jorge A. Pérez Hernández", "Luis Benet", "Luis Eduardo Ramírez Montoya"] -version = "0.3.1" +version = "0.4.0" [deps] Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"