diff --git a/.travis.yml b/.travis.yml index c370c13..c4cfcb3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,11 +2,15 @@ language: python sudo: false python: - '2.7' +- '3.6' + +matrix: + allow_failures: + - python: '3.6' + fast_finish: true install: -- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh - -O miniconda.sh; else wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh - -O miniconda.sh; fi +- wget http://bit.ly/miniconda -O miniconda.sh - bash miniconda.sh -b -p $HOME/miniconda - export PATH="$HOME/miniconda/bin:$PATH" - hash -r @@ -15,11 +19,9 @@ install: - conda info -a - conda config --add channels udst - conda config --add channels conda-forge -- | - conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION pip numpy=1.11 pandas pytest ipython-notebook pycodestyle matplotlib scikit-learn pyyaml basemap basemap-data-hires -- source activate test-environment +- conda create -q -n test-env python=$TRAVIS_PYTHON_VERSION pip numpy pandas pytest jupyter pycodestyle matplotlib scikit-learn pyyaml basemap basemap-data-hires pandana geopy osmnet +- source activate test-env - conda list -- pip install pandana==0.3.0 geopy osmnet - pip install . after_success: @@ -32,9 +34,8 @@ script: - cd ../urbanaccess/tests/integration; python remove_nb_magic.py -in simple_example.py -out simple_example_clean.py - cd ../../../demo; python simple_example_clean.py - cd ../urbanaccess/tests/integration; python integration_madison.py -- python integration_sandiego.py -- python integration_gb.py && cd $TRAVIS_BUILD_DIR +- python integration_sandiego.py && cd $TRAVIS_BUILD_DIR env: global: - secure: SW6dfeQen1oZUYa2pr/qMdJGDK5c3tIbJsF1POLSMtgpbYaRQvogCkCd7sFXiTkxTCaNnz/eQyT2nDyUZJyDmYpntZmRthuN1zDgNk8ziDpmy/PF1bD4eshDr3MeoI4HgNYryl5qD8brEP0up0P/rvaAMoi26w4eyk0r+sO3PDVF6Jy4MwTufY4a4B4qYpi7V8yhExExytshHOEjD8C2IqEQDkwyR9oto2Gx8EpoCJEvxETG+aqLw1xj2UnXnbWND10Ni6pkeRpjAHFv4qM0i35griG2RKu9075Dubz/6UPMvpIEy581Zx5cqaSuOSUzde1L172vLTgOH31lnFXe1flHau1wI2gxOiamSdlVTAnVtL5P1aEtm1L5FjBcPlIs9rHmNGnydByX1Qe16HRLUopgAVm+jLZqWxrlesC5ax3uJ6Q3g0ZyKfmTJ5uWDeRusMVZswBT3NJc0BhkHDq7tE+3fokBfFApJcQwoXIplvRwXPkGFtKnL2IgCMTrKbDzGEYfdm/v7eV2xYe5hrEUIC9cUhkC1Ns2azAERXSgWcyM7ciFH3r1Jz9ixT+fuw9bTXibqcMjAmxdcQAW9y/rIPRJ3GMSdT7WEzYX19naGr+oyKqVMgsHFQ+wL7U5iblAGIy8VLNpE7Aa67dyG6SVAPTGzp0RouYLY9LYiRIybrI= + secure: SW6dfeQen1oZUYa2pr/qMdJGDK5c3tIbJsF1POLSMtgpbYaRQvogCkCd7sFXiTkxTCaNnz/eQyT2nDyUZJyDmYpntZmRthuN1zDgNk8ziDpmy/PF1bD4eshDr3MeoI4HgNYryl5qD8brEP0up0P/rvaAMoi26w4eyk0r+sO3PDVF6Jy4MwTufY4a4B4qYpi7V8yhExExytshHOEjD8C2IqEQDkwyR9oto2Gx8EpoCJEvxETG+aqLw1xj2UnXnbWND10Ni6pkeRpjAHFv4qM0i35griG2RKu9075Dubz/6UPMvpIEy581Zx5cqaSuOSUzde1L172vLTgOH31lnFXe1flHau1wI2gxOiamSdlVTAnVtL5P1aEtm1L5FjBcPlIs9rHmNGnydByX1Qe16HRLUopgAVm+jLZqWxrlesC5ax3uJ6Q3g0ZyKfmTJ5uWDeRusMVZswBT3NJc0BhkHDq7tE+3fokBfFApJcQwoXIplvRwXPkGFtKnL2IgCMTrKbDzGEYfdm/v7eV2xYe5hrEUIC9cUhkC1Ns2azAERXSgWcyM7ciFH3r1Jz9ixT+fuw9bTXibqcMjAmxdcQAW9y/rIPRJ3GMSdT7WEzYX19naGr+oyKqVMgsHFQ+wL7U5iblAGIy8VLNpE7Aa67dyG6SVAPTGzp0RouYLY9LYiRIybrI= \ No newline at end of file diff --git a/HISTORY.rst b/HISTORY.rst index 3b765cb..245419e 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,3 +1,15 @@ +v0.2.0 +====== + +2018/11/02 + +* Python 3 compatibility (preserving compatibility with Python 2) + * Updated demo for cross compatibility + * Added Python 3 to travis +* Support latest version of Pandana v0.4.1 (preserving compatibility with prior versions) +* Removed integration test using Great Britain dataset as data no longer available for download +* Updated readme and docs + v0.1.0 ====== diff --git a/README.rst b/README.rst index e5ea25a..660eaac 100644 --- a/README.rst +++ b/README.rst @@ -46,16 +46,21 @@ Let us know what you are working on or if you think you have a great use case by tweeting us at ``@urbansim`` or post on the UrbanSim `forum `__. +Citation and academic literature +-------------------------------- + +To cite this tool and for a complete description of the UrbanAccess methodology see the paper below: + +`Samuel D. Blanchard and Paul Waddell. 2017. "UrbanAccess: Generalized Methodology for Measuring Regional Accessibility with an Integrated Pedestrian and Transit Network." Transportation Research Record: Journal of the Transportation Research Board. No. 2653. pp. 35–44. `__ + +For other related literature see `here `__. + Current status -------------- -UrbanAccess is currently in a alpha release and only compatible with -Python 2.x. Further code refinements are expected. - *Forthcoming improvements:* - Unit tests -- Python 3 Reporting bugs -------------- @@ -77,7 +82,9 @@ Install the latest release conda ~~~~~~ -conda installation is forthcoming. +UrbanAccess is available on conda and can be installed with:: + + conda install -c udst urbanaccess pip ~~~~~~ @@ -88,7 +95,7 @@ UrbanAccess is available on PyPI and can be installed with:: Development Installation ------------------------ -UrbanAccess is currently in a alpha release and further code refinements are expected. As such, it is suggested to install using the ``develop`` command rather than ``install``. Make sure you are using the latest version of the code base by using git's ``git pull`` inside the cloned repository. +Developers contributing code can install using the ``develop`` command rather than ``install``. Make sure you are using the latest version of the codebase by using git's ``git pull`` inside the cloned repository. To install UrbanAccess follow these steps: @@ -117,15 +124,6 @@ UrbanAccess are: ``stop_times``, ``stops``, ``routes``, ``calendar``, and ``trips`` however if there is no ``calendar``, ``calendar_dates`` can be used as a replacement. -Citation and academic literature --------------------------------- - -To cite this tool and for a complete description of the UrbanAccess methodology see the paper below: - -`Samuel D. Blanchard and Paul Waddell. 2017. "UrbanAccess: Generalized Methodology for Measuring Regional Accessibility with an Integrated Pedestrian and Transit Network." Transportation Research Record: Journal of the Transportation Research Board. No. 2653. pp. 35–44. `__ - -For other related literature see `here `__. - Related UDST libraries ---------------------- diff --git a/demo/simple_example.ipynb b/demo/simple_example.ipynb index 3fad342..a8088c1 100644 --- a/demo/simple_example.ipynb +++ b/demo/simple_example.ipynb @@ -13,15 +13,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "** Author:** UrbanSim\n", + "**Author:** UrbanSim\n", "\n", "This notebook provides a brief overview of the main functionality of UrbanAccess with examples using AC Transit and BART GTFS data and OpenStreetMap (OSM) pedestrian network data to create an integrated transit and pedestrian network for Oakland, CA for use in Pandana network accessibility queries.\n", "\n", - "** UrbanAccess on UDST:** https://github.com/UDST/urbanaccess\n", + "**UrbanAccess on UDST:** https://github.com/UDST/urbanaccess\n", "\n", - "** UrbanAccess documentation:** https://udst.github.io/urbanaccess/index.html\n", + "**UrbanAccess documentation:** https://udst.github.io/urbanaccess/index.html\n", "\n", - "** UrbanAccess citation:** \n", + "**UrbanAccess citation:** \n", "\n", "`Samuel D. Blanchard and Paul Waddell, 2017, \"UrbanAccess: Generalized Methodology for Measuring Regional Accessibility with an Integrated Pedestrian and Transit Network\" Transportation Research Record: Journal of the Transportation Research Board, 2653: 35–44.`\n", "\n", @@ -75,9 +75,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", @@ -127,9 +125,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "settings.to_dict()" @@ -192,9 +188,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "feeds.to_dict()" @@ -226,9 +220,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "gtfsfeeds.search(search_text='Bay Area Rapid Transit',\n", @@ -246,9 +238,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "gtfsfeeds.search(search_text='Bay Area Rapid Transit',\n", @@ -276,9 +266,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "feeds.add_feed(add_dict={'ac transit': 'http://www.actransit.org/wp-content/uploads/GTFSJune182017B.zip'})" @@ -294,9 +282,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "feeds.to_dict()" @@ -321,9 +307,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "gtfsfeeds.download()" @@ -351,9 +335,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "validation = True\n", @@ -388,9 +370,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "loaded_feeds.stops.head()" @@ -406,9 +386,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "loaded_feeds.stops.unique_agency_id.unique()" @@ -424,9 +402,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "loaded_feeds.stops.plot(kind='scatter', x='stop_lon', y='stop_lat', s=0.1)" @@ -435,9 +411,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "loaded_feeds.routes.head()" @@ -446,9 +420,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "loaded_feeds.stop_times.head()" @@ -457,9 +429,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "loaded_feeds.trips.head()" @@ -468,9 +438,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "loaded_feeds.calendar.head()" @@ -502,9 +470,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "ua.gtfs.network.create_transit_net(gtfsfeeds_dfs=loaded_feeds,\n", @@ -548,9 +514,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "urbanaccess_net.transit_edges.head()" @@ -559,9 +523,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "urbanaccess_net.transit_nodes.head()" @@ -570,9 +532,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "urbanaccess_net.transit_nodes.plot(kind='scatter', x='x', y='y', s=0.1)" @@ -597,9 +557,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "nodes, edges = ua.osm.load.ua_network_from_bbox(bbox=bbox,\n", @@ -627,9 +585,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "ua.osm.network.create_osm_net(osm_edges=edges,\n", @@ -647,9 +603,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "urbanaccess_net.osm_nodes.head()" @@ -658,9 +612,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "urbanaccess_net.osm_edges.head()" @@ -669,9 +621,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "urbanaccess_net.osm_nodes.plot(kind='scatter', x='x', y='y', s=0.1)" @@ -696,9 +646,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "ua.network.integrate_network(urbanaccess_network=urbanaccess_net,\n", @@ -715,9 +663,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "urbanaccess_net.net_nodes.head()" @@ -726,9 +672,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "urbanaccess_net.net_edges.head()" @@ -737,9 +681,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "urbanaccess_net.net_edges[urbanaccess_net.net_edges['net_type'] == 'transit'].head()" @@ -764,9 +706,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "ua.network.save_network(urbanaccess_network=urbanaccess_net,\n", @@ -793,9 +733,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "urbanaccess_net = ua.network.load_network(filename='final_net.h5')" @@ -829,9 +767,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "ua.plot.plot_net(nodes=urbanaccess_net.net_nodes,\n", @@ -868,9 +804,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "edgecolor = ua.plot.col_colors(df=urbanaccess_net.net_edges, col='weight', cmap='gist_heat_r', num_bins=5)\n", @@ -892,9 +826,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "edgecolor = ua.plot.col_colors(df=urbanaccess_net.net_edges, col='weight', cmap='gist_heat_r', num_bins=5)\n", @@ -925,9 +857,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "ua.plot.plot_net(nodes=urbanaccess_net.net_nodes,\n", @@ -950,9 +880,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "ua.plot.plot_net(nodes=urbanaccess_net.net_nodes,\n", @@ -989,9 +917,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "urbanaccess_net.net_edges['unique_route_id'].unique()" @@ -1000,9 +926,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "ua.plot.plot_net(nodes=urbanaccess_net.net_nodes,\n", @@ -1034,9 +958,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "urbanaccess_net.net_edges['unique_agency_id'].unique()" @@ -1045,9 +967,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "ua.plot.plot_net(nodes=urbanaccess_net.net_nodes,\n", @@ -1095,9 +1015,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "ua.gtfs.headways.headways(gtfsfeeds_df=loaded_feeds,\n", @@ -1107,9 +1025,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "loaded_feeds.headways.head()" @@ -1134,9 +1050,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "ua.network.integrate_network(urbanaccess_network=urbanaccess_net,\n", @@ -1155,9 +1069,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "edgecolor = ua.plot.col_colors(df=urbanaccess_net.net_edges, col='weight', cmap='gist_heat_r', num_bins=5)\n", @@ -1222,7 +1134,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false, "scrolled": true }, "outputs": [], @@ -1230,7 +1141,7 @@ "blocks = pd.read_hdf('bay_area_demo_data.h5','blocks')\n", "# remove blocks that contain all water\n", "blocks = blocks[blocks['square_meters_land'] != 0]\n", - "print 'Total number of blocks: {:,}'.format(len(blocks))\n", + "print('Total number of blocks: {:,}'.format(len(blocks)))\n", "blocks.head()" ] }, @@ -1244,22 +1155,19 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "lng_max, lat_min, lng_min, lat_max = bbox\n", "outside_bbox = blocks.loc[~(((lng_max < blocks[\"x\"]) & (blocks[\"x\"] < lng_min)) & ((lat_min < blocks[\"y\"]) & (blocks[\"y\"] < lat_max)))]\n", "blocks_subset = blocks.drop(outside_bbox.index)\n", - "print 'Total number of subset blocks: {:,}'.format(len(blocks_subset))" + "print('Total number of subset blocks: {:,}'.format(len(blocks_subset)))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false, "scrolled": false }, "outputs": [], @@ -1284,9 +1192,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "s_time = time.time()\n", @@ -1366,9 +1272,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "s_time = time.time()\n", @@ -1388,14 +1292,12 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ - "print jobs_45.head()\n", - "print jobs_30.head()\n", - "print jobs_15.head()" + "print(jobs_45.head())\n", + "print(jobs_30.head())\n", + "print(jobs_15.head())" ] }, { @@ -1416,7 +1318,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "collapsed": false, "scrolled": true }, "outputs": [], @@ -1440,9 +1341,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "s_time = time.time()\n", @@ -1464,9 +1363,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": false - }, + "metadata": {}, "outputs": [], "source": [ "s_time = time.time()\n", @@ -1477,25 +1374,61 @@ " plot_kwargs={'cmap':'gist_heat_r','s':4,'edgecolor':'none'})\n", "print('Took {:,.2f} seconds'.format(time.time() - s_time))" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 2", + "display_name": "Python [conda env:urbanaccess-py3-pdna4]", "language": "python", - "name": "python2" + "name": "conda-env-urbanaccess-py3-pdna4-py" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 2 + "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.11" + "pygments_lexer": "ipython3", + "version": "3.6.6" } }, "nbformat": 4, diff --git a/docs/source/installation.rst b/docs/source/installation.rst index 4097e2a..9b577cc 100644 --- a/docs/source/installation.rst +++ b/docs/source/installation.rst @@ -7,9 +7,10 @@ Dependencies ------------ * requests >= 2.9.1 +* six >= 1.11 * pandas >= 0.17.0 * numpy >= 1.11 -* osmnet >= 0.1a +* osmnet >= 0.1.4 * pandana >= 0.2.0 * matplotlib >= 2.0 * geopy >= 1.11.0 @@ -24,19 +25,18 @@ Dependencies can be installed through the ``conda-forge`` and ``udst`` channels. Current status -------------- -UrbanAccess is currently in a alpha release and only compatible with Python 2.x. Further code refinements are expected. - *Forthcoming improvements:* * Unit tests -* Python 3 Install the latest release -------------------------- conda ~~~~~~ -conda installation is forthcoming. +UrbanAccess is available on conda and can be installed with:: + + conda install -c udst urbanaccess pip ~~~~~~ @@ -47,7 +47,7 @@ UrbanAccess is available on PyPI and can be installed with:: Development Installation ------------------------ -UrbanAccess is currently in a alpha release and further code refinements are expected. As such, it is suggested to install using the ``develop`` command rather than ``install``. Make sure you are using the latest version of the code base by using git's ``git pull`` inside the cloned repository. +Developers contributing code can install using the ``develop`` command rather than ``install``. Make sure you are using the latest version of the codebase by using git's ``git pull`` inside the cloned repository. To install UrbanAccess follow these steps: diff --git a/setup.py b/setup.py index 0bc455f..032de19 100644 --- a/setup.py +++ b/setup.py @@ -18,20 +18,26 @@ setup( name='urbanaccess', - version='0.1.0', + version='0.2.0', license='AGPL', description=description, long_description=long_description, author='UrbanSim Inc. and Samuel D. Blanchard', url='https://github.com/UDST/urbanaccess', classifiers=[ + 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', 'Development Status :: 3 - Alpha', 'License :: OSI Approved :: GNU Affero General Public License v3' ], packages=find_packages(exclude=['*.tests']), install_requires=[ 'requests >= 2.9.1', + 'six >= 1.11', 'pandas >= 0.17.0', 'numpy >= 1.11', 'osmnet >= 0.1.4', diff --git a/urbanaccess/__init__.py b/urbanaccess/__init__.py index cf73268..4c16e9e 100644 --- a/urbanaccess/__init__.py +++ b/urbanaccess/__init__.py @@ -9,6 +9,6 @@ from .gtfsfeeds import * from .plot import * -__version__ = "0.1.0" +__version__ = "0.2.0" version = __version__ diff --git a/urbanaccess/gtfs/load.py b/urbanaccess/gtfs/load.py index 68bca75..0facd16 100644 --- a/urbanaccess/gtfs/load.py +++ b/urbanaccess/gtfs/load.py @@ -3,6 +3,7 @@ import re import time import pandas as pd +import six from urbanaccess import config from urbanaccess.utils import log @@ -31,7 +32,8 @@ def _standardize_txt(csv_rootpath=os.path.join(config.settings.data_folder, 'stop_times.txt', 'calendar.txt', 'agency.txt', 'calendar_dates.txt'] - _txt_encoder_check(gtfsfiles_to_use, csv_rootpath) + if six.PY2: + _txt_encoder_check(gtfsfiles_to_use, csv_rootpath) _txt_header_whitespace_check(gtfsfiles_to_use, csv_rootpath) @@ -40,7 +42,8 @@ def _txt_encoder_check(gtfsfiles_to_use, config.settings.data_folder, 'gtfsfeed_text')): """ - Standardize all text files inside a GTFS feed for encoding problems + Standardize all text files inside a GTFS feed for encoding problems. + Has not been updated for Python 3. Parameters ---------- diff --git a/urbanaccess/gtfs/utils_format.py b/urbanaccess/gtfs/utils_format.py index 8750fe9..6ed694d 100644 --- a/urbanaccess/gtfs/utils_format.py +++ b/urbanaccess/gtfs/utils_format.py @@ -799,20 +799,17 @@ def _timetoseconds(df, time_cols): h = pd.to_numeric(df[col].str[0:2]) if h.any() > 48: - log( - 'Warning: {} hour value is large and may be incorrect, ' + log('Warning: {} hour value is large and may be incorrect, ' 'please check this.'.format( df[col].str[0:2].max()), level=lg.WARNING) m = pd.to_numeric(df[col].str[3:5]) if m.any() > 60: - log( - 'Warning: {} minute value is large and may be incorrect, ' + log('Warning: {} minute value is large and may be incorrect, ' 'please check this.'.format( df[col].str[3:5].max()), level=lg.WARNING) s = pd.to_numeric(df[col].str[6:8]) if s.any() > 60: - log( - 'Warning: {} second value is large and may be incorrect, ' + log('Warning: {} second value is large and may be incorrect, ' 'please check this.'.format( df[col].str[6:8].max()), level=lg.WARNING) col_series = (h * 60 * 60) + (m * 60) + s @@ -830,8 +827,7 @@ def _timetoseconds(df, time_cols): final_df = pd.merge(df, concat_series_df, how='left', left_index=True, right_index=True, sort=False, copy=False) - log( - 'Successfully converted {} to seconds past midnight and appended new ' + log('Successfully converted {} to seconds past midnight and appended new ' 'columns to stop_times. Took {:,.2f} seconds'.format( time_cols, time.time() - start_time)) diff --git a/urbanaccess/gtfsfeeds.py b/urbanaccess/gtfsfeeds.py index cc6f0f7..0eb5373 100644 --- a/urbanaccess/gtfsfeeds.py +++ b/urbanaccess/gtfsfeeds.py @@ -1,12 +1,11 @@ import yaml import pandas as pd -import urllib -from urllib2 import urlopen import traceback import zipfile import os import logging as lg import time +from six.moves.urllib.request import urlopen from urbanaccess.utils import log from urbanaccess import config @@ -469,7 +468,7 @@ def download(data_folder=os.path.join(config.settings.data_folder), zipfile_path = ''.join([download_folder, '/', feed_name_key, '.zip']) if 'http' in feed_url_value: - status_code = urllib.urlopen(feed_url_value).getcode() + status_code = urlopen(feed_url_value).getcode() if status_code == 200: file = urlopen(feed_url_value) @@ -608,8 +607,8 @@ def _zipfile_type_check(file, feed_url_value): ------- nothing """ - if 'zip' not in file.info().dict['content-type'] \ - is True or 'octet' not in file.info().dict['content-type'] is True: + if 'zip' not in file.info().get('Content-Type') is True \ + or 'octet' not in file.info().get('Content-Type') is True: raise ValueError( 'data requested at {} is not a zipfile. ' 'Data must be a zipfile'.format(feed_url_value)) diff --git a/urbanaccess/osm/load.py b/urbanaccess/osm/load.py index c2a7693..567b1d6 100644 --- a/urbanaccess/osm/load.py +++ b/urbanaccess/osm/load.py @@ -2,14 +2,17 @@ import time from osmnet.load import network_from_bbox -from pandana.network import reserve_num_graphs +import pandana from pandana import Network from urbanaccess.utils import log # set the number of Pandana Networks in memory to arbitrary 40 for # removing low connectivity nodes -reserve_num_graphs(40) +# Note: reserve_num_graphs was removed in Pandana beginning in v0.4 but is +# required for prior versions +if pandana.__version__[:3] in ['0.1', '0.2', '0.3']: + pandana.network.reserve_num_graphs(40) def ua_network_from_bbox(lat_min=None, lng_min=None, lat_max=None, diff --git a/urbanaccess/tests/integration/integration_gb.py b/urbanaccess/tests/integration/integration_gb.py deleted file mode 100644 index 9eae3f0..0000000 --- a/urbanaccess/tests/integration/integration_gb.py +++ /dev/null @@ -1,45 +0,0 @@ -import os -import time - -import urbanaccess -from urbanaccess.gtfsfeeds import feeds - -start_time = time.time() - -name = 'gb' -url = 'http://www.gbrail.info/gtfs.zip' - -print ('-------------------------') -print('Starting integration test for {}...'.format(name)) - -new_feed = {name: url} -feeds.add_feed(new_feed) - -script_path = os.path.dirname(os.path.realpath(__file__)) -root_path = os.path.join(script_path, 'data', name) -data_path = os.path.join(root_path, 'gtfsfeed_text') - -urbanaccess.gtfsfeeds.download(data_folder=root_path) - -validation = True -verbose = True -# small bbox for testing purposes -bbox = (-0.5383, 51.3546, 0.2856, 51.7508) -remove_stops_outsidebbox = True -append_definitions = True - -loaded_feeds = urbanaccess.gtfs.load.gtfsfeed_to_df(data_path, - validation, - verbose, - bbox, - remove_stops_outsidebbox, - append_definitions) - -transit_net = urbanaccess.gtfs.network.create_transit_net( - gtfsfeeds_dfs=loaded_feeds, - day='monday', - timerange=['07:00:00', '10:00:00']) - -print('{} integration test completed successfully. Took {:,' - '.2f} seconds'.format(name, time.time() - start_time)) -print ('-------------------------') diff --git a/urbanaccess/tests/integration/integration_madison.py b/urbanaccess/tests/integration/integration_madison.py index e1ad7b8..9ebeaf9 100644 --- a/urbanaccess/tests/integration/integration_madison.py +++ b/urbanaccess/tests/integration/integration_madison.py @@ -9,7 +9,7 @@ name = 'madison' url = 'http://www.gtfs-data-exchange.com/agency/city-of-madison/latest.zip' -print ('-------------------------') +print('-------------------------') print('Starting integration test for {}...'.format(name)) new_feed = {name: url} @@ -88,4 +88,4 @@ print('{} integration test completed successfully. Took {:,' '.2f} seconds'.format(name, time.time() - start_time)) -print ('-------------------------') +print('-------------------------') diff --git a/urbanaccess/tests/integration/integration_sandiego.py b/urbanaccess/tests/integration/integration_sandiego.py index d15b155..1342164 100644 --- a/urbanaccess/tests/integration/integration_sandiego.py +++ b/urbanaccess/tests/integration/integration_sandiego.py @@ -8,7 +8,7 @@ name = 'san diego' -print ('-------------------------') +print('-------------------------') print('Starting integration test for {}...'.format(name)) script_path = os.path.dirname(os.path.realpath(__file__)) @@ -69,4 +69,4 @@ print('{} integration test completed successfully. Took {:,' '.2f} seconds'.format(name, time.time() - start_time)) -print ('-------------------------') +print('-------------------------')