Wednesday, December 8, 2021

Creating and using a dynamic library from JPL toolkit

Generating a dynamic library

In a previous post I showed how to generate a dynamic library from jpl toolkit, for linux systems (libcspice.so) and for Windows (libcspice.dll).

Before we proceed to the compilation of the library in the Termux environment, let's talk of the programs that we have just compiled from sources launching the script importCSpice.csh.

Open Termux in your phone and activate ssh:

sshd (and press Enter, from now on I take it for granted)

In your PC open your terminal emulator (cmd on Windows, gnome-terminal or whatever in Linux) and type:

ssh u0_a119@192.168.1.120 -p 8022 (use your own coordinates, this is an example, see previous post)

when you are in, type:

~ $ ls -l
total 107956
drwx------ 9 u0_a119 u0_a119      4096 Apr  8  2017 cspice
-rw------- 1 u0_a119 u0_a119 110530560 Apr 10  2017 cspice.tar
-rw------- 1 u0_a119 u0_a119        84 Apr 10  2017 importCSpice.csh
drwx------ 2 u0_a119 u0_a119      4096 Dec  6 19:26 storage
~ $

the directory cspice has been created during the compilation process

it contains several subdirs:

~ $ ls cspice
data  doc  etc  exe  include  lib  makeall.csh  src
~ $

let's look inside cspice/exe

 $ ls cspice/exe
brief        ckbrief.exe   dskexp       inspekt.exe  msopck      spacit.exe    states      tictoc.exe  version
brief.exe    commnt        dskexp.exe   mkdsk        msopck.exe  spkdiff       states.exe  tobin       version.exe
chronos      commnt.exe    frmdiff      mkdsk.exe    simple      spkdiff.exe   subpt       tobin.exe
chronos.exe  dskbrief      frmdiff.exe  mkspk        simple.exe  spkmerge      subpt.exe   toxfr
ckbrief      dskbrief.exe  inspekt      mkspk.exe    spacit      spkmerge.exe  tictoc      toxfr.exe
~ $

all of these files are executables, but built for different systems. The ones without extension are used in aarch64 architecture, those ending with .exe are for Windows.

You can personally check the nature of these executables, but first you must install the package file:

pkg install file

now change to subdirectory cspice/exe:

cd cspice/exe

and type file brief

~/cspice/exe $ file brief
brief: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /system/bin/linker64, not stripped
~/cspice/exe $

this executable is one of our interest. We'll make a good use of it later. If you type file brief.exe instead:

~/cspice/exe $ file brief.exe
brief.exe: PE32+ executable (console) x86-64, for MS Windows
~/cspice/exe $

this exe file won't run in your phone, it's generated for cgywin, which is a posix compatible programming environment for Windows systems.

Just for curiosity, launch brief:

~/cspice/exe $ ./brief
WARNING: linker: /data/data/com.termux/files/home/cspice/exe/brief: unsupported flags DT_FLAGS_1=0x8000001

BRIEF -- Version 4.0.0, September 8, 2010 -- Toolkit Version N0066

   BRIEF is a command-line utility program that displays a summary for
   one or more binary SPK or binary PCK files. The program usage is:

      % brief [-options] file [file ...]

   The most useful options are shown below. For the complete set of
   options, run BRIEF with the -h option. The order of options is not
   significant. The case of option keys is significant: they must be
   lowercase as shown below.

      -c           display centers of motion/relative-to frames
      -t           display summary in a tabular format
      -a           treat all files as a single file
      -utc         display times in UTC calendar date format (needs LSK)
      -utcdoy      display times in UTC day-of-year format (needs LSK)
      -etsec       display times as ET seconds past J2000

   An LSK file must be provided on the command line to display times in
   UTC formats. FK file(s) must be provided on the command line to
   display names of any frames that are not built into the Toolkit.

~/cspice/exe $

Let's proceed to the creation of a dynamic library.

Change directory to cspice/src/cspice

~/cspice/src $ cd
~ $ cd cspice/src/cspice
~/.../src/cspice $ ls
F77_aloc.c     daftb.c     et2lst_c.c         lnknxt.c      rav2xf_c.c  spkr15.c       vnorm_c.c     zzeknres.c
SpiceCK.h      dafus_c.c   et2utc.c           lnkprv.c      rawio.h     spkr17.c       vnormg.c      zzeknrml.c
SpiceCel.h     dafwcr.c    et2utc_c.c         lnksiz.c      raxisa.c    spkr18.c       vnormg_c.c    zzekordc.c
... a lot of files ...
dafrfr_c.c     errint_c.c  lnkfsl.c           r_sqrt.c      spkr08.c    vlcomg_c.c     zzeklled.c
dafrrr.c       errprt.c    lnkhl.c            r_tan.c       spkr09.c    vminug.c       zzekllei.c
dafrs_c.c      errprt_c.c  lnkila.c           r_tanh.c      spkr10.c    vminug_c.c     zzeklltc.c
dafrwa.c       esrchc.c    lnkilb.c           radrec.c      spkr12.c    vminus.c       zzeklltd.c
dafrwd.c       esrchc_c.c  lnkini.c           radrec_c.c    spkr13.c    vminus_c.c     zzekllti.c
daft2b.c       et2lst.c    lnknfn.c           rav2xf.c      spkr14.c    vnorm.c        zzekmloc.c
~/.../src/cspice $

It's a huge amount of C sources, we need to compile them in a standard .so dynamic library.

within the same directory type:

gcc -Wall -O2 -fPIC -shared -o libcspice.so *.c -lm -ldl

You deserve a brief explanation of the options I have given to the compiler:

gcc is the compiler, here used as assembler, compiler and linker altogether, any further consideration is beyond our scope.

-Wall stands for the maximum warning alert level, during compilation you'll see a ton of warnings.

-O2 is the optimization level, set to a good level compatible with robustness.

-fPIC -shared is the combination of two instructions aimed at generating a shared library with Position Independent Code (PIC)

-o libcspice.so is the name I have choosen for the compiled library, "lib" and ".so" are the structural parts.

*.c are all the C sources that are present in this directory

-lm -ldl are linked libraries, math and dynamic loader

After some time and a big amount of warnings, hopefully no errors found, you'll see a new file in your directory, libcspice.so. Move it to your home directory, to have it handy

mv libcspice.so ~/

Ok, it's enough for now, see you in the next post

Tuesday, December 7, 2021

JPL Toolkit on Termux in a cheap chinese smartphone

