Class TLcdNetCDFModelDecoder

java.lang.Object
com.luciad.format.netcdf.TLcdNetCDFModelDecoder
All Implemented Interfaces:
ILcdInputStreamFactoryCapable, ILcdDataSourceModelDecoder, ILcdModelDecoder, ILcdStatusSource

Decodes NetCDF, NcML, GRIB and HDF files.

A NetCDF file includes one or more NetCDF variables, each of which represents a set of scientific measurements sampled on specific spatial coordinates, with or without times and/or vertical positions. A NetCDF variable can for example contain temperature values of oceans for different locations, times and altitudes. A NetCDF model for this variable contains an image with temperature values that can vary over different times and altitudes.

An NcML file is an XML representation of NetCDF metadata and points to a NetCDF file. Hence, the XML file always needs to be accompanied with the actual NetCDF file.

This model decoder supports NetCDF 3 and NetCDF 4 (classic and HDF5) files that follow;

  • NetCDF CF (Climate & Forecast) conventions.
  • WRF (The Weather Research & Forecasting Model) NetCDF.
In addition, the data has to be regularly gridded.

Input files

FileRequiredEntry pointDescription
*.nc, *.netcdfXXThe NetCDF file
*.xmlXNcML File
*.grb, *.grib, *.dat, *.grb2, *.grib2XGRIB File
*.hdf, *.h5, *.he5, *.hdf5XXHDF5 File

Supported file transfer protocols

  • This model decoder decodes data from a file system.

Caching

This model decoder will generate certain cache files when decoding a source (e.g. GRIB index files). If the default directory for these cache files needs to be changed, it can be done by setting the system property com.luciad.netcdf.cachedir. Setting this property prevents issues with creating cache files in case the default cache directory is non-writable. The system property can be set by providing it as a VM argument, e.g. -Dcom.luciad.netcdf.cachedir=<a-valid-path>. The directory provided in the system property will be created if it is not available.

Model structure

  • This model decoder creates a model for every NetCDF coverage variable.
  • If the input NetCDF file has more than one coverage, the resulting model is an ILcdModelTreeNode.
  • A multi variable NetCDF file can also be queried for specific coverages by using a file:// URI with query parameters.
  • All models returned by this model decoder implement ILcd2DBoundsIndexedModel.

Model descriptor

Model reference

Model elements

See TLcdNetCDFFilteredModel for more information.

Sample code

Example: Decoding a source
    String source = "Data/NetCDF/cloud_cover.nc";

    // decode the model
    TLcdNetCDFModelDecoder decoder = new TLcdNetCDFModelDecoder();
    ILcdModel model = decoder.decode(source);
Example: Decode a specific set of coverages
You can either use a string which includes query parameters
    TLcdNetCDFModelDecoder decoder = new TLcdNetCDFModelDecoder();
    String source = "Data/NetCDF/wind_u.nc";
    //Use a query parameter to indicate that only the U-component should be decoded
    ILcdModel model = decoder.decode(source + "?variable=u-component_of_wind_isobaric");
or specify a set of data sources
    TLcdNetCDFModelDecoder decoder = new TLcdNetCDFModelDecoder();
    String source = "Data/NetCDF/wind_u.nc";

    List<ILcdDataSource> allDataSources = decoder.discoverDataSources(source);
    //Filter the available data sources
    List<TLcdNetCDFDataSource> filteredDataSources =
        allDataSources.stream()
                      .filter(dataSource -> dataSource instanceof TLcdNetCDFDataSource)
                      .map(dataSource -> (TLcdNetCDFDataSource) dataSource)
                      .filter(dataSource -> dataSource.getName().toLowerCase().contains("u-component"))
                      .collect(Collectors.toList());
    //Only pass the data sources in which we are interested to the model decoder
    ILcdModel model = decoder.decodeSource(new TLcdNetCDFMultiBandDataSource(filteredDataSources));
Example: Retrieve measurements
    //Decode the model
    List<TLcdISO19103Measure> measurementsToReturn = new ArrayList<>();
    String source = "Data/NetCDF/cloud_cover.nc";
    TLcdNetCDFModelDecoder decoder = new TLcdNetCDFModelDecoder();
    ILcd2DBoundsIndexedModel model = (ILcd2DBoundsIndexedModel) decoder.decode(source);

    //Create an ALcdMeasureProvider by using the ILcdModelMeasureProviderFactory instances registered as service
    Iterator<ILcdModelMeasureProviderFactory> iterator = TLcdServiceLoader.getInstance(ILcdModelMeasureProviderFactory.class).iterator();
    ALcdMeasureProvider measureProvider = null;
    while (iterator.hasNext() && measureProvider == null) {
      ILcdModelMeasureProviderFactory factory = iterator.next();
      measureProvider = factory.createMeasureProvider(model);
    }

    //Query the ALcdMeasureProvider for the measurements at a certain location
    if (measureProvider != null) {
      ILcdModelReference modelReference = model.getModelReference();
      ILcdPoint center = model.getBounds().getCenter();

      ALcdMeasureProvider.Parameters params = ALcdMeasureProvider.Parameters.newBuilder().build();
      TLcdISO19103Measure[] measurements = measureProvider.retrieveMeasuresAt(center, modelReference, params);
      for (TLcdISO19103Measure measurement : measurements) {
        //do something with the measurement
        System.out.println("measurement = " + measurement);
      }
    }
Example: filter a NetCDF model
    String source = "Data/NetCDF/cloud_cover.nc";
    TLcdNetCDFModelDecoder decoder = new TLcdNetCDFModelDecoder();
    ILcdModel model = decoder.decode(source);

    if (model instanceof ILcdMultiDimensionalModel) {
      // get the time axis if you don't have it already
      TLcdDimensionAxis<Date> timeAxis =
          ((ILcdMultiDimensional) model).getDimensions()
                                        .stream()
                                        .map(ILcdDimension::getAxis)
                                        .filter(axis -> axis.getType().equals(Date.class))
                                        .map(axis -> (TLcdDimensionAxis<Date>) axis)
                                        .findFirst()
                                        .orElse(null);

      Date startDate = ((ILcdMultiDimensionalModel) model).getDimensions()
                                                          .stream()
                                                          .filter(dimension -> dimension.getAxis() == timeAxis)
                                                          .map(ILcdDimension::getUnionOfValues)
                                                          .map(interval -> (TLcdDimensionInterval<Date>) interval)
                                                          .map(TLcdDimensionInterval::getMin)
                                                          .findFirst()
                                                          .orElse(null);

      // create a filter for a specific date
      TLcdDimensionFilter filter = TLcdDimensionFilter
          .newBuilder()
          .filterDimension(timeAxis, TLcdDimensionInterval.createSingleValue(Date.class, startDate))
          .build();

      // apply the filter within a write lock
      try (TLcdLockUtil.Lock lock = TLcdLockUtil.writeLock(model)) {
        ((ILcdMultiDimensionalModel) model).applyDimensionFilter(filter, ILcdModel.FIRE_LATER);
      } finally {
        // fire model changes outside lock
        model.fireCollectedModelChanges();
      }
    }
For more information on how to integrate and manipulate NetCDF data into your application, refer to the NetCDF developer's guide.

Thread safety

  • The decoded models are thread-safe for read access when taking a read lock.
Since:
2015.0
  • Constructor Details

    • TLcdNetCDFModelDecoder

      public TLcdNetCDFModelDecoder()
      Create a new decoder instance.
  • Method Details