How to deal with complex dimension dependencies - a proposal

The problem

Assume a layer, wind, with three modelruns. Each modelrun contains 48 forecasts at 1 hour intervals. In this situation, the available combinations of TIME and MODELRUN_TIME will be these:

  TIME
2009-11-26 2009-11-27 2009-11-28
MODELRUN_TIME 00-12 12-00 00-12 12-00 00-12 12-00
2009-11-26T00:00 * * * *
2009-11-26T12:00 * * * *
2009-11-27T00:00 * * * *

In this case, the normal capabilities document would contain these values for the dimensions modelruntime and time

  <Dimension name="MODELRUN_TIME" units="ISO8601" nearestValue="0" default="2009-11-27T00:00">
    2009-11-26T00:00/2009-11-27T00:00/PT12H
  </Dimension>
  <Dimension name="TIME" units="ISO8601" nearestValue="0" default="2009-11-27T12:00">
    2009-11-26T00:00/2009-11-29T00:00/PT1H
  </Dimension>

This would make it seem like it is possible to select a combination like MODELRUN_TIME=2009-11-27T00:00&TIME=2009-11-26T00:00, and the goal is to find a way to express which combinations that are (im)possible, so that a sufficiently advanced client can select any combination of dimensions that will return an image.

Capabilities document unsuitable?

I've been thinking of different ways of expressing these combinations as effectively as possible within the capabilities document, and I've come to the conclusion that it's not possible. If a layer offers many dimensions with many dependencies in other dimensions, you can't present a complete set of combinations without creating a huge document. Conversely, if you want to express the combinations compactly, you must hide some of the possible combinations from the client.

GetDimensions

I propose that we instead define a new WMS operation, called GetDimensions. The purpose of this operation is to return only those dimension values that are still available when the user has selected values from the other dimensions.

Parameters should be LAYERS (list of comma separated layers), TIME (currently selected TIME), ELEVATION (currently selected elevation) and DIM_* (currently selected value of any sample dimension), plus the standard WMS parameters, SERVICE, VERSION and REQUEST, of course.

Examples

http://host/wmsserver?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetDimensions&LAYERS=wind

This will return a list of dimensions almost identical to the one in the GetCapabilities response.

<DimensionList>
  <Dimension name="MODELRUN_TIME" units="ISO8601" nearestValue="0" default="2009-11-27T00:00">
    2009-11-26T00:00/2009-11-27T00:00/PT12H
  </Dimension>
  <Dimension name="TIME" units="ISO8601" nearestValue="0" default="2009-11-27T12:00">
    2009-11-26T00:00/2009-11-29T00:00/PT1H
  </Dimension>
</DimensionList>

The only difference is the parent element DimensionList

When the user selects a dimension value in the client, the client must issue another GetDimensions request, to get the updated list of available dimensions.

http://host/wmsserver?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetDimensions&LAYERS=wind&DIM_MODELRUN_TIME=2009-11-26T00:00

Now the TIME dimension has been truncated to only include the forecast times available for MODELRUN_TIME=2009-11-26T00:00. Note that MODELRUN_TIME still includes all available modelruns, and the attribute userValue, which repeats the selected value.

<DimensionList>
  <Dimension name="MODELRUN_TIME" units="ISO8601" nearestValue="0"
  default="2009-11-27T00:00" userValue="2009-11-26T00:00">
    2009-11-26T00:00/2009-11-27T00:00/PT12H
  </Dimension>
  <Dimension name="TIME" units="ISO8601" nearestValue="0" default="2009-11-27T12:00">
    2009-11-26T00:00/2009-11-28T00:00/PT1H
  </Dimension>
</DimensionList>

When the user selects a TIME value as well, the client must issue yet another GetDimensions request.

http://host/wmsserver?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetDimensions&LAYERS=wind&DIM_MODELRUN_TIME=2009-11-26T00:00&TIME=2009-11-26T15:00

The selected TIME is only available in two of the MODELRUN_TIMEs, so this time the reply will look like this:

<DimensionList>
  <Dimension name="MODELRUN_TIME" units="ISO8601" nearestValue="0"
  default="2009-11-27T00:00" userValue="2009-11-26T00:00">
    2009-11-26T00:00/2009-11-26T12:00/PT12H
  </Dimension>
  <Dimension name="TIME" units="ISO8601" nearestValue="0"
  default="2009-11-27T12:00" userValue="2009-11-26T15:00>
    2009-11-26T00:00/2009-11-28T00:00/PT1H
  </Dimension>
</DimensionList>

and so on. Every time the user changes the value of any dimension, or selects a new layer, a new GetDimension request is issued by the client. The returned XML-document will contain all values that the client shall present to the user, and assuming the user only changes one dimension value at a time, it will be impossible for the user to select an impossible combination.

Mutually exclusive dimensions

This solution could also be extended to work in situations where a layer offers multiple dimensions that are mutually exlusive. One example is the use of hour offsets instead the forecast time. The layer allows you to use both the TIME dimension and the OFFSET_TIME dimension, but using both in the same request will not make sense.

This can be solved by using a new element to group dimensions. I've called it DimensionGroup, but suggestions are welcome.

Examples

http://host/wmsserver?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetDimensions&LAYERS=wind

