Tuesday, February 4, 2014

Le Swiss Ephemeris portate in Python

Le Swiss Ephemeris, routine di calcolo astronomico di alta precisione, verranno utilizzate in questo progetto solo per alcune funzioni essenziali, non utilizzando i metodi di interpolazione delle effemeridi, e limitatamente al sistema di domificazione più diffuso (Placidus) di cui è nota l'impossibilità di utilizzo per latitudini polari a causa della degenerazione del metodo stesso. Una versione per Python in ambiente linux è gia disponibile sotto il nome di pyswisseph.
Le librerie pyswisseph sono molto facili da installare usando alcuni semplici comandi.
Li riassumo brevemente nel seguito, per utenti Ubuntu come il sottoscritto; credo sia altrettanto facile importarle in altre distribuzioni. Per Windows si possono ottenere dal curatore delle librerie stesse "for a small fee", oppure possono essere compilate dai sorgenti, più avanti faremo qualche tentativo.
In breve, per installare le pyswisseph bisogna:
caricare le python-developer  e pip con il comando :

sudo apt-get install python-dev python-pip

pip è un package realizzzato per installare i moduli presenti nel repository principale dei python developers: Pypi
quindi bisogna installare la libreria pyswisseph:

sudo pip install pyswisseph

a questo punto si possono usare le librerie nel vostro codice python semplicemente richiamandole con l'istruzione:

import swisseph 

oppure, in alternativa:

from swisseph import *

la seconda forma è, di regola, sconsigliata perchè rischia di contaminare il namespace principale con variabili e nomi di funzione che si possono sovrapporre ad omonimi già esistenti. Personalmente preferisco usare sempre il primo metodo, anche se occorre digitare ogni volta il nome del pacchetto principale, seguito da un punto, prima delle funzioni chiamate.

Di seguito dimostro, con poche righe di codice e molti commenti, come il cuore del nostro progetto si riduca a poche righe, naturalmente senza una gestione automatica della localizzazione, della grafica e della simbologia planetaria. Tuttavia si vede facilmente come una buona libreria risolva gran parte dei problemi legati alla stesura di codice. Il codice, così com'è, può essere copiato in un file astro.py ed eseguito direttamente tramite l'interprete python.

# -*- coding: utf-8 -*-
import swisseph
# input dati essenziali, ora espressa in UTC, tempo coordinato universale
# (sostanzialmente l'ora di Greenwich), le longitudini orientali sono positive,
# quelle ad Ovest di Greenwich sono negative
anno = 1990
mese = 7
giorno = 23
ora = 19
minuto = 10
latitudine = 45.00
longitudine = 11.00
# chiamata alla funzione swisseph._julday, che restituisce il giorno giuliano standard
# riferito alla data inputata (l'underscore prima del nome è intenzionale,
# identifica una funzione differente da swisseph.julday)
giorno_giuliano=swisseph._julday(anno, mese, giorno, ora, minuto)
# chiamata alla funzione houses che restituisce una tupla di tuple
# la longitudine di ogni casa si trova facilmente con gli indici:
# case[0][0], case [0][1] e così via fino alla dodicesima casa[0][11]
case=swisseph.houses(giorno_giuliano, latitudine, longitudine)
# chiamata alla funzione calc, che accetta come input il giorno giuliano
# precedentemente trovato e un indice che individua il pianeta:
# 0=sole, 1=luna, 2=mercurio, 3=venere, 4=marte, 5=giove, 6=saturno
# 7=urano, 8=nettuno, 9=plutone, 10=nodo lunare medio, 11= nodo lunare vero
# e una serie di altri corpi celesti che non consideriamo.
# Per facilità e rapidità di scrittura utilizzo una list comprehension per
# indicizzare i pianeti richiesti. 
long_planet = [swisseph.calc(giorno_giuliano, x) for x in xrange(0,12)]

print "il giorno giuliano è:", giorno_giuliano
for i in range(0,12):
    print swisseph.get_planet_name(i), long_planet[i][0]
for i in range(0,12):
    print "cuspide ",i+1,"° casa:",case[0][i]

L'output è il seguente:

