La bibliothèque NetCDF-Java/CDM lit de nombreux formats de fichiers binaires différents tels que NetCDF, HDF, GRIB, NEXRAD, etc., et rend les données accessibles via une API standard. Elle permet également de lire des jeux de données distants via OPeNDAP ou d'autres protocoles d'accès distant. En utilisant le langage NcML (NetCDF Markup Language), on peut aussi créer des jeux de données virtuels en modifiant et en agrégeant d'autres jeux de données. Dans le cas général, nous appellerons toute collection de données scientifiques accessibles via la bibliothèque NetCDF-Java/CDM un jeu de données CDM.

Le langage NcML est un dialecte XML qui vous permet de créer des jeux de données CDM. Le but de NcML est de permettre de:

  • Ajouter, supprimer et modifier des métadonnées,
  • Renommer, ajouter, supprimer et restructurer des variables,
  • Agréger les données de plusieurs fichiers.

Note

Pour cette partie du TP, on travaillera sur les données Upper Tropospheric Humidity du radiomètre Saphir du satellite Franco-Indien Megha-Topiques. Les données sont disponibles au format HDF dans le répertoire /anfsist/data/megha-tropiques.

Création du catalogue des données Megha-Tropiques

![](img/TP4.gif) Déclarer un nouveau catalogue racine `meghatrop-catalog.xml` dans le fichier de configuration de TDS `threddsConfig.xml`. Ce nouveau catalogue sera accessible à l'adresse [http://127.0.0.1:8080/thredds/meghatrop-catalog.html](http://127.0.0.1:8080/thredds/meghatrop-catalog.html)
  <catalogRoot>meghatrop-catalog.xml</catalogRoot>
![](img/TP4.gif) Editer le fichier catalogue `meghatrop-catalog.xml` pour décrire le nouveau dataset à partir d'une balise `datasetScan` et en incluant l'ensemble des fichiers HDF du répertoire `/anfsist/data/megha-tropiques`.
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="http://www.unidata.ucar.edu/namespaces/thredds/InvCatalog/v1.0" xmlns:xlink="http://www.w3.org/1999/xlink" 
   name="SIRTA Data Catalog" >

  <service name="all" base="" serviceType="compound">
    <service name="odap" serviceType="OpenDAP" base="/thredds/dodsC/" />
    <service name="http" serviceType="HTTPServer" base="/thredds/fileServer/" />
    <service name="ncss" serviceType="NetcdfSubset" base="/thredds/ncss/" />
    <service name="wcs" serviceType="WCS" base="/thredds/wcs/" />
    <service name="wms" serviceType="WMS" base="/thredds/wms/" />
    <service name="ncml" serviceType="NCML" base="/thredds/ncml/"/>
    <service name="uddc" serviceType="UDDC" base="/thredds/uddc/"/>
    <service name="iso" serviceType="ISO" base="/thredds/iso/"/>
    <service name="sos" serviceType="SOS" base="/thredds/sos/" />
  </service>

  <!-- Jeu de données multi-fichiers -->
  <!-- Attention le Path ne doit pas déjà exister dans un autre datasetRoot ou datasetScan -->
  <datasetScan name="Megha-Tropiques Upper Tropospheric Humidity" ID="MTUTH"
      path="mtdir" location="/anfsist/data/megha-tropiques/">
    <metadata inherited="true">
      <serviceName>all</serviceName>
      <dataType>Grid</dataType>
    </metadata>

    <filter>
      <include wildcard="*.hdf"/>
    </filter>
  </datasetScan>

</catalog>
  • Une fois les données servies par TDS, il est possible d'y accéder au travers des différents protocoles mis en place. On peut noter par exemple, que les fichiers HDF qui ne sont pas reconnus par la librairie NetCDF, peuvent être exploités par celle-ci en passant par le service OpenDAP du serveur THREDDS :
$ ncdump -h /anfsist/data/megha-tropiques/MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T22-33-49_V2-00.hdf
ncdump: /anfsist/data/megha-tropiques/MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T00-42-18_V2-00.hdf: NetCDF: Attempt to use feature that was not turned on when netCDF was built.

