Manuel du programmeur
Programmer dans libTT
|
|
|
|
|
|
|
|
|
|
Libtt est une librairie remplissant une grande partie des exigences posées aux paragraphes précédents. Nous avons choisi de programmer en C Ansi. De nombreuses structures sont utilisés comme des classes avec des constructeurs et des destructeurs. Ainsi, libtt est programmée en C mais avec une large structuration objet.
OS_UNIX_CC pour insérer les fichiers C directement dans un programme
compilé avec cc sous Unix.
OS_UNIX_CC_HP_SL pour générer libtt.sl avec un HP sous
Unix et le compilateur cc.
OS_DOS_WATC pour insérer les fichiers C directement dans un
programme compilé avec watcom sous DOS.
OS_UNIX_CC_DECBAG_SO_VADCL pour générer libtt.so avec
la Dec Station de Bagnère sous Unix et le compilateur cc.
OS_WIN_VCPP_DLL pour générer libtt.dll avec le compilateur
Visual C++ sous Windows.
OS_WIN_BORLB_DLL pour générer libtt.dll avec le compilateur
Borland Builder C++ sous Windows.
OS_WIN_BORL_DLL pour générer libtt.dll avec le compilateur
Borland 5 C++ sous Windows.
OS_DOS_WATC_LIB pour générer libtt.lib avec le compilateur
Watcom sous DOS.
OS_LINUX_GCC_SO pour générer libtt.so avec le compilateur
gcc de Linux.
juste après ces lignes, ajouter :
#ifndef __TTUSER2H__
#include "tt_user2.h"
#endif
juste aprrès cette ligne, ajouter :
TT_USER2_IMA_STACK user2;
juste aprrès cette ligne, ajouter :
TT_USER2_IMA_SERIES user2;
juste aprrès cette ligne, ajouter :
int tt_user2_ima_series_builder1(char *keys10,TT_IMA_SERIES *pseries);
int tt_user2_ima_series_builder2(TT_IMA_SERIES *pseries);
int tt_user2_ima_series_builder3(char *mot,char *argu,TT_IMA_SERIES
*pseries);
int tt_user2_ima_series_dispatch1(TT_IMA_SERIES *pseries,int
*fct_found, int *msg);
int tt_user2_ima_stack_builder1(char *keys10,TT_IMA_STACK *pstack);
int tt_user2_ima_stack_builder2(TT_IMA_STACK *pstack);
int tt_user2_ima_stack_builder3(char *mot,char *argu,TT_IMA_STACK
*pstack);
int tt_user2_ima_stack_dispatch1(TT_IMA_STACK *pstack,int *fct_found,
int *msg);
/***************************************************************************/
/* definitions perso du user1 visibles de tout libtt.
*/
/***************************************************************************/
#ifndef __TTUSER2H__
#define __TTUSER2H__
/* --- autorized between 2001 and 2999 ---*/
#define TT_IMASERIES_USER1_OFFSET_TOTO 2001
/* --- autorized between 2001 and 2999 ---*/
#define TT_IMASTACK_USER1_TUTU 2001
/* --- Ajout de parametres pour la classe ima/series --- */
typedef struct {
double param1;
} TT_USER2_IMA_SERIES;
/* --- Ajout de parametres pour la classe ima/stack --- */
typedef struct {
double param1;
} TT_USER2_IMA_STACK;
#endif
Ici, TT_IMASERIES_USER2_OFFSET_TOTO est le numéro de fonction, interne à TT, qui permettra de suivre la nouvelle fonction OFFSET_TOTO de IMA/SERIES. Pour le user 2, les numéros autorisés vont de 2001 à 2999, pour le user2 de 3001 à 3999, etc...
TT_IMASTACK_USER2_TUTU est le numéro de fonction, interne à TT, qui permettra de suivre la nouvelle fonction TUTU de IMA/STACK.
La structure TT_USER2_IMA_SERIES contient les variables des options de IMA/SERIES (ici concerne la valeur de l'option param1 de la fonction OFFSET_TOTO.
La structure TT_USER2_IMA_STACK contient les variables des options de IMA/STACK (ici concerne la valeur de l'option param1 de la fonction TUTU.
#include "tt.h"
/***** prototypes des fonctions internes du user1 ***********/
int tt_ima_series_offset_toto(TT_IMA_SERIES *pseries);
int tt_ima_stack_tutu(TT_IMA_STACK *pstack);
Toute nouvelle fonction doit aparaître obligatoirement dans le constructeur builder1 suivant :
int tt_user2_ima_series_builder1(char *keys10,TT_IMA_SERIES *pseries)
/**************************************************************************/
/* Definition du nom externe de la fonction et son lien interne
a libtt. */
/**************************************************************************/
{
if (strcmp(keys10,"OFFSET_TOTO")==0) { pseries->numfct=TT_IMASERIES_USER2_OFFSET_TOTO;
}
return(OK_DLL);
}
Si la nouvelle fonction contient des options, alors il faut initiliser ses valeurs par défaut dans le constructeur builder2 et convertir l'argument de chaîne en son type interne avec le constructeur builder3.
int tt_user2_ima_series_builder2(TT_IMA_SERIES *pseries)
/**************************************************************************/
/* Valeurs par defaut des parametres de la ligne de commande.
*/
/**************************************************************************/
{
pseries->user2.param1=0.;
return(OK_DLL);
}
int tt_user2_ima_series_builder3(char *mot,char *argu,TT_IMA_SERIES
*pseries)
/**************************************************************************/
/* Decodage de la valeur des parametres de la ligne de commande.
*/
/**************************************************************************/
{
if (strcmp(mot,"OFFSET_VALUE")==0) {
pseries->user2.param1=(double)(atof(argu));
}
return(OK_DLL);
}
Le distributeur dispatch1 permet d'assigner le nom de la fonction C concernant le calcul de la nouvelle fonction :
int tt_user2_ima_series_dispatch1(TT_IMA_SERIES *pseries,int
*fct_found, int *msg)
/*****************************************************************************/
/* Appel aux fonctions C qui vont effectuer le calcul des fonctions
externes */
/*****************************************************************************/
{
if (pseries->numfct==TT_IMASERIES_USER1_OFFSET_TOTO)
{
*msg=tt_ima_series_offset_toto(pseries);
*fct_found=TT_YES;
}
return(OK_DLL);
}
Dans notre cas, on remarque l'utilisateur connaît la fonction OFFSET_TOTO (mot clé définit dans le builder1) et que le programmeur lui associe la fonction C tt_ima_series_offset_toto pour effectuer les calculs. La fonction écrite en C peut être la suivante :
/**************************************************************************/
/**************************************************************************/
/* exemple de la fonction user OFFSET_TOTO implantee dans IMA/SERIES
*/
/**************************************************************************/
/* Fonction Offset2 (equivalent a Qmips32)
*/
/**************************************************************************/
int tt_ima_series_offset_toto(TT_IMA_SERIES *pseries)
{
TT_IMA *p_in,*p_out;
long nelem;
double value,offset;
int kkk,index;
/* --- intialisations ---*/
p_in=pseries->p_in;
p_out=pseries->p_out;
nelem=pseries->nelements;
index=pseries->index;
offset=pseries->user1.param1;
/* --- calcul de la fonction ---*/
tt_imabuilder(p_out);
tt_imacreater(p_out,p_in->naxis1,p_in->naxis2);
for (kkk=0;kkk<(int)(nelem);kkk++) {
value=p_in->p[kkk]+offset;
p_out->p[kkk]=(TT_PTYPE)(value);
}
/* --- calcul des temps (pour l'entete fits) ---*/
pseries->jj_stack=pseries->jj[index-1];
pseries->exptime_stack=pseries->exptime[index-1];
return(OK_DLL);
}
L'étape d'initialisation consiste à récupérer les informations utiles dans la structure TT_IMA_SERIES.
L'étape de calcul montre que l'image de sortie doit être écrite dans le pointeur pseries->p_out. Ce pointeur est lui même est structure d'image qu'il faut construire avec la fonction tt_imabuilder. Il n'est pas besoin de détruire pseries->p_out à la fin du calcul, cela est réalisé automatiquement par libTT. Après avoir construit le pointeur d'image de sortie, il faut le dimensionner avec tt_imacreater.
Le calcul lui même ne pose pas de difficultés. L'adressage en coordonnées (x,y) du pointeur de l'image de dimension (naxis1,naxis2) est le suivant : p[y*naxis1+x].
Les deux dernières lignes concernant les élements jj_stack et exptime_stack de la structure TT_IMA_SERIES, doivent toujours être écrites de cette façon afin que libTT puisse gérer correctement les mots clés Fits DATE-OBS et EXPTIME.
De la même façon que pour IMA/SERIES, il existe des constructeurs
et un distributeur pour les fonctions de type IMA/STACK. Dans tous les
cas, on consultera avec attention les fichiers tt_user1.h et tt_user1.c
présents dans les sources de libTT.