il giorno giuliano è: 2448096.29861
Sun 120.668415422
Moon 142.547706141
Mercury 141.295122231
Venus 94.3882989781
Mars 37.4190095096
Jupiter 114.409427893
Saturn 291.353521287
Uranus 276.657709825
Neptune 282.705341008
Pluto 224.96999813
mean Node 307.670417261
true Node 307.261137012
cuspide  1 ° casa: 308.094747498
cuspide  2 ° casa: 359.633528903
cuspide  3 ° casa: 36.8373098779
cuspide  4 ° casa: 61.8615329935
cuspide  5 ° casa: 82.0092465108
cuspide  6 ° casa: 102.058362387
cuspide  7 ° casa: 128.094747498
cuspide  8 ° casa: 179.633528903
cuspide  9 ° casa: 216.837309878
cuspide  10 ° casa: 241.861532994
cuspide  11 ° casa: 262.009246511
cuspide  12 ° casa: 282.058362387

nel prossimo post mostrerò come incasellare i risultati, resi più comprensibili, in una piccola interfaccia grafica 

4 comments:

  1. Salve Domenico, partendo dal presupposto che non sono un astronomo/programmatore ma cerco di studiare entrambi, sto cercando la possibilità di realizzare un piccolo script in python che mi permetta di calcolare la posizione di un pianeta heliocentrico o geocentrico. Attualmente utilizzo software esterni ma avrei bisogno di realizzare un piccolo programma. Ho installato pyephemeris ma riesco a visualizzare solo il movimento heliocentrico e non riesco a capire come fare quello geocentrico.
    Altra cosa, poiché sto studiando i cicli avrei la necessità di calcolare quanti gradi in totale si è mosso un pianeta oltre i 360 del cerchio. qualche idea?
    grazie
    Stefano

    ReplyDelete
  2. Ciao Stefano, benvenuto. Circa la tua prima domanda, se hai installato pyephem di Brandon Rhodes, c'è una Quick Reference alla pagina http://rhodesmill.org/pyephem/quick.html che ti fornisce le definizioni per vari tipi di coordinate, equatoriali ed eclittiche, geocentriche ed eliocentriche. Se segui gli esempio vedrai che il loro utilizzo è molto semplice. Dai un'occhiata anche a Skyfield, sempre di Brandon Rhodes, che è scritta interamente in Python e costituisce un progetto ancora più avanzato. Se hai installato le Swiss Ephemeris puoi avere (in linguaggio C, a meno che non vuoi divertiti a usare le estensioni C per Python o a utilizzare ctypes) le coordinate nei due sistemi di riferimento settando uno specifico flag. Dalla documentazione di Swiss Ephemeris:
    c. Heliocentric positions
    To compute a heliocentric position, add SEFLG_HELCTR.
    A heliocentric position can be computed for all planets including the moon.

    Per la riduzione delle posizioni angolari al cerchio fondamentale puoi, banalmente, usare il modulo a 360 della quantità di partenza, esempio:
    434.45 % 360.
    > 74.44999999999999
    Funziona anche con angoli negativi:

    -10 % 360
    > 350

    Fai qualche prova, non esitare a scrivere di nuovo se hai problemi.

    ReplyDelete
  3. Grazie Domenico, ora verifico nel sito di Rhodes quanto mi dici e ti farò sapere. Per il resto , integrare c in python , ho molta difficoltà non essendo io programmatore (sto studiando python per realizzare questi script o meglio tentare..). Per il questione dei 360 gradi, la soluzione proposta è funzionale ma il modulo pyephem mi indicherebbe eventualmente quanti gradi in totale si è mosso un pianeta, che tu sappia posso calcolare anche i nodi lunari?
    Al momento grazie, ma credo ci risentiamo presto per l'esito o se ho difficoltà di comprensione.
    Un saluto
    Stefano

    ReplyDelete
    Replies
    1. Ciao Stefano, scusa per la latenza, sono stato via qualche settimana. Per la progressione in gradi di un pianeta, puoi calcolare la distanza angolare tra punto d'inizio e punto d'arrivo. La longitudine del nodo lunare medio e vero puoi calcolarla con le formule di Jean Meeus - Astronomical Algorithms 2nd Ed. pagg 343-344. Se non hai il testo te ne faccio un estratto. Scrivimi pure all'indirizzo email indicato nel primo post di questo blog

      Delete

How to create a virtual linux machine with qemu under Debian or Ubuntu with near native graphics performance

It's been a long time since my latest post. I know, I'm lazy. But every now and then I like to publish something that other people c...