<DimensionList>
  <Dimension name="MODELRUN_TIME" units="ISO8601" nearestValue="0" default="2009-11-27T00:00">
    2009-11-26T00:00/2009-11-27T00:00/PT12H
  </Dimension>
  <DimensionGroup default="TIME">
    <Dimension name="TIME" units="ISO8601" nearestValue="0" default="2009-11-27T12:00">
      2009-11-26T00:00/2009-11-29T00:00/PT1H
    </Dimension>
    <Dimension name="OFFSET_TIME" nearestValue="0" default="0">
      0/48/1
    </Dimension>
  </DimensionGroup>
</DimensionList>

In this case, the client should present the user with an option to choose between using TIME or OFFSET_TIME, and when the user has made the selection, it'll be possible to select a value for that dimension. When the user selects a value, another GetDimension request is issued, just like in the other situations.

http://host/wmsserver?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetDimensions&LAYERS=wind&DIM_MODELRUN_TIME=2009-11-26T00:00&OFFSET_TIME=15

<DimensionList>
  <Dimension name="MODELRUN_TIME" units="ISO8601" nearestValue="0"
  default="2009-11-27T00:00" userValue="2009-11-26T00:00">
    2009-11-26T00:00/2009-11-27T00:00/PT12H
  </Dimension>
  <DimensionGroup default="TIME" userValue="OFFSET_TIME">
    <Dimension name="TIME" units="ISO8601" nearestValue="0" default="2009-11-27T12:00">
      2009-11-26T00:00/2009-11-28T00:00/PT1H
    </Dimension>
    <Dimension name="OFFSET_TIME" nearestValue="0" default="0" userValue="15">
      0/48/1
    </Dimension>
  </DimensionGroup>
</DimensionList>

Note that the TIME dimension now contains all values available for the selected MODELRUN_TIME, and completely ignores the OFFSET_TIME dimension. When generating the list of available values the server shall ignore any dimensions from the same dimension group. This way, the client can allow the user to switch back from OFFSET_TIME to TIME, and make a new TIME selection, based on the TIMEs available from the currently selected MODELRUN_TIME.

Vertical dimensions

So far, I've only used temporal dimensions as examples, but this mechanism should be powerful enough to allow for vertical dimensions as well

Example

http://host/wmsserver?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetDimensions&LAYERS=wind

<DimensionList>
  <Dimension name="MODELRUN_TIME" units="ISO8601" nearestValue="0" default="2009-11-27T00:00">
    2009-11-26T00:00/2009-11-27T00:00/PT12H
  </Dimension>
  <DimensionGroup default="TIME">
    <Dimension name="TIME" units="ISO8601" nearestValue="0" default="2009-11-27T12:00">
      2009-11-26T00:00/2009-11-29T00:00/PT1H
    </Dimension>
    <Dimension name="OFFSET_TIME" nearestValue="0" default="0">
      0/48/1
    </Dimension>
  </DimensionGroup>
  <DimensionGroup default="PRESSURE">
    <Dimension name="PRESSURE" units="hektoPascal" unitSymbol="hPa"
     nearestValue="0" default="1000">
      1000,925,850,700,500,400,300,250,200,150,100,70,50,30,10
    </Dimension>
    <Dimension name="ISENTROPIC_LEVEL" units="Kelvin" unitSymbol="K"
     nearestValue="0" default="270">
      270/370/5
    </Dimension>
  </DimensionGroup>
</DimensionList>

This DimensionGroup will work exactly as the TIME/OFFSET_TIME group.

Conclusion

I think this way of dealing with dealing with dimensions is flexible enough for all our needs. It necessarily adds some complexity to the client, but I think this is unavoidable anyway.

I also suggest that the capabilities document must contain all possible values for all possible dimensions for each of the layers. This will allow users of less sophisticated clients to still access all available data. It will be possible for those users to create request that asks for impossible combinations of dimensions, but it's still better than not being able to access the data at all.

There's one thing I haven't made an effort to address, and that's the situation when there's no complexity, and the use of GetDimensions is unnecessary. This can vary from layer to layer, and I think it would be a good idea to limit the use of GetDimensions to only those layers that needs it.

I also think it could be an idea to add more attributes to the elements. Maybe there should be a "name"-attribute to the DimensionGroup element? Perhaps an attribute to Dimension that indicates if the values are ascending or descending? An attribute that declares if the unitSymbol is postfix or prefix could also be useful.

-- TrondMichelsen - 27 Nov 2009

Example URLs

I have implemented a very simple example of how this could work. This example will only demonstrate the request and response. It doesn't actually filter out impossible combinations yet.

http://wms1.oslo.dnmi.no/interrisk/diana.map?Service=WMS&Request=GetDimensions&layers=oildrift_interrisk_82_2

To make it simple to implement in a client, I've also added the option of returning a JSON data structure instead of XML

http://wms1.oslo.dnmi.no/interrisk/diana.map?Service=WMS&Request=GetDimensions&layers=oildrift_interrisk_82_2&format=application/json

A client that uses the JSON-version is available here:

http://wms1.oslo.dnmi.no/interrisk/

This client will only request dimension values when a layer is switched on or off, and my suggestion will require a new GetDimension request every time the user changed the value of any dimension as well, but it shouldn't be too difficult to apply this change.

-- TrondMichelsen - 18 Jan 2010
Topic revision: r2 - 18 Jan 2010, TrondMichelsen
This site is powered by FoswikiThe information you supply is used for OGC purposes only. We will never pass your contact details to any third party without your prior consent.
If you enter content here you are agreeing to the OGC privacy policy.

Copyright &© by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding OGC Public Wiki? Send feedback