# Python MTA Utilities
[![badge](https://github.com/nolanbconaway/underground/workflows/Push/badge.svg)](https://github.com/nolanbconaway/underground/actions)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/underground)](https://pypi.org/project/underground/)
[![PyPI](https://img.shields.io/pypi/v/underground)](https://pypi.org/project/underground/)
This is a set of Python utilities that I use to deal with [real-time NYC subway data](https://datamine.mta.info/).
I usually want to know when trains are going to depart a specific stop along a specific train line, so right now the tools are mostly for that. But I tried to write them to support arbitrary functionality.
## Install
``` sh
pip install underground
```
Or if you'd like to live dangerously:
``` sh
pip install git+https://github.com/nolanbconaway/underground.git#egg=underground
```
## Python API
Use the Python API like:
``` python
import os
from underground import metadata, SubwayFeed
ROUTE = 'Q'
feed = SubwayFeed.get(ROUTE)
# under the hood, the Q route is mapped to a URL. This call is equivalent:
URL = 'https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-nqrw'
feed = SubwayFeed.get(URL)
# or
URL = metadata.resolve_url(ROUTE)
feed = SubwayFeed.get(URL)
```
### List train stops on each line
`feed.extract_stop_dict` will return a dictionary of dictionaries, like:
```python
>>> feed.extract_stop_dict()
{
"route_1": {
"stop_1": [datetime.datetime(...), datetime.datetime(...)],
"stop_2": [datetime.datetime(...), datetime.datetime(...)],
...
},
"route_2": {
"stop_1": [datetime.datetime(...), datetime.datetime(...)],
"stop_2": [datetime.datetime(...), datetime.datetime(...)],
...
}
}
```
## CLI
The `underground` command line tool is also installed with the package.
### `feed`
```
$ underground feed --help
Usage: underground feed [OPTIONS] ROUTE_OR_URL
Request an MTA feed via a route or URL.
ROUTE_OR_URL may be either a feed URL or a route (which will be used to
look up the feed url).
Examples (both access the same feed):
underground feed Q --json > feed_nrqw.json
URL='https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-nqrw' &&
underground feed $URL --json > feed_nrqw.json
Options:
--json Option to output the feed data as JSON. Otherwise
output will be bytes.
-r, --retries INTEGER Retry attempts in case of API connection failure.
Default 100.
--help Show this message and exit.
```
### `stops`
```
$ underground stops --help
Usage: underground stops [OPTIONS] [H|M|D|1|Z|A|N|GS|SI|J|G|Q|L|B|R|F|E|2|7|W|
6|4|C|5|FS]
Print out train departure times for all stops on a subway line.
Options:
-f, --format TEXT strftime format for stop times. Use `epoch` for a
unix timestamp.
-r, --retries INTEGER Retry attempts in case of API connection failure.
Default 100.
-t, --timezone TEXT Output timezone. Ignored if --epoch. Default to NYC
time.
-s, --stalled-timeout INTEGER Number of seconds between the last movement
of a train and the API update before
considering a train stalled. Default is 90 as
recommended by the MTA. Numbers less than 1
disable this check.
--help Show this message and exit.
```
Stops are printed to stdout in the format `stop_id t1 t2 ... tn` .
``` sh
$ underground stops Q | tail -2
Q05S 19:01 19:09 19:16 19:25 19:34 19:44 19:51 19:58
Q04S 19:03 19:11 19:18 19:27 19:36 19:46 19:53 20:00
```
If you know your stop id (stop IDs can be found in [stops.txt](http://web.mta.info/developers/data/nyct/subway/google_transit.zip)), you can grep the results:
``` sh
$ underground stops Q | grep Q05S
Q05S 19:09 19:16 19:25 19:34 19:44 19:51 19:58
```
If you don't know your stop, see below for a handy tool!
### `findstops`
```
$ underground findstops --help
Usage: underground findstops [OPTIONS] QUERY...
Find your stop ID.
Query a location and look for your stop ID, like:
$ underground findstops parkside av
Options:
--json Option to output the data as JSON. Otherwise will be human readable
table.
--help Show this message and exit.
```
Enter the name of your stop and a table of stops with matching names will be returned.
```
$ underground findstops parkside
ID: D27N Direction: NORTH Lat/Lon: 40.655292, -73.961495 Name: PARKSIDE AV
ID: D27S Direction: SOUTH Lat/Lon: 40.655292, -73.961495 Name: PARKSIDE AV
```
Some names are ambiguous (try "fulton st"), for these you'll have to dig into the [metadata](http://web.mta.info/developers/data/nyct/subway/google_transit.zip) more carefully.
Raw data
{
"_id": null,
"home_page": "https://github.com/nolanbconaway/underground",
"name": "underground",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "nyc, transit, subway, command-line, cli",
"author": "Nolan Conaway",
"author_email": "nolanbconaway@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/94/e5/4ce33a08a85e76fc0c3d3f7d191440582c05741097beed617de63047c3c1/underground-1.0.0.tar.gz",
"platform": null,
"description": "# Python MTA Utilities\n\n[![badge](https://github.com/nolanbconaway/underground/workflows/Push/badge.svg)](https://github.com/nolanbconaway/underground/actions)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/underground)](https://pypi.org/project/underground/)\n[![PyPI](https://img.shields.io/pypi/v/underground)](https://pypi.org/project/underground/)\n\nThis is a set of Python utilities that I use to deal with [real-time NYC subway data](https://datamine.mta.info/).\n\nI usually want to know when trains are going to depart a specific stop along a specific train line, so right now the tools are mostly for that. But I tried to write them to support arbitrary functionality.\n\n## Install\n\n``` sh\npip install underground\n```\n\nOr if you'd like to live dangerously:\n\n``` sh\npip install git+https://github.com/nolanbconaway/underground.git#egg=underground\n```\n\n## Python API\n\nUse the Python API like:\n\n``` python\nimport os\n\nfrom underground import metadata, SubwayFeed\n\nROUTE = 'Q'\nfeed = SubwayFeed.get(ROUTE)\n\n# under the hood, the Q route is mapped to a URL. This call is equivalent:\nURL = 'https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-nqrw'\nfeed = SubwayFeed.get(URL)\n\n# or\nURL = metadata.resolve_url(ROUTE)\nfeed = SubwayFeed.get(URL)\n```\n\n### List train stops on each line\n\n`feed.extract_stop_dict` will return a dictionary of dictionaries, like:\n\n```python\n>>> feed.extract_stop_dict()\n\n{\n\n \"route_1\": {\n \"stop_1\": [datetime.datetime(...), datetime.datetime(...)], \n \"stop_2\": [datetime.datetime(...), datetime.datetime(...)], \n ...\n }, \n \"route_2\": {\n \"stop_1\": [datetime.datetime(...), datetime.datetime(...)], \n \"stop_2\": [datetime.datetime(...), datetime.datetime(...)], \n ...\n }\n\n}\n```\n\n## CLI\n\nThe `underground` command line tool is also installed with the package.\n\n### `feed` \n```\n$ underground feed --help\nUsage: underground feed [OPTIONS] ROUTE_OR_URL\n\n Request an MTA feed via a route or URL.\n\n ROUTE_OR_URL may be either a feed URL or a route (which will be used to\n look up the feed url).\n\n Examples (both access the same feed):\n\n underground feed Q --json > feed_nrqw.json\n\n URL='https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-nqrw' &&\n underground feed $URL --json > feed_nrqw.json\n\nOptions:\n --json Option to output the feed data as JSON. Otherwise\n output will be bytes.\n\n -r, --retries INTEGER Retry attempts in case of API connection failure.\n Default 100.\n\n --help Show this message and exit.\n```\n\n### `stops` \n\n```\n$ underground stops --help\nUsage: underground stops [OPTIONS] [H|M|D|1|Z|A|N|GS|SI|J|G|Q|L|B|R|F|E|2|7|W|\n 6|4|C|5|FS]\n \n Print out train departure times for all stops on a subway line.\n\nOptions:\n\n -f, --format TEXT strftime format for stop times. Use `epoch` for a\n unix timestamp.\n -r, --retries INTEGER Retry attempts in case of API connection failure.\n Default 100.\n -t, --timezone TEXT Output timezone. Ignored if --epoch. Default to NYC\n time.\n -s, --stalled-timeout INTEGER Number of seconds between the last movement\n of a train and the API update before\n considering a train stalled. Default is 90 as\n recommended by the MTA. Numbers less than 1\n disable this check.\n --help Show this message and exit.\n```\n\nStops are printed to stdout in the format `stop_id t1 t2 ... tn` .\n\n``` sh\n$ underground stops Q | tail -2\nQ05S 19:01 19:09 19:16 19:25 19:34 19:44 19:51 19:58\nQ04S 19:03 19:11 19:18 19:27 19:36 19:46 19:53 20:00\n```\n\nIf you know your stop id (stop IDs can be found in [stops.txt](http://web.mta.info/developers/data/nyct/subway/google_transit.zip)), you can grep the results:\n\n``` sh\n$ underground stops Q | grep Q05S\nQ05S 19:09 19:16 19:25 19:34 19:44 19:51 19:58\n```\n\nIf you don't know your stop, see below for a handy tool!\n\n### `findstops` \n\n```\n$ underground findstops --help\nUsage: underground findstops [OPTIONS] QUERY...\n\n Find your stop ID.\n\n Query a location and look for your stop ID, like:\n\n $ underground findstops parkside av\n\nOptions:\n\n --json Option to output the data as JSON. Otherwise will be human readable\n table.\n\n --help Show this message and exit.\n```\n\nEnter the name of your stop and a table of stops with matching names will be returned.\n\n```\n$ underground findstops parkside\nID: D27N Direction: NORTH Lat/Lon: 40.655292, -73.961495 Name: PARKSIDE AV\nID: D27S Direction: SOUTH Lat/Lon: 40.655292, -73.961495 Name: PARKSIDE AV\n```\n\nSome names are ambiguous (try \"fulton st\"), for these you'll have to dig into the [metadata](http://web.mta.info/developers/data/nyct/subway/google_transit.zip) more carefully.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Utilities for NYC's realtime MTA data feeds.",
"version": "1.0.0",
"project_urls": {
"Homepage": "https://github.com/nolanbconaway/underground"
},
"split_keywords": [
"nyc",
" transit",
" subway",
" command-line",
" cli"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "e6b6c94b76b12671b388a889dfba0d8ad75a695aa09f98422d9d53e09771a5fa",
"md5": "e61bc3b59b17edf82dd7cbb66b3c237d",
"sha256": "40fe2dbc3fb0a703efb4bbf1b14fa7bb51920296221c2d43f23ab929f9ea44d0"
},
"downloads": -1,
"filename": "underground-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "e61bc3b59b17edf82dd7cbb66b3c237d",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 16156,
"upload_time": "2024-11-10T16:46:04",
"upload_time_iso_8601": "2024-11-10T16:46:04.981507Z",
"url": "https://files.pythonhosted.org/packages/e6/b6/c94b76b12671b388a889dfba0d8ad75a695aa09f98422d9d53e09771a5fa/underground-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "94e54ce33a08a85e76fc0c3d3f7d191440582c05741097beed617de63047c3c1",
"md5": "3b9890b9b0f4d1da361aad49733a03df",
"sha256": "cb48fdb1de77e2dcb50c377ddc66c2a1d0b556104737c82019b9f288d2cd6fbd"
},
"downloads": -1,
"filename": "underground-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "3b9890b9b0f4d1da361aad49733a03df",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 15989,
"upload_time": "2024-11-10T16:46:07",
"upload_time_iso_8601": "2024-11-10T16:46:07.445626Z",
"url": "https://files.pythonhosted.org/packages/94/e5/4ce33a08a85e76fc0c3d3f7d191440582c05741097beed617de63047c3c1/underground-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-10 16:46:07",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "nolanbconaway",
"github_project": "underground",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "underground"
}