Accessing data using the Download Service

Download Service is way to get the Open Data from the Finnish Meteorological Institute to be used by your applications. The guidelines for the INSPIRE directive give a couple of technological options for implementing a Download Service.

The Finnish Meteorological Institute has chosen to provide the data using the OGC Web Feature Service (WFS) interface. WFS is a generic interface standard for providing access to geospatial objects, or objects with some kind of location or covered geospatial area. These objects can contain any information, and the internal structure of the objects is not limited by the specification. A WFS service is like a generic object database with a standardized query language. These geospatial objects are called "features".

WFS returns XML files

Typically WFS services return the requested data encoded as XML language called Geography Markup Language (GML), which is another OGC and ISO standard. The service has to able to return the structure description of each of the provided feature types in XML Schema language (the DescribeFeatureType operation). This operation can be used to get the expected structure information for the WFS service data responses before making the actual GetFeature request for retrieving the data.

Essential operations of WFS

The latest version of the WFS standard is 2.0, which is also the version required by the INSPIRE directive technical guidance. Consequently the WFS service of the Finnish Meteorological Institute also only implements this version of the WFS specification.

The WFS 2.0 standard defines the following operations for the Simple WFS profile:

  • GetCapabilities returns service metadata,
  • DescribeFeatureType returns XML Schema description for the requestes feature types,
  • ListStoredQueries lists stored queries available at a server
  • DescribeStoredQueries returns detailed metadata about each stored queries,
  • GetFeature returns a list of features based on the given query.

The standard defines for the Basic WFS profile that it shall implement operations defined for Simple WFS and shall additionally implement the GetFeature operation with the Query action and the following operation:

  • GetPropertyValue returns only the values of selected properties of the requested features,

The standard also defines LockFeature, GetFeatureWithLock, Transaction, CreateStoredQuery and DropStoredQuery operations. See the standard for getting more information about the operations.

The Simple WFS profile is the minimum that a server shall implement. If the server does not support the Basic WFS then the Simple WFS is only supported. The response of GetCapabilities request describes which operations the server supports and what constraints it has.

Stored queries are identifiers for data sets

The current version on the Open Data WFS service of the Finnish Meteorological Institute uses the stored queries extensively to enable users to select the features, areas and times they require as easily as possible. See the Open data WFS Service for more detailed information about the available stored queries and their request parameters.

Data is returned using standard data models

For more info on the data models (feature types) used by the Open Data WFS service see page About the Observations & Measurements data model, and if the XML based WFS interface seems a bit too much, and you just want to get your hands on to the weather timeseries data of the Finnish Meteorological Institute, go directly to WFS timeseries page including usage examples for client library (MetOLib).

WFS provides collections of features

The WFS operation actually returning the data is called GetFeature. It always returns a collection of features, typically encoded as an XML document.

Some features are relatively simple:

<ms:greenland_elevation_contour>
  <gml:boundedBy>
    <gml:Envelope srsName="EPSG:32661">
      <gml:lowerCorner>-327189.501776 -456661.863393</gml:lowerCorner>
      <gml:upperCorner>-327164.993574 -456636.649888</gml:upperCorner>
    </gml:Envelope>
  </gml:boundedBy>
  <ms:msGeometry>
    <gml:LineString srsName="EPSG:32661">
      <gml:posList srsDimension="2">-327164.993574 -456638.840870
-327189.501776 -456636.649888
-327183.636846 -456661.863393
-327168.660334 -456653.526955
-327164.993574 -456638.840870
      </gml:posList>
    </gml:LineString>
  </ms:msGeometry>
  <ms:Label>1000 m</ms:Label>
  <ms:Elevation>1000.000000</ms:Elevation>
</ms:greenland_elevation_contour>

Some may be more complicated containing inner objects and deep structure:

<omso:PointTimeSeriesObservation gml:id="fct-1">
  <!-- Reference to HIRLAM forecast model 2011-01-18 09:00 UTC run
    metadata record (at FMI catalog service)-->
  <om:metadata xlink:href="http://catalog.fmi.fi/model/hirlam?run=2011-01-18T09:00:00Z&format=gml"/>

  <om:phenomenonTime>
    <gml:TimePeriod gml:id="time-1">
      <!-- Forecast spans this time period -->
      <gml:beginPosition>2011-01-18T12:00:00Z</gml:beginPosition>
      <gml:endPosition>2011-01-18T18:00:00Z</gml:endPosition>
    </gml:TimePeriod>
  </om:phenomenonTime>

  <om:resultTime>
    <gml:TimeInstant gml:id="time-2">
      <!-- This data became available at 09:45 UTC -->
      <gml:timePosition>2011-01-18T09:45:00Z</gml:timePosition>
    </gml:TimeInstant>
  </om:resultTime>

  <om:validTime>
    <gml:TimePeriod gml:id="time-3">
      <!-- This data should only be used for estimating the expected weather conditions
        within this time period. After this a more recent model run
        data should be used instead. -->
      <gml:beginPosition>2011-01-18T09:00:00Z</gml:beginPosition>
      <gml:endPosition>2011-01-18T16:00:00Z</gml:endPosition>
    </gml:TimePeriod>
  </om:validTime>

  <om:procedure xlink:href="../../../static/process/Inspire-Hirlam74-process.xml"/>

  <!-- Analysis time = nominal time for the forecast model run analysis phase.
      Different model runs are separated from each other by using
      different analysis times.
  -->
  <om:parameter>
    <om:NamedValue>
      <om:name xlink:href="http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value\
/numericalModel/analysisTime"/>
      <om:value>
        <gml:TimeInstant gml:id="at-1">
          <gml:timePosition>2012-01-18T09:00:00Z</gml:timePosition>
        </gml:TimeInstant>
      </om:value>
    </om:NamedValue>
  </om:parameter>

  <!-- Must be a reference by schema definition, no embedding allowed here, so make it dynamic: -->
  <om:observedProperty xlink:href="/observable-property-composite?\
params=air-temp-1h-max,atmospheric-pressure-1h-avg,wind-speed-1h-avg,\
wind-direction-1h-avg"/>

  <!-- Put the FOI embedded here, because this changes with every request with point forecast -->
  <om:featureOfInterest>
    <sams:SF_SpatialSamplingFeature gml:id="uuid-4329293474dfgdf">
      <sam:sampledFeature xlink:href="../../../static/foisurfaceWeatherTargetArea_Finland_epsg4258.xml"/>
      <sams:shape>
        <gml:Point gml:id="id-1" srsName="http://www.opengis.net/def/crs/EPSG/0/4258"\
