Class TLcdNetCDFFilteredModel

All Implemented Interfaces:
ILcd2DBoundsIndexedModel, ILcd2DBoundsInteractable, ILcdIntegerIndexedModel, ILcdModel, ILcdMultiDimensional, ILcdMultiDimensionalModel, ILcdBounded, ILcdTimeBounded, ILcdLockDependent, ILcdDisposable, Serializable, AutoCloseable

public class TLcdNetCDFFilteredModel extends TLcd2DBoundsIndexedModel implements ILcdTimeBounded, ILcdMultiDimensionalModel, ILcdLockDependent

This model wrapper around a NetCDF model makes it possible to filter NetCDF data. This model is suited for visualization: it can be visualized by default by the raster painting code, and it makes sure that only one image is painted at the same time. The image that will be painted can be selected using the applyDimensionFilter method. All the dimensions and possible filter values can be obtained using the getDimensions() method. The unfiltered (wrapped) NetCDF model can be retrieved using the getUnfilteredModel() method.

This model contains domain objects (typically one) that implements ILcdDataObject and contains an image in one of its properties. This property can be retrieved by inspecting the TLcdHasGeometryAnnotation of the data type.

The domain objects also contain properties that describe their time and vertical position. See TLcdNetCDFFilteredModelDataTypes.

