Programme de conversion du format grid au format csv pour import en d'autres applications.

Convertisseur grid à csv

Accueil

Journal de mission
Course à pied
Ski de randonnée
Alpinisme
Voile
Ecrits
Diaporamas

Programmation

Carnet des invités

Accueil > Programmation > Conversion du format grid à texte.

Programme de conversion du format grid au format csv pour import en d'autres applications.

But

Le format "grid" de CGGVeritas quoique compact, efficace et multi-applications, ne peut, autant que je ne sache, être aisément importé sous d'autres applications telle que arcview ou excel. Plusieurs applications CGGVeritas offrent de sauvegarder au format NAVP2, mais encore faut-il aussi reformatter ces NAVP2 de toutes façons.

Résumé

L'utilitaire ici proposé lit les données au format binaire et les sauve en texte, au format csv (comma separated values) de façon extrêmement rapide et simple. Ainsi;

prompt $ ./ingrid fastqc_grid

reformatte "fastqc_grid" en csv, sous un nom de fichier "fastqc_grid._csv". Il faut moins d'une seconde pour reformatter 43,000 bins.

1 - Examen du format grid

Depuis Geoland, on sauvegarde d'abord un fichier d'un seul, de deux, de trois, puis de quatre bins;

-rw-r--r-- 1 pros5 users    180 2007-11-14 16:39 1bin
-rw-r--r-- 1 pros5 users    184 2007-11-14 16:39 2bin
-rw-r--r-- 1 pros5 users    188 2007-11-14 16:39 3bin
-rw-r--r-- 1 pros5 users    192 2007-11-14 16:39 4bin

ce qui nous permet de conclure, étant donnée la simple croissance de 4 en 4, que l'information d'un bin doit tenir en quatre octets, donc d'un "float". A priori; on a donc;

formule  (1)    : taille_fichier_grid = 176 + 4 * nb_de_bins

On peut donc supposer la présence d'un quelconque header de 176 octets. On fait un test pour 10 bins, et le résultat est maintenant;

-rw-r--r-- 1 pros5 users 483388 2007-11-14 16:39 10bin

ce qui vient chambouler notre formule 1 quelque peu et que nous laissons donc de coté. Temporairement. Nous examinons les premiers bytes de nos fichiers;

prompt$ head 1bin
COMPACT-GRILLE
2
LITTLE_ENDIAN
1 1
696162.500000 3841212.500000
2481 10092
-0.000000 90.000000
25.000000 25.000000
Rectangular Unknown
Rectangular Unknown
Unknown Unknown

Intéressant. Cependant, od donne une information plus détaillée;

prompt$  od -Ad -t c 1bin
0000000   C   O   M   P   A   C   T   -   G   R   I   L   L   E  \n   2
0000016  \n   L   I   T   T   L   E   _   E   N   D   I   A   N  \n   1
0000032       1      \n   6   9   6   1   6   2   .   5   0   0   0   0
0000048   0       3   8   4   1   2   1   2   .   5   0   0   0   0   0
0000064      \n   2   4   8   1       1   0   0   9   2      \n   -   0
0000080   .   0   0   0   0   0   0       9   0   .   0   0   0   0   0
0000096   0      \n   2   5   .   0   0   0   0   0   0       2   5   .
0000112   0   0   0   0   0   0      \n   R   e   c   t   a   n   g   u
0000128   l   a   r       U   n   k   n   o   w   n  \n   R   e   c   t
0000144   a   n   g   u   l   a   r       U   n   k   n   o   w   n  \n
0000160   U   n   k   n   o   w   n       U   n   k   n   o   w   n  \n
0000176  \0  \0 200   ?
0000180

L'examen de mes fichiers sucessifs me permet de retrouver une constante, un format bien strict où se trouvent tour à tour;

1 1 la taille de ma grille, (ici 1 par 1)
696162.5 et 3841212.5les coordonnées du centre du premier bin de mon fichier
2481 10092la coordonnée i,j de mon premier bin

2 - Lecture d'en-tête

J'examine un nouvel en-tête de plus près et il semble en fait que ceux-ci contiennent en tous cas onze lignes de texte, que je peux lire ainsi;

prompt$ head -11 tests/ApexKrid_grd_Z_Coordinate11
COMPACT-GRILLE
2
LITTLE_ENDIAN
303 184
666741.500000 3837633.000000
1 1
40.849720 130.849716
33.807682 52.186699
X_Coordinate Unknown
Y_Coordinate Unknown
Z_Coordinate Unknown

Toute l'information d'une grille se trouve ici compactée. Ce qui est passablement puissant est que cette information, adjointe aux offsets mémoires des valeurs flottantes à lire par la suite, suffit pour déduire l'ensemble des coordonnées x, y de chacun des bins.

