Skip to main content

Python module to decode/encode met reports e.g. SYNOPs

Project description

README

This is a Python module which decodes meteorological reports (e.g. SYNOPs) into a Python dictionary. It can also take a Python dictionary and encode a meteorological report from it.

Currently supported

The current version of the module supports the following (in most cases; see Known Issues below):

  • SYNOP (FM-12)
  • SHIP (FM-13)
  • SYNOP MOBIL (FM-14)
  • METAR (FM-15) - partial support

Example usage

To decode a SYNOP:

from pymetdecoder import synop as s

synop = "AAXX 01004 88889 12782 61506 10094 20047 30111 40197 53007 60001 81541 333 81656 86070"
output = s.SYNOP().decode(synop)
print(output)

This yields the following output (pretty-printed):

{
  "station_type": {
    "value": "AAXX"
  },
  "obs_time": {
    "day": {
      "value": 1
    },
    "hour": {
      "value": 0
    }
  },
  "wind_indicator": {
    "value": 4,
    "unit": "KT",
    "estimated": false
  },
  "station_id": {
    "value": "88889"
  },
  "region": {
    "value": "III"
  },
  "precipitation_indicator": {
    "value": 1,
    "in_group_1": true,
    "in_group_3": false
  },
  "weather_indicator": {
    "value": 2,
    "automatic": false
  },
  "lowest_cloud_base": {
    "_table": "1600",
    "min": 1500,
    "max": 2000,
    "quantifier": null,
    "_code": 7,
    "unit": "m"
  },
  "visibility": {
    "_table": "4377",
    "value": 40000,
    "quantifier": null,
    "use90": false,
    "_code": 82,
    "unit": "m"
  },
  "cloud_cover": {
    "_table": "2700",
    "value": 6,
    "obscured": false,
    "unit": "okta",
    "_code": 6
  },
  "surface_wind": {
    "direction": {
      "_table": "0877",
      "value": 150,
      "varAllUnknown": false,
      "calm": false,
      "_code": 15,
      "unit": "deg"
    },
    "speed": {
      "value": 6,
      "unit": "KT"
    }
  },
  "air_temperature": {
    "value": 9.4,
    "unit": "Cel"
  },
  "dewpoint_temperature": {
    "value": 4.7,
    "unit": "Cel"
  },
  "station_pressure": {
    "value": 1011.1,
    "unit": "hPa"
  },
  "sea_level_pressure": {
    "value": 1019.7,
    "unit": "hPa"
  },
  "pressure_tendency": {
    "tendency": {
      "_table": "0200",
      "value": 3
    },
    "change": {
      "value": 0.7,
      "unit": "hPa"
    }
  },
  "precipitation_s1": {
    "amount": {
      "_table": "3590",
      "value": 0,
      "quantifier": null,
      "trace": false,
      "_code": 0,
      "unit": "mm"
    },
    "time_before_obs": {
      "_table": "4019",
      "value": 6,
      "unit": "h",
      "_code": 1
    }
  },
  "cloud_types": {
    "low_cloud_type": {
      "_table": "0513",
      "value": 5
    },
    "middle_cloud_type": {
      "_table": "0515",
      "value": 4
    },
    "high_cloud_type": {
      "_table": "0509",
      "value": 1
    },
    "low_cloud_amount": {
      "value": 1,
      "unit": "okta"
    }
  },
  "cloud_layer": [
    {
      "cloud_cover": {
        "_table": "2700",
        "value": 1,
        "obscured": false,
        "unit": "okta",
        "_code": 1
      },
      "cloud_genus": {
        "_table": "0500",
        "value": "Sc",
        "_code": 6
      },
      "cloud_height": {
        "_table": "1677",
        "value": 1800,
        "quantifier": null,
        "_code": 56,
        "unit": "m"
      }
    },
    {
      "cloud_cover": {
        "_table": "2700",
        "value": 6,
        "obscured": false,
        "unit": "okta",
        "_code": 6
      },
      "cloud_genus": {
        "_table": "0500",
        "value": "Ci",
        "_code": 0
      },
      "cloud_height": {
        "_table": "1677",
        "value": 6000,
        "quantifier": null,
        "_code": 70,
        "unit": "m"
      }
    }
  ]
}

Re-encoding this dict gets back the original SYNOP:

from pymetdecoder import synop as s

original = "AAXX 01004 88889 12782 61506 10094 20047 30111 40197 53007 60001 81541 333 81656 86070"
synop = s.SYNOP()
output = synop.decode(synop)
msg = synop.encode(output)

