Ora che abbiamo creato una libreria dinamica, è necessario creare l'interfaccia per il linguaggio Python. Il modulo ctypes della libreria standard è il metodo che prediligo, ma ce ne sono altri:
- SWIG, per esempio, utilizzabile con più linguaggi di programmazione
- le Python/C API, che consentono di scrivere codice python dentro un sorgente C (le trovo piuttosto scomode da usare)
- Cython, che è un compilatore statico per Python e per un linguaggio proprio derivato da Pyrex, molto più user friendly delle Python/C API
Io perferisco ctypes perchè diretto e relativamente facile da usare, come vi dimostrero' a breve.
Naturalmente qualcuno potrebbe obiettare che, avendo delle librerie SPICE scritte in C, tanto vale usare il C. Il problema è che C va bene per scrivere routine e libreria, ma è molto complesso da utilizzare in ambiente grafico e molto meno produttivo di Python. Inoltre il debug di C può essere molto più complicato.
Iniziamo dai collegamenti fondamentali.
Linking della libreria dinamica cspice
La volta scorsa abbiamo creato una shared library che abbiamo chiamato libcspice.so, equivalente in ambiente windows di una dll. Creiamo una directory testSPICE, che useremo per lo sviluppo del codice sorgente.
Oltre al file libcspice.so, copiamo nella directory uno o più file de
./brief de421.bsp
L'output del programma sarà il seguente:
BRIEF -- Version 4.0.0, September 8, 2010 -- Toolkit Version N0066
Summary for: de421.bsp
Bodies: MERCURY BARYCENTER (1) SATURN BARYCENTER (6) MERCURY (199)
VENUS BARYCENTER (2) URANUS BARYCENTER (7) VENUS (299)
EARTH BARYCENTER (3) NEPTUNE BARYCENTER (8) MOON (301)
MARS BARYCENTER (4) PLUTO BARYCENTER (9) EARTH (399)
JUPITER BARYCENTER (5) SUN (10) MARS (499)
Start of Interval (ET) End of Interval (ET)
----------------------------- -----------------------------
1899 JUL 29 00:00:00.000 2053 OCT 09 00:00:00.000
I corpi celesti di cui è possibile avere un'effemeride sono i pianeti o i loro baricentri, il sole, la terra e la luna. Tra parentesi sono indicati i codici NAIF corrispondenti. L'ultima riga contiene gli estremi temporali, in questo caso si va dal 29 luglio 1899 00:00:00 Ephemeris Time al 9 ottobre 2053 00:00:00. Se vogliamo fare ricerche storiche più lontane nel tempo dobbiamo caricare un file effemeride più grande e quindi necessariamente più voluminoso. Il sito della NASA contiene molte informazioni, tutorial e letture tecniche per capire come si usano, come si costruiscono, come si importano ed esportano i file SPK e come è possibile modificarli, per esempio per creane un estratto e salvarlo in un nuovo file. Le utilità della sottodirectory exe sono utili anche a questo scopo
La prima cosa che dobbiamo fare è creare un modulo che useremo nel seguito per creare i nostri sorgenti python.
Possiamo aprire il nostro editor Python (idle, Wingware, Geany, PyCharm sono i più diffusi in ambiente Ubuntu/Mint), e cominciare a buttare giù qualcosa.
#!/usr/bin/env python import ctypes as ct from tools import *
Il file tools.py è quello che ho creato due post addietro, contiene un po' di funzioni per lavorare con gradi e radianti, funzioni di calendario ecc. Se tornate indietro nel blog trovate tutto fatto. Ricordatevi di mette nella cartella un file vuoto chiamato __init__.py, che serve a considerare i file contenenti le funzioni di utilità come moduli.
Adesso generiamo il link alla libreria libcspice.so, che abbiamo opportunamente messo nella directory.
ct.shared_lib = ct.CDLL('./libcspice.so')
Da questo momento in poi ct.shared_lib è l'anello di congiunzione tra Python e C. A questa funzione collegheremo tutte le funzioni della libreria cspice, man mano che ci serviranno.
Inziamo da alcune costanti:
SpiceDouble pi_c ( void ) SpiceDouble dpr_c ( void ) SpiceDouble spd_c ( void )
la prima è semplicemente il valore di pi greco, la seconda è il coefficiente di conversione radianti->gradi, la terza è il numero di secondi trascorsi dall'epoca J2000 (1° gennaio 2000, tempo delle effemeridi) in un giorno. Per usare queste costanti dobbiamo creare l'equivalente in python.
_spd_c = ct.shared_lib.spd_c _pi_c = ct.shared_lib.pi_c _dpr_c = ct.shared_lib.dpr_c
Ho usato l'underscore iniziale perchè riservo il nome in piano alla funzione python che scrivero' successivamente.
Creiamo le funzioni proprie in Python:
def spd_c(): _spd_c.restype = ct.c_double return _spd_c() def pi_c(): _pi_c.restype = ct.c_double return _pi_c() def dpr_c(): _dpr_c.restype = ct.c_double return _dpr_c()
Fin qui è tutto molto semplice: dalla definizione C delle costanti desumo che non ricevono parametri di input(per forza, sono costanti) e restituiscono invece un valore SpiceDouble, che corrisponde ad un double di python. Per cui ognuna di queste costanti è chiamata dal codice Python come funzionePython, che gestisce all'interno la funzioneC con underscore e la restituisce con un return _funzioneC.
Mi fermo qui con questo post, nel prossimo continuiamo l'implentazione e facciamo qualche prova di collaudo. A presto.
No comments:
Post a Comment