wwvb


Namewwvb JSON
Version 3.0.7 PyPI version JSON
download
home_pagehttps://github.com/jepler/wwvbpy
SummaryGenerate WWVB timecodes for any desired time
upload_time2024-03-19 00:32:35
maintainer
docs_urlNone
authorJeff Epler
requires_python>=3.9
license
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage
            <!--
SPDX-FileCopyrightText: 2021 Jeff Epler

SPDX-License-Identifier: GPL-3.0-only
-->
[![Test wwvbgen](https://github.com/jepler/wwvbpy/actions/workflows/test.yml/badge.svg)](https://github.com/jepler/wwvbpy/actions/workflows/test.yml)
[![codecov](https://codecov.io/gh/jepler/wwvbpy/branch/main/graph/badge.svg?token=Exx0c3Gp65)](https://codecov.io/gh/jepler/wwvbpy)
[![Update DUT1 data](https://github.com/jepler/wwvbpy/actions/workflows/cron.yml/badge.svg)](https://github.com/jepler/wwvbpy/actions/workflows/cron.yml)
[![PyPI](https://img.shields.io/pypi/v/wwvb)](https://pypi.org/project/wwvb)
[![CodeQL](https://github.com/jepler/wwvbpy/actions/workflows/codeql.yml/badge.svg)](https://github.com/jepler/wwvbpy/actions/workflows/codeql.yml)
[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/jepler/wwvbpy/main.svg)](https://results.pre-commit.ci/latest/github/jepler/wwvbpy/main)

# Purpose

wwvbpy generates WWVB timecodes for any desired time.  These timecodes
may be useful in testing WWVB decoder software.

Where possible, wwvbpy uses existing facilities for calendar and time
manipulation (datetime and dateutil).

It uses DUT1/leap second data derived from IERS Bulletin "A" and from NIST's
"Leap second and UT1-UTC information" page.  With regular updates to
the "iersdata", wwvbpy should be able to correctly encode the time anywhere
within the 100-year WWVB epoch.  (yes, WWVB uses a 2-digit year! In order to
work with historical data, the epoch is arbitrarily assumed to run from 1970 to
2069.)

Programs include:
 * `wwvbgen`, the main commandline generator program
 * `wwvbdecode`, the main commandline decoder program
 * `wwvbtk`, visualize the simulated WWVB signal in real-time using Tkinter
 * `dut1table`, print the full history of dut1 values, including estimated future values
 * `updateiers`, download the latest dut1 data including prospective data from IERS and NIST

The package includes:
 * `wwvb`, for generating WWVB timecodes
 * `wwvb.decode`, a generator-based state machine for decoding WWVB timecodes (amplitude modulation only)
 * `uwwvb`, a version of the decoder intended for use on constrained environments such as [CircuitPython](https://circuitpython.org).

# Development status

The author (@jepler) occasionally develops and maintains this project, but
issues are not likely to be acted on.  They would be interested in adding
co-maintainer(s).


# WWVB Timecodes

The National Institute of Standards and Technology operates the WWVB time
signal service near Fort Collins, Colorado.  The signal can be received in most
of the continental US.  Each minute, the signal transmits the current time,
including information about leap years, daylight saving time, and leap seconds.
The signal is composed of an amplitude channel and a phase modulation channel.

The amplitude channel can be visualized as a sequence of (usually) 60 symbols,
which by default wwvbgen displays as 0, 1, or 2.  The 0s and 1s encode
information like the current day of the year, while the 2s appear in fixed
locations to allow a receiver to determine the start of a minute.

The phase channel (which is displayed with `--channel=phase` or
`--channel=both`) consists of the same number of symbols per minute.  This
channel is substantially more complicated than the phase channel.  It encodes
the current time as minute-of-the-century, provides extended DST information,
and includes error-correction information not available in the amplitude
channel.

# Usage

~~~~
Usage: python -m wwvb.gen [OPTIONS] [TIMESPEC]...

  Generate WWVB timecodes

  TIMESPEC: one of "year yday hour minute" or "year month day hour minute", or
  else the current minute

Options:
  -i, --iers / -I, --no-iers      Whether to use IESR data for DUT1 and LS.
                                  (Default: --iers)
  -s, --leap-second               Force a positive leap second at the end of
                                  the GMT month (Implies --no-iers)
  -n, --negative-leap-second      Force a negative leap second at the end of
                                  the GMT month (Implies --no-iers)
  -S, --no-leap-second            Force no leap second at the end of the month
                                  (Implies --no-iers)
  -d, --dut1 INTEGER              Force the DUT1 value (Implies --no-iers)
  -m, --minutes INTEGER           Number of minutes to show (default: 10)
  --style [bar|cradek|default|duration|json|sextant]
                                  Style of output
  -t, --all-timecodes / -T, --no-all-timecodes
                                  Show the 'WWVB timecode' line before each
                                  minute
  --channel [amplitude|phase|both]
                                  Modulation to show (default: amplitude)
  --help                          Show this message and exit.
~~~~

For example, to display the leap second that occurred at the end of 1998,
~~~~
$ python wwvbgen.py -m 7 1998 365 23 56
WWVB timecode: year=98 days=365 hour=23 min=56 dst=0 ut1=-300 ly=0 ls=1
'98+365 23:56  210100110200100001120011001102010100010200110100121000001002
'98+365 23:57  210100111200100001120011001102010100010200110100121000001002
'98+365 23:58  210101000200100001120011001102010100010200110100121000001002
'98+365 23:59  2101010012001000011200110011020101000102001101001210000010022
'99+001 00:00  200000000200000000020000000002000100101201110100121001000002
'99+001 00:01  200000001200000000020000000002000100101201110100121001000002
'99+001 00:02  200000010200000000020000000002000100101201110100121001000002
~~~~
(the leap second is the extra digit at the end of the 23:59 line; that minute
consists of 61 seconds, instead of the normal 60)


# How wwvbpy handles DUT1 data

wwvbpy stores a compact representation of DUT1 values in `wwvb/iersdata_dist.py` or `wwvb_iersdata.py`.
In this representation, one value is used for one day (0000UTC through 2359UTC).
The letters `a` through `u` represent offsets of -1.0s through +1.0s
in 0.1s increments; `k` represents 0s.  (In practice, only a smaller range
of values, typically -0.7s to +0.8s, is seen)

For 2001 through 2019, NIST has published the actual DUT1 values broadcast,
and the date of each change, though it in the format of an HTML
table and not designed for machine readability:

https://www.nist.gov/pml/time-and-frequency-division/atomic-standards/leap-second-and-ut1-utc-information

NIST does not update the value daily and does not seem to follow any
specific rounding rule.  Rather, in WWVB "the resolution of the DUT1
correction is 0.1 s, and represents an average value for an extended
range of dates. Therefore, it will not agree exactly with the weekly
UT1-UTC(NIST) values shown in the earlier table, which have 1 ms
resolution and are updated weekly."  Like wwvbpy's compact
representation of DUT1 values, the real WWVB does not appear to ever
broadcast DUT1=-0.0.

For a larger range of dates spanning 1973 through approximately one year from
now, IERS publishes historical and prospective UT1-UTC values to multiple
decimal places, in a machine readable fixed length format.

wwvbpy merges the WWVB and IERS datasets, favoring the WWVB dataset for dates when it is available. There are some caveats to this, which are mostly commented in the `wwvb/updateiers.py` script.

`wwvb/iersdata_dist.py` is updated monthly from github actions or with `iersdata --dist` from within the wwvbpy source tree. However, at this time, releases are not regularly made from the updated information.

A site or user version of the file, `wwvb_iersdata.py` can be created or updated with `iersdata --site` or `iersdata --user`.  If the distributed iersdata is out of date, the generator will prompt you to run the update command.

Leap seconds are inferred from the DUT1 data as follows: If X and Y are the
1-digit-rounded DUT1 values for consecutive dates, and `X*Y<0`, then there is a
leap second at the end of day X.  The direction of the leap second can be
inferred from the sign of X, a 59-second minute if X is positive and a
61-second minute if it is negative.  As long
as DUT1 changes slowly enough during other times that there is at least one day
of DUT1=+0.0, no incorrect (negative) leapsecond will be inferred. (something
that should remain true for the next few centuries, until the length of the day
is 100ms different from 86400 seconds)


# The phase modulation channel

This should be considered more experimental than the AM channel, as the
tests only cover a single reference minute.  Further tests could be informed
by the [other implementation I know of](http://www.leapsecond.com/tools/wwvb_pm.c), except that implementation appears incomplete.


# Testing wwvbpy

Run the testsuite, check coverage & type annotations with `gmake`.

There are several test suites:
 * `testwwvb.py`: Check output against expected values.  Uses hard coded leap seconds.  Tests amplitude and phase data, though the phase testcases are dubious as they were also generated by wwvbpy.
 * `testuwwvb.py`: Test the reduced-functionality version against the main version
 * `testls.py`: Check the IERS data through 2020-1-1 for expected leap seconds
 * `testpm.py`: Check the phase modulation data against a test case from NIST documentation
 * `testcli.py`: Check the commandline programs work as expected (limited tests to get 100% coverage)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/jepler/wwvbpy",
    "name": "wwvb",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": "",
    "keywords": "",
    "author": "Jeff Epler",
    "author_email": "jepler@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/18/a6/24ac83769e5abf5e26954ec87ebc6bbf316632f4319ccd19341463271cae/wwvb-3.0.7.tar.gz",
    "platform": null,
    "description": "<!--\nSPDX-FileCopyrightText: 2021 Jeff Epler\n\nSPDX-License-Identifier: GPL-3.0-only\n-->\n[![Test wwvbgen](https://github.com/jepler/wwvbpy/actions/workflows/test.yml/badge.svg)](https://github.com/jepler/wwvbpy/actions/workflows/test.yml)\n[![codecov](https://codecov.io/gh/jepler/wwvbpy/branch/main/graph/badge.svg?token=Exx0c3Gp65)](https://codecov.io/gh/jepler/wwvbpy)\n[![Update DUT1 data](https://github.com/jepler/wwvbpy/actions/workflows/cron.yml/badge.svg)](https://github.com/jepler/wwvbpy/actions/workflows/cron.yml)\n[![PyPI](https://img.shields.io/pypi/v/wwvb)](https://pypi.org/project/wwvb)\n[![CodeQL](https://github.com/jepler/wwvbpy/actions/workflows/codeql.yml/badge.svg)](https://github.com/jepler/wwvbpy/actions/workflows/codeql.yml)\n[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/jepler/wwvbpy/main.svg)](https://results.pre-commit.ci/latest/github/jepler/wwvbpy/main)\n\n# Purpose\n\nwwvbpy generates WWVB timecodes for any desired time.  These timecodes\nmay be useful in testing WWVB decoder software.\n\nWhere possible, wwvbpy uses existing facilities for calendar and time\nmanipulation (datetime and dateutil).\n\nIt uses DUT1/leap second data derived from IERS Bulletin \"A\" and from NIST's\n\"Leap second and UT1-UTC information\" page.  With regular updates to\nthe \"iersdata\", wwvbpy should be able to correctly encode the time anywhere\nwithin the 100-year WWVB epoch.  (yes, WWVB uses a 2-digit year! In order to\nwork with historical data, the epoch is arbitrarily assumed to run from 1970 to\n2069.)\n\nPrograms include:\n * `wwvbgen`, the main commandline generator program\n * `wwvbdecode`, the main commandline decoder program\n * `wwvbtk`, visualize the simulated WWVB signal in real-time using Tkinter\n * `dut1table`, print the full history of dut1 values, including estimated future values\n * `updateiers`, download the latest dut1 data including prospective data from IERS and NIST\n\nThe package includes:\n * `wwvb`, for generating WWVB timecodes\n * `wwvb.decode`, a generator-based state machine for decoding WWVB timecodes (amplitude modulation only)\n * `uwwvb`, a version of the decoder intended for use on constrained environments such as [CircuitPython](https://circuitpython.org).\n\n# Development status\n\nThe author (@jepler) occasionally develops and maintains this project, but\nissues are not likely to be acted on.  They would be interested in adding\nco-maintainer(s).\n\n\n# WWVB Timecodes\n\nThe National Institute of Standards and Technology operates the WWVB time\nsignal service near Fort Collins, Colorado.  The signal can be received in most\nof the continental US.  Each minute, the signal transmits the current time,\nincluding information about leap years, daylight saving time, and leap seconds.\nThe signal is composed of an amplitude channel and a phase modulation channel.\n\nThe amplitude channel can be visualized as a sequence of (usually) 60 symbols,\nwhich by default wwvbgen displays as 0, 1, or 2.  The 0s and 1s encode\ninformation like the current day of the year, while the 2s appear in fixed\nlocations to allow a receiver to determine the start of a minute.\n\nThe phase channel (which is displayed with `--channel=phase` or\n`--channel=both`) consists of the same number of symbols per minute.  This\nchannel is substantially more complicated than the phase channel.  It encodes\nthe current time as minute-of-the-century, provides extended DST information,\nand includes error-correction information not available in the amplitude\nchannel.\n\n# Usage\n\n~~~~\nUsage: python -m wwvb.gen [OPTIONS] [TIMESPEC]...\n\n  Generate WWVB timecodes\n\n  TIMESPEC: one of \"year yday hour minute\" or \"year month day hour minute\", or\n  else the current minute\n\nOptions:\n  -i, --iers / -I, --no-iers      Whether to use IESR data for DUT1 and LS.\n                                  (Default: --iers)\n  -s, --leap-second               Force a positive leap second at the end of\n                                  the GMT month (Implies --no-iers)\n  -n, --negative-leap-second      Force a negative leap second at the end of\n                                  the GMT month (Implies --no-iers)\n  -S, --no-leap-second            Force no leap second at the end of the month\n                                  (Implies --no-iers)\n  -d, --dut1 INTEGER              Force the DUT1 value (Implies --no-iers)\n  -m, --minutes INTEGER           Number of minutes to show (default: 10)\n  --style [bar|cradek|default|duration|json|sextant]\n                                  Style of output\n  -t, --all-timecodes / -T, --no-all-timecodes\n                                  Show the 'WWVB timecode' line before each\n                                  minute\n  --channel [amplitude|phase|both]\n                                  Modulation to show (default: amplitude)\n  --help                          Show this message and exit.\n~~~~\n\nFor example, to display the leap second that occurred at the end of 1998,\n~~~~\n$ python wwvbgen.py -m 7 1998 365 23 56\nWWVB timecode: year=98 days=365 hour=23 min=56 dst=0 ut1=-300 ly=0 ls=1\n'98+365 23:56  210100110200100001120011001102010100010200110100121000001002\n'98+365 23:57  210100111200100001120011001102010100010200110100121000001002\n'98+365 23:58  210101000200100001120011001102010100010200110100121000001002\n'98+365 23:59  2101010012001000011200110011020101000102001101001210000010022\n'99+001 00:00  200000000200000000020000000002000100101201110100121001000002\n'99+001 00:01  200000001200000000020000000002000100101201110100121001000002\n'99+001 00:02  200000010200000000020000000002000100101201110100121001000002\n~~~~\n(the leap second is the extra digit at the end of the 23:59 line; that minute\nconsists of 61 seconds, instead of the normal 60)\n\n\n# How wwvbpy handles DUT1 data\n\nwwvbpy stores a compact representation of DUT1 values in `wwvb/iersdata_dist.py` or `wwvb_iersdata.py`.\nIn this representation, one value is used for one day (0000UTC through 2359UTC).\nThe letters `a` through `u` represent offsets of -1.0s through +1.0s\nin 0.1s increments; `k` represents 0s.  (In practice, only a smaller range\nof values, typically -0.7s to +0.8s, is seen)\n\nFor 2001 through 2019, NIST has published the actual DUT1 values broadcast,\nand the date of each change, though it in the format of an HTML\ntable and not designed for machine readability:\n\nhttps://www.nist.gov/pml/time-and-frequency-division/atomic-standards/leap-second-and-ut1-utc-information\n\nNIST does not update the value daily and does not seem to follow any\nspecific rounding rule.  Rather, in WWVB \"the resolution of the DUT1\ncorrection is 0.1 s, and represents an average value for an extended\nrange of dates. Therefore, it will not agree exactly with the weekly\nUT1-UTC(NIST) values shown in the earlier table, which have 1 ms\nresolution and are updated weekly.\"  Like wwvbpy's compact\nrepresentation of DUT1 values, the real WWVB does not appear to ever\nbroadcast DUT1=-0.0.\n\nFor a larger range of dates spanning 1973 through approximately one year from\nnow, IERS publishes historical and prospective UT1-UTC values to multiple\ndecimal places, in a machine readable fixed length format.\n\nwwvbpy merges the WWVB and IERS datasets, favoring the WWVB dataset for dates when it is available. There are some caveats to this, which are mostly commented in the `wwvb/updateiers.py` script.\n\n`wwvb/iersdata_dist.py` is updated monthly from github actions or with `iersdata --dist` from within the wwvbpy source tree. However, at this time, releases are not regularly made from the updated information.\n\nA site or user version of the file, `wwvb_iersdata.py` can be created or updated with `iersdata --site` or `iersdata --user`.  If the distributed iersdata is out of date, the generator will prompt you to run the update command.\n\nLeap seconds are inferred from the DUT1 data as follows: If X and Y are the\n1-digit-rounded DUT1 values for consecutive dates, and `X*Y<0`, then there is a\nleap second at the end of day X.  The direction of the leap second can be\ninferred from the sign of X, a 59-second minute if X is positive and a\n61-second minute if it is negative.  As long\nas DUT1 changes slowly enough during other times that there is at least one day\nof DUT1=+0.0, no incorrect (negative) leapsecond will be inferred. (something\nthat should remain true for the next few centuries, until the length of the day\nis 100ms different from 86400 seconds)\n\n\n# The phase modulation channel\n\nThis should be considered more experimental than the AM channel, as the\ntests only cover a single reference minute.  Further tests could be informed\nby the [other implementation I know of](http://www.leapsecond.com/tools/wwvb_pm.c), except that implementation appears incomplete.\n\n\n# Testing wwvbpy\n\nRun the testsuite, check coverage & type annotations with `gmake`.\n\nThere are several test suites:\n * `testwwvb.py`: Check output against expected values.  Uses hard coded leap seconds.  Tests amplitude and phase data, though the phase testcases are dubious as they were also generated by wwvbpy.\n * `testuwwvb.py`: Test the reduced-functionality version against the main version\n * `testls.py`: Check the IERS data through 2020-1-1 for expected leap seconds\n * `testpm.py`: Check the phase modulation data against a test case from NIST documentation\n * `testcli.py`: Check the commandline programs work as expected (limited tests to get 100% coverage)\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "Generate WWVB timecodes for any desired time",
    "version": "3.0.7",
    "project_urls": {
        "Homepage": "https://github.com/jepler/wwvbpy"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8cf5e15d54232bdcbeb6458b5d8bcc9c96a59428b9ea1a6f53824093f04f2589",
                "md5": "cf40535369a02b60cf83ec008e70e3d5",
                "sha256": "8f77004dc323dad93434c8237d8b690dce5d0095b2707324a3299d94ceba7325"
            },
            "downloads": -1,
            "filename": "wwvb-3.0.7-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "cf40535369a02b60cf83ec008e70e3d5",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 36701,
            "upload_time": "2024-03-19T00:32:34",
            "upload_time_iso_8601": "2024-03-19T00:32:34.540792Z",
            "url": "https://files.pythonhosted.org/packages/8c/f5/e15d54232bdcbeb6458b5d8bcc9c96a59428b9ea1a6f53824093f04f2589/wwvb-3.0.7-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "18a624ac83769e5abf5e26954ec87ebc6bbf316632f4319ccd19341463271cae",
                "md5": "03ac70ac2ab3dda2ee746b4049dfb4c5",
                "sha256": "a4898c6395fdfc3ab0461d6811658c568acb0a3bccb0b6b76f7e54f7001d7259"
            },
            "downloads": -1,
            "filename": "wwvb-3.0.7.tar.gz",
            "has_sig": false,
            "md5_digest": "03ac70ac2ab3dda2ee746b4049dfb4c5",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 60820,
            "upload_time": "2024-03-19T00:32:35",
            "upload_time_iso_8601": "2024-03-19T00:32:35.903515Z",
            "url": "https://files.pythonhosted.org/packages/18/a6/24ac83769e5abf5e26954ec87ebc6bbf316632f4319ccd19341463271cae/wwvb-3.0.7.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-03-19 00:32:35",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "jepler",
    "github_project": "wwvbpy",
    "travis_ci": false,
    "coveralls": true,
    "github_actions": true,
    "lcname": "wwvb"
}
        
Elapsed time: 0.20692s