srsDimension="2">
          <gml:pos>60.17522 24.94458</gml:pos>
        </gml:Point>
      </sams:shape>
    </sams:SF_SpatialSamplingFeature>
  </om:featureOfInterest>

  <om:result>
    <gmlcov:MultiPointCoverage gml:id="mpcv1">
      <gml:domainSet>
        <gmlcov:SimpleMultiPoint gml:id="mp1" srsName="http://xml.fmi.fi/gml/crs/epoch-time.xml"\
srsDimension="1">
          <gmlcov:positions>
            <!--
              epoch times
              2011-01-18T12:00:00Z
              2011-01-18T13:00:00Z
              2011-01-18T14:00:00Z
              2011-01-18T15:00:00Z
              2011-01-18T16:00:00Z
              2011-01-18T17:00:00Z
              2011-01-18T18:00:00Z
            -->
            1295352000
            1295355600
            1295359200
            1295362800
            1295366400
            1295370000
            1295373600
          </gmlcov:positions>
        </gmlcov:SimpleMultiPoint>
      </gml:domainSet>
      <gml:rangeSet>
        <gml:DataBlock>
          <gml:rangeParameters/>
          <!-- the measurement values that correspond to the (temporal) grid points -->
          <gml:doubleOrNilReasonTupleList>
            1.1 1003.5 2.6 232.0
            1.0 1004.1 3.0 232.0
            1.1 1010.6 2.8 221.0
            1.0 1045.7 1.7 244.0
            1.0 1045.0 1.3 217.0
            1.0 1023.4 1.2 217.0
            1.0 1033.1 1.7 210.0
          </gml:doubleOrNilReasonTupleList>
        </gml:DataBlock>
      </gml:rangeSet>
      <gml:coverageFunction>
        <gml:CoverageMappingRule>
          <gml:ruleDefinition>Linear</gml:ruleDefinition>
        </gml:CoverageMappingRule>
      </gml:coverageFunction>

      <!-- Definition of the values given in the rangeSet -->
      <gmlcov:rangeType>
        <swe:DataRecord>
          <swe:field
            name="airTemperature"
            xlink:href="/observable-property?air-temp-1h-max"/>
          <swe:field
            name="atmosphericPressure"
            xlink:href="/observable-property?atmospheric-pressure-1h-avg"/>
          <swe:field
            name="windSpeed"
            xlink:href="/observable-property?wind-speed-1h-max"/>
          <swe:field
            name="windDirection"
            xlink:href="/observable-property?wind-direction-1h-avg"/>
        </swe:DataRecord>
      </gmlcov:rangeType>
    </gmlcov:MultiPointCoverage>
  </om:result>
</omso:PointTimeSeriesObservation>

 

In any case the GML encoded WFS response is wrapped in a wfs:FeatureCollection element:

<?xml version="1.0" encoding="UTF-8"?>
<wfs:FeatureCollection
  timeStamp="2012-04-03T22:56:09"
  numberMatched="15"
  numberReturned="1"
  xmlns:wfs="http://www.opengis.net/wfs/2.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns:om="http://www.opengis.net/om/2.0"
  xmlns:omso="http://inspire.ec.europa.eu/schemas/omso/2.9"
  xmlns:gml="http://www.opengis.net/gml/3.2"
  xmlns:swe="http://www.opengis.net/swe/2.0"
  xmlns:gmlcov="http://www.opengis.net/gmlcov/1.0"
  xmlns:sam="http://www.opengis.net/sampling/2.0"
  xmlns:sams="http://www.opengis.net/samplingSpatial/2.0"
  xsi:schemaLocation="http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd
http://www.opengis.net/gmlcov/1.0
http://schemas.opengis.net/gmlcov/1.0/gmlcovAll.xsd
http://www.opengis.net/sampling/2.0
http://schemas.opengis.net/sampling/2.0/samplingFeature.xsd
http://www.opengis.net/samplingSpatial/2.0
http://schemas.opengis.net/samplingSpatial/2.0/spatialSamplingFeature.xsd
http://www.opengis.net/swe/2.0
http://schemas.opengis.net/sweCommon/2.0/swe.xsd
http://inspire.ec.europa.eu/schemas/omso/2.9
http://inspire.ec.europa.eu/draftschemas/omso/2.9/SpecialisedObservations.xsd">

  <wfs:boundedBy>
    <!-- 2D Envelope for point forecast data (ETRS89 2D)  -->
    <gml:Envelope srsName="http://www.opengis.net/def/crs/EPSG/0/4258" srsDimension="2">
      <gml:lowerCorner>60.17522 24.94458</gml:lowerCorner>
      <gml:upperCorner>60.17522 24.94458</gml:upperCorner>
    </gml:Envelope>
  </wfs:boundedBy>

  <wfs:member>
     ....
     [the first response feature here]
     ....
  </wfs:member>

  <wfs:member>
     ....
     [the second response feature here]
     ....
  </wfs:member>

   [etc]

</wfs:featureCollection>