Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constructors #26

Merged
merged 4 commits into from
Nov 8, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add tests and write code allowing unit conversion with pipe
  • Loading branch information
mileslucas committed Nov 6, 2019
commit 3491fee5060e23007a0b1cd14e62de781998d6d7
13 changes: 8 additions & 5 deletions src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ struct ICRSCoords{T <: AbstractFloat} <: AbstractSkyCoords
end
ICRSCoords(ra::T, dec::T) where {T <: AbstractFloat} = ICRSCoords{T}(ra, dec)
ICRSCoords(ra::Real, dec::Real) = ICRSCoords(promote(float(ra), float(dec))...)
ICRSCoords(c::AbstractSkyCoords) = convert(ICRSCoords, c)

ICRSCoords(c::T) where {T <: AbstractSkyCoords} = convert(ICRSCoords, c)
ICRSCoords{F}(c::T) where {F,T <: AbstractSkyCoords} = convert(ICRSCoords{F}, c)

"""
GalCoords(l, b)
Expand All @@ -45,7 +45,8 @@ struct GalCoords{T <: AbstractFloat} <: AbstractSkyCoords
end
GalCoords(l::T, b::T) where {T <: AbstractFloat} = GalCoords{T}(l, b)
GalCoords(l::Real, b::Real) = GalCoords(promote(float(l), float(b))...)
GalCoords(c::AbstractSkyCoords) = convert(GalCoords, c)
GalCoords(c::T) where {T <: AbstractSkyCoords} = convert(GalCoords, c)
GalCoords{F}(c::T) where {F,T <: AbstractSkyCoords} = convert(GalCoords{F}, c)

"""
FK5Coords{equinox}(ra, dec)
Expand All @@ -66,8 +67,8 @@ end
FK5Coords{e}(ra::T, dec::T) where {e,T <: AbstractFloat} = FK5Coords{e,T}(ra, dec)
FK5Coords{e}(ra::Real, dec::Real) where {e} =
FK5Coords{e}(promote(float(ra), float(dec))...)
FK5Coords{e}(c::AbstractSkyCoords) where {e} = convert(FK5Coords{e}, c)

FK5Coords{e}(c::T) where {e,T <: AbstractSkyCoords} = convert(FK5Coords{e}, c)
FK5Coords{e,F}(c::T) where {e,F,T <: AbstractSkyCoords} = convert(FK5Coords{e,F}, c)


