diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index 0733389..92b637d 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -25,9 +25,9 @@ jobs: # with: # ref: 'v0.6' # enable to check out prior version of codebase - name: Build wheels - uses: RalfG/python-wheels-manylinux-build@v0.3.4 + uses: RalfG/python-wheels-manylinux-build@v0.5.0 with: - python-versions: 'cp36-cp36m cp37-cp37m cp38-cp38 cp39-cp39' + python-versions: 'cp38-cp38 cp39-cp39 cp310-cp310 cp311-cp311' - name: Save artifacts uses: actions/upload-artifact@v2 with: @@ -42,7 +42,7 @@ jobs: strategy: matrix: os: [macos-latest, windows-latest] - python-version: [3.6, 3.7, 3.8, 3.9] + python-version: [3.8, 3.9, '3.10', '3.11'] steps: - uses: actions/checkout@v2 # with: diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ae7bec9..5afbe34 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.8 + python-version: '3.10' - name: Install Pandana run: | pip install . diff --git a/.github/workflows/cross-compatibility.yml b/.github/workflows/cross-compatibility.yml index ee118ca..3dc65a9 100644 --- a/.github/workflows/cross-compatibility.yml +++ b/.github/workflows/cross-compatibility.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest] - python-version: [3.6, 3.7, 3.8] + python-version: [3.8, 3.9, '3.10', '3.11'] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} @@ -42,7 +42,7 @@ jobs: strategy: matrix: os: [windows-latest] - python-version: [3.6, 3.7, 3.8] + python-version: [3.8, 3.9, '3.10', '3.11'] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/.github/workflows/installation.yml b/.github/workflows/installation.yml index 31c59a7..91d6d08 100644 --- a/.github/workflows/installation.yml +++ b/.github/workflows/installation.yml @@ -21,7 +21,7 @@ jobs: # Pip installation for Windows is not supported. Pip installation for Mac is # broken in the GitHub Actions environment with Pandana v0.6 but should be fixed # in the next Pandana release. - python-version: [3.6, 3.7, 3.8] + python-version: [3.8, 3.9, '3.10', '3.11'] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} @@ -43,7 +43,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: [3.6, 3.7, 3.8, 3.9] + python-version: [3.8, 3.9, '3.10', '3.11'] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fbd528..72dd42e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +v0.7 +==== + +2023/07/26 + +* Adds support for calculating accessibility isochrones: which nodes are within x network distance of a source node +* Allows a maximum distance to be set for POIs +* Adds a warning when a shortest path is requested between unconnected nodes +* Supports PyTables 3.7+ +* Support Pandas 2.0 +* Switches to pyproject.toml packaging standards +* Adds binaries on PyPI to support Python 3.10 and 3.11 +* Improves compilation in MacOS 12+ + v0.6.1 ====== diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2b3e64b..6f10e44 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,6 +71,8 @@ You can contact Sam Maurer, the lead maintainer, at `maurer@urbansim.com`. The binary package installers or "wheels" are built using a GitHub Actions workflow, because each one needs to be compiled in its own target environment. This should run automatically when a PR is opened, to confirm nothing is broken, and again when a release is tagged in GitHub. You can download the resulting wheel files from the Action status page and then upload them to PyPI using the same command as above. +How to create wheels for ARM Macs: As of 7/2023, GitHub Actions doesn't provide this environment yet. You'll need an ARM Mac to create the wheels. One at a time, set up a Conda environment with Python 3.8, 3.9, etc. Include cython, numpy, clang, llvm-openmp, and pytables. These need to be ARM-native Conda environments -- check that you're getting `osx-arm64` versions of libraries. Run `python setup.py bdist_wheel` to generate a wheel file. Once one is built for each Python version, upload them to PyPI using the command above. + ## Distributing a release on Conda Forge (for conda installation): diff --git a/README.md b/README.md index a49cabf..a1ed825 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ As of March 2021, binary installers are provided for Mac, Linux, and Windows thr - `pip install pandana` - `conda install pandana --channel conda-forge` -Pandana is easiest to install in Python 3.6 to 3.9. The last version of Pandana with Python 2.7 binaries is v0.4.4 on Conda Forge. The last version with Python 3.5 binaries is v0.6 on Pip. +Pandana is easiest to install in Python 3.8 to 3.11. The last version of Pandana with Python 2.7 binaries is v0.4.4 on Conda Forge. The last version with Python 3.5 binaries is v0.6 on Pip. See the documentation for information about other [installation options](http://udst.github.io/pandana/installation.html). diff --git a/docs/source/conf.py b/docs/source/conf.py index 8b4dda9..c23aea6 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -57,9 +57,9 @@ # built documents. # # The short X.Y version. -version = '0.6.1' +version = '0.7' # The full version, including alpha/beta/rc tags. -release = '0.6.1' +release = '0.7' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/source/index.rst b/docs/source/index.rst index 85337b7..db7fcd5 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -8,7 +8,7 @@ Pandana Pandana is a Python library for network analysis that uses `contraction hierarchies `_ to calculate super-fast travel accessibility metrics and shortest paths. The numerical code is in C++. -v0.6.1, released March 17, 2021. +v0.7, released July 26, 2023. Acknowledgments diff --git a/docs/source/installation.rst b/docs/source/installation.rst index 9029d6a..9cd6984 100644 --- a/docs/source/installation.rst +++ b/docs/source/installation.rst @@ -17,7 +17,7 @@ Or Conda:: conda install pandana --channel conda-forge -Pandana is easiest to install in Python 3.6 to 3.9. The last version of Pandana with Python 2.7 binaries is v0.4.4 on Conda Forge. The last version with Python 3.5 binaries is v0.6 on Pip. +Pandana is easiest to install in Python 3.8 to 3.11. The last version of Pandana with Python 2.7 binaries is v0.4.4 on Conda Forge. The last version with Python 3.5 binaries is v0.6 on Pip. ARM-based Macs diff --git a/examples/range_example.py b/examples/range_example.py index 4110562..8228d81 100644 --- a/examples/range_example.py +++ b/examples/range_example.py @@ -36,4 +36,4 @@ # dataframe.info() # dataframe.memory_usage(deep=True) -# .set_index(['1','2'], inplace=True) \ No newline at end of file +# .set_index(['1', '2'], inplace=True) diff --git a/examples/shortest_path_example.py b/examples/shortest_path_example.py index c53de6e..0b73fe2 100644 --- a/examples/shortest_path_example.py +++ b/examples/shortest_path_example.py @@ -50,7 +50,7 @@ net.set(pd.Series(net.node_ids)) s = net.aggregate(10000, type='count') -connected_nodes = s[s==477] +connected_nodes = s[s == 477] n = 10000 nodes_a = np.random.choice(connected_nodes.index, n) @@ -60,19 +60,19 @@ print(nodes_a[0]) print(nodes_b[0]) -print(net.shortest_path(nodes_a[0],nodes_b[0])) -print(net.shortest_path_length(nodes_a[0],nodes_b[0])) +print(net.shortest_path(nodes_a[0], nodes_b[0])) +print(net.shortest_path_length(nodes_a[0], nodes_b[0])) print('Shortest path 2:') print(nodes_a[1]) print(nodes_b[1]) -print(net.shortest_path(nodes_a[1],nodes_b[1])) -print(net.shortest_path_length(nodes_a[1],nodes_b[1])) +print(net.shortest_path(nodes_a[1], nodes_b[1])) +print(net.shortest_path_length(nodes_a[1], nodes_b[1])) print('Repeat with vectorized calculations:') -print(net.shortest_paths(nodes_a[0:2],nodes_b[0:2])) -print(net.shortest_path_lengths(nodes_a[0:2],nodes_b[0:2])) +print(net.shortest_paths(nodes_a[0:2], nodes_b[0:2])) +print(net.shortest_path_lengths(nodes_a[0:2], nodes_b[0:2])) # Performance comparison print('Performance comparison for 10k distance calculations:') diff --git a/pandana/__init__.py b/pandana/__init__.py index 41b8045..bdb7d53 100644 --- a/pandana/__init__.py +++ b/pandana/__init__.py @@ -1,3 +1,3 @@ from .network import Network -version = __version__ = '0.7.dev0' +version = __version__ = '0.7' diff --git a/pandana/network.py b/pandana/network.py index fe3086c..6842edd 100644 --- a/pandana/network.py +++ b/pandana/network.py @@ -284,8 +284,8 @@ def shortest_path_length(self, node_a, node_b, imp_name=None): if len == 4294967.295: warnings.warn( - "Unsigned integer: shortest path distance is trying to be calculated between\ - external %s and %s unconntected nodes"%(node_a, node_b) + "Unsigned integer: shortest path distance is trying to be calculated between\ + external %s and %s unconntected nodes" % (node_a, node_b) ) return len @@ -329,11 +329,11 @@ def shortest_path_lengths(self, nodes_a, nodes_b, imp_name=None): lens = self.net.shortest_path_distances(nodes_a_idx, nodes_b_idx, imp_num) if 4294967.295 in lens: - unconnected_idx = [i for i,v in enumerate(lens) if v == 4294967.295] - unconnected_nodes = [(nodes_a[i],nodes_b[i]) for i in unconnected_idx] - warnings.warn( - "Unsigned integer: shortest path distance is trying to be calculated \ - between the following external unconnected nodes: %s"%(unconnected_nodes)) + unconnected_idx = [i for i, v in enumerate(lens) if v == 4294967.295] + unconnected_nodes = [(nodes_a[i], nodes_b[i]) for i in unconnected_idx] + warnings.warn( + "Unsigned integer: shortest path distance is trying to be calculated \ + between the following external unconnected nodes: %s" % (unconnected_nodes)) return lens diff --git a/pandana/utils.py b/pandana/utils.py index b3ef06f..c2507c1 100644 --- a/pandana/utils.py +++ b/pandana/utils.py @@ -26,9 +26,10 @@ def reindex(series1, series2): how="left") return df.right + def adjacency_matrix(edges_df, plot_matrix=False): df = pd.crosstab(edges_df['from'], edges_df['to']) idx = df.columns.union(df.index) - df = df.reindex(index = idx, columns=idx, fill_value=0) + df = df.reindex(index=idx, columns=idx, fill_value=0) return df diff --git a/setup.py b/setup.py index 0c9b873..7682b22 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ ############################################### -## Building the C++ extension +# Building the C++ extension ############################################### extra_compile_args = ["-w", "-std=c++11", "-O3"] @@ -50,12 +50,12 @@ ) ) - if "10.15" in os.popen("sw_vers").read(): + if " 10.15" in os.popen("sw_vers").read(): os.environ["CC"] = cc_catalina - elif "11." in os.popen("sw_vers").read(): - os.environ["CC"] = cc_catalina - else: + elif " 10." in os.popen("sw_vers").read(): # 10.14 and earlier os.environ["CC"] = cc + else: # 11.x, 12.x, etc. + os.environ["CC"] = cc_catalina else: print( @@ -77,23 +77,23 @@ cyaccess = Extension( - name='pandana.cyaccess', - sources=[ - 'src/accessibility.cpp', - 'src/graphalg.cpp', - 'src/cyaccess.pyx', - 'src/contraction_hierarchies/src/libch.cpp'], - language='c++', - include_dirs=['.', np.get_include()], - extra_compile_args=extra_compile_args, - extra_link_args=extra_link_args) + name='pandana.cyaccess', + sources=[ + 'src/accessibility.cpp', + 'src/graphalg.cpp', + 'src/cyaccess.pyx', + 'src/contraction_hierarchies/src/libch.cpp'], + language='c++', + include_dirs=['.', np.get_include()], + extra_compile_args=extra_compile_args, + extra_link_args=extra_link_args) ############################################### -## Standard setup +# Standard setup ############################################### -version = "0.7.dev0" +version = "0.7" packages = find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]) @@ -120,12 +120,12 @@ 'tables >=3.1' ], classifiers=[ - "Development Status :: 4 - Beta", - "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "License :: OSI Approved :: GNU Affero General Public License v3", ], )