$ ncdump -h http://127.0.0.1:8080/thredds/dodsC/mtdir/MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T22-33-49_V2-00.hdf
netcdf MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T22-33-49_V2-00 {

// global attributes:
                :File_Name = "MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T22-33-49_V2-00.hdf" ;
                :Icare_ID = "2017-11-01T22:33:49" ;
                :Mission = "Megha-Tropiques" ;
                :Product_Name = "L2-UTH-SAPSL1A2-1.08" ;
                :Product_Description = "A Saphir-only scheme has been developed in order to derive the upper tropospheric humidity (UTHs) from the 3 upper channels (+/- 0.2 GHz, +/- 1.1 GHz and +/-2.8 GHz). This retrieval follows the method developed initially for IR measurements (6.3 microns) of the HIRS (e.g. Soden & Bretherton, 1993) and METEOSAT-MVIRI (e.g. Schmetz and Turpeinen, 1988) radiometers and recently applied to microwave observations (Spencer & Braswell, 1997; Buehler & John, 2005)" ;
                :HDF_Version = "HDF Version 4.2 Release 5, February 17, 2010" ;
                :Beginning_Acquisition_Date = "2017-11-01T22-33-49" ;
                :End_Acquisition_Date = "2017-11-02T00-30-15" ;
                :Nadir_Pixel_Size = "10 km" ;
                :Software_Version = "1.3.0" ;
                :Scientific_Software_Version = "1.3.0" ;
                :Product_Version = "V2-00" ;
                :Production_Center = "ICARE" ;
                :Production_Date = "2017/11/14 08:12:08" ;
                :North_Bounding_Latitude = 28.02f ;
                :South_Bounding_Latitude = -27.5f ;
                :West_Bounding_Longitude = 0.f ;
                :East_Bounding_Longitude = 360.f ;
                :Sensors = "MT/SAPHIR" ;
                :Input_Files = "MT1SAPSL1A2_1.08_000_1_19_I_2017_11_01_22_32_49_2017_11_02_00_30_15_31261_31262_323_28_29_BL4_00.h5" ;
                :Ancillary_Files = "None" ;
                :nb_invalid_scan = 0s ;
                :Level1_Version = "ISRO_SAC_DP-MT1-SAPL1A2SW-VER-1.08F000(ISRO_SAC_DP-MT1-SW_PROD_ID-111_11_L1A__111_11_L1A2-0009000)" ;
                :RAD_AuxFile_Version = "1_19" ;
                :GEO_AuxFile_Version = "1_19" ;
                :_History = "Direct read of HDF4 file through CDM library" ;
                :HDF4_Version = "4.2.5 (HDF Version 4.2 Release 5, February 17, 2010)" ;
}

Agrégation de fichiers de données

Dans la suite du TP, nous allons créer un jeu de données virtuel en agrégeant les fichiers de données Megha-Topiques grâce au langage NCML.

Il existe plusieurs forme d'agrégations possibles gérées pat TDS (liste détaillée ici):

  • Union : union de toutes les dimensions, attributs et variables de plusieurs fichiers NetCDF.
  • JoinExisting : Les variables du même nom (dans différents fichiers) sont agrégées suivant une dimension existante, appelée dimension d'agrégation. Une variable de coordonnées doit exister pour cette dimension.
  • JoinNew : Les variables du même nom (dans différents fichiers) sont agrégées suivant une nouvelle dimension externe. Une nouvelle variable de coordonnées est créée pour cette dimension.
  • ForecastModelRunCollection (FMRC) : ce type d'agrégation gère les modèles de prévisions avec deux coordonnées temporelles : une heure d'exécution et une heure de prévision.

Dans la suite, on testera les agrégations de type JoinExisting et JoinNew.

Agrégation sur une nouvelle dimension

Les fichiers HDF de Megha-Topiques vont ici être agrégés dans un nouveau jeu de données suivant une dimension qui n'existe pas dans les fichiers de données d'origine.

Ajouter le dataset défini comme suit dans le catalogue meghatrop-catalog.xml :

<!-- Jeu de données multi-fichiers agrégés suivant   une nouvelle dimension-->
<dataset name="HDF MeghaTropique Dataset Aggregated" ID="MTUTHNcML-Aggregated" urlPath="MTUTH/Aggregated.nc">
    <metadata inherited="true">
      <serviceName>all</serviceName>
      <dataType>Grid</dataType>
    </metadata>

  <netcdf xmlns="http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2" >
    <aggregation dimName='time' type="joinNew">
      <variableAgg name ="Time"/>
      <scan location="/anfsist/data/megha-tropiques/" suffix=".hdf"/>
    </aggregation>
  </netcdf>
</dataset>
  • Dans l'exemple précédent, la nouvelle dimension Time n'est pas définie; TDS utilise dans ce cas le nom des fichiers comme valeurs de la nouvelle dimension. L'extraction OpenDAP de la variable Time montre :
Dataset {
    String time[time = 12];
} MTUTH/AggregatedNew.nc;
---------------------------------------------
time[12]
"MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T00-42-18_V2-00.hdf", "MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T02-24-35_V2-00.hdf", 
"MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T04-14-14_V2-00.hdf", "MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T06-04-21_V2-00.hdf",
"MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T09-03-50_V2-00.hdf", "MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T10-53-19_V2-00.hdf",
"MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T12-43-38_V2-00.hdf", "MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T14-57-10_V2-00.hdf", 
"MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T18-01-26_V2-00.hdf", "MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T18-54-38_V2-00.hdf", 
"MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T20-44-28_V2-00.hdf", "MT1_L2-UTH-SAPSL1A2-1.08_2017-11-01T22-33-49_V2-00.hdf"

Modifier le dataset précédemment défini pour définir la variable Time :