Le langage C me permet de lire, sauvegarder et imprimer ce simple en tête en ouvrant mon fichier en texte et en utilisant ensuite la fonction fgets(). Par exemple;

  /* Get the only header */
  for ( j = 0; j < 11; j++) {
    fgets ( header[j], 1024, fpin );
    printf ( "Line %d; %s", j, header[j] );
  }

imprime par exemple ceci;

Line 0; COMPACT-GRILLE
Line 1; 2
Line 2; LITTLE_ENDIAN
Line 3; 303 184
Line 4; 666741.500000 3837633.000000
Line 5; 1 1
Line 6; 40.849720 130.849716
Line 7; 33.807682 52.186699
Line 8; X_Coordinate Unknown
Line 9; Y_Coordinate Unknown
Line 10; Z_Coordinate Unknown

Il me suffira ensuite de découper les lignes 3, 4, 5, 6, 7, 8, 9, 10 et sauvegarder cette information de ma grille. On découpe ainsi en "jetons" en utilisant la fonction strtok_r(). Ainsi, dans la même boucle, j'obtiens avec;

      strcpy ( str, header[j] );
      str1 = strtok_r (str, "\n ", &saveptr1);
      str2 = strtok_r ((char *) NULL, "\n ", &saveptr1);
      printf ( "%d <%s> <%s>\n", j, str1, str2 );

La sortie suivante;

0 <COMPACT-GRILLE> <(null)>
1 <2> <(null)>
2 <LITTLE_ENDIAN> <(null)>
3 <303> <184>
4 <666741.500000> <3837633.000000>
5 <1> <1>
6 <40.849720> <130.849716>
7 <33.807682> <52.186699>
8 <X_Coordinate> <Unknown>
9 <Y_Coordinate> <Unknown>
10 <Z_Coordinate> <Unknown>

ce qui me montre que je peux maintenant extraire de "str1" et "str2" mes valeurs d'intérêts et les sauvegarder dans une structure de type GRILLE de telle sorte qu'invoquer par la suite;

  printf ("i size of grid         : %d\n", grid->i_size);
  printf ("j size of grid         : %d\n", grid->j_size);
  printf ("x origin of grid       : %.1f\n", grid->xor);
  printf ("y origin of grid       : %.1f\n", grid->yor);
  printf ("azimut of grid i axis  : %.7f\n", grid->azx);
  printf ("azimut of grid j axis  : %.7f\n", grid->azy);
  printf ("i origin of grid       : %d\n", grid->ior);
  printf ("j origin of grid       : %d\n", grid->jor);
  printf ("di of grid             : %.6f\n", grid->di);
  printf ("dj of grid             : %.6f\n", grid->dj);
  printf ("x axis label           : %s\n", grid->x_label);
  printf ("y axis label           : %s\n", grid->y_label);
  printf ("z axis label           : %s\n", grid->z_label);

me donne maintenant;

i size of grid         : 303
j size of grid         : 184
x origin of grid       : 666741.5
y origin of grid       : 3837633.0
azimut of grid i axis  : 0.7129621
azimut of grid j axis  : 2.2837584
i origin of grid       : 1
j origin of grid       : 1
di of grid             : 33.807682
dj of grid             : 52.186699
x axis label           : X_Coordinate
y axis label           : Y_Coordinate
z axis label           : Z_Coordinate

et me prouve que j'ai bel et bien relu mes valeurs, et que je suis bien en accord avec l'en-tête de mon fichier.

3 - Données

Après l'en-tête, il reste à lire les données, lesquels sont cette fois au format binaire. Je comprends aussi que la seule position offset mémoire d'une quelconque valeur flottante suffit à déterminer sa coordonnée. En effet, le fichier est réparti de telle façon qu'il fasse une taille rectangulaire de grid->i_size par grid->j_size. Connaissant l'origine, la taille di, dj et l'orientation de la grille, une transformation de coordonnées, par un passage de i,j à x,y se fera par l'appel à cette fonction;

   xy_from_ij (&x, &y, grid, i_bin, j_bin);

laquelle habille les cases mémoires où se trouvent x et y en fonction de i_bin, j_bin et, bien sûr, de la grille telle que lue de mon en-tête. Cette fonction contient donc une translation, rotation et retranslation;

int
xy_from_ij (double *x, double *y, GRILLE * grid, int i, int j)
{
  *x = (i - grid->ior) * grid->di + grid->xor;
  *y = (j - grid->jor) * grid->dj + grid->yor;
  rot (x, y, grid->xor, grid->yor, -grid->azx);
}
int
rot (double *x, double *y, float xor, float yor, double theta)
{
  double xp, yp;
  xp = (*x - xor) * cos (theta) + (*y - yor) * sin (theta);
  yp = -(*x - xor) * sin (theta) + (*y - yor) * cos (theta);
  *x = xp + xor;
  *y = yp + yor;
}