My laziness is unforgivable. Even if I rarely have some interesting news to offer to readers (as you can see from the following lines, I'm still deeply interested in exploring basic planetary position calculus from an astrological point of view, and I have already talked a lot about JPL toolkit), once in a while I feel the urge to communicate what I have learnt to anyone who can be find some interest in it. Something has changed, however. First of all, I'm going to write next posts in plain English because most of my readers are from abroad, google translator does a good job, but anyway ...

Another important novelty is the fact that I have totally abandoned Python 2, because it is deprecated and Python ver 3 is much richer and interesting. Most of my post in the past utilized the versions 2, I'll try to upgrade them every time it's necessary. But let's talk again about the JPL toolkit, which is the de facto standard for astronomical calculations. Many astrological softwares are based upon the Swiss Ephemeris, which are C libraries that make use of the jpl ephemeris, so I think it's better go with the original, as the development of software with the Swisseph is free only for non commercial products. As you could appreciate from my past posts, building a shared library from the C NASA routines is relatively straightforward, so why not use it? Let's recapitulate the fundamentals, and then let's implement the necessary routines on a specific debian-like platform, named TERMUX, which is usable on most cheap smartphones (mine is Meizu M5 Note, 64bit Arm Android 7 based, rather old phone, but it's fine for my purposes). No need to root your device, you can use it as it is, so you won't have any problem with your bank application or other institutional ones.

Main installation

To install Termux, forget about Google store, the app is unmantained. Install F-Droid app on your Android phone, than download the Termux apk from the F-Droid repository, it's easily recognizable from its icon:

Now launch the application from your screen. You will be welcomed to Termux and you'll see something like this photo:

The keyboard you see in the photo is the Hacker's Keyboard, you can install it from Play Store, but feel free to use the one you feel most comfortable with

Now let's do a few maintaining tasks. At prompt type:

pkg install root-repo
apt update
apt upgrade -y
apt install build-essential binutils wget openssh

N.B.: all four arguments in one line

build-essential and binutils are the minimum tools required to perform compilation and linking, wget is aimed at downloading files from the web, openssh is needed to install a ssh server on our phone.

If you see an error message like "The following signatures couldn't be verified because the public key is not available", don't worry. Write the command termux-change-repo, press enter and select the main repository, than the default repository or any one in the list, than repeat the commands.

To have access to the phone memory, use the following command:

termux-setup-storage and press enter

in your home directory, type ls and you'll see a new storage subdirectory, which contains the access to the main directories used by your phone during normal usage, the most important is storage/downloads. We'll use it later

Create a ssh connection from PC

As you may have ascertained, it's rather difficult to use a phone keyboard. To make this stuff easy, let's give access to Termux to your computer.

If you have installed, as in my previous instructions, the package openssh, it's a matter of seconds activating a ssh access to your phone. Type sshd and press enter. Remember: by default the ssh port in Termus is 8022, not 22.

Now you must find your phone coordinates: type whoami and press enter, this give you your identity, mine, in this exact moment, is u0_a119.

Create a password for ssh: type passwd and press enter. You will be prompted to type a password, then to retype it. Don't create a read only password, if you are prompted to do so.

Connect your phone to your home LAN, and get its address by typing ip addr and pressing enter. Under a long list of devices, you'll find and address like 192.168.1.120 or similar, the most important part are the first two numbers 192.168. Write the full address down, it's your ip coordinate in the LAN.

Now in your PC type in a terminal emulator (cmd in Windows, any terminal available in Linux or Mac): ssh u0_a119@192.168.1.120 -p 8022. Of course, change the argument to represent your real coordinates. If all is fine, you'll be within your phone home directory. You'll receive a warm welcome message, identical to the one you have already seen opening Termux. Hooray! Every new command you'll be typing in your PC terminal, will be executed in your phone memory.

Get the right JPL source

From your browser go to the following web page:

NAIF toolkit C sources.

Browse the following link:

PC, CYGWIN, gCC, 64bit

A new page will open, copy the link address of cspice.tar.gz (if you don't know how to do right click the link and copy the address, not the string).

Then in the Termux terminal you just opened type wget <paste here your link address>

After the download has finished (it will take a while), you will find a cspice.tar.gz file in your home directory

Same procedure for the file importCspice.csh, until you see it in your directory next to the .gz file

Now install tcsh, it's the shell you need to perform some fundamental operations. Type in your terminal apt install tcsh and press enter

Almost done. Unzip your cspice.tar.gz with gunzip cspice.tar.gz, your file is now named cspice.tar

Type tcsh importCSpice.csh and let the script do its job, it will take some time, ignore warnings, and wait until you see the message Toolkit Build Complete.

Where do we go from here?

As I told you a few years ago, the just finished compilation produces a lot of useful function to work with ephemeris files and a static library, not exactly the one we need.

In the upcoming posts we will talk about the creation of a dynamic C library and the linking of it in a basic C program, and how to bind it from a python3 script. In the following posts we will find a way to use these new libraries in a graphical setting, something similar to a true Android application. Let me know if the procedures described in this page are good for you or if you need some help. See you soon ...

Monday, March 25, 2019

Calcolo di posizione con JPL toolkit - funzione reclat_c per le coordinate eclittiche

Prima di passare alla stesura di alcune semplici applicazioni, devo completare l'elenco di funzioni del jpl toolkit con qualcosa di adatto a calcolare le posizioni eclittiche (longitudine e latitudine). Come già abbiamo fatto in precedenza con il linguaggio Python, utilizzeremo il kernel trueepoch.tf già creato qualche post addietro, con frame di riferimento eclittico e dinamico.

Nel JPL toolkit esiste una funzione adatta per il calcolo delle coordinate eclittiche, reclat_c, utile per passare dalle coordinate eclittiche rettangolari alle eclittiche sferiche.

L'immagine sopra, tratta da Wikipedia, mostra efficacemente l'inclinazione del piano equatoriale rispetto a quello eclittico. Il punto di intersezione dei due circoli equatoriale ed eclittico, dal quale parte il semicircolo eclittico al di sopra dell'equatore (declinazioni positive nel riferimento equatoriale) fino al punto opposto a 0° Bilancia , è chiamato punto vernale e coincide con la posizione solare apparente all'equinozio di primavera e con lo 0° di Ariete. Per completezza, le costellazioni zodiacali che costituiscono il folclore dell'Astrologia, non sono più usate da secoli (per effetto della precessione degli equinozi l'allineamento tra segni e costellazioni è andato completamente perso), lo zodiaco è determinato dalla scelta del punto 0° di Ariete e da lì il cerchio eclittico viene diviso in dodici parti di ampiezza 30°, che si succedono in senso antiorario, come del resto il movimento apparente del Sole nel corso dell'anno solare.

Vediamo la funzione che ci interessa:

reclat_c

Perchè il suo utilizzo abbia senso, il sistema o frame di riferimento deve essere eclittico. Nel toolkit, le funzioni recrad_c, reclat_c e recsph_c, usate con lo stesso frame, non fanno altro che riproporre le stesse distanze e angoli, ruotati opportunamente.

Per questo motivo, una volta scelto il riferimento eclittico da indicare nella funzione spkezr_c (ECLIPJ2000 se statico, o il nostro MYTRUEEPOCH se dinamico), possiamo utilizzare efficacemente la funzione. Vediamo la signature in C, molto simile a quella già incontrata per recrad_c):

   void reclat_c ( ConstSpiceDouble    rectan[3],
                        SpiceDouble       * radius,
                        SpiceDouble       * longitude,
                        SpiceDouble       * latitude  )
Brief_I/O
 
   VARIABLE  I/O  DESCRIPTION
   --------  ---  --------------------------------------------------
   rectan     I   Rectangular coordinates of a point.
   radius     O   Distance of the point from the origin.
   longitude  O   Longitude of the point in radians.
   latitude   O   Latitude of the point in radians.

Nulla di nuovo, come vediamo. Nella classe CSpice già vista nei precedenti post aggiungeremo le parti di interesse:

    public interface CLibrary extends Library {
        double pi_c();
        double spd_c();
        double dpr_c();
        void furnsh_c(String s);
        void unload_c(String s);
        double str2et_c(String s, DoubleByReference p);
        double spkezr_c(String targ, double et, String ref, String abcorr, String obs, double[] starg, DoubleByReference lt);
        double recrad_c(double[] rectan, DoubleByReference range, DoubleByReference ra, DoubleByReference dec);
        double reclat_c(double[] rectan, DoubleByReference radius, DoubleByReference longitude, DoubleByReference latitude);
    }

nella parte declarativa (interfaccia) e, nella parte riguardante la definizione della funzione, il codice seguente:

    double[] reclat_c(double[] rectan, DoubleByReference radius, DoubleByReference longitude, DoubleByReference latitude){
        radius.setValue(0.0); longitude.setValue(0.0); latitude.setValue(0.0);
        INSTANCE.reclat_c(rectan, radius, longitude, latitude);
        double[] ret = new double[6];
        ret[0] = rectan[0]; ret[1] = rectan[1]; ret[2] = rectan[2]; 
        ret[3] = radius.getValue(); ret[4] = longitude.getValue(); ret[5] = latitude.getValue();
        return ret;
        
    }

Per testare la nuova funzione utilizzero' il sito Miriade dell'Observatoire de Paris, che attraverso l'IMCCE Virtual Observatory Solar System portal fornisce un comodo ambiente web per il calcolo di posizione secondo vari sistemi e frame di riferimento.

Usando il mio programma di test, usando ECLIPJ2000 come ref statico, ottengo i seguenti: (longitudine e latitudine in gradi, minuti e secondi con decimali per una più facile comparazione con i risultati di Miriade)

Vettore posizione e velocità di  SUN 2019-03-25T17:15:00

 x:  0.9941741023222863
 y:  0.07837450273804566
 z:  -6.386035799020023E-6


Coordinate rettangolari e sferiche eclittiche
radius:  0.9972585965779094
longitudine:  4°30'27".07
latitudine:  -0°00'01".32


Vettore posizione e velocità di  MOON 2019-03-25T17:15:00

 x:  -0.001033206460039779
 y:  -0.002309224486574583
 z:  1.6574816415858715E-4


Coordinate rettangolari e sferiche eclittiche
radius:  0.0025352526052418367
longitudine:  245°53'42".11
latitudine:  3°44'54".68


Vettore posizione e velocità di  MERCURY 2019-03-25T17:15:00

 x:  0.6283821386649743
 y:  -0.15394903328787
 z:  0.01456646607325417


Coordinate rettangolari e sferiche eclittiche
radius:  0.6471295071137615
longitudine:  346°14'02".74
latitudine:  1°17'23".28


Vettore posizione e velocità di  VENUS 2019-03-25T17:15:00

 x:  1.0515933099261605
 y:  -0.6464412430519756
 z:  -0.01326528066622894


Coordinate rettangolari e sferiche eclittiche
radius:  1.2344677953965406
longitudine:  328°25'11".63
latitudine:  -0°36'56".51


Vettore posizione e velocità di  MARS 2019-03-25T17:15:00

 x:  1.0996446391999108
 y:  1.6346349816138936
 z:  0.03001478808475523


Coordinate rettangolari e sferiche eclittiche
radius:  1.9703174219248858
longitudine:  56°04'14".37
latitudine:  0°52'22".25


Vettore posizione e velocità di  JUPITER_BARYCENTER 2019-03-25T17:15:00

 x:  -0.5546811837096326
 y:  -5.015523791671758
 z:  0.05580703045516249


Coordinate rettangolari e sferiche eclittiche
radius:  5.046411055892613
longitudine:  263°41'20".91
latitudine:  0°38'01".08


Vettore posizione e velocità di  SATURN_BARYCENTER 2019-03-25T17:15:00

 x:  3.3846391497900328
 y:  -9.689305891517016
 z:  0.07463820459939993


Coordinate rettangolari e sferiche eclittiche
radius:  10.263722604165778
longitudine:  289°15'18".63
latitudine:  0°24'59".98


Vettore posizione e velocità di  URANUS_BARYCENTER 2019-03-25T17:15:00

 x:  17.836331344752253
 y:  10.586677831321417
 z:  -0.17908834868983295


Coordinate rettangolari e sferiche eclittiche
radius:  20.74233680134956
longitudine:  30°41'27".84
latitudine:  -0°29'40".90


Vettore posizione e velocità di  NEPTUNE_BARYCENTER 2019-03-25T17:15:00

 x:  30.040066592923566
 y:  -7.154084379289532
 z:  -0.5205399170871235


Coordinate rettangolari e sferiche eclittiche
radius:  30.884583306539174
longitudine:  346°36'16".04
latitudine:  -0°57'56"63


Vettore posizione e velocità di  PLUTO_BARYCENTER 2019-03-25T17:15:00

 x:  13.128721019597675
 y:  -31.432013468122367
 z:  -0.13859786812604474


Coordinate rettangolari e sferiche eclittiche
radius:  34.06396917036681
longitudine:  292°40'10".65
latitudine:  -0°13'59".24

Per lo stesso istante Miriade mi dà i seguenti (copio uno alla volta dal sito, Plutone è escluso);


Planetary theory: DE406 Reference Plane:ecliptic 
Type of Coordinates: Spherical Type of Ephemeris: MeanJ2000
-----------------------------------------------------------------------------
Target            Date              Longitude       Latitude       Distance
----------------------------------------------------------------------------
Sun     2019-03-25T17:15:00.00   4 30 21.4251 -00  0  0.9002  0.997243696
Moon    2019-03-25T17:15:00.00 245 53 42.0999 +03 44 54.6775  0.002566436
Mercury 2019-03-25T17:15:00.00 346 13 52.9789 +01 17 23.9700  0.647123973
Venus   2019-03-25T17:15:00.00 328 25  6.4727 -00 36 56.1647  1.234471820
Mars    2019-03-25T17:15:00.00  56  4 13.8153 +00 52 22.5126  1.970286798
Jupiter 2019-03-25T17:15:00.00 263 41 20.5542 +00 38  1.1265  5.046440794
Saturn  2019-03-25T17:15:00.00 289 15 18.2025 +00 24 59.9873 10.263743803
Uranus  2019-03-25T17:15:00.00  30 41 27.7752 -00 29 40.8371 20.742311016
Neptune 2019-03-25T17:15:00.00 346 36 15.7283 -00 57 56.5707 30.884601149
-----------------------------------------------------------------------------

Considerate le diversità già accennate tra i due sistemi di calcolo, i risultati sono incoraggianti. Dal prossimo post iniziamo a costruire piccoli software grafici in JavaFX (o in Swing, devo capire quale libreria grafica di Java dà i migliori risultati). Come IDE penso che usero' NetBeans, è un po' che ci traffico e mi sembra abbastanza comodo e facile da usare. Al prossimo post.

Saturday, March 16, 2019

Calcolo di posizione con JPL toolkit - funzione recrad_c per le coordinate equatoriali

Per la parte strettamente legata all'implementazione delle funzioni essenziali del toolkit, in questo post aggiungero' una funzione utile per avere la rappresentazione in coordinate sferiche equatoriali.

Con la funzione spekzr_c abbiamo ottenuto una rappresentazione vettoriale, di posizione e di velocità secondo le componenti x, y e z riferite ad uno specifico istante temporale, rappresentato come UTC e corretto automaticamente in TDB.

il passo ulteriore è convertire le coordinate rettangolari in sferiche. Ci viene in aiuto una funzione C dello spice toolkit, recrad_c, che fornisce distanza, ascensione retta e declinazione.

Brevemente descrivo il codice, vi sarà già chiaro come modificare opportunamente la classe CSpice.java per la sua implementazione.

Cominciamo con la signature della funzione, presente nella documentazione del jpl toolkit:

   void recrad_c ( ConstSpiceDouble    rectan[3],
                   SpiceDouble       * range,
                   SpiceDouble       * ra,
                   SpiceDouble       * dec      ) 

Brief_I/O
 
   VARIABLE  I/O  DESCRIPTION 
   --------  ---  -------------------------------------------------- 
   rectan     I   Rectangular coordinates of a point. 
   range      O   Distance of the point from the origin. 
   ra         O   Right ascension in radians. 
   dec        O   Declination in radians. 

Il rendering in codice Java è quello che segue:

    public interface CLibrary extends Library {
        ......
        double recrad_c(double[] rectan, DoubleByReference range, DoubleByReference ra, DoubleByReference dec);
        
    }
    double[] reclat_c(double[] rectan, DoubleByReference radius, DoubleByReference longitude, DoubleByReference latitude){
        radius.setValue(0.0); longitude.setValue(0.0); latitude.setValue(0.0);        
        INSTANCE.reclat_c(rectan, radius, longitude, latitude);
        double[] ret = new double[6];
        ret[0] = rectan[0]; ret[1] = rectan[1]; ret[2] = rectan[2]; 
        ret[3] = radius.getValue(); ret[4] = longitude.getValue(); ret[5] = latitude.getValue();
        return ret;
    }

La definizione di dettaglio della funzione va invece semplicemente accodata alle precedenti. Come già in precedenza, in C la funzione non ritorna valore, in quanto le variabili vengono modificate per riferimento ed estratte al di fuori della funzione stessa. In Java preferisco creare artificialmente un array di double come valore di ritorno. Come già discusso in precedenza, nella sezione declarativa dell'interfaccia le funzioni che restituiscono un array vanno dichiarate per tipo, non per array del tipo, che invece è il valore di ritorno delle stesse e, come tale, rappresentato nella sezione di definizione. Per il resto si segue la procedura già vista in precedenza. Vediamo le cose essenziali:

La funzione accetta un vettore di tre elementi (le coordinate rettangolari di posizione, già viste come valore di ritorno della funzione spekzr_c, e modifica tre puntatori a variabile double, fornite come parametri di input. Nulla di nuovo, la funzione java sarà modificata per restituire tre double, ottenuti estraendo il relativo valore dalle variabili dichiarate DoubleByReference con il metodo getValue(). La restituzione di un array di 6 double contenente anche le coordinate rettangolari fornite in input non è necessaria, l'ho implementata solo per controllo.

Con questo post termino la parte di pura stesura del codice. Dal prossimo post iniziamo a creare un applicativo per usare quento abbiamo realizzato finora. Al prossimo post.

Thursday, March 7, 2019

Calcolo di posizione con JPL toolkit - nuove funzioni

Per completare il nucleo essenziale delle funzioni usate per pilotare l'accesso al jpl toolkit scriviamo tre nuove, e per il momento, ultime, funzioni. Il toolkit è molto ampio, c'è ancora parecchio da sviluppare, ma per l'astrologia serve molto poco.

Spekzr_c

Questa funzione serve per il calcolo di posizione, espressa in coordinate rettangolari e vettore velocità, di un corpo celeste dati il corpo obiettivo, il punto di osservazione, l'istante temporale e alcune altre variabili che non utilizzeremo. Vediamo per prima cosa la signature, ripetendo quello che abbiamo già visto con le ctypes di Python:

   void spkezr_c ( ConstSpiceChar     *targ,
                   SpiceDouble         et,
                   ConstSpiceChar     *ref,
                   ConstSpiceChar     *abcorr,
                   ConstSpiceChar     *obs,
                   SpiceDouble         starg[6],
                   SpiceDouble        *lt        )

   Variable  I/O  Description 
   --------  ---  -------------------------------------------------- 
   targ       I   Target body name. 
   et         I   Observer epoch. 
   ref        I   Reference frame of output state vector. 
   abcorr     I   Aberration correction flag. 
   obs        I   Observing body name. 
   starg      O   State of target. 
   lt         O   One way light time between observer and target. 
 
   starg       is a Cartesian state vector representing the position 
               and velocity of the target body relative to the 
               specified observer. `starg' is corrected for the 
               specified aberrations, and is expressed with respect 
               to the reference frame specified by `ref'. The first 
               three components of `starg' represent the x-, y- and 
               z-components of the target's position; the last three 
               components form the corresponding velocity vector. 
 
               The position component of `starg' points from the 
               observer's location at `et' to the aberration-corrected 
               location of the target. Note that the sense of the 
               position vector is independent of the direction of 
               radiation travel implied by the aberration 
               correction. 
 
               The velocity component of `starg' is the derivative
               with respect to time of the position component of
               `starg.'
 
               Units are always km and km/sec. 

La documentazione ci dice che, dati il target body name (stringa), l'observer epoch (double), il reference frame (il nostro opzionale kernel), il flag di correzione dell'aberrazione (che non usiamo), il nome del corpo di osservazione (la Terra nel nostro caso - Stringa) e dun vettore double di 6 elementi e un eventuale puntatore a double (light time, non utilizzato), possiamo accedere ad un vettore posizione (coordinate x,y,z) e un vettore velocità (vx, vy, vz) deferenziando il vettore double che abbiamo fornito in input).

Siccome il codice sta diventando troppo lungo per incorporarlo per intero, scrivo solo i segmenti, avrete capito che i suguenti frammenti vanno accodati al codice già scritto nei post precedenti, uno all'interno della public interface CLibrary e uno in coda. Attenti però a come definiamo il valore di ritorno, nel caso vogliamo dereferenziare un vettore: nella dichiarazione dentro l'interface indicheremo solo il tipo di dati, nella definizione il double sarà dichiarato come array:

public class CSpice {
    private static final CLibrary INSTANCE;

    static {
        INSTANCE = Native.load("cspice", CLibrary.class);
    }

    public interface CLibrary extends Library {
     ...........

        double spkezr_c(String targ, double et, String ref, 
                     String abcorr, String obs, 
                     double[] starg, DoubleByReference lt);
        }

     // funzione spekzr_c
    }
 
    double[] spkezr_c(String targ, double et, String ref, 
                      String abcorr, String obs, double[] starg, DoubleByReference lt){
        
             for (int i = 0; i < 6; i++){        
                 starg[0] = 0.0;
             }
             INSTANCE.spkezr_c(targ, et, ref, abcorr, obs, starg, lt);
             return starg;
    }

L'array starg, come valore di ritorno, andrà scandito con un ciclo for per recuperare i singoli valori dei due vettori.

Estendiamo il file Main.java:

        ....
        DoubleByReference p = new DoubleByReference();
        System.out.println("Secondi dal J2000: "+spice.str2et_c("2000-01-01T12:00:00", p));
        System.out.println("\n");
        
        // spkezr_c        
        String timestring = "2017-08-10T18:53:22";
        double et = spice.str2et_c(timestring, p);
        String ref = "J2000";
        String target = "SATURN_BARYCENTER";
        String observer = "EARTH";
        String abcorr = "NONE";
        double[] starg = new double[6];
        DoubleByReference lt = new DoubleByReference();
        double[] d = new double[6]; 
        d = spice.spkezr_c(target, et, ref, abcorr, observer, starg, lt);
        String[] elem = {" x: "," y: "," z: ","vx: ","vy: ","vz: "};
        System.out.println("Vettore posizione e velocità di Saturno baricentro per il " + timestring + "\n");
        for (int i = 0; i < 6; i++){
            System.out.println(elem[i]+ " " + d[i]);            
        }
        System.out.println("\n");

In breve, inizializziamo le variabili di input, comprese quelle che serviranno per estrarre i valori di ritorno, secondo il loro tipo, chiamiamo la funzione e scompattiamo l'array.

Facciamo una prova:

ubuntu@ubuntu-desktop:~/Scrivania/CSpice$ javac -classpath .:jna-5.2.0.jar -g Main.java
ubuntu@ubuntu-desktop:~/Scrivania/CSpice$ java -classpath .:jna-5.2.0.jar Main
Valore di Pi greco: 3.141592653589793
Secondi in un giorno: 86400.0
Numero di gradi per radiante: 57.29577951308232
OK Kernel caricati
Secondi dal J2000: 64.18392728473108


Vettore posizione e velocità di Saturno baricentro per il 2017-08-10T18:53:22

 x:  -2.1891291720093992E8
 y:  -1.2962750669325852E9
 z:  -5.289702916654781E8
vx:  -10.299865176779855
vy:  -20.74633831944049
vz:  -9.37634837706102




OK Kernel dismessi
ubuntu@ubuntu-desktop:~/Scrivania/CSpice$ 

Come potete verificare, ho ottenuto gli stessi valori, ma in notazione decimale anzichè esponenziale, che avevo ottenuto con python ctypes; per le verifiche di accuratezza potere rifarvi a questo post precedente. Gli input erano identici, quindi non occorre ripetere le verifiche di accuratezza.

Nei prossimi post aggiungeremo le funzioni di conversione da coordinate rettangoli a sferiche equatoriali ed eclittiche utilizzando due diversi frame di riferimento.

Wednesday, March 6, 2019

Caricare i kernel - CSPICE data types - Ulteriori funzioni

Proseguiamo l'estensione delle funzioni del toolkit accessibili tramite JNA. Come già visto nei post dedicati al linguaggio Python, il toolkit fornisce due metodi che possiamo utilizzare per il caricamento e per la dismissione dei kernel. I kernel sono i file dati utilizzati dal toolkit, ce ne sono di vario tipo, per una disamina completa potete leggere questa pagina della documentazione. Per ora ci intereressa caricare il kernel delle effemeridi (de421.bsp o simili) e il naif0012.tls per i leapsecond. Quindi aggiungeremo in seguito il kernel per specificare un frame di riferimento customizzato (trueepoch.tf)

Nel piccolo file interfaccia creato nel post precedente era già integrata la dichiarazione delle due funzioni di libreria furnsh_c e unload_c, ora ne scriveremo la definizione.

Partiamo dalle signature:


        void furnsh_c ( ConstSpiceChar  * file ) 
        void unload_c ( ConstSpiceChar  * file )

In Java le tradurremo come:


        void furnsh_c(String s);
        void unload_c(String s);

e la corrispondente definizione sarà:


    public void furnsh_c(String s){    
        INSTANCE.furnsh_c(s);        
        return;
    }

    public void unload_c(String s){
        INSTANCE.unload_c(s);
        return;
    }

Rivediamo il file CSpice.java e Main.java modificati:

import com.sun.jna.*;
import com.sun.jna.ptr.*;

public class CSpice {
    private static CLibrary INSTANCE;

    static {
        INSTANCE = Native.load("cspice", CLibrary.class);
    }

    public interface CLibrary extends Library {
        double pi_c();
        double spd_c();
        double dpr_c();
        void furnsh_c(String s);
        void unload_c(String s);

    }
    public double pi_c() {
        return INSTANCE.pi_c();
    }

    public double spd_c() {
        return INSTANCE.spd_c();
    }

    public double dpr_c() {
        return INSTANCE.dpr_c();
    }

    public void furnsh_c(String s){    
        INSTANCE.furnsh_c(s);        
        return;
    }

    public void unload_c(String s){
        INSTANCE.unload_c(s);
        return;
    }

}

e
public class Main {

     public static void main(String[] args) {
        CSpice spice = new CSpice();
        System.out.println("Valore di Pi greco: " + spice.pi_c());
        System.out.println("Secondi in un giorno: " + spice.spd_c());
        System.out.println("Numero di gradi per radiante: " + spice.dpr_c());
        spice.furnsh_c("de421.bsp");
        spice.furnsh_c("naif0012.tls");
        System.out.println("OK Kernel caricati");
        spice.unload_c("de421.bsp");
        spice.unload_c("naif0012.tls");
        System.out.println("OK Kernel dismessi");        
     }
}

Ricompiliamo il tutto ed eseguiamo:

ubuntu@ubuntu-desktop:~/Scrivania/CSpice$ javac -classpath .:jna-5.2.0.jar -g Main.java
ubuntu@ubuntu-desktop:~/Scrivania/CSpice$ java -classpath .:jna-5.2.0.jar Main
Valore di Pi greco: 3.141592653589793
Secondi in un giorno: 86400.0
Numero di gradi per radiante: 57.29577951308232
OK Kernel caricati
OK Kernel dismessi
ubuntu@ubuntu-desktop:~/Scrivania/CSpice$ 

Siamo pra pronti ad inserire la chiamata alla funzione che, data una stringa di formattazione di data e ora in formato ISO 8601, restituisce il numero di secondi TDB (Temps Dynamique Barycentrique) a partire dalla epoch J2000.

La signature della funzione è la seguente:


void str2et_c ( ConstSpiceChar * str,
                SpiceDouble    * et   )

dove str è la data in formato ISO, et è il puntatore al valore double fornito come parametro e che va recuperato come valore.

per i puntatori abbiamo già considerato l'import delle classi del blocco com.sun.jna.ptr (seconda riga del file CSpice). La traduzione in Java sarà la seguente:


       double str2et_c(String s, DoubleByReference p);

per la dichiarazione e


    double str2et_c(String s, DoubleByReference p){
        INSTANCE.str2et_c(s,p);
        return p.getValue();
    }

per la definizione.

In buona sostanza: la funzione str2et_c, che nel toolkit restituisce un void, viene trasformata da noi in modo da restituire un double, che corrisponde al nuovo contenuto della variabile p, modificato dalla funzione ed estratto (dereferenziato, con la terminologia usata dal linguaggio C) con il metodo getValue(). Molto simile, nel procedimento, a quanto già fatto con python ctypes.

Rivediamo i file CSpice.java e Main.java con le ultime modifiche:

import com.sun.jna.*;
import com.sun.jna.ptr.*;

public class CSpice {
    private static CLibrary INSTANCE;

    static {
        INSTANCE = Native.load("cspice", CLibrary.class);
    }

    public interface CLibrary extends Library {
        double pi_c();
        double spd_c();
        double dpr_c();
        void furnsh_c(String s);
        void unload_c(String s);
        double str2et_c(String s, DoubleByReference p);

    }
    public double pi_c() {
        return INSTANCE.pi_c();
    }

    public double spd_c() {
        return INSTANCE.spd_c();
    }

    public double dpr_c() {
        return INSTANCE.dpr_c();
    }

    public void furnsh_c(String s){    
        INSTANCE.furnsh_c(s);        
        return;
    }

    public void unload_c(String s){
        INSTANCE.unload_c(s);
        return;
    }

    double str2et_c(String s, DoubleByReference p){
        INSTANCE.str2et_c(s,p);
        return p.getValue();
    }

}
import com.sun.jna.ptr.DoubleByReference;

public class Main {

     public static void main(String[] args) {
        CSpice spice = new CSpice();
        System.out.println("Valore di Pi greco: " + spice.pi_c());
        System.out.println("Secondi in un giorno: " + spice.spd_c());
        System.out.println("Numero di gradi per radiante: " + spice.dpr_c());
        spice.furnsh_c("de421.bsp");
        spice.furnsh_c("naif0012.tls");
        System.out.println("OK Kernel caricati");

        DoubleByReference et = new DoubleByReference();
        System.out.println("Secondi dal J2000: "+spice.str2et_c("2000-01-01T12:00:00", et));
        
        spice.unload_c("de421.bsp");
        spice.unload_c("naif0012.tls");
        System.out.println("OK Kernel dismessi");        
     }
}

E ricompiliamo

ubuntu@ubuntu-desktop:~/Scrivania/CSpice$ javac -classpath .:jna-5.2.0.jar -g Main.java
ubuntu@ubuntu-desktop:~/Scrivania/CSpice$ java -classpath .:jna-5.2.0.jar Main
Valore di Pi greco: 3.141592653589793
Secondi in un giorno: 86400.0
Numero di gradi per radiante: 57.29577951308232
OK Kernel caricati
Secondi dal J2000: 64.18392728473108
OK Kernel dismessi
ubuntu@ubuntu-desktop:~/Scrivania/CSpice$ 

Tuesday, March 5, 2019

Marshalling di alcune funzioni riferite a costanti fondamentali

Come ho fatto per il linguaggio Python, scrivero' per prime alcune funzioni in Java finalizzate al recupero di valori di costanti matematiche o astronomiche di rilievo (pi greco, numero di secondi in un giorno, gradi per radiante.

Le funzioni del toolkit che consentono queste operazioni sono le seguenti, con la loro signature completa:

SpiceDouble pi_c  ( void )
SpiceDouble spd_c ( void )
SpiceDouble dpr_c ( void )

Nel file CSpice.java introdurro' le seguenti modifiche:

import com.sun.jna.*;
import com.sun.jna.ptr.*;

public class CSpice {
    private static CLibrary INSTANCE;

    static {
        INSTANCE = Native.load("cspice", CLibrary.class);
    }

    public interface CLibrary extends Library {
        double pi_c();
        double spd_c();
        double dpr_c();
        void furnsh_c(String s);
        void unload_c(String s);

    }
    public double pi_c() {
        return INSTANCE.pi_c();
    }

    public double spd_c() {
        return INSTANCE.spd_c();
    }

    public double dpr_c() {
        return INSTANCE.dpr_c();
    }

}

Nell'interface ho definito le funzioni traducendo i tipi di variabili SpaceDouble del toolkit nel tipo double di Java e il tipo void del parametro delle funzioni in uno spazio vuoto. In questo caso il marshalling è particolarmente semplice. La stesura effettiva delle funzioni relative è appena poco più estesa: le funzioni prima dichiarate diventano metodi della INSTANCE della libreria nativa cspice.

Per finire modifichiamo opportunamente la classe Main.java per estrarre i valori delle costanti dichiarate tramite i metodi associati:

public class Main {

     public static void main(String[] args) {
        CSpice spice = new CSpice();
        System.out.println("Valore di Pi greco: " + spice.pi_c());
        System.out.println("Secondi in un giorno: " + spice.spd_c());
        System.out.println("Numero di gradi per radiante: " + spice.dpr_c());

     }
}

A questo punto ricompiliamo il tutto:

ubuntu@ubuntu-desktop:~/Scrivania/CSpice$ javac -classpath .:jna-5.2.0.jar -g Main.java
ubuntu@ubuntu-desktop:~/Scrivania/CSpice$ java -classpath .:jna-5.2.0.jar Main
Valore di Pi greco: 3.141592653589793
Secondi in un giorno: 86400.0
Numero di gradi per radiante: 57.29577951308232
ubuntu@ubuntu-desktop:~/Scrivania/CSpice$ 

Come è facile vedere, il risultato è perfettamente corrispondente a quello atteso. Il più è fatto. Da qui in poi estenderemo le funzioni usate fino a riprodurre quanto abbiamo già realizzato con il linguaggio python. Nel post successivo iniziamo a definire funzioni un po' più complesse

JNA e jpl toolkit - creazione dell'interfaccia

Per chiamare da Java le funzioni della shared library, dobbiamo imparare le fondamentali tecniche di interfacciamento e di marshalling (cioè di definizione di formati dati di interscambio tra codice gestito (Java) e non gestito (libreria C).

Prima di tutto scarichiamo la libreria in formato .jar dell'ultima versione disponibile di JNA, che troviamo QUI.


Cominciando dall'interfaccia, utilizzeremo un template, cioè un po' di codice boilerplate, come lo chiamano gli Americani, per renderci la vita più semplice.

import com.sun.jna.*;
import com.sun.jna.ptr.*;

public class CSpice {
    private static CLibrary INSTANCE;

    static {
        INSTANCE = Native.load("cspice", CLibrary.class);
    }

    public interface CLibrary extends Library {
//<-----------------definizione dei prototipi delle funzioni------------>
    }
//<-----------------chiamata alle funzioni, una alla volta-------------->
}

Spiegazione: l'import riguarda il core della libreria JNA e il complesso delle classi per la gestione dei puntatori, lo vediamo nel corso dello sviluppo. La classe pubblica CSpice conterrà tutto il codice per la creazione di un oggetto che sarà l'interfaccia da usare. Per il momento dò per scontato il resto del codice, fatta eccezione per la definizione statica dell'INSTANCE come
Native.Load("cspice", CLibrary.class).
Qui la libreria libcspice.so è richiamata esplicitamente, togliendo dal nome il prefisso lib e l'estensione .so. Questo vale per qualsiasi altra situazione in cui una generica libreria .so è utilizzata: libHelloWorld.so -> INSTANCE = Native.load("HelloWorld", CLibrary.class);.

Buttiamo giù un veloce file di classe Main.java, giusto per ospitare un metodo main:

public class Main {

     public static void main(String[] args) {
        CSpice spice = new CSpice();
     }
}

Facciamo una compilazione di prova: ricordiamoci di richiamare esplicitamente la libreria jna con l'opzione classpath:

javac -classpath .:jna-5.2.0.jar -g Main.java

Come potete apprezzare, la classe CSpice che contiene l'interfaccia viene richiamata implicitamente durante la compilazione di Main.java e il file di classe corrispondente viene creato come CSpice.class nella directory di progetto. Se facciamo il listing della directory vediamo i file seguenti:

ubuntu@ubuntu-desktop:~/Scrivania/CSpice$ ls
 backup.java           CSpice.java     libcspice.so   naif0012.tls
'CSpice$CLibrary.class'   de421.bsp       Main.class     trueepoch.tf
 CSpice.class          jna-5.2.0.jar   Main.java
ubuntu@ubuntu-desktop:~/Scrivania/CSpice$

Proviamo a lanciare il programma con il comando seguente:

java -classpath .:jna-5.2.0.jar Main

Se il comando non produce output vuol dire che va tutto bene

Mi fermo qui, continuiamo nel prossimo post.

JAVA, JNA, codice unmanaged e marshalling

Lavorare su codice nativo non gestito da un ambiente operativo diverso da quello di produzione non è sempre facile, ma spesso non avete alternative. Pensate al nostro JPL toolkit, scritto in C e Fortran. Avreste voglia di riscrivere tutto in Python o in Java? sono centinaia di funzioni, non è il caso. Questo vale per molte situazioni diverse, pensate alle librerie scientifiche compilate in Fortran negli anni dei pionieri, o a tutto il codice generato dalle vecchie versioni Visual Studio (non so se interoperabilità COM vi ricorda qualcosa). Anche la nostra piccola shared library compilata qualche post fa, libcspice.so o la sua equivalente in Windows libcspice.dll rischia di restare un bel giocattolo se non troviamo il modo di riutilizzarla con i compilatori o interpreti scritti in altri linguaggi. Abbiamo esplorato un po' ctypes di Python, ora voglio iniziare, come accennato nel post precedente, a JNA di Java.

Per questo piccolo progetto non usero', almeno prima di un certo numero di post, un IDE grafico come Eclipse o Netbeans, preferisco, per semplicità e beneficio didattico, fare tutte le compilazioni da riga di comando. Userò, come compilatore C per JPL SPICE il GNU gcc (ma trovate tutto già spiegato nei post precedenti) e come compilatore java openjdk (una qualsiasi versione successiva alla 7 va bene, attualmente nella mia Ubuntu 18.10 uso la versione 11.0.2). Se operate in ambiente windows, vista l'elevata portabilità di Java, potremo facilmente usare la linea di comando in una finestra terminale, se volete un compilatore C per questa piattaforma avete ampia libertà di scelta, c'è Visual Studio, oppure Mingw che riproduce un ambiente POSIX sotto Windows, vedete voi cosa preferite, alla fine di tutto faro' io un post apposito).

La prima cosa che faremo sarà creare una directory dedicata al progettino Java sul desktop o in qualsiasi posizione comoda per lavorare. All'interno collocheremo alcuni file creati precedentemente, come vi mostra lo schemino seguente.

ubuntu@ubuntu-desktop:~/Scrivania/CSpice$ ls -l
totale 20596
-rw-rw-r-- 1 ubuntu ubuntu 16788480 mar  2 10:56 de421.bsp
-rwxrwxr-x 1 ubuntu ubuntu  4281824 mar  2 10:45 libcspice.so
-rw-rw-r-- 1 ubuntu ubuntu     5257 mar  2 11:00 naif0012.tls
-rwxrwxrwx 1 ubuntu ubuntu      598 ago 12  2017 trueepoch.tf
ubuntu@ubuntu-desktop:~/Scrivania/CSpice$

Riepilogando:

libcspice.so è la libreria condivisa che contiene le funzioni del JPL toolkit (per un accesso veloce ai metodi di compilazione partite da Questo post in avanti)

de421.bsp è il file delle effemeridi fornito dal sito ftp della NASA. Se volete un file più recente c'è ampia scelta, il 421 ha il pregio di essere abbastanza leggero e portabile anche in ambiente Android.

naif0012.tls è il kernel generico che contiene l'elenco aggiornato dei leapsecond (secondo intervalare in italiano), ricordate che si tratta della ".. correzione del tempo applicata al tempo coordinato universale (UTC) per mantenerlo allineato al giorno solare medio, l'ente responsabile della regolazione è l'International Earth Rotation and Reference Systems Service (IERS) (sorgente Wikipedia). Trovate l'elenco dei kernel disponibili in questa pagina.

Infine trueepoch.tf è il kernel creato da me seguendo le istruzioni fornite dal NAIF in questa pagina , che servirà più avanti per svincolarsi dal frame di riferimento inerziale e spostarsi su un frame dinamico come quello che usano gli astrologi. Trovate i dettagli per la sua costruzione nei miei post precedenti già citati.

A questo punto possiamo iniziare a scrivere un po' di codice Java. Per semplicità metto tutto nella stessa directory, rinunciando a creare un package, nulla vieta di strutturare meglio il progetto, lo faremo in seguito.
Dopo questa lunga premessa, passo al post successivo per la scrittura delle prime classi Java che ci servono.

Monday, March 4, 2019

JPL Spice Toolkit, Java, JNA - come utilizzare la libreria nativa libcspice.so in ambiente Java

Sono due anni che prometto di occuparmi di domificazione e ogni volta trovo una scusa per rinviare. Sarà che non sento molto il problema, sarà che ce n'è fin troppi di sistemi di domificazione, sarà che il più usato (Placidus) ha un comportamento degenere alle latitudini estreme, per un motivo o per l'altro trovo sempre qualcos'altro di cui occuparmi.

Da qualche giorno sto pasticciando con JAVA (vi ricordo che non sono un professionista né dell'informatica né dell'astrologia), l'ho usato un po' in passato per ambienti desktop e un po' per creare qualcosa per Android. Mi chiedevo se era possibile usare una libreria nativa come la libreria dinamica libcspice.so che avevo compilato qualche post addietro, in piattaforma JAVA, un po' come abbiamo fatto con la libreria ctypes di Python.

Il metodo effettivamente esiste, anzi ne esiste più di uno, c'è SWIG, c'è JNI, ma poi ho cominciato a usare JNA e ha funzionato abbastanza presto. Ho, pertanto, deciso di scrivere un piccolo tutorial su JNA, visto che quello che si trova in giro, anche in ambienti seri come Stack Overflow è poco più di Hello World. (per inciso, se un giorno scoppierà una rivoluzione, sarà per l'esasperazione dei programmatori che si trovano sempre un HelloWorld inutile ogni volta che cercano qualche informazione sul web).

Se andate indietro di qualche post e rileggete quello che ho scritto su ctypes, vi renderete conto che è una libreria non di immediata comprensione, ma che, una volta imparate le basi, diventa estremamente soddisfacente. La stessa cosa vale per JNA, interfaccia in puro linguaggio JAVA per il binding di funzioni nascoste in una libreria di sistema, sia essa una DLL di Windows o una SO di Linux. Se avrete la pazienza di seguirmi, ho qualche piccolo trucco da esporre in chiaro.

Per rendere le cose più semplici, partirò, come ho fatto per Python ctypes, con il call di costanti presenti nel JPL toolkit e aggiungerò progressivamente delle chiamate a funzioni, facendovi partecipi di questo accostamento iniziale a JNA. Mi perdonerete se l'approccio potrà sembrare poco professionale, ma, ripeto, sono un programmatore amatoriale.

Al prossimo post, penso di scriverlo a giorni, le mie routine sono sufficientemente mature per una breve esposizione. A presto.

Wednesday, May 16, 2018

Piccola deviazione dal tema principale: preparare la carne vegetale

A furia di tentativi ed errori sono riuscito a produrre, con mezzi semplici, un sostituto salutare ed economico della carne, che non sa di molto ma è abbastanza facile da realizzare, poco costosa, molto digeribile. Ricetta adatta all' ingresso di Urano nel Toro, che esprime, in ogni caso, un cambiamento nelle abitudini alimentari.

Senza ulteriori indugi, vi passo la mia ricetta personale.

Ricetta della carne vegetale

Ingredienti

  1. lenticchie secche (varietà economica da discount) g.400
  2. farina manitoba (o comunque ad alto contenuto proteico) Kg 2
  3. Semi di varia estrazione (girasole, lino, sesamo, papavero) g. 200
  4. acqua (300ml per 500g di farina): 1200ml
  5. sale, aromi a piacere, due cucchiai di olio d'oliva, peperoncino macinato, pepe, un cucchiaio di curcuma

Attrezzatura

  1. una pentola grande
  2. un recipiente in plastica di grandi dimensioni (per due kg di pasta)
  3. uno scolapasta in plastica o acciaio di misure corrispondenti al recipiente di cui sopra
  4. un telino bianco pulito e deodorato (se è fresco di bucato, farlo bollire dieci minuti in acqua)
  5. un miscelatore o robot da cucina o impastatrice
  6. recipienti più piccoli, piatti e stoviglie al bisogno

Preparazione

Formare il seitan (glutine)

Impastare tutta la farina con l'acqua, non aggiungere nè lievito nè sale

Formare una palla di pasta e metterla in un recipiente largo, totalmente immersa in acqua, per almeno 4 ore (serve a formare il glutine)

Al termine scolarla, inserirla nello scolapasta e inserire quest'ultimo nel recipiente di cui sopra, dopo averlo completamente scolato.

Con un filo d'acqua, alternando acqua calda e fredda, lavorare l'impasto per eliminare tutto l'amido.

Dopo quindici-venti minuti di lavorazione la pasta, che è diventata molto più morbida, diventa più densa e mantiene la forma e l'acqua di lavaggio da bianca opaca diventa madreperlacea e semitrasparente.

Quando non si riesce più a estrarre amido, mettere il seitan così ottenuto a scolare dentro lo scolapasta.

Preparare le farine di lenticchie e semi oleosi

Le farine possono essere preparate anche in un altro momento e conservate. Per macinare le lenticchie io uso un comune macinacaffè elettrico, ma va bene anche un frullatore. La farina che si ottiene è abbastanza grossa, tipo semola. I semi oleosi (girasole, lino, sesamo) vanno macinati con un po' di lenticchie (che sono più secche).

Preparazione dell'impasto

Far girare le farine con gli aromi, unire l'olio di oliva, fino ad ottenere un impasto granuloso e omogeneo. Continuare a miscelare e unire, poco alla volta, il seitan tagliato a pezzi grossi come un mandarino.

Non serve omogeneizzare troppo, il seitan fa un po' le veci del grasso animale, per cui è meglio se rimane un po' visibile.

Dopo la miscelazione (in base alle dimensioni della pentola si puo' fare una porzione o anche due) dare una forma grossolana all'impasto e chiuderlo dentro il telino bianco.

Legare con spago bianco alimentare lasciando un po' lasco perchè con la cottura cresce di volume.

Immergere il tutto in acqua salata, non servono altri aromi. Cuocere per un'ora. Al termine scolare, mettere su un tagliere di legno ad asciugare, dopo una o due ore tagliare a fette e conservare in congelatore quello che non si consuma subito.

Per non fare attaccare le fette tra loro durante il congelamento usare strisce di carta forno tra una fetta e l'altra.

Dopo scongelamento basta riscaldare, non serve ulteriore cottura. Non ha un gran sapore, tende a prendere quello del condimento, quindi si puo' usare del sugo di pomodoro o quello che la fantasia ispira.

Una o due fette vanno bene per un normale secondo, è molto digeribile.

Valore nutrizionale

Qualcosa si perde con la cottura, va considerata fisiologica una diminuzione della disponibilità finale di vitamine e sali minerali.

L'apporto di carboidrati è minimo, ma non è la fonte principale di approvvigionamento per questo componente

Dal punto di vista proteico, possiamo calcolare:

grammi/100g peso in grammi tipo alimento totale grammi
23 400 lenticchie secche 92
13 2000 farina manitoba 260
21 100 semi di girasole 21
18 100 altri semi 18

totale = 391g (19.55g / 100g)


le proteine della carne vegetale contengono tutti gli aminoacidi essenziali (per la combinazione di legumi e cereali). Una normale fetta di manzo del peso di circa 100g contiene mediamente 18g di proteine, per cui, almeno in peso, c'è una discreta equivalenza. Il costo di preparazione della carne vegetale, al lordo di tutti i costi, non supera i 2 euro per Kg.

il peso totale della carne vegetale a fine cottura è di circa 2 kg, quindi il contenuto finale proteico è 195.5g/1000g = circa il 19.55% del peso al consumo.

Come dicevo sopra, la miscela di amminoacidi essenziali è buona, puo' sostituire integralmente la carne animale. Bisogna ricordare pero' che la dieta rimane scoperta di vitamina B12, che va quindi integrata a parte, in caso di alimentazione vegana pura.

Non mi resta che augurarvi buona sperimentazione e buon appetito.

<h1>Magic: Will, Reality and Science</h1>

Conversation between me and Gemini Me: Gemini, let's hypothesize that magic, that is, the art of causing changes in accordance w...