<!-- Jeu de données multi-fichiers agrégés suivant une nouvelle dimension-->
<dataset name="HDF MeghaTropique Dataset Aggregated - joinNew" ID="MTUTHNcML-AggregatedNew" urlPath="MTUTH/AggregatedNew.nc">
    <metadata inherited="true">
      <serviceName>all</serviceName>
      <dataType>Grid</dataType>
    </metadata>

  <netcdf xmlns="http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2" >
    <variable name="time" type="int" >
      <attribute name="units" value="months since 2000-6-16 6:00"/>
      <attribute name="_CoordinateAxisType" value="Time" />
      <!--values>0 1 2 3 4 5 6 7 8 9 10 11</values-->
      <values start="0" increment="1"/>
    </variable>
    <aggregation dimName='time' type="joinNew">
      <variableAgg name ="Time"/>
      <scan location="/anfsist/data/megha-tropiques/" suffix=".hdf"/>
    </aggregation>
  </netcdf>
</dataset>

Noter dans cet exemple que les valeurs de time peuvent être définies explicitement (<!--values>0 1 2 3 4 5 6 7 8 9 10 11</values-->) ou avec une valeur de début et un incrément (<values start="0" increment="1"/>).

  • L'extraction OpenDAP de la variable Time montre maintenant :
Dataset {
    Int32 time[time = 12];
} MTUTH/AggregatedNew.nc;
---------------------------------------------
time[12]
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11

Agrégation sur une dimension existante

Il est également possible d'agréger les fichiers suivant une dimension ou un paramètre déjà existant.

Extraction des informations d'agrégation à partir des noms de fichiers

Dans cet exemple, les fichiers HDF de Megha-Topiques vont être agrégés dans un nouveau jeu de données en tenant compte de la date contenue dans le nom du fichier.

Ajouter le dataset défini comme suit dans le catalogue meghatrop-catalog.xml :

<!-- Jeu de données multi-fichiers agrégés suivant une dimension existante-->
<dataset name="HDF MeghaTropique Dataset Aggregated - joinExisting" ID="MTUTHNcML-AggregatedExisting" urlPath="MTUTH/AggregatedExisting.nc">
    <metadata inherited="true">
      <serviceName>all</serviceName>
      <dataType>Grid</dataType>
    </metadata>

    <netcdf xmlns="http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2">
      <aggregation dimName="time" type="joinExisting" recheckEvery="30 min">
        <scan location="/anfsist/data/megha-tropiques/"
         dateFormatMark="MT1_L2-UTH-SAPSL1A2-1.08_#yyyy-MM-dd'T'HH-mm-ss" suffix=".hdf" subdirs="false" />
      </aggregation>
    </netcdf>
</dataset>

Noter :

  • dimName indique le nom de la dimension d'agrégation : time
  • recheckEvery permet d'indiquer à quelle fréquence exécuter le scan du répertoire de données pour prendre en compte des ajout ou suppression de données.
  • dateFormatMark permet de décrire le champs date et heure à partir duquel la variable time prendra ses valeurs

  • L'extraction OpenDAP de la variable Time montre maintenant :

Dataset {
    String time[time = 12];
} MTUTH/AggregatedExisting.nc;
---------------------------------------------
time[12]
"2017-11-01T00:42:18Z", "2017-11-01T02:24:35Z", "2017-11-01T04:14:14Z", 
"2017-11-01T06:04:21Z", "2017-11-01T09:03:50Z", "2017-11-01T10:53:19Z", 
"2017-11-01T12:43:38Z", "2017-11-01T14:57:10Z", "2017-11-01T18:01:26Z", 
"2017-11-01T18:54:38Z", "2017-11-01T20:44:28Z", "2017-11-01T22:33:49Z"

Concaténation suivant la dimension temporelle

Pour cette partie, on utilisera à nouveau le catalogue des données du SIRTA.

Editer le fichier sirta-catalog.xml pour ajouter le dataset défini comme suit :

<!-- Jeu de données multi-fichiers agrégés suivant une dimension existante-->
<dataset name="Sirta Wind Profiles Aggregated" ID="SirtaWP-Aggregated" urlPath="sirtadir/Aggregated.nc">
    <metadata inherited="true">
      <serviceName>all</serviceName>
      <dataType>Grid</dataType>
    </metadata>

    <netcdf xmlns="http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2">
      <aggregation dimName="time" type="joinExisting" recheckEvery="30 min">
        <scan location="/anfsist/data/sirta/" suffix=".nc" subdirs="false" />
      </aggregation>
    </netcdf>
</dataset>
  • Le nouveau jeu de données défini crée ainsi un fichier virtuel contenant les données de l'ensemble des fichiers NetCDF Sirta.
Visualisation des données du serveur THREDDS avec Panoply

Exécuter Panoply

$ panoply
  • A l'ouverture de la boite de dialogue cliquer sur Annuler
  • Dans le menu File, cliquer sur Open Remote Catalog
  • Entrer l'URL du catalog THREDDS SIRTA : http://localhost:8080/thredds/sirta-catalog.xml, puis Load
  • Sélectionner le jeu de données Sirta Wind Profiles Aggregated, puis cliquer sur le lien OpenDAP pour charger les données dans Panoply
  • Dans la liste des datasets, sélectionner un jeu de données, ws_100 par exemple
  • Cliquer sur "Create a plot", puis "Create"

Le catalogue THREDDS sert l'ensemble des données des fichiers du SIRTA comme s'il s'agissait d'un unique fichier :