4 - Sauvegarde des coordonnées en csv

Ma fonction xy_from_ij() ayant fait le calcul, il ne reste qu'à sauvegarder le résultat du calcul en mon fichier de sortie csv. Je trouve également qu'un grand nombre négatif est discrédité par le programme. Je fais de même.

  while (!feof (fpin))
    {
      fread (&value, sizeof (float), 1, fpin);
      i_bin = offset_bin % grid->i_size + grid->ior;
      j_bin = ((int) offset_bin / grid->i_size) + grid->jor;
      xy_from_ij (&x, &y, grid, i_bin, j_bin);
      if (value > -1E+30) {
        fprintf (fpou, "%d,%d,%.1f,%.1f,%f\n", i_bin, j_bin, x, y, value);
        nb_bins++;
      }
      offset_bin++;
    }

5 - Exécution

J'ai en fastqc la grille suivante, de 42376 bins, représentant la profondeur d'eau en un certain endroit le long de la côte Tunisienne. On remarque que cette profondeur augmente du nord au sud. Est également remarquable ici un chenal bien rectiligne, dragué pour permettre le passage de traversiers. Aussi, on peut remarquer l'entrée dans un port dans le nord-ouest au bout de ce chenal.

Je lance le programme, ce qui donne à l'écran;

prompt$ ./ingrid tests/ApexKrid_grd_Z_Coordinate11
ingrid - 0.0.2 - G. Martineau - Formats a grid file as a csv - Nov 15 2007
Read header of grid file : tests/ApexKrid_grd_Z_Coordinate11
Assuming :
i size of grid         : 303
j size of grid         : 184
x origin of grid       : 666741.5
y origin of grid       : 3837633.0
azimut of grid i axis  : 0.7129621
azimut of grid j axis  : 2.2837584
i origin of grid       : 1
j origin of grid       : 1
di of grid             : 33.807682
dj of grid             : 52.186699
x axis label           : X_Coordinate
y axis label           : Y_Coordinate
z axis label           : Z_Coordinate
42376 bins saved

Je zoom sur un bin particulier, le 24,134 et remarque ses coordonnées x,y,z;

Je remarque que mon programme a écrit;

prompt$ awk '/^24,134/' tests/ApexKrid_grd_Z_Coordinate11.csv
24,134,662789.8,3843391.8,-3.975180

Les résultants me satisfaisant, je tente l'import de mon csv sous "arcview". La conclusion parle d'elle-même. C'est un succès;

Je suis donc satisfait de ma petite application à deux sous me permettant de transférer mes données vers arcview. Cette dernière application me permet sans doute moins de calculs que fastqc, mais elle permet en revanche une belle mise en page et un habillage cartographique de grande qualité,avec photos satellite, fonds de cartes différents, etc, ce qui fait toujours le plus grand bonheur du client et est donc bienvenu dans les rapports finaux.

On remarque, finalement, la taille quelque 8 fois plus grande du csv. Aussi, après utilisation, on tâchera de supprimer ce dernier fichier et de ne conserver que le grid, beaucoup moins gourmand en espace;

prompt$ ls -al tests/Ap*
-rw-r--r-- 1 pros5 users  223184 2007-11-15 14:43 tests/ApexKrid_grd_Z_Coordinate11
-rw-r--r-- 1 pros5 users 1536247 2007-11-15 16:35 tests/ApexKrid_grd_Z_Coordinate11.csv

6 - Bogues

Un mauvais format de fichier soumis en entrée causera une erreur d'exécution fatale.

7 - A faire

Vérifier le format d'entrée, les paramètres de grille.

8 - Licence et téléchargement

Le programme est publié sous la GPL.

Pour télécharger, faire un clic droit sur le lien ci-dessous, sauvegarder en "ingrid-0.0.2.tar.gz".

ingrid-0.0.2.tar.gz

A noter que pour fins de confidentialité, le fichier ici donné en exemple, a été supprimé de l'archive.

Ensuite, aller dans le répertoire de sauvegarde et lancer;

prompt$ tar xzf ingrid-0.0.2.tar.gz
prompt$ cd ingrid-0.0.2
prompt$ make
gcc -o ingrid ingrid.c -lm
ingrid has been copied into your /home/gaetan/bin directory.
Done
Run as; ingrid grid_file (will save grid_file as a csv for arcview or other)

Si un répertoire $HOME/bin est trouvé, l'exécutable sera déplacé en ce répertoire. Sinon, il demeure dans le répertoire courant d'où on le déplacera à convenance. La compilation faite, on aura le choix de modifier le code à loisir, ce qui reste un grand plaisir de la programmation, ou de simplement supprimer le source pour ne conserver que l'archive;

prompt$ cd ..; rm -Rf ingrid-0.0.2

 

Haut de page

Tous droits réservés © 2003-2006 Gaétan Martineau