Riprendo a scrivere il mio blog, anche se con un po' di fatica, dopo molti mesi di assenza. Ho accantonato il progetto di conversione tra i formati SVG e Tk perchè si tratta di un progetto impegnativo e non ho più avuto il tempo di stargli dietro. Lo riprendero' appena avro' di nuovo voglia e tempo di farlo.
Ho invece lasciato un po' in sospeso la parte dedicata ai riferimenti temporali e geografici del l'ora, fondamentali per il corretto calcolo della domificazione, cioè dell'Ascendente e del Medio Cielo. Mi riprometto di continuare quanto già iniziato in precedenza con il database delle località e di parlare un po' del tempo nei suoi aspetti convenzionali, cioè il tempo degli orologi rispetto al tempo terrestre, i fusi orari e i Daylight Savings, che in italiano chiamiamo ora legale, e la libreria tz di Python che consente di accedere velocemente alla storia del tempo nei vari paesi del mondo.
Prima di procedere oltre vorrei accennare ad un problema che ha a che fare con i metodi di computo della posizione dei corpi celesti e i diversi sistemi di coordinate. Pur avendo finora usato le swiss ephemerides nella versione di libreria Python Pyswisseph, credo che sia utile parlare dei metodi astronomici di calcolo e di come si puo' costruire una libreria ex novo.
Le funzioni trigonometriche sono disponibili in Python attraverso la libreria math. Per chiamarla nel nostro codice sarà sufficiente un'operazione di import:
import math
Utilizzando il metodo dir(math) disporremo dell'intero set di funzioni matematiche, alcune delle quali goniometriche, e di due costanti: pi greco e numero e.
>>> dir(math) ['__doc__', '__name__', '__package__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'hypot', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc'] >>>
Ogni funzione sarà accessibile richiamando nel codice il package math seguito da un punto e dalla funzione desiderata.
>>> print math.pi 3.14159265359 >>> print math.e 2.71828182846 >>> print math.sin(math.pi/6) 0.5 >>>
Nel calcolo astronomico si utilizza comunemente il formato gradi/minuti/secondi o gradi e frazioni di grado anzichè i radianti come normalmente usati in trigonometria. La conversione è semplice: 180° corrispondono a pi radianti, per cui un modo per usare nativamente funzioni goniometriche di grado anzichè di radiante consiste nel definire, nel namespace principale o in un modulo, delle nuove funzioni dedicate:
def sin(x): return math.sin(math.radians(x))
Quindi se chiamiamo sin(30) anziché math.sin(math.pi/6) otterremo lo stesso risultato ma potremo utilizzare le formule che normalmente usano gli astronomi.
La soluzione proposta è in assoluto la più semplice. Un'alternativa possibile è l'uso dei decoratori:
import math def deg(func): def wrapper(x): return func(math.radians(x)) return wrapper @deg def sin(x): return math.sin(x) @deg def cos(x): return math.cos(x) print sin(30) print cos(30) >>> 0.5 0.866025403784 >>>
In questo secondo caso si usa il decoratore per modificare la variabile argomento prima di applicare la funzione goniometrica, non è l'esempio più felice di uso dei decoratori, ha solo, evidentemente, una funzione dimostrativa.
Terza possibilità: usare i metodi getattr e setattr per generare le nuove funzioni goniometriche nello spazio globale:
import math def deg(func): def wrapper(x): return func(math.radians(x)) return wrapper for i in ("sin", "cos", "tan"): globals()[i]=deg(getattr(math,i)) >>> dir() ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'cos', 'deg', 'i', 'math', 'sin', 'tan'] >>> globals() {'cos': <function wrapper at 0x7fbbc1780938>, '__builtins__': <module '__builtin__' (built-in)>, '__file__': '/home/mint/prova.py', '__package__': None, 'i': 'tan', '__name__': '__main__', 'tan': <function wrapper at 0x7fbbc17809b0>, 'sin': <function wrapper at 0x7fbbc17802a8>, '__doc__': None, 'math': <module 'math' (built-in)>, 'deg': <function deg at 0x7fbbc627c6e0>} >>> sin(30) 0.49999999999999994 >>> cos(30) 0.8660254037844387 >>>
Va da sè che le possibilità offerte dal linguaggio Python sono tante, ma atteniamoci alla metodologia più semplice, che è quella illustrata per prima. Nei prossimi post inizieremo a scrivere una nuova libreria di calcolo astronomico, in cui proporremo delle formule di calcolo approssimato, ma sufficiente per molti dei nostri scopi.
No comments:
Post a Comment