5
#!/bin/perl 

use Inline Python; 

$s = new Sun(); 
print "SUN: $s\n"; 
$m = new Moon(); 

__END__ 
__Python__ 
from ephem import Sun as Sun; 
from ephem import Moon as Moon; 

The code above yields:

SUN: <Sun "Sun" at 0x9ef6f14>
Can't bless non-reference value at /usr/local/lib/perl5/site_perl/5.10.0/i386-linux-thread-multi/Inline/Python.pm line 317.

What's wrong? I've tried this with many other objects (eg:

from ephem import Observer as Observer;

and then

$o= new Observer();

in the body of my code) and it works fine for everything I've tried EXCEPT Moon.

EDIT (probably useless information):

In https://github.com/brandon-rhodes/pyephem/tree/master/libastro-3.7.5 :

  • The routines for calculating Sun, Mercury, Venus, Mars (the ones that work fine) are done in vsop87.c, function vsop87()

  • The routines for calculating Jupiter, Saturn, etc (the ones that don't work) are done in chap95.c, function chap95()

  • vsop87() "returns" an array of 6 doubles, which appear to be some sort of spherical coordinates.

  • chap95() "returns" an array of 6 doubles, which appear to be Cartesian coordinates, ie, rectangular and NOT spherical.

  • planpos() in plans.c calls one of the two functions above, depending on which planet you choose. What's odd is that planpos() treats the function results the same (sort of), even though they return very different things.

  • After planpos(), all planets are treated the same. planpos() is called by plans() (also in plans.c), which is in turn called by obj_planet() in circum.c which is then called by obj_cir() also in circum.c

  • obj_planet() and obj_cir() define the planet. Since planets are treated the same after planpos(), there should be no difference between them.

Lok Jun
  • 1,315
  • 2
  • 9
  • 16
  • Jupiter and Saturn also do not work, but Mercury and Venus work. The three non-working are somehow special-cased in the python code. – Slaven Rezic Nov 27 '13 at 07:01
  • I also tried Mars earlier, and it works. I don't know if there IS any Python code... I think the Python stuff is just bindings to a C library, libastro. –  Nov 27 '13 at 16:05
  • There's some glue python code, on my system in `/usr/local/lib/python2.7/site-packages/ephem/__init__.py`. I see special handling for Moon, Jupiter, and Saturn there. The comment says "We now replace two of the classes we have just created, because _libastro actually provides separate types for two of the bodies." – Slaven Rezic Nov 28 '13 at 01:16
  • @SlavenRezic You are correct. Sadly, "from ephem import _libastro.Moon as Moon;" doesn't work either. –  Nov 28 '13 at 02:49

1 Answers1

0

It is indeed the different handling for the Moon, Jupiter and Saturn bodies, as pointed out by Slaven in the comments. In fact, you're running into the Python 2 issue that there is a difference between types and classes. I can't give you the details, but there is quite a bit of material on the subject.

Suffice to say, that the Python wrapper provided by PyEphem turns the bodies into a proper class, which Python::Inline can handle. The Python-C wrapper, _libastro, provides types instead, and thus setting Moon to _libastro.Moon makes Moon a type instead of a class. Why Python::Inline can deal with classes and not types, I don't know.

This, however, provides enough information for a work-around: turn ephem.Moon into a class. Thus, the following may work:

#!/usr/bin/env perl

use Inline Python; 

$s = new Sun(); 
print "SUN: $s\n"; 
$m = new Moon(); 
print "Moon: $m\n";

__END__ 
__Python__ 
from ephem import Sun
from ephem import Moon
class Moon(Moon):
    pass

which for me results in:

SUN: <Sun "Sun" at 0x1f450b0>
Moon: <Moon "Moon" at 0x20eec50>

You can apply the same trick to Saturn and Jupiter of course.

(I've "Pythonized" the import statements a bit: no need for as or semi-colons.)

In case you'd like to verify that the Moon is still a special body even after turning it into a class, try to use on of its special attributes, for example libration_lat:

$m->compute()
$mllat = $m->{libration_lat};
print "Moon: ${mllat}\n";

Moon: 5:50:29.6

which will fail for any other type such as the Sun.

(I found these special attributes in test_bodies.py in the PyEphem package, though I presume these are documented as well. In case you'd like to test for Saturn and Jupiter, you can find them there.)

Community
  • 1
  • 1
  • Awesome, thanks! In the interim, I discovered Skyfield... now, how to use that in Perl, hmmm. –  Feb 10 '14 at 22:39