Saturday, August 5, 2017

Implementare CSPICE - Alcune costanti e funzioni comuni

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.bsp che recuperiamo dal sito ftp della NASA, sono i cosiddetti DAF/SPK Kernel, che contengono i coefficienti dei polinomi interpolatori usati per calcolare le posizioni di oggetti nello spazio, in particolare i pianeti. Durante la compilazione della libreria abbiamo creato anche una serie di file eseguibili che troviamo nella directory cspice/exe. Uno di questi è brief, che possiamo usare per trovare le specifiche di ognuno di questi file. Per esempio, se abbiamo scaricato de421.bsp e vogliamo sapere cosa contiene, copiamo brief nella directory test e lo lanciamo in esecuzione:

./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

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...