Since:
2015.0
See Also:
  • Constructor Details

    • TLcdNetCDFFilteredModel

      public TLcdNetCDFFilteredModel(ILcdModel aModel)
      Creates a new model wrapper around an unfiltered (multidimensional) model.
      Parameters:
      aModel - an unfiltered NetCDF model.
      Throws:
      IllegalArgumentException - when the given model is not an unfiltered NetCDF model.
  • Method Details

    • getUnfilteredModel

      public ILcdModel getUnfilteredModel()

      Returns the unfiltered model that is wrapped by this filtered model instance. The unfiltered model contains domain objects (typically one) that implement the ILcdMultiDimensional interface. It can be used to retrieve the possible axes and dimension intervals for which data is available. Note that the data (i.e. the ALcdImage objects) itself can only be retrieved using the filtered model.

      Returns:
      the unfiltered model that is wrapped by this filtered model instance.
    • setFilterParameter

      public void setFilterParameter(TLcdDimensionAxis<?> aAxis, TLcdDimensionInterval<?> aInterval, int aEventMode)

      Sets one of the filter parameters. Filter parameters are for example a time or depth. This method can for example be used to select one image that represents temperature at a specific time or depth. The possible axes and dimension intervals to use can be retrieved from the getDimensionAxes method. Note that these axes don't include spatial (i.e. lon/lat) axes.

      Calling this method can modify the model elements contained in this model. Please refer to ILcdModel's Changing data for threading and locking policies. After this method is called, the geometry property of the domain object (which implements ILcdDataObject) is modified. Note that it is possible that the model elements contained in this model are not modified after calling this method.

      Parameters:
      aAxis - the dimension axis on which to filter
      aInterval - the interval defined on the given axis used for filtering.
      aEventMode - the mode for sending out the model change event. This can be one of FIRE_NOW, FIRE_LATER or NO_EVENT.
      See Also:
    • getFilterParameter

      public TLcdDimensionInterval<?> getFilterParameter(TLcdDimensionAxis<?> aAxis)
      Deprecated.
      Returns the currently used filter parameter that corresponds to the given axis.
      Parameters:
      aAxis - the axis for which to retrieve the filter parameter.
      Returns:
      the currently used filter parameter that corresponds to the given axis.
      See Also:
    • getDimensionAxes

      public Collection<TLcdDimensionAxis<?>> getDimensionAxes()
      Deprecated.
      use getDimensions() instead.

      Returns the axes for which data is available. See applyDimensionFilter(com.luciad.multidimensional.TLcdDimensionFilter, int) setFilter}. Note that the returned collection is unmodifiable. Axes can for example represent time or depth. This means that it is possible to retrieve different images for different times or depths. Note that the returned axes don't include spatial (i.e. lon/lat) axes or axes for the actual data (e.g. temperature), only the axes using which can be filtered.

      The axes returned in this method contain either Date or TLcdISO19103Measure intervals.

      Returns:
      the axes for which data is available.
    • applyDimensionFilter

      public void applyDimensionFilter(TLcdDimensionFilter aFilter, int aEventMode)
      Description copied from interface: ILcdMultiDimensionalModel
      Applies a given dimensional filter and fires an event accordingly. The given filter may specify one interval per axis. The filter may contain more or less axes than the model supports.
      • If the filter contains more axes than the model supports, the model should ignore those axes.
      • If the filter contains less axes than the model supports, the model should reset to its default for those axes.
      In particular, in case of the empty filter, the model should reset to the default filter. The default filter is typically an accept-all filter, but the specific behavior depends on the model implementation.

      Filtering behavior
      In practice, filtering behavior and the default filter depend on the type of the model:

      • Vector models, such as NVG or ASTERIX, have multiple elements, where every element is a domain object. Each element has a validity defined by an interval, for example a temporal interval on a time axis. The filtered model will only contain the elements that match the filter. When a new filter is applied, events will be fired as elements are removed or added based on the new filter. The default filter in this case is 'no filter', which means that all elements match the filter and the model behaves as if unfiltered. In case no elements match the filter, the model will be empty.
      • Raster models, such as NetCDF, have a single or a couple of model elements, where every model element corresponds with exactly one image. Internally, each element is possibly backed up by multiple ALcdImage instances, every one of which is valid within a certain interval. An implementation of this interface needs to make sure that
        • a model element only corresponds with exactly one of these images, based on the currently configured filter.
        • the model element's image is available through ALcdImage.fromDomainObject(java.lang.Object). We advise to use the 'has-an-image' paradigm to expose this image, because it allows for faster updates in a Lightspeed view.
        • changes in filtering are correctly applied. When a filter is changed, it must either replace the element with a new element, or when the 'has-an-image' paradigm is used, it must replace the image that is exposed by the model element. When a filter doesn't match anything, it must make sure that there is no element present in the model. Using 'has-an-image' with a null image is not a valid way to express this.
        Typically, the default image will be the 'first' image.
      Example: consider a NetCDF model with an initial filter which selects the 'first' image. The NetCDF model has two dimensions: time and vertical position. Suppose a filter is applied for a specific time and vertical position: the model's domain object selects the corresponding image and fires an appropriate event. Now suppose a filter is applied for a specific time but no vertical position: multiple images match for multiple vertical positions, but the model selects the 'first'.

      Filter matching
      Matching intervals happens based on TLcdDimensionInterval.overlaps(com.luciad.multidimensional.TLcdDimensionInterval<T>, com.luciad.multidimensional.TLcdDimensionInterval<T>). The rationale for this is the following:

      • Each element has a validity defined by an interval, for example on a time axis.
      • Using the filter, you're asking the model to "match everything which is valid in the filter interval(s)", which corresponds to the meaning of overlap.

      Locking
      This method should typically be called from within a write lock:

      
          try (TLcdLockUtil.Lock lock = TLcdLockUtil.writeLock(model) {
            ...
            model.applyDimensionFilter(filter, ILcdModel.FIRE_LATER);
            ...
          } finally {
            model.fireCollectedModelChanges();
          }
       
      The most common exception to this rule is when you're creating a model initially and no-one has a reference to it yet: in that case, it's safe to not lock at all and use ILcdModel.NO_EVENT.

      No snapping
      Implementations should not 'snap' to the intervals defined by the filter in case no elements match. There shall be no snapping to nearest, previous or next. Instead, the result must be 'empty' (or 'image is null' in case of raster models). If you need to snap a filter interval to an actual interval the model has to offer, you should use TLcdDimensionFilter.createSnappingFilter(com.luciad.multidimensional.ILcdMultiDimensionalModel, com.luciad.multidimensional.TLcdDimensionFilter.SnapMode) to create a snapped filter.

      Differences with createSnappingFilter
      As its name suggests, the primary purpose of the utility method createSnappingFilter is to create a filter which 'snaps' to filter intervals so that there is always at least one match. But the method does more than just that. Here is a list of differences between using and not using createSnappingFilter:

      Behavior applyDimensionFilter createSnappingFilter->applyDimensionFilter
      Snapping Never, possibly resulting in no matches Snaps to intervals defined by the model if needed, such that there is always at least one match
      Supported snap modes None Nearest, previous, next, or none (null)
      Filter has less axes than supported by model Reset to default for those axes Keep the last current filter value for those axes, so that there are minimal model changes
      Empty filter Reset to default filter Keep current filter, so that there are no model changes
      ILcdModel which is not ILcdMultiDimensionalModel Not supported Checks instance of ILcdMultiDimensionalModel, leaves others alone
      Specified by:
      applyDimensionFilter in interface ILcdMultiDimensionalModel
      Parameters:
      aFilter - The dimensional filter, possibly empty but never null.
      aEventMode - The mode of the event that should be triggered when the value of the filter parameters changes.
      See Also:
    • getDimensionFilter

      public TLcdDimensionFilter getDimensionFilter()
      Description copied from interface: ILcdMultiDimensionalModel
      Gets the current dimensional filter, possibly empty but never null. The current dimensional filter is the last one that was set on this model using ILcdMultiDimensionalModel.applyDimensionFilter(TLcdDimensionFilter, int). It may contain more or less dimensions than this model supports, and it may be empty (TLcdDimensionFilter.EMPTY_FILTER), but it must never be null. The filter intervals may but does not have to be one of the intervals given by getDimensions().getValues().

      When no dimensional filter has been set on this model yet, this method returns the default dimensional filter. The default dimensional filter depends on the implementation. Typical implementations:

      • Multi-dimensional raster models, such as NetCDF, typically define a default filter which matches exactly one combination of dimensional values, often the first combination. The reason for this is that the rasters are typically mutually exclusive: only one can be included in the filtered result. Intuitively, this corresponds to a "match any" or "match first" filter.
      • Multi-dimensional object models, such as NVG, typically define an unbounded default filter which matches all objects. The reason for this is that the objects are are not mutually exclusive: they can all be included in the filtered result. Intuitively, this corresponds to "no filter".

      The default filter is not necessarily constant. It may change as elements are added to or removed from the model, because the default filter is often computed from the dimensional information of the elements.

      Specified by:
      getDimensionFilter in interface ILcdMultiDimensionalModel
      Returns:
      The current dimensional filter, possibly the TLcdDimensionFilter.EMPTY_FILTER but never null.
    • getDimensions

      public List<TLcdDimension<?>> getDimensions()
      Gets a list of dimensions, for example time or height, over which this multi-dimensional object is defined. Each dimension defines an axis, its possible values, and the range of possible values. The values of the dimension axes are all the possible values this multi-dimensional object can be filtered on. An empty list means that the instance is not dimensionally filterable.

      If this model is an interpolated one, the returned dimensions from this method consist of regular (=non-single-value) intervals between all values for which data is available. Otherwise the returned dimensions consist of multiple single-value intervals, one for each piece of data.

      Specified by:
      getDimensions in interface ILcdMultiDimensional
      Returns:
      a list dimensions (axes and their possible values) over which this multi-dimensional object is defined, possibly empty but never null.
      See Also:
    • getDimension

      public <T> ILcdDimension<T> getDimension(TLcdDimensionAxis<T> aAxis)

      Returns the data ranges for which data is available. These contain the possible intervals that can be used for filtering. See applyDimensionFilter(TLcdDimensionFilter, int) applyDimensionFilter}. Note that the returned collection is unmodifiable. Axes can for example represent time or depth. This means that it is possible to retrieve different images for different times or depths. Note that the returned axes don't include spatial (i.e. lon/lat) axes or axes for the actual data (e.g. temperature), only the axes using which can be filtered.

      If this model is an interpolated one, the returned dimension from this method consists of regular (=non-single-value) intervals between all values for which data is available. Otherwise the returned dimension consists of multiple single-value intervals, one for each piece of data.

      The ranges returned in this method contain either Date or TLcdISO19103Measure intervals.

      Returns:
      the data ranges for which data is available.
    • retrieveDimensionAxis

      public <T> TLcdDimensionAxis<T> retrieveDimensionAxis(Class<T> aType, ILcdISO19103UnitOfMeasure aUnit)
      Deprecated.
      use getDimensions() instead
      Returns the axis that corresponds to the given type and (optional) unit. If no axis can be found, null is returned. If more than one axis corresponds to the given type and unit, the first one is returned.
      Parameters:
      aType - the type.
      aUnit - the (optional) unit.
      Returns:
      the axis that corresponds to the given type and (optional) unit. Can be null if no axis can be found.
    • getTimeBounds

      public ILcdTimeBounds getTimeBounds()
      Description copied from interface: ILcdTimeBounded
      Returns the ILcdTimeBounds by which this object is bounded.
      Specified by:
      getTimeBounds in interface ILcdTimeBounded
      Returns:
      the ILcdTimeBounds by which this object is bounded.
    • getDependentObjects

      public List<Object> getDependentObjects()
      Description copied from interface: ILcdLockDependent
      Returns the objects that must be locked along with this object. TLcdLockUtilfirst locks all objects returned by this method before locking this object.
      Specified by:
      getDependentObjects in interface ILcdLockDependent
      Returns:
      the objects that must be locked along with this object.
    • dispose

      public void dispose()
      Description copied from class: ALcdModel
      Disposes of this model and allows it to release any system resources that it is holding. The result of calling any other method (other than finalize) on this model subsequent to a call to this method is undefined.

      When a model disposer has been provided it is called, otherwise this method does nothing. When overriding this method it is recommended to call super.dispose().

      Specified by:
      dispose in interface ILcdDisposable
      Specified by:
      dispose in interface ILcdModel
      Overrides:
      dispose in class ALcdModel
      See Also: