-
Notifications
You must be signed in to change notification settings - Fork 21
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
Add precess_cd function #16
Conversation
*TODO.md: Remove 'precess_cd' from list. *docs/src/ref.md: Add "precess_cd" entry to the manual. *src/utils.jl: Add precess_cd entry to "utils". *src/precess_cd.jl: Contains code of precess_cd function. *test/util-tests.jl: Include tests for precess_cd.
Codecov Report
@@ Coverage Diff @@
## master #16 +/- ##
==========================================
- Coverage 99.71% 99.54% -0.18%
==========================================
Files 61 62 +1
Lines 1055 1095 +40
==========================================
+ Hits 1052 1090 +38
- Misses 3 5 +2
Continue to review full report at Codecov.
|
src/precess_cd.jl
Outdated
function _precess_cd{T<:AbstractFloat}(cd::Matrix{T}, epoch1::T, epoch2::T, crval_old::Vector{T}, | ||
crval_new::Vector{T}, FK4::Bool) | ||
crvalold = deg2rad.(crval_old) | ||
crvalnew = deg2rad.(crval_new) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Julia sind
and cosd
functions that allows you to avoid defining crvalold
and crvalnew
.
src/precess_cd.jl
Outdated
c = t*(20043.109 - st*(85.33 + st*0.217) + t*(-42.665 - st*0.217 - t*41.8))/3600 | ||
end | ||
pole_ra = 0 | ||
pole_dec = 90 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pole_ra
and pole_dec
are type-unstable! Use
pole_ra = zero(T)
pole_dec = one(T) * 90
instead ;-)
src/precess_cd.jl
Outdated
pole_ra, pole_dec = precess(pole_ra, pole_dec, epoch1, epoch2, FK4=FK4) | ||
end | ||
sind1, sind2 = sin.([crvalold[2], crvalnew[2]]) | ||
cosd1, cosd2 = cos.([crvalold[2], crvalnew[2]]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This writing is concise, but you're also allocating useless arrays. You can simply do
sind1 = sind(crval_old[2])
sind2 = ...
(remember the comment above about sind
and cosd
)
src/precess_cd.jl
Outdated
sinra = sin(crvalnew[1] - deg2rad.(pole_ra)) | ||
cosfi = (cos(c) - sind1*sind2)/(cosd1*cosd2) | ||
sinfi = (abs(sin(c))* sinra)/cosd1 | ||
r = [[cosfi -sinfi]; [sinfi cosfi]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be simplified to
r = [cosfi -sinfi; sinfi cosfi]
which is also much faster and allocates a single array, instead of 3.
src/precess_cd.jl
Outdated
@@ -0,0 +1,78 @@ | |||
# This file is a part of AstroLib.jl. License is MIT "Expat". | |||
|
|||
function _precess_cd{T<:AbstractFloat}(cd::Matrix{T}, epoch1::T, epoch2::T, crval_old::Vector{T}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For more generality, use AbstractMatrix
and AbstractVector
in place of Matrix
and Vector
;-)
src/precess_cd.jl
Outdated
### Example ### | ||
|
||
```julia | ||
julia> precess_cd([[20 60]; [45 45]], 1950, 2000, [34, 58], [12, 83]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[[20 60]; [45 45]]
can be simplified to [20 60; 45 45]
. Also in tests.
src/precess_cd.jl
Outdated
This function should not be used for values more than 2.5 centuries from the year 1900. | ||
This function calls [precess](@ref) and [bprecess](@ref). | ||
""" | ||
precess_cd{R<:Real}(cd::Matrix{R}, epoch1::Real, epoch2::Real, crval_old::Vector{R}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like above, for more generality use AbstractMatrix
and AbstractVector
in place of Matrix
and Vector
. In addition, here we're not interested in annotating the R
type so exploiting new syntax you can simply write
precess_cd(cd::AbstractMatrix{<:Real}, epoch1::Real, epoch2::Real, crval_old::AbstractVector{<:Real},
crval_new::AbstractVector{<:Real}, FK4::Bool=false) =
This couldn't be done in previous Julia <= 0.5. Have a look at the third point of "New type system capabilities" at https://github.com/JuliaLang/julia/blob/release-0.6/NEWS.md#new-language-features
src/precess_cd.jl
Outdated
cosfi = (cos(c) - sind1*sind2)/(cosd1*cosd2) | ||
sinfi = (abs(sin(c))* sinra)/cosd1 | ||
r = [[cosfi -sinfi]; [sinfi cosfi]] | ||
cd = cd * r |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pay attention here! You're mutating the input cd
array. This may a good idea, but if you do so, you should rename the function to precess_cd!
(and document that the input array is mutated), because the exclamation mark appended to function name is used to denote a mutating function. Furthermore, with improved loop fusion this could be better written as cd .= cd * r
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a second thought, I think that's probably better not to mutate the input array. Thus, I suggest to delete the assignment cd = ...
and simply return cd * r
(but also look at the order of operands, I'm not sure it's correct).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the record, this assignment does not mutate the input array. It first creates a new array cd * r
then assigns the value to the identifier cd
. The identifier cd
no longer points to the input array, which is unmodified.
But yeah, simply return cd * r
would be good here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uhm, you're right! I was doing tests and noted that the input cd
matrix was changing, but probably I had replaced the line with cd .= cd * r
, which does mutate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In precess_cd.pro, the order of operands is r # cd (r * cd). However, from the IDL documentation, the matrix multiplication in IDL is done by multiplying the columns of the first array by the rows of the second array. So I reversed the the operands to make it a normal matrix multiplication.
test/utils-tests.jl
Outdated
@@ -441,6 +441,22 @@ let | |||
@test dec2 ≈ [-56.87186126487889] | |||
end | |||
|
|||
# Test precess_cd | |||
@testset "precess_cd" begin | |||
@test precess_cd([[30 60]; [60 90]], 1950, 2000, [13, 8], [43, 23]) ≈ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you compare the results of these tests with IDL AstroLib?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, haven't been able to run IDL on my distro till now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check out http://gnudatalanguage.sourceforge.net/ then, most AstroLib procedures work in GDL ;-)
src/precess_cd.jl
Outdated
sinra = sind(crval_new[1] - pole_ra) | ||
cosfi = (cos(c) - sind1*sind2)/(cosd1*cosd2) | ||
sinfi = (abs(sin(c))* sinra)/cosd1 | ||
r = [cosfi sinfi; -sinfi cosfi] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had transposed this r = [cosfi -sinfi; sinfi cosfi
] because I initially wanted to keep operands sequence as r * cd, but then I changed my mind about the sequence and forgot to rectify the transposing. Corrected.
src/precess_cd.jl
Outdated
|
||
### Arguments ### | ||
|
||
* `cd`: 2 x 2 coordinate description matrix in degrees or radians |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that the matrix has to be in degrees. I think that the original description in inaccurate, they also say the matrix is altered to match the units of input matrix, but they don't do so.
src/precess_cd.jl
Outdated
else | ||
pole_ra, pole_dec = precess(pole_ra, pole_dec, epoch1, epoch2, FK4=FK4) | ||
end | ||
sind1, sind2 = sind.([crval_old[2], crval_new[2]]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use the arrays here ;-) If you still want to have two calculation in one line you can do
sind1, sind2 = sind(crval_old[2]), sind(crval_new[2])
...
but I don't think you can gain much with respect to
sind1 = sind(crval_old[2])
sind2 = sind(crval_new[2])
...
That's up to you
src/precess_cd.jl
Outdated
|
||
function _precess_cd{T<:AbstractFloat}(cd::AbstractMatrix{T}, epoch1::T, epoch2::T, crval_old::AbstractVector{T}, | ||
crval_new::AbstractVector{T}, FK4::Bool) | ||
t = deg2rad((epoch2 - epoch1)*0.001) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that you shouldn't call deg2rad
here, t
isn't simply a global multiplicative factor in definition of c
, which is rather a third-order polynomial in t
.
src/precess_cd.jl
Outdated
|
||
if FK4 | ||
st = (epoch1 - 1900)*0.001 | ||
c = t*(20046.85 - st*(85.33 + st*0.37) + t*(-42.67 - st*0.37 - t*41.8))/3600 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove division by 3600 and wrap the whole right-hand-side with sec2rad
(this is an AstroLib.jl's function).
src/precess_cd.jl
Outdated
c = t*(20043.109 - st*(85.33 + st*0.217) + t*(-42.665 - st*0.217 - t*41.8))/3600 | ||
end | ||
pole_ra = zero(T) | ||
pole_dec = one(T)*90 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I told you to use one(T) * 90
, but T(90)
is actually better. Sorry for the wrong suggestion before.
src/precess_cd.jl
Outdated
c = t*(20046.85 - st*(85.33 + st*0.37) + t*(-42.67 - st*0.37 - t*41.8))/3600 | ||
else | ||
st = (epoch1 - 2000)*0.001 | ||
c = t*(20043.109 - st*(85.33 + st*0.217) + t*(-42.665 - st*0.217 - t*41.8))/3600 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as at line 9.
Test cases values found to be in an acceptable range with those received from precess_cd.pro (using GDL - GNU Data Language [Version 0.9.4])
src/precess_cd.jl
Outdated
c = sec2rad(t*(20043.109 - st*(85.33 + st*0.217) + t*(-42.665 - st*0.217 - t*41.8))) | ||
end | ||
pole_ra = zero(T) | ||
pole_dec = one(90) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
T(90)
, not one(90)
:-) (you have to adjust the example and tests)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops! Fixed now
* Fixed silly mistake * Updated example and tests
5107.504395433958 6887.55936949333 ] | ||
@test precess_cd([30.0 28.967; 60.45 90.65], 2000, 1975, [13, 10.658], [35.54, 67], true) ≈ | ||
[64.78429186351575 62.637156996728194 ; | ||
130.49379143419722 195.9699513801844 ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Were these values generated by running the Julia code or by the IDL version? I think we're really going to want to have tests against the IDL version output. But at the very least, there should be a comment here explaining where the "truth" values come from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I compared some of the results with IDL AstroLib. There's a difference on the leas significant digits, but it happens the same with bprecess
.
I don't think it's a good idea to always compare with results from IDL AstroLib, there are often 32- and 64-bit floating point numbers mixed together, so that they're often numerically unreliable if one expects full 64-bit accuracy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One could then just decrease the required precision for isapprox
, right? I think a test against an independent implementation is more valuable than a test of this implementation against itself.
Or we could have both tests, or maybe just put the IDL results in a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One could then just decrease the required precision for
isapprox
, right?
Yes, and for the specific case probably this isn't even needed, because rtol
defaults to sqrt(eps(T))
(pretty high, IMHO) and atol
to 0, I think the results will be well consistent within 1 part in ~10^8.
I think a test against an independent implementation is more valuable than a test of this implementation against itself.
If you don't know the "truth", testing an implementation against itself doesn't ensure the code is doing the Right Thing, but at least checks that nothing will be broken by future changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or we could have both tests, or maybe just put the IDL results in a comment.
Commenting the IDL results seems doable. I could work on it during and after the missing astronomical routines are done.
*TODO.md: Remove 'precess_cd' from list.
*docs/src/ref.md: Add "precess_cd" entry to the manual.
*src/utils.jl: Add precess_cd entry to "utils".
*src/precess_cd.jl: Contains code of precess_cd function.
*test/util-tests.jl: Include tests for precess_cd.