print(msg)
# Returns AAXX 01004 88889 12782 61506 10094 20047 30111 40197 53007 60001 81541 333 81656 86070

Commonly seen attributes in the output dict are as follows:

  • value - The absolute value of the attribute
  • min, max - If a code value converts to a range, the min/max specifies the limit of the range
  • quantifier - Used alongside min/max/value to add an inequality if needs be (e.g. { "value": 6000, "quantifier": "isGreater"} represents a value >6000). This is often the case when looking up values in a code table
  • unit - The unit the value is measured in. The Unified Code for Units of Measure is used here (https://ucum.org/ucum.html)
  • _table - This is the code table used to look up the value
  • _code - The code value looked up in the code table. When encoding a message, if this attribute is present, it will use that, rather than trying to calculate it from the value

Malformed reports

The module will try to decode as much of a report as it can. Non-fatal problems (e.g. invalid codes) will emit a warning message and continue. Fatal problems will emit a DecodeError exception, which can be caught in a try...except block.

Scripts

Introduced in version 0.2.0, you can decode/encode reports directly from the command line. The following command decodes the same SYNOP as in the example above:

$ python3 -m pymetdecoder decode --synop="AAXX 01004 88889 12782 61506 10094 20047 30111 40197 53007 60001 81541 333 81656 86070"

It can also read reports in from standard input by specifying --synop=-:

$ echo "AAXX 01004 88889 12782 61506 10094 20047 30111 40197 53007 60001 81541 333 81656 86070" | python3 -m pymetdecoder decode --synop=-

Encoding reports works in the same way. The --synop switch can be specified multiple times if multiple SYNOPs are to be decoded/encoded. Similarly, a --metar switch can be used to decode/encode METARs.

Changelog

See CHANGELOG.md for the list of changes

Known issues

This version is 0.2.1. There may be some uncaught bugs/issues or other problems that have not been found yet. The following is a list of known issues which are still to be addressed:

  • Not all countries are auto-detected. As more region-specific handling is added, more countries will be added to the list
  • Section 5 of the SYNOP messages are not handled yet. Any codes in these sections are stored in the output dict under the section5 attribute
  • Most of the group 9 codes of section 3 are handled. Any codes not handled are added to a list in the output dict under the _not_implemented attribute
  • Some aspects of encoding have not been fully tested
  • Not all elements of METARs are supported, but most simple METARs will work

Feel free to raise any additional issues/bugs in the issue tracker

Future plans

In future, it is intended that the module will support the following:

  • SYNOP section 5
  • BUOY (FM-18)
  • TEMP (FM-35)
  • CLIMAT (FM-71)

If you would like to contribute to this module by adding in the functionality to support any of these reports (or other reports), then feel free to do so!

License

(c) UK Research and Innovation (UKRI), 2021 - 2026, British Antarctic Survey. You may use and re-use this software and associated documentation files free of charge in any format or medium, under the terms of the Open Government Licence v3.0. You may obtain a copy of the Open Government Licence at http://www.nationalarchives.gov.uk/doc/open-government-licence/

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pymetdecoder-0.2.1.tar.gz (50.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pymetdecoder-0.2.1-py3-none-any.whl (52.7 kB view details)

Uploaded Python 3

File details

Details for the file pymetdecoder-0.2.1.tar.gz.

File metadata

  • Download URL: pymetdecoder-0.2.1.tar.gz
  • Upload date:
  • Size: 50.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.12.3 Linux/6.17.0-29-generic

File hashes

Hashes for pymetdecoder-0.2.1.tar.gz
Algorithm Hash digest
SHA256 c38170c0708859019f40f5385b1123ee898473676248731d310e55d76bf12520
MD5 491e36a2b669cb704f125724aa0b33b9
BLAKE2b-256 6bb838a66def9d6c20eb1a7c8d51975d51115af200d9f3ef632e4e7a8722ab06

See more details on using hashes here.

File details

Details for the file pymetdecoder-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: pymetdecoder-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 52.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.2 CPython/3.12.3 Linux/6.17.0-29-generic

File hashes

Hashes for pymetdecoder-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e39b4c6f83c0171a28fc839ac89807e067dfe8adfcbeae37f6c045604beb649d
MD5 136f1b44cc07364205681f9ccc429a2d
BLAKE2b-256 8f24c50f6173554f981632adc91c70b3a4d9b996110da548ea4cb8e8c61b8f20

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page