# Scalar coordinate conversions
Expand All @@ -78,3 +79,5 @@ function Base.convert(::Type{T}, c::S) where {T <: AbstractSkyCoords,S <: Abstra
lon, lat = cart2coords(r)
T(lon, lat)
end

Base.:(==)(a::T, b::T) where {T <: AbstractSkyCoords} = lon(a) == lon(b) && lat(a) == lat(b)
83 changes: 54 additions & 29 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,35 @@ rad2arcsec(r) = 3600 * rad2deg(r)

# input coordinates
fname = joinpath(datapath, "input_coords.csv")
indata, inhdr = readdlm(fname, ','; header=true)
indata, inhdr = readdlm(fname, ','; header = true)

# Float32 has a large tolerance compared to Float64 and BigFloat, but here we
# are more interested in making sure that the infrastructure works for different
# floating types.
for (F, TOL) in ((Float32, 0.2), (Float64, 0.0001), (BigFloat, 0.0001))
println("Testing type ", F)
@testset "Testing $F" for (F, TOL) in ((Float32, 0.2), (Float64, 0.0001), (BigFloat, 0.0001))

for (insys, T) in (("icrs", ICRSCoords{F}), ("fk5j2000", FK5Coords{2000,F}),
("fk5j1975", FK5Coords{1975,F}), ("gal", GalCoords{F}))

c_in = T[T(indata[i, 1], indata[i, 2]) for i=1:size(indata,1)]
c_in = T[T(indata[i, 1], indata[i, 2]) for i = 1:size(indata, 1)]
for c in c_in
@test convert(T, c) == c
end

for (outsys, S) in (("icrs", ICRSCoords{F}), ("fk5j2000", FK5Coords{2000,F}),
("fk5j1975", FK5Coords{1975,F}), ("gal", GalCoords{F}))
(outsys == insys) && continue

c_out = S[convert(S, c) for c in c_in]

# Test pipe and constructor conversion
@test c_out == S[S(c) for c in c_in]
@test c_out == S[c |> S for c in c_in]

# Read in reference answers.
ref_fname = joinpath(datapath, "$(insys)_to_$(outsys).csv")
refdata, hdr = readdlm(ref_fname, ','; header=true)
c_ref = S[S(refdata[i, 1], refdata[i, 2]) for i=1:size(refdata,1)]
refdata, hdr = readdlm(ref_fname, ','; header = true)
c_ref = S[S(refdata[i, 1], refdata[i, 2]) for i = 1:size(refdata, 1)]

# compare
sep = separation.(c_out, c_ref)
Expand All @@ -49,28 +56,46 @@ for (F, TOL) in ((Float32, 0.2), (Float64, 0.0001), (BigFloat, 0.0001))
end

# Test separation between coordinates and conversion with mixed floating types.
c1 = ICRSCoords(ℯ, pi/2)
c5 = ICRSCoords(ℯ, 1 + pi/2)
@test separation(c1, c5) ≈ separation(c5, c1) ≈
separation(c1, convert(GalCoords, c5)) ≈
separation(convert(FK5Coords{1980}, c5), c1) ≈ 1
for T in (GalCoords, FK5Coords{2000})
c2 = convert(T{Float32}, c1)
c3 = convert(T{Float64}, c1)
c4 = convert(T{BigFloat}, c1)
@test typeof(c2) === T{Float32}
@test typeof(c3) === T{Float64}
@test typeof(c4) === T{BigFloat}
@test isapprox(lat(c2), lat(c3), rtol=sqrt(eps(Float32)))
@test isapprox(lat(c3), lat(c4), rtol=sqrt(eps(Float64)))
@test isapprox(lon(c2), lon(c3), rtol=sqrt(eps(Float32)))
@test isapprox(lon(c3), lon(c4), rtol=sqrt(eps(Float64)))
c6 = convert(T, c5)
@test separation(c3, c6) ≈ separation(c6, c3) ≈ 1
@testset "Separation" begin
c1 = ICRSCoords(ℯ, pi / 2)
c5 = ICRSCoords(ℯ, 1 + pi / 2)
@test separation(c1, c5) ≈ separation(c5, c1) ≈
separation(c1, convert(GalCoords, c5)) ≈
separation(convert(FK5Coords{1980}, c5), c1) ≈ 1
for T in (GalCoords, FK5Coords{2000})
c2 = convert(T{Float32}, c1)
c3 = convert(T{Float64}, c1)
c4 = convert(T{BigFloat}, c1)
@test typeof(c2) === T{Float32}
@test typeof(c3) === T{Float64}
@test typeof(c4) === T{BigFloat}
@test isapprox(lat(c2), lat(c3), rtol = sqrt(eps(Float32)))
@test isapprox(lat(c3), lat(c4), rtol = sqrt(eps(Float64)))
@test isapprox(lon(c2), lon(c3), rtol = sqrt(eps(Float32)))
@test isapprox(lon(c3), lon(c4), rtol = sqrt(eps(Float64)))
c6 = convert(T, c5)
@test separation(c3, c6) ≈ separation(c6, c3) ≈ 1
end
end

# Constructor of FK5Coords{1950} with non-float arguments
@test typeof(FK5Coords{1950}(1, big(2))) == FK5Coords{1950,BigFloat}

println()
println("All tests passed.")
# @testset "Pre-conversion of inputs" begin
# # Constructor of FK5Coords{1950} with non-float arguments
# @test typeof(FK5Coords{1950}(1, big(2))) == FK5Coords{1950,BigFloat}

# # Unitful
# @test ICRSCoords(20u"°", 0u"rad") == ICRSCoords(0.3490658503988659, 0.0)
# @test GalCoords(20u"°", 0u"rad") == GalCoords(0.3490658503988659, 0.0)
# @test FK5Coords{2000}(20u"°", 0u"rad") == FK5Coords{2000}(0.3490658503988659, 0.0)
# end

# @testset "Coord String" begin
# @test coord"0h0m0s" == coord"0°0'0\"" == 0.0
# @test coord"12h0m0s" ≈ coord"180°0'0\"" ≈ π
# @test coord"-12h0m0s" ≈ coord"-180°0'0\"" ≈ -π
# @test coord"+12h0m0s" ≈ coord"+180°0'0\"" ≈ π
# @test coord"18h36m56.33635s" ≈ 4.873565508047745
# @test coord"38°47'01.2802\"" ≈ 0.6769030681498798
# @test coord"- 10° 02' 10.885 \"" ≈ -0.17389837681291273
# @test coord"2 h 12 m 33.33 s" ≈ 0.5783824791568358
# @test_throws LoadError eval(:(coord"02 50 1242.444"))
# end