@LcdService(service=ILcdModelDecoder.class, priority=20000) public class TLcdNetCDFModelDecoder extends Object implements ILcdModelDecoder,ILcdDataSourceModelDecoder, ILcdStatusSource, ILcdInputStreamFactoryCapable
File | Required | Entry point | Description |
---|---|---|---|
*.nc, *.netcdf | X | X | The NetCDF file |
*.xml | X | NcML File | |
*.grb, *.grib, *.dat, *.grb2, *.grib2 | X | GRIB File | |
*.hdf, *.h5, *.he5, *.hdf5 | X | X | HDF5 File |
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.
ILcdModelTreeNode
.ILcd2DBoundsIndexedModel
.TLcdNetCDFModelDescriptor#TYPE_NAME
as type name (for NetCDF files) or with TLcdNetCDFModelDescriptor#TYPE_NAME_GRIB
(for Grib files).TLcdNetCDFModelDescriptor
.ILcdGeodeticReference
or ILcdGridReference
.TLcdNetCDFFilteredModel
instance.ILcdDataObject
and have
a property that contains an ALcdImage
. See also
TLcdNetCDFFilteredModelDataTypes
.TLcdNetCDFFilteredModel
for more information.
String source = "Data/NetCDF/cloud_cover.nc";
// decode the model
TLcdNetCDFModelDecoder decoder = new TLcdNetCDFModelDecoder();
ILcdModel model = decoder.decode(source);
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));
//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);
}
}
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.
read lock
.Modifier and Type | Class and Description |
---|---|
static class |
TLcdNetCDFModelDecoder.MultiBandImageCreation
Determines when a multi-band image should be created.
|
Constructor and Description |
---|
TLcdNetCDFModelDecoder()
Create a new decoder instance.
|
Modifier and Type | Method and Description |
---|---|
void |
addStatusListener(ILcdStatusListener aListener)
Registers the given listener so it will receive status events from this source.
|
boolean |
canDecodeSource(ILcdDataSource aDataSource)
Checks whether this model decoder can decode the data source(s), identified by the passed
ILcdDataSource . |
boolean |
canDecodeSource(String aSource)
Checks whether this model decoder can decode the specified data source.
|
ILcdModel |
decode(String aSource)
Creates a new model from the given data source.
|
TLcdModelMetadata |
decodeModelMetadata(ILcdDataSource aDataSource)
Decodes the model metadata of a NetCDF source.
|
ILcdModel |
decodeSource(ILcdDataSource aDataSource)
Creates a new model from the given data source.
|
List<ILcdDataSource> |
discoverDataSources(String aSource)
Fetch the data sources from the given NetCDF file path.
|
String |
getDisplayName()
Returns a short, displayable name for the format that is decoded by this
ILcdModelDecoder . |
ILcdInputStreamFactory |
getInputStreamFactory()
Returns the input stream factory that is used.
|
TLcdNetCDFModelDecoder.MultiBandImageCreation |
getMultiBandImageCreation()
Returns when multi-band images are created.
|
void |
removeStatusListener(ILcdStatusListener aListener)
Removes the specified listener so it is no longer notified.
|
void |
setInputStreamFactory(ILcdInputStreamFactory aInputStreamFactory)
Sets the input stream factory to be used.
|
void |
setMultiBandImageCreation(TLcdNetCDFModelDecoder.MultiBandImageCreation aMultiValuedRasterCreation)
Configures the creation of multi-band images.
|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
decodeModelMetadata
public TLcdNetCDFModelDecoder()
public TLcdNetCDFModelDecoder.MultiBandImageCreation getMultiBandImageCreation()
AUTO
or NEVER
.setMultiBandImageCreation(com.luciad.format.netcdf.TLcdNetCDFModelDecoder.MultiBandImageCreation)
public void setMultiBandImageCreation(TLcdNetCDFModelDecoder.MultiBandImageCreation aMultiValuedRasterCreation)
Configures the creation of multi-band images. Multi-band images combine related datasets, such as the x and y components of a wind measurement. They are typically visualized with a grid of icons.
When loading GRIB 1 files, setting this flag to AUTO
will also make sure that the decode
method looks for other related GRIB files next to the one being decoded. For example, when passing a GRIB
file that only contains 'wind U' data, it will also look for a file that contains 'Wind V' data. This automatic
combining is based on a heuristic that assumes that the GRIB parameter ID is part of the file name.
In case setting this flag to AUTO
fails to automatically create multi-band images, it is possible
to combine them manually. This can be done by passing a TLcdNetCDFMultiBandDataSource
to the decodeSource
method.
aMultiValuedRasterCreation
- used to configure when multi-band images are created, AUTO
or NEVER
getMultiBandImageCreation()
public String getDisplayName()
ILcdModelDecoder
ILcdModelDecoder
.getDisplayName
in interface ILcdModelDecoder
ILcdModelDecoder
.public boolean canDecodeSource(String aSource)
ILcdModelDecoder
true
for a source name while decode
throws an exception for that same source name.
For performance reasons, we strongly recommend that this will only be a simple test. For example: check the file extension of a file, but not that the file exists or contains expected content.
canDecodeSource
in interface ILcdModelDecoder
aSource
- the data source to be verified; typically a file name or a URL.true
if this decoder can likely decode the data specified by the source name, false
otherwise.ILcdModelDecoder.decode(String)
,
ILcdModelDecoder.decodeModelMetadata(String)
public List<ILcdDataSource> discoverDataSources(String aSource) throws IOException
Fetch the data sources from the given NetCDF file path.
The data sources are either TLcdNetCDFDataSource
or TLcdNetCDFMultiBandDataSource
instances.
Data sources are combined in a TLcdNetCDFMultiBandDataSource
if they are related.
To only get single-band sources, set the multi-band image creation of this decoder to TLcdNetCDFModelDecoder.MultiBandImageCreation.NEVER
using the setMultiBandImageCreation(com.luciad.format.netcdf.TLcdNetCDFModelDecoder.MultiBandImageCreation)
method
To identify the type of data that is represented by a TLcdNetCDFDataSource
instance, you can retrieve the full name
of the NetCDF variable using the TLcdNetCDFDataSource.getName()
method.
To identify the type of data that is represented by a TLcdNetCDFMultiBandDataSource
instance, you can retrieve data sources
that are part of the multi-band source by using the TLcdNetCDFMultiBandDataSource.getDataSources()
method.
discoverDataSources
in interface ILcdModelDecoder
aSource
- a path to a NetCDF file.null
.
Note that not all data sources returned may be supported by this decoder.IOException
- if the decoder can't decode the source file.public boolean canDecodeSource(ILcdDataSource aDataSource)
Checks whether this model decoder can decode the data source(s), identified by the passed ILcdDataSource
.
For performance reasons, we strongly recommend that this will only be a simple test.
For example: check the instance class of aDataSource
,
or check the file extension if it is a TLcdDataSource
.
The default implementation of this method will check if the given ILcdDataSource
is a
TLcdDataSource
. If not, this method returns false. Otherwise, it delegates
the source to the ILcdModelDecoder.canDecodeSource(String)
method.
Supported data sources are:
canDecodeSource
in interface ILcdModelDecoder
aDataSource
- the ILcdModelSource
to be verified.true
if this decoder can likely decode the data specified by aDataSource
, false
otherwise.ILcdModelDecoder.decodeSource(ILcdDataSource)
,
ILcdModelDecoder.decodeModelMetadata(ILcdDataSource)
public ILcdModel decode(String aSource) throws IOException
ILcdModelDecoder
decode
in interface ILcdModelDecoder
aSource
- the data source to be decoded; typically a file name or a URL.null
is allowed, implementors are advised to throw an error instead.IOException
- for any exceptions caused by IO problems or invalid data. Since decoding invalid data almost
always results in RunTimeExceptions (NullPointerException, IndexOutOfBoundsException,
IllegalArgumentException, ...) on unexpected places, implementations are advised to catch
RuntimeExceptions in their decode() method, and wrap them into an IOException, as illustrated
in the code snippet below.
public ILcdModel decode( String aSourceName ) throws IOException {
try (InputStream input = fInputStreamFactory.createInputStream(aSourceName)) {
// Perform decoding ...
} catch (RuntimeException e) {
throw new IOException(e);
}
}
InterruptedIOException
- When the thread on which this method is called is interrupted: it is recommended to stop the decoding
and throw an InterruptedIOException
.
This same exception can also be used if the decoder shows UI to the user, and the user cancels the decoding
through the UI.ILcdModelDecoder.canDecodeSource(String)
public TLcdModelMetadata decodeModelMetadata(ILcdDataSource aDataSource) throws IOException
Supported data sources are:
For multi-band sources, one of the sources is used as the entry point source of the model metadata. All other sources will be set as the supporting sources of the model metadata.
decodeModelMetadata
in interface ILcdModelDecoder
aDataSource
- the data source to be decoded.TLcdModelMetadata
instance containing the model metadata of the NetCDF model of the source.IOException
- If the given source cannot be decoded for some reason.discoverDataSources(String)
public ILcdModel decodeSource(ILcdDataSource aDataSource) throws IOException
Creates a new model from the given data source.
By default, this method:
NullPointerException
when a null
data source is passed.ILcdModelDecoder.decode(String)
method when a TLcdDataSource
is passed.Supported data sources are:
decodeSource
in interface ILcdModelDecoder
aDataSource
- the ILcdDataSource
to be decoded.null
is allowed, implementors are advised to throw an error instead.IOException
- for any exceptions caused by IO problems or invalid data. Since decoding invalid data almost
always results in RunTimeExceptions (NullPointerException, IndexOutOfBoundsException,
IllegalArgumentException, ...) on unexpected places, implementations are advised to catch
RuntimeExceptions in their decode() method, and wrap them into an IOException, as illustrated
in the code snippet below.
public ILcdModel decodeSource(ILcdDataSource aDataSource) throws IOException {
try {
// Perform decoding ...
} catch (RuntimeException e) {
throw new IOException(e);
}
}
ILcdModelDecoder.canDecodeSource(ILcdDataSource)
public void addStatusListener(ILcdStatusListener aListener)
ILcdStatusSource
Registers the given listener so it will receive status events from this source.
In case you need to register a listener which keeps a reference to an object with a shorter life-time than this status source,
you can use a ALcdWeakStatusListener
instance as status listener.
addStatusListener
in interface ILcdStatusSource
aListener
- The listener to be notified when the status has changed.public void removeStatusListener(ILcdStatusListener aListener)
ILcdStatusSource
removeStatusListener
in interface ILcdStatusSource
aListener
- The listener to remove.public void setInputStreamFactory(ILcdInputStreamFactory aInputStreamFactory)
File.createTempFile(String, String)
in the OS temporary files directory.setInputStreamFactory
in interface ILcdInputStreamFactoryCapable
aInputStreamFactory
- the input stream factory to be used.ILcdModel.dispose()
public ILcdInputStreamFactory getInputStreamFactory()
ILcdInputStreamFactoryCapable
getInputStreamFactory
in interface ILcdInputStreamFactoryCapable