2

I am writing a program which goes through FITS files with photometry and looks for stars given in a .dat file. One of the steps is computing distances between two given stars using ephem.separation()

It works well. However, from time to time separation returns angles like 1389660529:33:00.8

import ephem
import math

star = ['21:45:15.00', '65:49:24.0']
first_coo = ['21:45:15.00', '65:49:24.0']

check = ephem.FixedBody()
check._ra = ephem.hours(star[0])
check._dec = ephem.degrees(star[1])
check.compute()

# star is a list with coordinates, strings in form %s:%s:%s

first = ephem.FixedBody()
first._ra = ephem.hours(first_coo[0])
first._dec = ephem.degrees(first_coo[1])
first.compute()

sep = math.degrees(float(ephem.separation(check,first)))
print sep

It occurs randomly. Have anybody encountered such behaviour?

I search for 18 stars in 212 files, which makes 3816 cycles. Might have something to do with it?

user3018591
  • 97
  • 1
  • 7
  • The `separation()` function returns the result of the C call `acos()` which, according to its manual page, is supposed to return a value within the range [0, ]. I wonder why it is returning such a huge result? Please provide your operating system and version, in case that is part of the issue; and, could you provide some code that creates two of the angles you are working with, runs `separation()` on them, and prints the result, so that I have a specific broken example to work with? Thanks! – Brandon Rhodes Nov 23 '13 at 22:25
  • OS -> Ubuntu 12.04 64bit. `check = ephem.FixedBody() check._ra = ephem.hours(star[0]) check._dec = ephem.degrees(star[1]) check.compute() star is a list with coordinates, strings in form %s:%s:%s first = ephem.FixedBody() first._ra = ephem.hours(first_coo[0]) first._dec = ephem.degrees(first_coo[1]) first.compute() sep = math.degrees(float(ephem.separation(check,first)))` – user3018591 Nov 23 '13 at 23:36
  • I've just found out its always the same angle, 1389660529:33:00.8 – user3018591 Nov 24 '13 at 00:08
  • All right, we are getting close! I have copied your code into your question so that everyone can easily read it, and have thrown in some sample data so that the code will at least run when people paste this into their editors. Only one thing is left: you need to supply actual values of a star and coordinate for which you are getting the crazy return value, since otherwise we can't guess what values might be causing this. Once real data is inserted into the code, we should easily be able to track down what is going wrong! – Brandon Rhodes Nov 24 '13 at 01:50
  • I updated the coordinates for which I get the crazy value... It's a case when they are the same. The separation angle should be 0.0, but it isn't. – user3018591 Nov 24 '13 at 09:37
  • So when you paste the above code into a fresh `.py` file, you get that ugly huge number? There must be some difference between our systems; I get the very small angle `8.53773646252e-07` which — hold on, wait, now I am getting `0.0`. Strange. But in neither case am I getting a big number. So: what version of Python and operating system are you using — maybe this has something to do with your platform or the version of C used to compile Python and PyEphem? – Brandon Rhodes Nov 24 '13 at 17:05
  • **UPDATE:** I have released a new PyEphem 3.7.5.2 that fixes this special case of comparing an angle to itself. – Brandon Rhodes Dec 21 '13 at 14:09

1 Answers1

0
UPDATE: I have released a new PyEphem 3.7.5.2 that fixes this special case of comparing an angle to itself.

Your code sample has two interesting features: first, it contains a slight bug that I thought at first might be behind the problem; and, second, I was wrong that your code was the problem because your code does indeed expose a flaw in the separation() function when it is asked how far a position is from itself!

The bug in your own code is that calling compute() and asking about .ra and .dec returns those coordinates in the coordinate system of the very moment that you are calling compute() for — so your two compute() calls are returning coordinates in two different coordinate systems that are very slightly different, and so the resulting positions cannot be meaningfully compared with separation() because separation() requires two coordinates that are in the same coordinate system.

To fix this problem, chose a single now moment to use as your equinox epoch:

now = ephem.now()
...
check.compute(epoch=now)
...
first.compute(epoch=now)

That will give you coordinates that can be meaningfully compared.

Now, on to the problem in PyEphem itself!

When presented with two copies of the same position are provided to separation() it goes ahead and tries to find a distance between them anyway, and winds up doing a calculation that amounts to:

acos(sin(angle) ** 2.0 + cos(angle) ** 2.0)

which should remind us of the standard Euclidean distance formula but with an acos() around it instead of a sqrt(). The problem is that while in theory the value inside of the parens should always be 1.0, the rounding inside of IEEE floating point math does not always produce squares that sum to exactly 1.0. Instead, it sometimes produces a value that is a bit high or a bit low.

When the result is a bit below 1.0, separation() will return a very slight separation for the coordinates, even though they are actually “the same coordinate.”

When the result exceeds 1.0 by a little bit, separation() will return not-a-number (nan) on my system — and, I will bet, returns that huge return value that you are seeing printed out on yours — because cos() cannot, by definition, return a number greater than 1.0, so there is no answer acos() can return when asked “what angle returns this value that is greater than one?”

I have created a bug report in GitHub and will fix this for the next version of PyEphem:

https://github.com/brandon-rhodes/pyephem/issues/31

Meanwhile, your code will have to avoid calling separation() for two positions that are actually the same position — could you use an if statement with two == comparisons between ra and dec to detect such cases and just use the value 0.0 for the separation instead?

Brandon Rhodes
  • 83,755
  • 16
  • 106
  • 147
  • I have already altered the code for the cases of equal coordinates. However, the formula used to compute angular distance isn't quite right I think. Shouldn't it use this one instead? `cos(A) = sin(d1)sin(d2) + cos(d1)cos(d2)cos(ra1-ra2)` – user3018591 Nov 24 '13 at 23:56
  • Yes, that is the formula; but if `d1 == d2` and `r1 == r2` then the `cos(ra1-ra2)` disappears since `cos(0.0) == 1.0`. – Brandon Rhodes Nov 25 '13 at 03:38