├── .gitattributes
├── .github
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE.md
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
├── release.yml
└── workflows
│ ├── build_docs.yml
│ ├── release_and_publish.yml
│ └── testing.yml
├── .gitignore
├── .pre-commit-config.yaml
├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── ci
├── 310-latest.yaml
├── 310-oldest.yaml
├── 311-latest.yaml
├── 312-dev.yaml
└── 312-latest.yaml
├── codecov.yml
├── docs
├── .buildinfo
├── .nojekyll
├── Makefile
├── _static
│ ├── images
│ │ ├── ardc_logo.png
│ │ ├── crime_counts.png
│ │ ├── facility_location.png
│ │ ├── mst_logo_pasta.png
│ │ ├── net_rep.png
│ │ ├── network_k.png
│ │ ├── nsf_logo.png
│ │ ├── pysal_favicon.ico
│ │ ├── pysal_logo.png
│ │ ├── pysal_logo.svg
│ │ ├── pysal_nav_logo_2line.svg
│ │ └── spaghetti_nav_logo.svg
│ ├── pysal-styles.css
│ ├── pysal_favicon.ico
│ └── references.bib
├── api.rst
├── conf.py
├── index.rst
├── installation.rst
├── references.rst
└── tutorials.rst
├── environment.yml
├── notebooks
├── caveats.ipynb
├── connected-components.ipynb
├── facility-location.ipynb
├── network-segmentation.ipynb
├── network-spatial-autocorrelation.ipynb
├── network-spatial-dependence.ipynb
├── network-spatial-weights.ipynb
├── pointpattern-attributes.ipynb
├── quickstart.ipynb
├── shortest-path-visualization.ipynb
├── spanning-trees.ipynb
├── transportation-problem.ipynb
└── tsp.ipynb
├── paper
├── figs
│ ├── spaghetti_network.png
│ └── spaghetti_pointpattern_moran.png
├── paper.bib
└── paper.md
├── pyproject.toml
└── spaghetti
├── __init__.py
├── analysis.py
├── network.py
├── tests
├── __init__.py
└── test_network.py
└── util.py
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.ipynb linguist-language=Python
2 | spaghetti/_version.py export-subst
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines for `spaghetti`
2 |
3 | Thank you for your interest in contributing! We work primarily on Github. Please review the contributing procedures [here](http://pysal.org/getting_started#for-developers) and [here](https://github.com/pysal/pysal/wiki/GitHub-Standard-Operating-Procedures) so that we can accept your contributions! Alternatively, contact someone in the [development chat channel](https://gitter.im//pysal/Spaghetti).
4 |
5 |
6 | ## Contact
7 |
8 | 1. All questions, comments, & discussions should happen in a public forum, where possible. Please start a [discussion](https://github.com/pysal/spaghetti/discussions) for questions or open an [issue](https://github.com/pysal/spaghetti/issues) if there appears to be a bug. Private messages and emails will not be answered in a substantive manner.
9 |
10 |
11 | ## Style and format
12 |
13 | 1. At the time of this writing, Python 3.10, 3.11, and 3.12 are the officially supported versions.
14 | 2. This project implements the linting and formatting conventions of [`ruff`](https://docs.astral.sh/ruff/) on all incoming Pull Requests. To ensure a PR is properly linted and formatted prior to creating a Pull Request, [install `pre-commit`](https://pre-commit.com/#installation) in your development environment and then [set up the configuration of pre-commit hooks](https://pre-commit.com/#3-install-the-git-hook-scripts).
15 | 3. Import packages, classes, and functions with their full name where possible.
16 | * For example:
17 |
18 | :white_check_mark:
19 | ```python
20 | import spaghetti
21 | from shapely.geometry import Point
22 | ```
23 | :x:
24 | ```python
25 | import spaghetti as spgh
26 | from shapely.geometry import Point as pt
27 | ```
28 |
29 |
30 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Thank you for filing this issue! To help troubleshoot this issue, please follow
2 | the following directions to the best of your ability before submitting an issue.
3 | Feel free to delete this text once you've filled out the relevant requests.
4 |
5 | Please include the output of the following in your issue submission. If you don't know how to provide the information, commands to get the relevant information from the Python interpreter will follow each bullet point.
6 |
7 | Feel free to delete the commands after you've filled out each bullet.
8 |
9 |
10 | - Platform information:
11 | ```python
12 | >>> import os; print(os.name, os.sys.platform);print(os.uname())
13 | ```
14 | - Python version:
15 | ```python
16 | >>> import sys; print(sys.version)
17 | ```
18 | - spaghetti version:
19 | ```python
20 | >>> import spaghetti; print(spaghetti.__version__)
21 | ```
22 | - libpysal version:
23 | ```python
24 | >>> import libpysal; print(libpysal.__version__)
25 | ```
26 | - SciPy version:
27 | ```python
28 | >>> import scipy; print(scipy.__version__)
29 | ```
30 | - NumPy version:
31 | ```python
32 | >>> import numpy; print(numpy.__version__)
33 | ```
34 | - GeoPandas verion (if applicable):
35 | ```python
36 | >>> import geopandas; print(geopandas.__version__)
37 | ```
38 |
39 | Also, please upload any relevant data as [a file
40 | attachment](https://help.github.com/articles/file-attachments-on-issues-and-pull-requests/). Please **do not** upload pickled objects, since it's nearly impossible to troubleshoot them without replicating your exact namespace. Instead, provide the minimal subset of the data required to replicate the problem. If it makes you more comfortable submitting the issue, feel free to:
41 |
42 | 1. remove personally identifying information from data or code
43 | 2. provide only the required subset of the full data or code
44 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: jGaboardi
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior
15 |
16 | **Expected behavior**
17 | A clear and concise description of what you expected to happen.
18 |
19 | **Screenshots**
20 | If applicable, add screenshots to help explain your problem.
21 |
22 | **Additional context**
23 | Add any other context about the problem here.
24 |
25 | **System & Versions**
26 | - Platform information:
27 | ```python
28 | >>> import os; print(os.name, os.sys.platform);print(os.uname())
29 | ```
30 | - Python version:
31 | ```python
32 | >>> import sys; print(sys.version)
33 | ```
34 | - spaghetti version:
35 | ```python
36 | >>> import spaghetti; print(spaghetti.__version__)
37 | ```
38 | - libpysal version:
39 | ```python
40 | >>> import libpysal; print(libpysal.__version__)
41 | ```
42 | - SciPy version:
43 | ```python
44 | >>> import scipy; print(scipy.__version__)
45 | ```
46 | - NumPy version:
47 | ```python
48 | >>> import numpy; print(numpy.__version__)
49 | ```
50 | - GeoPandas verion (if applicable):
51 | ```python
52 | >>> import geopandas; print(geopandas.__version__)
53 | ```
54 |
55 | Also, please upload any relevant data as [a file
56 | attachment](https://help.github.com/articles/file-attachments-on-issues-and-pull-requests/). Please **do not** upload pickled objects, since it's nearly impossible to troubleshoot them without replicating your exact namespace. Instead, provide the minimal subset of the data required to replicate the problem. If it makes you more comfortable submitting the issue, feel free to:
57 |
58 | 1. remove personally identifying information from data or code
59 | 2. provide only the required subset of the full data or code
60 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: jGaboardi
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Hello! Please make sure to check all these boxes before submitting a Pull Request
2 | (PR). Once you have checked the boxes, feel free to remove all text except the
3 | justification in point 4.
4 |
5 | 1. [ ] You have run tests on this submission, either by using [Travis Continuous Integration testing](https://github.com/pysal/pysal/wiki/GitHub-Standard-Operating-Procedures#automated-testing-w-travis-ci) testing or running `nosetests` on your changes?
6 | 2. [ ] This pull introduces new functionality covered by
7 | [docstrings](https://en.wikipedia.org/wiki/Docstring#Python) and
8 | [unittests](https://docs.python.org/3.6/library/unittest.html)?
9 | 3. [ ] You have [assigned a
10 | reviewer](https://help.github.com/articles/assigning-issues-and-pull-requests-to-other-github-users/) and added relevant [labels](https://help.github.com/articles/applying-labels-to-issues-and-pull-requests/)
11 | 4. [ ] The justification for this PR is:
12 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "github-actions"
9 | directory: "/"
10 | schedule:
11 | interval: "daily"
12 | reviewers:
13 | - "jGaboardi"
14 |
15 | - package-ecosystem: "pip"
16 | directory: "/"
17 | schedule:
18 | interval: "daily"
19 | reviewers:
20 | - "jGaboardi"
21 |
--------------------------------------------------------------------------------
/.github/release.yml:
--------------------------------------------------------------------------------
1 | changelog:
2 | exclude:
3 | labels:
4 | - ignore-for-release
5 | authors:
6 | - octocat
7 | - dependabot
8 | categories:
9 | - title: Breaking Changes 🛠
10 | labels:
11 | - Semver-Major
12 | - breaking-change
13 | - title: Exciting New Features 🎉
14 | labels:
15 | - Semver-Minor
16 | - enhancement
17 | - title: Other Changes
18 | labels:
19 | - "*"
20 |
--------------------------------------------------------------------------------
/.github/workflows/build_docs.yml:
--------------------------------------------------------------------------------
1 | name: Build Docs
2 |
3 | on:
4 | push:
5 | # Sequence of patterns matched against refs/tags
6 | tags:
7 | - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
8 | workflow_dispatch:
9 | inputs:
10 | version:
11 | description: Manual Doc Build
12 | default: test
13 | required: false
14 | jobs:
15 | docs:
16 | name: build & push docs
17 | runs-on: ${{ matrix.os }}
18 | timeout-minutes: 90
19 | strategy:
20 | matrix:
21 | os: ['ubuntu-latest']
22 | environment-file: [ci/312-latest.yaml]
23 | experimental: [false]
24 | defaults:
25 | run:
26 | shell: bash -l {0}
27 |
28 | steps:
29 | - name: checkout repo
30 | uses: actions/checkout@v4
31 | with:
32 | fetch-depth: 0 # Fetch all history for all branches and tags.
33 |
34 | - name: setup micromamba
35 | uses: mamba-org/setup-micromamba@v2
36 | with:
37 | environment-file: ${{ matrix.environment-file }}
38 | micromamba-version: 'latest'
39 |
40 | - name: reinstall for version
41 | run: |
42 | pip install -e . --no-deps --force-reinstall
43 |
44 | - name: make docs
45 | run: |
46 | cd docs
47 | make html
48 |
49 | - name: commit docs
50 | run: |
51 | git clone https://github.com/ammaraskar/sphinx-action-test.git --branch gh-pages --single-branch gh-pages
52 | cp -r docs/_build/html/* gh-pages/
53 | cd gh-pages
54 | git config --local user.email "action@github.com"
55 | git config --local user.name "GitHub Action"
56 | git add .
57 | git commit -m "Update documentation" -a || true
58 | # The above command will fail if no changes were present,
59 | # so we ignore the return code.
60 |
61 | - name: push to gh-pages
62 | uses: ad-m/github-push-action@master
63 | with:
64 | branch: gh-pages
65 | directory: gh-pages
66 | github_token: ${{ secrets.GITHUB_TOKEN }}
67 | force: true
68 |
--------------------------------------------------------------------------------
/.github/workflows/release_and_publish.yml:
--------------------------------------------------------------------------------
1 | # Release package on GitHub and publish to PyPI
2 | # IMPORTANT -- 1 MANUAL STEP
3 | # * FOLLOWING TAGGED RELEASE
4 | # - update CHANGELOG.md
5 | #--------------------------------------------------
6 | name: Release & Publish
7 |
8 | on:
9 | push:
10 | # Sequence of patterns matched against refs/tags
11 | tags:
12 | - "v*" # Push events to matching v*, i.e. v1.0, v20.15.10
13 | workflow_dispatch:
14 | inputs:
15 | version:
16 | description: Manual Release
17 | default: test
18 | required: false
19 |
20 |
21 | jobs:
22 | build:
23 | name: Create release & publish to PyPI
24 | runs-on: ubuntu-latest
25 | steps:
26 | - name: Checkout repo
27 | uses: actions/checkout@v4
28 | with:
29 | fetch-depth: 0 # Fetch all history for all branches and tags.
30 |
31 | - name: Set up python
32 | uses: actions/setup-python@v5
33 | with:
34 | python-version: "3.x"
35 |
36 | - name: Install Dependencies
37 | run: |
38 | python -m pip install --upgrade pip
39 | python -m pip install --upgrade build twine
40 | python -m build
41 | twine check --strict dist/*
42 |
43 | - name: Create Release Notes
44 | uses: actions/github-script@v7
45 | with:
46 | github-token: ${{secrets.GITHUB_TOKEN}}
47 | script: |
48 | await github.request(`POST /repos/${{ github.repository }}/releases`, {
49 | tag_name: "${{ github.ref }}",
50 | generate_release_notes: true
51 | });
52 |
53 | - name: Publish distribution 📦 to PyPI
54 | uses: pypa/gh-action-pypi-publish@release/v1
55 | with:
56 | user: __token__
57 | password: ${{ secrets.PYPI_PASSWORD }}
58 |
--------------------------------------------------------------------------------
/.github/workflows/testing.yml:
--------------------------------------------------------------------------------
1 | name: Continuous Integration
2 |
3 | on:
4 | push:
5 | branches:
6 | - '*'
7 | pull_request:
8 | branches:
9 | - '*'
10 | schedule:
11 | - cron: '59 23 * * *'
12 | workflow_dispatch:
13 | inputs:
14 | version:
15 | description: Manual Unittest Run
16 | default: test
17 | required: false
18 |
19 | jobs:
20 | testing:
21 | name: ${{ matrix.os }}, ${{ matrix.environment-file }}
22 | runs-on: ${{ matrix.os }}
23 | timeout-minutes: 30
24 | strategy:
25 | matrix:
26 | os: [ubuntu-latest]
27 | environment-file:
28 | - ci/310-oldest.yaml
29 | - ci/310-latest.yaml
30 | - ci/311-latest.yaml
31 | - ci/312-latest.yaml
32 | - ci/312-dev.yaml
33 | include:
34 | - environment-file: ci/312-latest.yaml
35 | os: macos-13 # Intel
36 | - environment-file: ci/312-latest.yaml
37 | os: macos-14 # Apple Silicon
38 | - environment-file: ci/312-latest.yaml
39 | os: windows-latest
40 | fail-fast: false
41 |
42 | defaults:
43 | run:
44 | shell: bash -l {0}
45 |
46 | steps:
47 | - name: checkout repo
48 | uses: actions/checkout@v4
49 | with:
50 | fetch-depth: 0 # Fetch all history for all branches and tags.
51 |
52 | - name: setup micromamba
53 | uses: mamba-org/setup-micromamba@v2
54 | with:
55 | environment-file: ${{ matrix.environment-file }}
56 | micromamba-version: 'latest'
57 |
58 | - name: environment info
59 | run: |
60 | micromamba info
61 | micromamba list
62 |
63 | - name: spatial versions
64 | run: 'python -c "import geopandas; geopandas.show_versions();"'
65 |
66 | - name: run tests
67 | run: |
68 | pytest \
69 | spaghetti \
70 | -v \
71 | -r a \
72 | -n auto \
73 | --color yes \
74 | --cov spaghetti \
75 | --cov-append \
76 | --cov-report term-missing \
77 | --cov-report xml \
78 | --timeout 60
79 |
80 | - name: run docstring tests
81 | if: contains(matrix.environment-file, 'latest') || contains(matrix.environment-file, 'dev')
82 | run: |
83 | pytest \
84 | -v \
85 | -r a \
86 | -n auto \
87 | --color yes \
88 | --doctest-only spaghetti
89 |
90 | - name: codecov
91 | uses: codecov/codecov-action@v5
92 | with:
93 | token: ${{ secrets.CODECOV_TOKEN }}
94 | file: ./coverage.xml
95 | name: spaghetti-codecov
96 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | *.pyc
3 | .rope*
4 | .idea/
5 | *.ipynb
6 | notebooks/.ipynb_checkpoints/
7 | .ipynb_checkpoints/
8 | .DS_Store
9 |
10 | *.egg
11 | *.egg-info
12 | dist
13 | build
14 | eggs
15 | parts
16 | bin
17 | var
18 | sdist
19 | develop-eggs
20 | .installed.cfg
21 | lib
22 | lib64
23 | __pycache__
24 |
25 | .log
26 |
27 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | files: "spaghetti\/"
2 | repos:
3 | - repo: https://github.com/astral-sh/ruff-pre-commit
4 | rev: "v0.8.6"
5 | hooks:
6 | - id: ruff
7 | - id: ruff-format
8 |
9 | ci:
10 | autofix_prs: false
11 | autoupdate_schedule: quarterly
12 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | # Changes
3 |
4 | ## Version 1.5.0 (2020-05-04)
5 |
6 | We closed a total of 9 issues (enhancements and bug fixes) through 3 pull requests, since our last release on 2020-05-03.
7 |
8 | ## Highlights
9 | * New logo!
10 | * Minimum/maximum spanning trees
11 | * Refactored *K* Function
12 | * More notebooks and tutorials
13 | * Further improved and refactored testing
14 |
15 | ## Issues Closed
16 | - GHA for release and publish (#487)
17 | - Attempting GHA release workflow #2 (#489)
18 | - Attempting GHA release workflow (#488)
19 | - Version bump for release v1.5.0.rc0 (#486)
20 | - [WIP] Update Network K Function (#469)
21 | - Break spatial analysis tutorial into several notebooks (#478)
22 |
23 | ## Pull Requests
24 | - Attempting GHA release workflow #2 (#489)
25 | - Attempting GHA release workflow (#488)
26 | - Version bump for release v1.5.0.rc0 (#486)
27 |
28 | The following individuals contributed to this release:
29 |
30 | - James Gaboardi
31 |
32 | ------------------------------------
33 |
34 | ## Version 1.5.0.rc0 (2020-05-02)
35 |
36 | We closed a total of 100 issues (enhancements and bug fixes) through 38 pull requests, since our last release on 2020-02-24.
37 |
38 | ## Issues Closed
39 | - [WIP] Update Network K Function (#469)
40 | - Break spatial analysis tutorial into several notebooks (#478)
41 | - Update, review, and rename K statistic (#477)
42 | - toy PR to test codecov.yml (#485)
43 | - toy PR to test tcodecov.yml (#484)
44 | - treebeard CI (#481)
45 | - Docs funding (#483)
46 | - [WIP] Dropping "change" param in codecov.yml (#479)
47 | - Add funding source? (#480)
48 | - add funding sources to README (#482)
49 | - [BUG] Correction to NetworkK formulation (#470)
50 | - Revert "[Bug] Addressing bug in K-Function formation" (#476)
51 | - [Bug] Addressing bug in K-Function formation (#471)
52 | - [TST] add codecov.yml (#472)
53 | - no post until 24 codecov reports (#475)
54 | - attempting custom codecov reports (#474)
55 | - update install docs (#473)
56 | - Network L Function (#467)
57 | - Remove G and F functions (#466)
58 | - Removing G and F functions (#468)
59 | - [TEST] regular 3x3 lattice for network analysis testing (#442)
60 | - DOC: correct comments for K-function related code (#465)
61 | - Updating docs with new sphinx release (#464)
62 | - Remedy for non-transparent favicon (#463)
63 | - stylize the minimum spanning tree plot in README.md (#462)
64 | - Updating pinned requirements versions (#461)
65 | - Streamling GHA (#460)
66 | - [ENH] Functionality for spanning trees (#449)
67 | - [ENH][WIP] Min/Max Spanning Trees functionality (#459)
68 | - Update Python version support in CONTRIBUTING.md (#458)
69 | - Adding network arc spatial weights notebook (#457)
70 | - Appveyor still being triggered (#454)
71 | - Corrections for Caveat notebook (#456)
72 | - CHANGELOG.txt --> CHANGELOG.md (#455)
73 | - [TST] GitHub Actions only; Migrate away from Travis/Appveyor (#453)
74 | - Customizing/improving GitHub Actions (#452)
75 | - Trying out GitHub Actions for additional testing (#451)
76 | - [ENH] caveats notebook (#426)
77 | - [WIP][ENH] New notebook for caveats (#445)
78 | - release v1.4.3 (#404)
79 | - logo update, rearrange (#448)
80 | - updating README logo (#447)
81 | - package import warning? (#427)
82 | - Improved docstrings for NetworkF and NetworkG (#444)
83 | - analysis.ffunction() may not be correct (#225)
84 | - [MAINT] re-evaluate testing structure (#438)
85 | - [TST] Updating tests and testing structure (#443)
86 | - moving watermark to notebook reqs (#441)
87 | - appveyor — rebuild the master 3.8 PYPI (#436)
88 | - [MAINT] DRYing off unittests (#439)
89 | - Docs for v1.4.2.post1 were not rebuilt (#434)
90 | - rebuilding docs for post release (#435)
91 | - release v1.4.2 (#392)
92 | - pushing changelog for 1.4.2post1 (#433)
93 | - version bump v1.4.2 --> 1.4.2post1 (#432)
94 | - fixing conda-forge failure (#431)
95 | - final PR before v1.4.2 release — updating CHANGELOG.md (#430)
96 | - updating README (#429)
97 | - [WIP][ENH] longest and largest network components (#424)
98 | - Add a fully connected attribute (#425)
99 | - [ENH] longest/largest connected component (#414)
100 | - add logos to website (#345)
101 |
102 | ## Pull Requests
103 | - Update, review, and rename K statistic (#477)
104 | - toy PR to test codecov.yml (#485)
105 | - Docs funding (#483)
106 | - [WIP] Dropping "change" param in codecov.yml (#479)
107 | - add funding sources to README (#482)
108 | - [Bug] Addressing bug in K-Function formation (#471)
109 | - no post until 24 codecov reports (#475)
110 | - attempting custom codecov reports (#474)
111 | - update install docs (#473)
112 | - Removing G and F functions (#468)
113 | - DOC: correct comments for K-function related code (#465)
114 | - Updating docs with new sphinx release (#464)
115 | - Remedy for non-transparent favicon (#463)
116 | - stylize the minimum spanning tree plot in README.md (#462)
117 | - Updating pinned requirements versions (#461)
118 | - Streamling GHA (#460)
119 | - [ENH][WIP] Min/Max Spanning Trees functionality (#459)
120 | - Update Python version support in CONTRIBUTING.md (#458)
121 | - Adding network arc spatial weights notebook (#457)
122 | - Corrections for Caveat notebook (#456)
123 | - CHANGELOG.txt --> CHANGELOG.md (#455)
124 | - [TST] GitHub Actions only; Migrate away from Travis/Appveyor (#453)
125 | - Customizing/improving GitHub Actions (#452)
126 | - Trying out GitHub Actions for additional testing (#451)
127 | - [WIP][ENH] New notebook for caveats (#445)
128 | - logo update, rearrange (#448)
129 | - updating README logo (#447)
130 | - Improved docstrings for NetworkF and NetworkG (#444)
131 | - [TST] Updating tests and testing structure (#443)
132 | - moving watermark to notebook reqs (#441)
133 | - [MAINT] DRYing off unittests (#439)
134 | - rebuilding docs for post release (#435)
135 | - pushing changelog for 1.4.2post1 (#433)
136 | - version bump v1.4.2 --> 1.4.2post1 (#432)
137 | - fixing conda-forge failure (#431)
138 | - final PR before v1.4.2 release — updating CHANGELOG.md (#430)
139 | - updating README (#429)
140 | - [WIP][ENH] longest and largest network components (#424)
141 |
142 | The following individuals contributed to this release:
143 |
144 | - James Gaboardi
145 | - Serge Rey
146 |
147 | ------------------------------------
148 |
149 |
150 | ## Version 1.4.2.post2 (2020-02-24)
151 |
152 | We closed a total of 1 issues (enhancements and bug fixes) through 1 pull requests, since our last release on 2020-02-24.
153 |
154 | ## Issues Closed
155 | - rebuilding docs for post release (#435)
156 |
157 | ## Pull Requests
158 | - Docs for v1.4.2.post1 were not rebuilt (#434)
159 |
160 | The following individuals contributed to this release:
161 |
162 | - James Gaboardi
163 |
164 | ------------------------------------
165 |
166 |
167 | ## Version 1.4.2post1 (2020-02-24)
168 |
169 | We closed a total of 0 issues (enhancements and bug fixes) through 2 pull requests, since our last release on 2020-02-24.
170 |
171 | ## Pull Requests
172 | - version bump v1.4.2 --> 1.4.2post1 (#432)
173 | - fixing conda-forge failure (#431)
174 |
175 | The following individuals contributed to this release:
176 |
177 | - James Gaboardi
178 |
179 | ------------------------------------
180 |
181 |
182 | ## Version 1.4.2 (2020-02-24)
183 |
184 | We closed a total of 57 issues (enhancements and bug fixes) through 18 pull requests, since our last release on 2020-01-25.
185 |
186 | ## Highlights
187 | * Python 3.8 support and Windows OS testing
188 | * Increased robustness of `regular_lattices()`, which now can create a lattice from any bounds, including bounding box of a shapefile or GeoDataFrame
189 | * Point type A to point type B shortest path extraction
190 | * Longest and largest network component identification
191 | * Network component extraction
192 | * New "Integrations and Applications" notebook
193 | * General cleanup, including bug and typo fixes
194 |
195 |
196 | ## Issues Closed
197 | - updating README (#429)
198 | - [WIP][ENH] longest and largest network components (#424)
199 | - Add a fully connected attribute (#425)
200 | - [ENH] longest/largest connected component (#414)
201 | - add logos to website (#345)
202 | - attempting fast finish again (#428)
203 | - pushing fix for environment.yml (#423)
204 | - Add 3.8 as a supported Python version in docs (#422)
205 | - [ENH] matplotlib-scalebar for notebooks/binders (#416)
206 | - using a true scalebar in notebook plots (#421)
207 | - [REQ] requirements for notebooks/binders? (#413)
208 | - adding notebook reqs files (#420)
209 | - support multiplatform testing (#407)
210 | - make sure data set is downloaded for appveyor.yml (#419)
211 | - Migrate testing functionality from nose to pytest (#417)
212 | - [ENH] moving towards multi-platform testing (#418)
213 | - [On Hold] too many emails from Travis CI (#322)
214 | - origin-destination point patterns for shortest_paths() (#412)
215 | - The Transportation Problem notebook (#103)
216 | - transportation problem ipynb and type-a to type-b shortest paths (#415)
217 | - [WIP][ENH] origin for lattice (#405)
218 | - add testing for Python 3.8 (#408)
219 | - [BUG] typo in Travis CI badge URL (#410)
220 | - silently hands RuntimeWarning in NetworkK (#411)
221 | - adding py3.8 to travis (#409)
222 | - [DOC] notebook doc pngs (#406)
223 | - release v1.4.1 (#365)
224 | - rebuilding docs for version bump (#402)
225 | - Version bump to v1.4.1 (#401)
226 | - Binder is broken for network-analysis (#399)
227 | - Some tutorial links giving 404 (#400)
228 | - Fix links 2 (#398)
229 | - Fix links for notebooks (#397)
230 | - [DOC] Reorg for tutorials page (#396)
231 | - Traveling Salesperson Notebook (#110)
232 | - create new TSP notebook with pulp (#100)
233 | - [WIP] TSP notebook (#386)
234 | - [DOC] paths docstring missing (#394)
235 | - correcting routes doc (#395)
236 |
237 | ## Pull Requests
238 | - final PR before v1.4.2 release — updating CHANGELOG.md (#430)
239 | - updating README (#429)
240 | - [WIP][ENH] longest and largest network components (#424)
241 | - pushing fix for environment.yml (#423)
242 | - Add 3.8 as a supported Python version in docs (#422)
243 | - using a true scalebar in notebook plots (#421)
244 | - adding notebook reqs files (#420)
245 | - make sure data set is downloaded for appveyor.yml (#419)
246 | - [ENH] moving towards multi-platform testing (#418)
247 | - transportation problem ipynb and type-a to type-b shortest paths (#415)
248 | - [WIP][ENH] origin for lattice (#405)
249 | - adding py3.8 to travis (#409)
250 | - [DOC] notebook doc pngs (#406)
251 | - rebuilding docs for version bump (#402)
252 | - Version bump to v1.4.1 (#401)
253 | - Fix links 2 (#398)
254 | - Fix links for notebooks (#397)
255 | - [WIP] TSP notebook (#386)
256 | - correcting routes doc (#395)
257 |
258 | The following individuals contributed to this release:
259 |
260 | - James Gaboardi
261 | - Serge Rey
262 |
263 |
264 |
265 | ---------------------------------------------
266 |
267 | ## Version 1.4.1 (2020-01-25)
268 |
269 | We closed a total of 93 issues (enhancements and bug fixes) through 35 pull requests, since our last release on 2019-12-31.
270 |
271 | ## Issues Closed
272 | - Binder is broken for network-analysis (#399)
273 | - Some tutorial links giving 404 (#400)
274 | - Fix links 2 (#398)
275 | - Fix links for notebooks (#397)
276 | - [DOC] Reorg for tutorials page (#396)
277 | - Traveling Salesperson Notebook (#110)
278 | - create new TSP notebook with pulp (#100)
279 | - [WIP] TSP notebook (#386)
280 | - [DOC] paths docstring missing (#394)
281 | - correcting routes doc (#395)
282 | - [ENH] add back `build` badge (#393)
283 | - [BUG] Stale links on pysal.org/spaghetti (#387)
284 | - Rebuild docs (#391)
285 | - force read-add conn-comp notebook (#390)
286 | - repushing missing notebooks (#389)
287 | - Stale links (#388)
288 | - [ENH] shortest-path extraction (#380)
289 | - [ENH] regular lattice generator (#385)
290 | - [WIP][ENH] addressing shortest path extract (#382)
291 | - mention the pysal/notebook project (#384)
292 | - point pattern --> network error message (#383)
293 | - [ENH] connected components demo notebook (#381)
294 | - updating README.md (#379)
295 | - data type testing (#378)
296 | - spaghetti should handle native cg.Point/Chain objects (#217)
297 | - Native geometries (#377)
298 | - adding CoC link to README.md (#376)
299 | - update CHANGELOG.md format (#375)
300 | - all reqs found in requirements*.txt necessary? (#346)
301 | - [ENH] explore overlapping "nearest point" calculation — DRY (#320)
302 | - altering reference format in docs (#372)
303 | - Clear instructions for black/pre-commit for contributing (#369)
304 | - Contrib precommit (#371)
305 | - alldistances vs. distancematrix? (#351)
306 | - distance matrix and tree storage (#370)
307 | - update readme (#367)
308 | - Adding citations for facility location notebook (#366)
309 | - v1.4 release checklist (#340)
310 | - updating README.md (#364)
311 | - add pre-commit black for PRs? (#333)
312 | - trying out the black pre-commit hook (#363)
313 | - adding descartes to environment.yml (#362)
314 | - Attempt binder3 (#361)
315 | - need readthedocs.yml? (#360)
316 | - need all tarball tests? (#359)
317 | - Attempt binder2 (#358)
318 | - using environment.yml for binder (#357)
319 | - Add blob/master/ to notebooks link (#354)
320 | - addressing #354 (#356)
321 | - Citation review (#355)
322 | - launch binder (#78)
323 | - version 1.3.1 --> 1.4 bump (#353)
324 | - updating version and docs (#352)
325 | - improve spaghetti homepage and notebooks? (#332)
326 | - Review docs for links, etc. (#338)
327 | - Spelling and default value of `n_processes` (#341)
328 | - [WIP] TSP notebook (#330)
329 | - [ENH][WIP]extension of #339: Rahul799 docs/bugfix (#342)
330 |
331 | ## Pull Requests
332 | - Fix links 2 (#398)
333 | - Fix links for notebooks (#397)
334 | - [WIP] TSP notebook (#386)
335 | - correcting routes doc (#395)
336 | - [ENH] add back `build` badge (#393)
337 | - Rebuild docs (#391)
338 | - force read-add conn-comp notebook (#390)
339 | - repushing missing notebooks (#389)
340 | - Stale links (#388)
341 | - [WIP][ENH] addressing shortest path extract (#382)
342 | - mention the pysal/notebook project (#384)
343 | - point pattern --> network error message (#383)
344 | - [ENH] connected components demo notebook (#381)
345 | - updating README.md (#379)
346 | - data type testing (#378)
347 | - Native geometries (#377)
348 | - adding CoC link to README.md (#376)
349 | - update CHANGELOG.md format (#375)
350 | - altering reference format in docs (#372)
351 | - Contrib precommit (#371)
352 | - distance matrix and tree storage (#370)
353 | - update readme (#367)
354 | - Adding citations for facility location notebook (#366)
355 | - updating README.md (#364)
356 | - trying out the black pre-commit hook (#363)
357 | - adding descartes to environment.yml (#362)
358 | - Attempt binder3 (#361)
359 | - Attempt binder2 (#358)
360 | - using environment.yml for binder (#357)
361 | - addressing #354 (#356)
362 | - Citation review (#355)
363 | - version 1.3.1 --> 1.4 bump (#353)
364 | - updating version and docs (#352)
365 | - [WIP] TSP notebook (#330)
366 | - [ENH][WIP]extension of #339: Rahul799 docs/bugfix (#342)
367 |
368 | The following individuals contributed to this release:
369 |
370 | - James Gaboardi
371 |
372 |
373 |
374 | -----------------------------------------------------
375 |
376 |
377 | ## Version 1.4.0 (2019-12-31)
378 |
379 | We closed a total of 84 issues (enhancements and bug fixes) through 31 pull requests, since our last release on 2019-07-29.
380 |
381 | ### Issues Closed
382 | - updating version and docs (#352)
383 | - improve spaghetti homepage and notebooks? (#332)
384 | - Review docs for links, etc. (#338)
385 | - Spelling and default value of `n_processes` (#341)
386 | - [WIP] TSP notebook (#330)
387 | - [ENH][WIP]extension of #339: Rahul799 docs/bugfix (#342)
388 | - Revert "order analysis.py classes/functions alphabetically" (#350)
389 | - order analysis.py classes/functions alphabetically (#349)
390 | - updating requirement_dev.txt (#347)
391 | - update README.md (#348)
392 | - tarball jobs failing on Travis (#343)
393 | - updating README.md (#344)
394 | - links in the docs,reviewed (#339)
395 | - automatically generate docstrings for class members (#336)
396 | - Update docs (#337)
397 | - Updating .travis.yml (#335)
398 | - fix indentation in `.travis.yml` (#334)
399 | - update README.md badges (#331)
400 | - Citation stipulation for notebooks (#327)
401 | - Notebooks update part 2 (#329)
402 | - Notebooks update (#328)
403 | - update email address in notebooks (#324)
404 | - Plotting error in Facility_Location.ipynb (#325)
405 | - Updating Notebooks (#326)
406 | - module 'pysal.explore.spaghetti' has no attribute 'element_as_gdf' (#323)
407 | - [ENH] util.compute_length() — DRY (#318)
408 | - swapping out distance calculation function (#319)
409 | - adjusting snapping image in README.md (#317)
410 | - inaccurate documentation — Network.split_arcs() (#315)
411 | - Split arcs update (#316)
412 | - streamline badges in README.md (#313)
413 | - streaming badges on README.md (#314)
414 | - adding +travis to notification recipients (#312)
415 | - broken "development guidelines" link (#309)
416 | - updating broken dev link (#311)
417 | - Update Travis CI schema (#299)
418 | - Update travis CI for new testing schema (#308)
419 | - adding static docs badge (#310)
420 | - mock c modules for doc dependencies (#288)
421 | - doi missing from citation (#306)
422 | - adding Zenodo DOI to README.md and website (#307)
423 | - blackify setup.py (#305)
424 | - Change Read the Docs to GitHub? (#301)
425 | - updating README to reflect GitHub docs (#304)
426 | - switching to github docs as per #301 (#303)
427 | - get_versions() function (#302)
428 | - code formatting with black (#293)
429 | - blackifying code (#293) (#300)
430 | - rtree missing libspatialindex_c library file (#294)
431 | - updating install instructions (addressing #294) (#296)
432 | - updating install instructions + version bump (#298)
433 | - updating font for "Warning" (#297)
434 | - update of install instructions in README.md (#295)
435 |
436 | ### Pull Requests
437 | - updating version and docs (#352)
438 | - [WIP] TSP notebook (#330)
439 | - [ENH][WIP]extension of #339: Rahul799 docs/bugfix (#342)
440 | - Revert "order analysis.py classes/functions alphabetically" (#350)
441 | - order analysis.py classes/functions alphabetically (#349)
442 | - updating requirement_dev.txt (#347)
443 | - update README.md (#348)
444 | - updating README.md (#344)
445 | - Update docs (#337)
446 | - Updating .travis.yml (#335)
447 | - fix indentation in `.travis.yml` (#334)
448 | - update README.md badges (#331)
449 | - Notebooks update part 2 (#329)
450 | - Notebooks update (#328)
451 | - Updating Notebooks (#326)
452 | - swapping out distance calculation function (#319)
453 | - adjusting snapping image in README.md (#317)
454 | - Split arcs update (#316)
455 | - streaming badges on README.md (#314)
456 | - adding +travis to notification recipients (#312)
457 | - updating broken dev link (#311)
458 | - Update travis CI for new testing schema (#308)
459 | - adding static docs badge (#310)
460 | - adding Zenodo DOI to README.md and website (#307)
461 | - blackify setup.py (#305)
462 | - updating README to reflect GitHub docs (#304)
463 | - switching to github docs as per #301 (#303)
464 | - blackifying code (#293) (#300)
465 | - updating install instructions + version bump (#298)
466 | - updating font for "Warning" (#297)
467 | - update of install instructions in README.md (#295)
468 |
469 | The following individuals contributed to this release:
470 |
471 | - James Gaboardi
472 | - Rahul799
473 |
474 |
475 |
476 | -----------------------------------------------------
477 |
478 |
479 | ## Version 1.3.1 (2019-07-29)
480 |
481 | We closed a total of 21 issues (enhancements and bug fixes) through 7 pull requests, since our last release on 2019-05-21.
482 |
483 | ### Issues Closed
484 | - updating font for "Warning" (#297)
485 | - update of install instructions in README.md (#295)
486 | - remove geopandas version stipulation (#291)
487 | - updating citation langauge (#290)
488 | - build error beginning (07/01/2019) (#289)
489 | - update css (#287)
490 | - update readthedocs.yml? (#284)
491 | - spaghetti api docs rendering incorrectly (#285)
492 | - docs table left aligned (#286)
493 | - remove extra line in .travis.yml (#283)
494 | - update Changelog (#282)
495 | - Manually updated CHANGELOG following stable release. (#281)
496 | - v1.3 release (#264)
497 | - Bump version 1.3rc2 --> 1.3 (#280)
498 |
499 | ### Pull Requests
500 | - updating font for "Warning" (#297)
501 | - update of install instructions in README.md (#295)
502 | - updating citation langauge (#290)
503 | - docs table left aligned (#286)
504 | - remove extra line in .travis.yml (#283)
505 | - update Changelog (#282)
506 | - Bump version 1.3rc2 --> 1.3 (#280)
507 |
508 | The following individuals contributed to this release:
509 |
510 | - James Gaboardi
511 | - Wei Kang
512 |
513 | -----------------------------------------------------
514 |
515 |
516 | ## Version 1.3 (2019-05-21)
517 |
518 | We closed a total of 14 issues (enhancements and bug fixes) through 5 pull requests, since our last release on 2019-05-14.
519 |
520 | ### Issues Closed
521 | - Manually updated CHANGELOG following stable release (#281)
522 | - v1.3 release (#264)
523 | - add `requirements_dev.txt` to `MANIFEST.in` (#277)
524 | - Update changelog (#279)
525 | - version bump to include req_dev in MANIFEST.in (#278)
526 | - v1.2 --> 1.3rc1 (for release candidate) (#276)
527 | - Updating notebooks prior to v1.3 release (#275)
528 | - updating README (#274)
529 | - update notebooks following prior to v1.3 release (#158)
530 |
531 | ### Pull Requests
532 | - Update changelog (#279)
533 | - version bump to include req_dev in MANIFEST.in (#278)
534 | - v1.2 --> 1.3rc1 (for release candidate) (#276)
535 | - Updating notebooks prior to v1.3 release (#275)
536 | - updating README (#274)
537 |
538 | The following individuals contributed to this release:
539 |
540 | - James Gaboardi
541 |
542 |
543 | -----------------------------------------------------
544 |
545 |
546 | ## Version 1.3rc2 (2019-05-14)
547 |
548 | We closed a total of 9 issues (enhancements and bug fixes) through 4 pull requests, since our last release on 2019-05-14.
549 |
550 | ### Issues Closed
551 | - version bump to include req_dev in MANIFEST.in (#278)
552 | - v1.2 --> 1.3rc1 (for release candidate) (#276)
553 | - Updating notebooks prior to v1.3 release (#275)
554 | - updating README (#274)
555 | - update notebooks following prior to v1.3 release (#158)
556 |
557 | ### Pull Requests
558 | - version bump to include req_dev in MANIFEST.in (#278)
559 | - v1.2 --> 1.3rc1 (for release candidate) (#276)
560 | - Updating notebooks prior to v1.3 release (#275)
561 | - updating README (#274)
562 |
563 | The following individuals contributed to this release:
564 |
565 | - James Gaboardi
566 |
567 |
568 | -----------------------------------------------------
569 |
570 |
571 | ## Version 1.3rc1 (2019-05-14)
572 |
573 | We closed a total of 54 issues (enhancements and bug fixes) through 18 pull requests, since our last release on 2019-02-27.
574 |
575 | ### Issues Closed
576 | - Updating notebooks prior to v1.3 release (#275)
577 | - updating README (#274)
578 | - update notebooks following prior to v1.3 release (#158)
579 | - TypeError: '>' not supported between instances of '_NodeCursor' and '_NodeCursor' (#196)
580 | - Update docsite (#273)
581 | - fix docs building (#272)
582 | - docs failing with rtree (#268)
583 | - 3.5 --> 3.7 readthedocs (#269)
584 | - updating README.md (#271)
585 | - conda-forge recipe (#265)
586 | - Solo owner/maintainer (#270)
587 | - update requirements in README (#266)
588 | - updating requirements in README (#267)
589 | - Switch snapping to Rtree package? (#259)
590 | - update python versions in setup.py (#262)
591 | - updating supported python versions in setup.py (#263)
592 | - Drop 3.5, Add 3.7 testing (#260)
593 | - adding support for python3.7 (#261)
594 | - Update Facility_Location.ipynb (#257)
595 | - Further failures in TravisCI builds. (`rake`) (#256)
596 | - bumping down geopandas requirement to 0.3.0 (#255)
597 | - bumping geopandas req version to 0.4.1 (#254)
598 | - TravisCI build failing with `geopandas` (#253)
599 | - Streamline setup travis (#252)
600 | - Remove redundancies in `requirements_xxx.txt` files (#250)
601 | - Removing redundant requirements (#251)
602 | - pandas.core error leading to Travis CI failure (#240)
603 | - uniform .travis.yml (#248)
604 | - switching from pip to conda for reqs install resolves .travis error (#249)
605 | - v1.2.rc1? (#246)
606 | - updating GitHub version badge (#247)
607 | - update version badges (#245)
608 | - AttributeError: module 'spaghetti' has no attribute 'element_as_gdf' (#242)
609 | - bump from rc to stable (#244)
610 | - v1.2rc1 bump (#243)
611 | - adding pandas as a requirement (#241)
612 |
613 | ### Pull Requests
614 | - Updating notebooks prior to v1.3 release (#275)
615 | - updating README (#274)
616 | - Update docsite (#273)
617 | - fix docs building (#272)
618 | - 3.5 --> 3.7 readthedocs (#269)
619 | - updating README.md (#271)
620 | - updating requirements in README (#267)
621 | - Switch snapping to Rtree package? (#259)
622 | - updating supported python versions in setup.py (#263)
623 | - adding support for python3.7 (#261)
624 | - Update Facility_Location.ipynb (#257)
625 | - bumping down geopandas requirement to 0.3.0 (#255)
626 | - bumping geopandas req version to 0.4.1 (#254)
627 | - Streamline setup travis (#252)
628 | - switching from pip to conda for reqs install resolves .travis error (#249)
629 | - updating GitHub version badge (#247)
630 | - bump from rc to stable (#244)
631 | - v1.2rc1 bump (#243)
632 |
633 | The following individuals contributed to this release:
634 |
635 | - James Gaboardi
636 | - Wei Kang
637 | - Levi John Wolf
638 | - @Tomgertin
639 |
640 |
641 | -----------------------------------------------------
642 |
643 |
644 | ## Version 1.2 (2019-02)
645 |
646 | This is a stable release of v1.2rc1 with no changes to code.
647 |
648 |
649 |
650 | -----------------------------------------------------
651 |
652 | ## Version 1.2rc1 (2019-02-27)
653 |
654 | We closed a total of 160 issues (enhancements and bug fixes) through 60 pull requests, since our last release on 2018-11-01.
655 |
656 | ### Issues Closed
657 | - Coverage testing (#239)
658 | - update .travis.yml and introduce .coveragerc similar to pysal/giddy#81 (#238)
659 | - Update `bug` template (#237)
660 | - Update issue templates (#236)
661 | - Add .github directory based on libpysal (#234)
662 | - Adding community info (#235)
663 | - remove README.rst (#223)
664 | - Removing README.rst and updating setup.py (#233)
665 | - pysal/giddy#77 (reference labels) (#231)
666 | - Ref docs (#232)
667 | - Api site doc (#230)
668 | - correction in notebooks/Network_Usage.ipynb (#229)
669 | - edges_to_arcs naming convention (#227)
670 | - altering edges_to_arcs crosswalk name (#228)
671 | - Improve in-line docs -- 24PullRequests for Christmas (#202)
672 | - updating utils.py docs (#226)
673 | - updating all analysis.py docs (#224)
674 | - Docs split arcs (#222)
675 | - Docs allneighbordistances (#221)
676 | - updating docs for full_distance_matrix (#220)
677 | - notes for simulate_observations (#219)
678 | - Docs net funcs (#218)
679 | - bug in snapping points? (#125)
680 | - Deprecation: Container-Based Linux Build Environments (#188)
681 | - Remove sorted edges (#216)
682 | - purpose of class SortedEdges(OrderedDict)? (#90)
683 | - geometry notes in _newpoint_coords (#215)
684 | - count_per_link -- updating docs (#214)
685 | - TravisCI error raise ReadTimeoutError(self._pool, None, 'Read timed out.') (#213)
686 | - variable declaration correction in _snap_to_link (#212)
687 | - compute_distance_to_vertices -- in-line doc improvement (#211)
688 | - improved in-line comments in network.Network.distancebandweights (#210)
689 | - improved in-line comments in network.Network.contiguityweights (#209)
690 | - improved in-line comments in network.Network._docs_evaluate_napts (#208)
691 | - improved in-line comments in network.Network._yield_napts (#207)
692 | - improved in-line comments in network.Network.extractgraph (#206)
693 | - improved in-line comments in network.Network.extract_components (#205)
694 | - improved in-line comments in network.Network._round_sig (#204)
695 | - improved in-line comments in network.Network.__init__ (#203)
696 | - improved in-line comments in _extractnetwork (#201)
697 | - minor spaghetti/util.py doc clean (#200)
698 | - update notebooks following #185 (#187)
699 | - README graphic legend update (#197)
700 | - Update notebooks (#199)
701 | - correcting arc -- arcs attribute (#193)
702 | - attribute declaration error (network.Network.arc) (#192)
703 | - (from pysal.network) Edge ID data structure #933 (#176)
704 | - (from pysal.network) network ring bug #655 (#184)
705 | - Debug of data structure/algo that led to ring/graph errors (#185)
706 | - Creating Network instance from road shapefile fails; ValueError: list.remove(x): x not in list (#9)
707 | - (from pysal.network) Revisit graph weights in network module #496 (#186)
708 | - Updating spaghetti ReadTheDocs (#183)
709 | - tree not recorded in same network arc (#180)
710 | - Nearest tree update (#182)
711 | - clean/create more coherent and uniform variable names (#49)
712 | - Updating/standardizing network/graph element naming (#181)
713 | - Dijkstra maintenance (#179)
714 | - [MAINT] dijkstra (#178)
715 | - Adding .png of snapped point to README.md (#177)
716 | - fixing bug in distancebandweights (#175)
717 | - bug in network.Network.distancebandweights (#174)
718 | - determine necessity of test_distance_band_weights (#62)
719 | - updating ReadTheDocs following #172 (#173)
720 | - Pep8 docs review (#172)
721 | - record connected components (#168)
722 | - [WIP] contiguityweights and connected_components (#171)
723 | - add break condition in contiguityweights() (#170)
724 | - Edge Weighting pysal/pysal #609 (#66)
725 | - Merge unittest scripts (#169)
726 | - Further streamline unittests (#157)
727 | - api docs (#162)
728 | - network element as geodataframe (#143)
729 | - Refactor element as gdf (#167)
730 | - Restructure docs (#166)
731 | - Non responsive docs (#165)
732 | - typo in dijkstra reference (#163)
733 | - Update api docs (#164)
734 | - Update api (#161)
735 | - cleaning up notebooks/Snapping_Demonstration.ipynb (#160)
736 | - Update notebooks (#159)
737 | - add minor test for _round_sig (#152)
738 | - Round sig test (#156)
739 | - updating element_as_gdf.rst (#155)
740 | - Update doc element to gdf (#154)
741 | - Streamline unittests (#147)
742 | - Streamline unittests (#153)
743 | - ENH: element_to_gdf() (#145)
744 | - correcting list comp syntax in _round_sig (#151)
745 | - error in _round_sig() when a coordinate is 0.0 (#150)
746 | - [ENH] streets/network and points need to be in the same CRS/EPSG (#71)
747 | - update markdown docs fromSpaghetti_Pointpatterns_Empirical.ipynb (#146)
748 | - updating typo in notebooks/Spaghetti_Pointpatterns_Empirical.ipynb (#149)
749 | - Minor notebook update (#148)
750 | - update spaghetti info on pysal.site (#144)
751 | - fix RuntimeWarning in analysis.py (#140)
752 | - usage of networkx (#141)
753 | - updating notebooks (#142)
754 | - update spaghetti landing site notebook links (#139)
755 | - rerunning notebooks (#138)
756 | - travis build still failing (#127)
757 |
758 | ### Pull Requests
759 | - Coverage testing (#239)
760 | - Update `bug` template (#237)
761 | - Update issue templates (#236)
762 | - Adding community info (#235)
763 | - Removing README.rst and updating setup.py (#233)
764 | - Ref docs (#232)
765 | - Api site doc (#230)
766 | - correction in notebooks/Network_Usage.ipynb (#229)
767 | - altering edges_to_arcs crosswalk name (#228)
768 | - updating utils.py docs (#226)
769 | - updating all analysis.py docs (#224)
770 | - Docs split arcs (#222)
771 | - Docs allneighbordistances (#221)
772 | - updating docs for full_distance_matrix (#220)
773 | - notes for simulate_observations (#219)
774 | - Docs net funcs (#218)
775 | - Remove sorted edges (#216)
776 | - geometry notes in _newpoint_coords (#215)
777 | - count_per_link -- updating docs (#214)
778 | - variable declaration correction in _snap_to_link (#212)
779 | - compute_distance_to_vertices -- in-line doc improvement (#211)
780 | - improved in-line comments in network.Network.distancebandweights (#210)
781 | - improved in-line comments in network.Network.contiguityweights (#209)
782 | - improved in-line comments in network.Network._docs_evaluate_napts (#208)
783 | - improved in-line comments in network.Network._yield_napts (#207)
784 | - improved in-line comments in network.Network.extractgraph (#206)
785 | - improved in-line comments in network.Network.extract_components (#205)
786 | - improved in-line comments in network.Network._round_sig (#204)
787 | - improved in-line comments in network.Network.__init__ (#203)
788 | - improved in-line comments in _extractnetwork (#201)
789 | - minor spaghetti/util.py doc clean (#200)
790 | - Update notebooks (#199)
791 | - correcting arc -- arcs attribute (#193)
792 | - Debug of data structure/algo that led to ring/graph errors (#185)
793 | - Updating spaghetti ReadTheDocs (#183)
794 | - Nearest tree update (#182)
795 | - Updating/standardizing network/graph element naming (#181)
796 | - Dijkstra maintenance (#179)
797 | - Adding .png of snapped point to README.md (#177)
798 | - fixing bug in distancebandweights (#175)
799 | - updating ReadTheDocs following #172 (#173)
800 | - Pep8 docs review (#172)
801 | - [WIP] contiguityweights and connected_components (#171)
802 | - Merge unittest scripts (#169)
803 | - Refactor element as gdf (#167)
804 | - Restructure docs (#166)
805 | - Non responsive docs (#165)
806 | - Update api docs (#164)
807 | - Update api (#161)
808 | - cleaning up notebooks/Snapping_Demonstration.ipynb (#160)
809 | - Update notebooks (#159)
810 | - Round sig test (#156)
811 | - updating element_as_gdf.rst (#155)
812 | - Update doc element to gdf (#154)
813 | - Streamline unittests (#153)
814 | - ENH: element_to_gdf() (#145)
815 | - correcting list comp syntax in _round_sig (#151)
816 | - updating typo in notebooks/Spaghetti_Pointpatterns_Empirical.ipynb (#149)
817 | - updating notebooks (#142)
818 | - rerunning notebooks (#138)
819 |
820 | The following individuals contributed to this release:
821 |
822 | - James Gaboardi
823 |
824 | -----------------------------------------------------
825 |
826 |
827 | ## Version 1.1.1 (2018-10-31)
828 |
829 | We closed a total of 5 issues (enhancements and bug fixes) through 2 pull requests, since our last release on 2018-10-30.
830 |
831 | ### Issues Closed
832 | - removed .txt format CHANGELOG (#129)
833 | - rel: v1.1.0 -- Adjusting CHANGELOG.md prior to tagged release (#128)
834 | - prepare new release for pypi -- v1.1.0 (#57)
835 |
836 | ### Pull Requests
837 | - removed .txt format CHANGELOG (#129)
838 | - rel: v1.1.0 -- Adjusting CHANGELOG.md prior to tagged release (#128)
839 |
840 | The following individuals contributed to this release:
841 |
842 | - James Gaboardi
843 |
844 | -----------------------------------------------------
845 |
846 |
847 | ## Version 1.1.0 (2018-10-30)
848 |
849 | We closed a total of 82 issues (enhancements and bug fixes) through 25 pull requests, since our last release on 2018-08-10.
850 |
851 | ### Issues Closed
852 | - prepare new release for pypi -- v1.1.0 (#57)
853 | - refreshing documentation (#124)
854 | - option to add distance from point to snapped location (#75)
855 | - attempting pyproj_fix (#122)
856 | - [WIP] Add snap dist (#123)
857 | - travis CI build failing with `KeyError: 'PROJ_LIB'` (#121)
858 | - resolving obs_to_node question (#120)
859 | - why convert obs_to_node from defaultdict to list? (#93)
860 | - network.PointPatterns condense code chunk (#74)
861 | - condensing idvariable code chunk (#119)
862 | - Network Cross Nearest Neighbor (#102)
863 | - refreshing docs (#117)
864 | - shortest path look up from allneighborsdistances? (#115)
865 | - adding shortest path traceback for point patterns (#116)
866 | - ImportError: No module named 'boto3' (#113)
867 | - adding boto3 test req for current fiona bug (#114)
868 | - [WIP] cleanup_nearest_neighbor (#112)
869 | - duplicate neighbor distance functions? (#91)
870 | - network.allneighbordistances documentation not accurate (#111)
871 | - [WIP] General package maintenance (#109)
872 | - new badges (#96)
873 | - tools/ (#99)
874 | - updating thumbnails in docs (#108)
875 | - [WIP] updating docs, badges, tools, etc. (#107)
876 | - initializing new sphinx docs based on submodule_template (#98)
877 | - new labels for issues (#105)
878 | - populating sphinx docs (#37)
879 | - tests for analysis and util (#44)
880 | - NetworkF (#94)
881 | - rename functions to be more pythonic (#104)
882 | - add poisson distribution to tests (#106)
883 | - initial sphix docs attempt (#67)
884 | - bumping version to 1.1.0 (#97)
885 | - adding in new tests for utils.py (#95)
886 | - add flag for util.generatetree() (#92)
887 | - [completed atm] - docstrings cleanup (#89)
888 | - clean docstrings (#77)
889 | - adding MANIFEST.in (#88)
890 | - clearing Facility_Location.ipynb (#87)
891 | - removing typo in Facility_Location (#86)
892 | - clearing Facility_Location.ipynb (#85)
893 | - updating Facility_Location.ipynb for typos (#84)
894 | - adding Facility_Location.ipynb (#83)
895 | - new notebook ideas (#48)
896 | - adding windows functionality for 'last updated' (#82)
897 | - ensure nearest nodes are returned as np.array() (#73)
898 | - snapping trouble when the initial node in KDtree is the nearest (#72)
899 | - add Github version badge (#80)
900 | - add open issues badge (#79)
901 | - update notebooks as per pysal/pysal#1057 (#81)
902 | - [Complete/Needs Review] updating `in_shp` parameter in spaghetti.Network (#69)
903 | - [ENH] geopandas.GeoDataFrame for PointPattern (#28)
904 | - update in_shp kwarg in spaghetti.Network (#68)
905 | - removing undeclared edge_time attribute (#65)
906 | - update README.txt (#33)
907 | - [ENH] Add badges (#31)
908 | - Publish on Zenodo (#36)
909 |
910 | ### Pull Requests
911 | - refreshing documentation (#124)
912 | - attempting pyproj_fix (#122)
913 | - [WIP] Add snap dist (#123)
914 | - resolving obs_to_node question (#120)
915 | - condensing idvariable code chunk (#119)
916 | - refreshing docs (#117)
917 | - adding shortest path traceback for point patterns (#116)
918 | - [WIP] cleanup_nearest_neighbor (#112)
919 | - [WIP] General package maintenance (#109)
920 | - updating thumbnails in docs (#108)
921 | - [WIP] updating docs, badges, tools, etc. (#107)
922 | - initializing new sphinx docs based on submodule_template (#98)
923 | - bumping version to 1.1.0 (#97)
924 | - adding in new tests for utils.py (#95)
925 | - [completed atm] - docstrings cleanup (#89)
926 | - adding MANIFEST.in (#88)
927 | - clearing Facility_Location.ipynb (#87)
928 | - removing typo in Facility_Location (#86)
929 | - clearing Facility_Location.ipynb (#85)
930 | - updating Facility_Location.ipynb for typos (#84)
931 | - adding Facility_Location.ipynb (#83)
932 | - adding windows functionality for 'last updated' (#82)
933 | - ensure nearest nodes are returned as np.array() (#73)
934 | - [Complete/Needs Review] updating `in_shp` parameter in spaghetti.Network (#69)
935 | - removing undeclared edge_time attribute (#65)
936 |
937 | The following individuals contributed to this release:
938 |
939 | - James Gaboardi
940 |
941 |
942 | --------------------------------------------------------------
943 |
944 |
945 | ## GitHub Stats for 2017/03/15 - 2018/07/28 (tag: None)
946 |
947 | These lists are automatically generated,and may be incomplete or contain duplicates.
948 |
949 |
950 | We closed a total of 39 issues, 12 pull requests and 27 regular issues;
951 | this is the full list (generated with the script
952 | :file:`tools/github_stats.py`):
953 |
954 | ### Pull Requests (12):
955 |
956 | * `#25`: preparing for pypi release
957 | * `#23`: Py2topy3
958 | * `#24`: Spaghetti/update travis
959 | * `#16`: adding an api.py file to spaghetti
960 | * `#17`: Spag/analysis cosmetics
961 | * `#14`: removing `math` in favor of `numpy` for calcs
962 | * `#13`: minor doc commit to practice git workflow
963 | * `#11`: adding a license
964 | * `#10`: setting up travis ci
965 | * `#8`: the first of the new network tutorial notebooks for pysal/spaghetti
966 | * `#7`: rename makes geonet redundant
967 | * `#6`: updated package name and short description in __init__
968 |
969 | ### Issues (27):
970 |
971 | * `#5`: update import scheme for new package name
972 | * `#26`: Prepare a release of spaghetti for pypi
973 | * `#32`: pip
974 | * `#25`: preparing for pypi release
975 | * `#19`: api.py tests
976 | * `#29`: trailing comma not allowed with surrounding parenthesis
977 | * `#27`: Necessity of __future__?
978 | * `#21`: `spaghetti` currently only python 2.7.x compatible
979 | * `#22`: Geopandas read
980 | * `#23`: Py2topy3
981 | * `#24`: Spaghetti/update travis
982 | * `#20`: Generalize the Network input API for libpysal/#59
983 | * `#18`: adding gitter badge to README.md
984 | * `#15`: spaghetti needs an api.py module
985 | * `#17`: Spag/analysis cosmetics
986 | * `#16`: adding an api.py file to spaghetti
987 | * `#4`: test release and setup.py
988 | * `#3`: add a readme
989 | * `#14`: removing `math` in favor of `numpy` for calcs
990 | * `#13`: minor doc commit to practice git workflow
991 | * `#12`: Pp notebook
992 | * `#11`: adding a license
993 | * `#2`: set up testing for travis
994 | * `#10`: setting up travis ci
995 | * `#8`: the first of the new network tutorial notebooks for pysal/spaghetti
996 | * `#7`: rename makes geonet redundant
997 | * `#6`: updated package name and short description in __init__
998 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright 2017 PySAL-spaghetti Developers
2 |
3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4 |
5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6 |
7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8 |
9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10 |
11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | # [pysal/spaghetti](http://pysal.org/spaghetti/)
7 |
8 | # *SPA*tial *G*rap*H*s: n*ET*works, *T*opology, & *I*nference
9 |
10 | Spaghetti is an open-source Python library for the analysis of network-based spatial data. Originating from the `network` module in [PySAL (Python Spatial Analysis Library)](http://pysal.org), it is under active development for the inclusion of newly proposed methods for building graph-theoretic networks and the analysis of network events.
11 |
12 | *An example of a network's [minimum spanning tree](https://pysal.org/spaghetti/generated/spaghetti.spanning_tree.html#spaghetti.spanning_tree):*
13 |
14 |
15 |
16 | |[](https://badge.fury.io/py/spaghetti)| [](https://anaconda.org/conda-forge/spaghetti) |  | [](https://mybinder.org/v2/gh/pysal/spaghetti/main)
17 | |:---:|:---:|:---:|:---:|
18 | |[](https://pepy.tech/project/spaghetti) | [](https://anaconda.org/conda-forge/spaghetti) | [](http://pysal.org/spaghetti/) | [](https://discord.gg/BxFTEPFFZn)
19 | |  | [](https://github.com/conda-forge/spaghetti-feedstock) | [](https://codecov.io/gh/pysal/spaghetti) | [](https://github.com/astral-sh/ruff)
20 | | [](https://github.com/pysal/spaghetti/actions/workflows/testing.yml) | [](https://joss.theoj.org/papers/52b8d0c81bbf311465b45bfc26379e74) | [](https://zenodo.org/badge/latestdoi/88305306) | [](https://opensource.org/licenses/BSD-3-Clause)
21 |
22 | ## Examples
23 |
24 | The following are a selection of some examples that can be launched individually as interactive binders from the links on their respective pages. Additional examples can be found in the [Tutorials](https://pysal.org/spaghetti/tutorials.html) section of the documentation. See the [`pysal/notebooks`](http://pysal.org/notebooks) project for a [`jupyter-book`](https://github.com/choldgraf/jupyter-book) version of this repository.
25 | * [Quickstart](https://pysal.org/spaghetti/notebooks/quickstart.html)
26 | * [Shortest Path Visualization](https://pysal.org/spaghetti/notebooks/shortest-path-visualization.html)
27 | * [Caveats](https://pysal.org/spaghetti/notebooks/caveats.html)
28 |
29 | ## Installation
30 |
31 | Python >= [3.10](https://docs.python.org/3.10/) is tested for support by `spaghetti`. Please make sure that you are operating in a Python >= 3.10 environment.
32 |
33 | **Installing with `conda` via [`conda-forge`](https://github.com/conda-forge/spaghetti-feedstock) (highly recommended)**
34 |
35 | To install `spaghetti` and all its dependencies, we recommend using the [`conda`](https://docs.conda.io/en/latest/)
36 | manager, specifically with the [`conda-forge`](https://conda-forge.org) channel. This can be obtained by installing the [`Anaconda Distribution`](https://docs.continuum.io/anaconda/) (a free Python distribution for data science), or through [`miniconda`](https://docs.conda.io/en/latest/miniconda.html) (minimal distribution only containing Python and the conda package manager).
37 |
38 | Using `conda`, `spaghetti` can be installed as follows:
39 | ```
40 | $ conda config --set channel_priority strict
41 | $ conda install --channel conda-forge spaghetti
42 | ```
43 | Also, `geopandas` provides [a nice example](https://geopandas.readthedocs.io/en/latest/getting_started/install.html#creating-a-new-environment) to create a fresh environment for working with spatial data.
44 |
45 | **Installing with [`PyPI`](https://pypi.org/project/spaghetti/)**
46 | ```
47 | $ pip install spaghetti
48 | ```
49 | *or* download the source distribution (`.tar.gz`) and decompress it to your selected destination. Open a command shell and navigate to the decompressed folder.
50 | ```
51 | $ pip install .
52 | ```
53 |
54 | ***Warning***
55 |
56 | When installing via `pip`, you have to ensure that the required dependencies for `spaghetti` are installed on your operating system. Details on how to install these packages are linked below. Using `conda` (above) avoids having to install the dependencies separately.
57 |
58 | Install the most current development version of `spaghetti` by running:
59 |
60 | ```
61 | $ pip install git+https://github.com/pysal/spaghetti
62 | ```
63 |
64 | ## Requirements
65 |
66 | - [`esda`](https://pysal.org/esda/)
67 | - [`geopandas`](https://geopandas.org/en/stable/)
68 | - [`libpysal`](https://pysal.org/libpysal/)
69 | - [`libspatialindex`](https://libspatialindex.org/en/stable/)
70 | - [`numpy`](https://numpy.org/devdocs/)
71 | - [`rtree`](https://rtree.readthedocs.io/en/stable/)
72 | - [`scipy`](http://scipy.github.io/devdocs/)
73 | - [`shapely`](https://shapely.readthedocs.io/en/stable/)
74 |
75 | ## History
76 |
77 | `spaghetti` was
78 | created and has evolved in line with the Python Spatial Analysis Library ecosystem for
79 | the specific purpose of utilizing the functionality of spatial weights in
80 | [`libpysal`](https://pysal.org/libpysal/) for generating network segment contiguity objects.
81 | The PySAL project was started in the mid-2000s when installation was difficult to maintain.
82 | Due to the non-triviality of relying on dependencies to secondary packages, a conscious
83 | decision was made to limit dependencies and build native PySAL data structures in cases
84 | where at all possible. Therefore, the original `pysal.network` submodule was developed to
85 | address the need for integrating support for network data structures with PySAL weights
86 | data structures, with the target audience being spatial data scientists and anyone
87 | interested in investigating network-centric phenomena within PySAL. Owing to the
88 | co-development of network functionality found within `spaghetti` and the evolution of
89 | the wider PySAL ecosystem, today, the package provides specialized network functionality
90 | that easily integrates with the rest of PySAL. This allows users of `spaghetti`’s network
91 | functionality to access spatial analysis functionality that complements network analysis,
92 | such as spatial statistical tools with `esda` and integration with core components of
93 | `libpysal`: `libpysal.weights` (mentioned above),
94 | `libpysal.cg` (computational geometry and data structures),
95 | `libpysal.io` (input-output), and `libpysal.examples` (built-in example data).
96 |
97 | ## Contribute
98 |
99 | PySAL-spaghetti is under active development and contributors are welcome.
100 |
101 | If you have any suggestions, feature requests, or bug reports, please open new [issues](https://github.com/pysal/spaghetti/issues) on GitHub. To submit patches, please review [PySAL's documentation for developers](https://pysal.org/docs/devs/), the PySAL [development guidelines](https://github.com/pysal/pysal/wiki), the `spaghetti` [contributing guidelines](https://github.com/pysal/spaghetti/blob/main/.github/CONTRIBUTING.md) before opening a [pull request](https://github.com/pysal/spaghetti/pulls). Once your changes get merged, you’ll automatically be added to the [Contributors List](https://github.com/pysal/spaghetti/graphs/contributors).
102 |
103 | ## Support
104 |
105 | If you are having issues, please [create an issue](https://github.com/pysal/spaghetti/issues), start a [discussion](https://github.com/pysal/spaghetti/discussions), or talk to us in [PySAL's Discord channel](https://discord.gg/BxFTEPFFZn). All questions, comments, & discussions should happen in a public forum, where possible. Private messages and emails will not be answered in a substantive manner.
106 |
107 | ## Code of Conduct
108 |
109 | As a PySAL-federated project, `spaghetti` follows the [Code of Conduct](https://github.com/pysal/governance/blob/main/conduct/code_of_conduct.rst) under the [PySAL governance model](https://github.com/pysal/governance).
110 |
111 | ## License
112 |
113 | The project is licensed under the [BSD 3-Clause license](https://github.com/pysal/spaghetti/blob/main/LICENSE.txt).
114 |
115 | ## BibTeX Citation
116 |
117 | If you use PySAL-spaghetti in a scientific publication, we would appreciate using the following citations:
118 |
119 | ```
120 | @article{Gaboardi2021,
121 | doi = {10.21105/joss.02826},
122 | url = {https://doi.org/10.21105/joss.02826},
123 | year = {2021},
124 | publisher = {The Open Journal},
125 | volume = {6},
126 | number = {62},
127 | pages = {2826},
128 | author = {James D. Gaboardi and Sergio Rey and Stefanie Lumnitz},
129 | title = {spaghetti: spatial network analysis in PySAL},
130 | journal = {Journal of Open Source Software}
131 | }
132 |
133 | @misc{Gaboardi2018,
134 | author = {Gaboardi, James D. and Laura, Jay and Rey, Sergio and
135 | Wolf, Levi John and Folch, David C. and Kang, Wei and
136 | Stephens, Philip and Schmidt, Charles},
137 | month = {oct},
138 | year = {2018},
139 | title = {pysal/spaghetti},
140 | url = {https://github.com/pysal/spaghetti},
141 | doi = {10.5281/zenodo.1343650},
142 | keywords = {graph-theory,network-analysis,python,spatial-networks,topology}
143 | }
144 | ```
145 |
146 | ## Funding
147 | This project is/was partially funded through:
148 |
149 | [
](https://atlantardc.wordpress.com) Atlanta Research Data Center: [A Polygon-Based Approach to Spatial Network Allocation](https://atlantardc.files.wordpress.com/2018/05/ardc-newsletter_2018_2.pdf)
150 |
151 | [
](https://www.nsf.gov/index.jsp) National Science Foundation Award #1825768: [National Historical Geographic Information System](https://www.nsf.gov/awardsearch/showAward?AWD_ID=1825768&HistoricalAwards=false)
152 |
--------------------------------------------------------------------------------
/ci/310-latest.yaml:
--------------------------------------------------------------------------------
1 | name: test
2 | channels:
3 | - conda-forge
4 | dependencies:
5 | - python=3.10
6 | # required
7 | - esda
8 | - geopandas
9 | - libpysal
10 | - numpy
11 | - pandas
12 | - pip
13 | - rtree
14 | - scipy
15 | - shapely
16 | - watermark
17 | # testing
18 | - codecov
19 | - pytest
20 | - pytest-cov
21 | - pytest-doctestplus
22 | - pytest-timeout
23 | - pytest-xdist
24 |
--------------------------------------------------------------------------------
/ci/310-oldest.yaml:
--------------------------------------------------------------------------------
1 | name: test
2 | channels:
3 | - conda-forge
4 | dependencies:
5 | - python=3.10
6 | # required
7 | - esda=2.1
8 | - fiona<1.10
9 | - geopandas=0.12
10 | - libpysal=4.6
11 | - numpy=1.22
12 | - pandas=1.4
13 | - pip
14 | - rtree=1.0
15 | - scipy=1.8
16 | - shapely=2.0
17 | # testing
18 | - codecov
19 | - pytest
20 | - pytest-cov
21 | - pytest-timeout
22 | - pytest-xdist
23 |
--------------------------------------------------------------------------------
/ci/311-latest.yaml:
--------------------------------------------------------------------------------
1 | name: test
2 | channels:
3 | - conda-forge
4 | dependencies:
5 | - python=3.11
6 | # required
7 | - esda
8 | - geopandas
9 | - libpysal
10 | - numpy
11 | - pandas
12 | - pip
13 | - rtree
14 | - scipy
15 | - shapely
16 | - watermark
17 | # testing
18 | - codecov
19 | - pytest
20 | - pytest-cov
21 | - pytest-doctestplus
22 | - pytest-timeout
23 | - pytest-xdist
24 |
--------------------------------------------------------------------------------
/ci/312-dev.yaml:
--------------------------------------------------------------------------------
1 | name: test
2 | channels:
3 | - conda-forge
4 | dependencies:
5 | - python=3.12
6 | # required
7 | - geos # for shapely
8 | - matplotlib # for esda
9 | - numpy
10 | - pip
11 | - rtree
12 | - watermark
13 | # testing
14 | - codecov
15 | - pytest
16 | - pytest-cov
17 | - pytest-doctestplus
18 | - pytest-timeout
19 | - pytest-xdist
20 | - pip:
21 | # dev versions of packages
22 | - --pre --index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple --extra-index-url https://pypi.org/simple
23 | - pandas
24 | - scipy
25 | - git+https://github.com/pysal/esda.git@main
26 | - git+https://github.com/geopandas/geopandas.git@main
27 | - git+https://github.com/pysal/libpysal.git@main
28 | - git+https://github.com/shapely/shapely.git@main
29 |
--------------------------------------------------------------------------------
/ci/312-latest.yaml:
--------------------------------------------------------------------------------
1 | name: test
2 | channels:
3 | - conda-forge
4 | dependencies:
5 | - python=3.12
6 | # required
7 | - esda
8 | - geopandas
9 | - libpysal
10 | - numpy
11 | - pandas
12 | - pip
13 | - rtree
14 | - scipy
15 | - shapely
16 | - watermark
17 | # testing
18 | - codecov
19 | - pytest
20 | - pytest-cov
21 | - pytest-doctestplus
22 | - pytest-timeout
23 | - pytest-xdist
24 | # for docs build action (this env only)
25 | - nbsphinx
26 | - numpydoc
27 | - sphinx
28 | - sphinxcontrib-bibtex
29 | - sphinx_bootstrap_theme
30 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | codecov:
2 | notify:
3 | after_n_builds: 6
4 | coverage:
5 | range: 50..95
6 | round: nearest
7 | precision: 1
8 | status:
9 | project:
10 | default:
11 | threshold: 2%
12 | patch:
13 | default:
14 | threshold: 2%
15 | target: 80%
16 | ignore:
17 | - "tests/*"
18 | comment:
19 | layout: "reach, diff, files"
20 | behavior: once
21 | after_n_builds: 6
22 | require_changes: true
23 |
--------------------------------------------------------------------------------
/docs/.buildinfo:
--------------------------------------------------------------------------------
1 | # Sphinx build info version 1
2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
3 | config: 23a3f8d9c1559fbe5ac06f8019bbbead
4 | tags: 645f666f9bcd5a90fca523b33c5a78b7
5 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SPHINXPROJ = spaghetti
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @rsync -r --exclude '.ipynb_checkpoints/' ../notebooks/ ./notebooks/
21 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
22 |
23 | github:
24 | @make html
25 |
26 | sync:
27 | @rsync -avh _build/html/ ../docs/ --delete
28 | @make clean
29 | touch .nojekyll
30 |
31 | clean:
32 | rm -rf $(BUILDDIR)/*
33 | rm -rf auto_examples/
34 | rm -rf generated/
35 |
--------------------------------------------------------------------------------
/docs/_static/images/ardc_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spaghetti/72ae8892a9ae62d0d18aecc310709b0e00d5f090/docs/_static/images/ardc_logo.png
--------------------------------------------------------------------------------
/docs/_static/images/crime_counts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spaghetti/72ae8892a9ae62d0d18aecc310709b0e00d5f090/docs/_static/images/crime_counts.png
--------------------------------------------------------------------------------
/docs/_static/images/facility_location.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spaghetti/72ae8892a9ae62d0d18aecc310709b0e00d5f090/docs/_static/images/facility_location.png
--------------------------------------------------------------------------------
/docs/_static/images/mst_logo_pasta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spaghetti/72ae8892a9ae62d0d18aecc310709b0e00d5f090/docs/_static/images/mst_logo_pasta.png
--------------------------------------------------------------------------------
/docs/_static/images/net_rep.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spaghetti/72ae8892a9ae62d0d18aecc310709b0e00d5f090/docs/_static/images/net_rep.png
--------------------------------------------------------------------------------
/docs/_static/images/network_k.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spaghetti/72ae8892a9ae62d0d18aecc310709b0e00d5f090/docs/_static/images/network_k.png
--------------------------------------------------------------------------------
/docs/_static/images/nsf_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spaghetti/72ae8892a9ae62d0d18aecc310709b0e00d5f090/docs/_static/images/nsf_logo.png
--------------------------------------------------------------------------------
/docs/_static/images/pysal_favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spaghetti/72ae8892a9ae62d0d18aecc310709b0e00d5f090/docs/_static/images/pysal_favicon.ico
--------------------------------------------------------------------------------
/docs/_static/images/pysal_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spaghetti/72ae8892a9ae62d0d18aecc310709b0e00d5f090/docs/_static/images/pysal_logo.png
--------------------------------------------------------------------------------
/docs/_static/pysal-styles.css:
--------------------------------------------------------------------------------
1 | /* Make thumbnails with equal heights */
2 | @media only screen and (min-width : 500px) {
3 | .row.equal-height {
4 | display: flex;
5 | flex-wrap: wrap;
6 | }
7 | .row.equal-height > [class*='col-'] {
8 | display: flex;
9 | flex-direction: row, column;
10 | }
11 | .row.equal-height.row:after,
12 | .row.equal-height.row:before {
13 | display: flex;
14 | }
15 |
16 | .row.equal-height > [class*='col-'] > .thumbnail,
17 | .row.equal-height > [class*='col-'] > .thumbnail > .caption {
18 | display: flex;
19 | flex: .9 .1 auto;
20 | flex-direction: column;
21 | }
22 | .row.equal-height > [class*='col-'] > .thumbnail > .caption > .flex-text {
23 | flex-grow: 1;
24 | }
25 | .row.equal-height > [class*='col-'] > .thumbnail > img {
26 | width: 400px;
27 | height: 100%; /* force image's height */
28 |
29 | /* force image fit inside it's "box" */
30 | -webkit-object-fit: cover;
31 | -moz-object-fit: cover;
32 | -ms-object-fit: cover;
33 | -o-object-fit: cover;
34 | object-fit: cover;
35 | }
36 | }
37 |
38 | .row.extra-bottom-padding{
39 | margin-bottom: 20px;
40 | }
41 |
42 |
43 | .topnavicons {
44 | margin-left: 10% !important;
45 | }
46 |
47 | .topnavicons li {
48 | margin-left: 0px !important;
49 | min-width: 100px;
50 | text-align: center;
51 | }
52 |
53 | .topnavicons .thumbnail {
54 | margin-right: 10px;
55 | border: none;
56 | box-shadow: none;
57 | text-align: center;
58 | font-size: 85%;
59 | font-weight: bold;
60 | line-height: 10px;
61 | height: 100px;
62 | }
63 |
64 | .topnavicons .thumbnail img {
65 | display: block;
66 | margin-left: auto;
67 | margin-right: auto;
68 | }
69 |
70 |
71 | /* Table with a scrollbar */
72 | .bodycontainer { max-height: 800px; width: 100%; margin: 0; padding: 0; overflow-y: auto; }
73 | .table-scrollable { margin: 0; padding: 0; }
74 |
75 | .label {
76 | color: #E74C3C;
77 | font-size: 100%;
78 | font-weight: bold;
79 | width: 100%;
80 | height: 100%;
81 | text-align: left;
82 | vertical-align: middle;
83 | padding: 6px;
84 | margin: 2px;
85 | overflow-x: auto;
86 | overflow-y: auto;
87 | }
88 |
89 | div.body {
90 | max-width: 1080px;
91 | }
92 |
93 | table.longtable.align-default{
94 | text-align: left;
95 | }
96 |
--------------------------------------------------------------------------------
/docs/_static/pysal_favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spaghetti/72ae8892a9ae62d0d18aecc310709b0e00d5f090/docs/_static/pysal_favicon.ico
--------------------------------------------------------------------------------
/docs/_static/references.bib:
--------------------------------------------------------------------------------
1 | %% Saved with string encoding Unicode (UTF-8)
2 |
3 | @article{Dijkstra1959a,
4 | abstract = {We consider a graph with n vertices, all pairs of which are connected by an edge; each edge is of given positive length. The following two basic problems are solved. Problem 1: construct the tree of minimal total length between the n vertices. (A tree is a graph with one and only one path between any two vertices.) Problem 2: find the path of minimal total length between two given vertices.},
5 | author = {Dijkstra, E. W.},
6 | doi = {10.1007/BF01386390},
7 | isbn = {0029-599X (Print) 0945-3245 (Online)},
8 | issn = {0029-599X},
9 | journal = {Numerische Mathematik},
10 | number = {1},
11 | pages = {269--271},
12 | pmid = {18215627},
13 | title = {{A Note on Two Problems in Connexion with Graphs}},
14 | volume = {1},
15 | year = {1959}
16 | }
17 |
18 | @article{Baddeley2020,
19 | author = {Baddeley, Adrian and Nair, Gopalan and Rakshit, Suman and McSwiggan, Greg and Davies, Tilman M.},
20 | doi = {10.1016/j.spasta.2020.100435},
21 | journal = {Spatial Statistics},
22 | keywords = {Distance metric,K-function,Kernel density estimation,Nonparametric estimation,Pair correlation function,Stationary process},
23 | number = {xxxx},
24 | pages = {100435},
25 | publisher = {Elsevier B.V.},
26 | title = {{Analysing point patterns on networks - A review}},
27 | year = {2020}
28 | }
29 |
30 | @article{doi:10.1111/j.1538-4632.2001.tb00448.x,
31 | author = {Okabe, Atsuyuki and Yamada, Ikuho},
32 | title = {{The K-Function Method on a Network and Its Computational Implementation}},
33 | journal = {Geographical Analysis},
34 | volume = {33},
35 | number = {3},
36 | pages = {271-290},
37 | doi = {10.1111/j.1538-4632.2001.tb00448.x},
38 | abstract = {This paper proposes two statistical methods, called the network K-function method and the network cross K-function method, for analyzing the distribution of points on a network. First, by extending the ordinary K-function method defined on a homogeneous infinite plane with the Euclidean distance, the paper formulates the K-function method and the cross K-function method on a finite irregular network with the shortest-path distance. Second, the paper shows advantages of the network K-function methods, such as that the network K-function methods can deal with spatial point processes on a street network in a small district, and that they can exactly take the boundary effect into account. Third, the paper develops the computational implementation of the network K-functions, and shows that the computational order of the K-function method is O(n2Q log nQ) and that of the network cross K-function is O(nQ log U3Q), where nQ is the number of nodes of a network.},
39 | year = {2001}
40 | }
41 |
42 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Chapter 3
43 | @inbook{doi:10.1002/9781119967101.ch3,
44 | author = {Okabe, Atsuyki and Sugihara, Kokichi},
45 | publisher = {John Wiley \& Sons, Ltd},
46 | isbn = {9781119967101},
47 | title = {Basic Computational Methods for Network Spatial Analysis},
48 | booktitle = {Spatial Analysis along Networks},
49 | chapter = {3},
50 | pages = {45-80},
51 | doi = {10.1002/9781119967101.ch3},
52 | year = {2012},
53 | keywords = {basic computational methods in network spatial analysis, practical computational methods, data structures for one-layer networks, winged-edge data, retrieving local information, attribute data representation, winged-edge, new nodes inserted and existing nodes deleted, nonplanar network data structure, multiple-layered networks, basic geometric computations, time complexity of algorithm, and measuring efficiency, three basic computational methods, and minimum spanning tree},
54 | abstract = {Summary This chapter contains sections titled: Data structures for one-layer networks Data structures for nonplanar networks Basic geometric computations Basic computational methods on networks}
55 | }
56 |
57 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Chapter 5
58 | @inbook{doi:10.1002/9781119967101.ch5,
59 | author = {Okabe, Atsuyki and Sugihara, Kokichi},
60 | publisher = {John Wiley \& Sons, Ltd},
61 | isbn = {9781119967101},
62 | title = {Network Nearest-Neighbor Distance Methods},
63 | booktitle = {Spatial Analysis along Networks},
64 | chapter = {5},
65 | pages = {101-118},
66 | doi = {10.1002/9781119967101.ch5},
67 | year = {2012},
68 | keywords = {network nearest-neighbor distance methods, neighborhood, an underlying concept common to spatial methods, network-constrained NND, neighborhood and shortest-path distance, event to next nearest event, network NND method, NND extension on plane or planar NND, network auto NND and network cross NND method, network cross NND methods, straightforward extension, local cross NND to global cross NND, network NND for lines, computational methods, for auto NND and cross NND},
69 | abstract = {Summary This chapter contains sections titled: Network auto nearest-neighbor distance methods Network cross nearest-neighbor distance methods Network nearest-neighbor distance method for lines Computational methods for the network nearest-neighbor distance methods}
70 | }
71 |
72 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Chapter 6
73 | @inbook{doi:10.1002/9781119967101.ch6,
74 | author = {Okabe, Atsuyki and Sugihara, Kokichi},
75 | publisher = {John Wiley \& Sons, Ltd},
76 | isbn = {9781119967101},
77 | title = {Network K Function Methods},
78 | booktitle = {Spatial Analysis along Networks},
79 | chapter = {6},
80 | pages = {119-136},
81 | doi = {10.1002/9781119967101.ch6},
82 | year = {2012},
83 | keywords = {network K function methods, distance-based methods, point pattern analysis in spatial, NND and network K function, network K function, extension of K as planar K function, K function in spatial statistics, or Ripley's K function, the planar K function, most used in spatial analysis, network K function, network auto K and the network cross K function, auto K function with one type of point, and cross K with two, global Voronoi cross K, point of type A to collection of type B points, shortest-path distance and network geometric characteristics, shortest-path distances and corresponding Euclidean distances},
84 | abstract = {Summary This chapter contains sections titled: Network auto K function methods Network cross K function methods Network K function methods in relation to geometric characteristics of a network Computational methods for the network K function methods}
85 | }
86 |
87 | @inbook{doi:10.1002/9780470549094.ch5,
88 | author = {ÓSullivan, D. and Unwin, D. J.},
89 | publisher = {John Wiley \& Sons, Ltd},
90 | isbn = {9780470549094},
91 | title = {Point Pattern Analysis},
92 | booktitle = {Geographic Information Analysis},
93 | chapter = {5},
94 | pages = {121-156},
95 | doi = {10.1002/9780470549094.ch5},
96 | year = {2010},
97 | keywords = {point separation, standard deviation, observed VMR, estimation methods, computationally intensive},
98 | abstract = {Summary This chapter contains sections titled: Introduction Describing a Point Pattern Assessing Point Patterns Statistically Monte Carlo Testing Conclusions}
99 | }
100 |
101 | @article{Ripley1976,
102 | author = {Ripley, Brian David},
103 | doi = {10.2307/3212829},
104 | journal = {Journal of Applied Probability},
105 | number = {2},
106 | pages = {255--266},
107 | title = {{The Second-Order Analysis of Stationary Point Processes}},
108 | volume = {13},
109 | year = {1976}
110 | }
111 |
112 | @article{Ripley1977,
113 | author = {Ripley, Brian David},
114 | journal = {Journal of the Royal Statistical Society},
115 | number = {2},
116 | pages = {172--212},
117 | title = {{Modelling Spatial Patterns}},
118 | volume = {39},
119 | year = {1977},
120 | doi = {10.1111/j.2517-6161.1977.tb01615.x}
121 | }
122 |
123 | @Article{pysal2007,
124 | author={Rey, Sergio J. and Anselin, Luc},
125 | title={{PySAL: A Python Library of Spatial Analytical Methods}},
126 | journal={The Review of Regional Studies},
127 | year=2007,
128 | volume={37},
129 | number={1},
130 | pages={5-27},
131 | keywords={Open Source; Software; Spatial},
132 | url = {https://rrs.scholasticahq.com/article/8285.pdf}
133 | }
134 |
135 | @book{AnselinRey2014,
136 | address = {Chicago},
137 | author = {Anselin, Luc and Rey, Sergio J.},
138 | publisher = {{GeoDa Press}},
139 | title = {{Modern Spatial Econometrics in Practice: A Guide to {GeoDa}, {GeoDaSpace} and {PySAL}}},
140 | year = {2014}
141 | }
142 |
143 | @Article{rey_open_2015,
144 | Title = {Open {Geospatial} {Analytics} with {PySAL}},
145 | Author = {Rey, Sergio J. and Anselin, Luc and Li, Xun and Pahle, Robert and Laura, Jason and Li, Wenwen and Koschinsky, Julia},
146 | Journal = {{ISPRS International Journal of Geo-Information}},
147 | Year = {2015},
148 | Number = {2},
149 | Pages = {815--836},
150 | Volume = {4},
151 | Keywords = {open science},
152 | doi = {doi:10.3390/ijgi4020815}
153 | }
154 |
155 | @misc{esda:_2019,
156 | author={S.J. Rey and L.J. Wolf and W. Kang and P. Stephens and J. Laura and C. Schmidt and D. Arribas-Bel and S. Lumnitz and J.C. Duque and D.C. Folch and L. Anselin and N. Malizia and J.D. Gaboardi and F. Fernandes and M. Seth and mhwang4 and mlyons-tcc},
157 | title={{pysal/esda}},
158 | month=jul,
159 | year={2019},
160 | publisher={Zenodo},
161 | version={v2.1.1},
162 | doi={10.5281/zenodo.3265190}
163 | }
164 |
165 | @article{doi:10.1111/gean.12211,
166 | author = {Gaboardi, James D. and Folch, David C. and Horner, Mark W.},
167 | title = {{Connecting Points to Spatial Networks: Effects on Discrete Optimization Models}},
168 | journal = {Geographical Analysis},
169 | year = {2020},
170 | volume = {52},
171 | issue = {2},
172 | pages = {299--322},
173 | doi = {10.1111/gean.12211},
174 | abstract = {To accommodate network allocation, population polygons are frequently transformed into singular, weighted centroids which are then integrated into the network either by snapping each centroid to the nearest network segment or by generating an artificial connector that becomes part of the network. In this article, an investigation of the connection method of network allocation is undertaken with two primary foci: (1) how the density of centroid connectors effects travel cost along the network; and (2) how the algorithms utilized to determine the placement of connectors are affected by the density of connectors. We hypothesize that both issues have an effect on network travel cost and, therefore, on network-based modeling. These hypotheses are tested on three nested spatial networks in the New England region of the United States. Two fundamental facility location models, the p-median problem, and p-center problem, are solved at each spatial extent while varying the density of connectors from one to four. When generating more than one connector thought must be given to the method of connection, the angle of dispersion, the acceptable tolerance of connector length, segment crossing, and saturated connectivity. A novel and thorough framework is proposed to address these concerns.}
175 | }
176 |
177 | @incollection{Cliff1981,
178 | address = {London},
179 | author = {Cliff, A.D. and Haggett, P.},
180 | booktitle = {Quantitative Geography: A British View},
181 | chapter = {22},
182 | editor = {Wrigley, N. and Bennett, R.J.},
183 | pages = {225--234},
184 | publisher = {Routledge {\&} Kegan Paul},
185 | title = {{Graph Theory}},
186 | year = {1981}
187 | }
188 |
189 | @article{Tansel1983a,
190 | author = {Tansel, Barbaros C. and Francis, Richard L .and Lowe, Timothy J.},
191 | journal = {Management Science},
192 | number = {4},
193 | pages = {482--497},
194 | title = {{State of the Art---Location on Networks: A survey. Part I: The p-center and p-median Problems}},
195 | volume = {29},
196 | year = {1983},
197 | doi = {https://doi.org/10.1287/mnsc.29.4.482},
198 | }
199 |
200 | @book{AhujaRavindraK,
201 | publisher = {Prentice Hall},
202 | isbn = {013617549X},
203 | year = {1993},
204 | title = {{Network Flows: Theory, Algorithms, and Applications}},
205 | language = {eng},
206 | address = {Englewood Cliffs, N.J.},
207 | author = {Ahuja, Ravindra K. and Magnanti, Thomas L. and Orlin, James B.},
208 | keywords = {Network analysis (Planning); Mathematical optimization},
209 | lccn = {92026702},
210 | }
211 |
212 | @incollection{Labbe1995,
213 | author = {Labbé, Martine and Peeters, Dominique and Thisse, Jacques-Fran{\c{c}}ois},
214 | booktitle = {Network Routing},
215 | chapter = {7},
216 | doi = {10.1016/S0927-0507(05)80111-2},
217 | isbn = {9780444821416},
218 | issn = {09270507},
219 | pages = {551--624},
220 | publisher = {Elsevier},
221 | series = {Handbooks in Operations Research and Management Science},
222 | title = {{Location on Networks}},
223 | volume = {8},
224 | year = {1995}
225 | }
226 |
227 | @incollection{Kuby2009,
228 | title = {{Network Analysis}},
229 | editor = {Rob Kitchin and Nigel Thrift},
230 | booktitle = {{International Encyclopedia of Human Geography}},
231 | publisher = {Elsevier},
232 | address = {Oxford},
233 | pages = {391--398},
234 | year = {2009},
235 | isbn = {978-0-08-044910-4},
236 | doi = {https://doi.org/10.1016/B978-008044910-4.00481-8},
237 | author = {Kuby, M.J. and Roberts, T.D. and Upchurch, C.D. and S. Tierney}
238 | }
239 |
240 | @article{Barthelemy2011,
241 | author = {Barthélemy, Marc},
242 | isbn = {0370-1573},
243 | issn = {03701573},
244 | journal = {Physics Reports},
245 | number = {1--3},
246 | pages = {1--101},
247 | pmid = {24906003},
248 | publisher = {Elsevier B.V.},
249 | title = {{Spatial networks}},
250 | volume = {499},
251 | year = {2011},
252 | doi = {https://doi.org/10.1016/j.physrep.2010.11.002},
253 | }
254 |
255 | @book{Okabe2012,
256 | address = {West Sussex, UK},
257 | author = {Okabe, Atsuyki and Sugihara, Kokichi},
258 | publisher = {John Wiley {\&} Sons, Inc.},
259 | title = {{Spatial Analysis Along Networks}},
260 | year = {2012},
261 | doi = {10.1002/9781119967101}
262 | }
263 |
264 | @book{daskin2013,
265 | author = {Mark S. Daskin},
266 | publisher = {John Wiley \& Sons, Ltd},
267 | isbn = {9781118537015},
268 | title = {{Network and Discrete Location: Models, Algorithms, and Applications, Second Edition}},
269 | doi = {10.1002/9781118537015},
270 | year = {2013},
271 | keywords = {location taxonomy, analytic models, continuous models, discrete location models, network models, maximum covering model, ambulance location, landfill location},
272 | }
273 |
274 | @article{Ducruet2014,
275 | author = {Ducruet, César and Beauguitte, Laurent},
276 | doi = {10.1007/s11067-013-9222-6},
277 | issn = {15729427},
278 | journal = {Networks and Spatial Economics},
279 | number = {3--4},
280 | pages = {297--316},
281 | title = {{Spatial Science and Network Science: Review and Outcomes of a Complex Relationship}},
282 | volume = {14},
283 | year = {2014}
284 | }
285 |
286 | @article{Weber2016,
287 | author = {Weber, Joe},
288 | doi = {10.1080/00330124.2015.1106324},
289 | issn = {0033-0124},
290 | journal = {The Professional Geographer},
291 | number = {January},
292 | pages = {1--11},
293 | title = {{The Properties of Topological Network Connectivity Measures and Their Application to U.S. Urban Freeway Networks}},
294 | volume = {0124},
295 | year = {2016}
296 | }
297 |
298 | @article{Okabe2006a,
299 | author = {Okabe, Atsuyuki and Okunuki, Keiichi and Shiode, Shino},
300 | doi = {10.1111/j.0016-7363.2005.00674.x},
301 | isbn = {1538-4632},
302 | issn = {0016-7363},
303 | journal = {Geographical Analysis},
304 | pages = {57--66},
305 | title = {{SANET: A Toolbox for Spatial Analysis on a Network}},
306 | volume = {38},
307 | year = {2006}
308 | }
309 |
310 | @inproceedings{Hagberg2008,
311 | address = {Pasadena, CA USA},
312 | author = {Hagberg, A.A. and Schult, D.A. and Swart, P.J.},
313 | booktitle = {Proceedings of the 7th Python in Science Conference (SciPy 2008)},
314 | editor = {Varoquaux, G. and Vaught, T. and Millman, J.},
315 | isbn = {3333333333},
316 | issn = {1540-9295},
317 | pages = {11--15},
318 | title = {{Exploring Network Structure, Dynamics, and Function using NetworkX}},
319 | year = {2008}
320 | }
321 |
322 | @article{Foti2012,
323 | author = {Foti, Fletcher and Waddell, Paul and Luxen, Dennis},
324 | journal = {{4th Transportation Research Board Conference on Innovations in Travel Modeling (ITM)}},
325 | pages = {1--14},
326 | title = {{A Generalized Computational Framework for Accessibility: From the Pedestrian to the Metropolitan Scale}},
327 | year = {2012}
328 | }
329 |
330 | @article{Boeing2017,
331 | author = {Boeing, Geoff},
332 | doi = {10.1016/j.compenvurbsys.2017.05.004},
333 | issn = {01989715},
334 | journal = {Computers, Environment and Urban Systems},
335 | pages = {126--139},
336 | publisher = {Elsevier Ltd},
337 | title = {{OSMnx: New Methods for Acquiring, Constructing, Analyzing, and Visualizing Complex Street Networks}},
338 | volume = {65},
339 | year = {2017}
340 | }
341 |
342 | @article{Hakimi1964,
343 | author = {Hakimi, S. L.},
344 | doi = {10.1287/opre.12.3.450},
345 | isbn = {0030364X},
346 | issn = {0030-364X},
347 | journal = {Operations Research},
348 | number = {3},
349 | pages = {450--459},
350 | pmid = {8598587},
351 | title = {{Optimum Locations of Switching Centers and the Absolute Centers and Medians of a Graph}},
352 | volume = {12},
353 | year = {1964}
354 | }
355 |
356 | @article{ReVelle1970,
357 | author = {ReVelle, C. S. and Swain, R.W.},
358 | journal = {Geographical Analysis},
359 | number = {1},
360 | pages = {30--42},
361 | title = {{Central Facilities Location}},
362 | volume = {2},
363 | year = {1970}
364 | }
365 |
366 | @article{Toregas1971,
367 | author = {Toregas, Constantine and Swain, R. and ReVelle, C. S. and Bergman, L.},
368 | doi = {10.1287/opre.19.6.1363},
369 | isbn = {0030364X},
370 | issn = {0030-364X},
371 | journal = {Operations Research},
372 | number = {6},
373 | pages = {1363--1373},
374 | title = {{The Location of Emergency Service Facilities}},
375 | volume = {19},
376 | year = {1971}
377 | }
378 |
379 | @article{Toregas1972,
380 | author = {Toregas, Constantine and ReVelle, Charles S.},
381 | doi = {10.1017/CBO9781107415324.004},
382 | isbn = {9788578110796},
383 | issn = {1098-6596},
384 | journal = {Papers of the Regional Science Association},
385 | number = {1},
386 | pages = {133 -- 144},
387 | pmid = {25246403},
388 | title = {{Optimal Location Under Time or Distance Constraints}},
389 | volume = {28},
390 | year = {1972}
391 | }
392 |
393 | @article{Church1974,
394 | author = {Church, Richard L. and ReVelle, C.S.},
395 | doi = {doi.org/10.1111/j.1435-5597.1974.tb00902.x},
396 | isbn = {10568190 (ISSN)},
397 | issn = {10568190},
398 | journal = {Papers in Regional Science Association},
399 | pages = {101--118},
400 | title = {{The Maximal Covering Location Problem}},
401 | volume = {32},
402 | year = {1974}
403 | }
404 |
405 | @article{ReVelle2005,
406 | author = {ReVelle, C. S. and Eiselt, H. A.},
407 | doi = {10.1016/j.ejor.2003.11.032},
408 | isbn = {1410516709},
409 | issn = {01679295},
410 | journal = {European Journal of Operational Research},
411 | pages = {1--19},
412 | title = {{Location analysis: A synthesis and survey}},
413 | volume = {165},
414 | year = {2005}
415 | }
416 |
417 | @misc{tom_russell_2019_3379659,
418 | author = {Tom Russell and Elco Koks},
419 | title = {{tomalrussell/snkit: v1.6.0}},
420 | month = aug,
421 | year = {2019},
422 | publisher = {Zenodo},
423 | version = {v1.6.0},
424 | doi = {10.5281/zenodo.3379659}
425 | }
426 |
427 |
428 | @article{Bektas2014,
429 | author = {Bektaş, Tolga and Gouveia, Luis},
430 | doi = {10.1016/j.ejor.2013.07.038},
431 | issn = {03772217},
432 | journal = {European Journal of Operational Research},
433 | number = {3},
434 | pages = {820--832},
435 | title = {{Requiem for the Miller-Tucker-Zemlin subtour elimination constraints?}},
436 | volume = {236},
437 | year = {2014}
438 | }
439 | @article{Miller1960,
440 | author = {Miller, C. E. and Tucker, A. W. and Zemlin, R. A.},
441 | doi = {10.1145/321043.321046},
442 | issn = {1557735X},
443 | journal = {Journal of the ACM (JACM)},
444 | number = {4},
445 | pages = {326--329},
446 | title = {{Integer Programming Formulation of Traveling Salesman Problems}},
447 | volume = {7},
448 | year = {1960}
449 | }
450 |
451 | @article{Flood1956,
452 | author = {Flood, Merrill M.},
453 | journal = {Operations Research},
454 | number = {1},
455 | pages = {61--75},
456 | title = {{The Traveling-Salesman Problem}},
457 | volume = {4},
458 | year = {1956}
459 | }
460 |
461 | @article{Dantzig1954,
462 | author = {Dantzig, G. and Fulkerson, R. and Johnson, S.},
463 | journal = {Journal of the Operational Research Society of America},
464 | number = {4},
465 | pages = {393--410},
466 | title = {{Solution of a Large-Scale Traveling-Salesman Problem}},
467 | volume = {2},
468 | year = {1954}
469 | }
470 |
471 | @book{Miller2001,
472 | address = {New York},
473 | author = {Miller, Harvey J. and Shaw, Shih-Lung},
474 | publisher = {Oxford University Press},
475 | title = {{Geographic Information Systems for Transportation}},
476 | year = {2001}
477 | }
478 |
479 | @book{Gass2005,
480 | address = {New York},
481 | author = {Gass, Saul I. and Assad, Arjang A.},
482 | publisher = {Springer},
483 | title = {{An Annotated Timeline of Operations Research: An Informal History}},
484 | year = {2005}
485 | }
486 |
487 | @misc{Cummings2000,
488 | author = {Cummings, Nigel},
489 | title = {A brief History of the Travelling Salesman Problem},
490 | editor = {The Operational Research Society},
491 | month = {jun},
492 | year = {2000},
493 | url = {https://www.theorsociety.com/about-or/or-methods/heuristics/a-brief-history-of-the-travelling-salesman-problem/},
494 | note = {Accessed: January, 2020},
495 | }
496 |
497 | @book{Church2009,
498 | address = {Hoboken},
499 | author = {Church, Richard L. and Murray, Alan T.},
500 | publisher = {John Wiley {\&} Sons, Inc.},
501 | title = {{Business Site Selection, Locational Analysis, and GIS}},
502 | year = {2009}
503 | }
504 |
505 | @article{Koopmans1949,
506 | author = {Koopmans, Tjalling},
507 | journal = {Econometrica},
508 | pages = {136--146},
509 | title = {{Optimum Utilization of the Transportation System}},
510 | volume = {17},
511 | year = {1949}
512 | }
513 |
514 | @book{Phillips1981a,
515 | address = {Englewood Cliffs, NJ},
516 | author = {Phillips, Don T. and Garcia-Diaz, Alberto},
517 | publisher = {Prentice Hall},
518 | title = {{Fundamentals of Network Analysis}},
519 | year = {1981}
520 | }
521 |
522 | @article{Hitchcock1941,
523 | author = {Hitchcock, Frank L.},
524 | doi = {10.1017/CBO9781107415324.004},
525 | isbn = {9788578110796},
526 | issn = {1098-6596},
527 | journal = {Journal of Math and Physics},
528 | number = {1},
529 | pages = {224--230},
530 | pmid = {25246403},
531 | title = {{The Distribution of a Product from Several Sources to Numerous Localities}},
532 | volume = {20},
533 | year = {1941}
534 | }
535 |
536 | @article{GrahamHell_1985,
537 | author = {Graham, R. L. and Hell, Pavol},
538 | title = {On the History of the Minimum Spanning Tree Problem},
539 | year = {1985},
540 | volume = {7},
541 | number = {1},
542 | doi = {10.1109/MAHC.1985.10011},
543 | journal = {IEEE Annals of the History of Computing},
544 | pages = {43-57}
545 | }
546 |
547 | @article{Moran1950,
548 | author = {Moran, P. A. P.},
549 | doi = {10.2307/2332142},
550 | journal = {Biometrika},
551 | number = {1/2},
552 | pages = {17-23},
553 | title = {{Notes on Continuous Stochastic Phenomena}},
554 | volume = {37},
555 | year = {1950}
556 | }
557 |
558 | @article{Getis1992,
559 | author = {Getis, Arthur and Ord, J. K.},
560 | doi = {10.1111/j.1538-4632.1992.tb00261.x},
561 | journal = {Geographical Analysis},
562 | number = {3},
563 | pages = {189--206},
564 | title = {{The Analysis of Spatial Association by Use of Distance Statistics}},
565 | volume = {24},
566 | year = {1992}
567 | }
568 |
569 | @article{Lumnitz2020,
570 | author = {Lumnitz, Stefanie and Arribas-Bell, Dani and Cortes, Renan X. and Gaboardi, James D. and Griess, Verena and Kang, Wei and Oshan, Taylor M. and Wolf, Levi and Rey, Sergio},
571 | doi = {10.21105/joss.01882},
572 | journal = {Journal of Open Source Software},
573 | number = {47},
574 | pages = {1--4},
575 | title = {splot - visual analytics for spatial statistics},
576 | volume = {5},
577 | year = {2020}
578 | }
579 |
580 | @misc{splot:package:_2020,
581 | author = {Stefanie Lumnitz and
582 | Dani Arribas-Bel and
583 | Renan Xavier Cortes and
584 | James Gaboardi and
585 | Verena Griess and
586 | Wei Kang and
587 | Taylor Oshan and
588 | Levi John Wolf and
589 | Sergio Rey},
590 | title = {splot - visual analytics for spatial statistics},
591 | month = mar,
592 | year = 2020,
593 | publisher = {Zenodo},
594 | version = {v.1.1.3},
595 | doi = {10.5281/zenodo.3724199},
596 | }
597 |
598 | @article{Anselin1995,
599 | author = {Anselin, Luc},
600 | doi = {10.1111/j.1538-4632.1995.tb00338.x},
601 | journal = {Geographical Analysis},
602 | number = {2},
603 | pages = {93--115},
604 | title = {{Local indicators of spatial association --- LISA}},
605 | volume = {27},
606 | year = {1995}
607 | }
608 |
609 | @book{moran:_cliff81,
610 | Address = {London},
611 | Author = {Cliff, A.D. and Ord, J.K.},
612 | Publisher = {Pion},
613 | Title = {Spatial Processes: Models and Applications},
614 | Year = {1981}
615 | }
616 |
617 | @article{Gaboardi2021,
618 | doi = {10.21105/joss.02826},
619 | year = {2021},
620 | publisher = {{The Open Journal}},
621 | volume = {6},
622 | number = {62},
623 | pages = {2826},
624 | author = {James D. Gaboardi and Sergio Rey and Stefanie Lumnitz},
625 | title = {{spaghetti: spatial network analysis in PySAL}},
626 | journal = {{Journal of Open Source Software}}
627 | }
628 |
629 | @article{Rey2021,
630 | author = {Rey, S.J. and Anselin, L. and Amaral, P. and Arribas-Bel, D. and Cortes, R.X. and Gaboardi, J.D. and Kang, W. and Knaap, E. and Li, Z. and Lumnitz, S. and Oshan, T.M. and Shao, H. and Wolf, L.J.},
631 | title = {{The PySAL Ecosystem: Philosophy and Implementation}},
632 | journal = {Geographical Analysis},
633 | year = {2021},
634 | doi = {10.1111/gean.12276},
635 | abstract = {PySAL is a library for geocomputation and spatial data science. Written in Python, the library has a long history of supporting novel scholarship and broadening methodological impacts far afield of academic work. Recently, many new techniques, methods of analyses, and development modes have been implemented, making the library much larger and more encompassing than that previously discussed in the literature. As such, we provide an introduction to the library as it stands now, as well as the scientific and conceptual underpinnings of its core set of components. Finally, we provide a prospective look at the library's future evolution.}
636 | }
637 |
--------------------------------------------------------------------------------
/docs/api.rst:
--------------------------------------------------------------------------------
1 | .. _api_ref:
2 |
3 | .. currentmodule:: spaghetti
4 |
5 | API reference
6 | =============
7 |
8 | .. _network_api:
9 |
10 |
11 | Network feature instantiation
12 | -----------------------------
13 |
14 | .. autosummary::
15 | :toctree: generated/
16 |
17 | spaghetti.Network
18 | spaghetti.PointPattern
19 |
20 |
21 | Network feature extraction and creation
22 | ---------------------------------------
23 |
24 | .. autosummary::
25 | :toctree: generated/
26 |
27 | spaghetti.extract_component
28 | spaghetti.spanning_tree
29 | spaghetti.element_as_gdf
30 | spaghetti.regular_lattice
31 |
32 |
33 | Save and load a network
34 | -----------------------
35 |
36 | .. autosummary::
37 | :toctree: generated/
38 |
39 | spaghetti.network.Network.savenetwork
40 | spaghetti.network.Network.loadnetwork
41 |
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # SPAGHETTI documentation build configuration file, based on `giddy`. This file is
4 | # execfile()d with the current directory set to its containing dir. Note that not all
5 | # possible configuration values are present in this autogenerated file. All configuration
6 | # values have a default; values that are commented out serve to show the default. If
7 | # extensions (or modules to document with autodoc) are in another directory, add these
8 | # directories to sys.path here. If the directory is relative to the documentation root,
9 | # use os.path.abspath to make it absolute, like shown here.
10 |
11 |
12 | import sphinx_bootstrap_theme
13 | import spaghetti
14 |
15 | # -- General configuration ------------------------------------------------
16 |
17 | # If your documentation needs a minimal Sphinx version, state it here.
18 | #
19 | # needs_sphinx = '1.0'
20 | # Add any Sphinx extension module names here, as strings. They can be
21 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
22 | # ones.
23 | extensions = [ #'sphinx_gallery.gen_gallery',
24 | "sphinx.ext.autodoc",
25 | "sphinx.ext.autosummary",
26 | "sphinx.ext.viewcode",
27 | "sphinxcontrib.bibtex",
28 | "sphinx.ext.mathjax",
29 | "sphinx.ext.doctest",
30 | "sphinx.ext.intersphinx",
31 | "numpydoc",
32 | "nbsphinx",
33 | ]
34 | bibtex_bibfiles = ["_static/references.bib"]
35 |
36 | # Add any paths that contain templates here, relative to this directory.
37 | templates_path = ["_templates"]
38 |
39 | # The suffix(es) of source filenames.
40 | # You can specify multiple suffix as a list of string:
41 | #
42 | # source_suffix = ['.rst', '.md']
43 | source_suffix = ".rst"
44 |
45 | # The master toctree document.
46 | master_doc = "index"
47 |
48 | # General information about the project.
49 | project = "spaghetti"
50 | copyright = "2017-, pysal developers"
51 | author = "pysal developers"
52 |
53 | # The version info for the project you're documenting, acts as replacement for
54 | # |version| and |release|, also used in various other places throughout the
55 | # built documents.
56 | #
57 | # The full version.
58 | version = spaghetti.__version__
59 | release = spaghetti.__version__
60 |
61 | # The language for content autogenerated by Sphinx. Refer to documentation
62 | # for a list of supported languages.
63 | #
64 | # This is also used if you do content translation via gettext catalogs.
65 | # Usually you set "language" from the command line for these cases.
66 | language = "en"
67 |
68 | # List of patterns, relative to source directory, that match files and
69 | # directories to ignore when looking for source files.
70 | # This patterns also effect to html_static_path and html_extra_path
71 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "tests/*"]
72 |
73 | # The name of the Pygments (syntax highlighting) style to use.
74 | pygments_style = "sphinx"
75 |
76 | # If true, `todo` and `todoList` produce output, else they produce nothing.
77 | todo_include_todos = False
78 |
79 | # -- Options for HTML output ----------------------------------------------
80 |
81 | # The theme to use for HTML and HTML Help pages. See the documentation for
82 | # a list of builtin themes.
83 | #
84 | # html_theme = "alabaster"
85 | html_theme = "bootstrap"
86 | html_theme_path = sphinx_bootstrap_theme.get_html_theme_path()
87 | html_title = "%s v%s Manual" % (project, version)
88 |
89 | # (Optional) Logo of your package. Should be small enough to fit the navbar (ideally 24x24).
90 | # Path should be relative to the ``_static`` files directory.
91 | # html_logo = "_static/images/package_logo.jpg"
92 |
93 | # (Optional) PySAL favicon
94 | html_favicon = "_static/images/pysal_favicon.ico"
95 |
96 |
97 | # Theme options are theme-specific and customize the look and feel of a theme
98 | # further. For a list of options available for each theme, see the
99 | # documentation.
100 | #
101 | html_theme_options = {
102 | # Navigation bar title. (Default: ``project`` value)
103 | "navbar_title": project,
104 | # Render the next and previous page links in navbar. (Default: true)
105 | "navbar_sidebarrel": False,
106 | # Render the current pages TOC in the navbar. (Default: true)
107 | #'navbar_pagenav': True,
108 | #'navbar_pagenav': False,
109 | # No sidebar
110 | "nosidebar": True,
111 | # Tab name for the current pages TOC. (Default: "Page")
112 | #'navbar_pagenav_name': "Page",
113 | # Global TOC depth for "site" navbar tab. (Default: 1)
114 | # Switching to -1 shows all levels.
115 | "globaltoc_depth": 2,
116 | # Include hidden TOCs in Site navbar?
117 | #
118 | # Note: If this is "false", you cannot have mixed ``:hidden:`` and
119 | # non-hidden ``toctree`` directives in the same page, or else the build
120 | # will break.
121 | #
122 | # Values: "true" (default) or "false"
123 | "globaltoc_includehidden": "true",
124 | # HTML navbar class (Default: "navbar") to attach to element.
125 | # For black navbar, do "navbar navbar-inverse"
126 | #'navbar_class': "navbar navbar-inverse",
127 | # Fix navigation bar to top of page?
128 | # Values: "true" (default) or "false"
129 | "navbar_fixed_top": "true",
130 | # Location of link to source.
131 | # Options are "nav" (default), "footer" or anything else to exclude.
132 | "source_link_position": "footer",
133 | # Bootswatch (http://bootswatch.com/) theme.
134 | #
135 | # Options are nothing (default) or the name of a valid theme
136 | # such as "amelia" or "cosmo", "yeti", "flatly".
137 | "bootswatch_theme": "yeti",
138 | # Choose Bootstrap version.
139 | # Values: "3" (default) or "2" (in quotes)
140 | "bootstrap_version": "3",
141 | # Navigation bar menu
142 | "navbar_links": [
143 | ("Installation", "installation"),
144 | ("Tutorials", "tutorials"),
145 | ("API", "api"),
146 | ("References", "references"),
147 | ],
148 | }
149 |
150 | # Add any paths that contain custom static files (such as style sheets) here,
151 | # relative to this directory. They are copied after the builtin static files,
152 | # so a file named "default.css" will overwrite the builtin "default.css".
153 | html_static_path = ["_static"]
154 |
155 | # Custom sidebar templates, maps document names to template names.
156 | # html_sidebars = {}
157 | # html_sidebars = {'sidebar': ['localtoc.html', 'sourcelink.html', 'searchbox.html']}
158 |
159 | # -- Options for HTMLHelp output ------------------------------------------
160 |
161 | # Output file base name for HTML help builder.
162 | htmlhelp_basename = project + "doc"
163 |
164 |
165 | # -- Options for LaTeX output ---------------------------------------------
166 |
167 | latex_elements = {
168 | # The paper size ('letterpaper' or 'a4paper').
169 | #
170 | # 'papersize': 'letterpaper',
171 | # The font size ('10pt', '11pt' or '12pt').
172 | #
173 | # 'pointsize': '10pt',
174 | # Additional stuff for the LaTeX preamble.
175 | #
176 | # 'preamble': '',
177 | # Latex figure (float) alignment
178 | #
179 | # 'figure_align': 'htbp',
180 | }
181 |
182 | # Grouping the document tree into LaTeX files. List of tuples
183 | # (source start file, target name, title,
184 | # author, documentclass [howto, manual, or own class]).
185 | latex_documents = [
186 | (
187 | master_doc,
188 | "%s.tex" % project,
189 | "%s Documentation" % project,
190 | "pysal developers",
191 | "manual",
192 | )
193 | ]
194 |
195 |
196 | # -- Options for manual page output ---------------------------------------
197 |
198 | # One entry per manual page. List of tuples
199 | # (source start file, name, description, authors, manual section).
200 | man_pages = [(master_doc, "%s" % project, "%s Documentation" % project, [author], 1)]
201 |
202 |
203 | # -- Options for Texinfo output -------------------------------------------
204 |
205 | # Grouping the document tree into Texinfo files. List of tuples
206 | # (source start file, target name, title, author,
207 | # dir menu entry, description, category)
208 | texinfo_documents = [
209 | (
210 | master_doc,
211 | "%s" % project,
212 | "%s Documentation" % project,
213 | author,
214 | "%s" % project,
215 | "SPAtial GrapHs: nETworks, Topology, & Inference",
216 | "Miscellaneous",
217 | )
218 | ]
219 |
220 |
221 | # -----------------------------------------------------------------------------
222 | # Autosummary
223 | # -----------------------------------------------------------------------------
224 |
225 | # Generate the API documentation when building
226 | autosummary_generate = True
227 |
228 | # avoid showing members twice
229 | numpydoc_show_class_members = False
230 | numpydoc_use_plots = True
231 | class_members_toctree = True
232 | numpydoc_show_inherited_class_members = True
233 | numpydoc_xref_param_type = True
234 |
235 | # automatically document class members
236 | autodoc_default_options = {"members": True, "undoc-members": True}
237 |
238 | # display the source code for Plot directive
239 | plot_include_source = True
240 |
241 |
242 | def setup(app):
243 | app.add_css_file("pysal-styles.css")
244 |
245 |
246 | # Example configuration for intersphinx: refer to the Python standard library.
247 | intersphinx_mapping = {
248 | "esda": ("https://pysal.org/esda/", None),
249 | "geopandas": ("https://geopandas.org/en/latest/", None),
250 | "libpysal": ("https://pysal.org/libpysal/", None),
251 | "matplotlib": ("https://matplotlib.org/stable/", None),
252 | "networkx": ("https://networkx.org/documentation/stable/", None),
253 | "numpy": ("https://numpy.org/doc/stable/", None),
254 | "pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None),
255 | "pointpats": ("https://pysal.org/pointpats/", None),
256 | "python": ("https://docs.python.org/3.12/", None),
257 | "scipy": ("https://docs.scipy.org/doc/scipy/", None),
258 | }
259 |
260 | # This is processed by Jinja2 and inserted before each notebook
261 | nbsphinx_prolog = r"""
262 | {% set docname = env.doc2path(env.docname, base=None) %}
263 |
264 | .. only:: html
265 |
266 | .. role:: raw-html(raw)
267 | :format: html
268 |
269 | .. nbinfo::
270 |
271 | This page was generated from `{{ docname }}`__.
272 | Interactive online version:
273 | :raw-html:`

`
274 |
275 | __ https://github.com/pysal/spaghetti/blob/main/{{ docname }}
276 |
277 | .. raw:: latex
278 |
279 | \nbsphinxstartnotebook{\scriptsize\noindent\strut
280 | \textcolor{gray}{The following section was generated from
281 | \sphinxcode{\sphinxupquote{\strut {{ docname | escape_latex }}}} \dotfill}}
282 | """
283 |
284 | # This is processed by Jinja2 and inserted after each notebook
285 | nbsphinx_epilog = r"""
286 | .. raw:: latex
287 |
288 | \nbsphinxstopnotebook{\scriptsize\noindent\strut
289 | \textcolor{gray}{\dotfill\ \sphinxcode{\sphinxupquote{\strut
290 | {{ env.doc2path(env.docname, base='doc') | escape_latex }}}} ends here.}}
291 | """
292 |
293 | # List of arguments to be passed to the kernel that executes the notebooks:
294 | nbsphinx_execute_arguments = [
295 | "--InlineBackend.figure_formats={'svg', 'pdf'}",
296 | "--InlineBackend.rc={'figure.dpi': 96}",
297 | ]
298 |
299 |
300 | mathjax3_config = {
301 | "TeX": {"equationNumbers": {"autoNumber": "AMS", "useLabelIds": True}},
302 | }
303 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | .. documentation master file
2 |
3 | .. raw:: html
4 |
5 |

12 |
13 | `spaghetti`
14 | ===========
15 |
16 | **SPA**\ tial **G**\ rap\ **H**\ s: n\ **ET**\ works, **T**\ opology, & **I**\ nference
17 | ---------------------------------------------------------------------------------------
18 |
19 | `Spaghetti` is an open-source Python library for the analysis of network-based
20 | spatial data. Originating from the `network` module in `PySAL (Python Spatial
21 | Analysis Library)
`_, it is under active development for the
22 | inclusion of newly proposed methods for building graph-theoretic networks and
23 | the analysis of network events. An installation guide, API reference,
24 | and usage tutorials are provided here through the links above.
25 |
26 | .. raw:: html
27 |
28 |
64 |
65 |
66 | History
67 | -------
68 |
69 | `Spaghetti` was
70 | created and has evolved in line with the Python Spatial Analysis Library ecosystem for
71 | the specific purpose of utilizing the functionality of spatial weights in
72 | `libpysal `_ for generating network segment contiguity objects.
73 | The PySAL project was started in the mid-2000s when installation was difficult to maintain.
74 | Due to the non-triviality of relying on dependencies to secondary packages, a conscious
75 | decision was made to limit dependencies and build native PySAL data structures in cases
76 | where at all possible. Therefore, the original `pysal.network` submodule was developed to
77 | address the need for integrating support for network data structures with PySAL weights
78 | data structures, with the target audience being spatial data scientists and anyone
79 | interested in investigating network-centric phenomena within PySAL. Owing to the
80 | co-development of network functionality found within `spaghetti` and the evolution of
81 | the wider PySAL ecosystem, today, the package provides specialized network functionality
82 | that easily integrates with the rest of PySAL. This allows users of `spaghetti`’s network
83 | functionality to access spatial analysis functionality that complements network analysis,
84 | such as spatial statistical tools with `esda` and integration with core components of
85 | `libpysal`: `libpysal.weights` (mentioned above),
86 | `libpysal.cg` (computational geometry and data structures),
87 | `libpysal.io` (input-output), and `libpysal.examples` (built-in example data).
88 |
89 | Development
90 | -----------
91 |
92 | Development of `spaghetti` is hosted on GitHub_.
93 |
94 | Support
95 | -------
96 |
97 | All questions, comments, & discussions should happen in a public forum, where possible.
98 | Please start a `discussion `_ for questions, talk to us in `PySAL's Discord channel `_, or open an `issue `_ if there appears to be a
99 | bug. Private messages and emails will not be answered in a substantive manner.
100 |
101 | Citing `spaghetti`
102 | ------------------
103 |
104 | If you use PySAL-spaghetti in a scientific publication, we would appreciate using the following BibTeX citations::
105 |
106 | @article{Gaboardi2021,
107 | doi = {10.21105/joss.02826},
108 | url = {https://doi.org/10.21105/joss.02826},
109 | year = {2021},
110 | publisher = {The Open Journal},
111 | volume = {6},
112 | number = {62},
113 | pages = {2826},
114 | author = {James D. Gaboardi and Sergio Rey and Stefanie Lumnitz},
115 | title = {spaghetti: spatial network analysis in PySAL},
116 | journal = {Journal of Open Source Software}
117 | }
118 |
119 | @misc{Gaboardi2018,
120 | author = {Gaboardi, James D. and Laura, Jay and Rey, Sergio and
121 | Wolf, Levi John and Folch, David C. and Kang, Wei and
122 | Stephens, Philip and Schmidt, Charles},
123 | month = {oct},
124 | year = {2018},
125 | title = {pysal/spaghetti},
126 | url = {https://github.com/pysal/spaghetti},
127 | doi = {10.5281/zenodo.1343650},
128 | keywords = {graph-theory,network-analysis,python,spatial-networks,topology}
129 | }
130 |
131 | Citing Work
132 | -----------
133 |
134 | * **Lovelace, R**. `Open source tools for geographic analysis in transport planning`. Journal of Geographical Systems (2021): 1-32. https://doi.org/10.1007/s10109-020-00342-2.
135 | * **Rey, Sergio J., et al**. `The PySAL Ecosystem: Philosophy and Implementation`. Geographical Analysis (2022): 467-487. https://doi.org/10.1111/gean.12276.
136 | * **Barboza-Salerno, Gia E., and Jacquelyn CA Meshelemiah**. `Gun Violence on Walkable Routes to and from School: Recommendations for Policy and Practice`. Journal of Urban Health (2023): 1-16. https://doi.org/10.1007/s11524-023-00802-2
137 | * **Barboza, Gia, and Jacquelyn Meshelemiah**. `Danger, Students Beware, School Ahead! Gun Violence Exposure Near Schools in Compton, California`. (2023). https://doi.org/10.21203/rs.3.rs-2976516/v1
138 |
139 | Funding
140 | -------
141 |
142 | This project is/was partially funded through:
143 |
144 | .. figure:: _static/images/ardc_logo.png
145 | :target: https://atlantardc.wordpress.com
146 | :width: 150
147 | :align: left
148 |
149 | The Atlanta Research Data Center: `A Polygon-Based Approach to Spatial Network Allocation `_
150 |
151 | .. figure:: _static/images/nsf_logo.png
152 | :target: https://www.nsf.gov/index.jsp
153 | :width: 100
154 | :align: left
155 |
156 | National Science Foundation Award #1825768: `National Historical Geographic Information System `_
157 |
158 | .. raw:: html
159 |
160 |
167 |
168 | .. toctree::
169 | :hidden:
170 | :maxdepth: 3
171 | :caption: Contents:
172 |
173 | Installation
174 | Tutorials
175 | API
176 | References
177 |
178 | .. _PySAL: https://github.com/pysal/pysal
179 | .. _GitHub: https://github.com/pysal/spaghetti
180 |
--------------------------------------------------------------------------------
/docs/installation.rst:
--------------------------------------------------------------------------------
1 | .. Installation
2 |
3 | Python 3.10_ is tested for support by `spaghetti`. Please make sure that you are operating in a Python >= 3.10 environment.
4 |
5 | Installation
6 | ============
7 |
8 | Installing with ``conda`` via `spaghetti-feedstock`_ (highly recommended)
9 | -------------------------------------------------------------------------
10 |
11 | To install `spaghetti` and all its dependencies, we recommend using the conda_ manager, specifically with the conda-forge_ channel. This can be obtained by installing the `Anaconda Distribution`_ (a free Python distribution for data science), or through miniconda_ (minimal distribution only containing Python and the ``conda`` package manager).
12 |
13 | Using ``conda``, `spaghetti` can be installed as follows::
14 |
15 | $ conda config --set channel_priority strict
16 | $ conda install --channel conda-forge spaghetti
17 |
18 | Also, ``geopandas`` provides `a nice example`_ to create a fresh environment for working with spatial data.
19 |
20 | Installing with `Python Package Index`_
21 | ---------------------------------------
22 | ::
23 |
24 | $ pip install spaghetti
25 |
26 | *or* download the source distribution (``.tar.gz``) and decompress it to your selected destination. Open a command shell and navigate to the decompressed folder. ::
27 |
28 | $ pip install .
29 |
30 | .. role:: rubric
31 |
32 | **Warning**
33 |
34 | When installing via ``pip``, you have to ensure that the required dependencies for `spaghetti` are installed on your operating system. Details on how to install these packages are linked here_. Using ``conda`` (above) avoids having to install the dependencies separately.
35 |
36 | Development Version
37 | -------------------
38 |
39 | Install the most current development version of `spaghetti` by running::
40 |
41 | $ pip install git+https://github.com/pysal/spaghetti
42 |
43 | You can also fork_ the `pysal/spaghetti`_ repo and create a local clone of your fork. By making changes to your local clone and submitting a pull request to `pysal/spaghetti`_, you can contribute to the spaghetti development.
44 |
45 | |
46 |
47 | .. _3.10: https://docs.python.org/3.10/
48 | .. _spaghetti-feedstock: https://github.com/conda-forge/spaghetti-feedstock
49 | .. _a nice example: https://geopandas.readthedocs.io/en/latest/getting_started/install.html#creating-a-new-environment
50 | .. _conda: https://docs.conda.io/en/latest/
51 | .. _conda-forge: https://conda-forge.org
52 | .. _Anaconda Distribution: https://docs.continuum.io/anaconda/
53 | .. _miniconda: https://docs.conda.io/en/latest/miniconda.html
54 | .. _Python Package Index: https://pypi.org/project/spaghetti/
55 | .. _pysal/spaghetti: https://github.com/pysal/spaghetti
56 | .. _fork: https://help.github.com/articles/fork-a-repo/
57 | .. _here: https://github.com/pysal/spaghetti#requirements
58 |
--------------------------------------------------------------------------------
/docs/references.rst:
--------------------------------------------------------------------------------
1 | .. reference for the docs
2 |
3 | References
4 | ==========
5 |
6 | .. bibliography:: _static/references.bib
7 | :all:
8 |
--------------------------------------------------------------------------------
/docs/tutorials.rst:
--------------------------------------------------------------------------------
1 | .. tutorials
2 |
3 |
4 | Tutorials
5 | =========
6 |
7 | .. toctree::
8 | :maxdepth: 1
9 | :caption: Basic functionality:
10 |
11 | notebooks/quickstart.ipynb
12 | notebooks/pointpattern-attributes.ipynb
13 | notebooks/connected-components.ipynb
14 | notebooks/shortest-path-visualization.ipynb
15 |
16 | .. toctree::
17 | :maxdepth: 1
18 | :caption: Advanced functionality and known limitations:
19 |
20 | notebooks/network-segmentation.ipynb
21 | notebooks/network-spatial-dependence.ipynb
22 | notebooks/network-spatial-weights.ipynb
23 | notebooks/spanning-trees.ipynb
24 | notebooks/caveats.ipynb
25 |
26 | .. toctree::
27 | :maxdepth: 1
28 | :caption: Integrations & applications:
29 |
30 | notebooks/network-spatial-autocorrelation.ipynb
31 | notebooks/facility-location.ipynb
32 | notebooks/transportation-problem.ipynb
33 | notebooks/tsp.ipynb
34 |
35 | Citations:
36 | * Advanced functionality:
37 |
38 | * Spatial Dependence:
39 | :cite:`Ripley1976`, :cite:`Ripley1977`, :cite:`doi:10.1002/9780470549094.ch5`, :cite:`doi:10.1111/j.1538-4632.2001.tb00448.x`, :cite:`doi:10.1002/9781119967101.ch6`
40 |
41 | * Spatial Weights:
42 | :cite:`pysal2007`, :cite:`AnselinRey2014`, :cite:`rey_open_2015`
43 |
44 | * Spanning Trees:
45 | :cite:`GrahamHell_1985`, :cite:`AhujaRavindraK`, :cite:`doi:10.1002/9781119967101.ch3`
46 |
47 | * Integrations & applications:
48 |
49 | * Spatial Autocorrelation:
50 | :cite:`Moran1950`, :cite:`moran:_cliff81`, :cite:`Anselin1995`, :cite:`Getis1992`, :cite:`esda:_2019`, :cite:`splot:package:_2020`, :cite:`Lumnitz2020`
51 |
52 | * Facility Location:
53 | :cite:`Hakimi1964`, :cite:`ReVelle1970`, :cite:`Toregas1971`, :cite:`Toregas1972`, :cite:`Church1974`, :cite:`ReVelle2005`
54 |
55 | * The Transportation Problem:
56 | :cite:`Hitchcock1941`, :cite:`Koopmans1949`, :cite:`Phillips1981a`, :cite:`Gass2005`, :cite:`Church2009`, :cite:`daskin2013`
57 |
58 | * The Traveling Salesperson Problem:
59 | :cite:`Dantzig1954`, :cite:`Flood1956`, :cite:`Miller1960`, :cite:`Cummings2000`, :cite:`Miller2001`, :cite:`Bektas2014`
60 |
61 |
62 |
--------------------------------------------------------------------------------
/environment.yml:
--------------------------------------------------------------------------------
1 | name: notebooks-environment
2 | channels:
3 | - conda-forge
4 | dependencies:
5 | - python=3.12
6 | - esda
7 | - geopandas
8 | - libspatialindex
9 | - matplotlib
10 | - matplotlib-scalebar
11 | - numpy
12 | - pandas
13 | - pulp
14 | - rtree
15 | - scipy
16 | - seaborn
17 | - shapely
18 | - splot
19 | - watermark
20 | - pip
21 | - pip:
22 | - mip
23 | - ortools
24 | - git+https://github.com/pysal/spaghetti.git@main
25 |
--------------------------------------------------------------------------------
/paper/figs/spaghetti_network.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spaghetti/72ae8892a9ae62d0d18aecc310709b0e00d5f090/paper/figs/spaghetti_network.png
--------------------------------------------------------------------------------
/paper/figs/spaghetti_pointpattern_moran.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spaghetti/72ae8892a9ae62d0d18aecc310709b0e00d5f090/paper/figs/spaghetti_pointpattern_moran.png
--------------------------------------------------------------------------------
/paper/paper.bib:
--------------------------------------------------------------------------------
1 | @article{pysal2007,
2 | author={Sergio Rey and Luc Anselin},
3 | title={{PySAL: A Python Library of Spatial Analytical Methods}},
4 | journal={The Review of Regional Studies},
5 | year=2007,
6 | volume={37},
7 | number={1},
8 | pages={5-27},
9 | keywords={Open Source; Software; Spatial},
10 | url={https://rrs.scholasticahq.com/article/8285.pdf}
11 | }
12 |
13 | @article{pysal2015,
14 | title={Open {Geospatial} {Analytics} with {PySAL}},
15 | author={Sergio Rey and Luc Anselin and Xun Li and Robert Pahle and Jason Laura and Wenwen Li and Julia Koschinsky},
16 | journal={{ISPRS International Journal of Geo-Information}},
17 | year={2015},
18 | number={2},
19 | pages={815--836},
20 | volume={4},
21 | keywords={open science},
22 | doi={10.3390/ijgi4020815}
23 | }
24 |
25 | @article{gaboardi2020a,
26 | author={James D. Gaboardi and David C. Folch and Mark W. Horner},
27 | title={{Connecting Points to Spatial Networks: Effects on Discrete Optimization Models}},
28 | journal={Geographical Analysis},
29 | year={2020},
30 | volume={52},
31 | issue={2},
32 | pages={299--322},
33 | doi={10.1111/gean.12211},
34 | }
35 |
36 | @misc{gaboardi2018,
37 | author={James D. Gaboardi and Jay Laura and Sergio Rey and Levi John Wolf and David C. Folch and Wei Kang and Philip Stephens and Charles Schmidt},
38 | month={oct},
39 | year={2018},
40 | title={pysal/spaghetti},
41 | url= {https://github.com/pysal/spaghetti},
42 | doi={10.5281/zenodo.1343650},
43 | keywords={graph-theory,network-analysis,python,spatial-networks,topology}
44 | }
45 |
46 | @article{okabe2006a,
47 | author={Atsuyuki Okabe and Keiichi Okunuki and Shino Shiode},
48 | doi={10.1111/j.0016-7363.2005.00674.x},
49 | isbn={1538-4632},
50 | issn={0016-7363},
51 | journal={Geographical Analysis},
52 | pages={57--66},
53 | title={{SANET: A Toolbox for Spatial Analysis on a Network}},
54 | volume={38},
55 | year={2006}
56 | }
57 |
58 | @book{okabe2012,
59 | address={West Sussex, UK},
60 | author={Atsuyuki Okabe and Kokichi Sugihara},
61 | publisher={John Wiley {\&} Sons, Inc.},
62 | title={{Spatial Analysis Along Networks}},
63 | year={2012},
64 | doi={10.1002/9781119967101}
65 | }
66 |
67 | @inproceedings{hagberg2008,
68 | address={Pasadena, CA USA},
69 | author={Aric A. Hagberg and Daniel A. Schult and Pieter J. Swart},
70 | booktitle={Proceedings of the 7th Python in Science Conference (SciPy 2008)},
71 | editor={G{\"{a}}el Varoquaux and Travis Vaught and Jarrod Millman},
72 | issn ={1540-9295},
73 | pages={11--15},
74 | title={{Exploring Network Structure, Dynamics, and Function using NetworkX}},
75 | year={2008}
76 | }
77 |
78 | @article{boeing2017,
79 | author={Geoff Boeing},
80 | doi={10.1016/j.compenvurbsys.2017.05.004},
81 | issn={01989715},
82 | journal={Computers, Environment and Urban Systems},
83 | pages={126--139},
84 | publisher={Elsevier Ltd},
85 | title={{OSMnx: New Methods for Acquiring, Constructing, Analyzing, and Visualizing Complex Street Networks}},
86 | volume={65},
87 | year={2017}
88 | }
89 |
90 | @misc{russell2019,
91 | author={Tom Russell and Elco Koks},
92 | title={{tomalrussell/snkit: v1.6.0}},
93 | month=aug,
94 | year={2019},
95 | publisher={Zenodo},
96 | version={v1.6.0},
97 | doi={10.5281/zenodo.3379659}
98 | }
99 |
100 | @misc{geopandas2021,
101 | author={Kelsey Jordahl and Joris Van den Bossche and Martin Fleischmann and James McBride and Jacob Wasserman and Jeffrey Gerard and Adrian Garcia Badaracco and Alan D. Snow and Jeff Tratner and Matthew Perry and Carson Farmer and Geir Arne Hjelle and Micah Cochran and Sean Gillies and Lucas Culbertson and Matt Bartos and Giacomo Caria and Nick Eubank and sangarshanan and Sergio Rey and maxalbert and Aleksey Bilogur and Brendan Ward and Christopher Ren and Dani Arribas-Bel and Flavin and Leah Wasser and Levi John Wolf and Martin Journois and abonte},
102 | title={geopandas/geopandas: v0.9.0},
103 | month=feb,
104 | year=2021,
105 | publisher={Zenodo},
106 | version={v0.9.0},
107 | doi={10.5281/zenodo.4569086},
108 | url={https://doi.org/10.5281/zenodo.4569086}
109 | }
110 |
111 | @misc{reback2021pandas,
112 | author={Jeff Reback and Wes McKinney and jbrockmendel and Joris Van den Bossche and Tom Augspurger and Phillip Cloud and gfyoung and Simon Hawkins and Sinhrks and Matthew Roeschke and Adam Klein and Terji Petersen and Jeff Tratner and Chang She and William Ayd and Shahar Naveh and Marc Garcia and patrick and Jeremy Schendel and Andy Hayden and Daniel Saxton and Vytautas Jancauskas and Richard Shadrach and Marco Gorelli and Ali McMaster and Pietro Battiston and Skipper Seabold and Kaiqi Dong and chris-b1 and h-vetinari},
113 | title={pandas-dev/pandas: Pandas 1.2.3},
114 | month=mar,
115 | year=2021,
116 | publisher={Zenodo},
117 | version={v1.2.3},
118 | doi={10.5281/zenodo.4572994},
119 | url={https://doi.org/10.5281/zenodo.4572994}
120 | }
121 |
122 | @inproceedings{ mckinney-proc-scipy-2010,
123 | author={{W}es {M}c{K}inney},
124 | title={{D}ata {S}tructures for {S}tatistical {C}omputing in {P}ython},
125 | booktitle={{P}roceedings of the 9th {P}ython in {S}cience {C}onference},
126 | pages={56--61},
127 | year={2010},
128 | editor={{S}t\'efan van der {W}alt and {J}arrod {M}illman},
129 | doi={10.25080/Majora-92bf1922-00a}
130 | }
131 |
132 | @misc{libpysal2020,
133 | author={Sergio Rey and Philip Stephens and Levi John Wolf and Charles Schmidt and jlaura and Taylor Oshan and Dani Arribas-Bel and James Gaboardi and David Folch and mhwang4 and Wei Kang and Nicholas Malizia and Pedro Amaral and Luc Anselin and Eli Knaap and Hu Shao and Marynia and Andrew Winslow and Conceptron and Jotham Apaloo and Martin Fleischmann and Andy Eschbacher and Stefanie Lumnitz and Siddharth S and Forest Gregg and Elliott Sales de Andrade and Bas Couwenberg and Josh Kalderimis and Hannes and Andy Reagan},
134 | title={pysal/libpysal: v4.2.2},
135 | month=feb,
136 | year=2020,
137 | publisher={Zenodo},
138 | version={v4.2.2},
139 | doi={10.5281/zenodo.1472807},
140 | url={https://doi.org/10.5281/zenodo.1472807}
141 | }
142 |
143 | @article{Marshall2018,
144 | author={Stephen Marshall and Jorge Gil and Karl Kropf and Martin Tomko and Lucas Figueiredo},
145 | doi={10.1007/s11067-018-9427-9},
146 | issn={15729427},
147 | journal={Networks and Spatial Economics},
148 | keywords={Graph representation,Modelling,Street networks},
149 | number={3},
150 | pages={735--749},
151 | title={{Street Network Studies: from Networks to Models and their Representations}},
152 | volume={18},
153 | year={2018}
154 | }
155 |
156 | @inproceedings{foti2012generalized,
157 | title={A generalized computational framework for accessibility: from the pedestrian to the metropolitan scale},
158 | author={Fletcher Foti and Paul Waddell and Dennis Luxen},
159 | booktitle={Proceedings of the 4th TRB Conference on Innovations in Travel Modeling. Transportation Research Board},
160 | year={2012}
161 | }
162 |
163 | @inbook{osullivan_unwin2010.ch5,
164 | author={David O'Sullivan and David J. Unwin},
165 | publisher={John Wiley \& Sons, Ltd},
166 | isbn={9780470549094},
167 | title={Point Pattern Analysis},
168 | booktitle={Geographic Information Analysis},
169 | chapter={5},
170 | pages={121-156},
171 | doi={10.1002/9780470549094.ch5},
172 | year={2010},
173 | keywords={point separation, standard deviation, observed VMR, estimation methods, computationally intensive},
174 | abstract={Summary This chapter contains sections titled: Introduction Describing a Point Pattern Assessing Point Patterns Statistically Monte Carlo Testing Conclusions}
175 | }
176 |
177 | @article{splot:_Lumnitz2020,
178 | author={Stefanie Lumnitz and Dani Arribas-Bell and Renan X. Cortes and James D. Gaboardi and Verena Griess and Wei Kang and Taylor M. Oshan and Levi Wolf and Sergio Rey},
179 | doi={10.21105/joss.01882},
180 | journal={Journal of Open Source Software},
181 | number={47},
182 | pages={1--4},
183 | title={splot - visual analytics for spatial statistics},
184 | volume={5},
185 | year={2020}
186 | }
187 |
188 | @misc{esda:_2019,
189 | author={Sergio Rey and Levi Wolf and Wei Kang and Phil Stephens and Jason Laura and Charles Schmidt and Dani Arribas-Bel and Stefanie Lumnitz and Juan Carlos Duque and David Folch and Luc Anselin and Nicholas Malizia and James Gaboardi and Filipe Fernandes and Mridul Seth and mhwang4 and mlyons-tcc},
190 | title={{pysal/esda}},
191 | month=jul,
192 | year={2019},
193 | publisher={Zenodo},
194 | version={v2.1.1},
195 | doi={10.5281/zenodo.3265190}
196 | }
197 |
198 | @book{moran:_cliff81,
199 | address={London},
200 | author={Andrew David Cliff and J. Keith Ord},
201 | publisher={Pion},
202 | title={Spatial Processes: Models and Applications},
203 | year={1981}
204 | }
205 |
--------------------------------------------------------------------------------
/paper/paper.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'spaghetti: spatial network analysis in PySAL'
3 | tags:
4 | - Python
5 | - PySAL
6 | - spatial networks
7 | - network analysis
8 | authors:
9 | - name: James D. Gaboardi
10 | orcid: 0000-0002-4776-6826
11 | affiliation: 1
12 | - name: Sergio Rey
13 | orcid: 0000-0001-5857-9762
14 | affiliation: 2
15 | - name: Stefanie Lumnitz
16 | orcid: 0000-0002-7007-5812
17 | affiliation: 3
18 | affiliations:
19 | - name: Pennsylvania State University
20 | index: 1
21 | - name: Center for Geospatial Sciences, University of California Riverside
22 | index: 2
23 | - name: Directorate of Earth Observation Programs, ESRIN, European Space Agency
24 | index: 3
25 | date: 2 April 2021
26 | bibliography: paper.bib
27 | ---
28 |
29 |
30 | # Summary
31 |
32 | The role spatial networks, such as streets, play on the human experience cannot be overstated. All of our daily activities fall along, or in close proximity to, roads, bike paths, and subway systems to name a few. Therefore, when performing spatial analysis in many cases considering network space, as opposed to Euclidean space, allows for a more precise representation of daily human action and movement patterns. For example, people generally cannot get to work by driving in a straight line directly from their home, but move along paths within networks. To this end, `spaghetti` (**spa**tial **g**rap**h**s: n**et**works, **t**opology, & **i**nference), a sub-module embedded in the wider [PySAL](https://pysal.org) ecosystem, was developed to address network-centric research questions with a strong focus on spatial analysis [@pysal2007;@pysal2015;@gaboardi2018].
33 |
34 | Through `spaghetti`, first, network objects can be created and analysed from collections of line data by various means including reading in a shapefile or passing in a `geopandas.GeoDataFrame` at which time the line data are assigned network topology. Second, `spaghetti` provides computational tools to support statistical analysis of so-called network-based events along many different types of previously loaded networks. Network based-events or near-network observations are events that happen along spatial networks in our daily lives, i.e., locations of trees along footpaths, biking accidents along roads or locations of coffee shops along streets. As with `spaghetti.Network` objects, `spaghetti.PointPattern` objects can be [created from](https://pysal.org/spaghetti/generated/spaghetti.PointPattern.html#spaghetti.PointPattern) shapefiles, `geopandas.GeoDataFrame` objects or single `libpysal.cg.Point `objects. Near-network observations can then be snapped to nearest network segments enabling the calculation of observation distance matrices. Third, these observation distance matrices can be used both within `spaghetti` to perform clustering analysis or serve as input for other network-centric problems (e.g., optimal routing), or within the wider PySAL ecosystem to perform exploratory spatial analysis with [`esda`](https://pysal.org/esda/). Finally, `spaghetti`’s network elements (vertices and arcs) can also be extracted as `geopandas.GeoDataFrame` objects for visualization and integrated into further spatial statistical analysis within PySAL (e.g., `esda`).
35 |
36 |
37 | # Related Work & Statement of Need
38 |
39 | The most well-known network analysis package within the Python scientific stack is [NetworkX](https://networkx.github.io) [@hagberg2008], which can be used for modelling any type of complex network (e.g., social, spatial, etc.). [OSMnx](https://osmnx.readthedocs.io/en/stable/) [@boeing2017] is built on top of NetworkX and queries [OpenStreetMap](https://openstreetmap.org) for modelling street networks with resultant network objects returned within a `geopandas.GeoDataFrame` [@geopandas2021]. Another package, [`pandana`](https://github.com/UDST/pandana) [@foti2012generalized], is built on top of `pandas` [@mckinney-proc-scipy-2010;@reback2021pandas] with a focus on shortest path calculation and accessibility measures. Within the realm of Python, the functionality provided by [`snkit`](https://github.com/tomalrussell/snkit) [@russell2019] is most comparable to `spaghetti`, though it's main purpose is the processing of raw line data into clean network objects. Outside of Python, [SANET](http://sanet.csis.u-tokyo.ac.jp) [@okabe2006a] is the most closely related project to `spaghetti`, however, it is not written in Python and provides a GUI plugin for GIS software such as QGIS. Moreover, SANET is not fully open source. While all the libraries above are important for network-based research, `spaghetti` was created and has evolved in line with the Python Spatial Analysis Library ecosystem for the specific purpose of utilizing the functionality of spatial weights in [`libpysal`](https://pysal.org/libpysal/) for generating network segment contiguity objects.
40 |
41 |
42 | # Current Functionality
43 |
44 | Considering the related projects in the [Related Work & Statement of Need section](# Related Work & Statement of Need) detailed above, `spaghetti` fills a niche for not only the processing of spatial network objects, but also post-processing analysis. In other words, this package can be used to study the network *itself* or provide the foundation for studying network-based phenomena, such as crimes along city streets, all within a fully open-source environment. Considering this, the primary purpose of `spaghetti` is creating network objects: collections of vertices and arcs, and their topological relationships. The creation of a network object is realized through the following general steps:
45 |
46 | 1. read in line data or create features (regular lattices)
47 | 1. generate the network representation
48 | 1. extract contiguity weights (if desired) as show in \autoref{fig:gridweights}
49 | 1. identify connected components (if desired)
50 | 1. extract graph representation of the network (if desired)
51 |
52 | After the creation of a base network object it can be manipulated, analyzed, and utilized as the input for subsequent modelling scenarios. The following are several such examples:
53 |
54 | * allocating (snapping) observation point patterns to the network (see \autoref{fig:pointsnapmoran})
55 | * calculating all neighbor distance matrices
56 | * point type A to point type A (auto)
57 | * point type A to point type B (cross)
58 | * utilizing observation counts on network segments and network spatial weights within the [Moran’s *I*](https://pysal.org/spaghetti/generated/spaghetti.Network.html#spaghetti.Network.Moran) attribute to analyze global spatial autocorrelation [@moran:_cliff81;@esda:_2019] as seen in \autoref{fig:pointsnapmoran}
59 | * simulating point patterns that can be used within the [*K* function](https://pysal.org/spaghetti/generated/spaghetti.Network.html#spaghetti.Network.GlobalAutoK) attribute for cluster analysis [@osullivan_unwin2010.ch5;@okabe2012]
60 | * splitting the network into (nearly) uniform segments
61 | * extracting features as `geopandas.GeoDataFrame` objects:
62 | * network arcs, vertices and point patterns
63 | * largest/longest components
64 | * shortest paths
65 | * minimum/maximum spanning trees
66 |
67 | The following two demonstrations show several functionalities mentioned above, including feature creation, network instantiation, network allocation, and feature extraction, along with supplementary plots in \autoref{fig:gridweights} and \autoref{fig:pointsnapmoran}.
68 |
69 | ```python
70 | import spaghetti
71 | %matplotlib inline
72 | # generate network
73 | lattice = spaghetti.regular_lattice((0,0,3,3), 2, exterior=True)
74 | ntw = spaghetti.Network(in_data=lattice)
75 | # extract network elements
76 | vertices_df, arcs_df = spaghetti.element_as_gdf(ntw, vertices=True, arcs=True)
77 | # plot
78 | base_kws = {"figsize":(12, 12), "lw":5, "color":"k", "zorder":0}
79 | base = arcs_df.plot(**base_kws, alpha=.35)
80 | node_kws, edge_kws = {"s":100, "zorder":2}, {"zorder":1}
81 | w_kws = {"edge_kws":edge_kws, "node_kws":node_kws}
82 | ntw.w_network.plot(arcs_df, indexed_on="id", ax=base, **w_kws)
83 | vertices_df.plot(ax=base, fc="r", ec="k", markersize=50, zorder=2)
84 | ```
85 |
86 | ![A 4x4 regular lattice with network arcs in gray and vertices in red. Connectivity is demonstrated with `libpysal` spatial weights, which are plotted over the network in black [@libpysal2020]. \label{fig:gridweights}](figs/spaghetti_network.png){ width=50% }
87 |
88 | ```python
89 | import spaghetti, libpysal, matplotlib
90 | # create a network from a line shapefile
91 | ntw = spaghetti.Network(in_data=libpysal.examples.get_path("streets.shp"))
92 | # associate point observations with the network
93 | pp_name = "schools"
94 | pp_shp = libpysal.examples.get_path("%s.shp" % pp_name)
95 | ntw.snapobservations(pp_shp, pp_name, attribute=True)
96 | # calculation global spatial autocorrelation (Moran's I)
97 | moran, yaxis = ntw.Moran(pp_name)
98 | # extract network elements & observations
99 | arcs_df = spaghetti.element_as_gdf(ntw, arcs=True)
100 | schools = spaghetti.element_as_gdf(ntw, pp_name=pp_name)
101 | schools_snapped = spaghetti.element_as_gdf(ntw, pp_name=pp_name, snapped=True)
102 | # plot
103 | base_kws = {"figsize":(7, 7), "lw":3, "color":"k", "zorder":0}
104 | base = arcs_df.plot(**base_kws, alpha=.35)
105 | schools.plot(ax=base, fc="b", ec="k", markersize=100, zorder=1, alpha=.5)
106 | schools_snapped.plot(ax=base, fc="g", ec="k", markersize=50, zorder=2)
107 | matplotlib.pyplot.title(f"Moran's $I$: {round(moran.I, 3)}", size="xx-large")
108 | ```
109 |
110 | { width=50% }
111 |
112 | The overview presented here provides a high-level summary of functionality. More detailed examples and applications can be found in the *Tutorials* section of the `spaghetti` [documentation](https://pysal.org/spaghetti/tutorials.html).
113 |
114 |
115 | # Planned Enhancements
116 |
117 | As with any software project, there are always plans for further improvements and additional functionality. Four such major enhancements are described here. The first addition will likely be network partitioning through use of voronoi diagrams generated in network space. Network-constrained voronoi diagrams can be utilized as tools for analysis in and of themselves and can also be input for further analysis, such as the voronoi extension of the Network *K* function [@okabe2012]. Second, the current algorithm for allocating observations to a network within `spaghetti` allows for points to be snapped to a single location along the nearest network segment. While this is ideal for concrete observations, such as individual crime incidents, multiple network connections for abstract network events, such as census tract centroids, may be more appropriate [@gaboardi2020a]. Third, the core functionality of `spaghetti` is nearly entirely written with pure Python data structures, which are excellent for code readability and initial development but generally suffer in terms of performance. There are currently several functions that can be utilized with an optional `geopandas` installation, however, further integration with the `pandas` stack has the potential to greatly improve performance. Finally, `spaghetti` developers will assess together with PySAL developers how to best support visualization and visual analysis targeted towards `spaghetti` network objects, implemented within visualization packages like [`splot`](https://splot.readthedocs.io/en/latest/?badge=latest) or [`mapclassify`](https://pysal.org/mapclassify/) and exposed as high level plotting functionality in `spaghetti` [@splot:_Lumnitz2020].
118 |
119 |
120 | # Concluding Remarks
121 |
122 | Network-constrained spatial analysis is an important facet of scientific inquiry, especially within the social and geographic sciences [@Marshall2018]. Being able to perform this type of spatial analysis with a well-documented and tested open-source software package further facilitates fully reproducible and open science. With these motivations and core values, the `spaghetti` developers and wider PySAL team look forward to creating and supporting research into the future.
123 |
124 |
125 | # Acknowledgements
126 |
127 | Firstly, we would like to thank all the contributors to, and users of, this package. We would also like to acknowledge Jay Laura, who was the original lead developer of this package (`pysal.network`) prior to the introduction of the PySAL 2.0 ecosystem. The development of this package was partially supported by the [Atlanta Research Data Center](https://atlantardc.wordpress.com) and National Science Foundation Award [#1825768](https://www.nsf.gov/awardsearch/showAward?AWD_ID=1825768).
128 |
129 |
130 | # References
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["setuptools>=61.0", "setuptools_scm[toml]>=6.2"]
3 | build-backend = "setuptools.build_meta"
4 |
5 | [tool.setuptools_scm]
6 |
7 | [project]
8 | name = "spaghetti"
9 | dynamic = ["version"]
10 | maintainers = [
11 | {name = "James D. Gaboardi", email = "jgaboardi@gmail.com"},
12 | ]
13 | license = {text = "BSD 3-Clause"}
14 | description = "Analysis of Network-constrained Spatial Data"
15 | keywords = ["spatial statistics", "networks", "graphs"]
16 | readme = "README.md"
17 | classifiers = [
18 | "Programming Language :: Python :: 3",
19 | "License :: OSI Approved :: BSD License",
20 | "Operating System :: OS Independent",
21 | "Intended Audience :: Science/Research",
22 | "Topic :: Scientific/Engineering :: GIS",
23 | ]
24 | requires-python = ">=3.10"
25 | dependencies = [
26 | "esda>=2.1",
27 | "geopandas>=0.12",
28 | "libpysal>=4.6",
29 | "numpy>=1.22",
30 | "pandas>=1.4,!=1.5.0",
31 | "rtree>=1.0",
32 | "scipy>=1.8",
33 | "shapely>=2.0.1",
34 | ]
35 |
36 | [project.urls]
37 | Home = "https://pysal.org/spaghetti/"
38 | Repository = "https://github.com/pysal/spaghetti"
39 |
40 | [project.optional-dependencies]
41 | dev = [
42 | "ruff",
43 | "pre-commit",
44 | ]
45 | docs = [
46 | "nbsphinx",
47 | "numpydoc",
48 | "sphinx",
49 | "sphinxcontrib-bibtex",
50 | "sphinx_bootstrap_theme",
51 | ]
52 | tests = [
53 | "pytest",
54 | "pytest-cov",
55 | "pytest-doctestplus",
56 | "pytest-timeout",
57 | "pytest-xdist",
58 | "codecov",
59 | "coverage",
60 | "twine",
61 | "wheel",
62 | ]
63 | nb_pypi = [
64 | "mip",
65 | "ortools",
66 | ]
67 | nb_conda = [
68 | "matplotlib",
69 | "matplotlib-scalebar",
70 | "pulp",
71 | "seaborn",
72 | "splot",
73 | "watermark",
74 | ]
75 |
76 | [tool.setuptools.packages.find]
77 | include = [
78 | "spaghetti",
79 | "spaghetti.*",
80 | ]
81 |
82 | [tool.ruff]
83 | line-length = 88
84 | lint.select = ["E", "F", "W", "I", "UP", "N", "B", "A", "C4", "SIM", "ARG"]
85 | exclude = ["spaghetti/tests/*", "docs/*"]
86 |
87 | [tool.ruff.lint.per-file-ignores]
88 | "*__init__.py" = [
89 | "F401", # imported but unused
90 | "F403", # star import; unable to detect undefined names
91 | ]
92 |
93 | [tool.coverage.run]
94 | source = ["./spaghetti"]
95 |
96 | [tool.coverage.report]
97 | exclude_lines = [
98 | "if self.debug:",
99 | "pragma: no cover",
100 | "raise NotImplementedError",
101 | "except ModuleNotFoundError:",
102 | "except ImportError",
103 | ]
104 | ignore_errors = true
105 | omit = ["spaghetti/tests/*", "docs/conf.py"]
106 |
--------------------------------------------------------------------------------
/spaghetti/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | # `spaghetti` --- Spatial Graphs: Networks, Topology, & Inference
3 | """
4 |
5 | import contextlib
6 | from importlib.metadata import PackageNotFoundError, version
7 |
8 | from .network import (
9 | Network,
10 | PointPattern,
11 | SimulatedPointPattern,
12 | element_as_gdf,
13 | extract_component,
14 | regular_lattice,
15 | spanning_tree,
16 | )
17 |
18 | with contextlib.suppress(PackageNotFoundError):
19 | __version__ = version("spaghetti")
20 |
--------------------------------------------------------------------------------
/spaghetti/analysis.py:
--------------------------------------------------------------------------------
1 | import numpy
2 |
3 |
4 | class FuncBase:
5 | """Base object for performing network analysis on a
6 | ``spaghetti.Network`` object.
7 |
8 | Parameters
9 | ----------
10 | ntw : spaghetti.Network
11 | A spaghetti network object.
12 | pointpattern : spaghetti.network.PointPattern
13 | A spaghetti point pattern object.
14 | nsteps : int
15 | The number of steps at which the count of the nearest
16 | neighbors is computed. Default is 10.
17 | permutations : int
18 | The number of permutations to perform. Default is 99.
19 | threshold : float
20 | The level at which significance is computed.
21 | (0.5 would be 97.5% and 2.5%). Default is 0.5.
22 | distribution : str
23 | The distribution from which random points are sampled.
24 | Currently, the only supported distribution is uniform.
25 | upperbound : float
26 | The upper bound at which the `K`-function is computed.
27 | Defaults to the maximum observed nearest neighbor distance.
28 |
29 | Attributes
30 | ----------
31 | sim : numpy.ndarray
32 | A simulated distance matrix.
33 | npts : int
34 | The number of points (``pointpattern.npoints``).
35 | xaxis : numpy.ndarray
36 | The observed x-axis of values.
37 | observed : numpy.ndarray
38 | The observed y-axis of values.
39 |
40 | """
41 |
42 | def __init__(
43 | self,
44 | ntw,
45 | pointpattern,
46 | nsteps=10,
47 | permutations=99,
48 | threshold=0.5,
49 | distribution="uniform",
50 | upperbound=None,
51 | ):
52 | # set initial class attributes
53 | self.ntw = ntw
54 | self.pointpattern = pointpattern
55 | self.nsteps = nsteps
56 | self.permutations = permutations
57 | self.threshold = threshold
58 |
59 | # set and validate the distribution
60 | self.distribution = distribution.lower()
61 | self.validatedistribution()
62 |
63 | # create an empty array to store the simulated points
64 | self.sim = numpy.empty((permutations, nsteps))
65 | self.pts = self.pointpattern
66 | self.npts = self.pts.npoints
67 |
68 | # set the upper bounds
69 | self.upperbound = upperbound
70 |
71 | # compute the statistic K
72 | self.computeobserved()
73 | self.computepermutations()
74 |
75 | # compute the envelope vectors
76 | self.computeenvelope()
77 |
78 | def validatedistribution(self):
79 | """Ensure the statistical distribution is supported."""
80 |
81 | valid_distributions = ["uniform"]
82 | if self.distribution not in valid_distributions:
83 | msg = f"{self.distribution} distribution not currently supported."
84 | raise RuntimeError(msg)
85 |
86 | def computeenvelope(self):
87 | """Compute upper and lower bounds of envelope."""
88 |
89 | upper = 1.0 - self.threshold / 2.0
90 | lower = self.threshold / 2.0
91 |
92 | self.upperenvelope = numpy.nanmax(self.sim, axis=0) * upper
93 | self.lowerenvelope = numpy.nanmin(self.sim, axis=0) * lower
94 |
95 | def setbounds(self, distances):
96 | """Set the upper bound."""
97 | if self.upperbound is None:
98 | self.upperbound = numpy.nanmax(distances)
99 |
100 |
101 | class GlobalAutoK(FuncBase):
102 | """See full description in ``network.Network.GlobalAutoK()``.
103 |
104 | Attributes
105 | ----------
106 | lam : float
107 | The ``lambda`` value; representing intensity.
108 |
109 | """
110 |
111 | def computeobserved(self):
112 | """Compute the K function of observed points."""
113 |
114 | # pairwise distances
115 | distances = self.ntw.allneighbordistances(self.pointpattern)
116 | distances = upper_triangle_as_vector(distances)
117 |
118 | self.setbounds(distances)
119 |
120 | # set the intensity (lambda)
121 | self.lam = self.npts / sum(self.ntw.arc_lengths.values())
122 |
123 | # compute a Global Auto K-Function
124 | observedx, observedy = global_auto_k(
125 | self.npts, distances, self.upperbound, self.lam, self.nsteps
126 | )
127 |
128 | # set observed values
129 | self.observed = observedy
130 | self.xaxis = observedx
131 |
132 | def computepermutations(self):
133 | """Compute the K function on permutations (Monte Carlo simulation)."""
134 |
135 | # for each round of permutations
136 | for p in range(self.permutations):
137 | # simulate a point pattern
138 | sim = self.ntw.simulate_observations(
139 | self.npts, distribution=self.distribution
140 | )
141 |
142 | # distances
143 | distances = self.ntw.allneighbordistances(sim)
144 | distances = upper_triangle_as_vector(distances)
145 |
146 | # compute a Global Auto K-Function
147 | simx, simy = global_auto_k(
148 | self.npts, distances, self.upperbound, self.lam, self.nsteps
149 | )
150 |
151 | # label the permutation
152 | self.sim[p] = simy
153 |
154 |
155 | def upper_triangle_as_vector(matrix):
156 | """Return the upper triangle of a symmetric matrix without the diagonal."""
157 | return matrix[numpy.triu_indices_from(matrix, k=1)]
158 |
159 |
160 | def global_auto_k(n_obs, dists, upperbound, intensity, nsteps):
161 | """Compute a `K`-function.
162 |
163 | Parameters
164 | ----------
165 | n_obs : int
166 | The number of observations. See ``self.npts``.
167 | dists : numpy.ndarray
168 | A vector (the upper triangle of a symmetric matrix)
169 | of pairwise distances.
170 | upperbound : int or float
171 | The end value of the sequence.
172 | intensity : float
173 | lambda value
174 | nsteps : int
175 | The number of distance bands. Must be non-negative.
176 |
177 | Returns
178 | -------
179 | x : numpy.ndarray
180 | The x-axis of values.
181 | y : numpy.ndarray
182 | The y-axis of values.
183 |
184 | """
185 |
186 | # create interval for x-axis
187 | x = numpy.linspace(0, upperbound, num=nsteps).reshape(-1, 1)
188 |
189 | # "iterate" over the x-axis interval, slice out and count neighbors within
190 | # each step radius, and multiply x2 to account for the lower triangle
191 | y = (dists < x).sum(axis=1) * 2.0
192 |
193 | # finalize the K computation for the denominator if the y-axis vector
194 | y /= n_obs * intensity
195 |
196 | # reset the shape of the x-axis
197 | x = x.squeeze()
198 |
199 | return x, y
200 |
--------------------------------------------------------------------------------
/spaghetti/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pysal/spaghetti/72ae8892a9ae62d0d18aecc310709b0e00d5f090/spaghetti/tests/__init__.py
--------------------------------------------------------------------------------
/spaghetti/util.py:
--------------------------------------------------------------------------------
1 | import geopandas
2 | import numpy
3 | import pandas
4 | import shapely
5 | from libpysal import cg
6 | from rtree import Rtree
7 | from shapely.geometry import LineString
8 |
9 |
10 | def compute_length(v0, v1):
11 | """Compute the euclidean distance between two points.
12 |
13 | Parameters
14 | ----------
15 | v0 : tuple
16 | Coordinate sequence in the form x,y.
17 | vq : tuple
18 | Coordinate sequence in the form x,y.
19 |
20 | Returns
21 | -------
22 | euc_dist : float
23 | Euclidean distance.
24 |
25 | Examples
26 | --------
27 |
28 | >>> import spaghetti
29 | >>> point1, point2 = (0,0), (1,1)
30 | >>> spaghetti.util.compute_length(point1, point2)
31 | 1.4142135623730951
32 |
33 | """
34 |
35 | euc_dist = cg.standalone.get_points_dist(v0, v1)
36 |
37 | return euc_dist
38 |
39 |
40 | def get_neighbor_distances(ntw, v0, link):
41 | """Get distances to the nearest vertex neighbors along
42 | connecting arcs.
43 |
44 | Parameters
45 | ----------
46 | ntw : spaghetti.Network
47 | A spaghetti network object.
48 | v0 : int
49 | The vertex ID.
50 | link : dict
51 | The key is a tuple (start vertex, end vertex); value is ``float``.
52 | Cost per arc to travel, e.g. distance.
53 |
54 | Returns
55 | -------
56 | neighbors : dict
57 | The key is an integer (vertex ID); value is ``float`` (distance).
58 |
59 | Examples
60 | --------
61 |
62 | >>> import spaghetti
63 | >>> from libpysal import examples
64 | >>> ntw = spaghetti.Network(examples.get_path("streets.shp"))
65 | >>> neighs = spaghetti.util.get_neighbor_distances(ntw, 0, ntw.arc_lengths)
66 | >>> numpy.round(neighs[1], 10)
67 | np.float64(102.6235345344)
68 |
69 | """
70 |
71 | # fetch links associated with vertices
72 | arcs = ntw.enum_links_vertex(v0)
73 |
74 | # create neighbor distance lookup
75 | neighbors = {}
76 |
77 | # iterate over each associated link
78 | for arc in arcs:
79 | # set distance from vertex1 to vertex2 (link length)
80 | if arc[0] != v0:
81 | neighbors[arc[0]] = link[arc]
82 | else:
83 | neighbors[arc[1]] = link[arc]
84 |
85 | return neighbors
86 |
87 |
88 | def generatetree(pred):
89 | """Rebuild the shortest path from root origin to destination.
90 |
91 | Parameters
92 | ----------
93 | pred : list
94 | List of preceding vertices for route traversal.
95 |
96 | Returns
97 | -------
98 | tree : dict
99 | The key is the root origin; value is the root origin to destination.
100 |
101 | Examples
102 | --------
103 |
104 | >>> import spaghetti
105 | >>> from libpysal import examples
106 | >>> ntw = spaghetti.Network(examples.get_path("streets.shp"))
107 | >>> distance, pred = spaghetti.util.dijkstra(ntw, 0)
108 | >>> tree = spaghetti.util.generatetree(pred)
109 | >>> tree[3]
110 | [np.int64(23), np.int64(22), np.int64(20), np.int64(19), np.int64(170), np.int64(2), np.int64(0)]
111 |
112 | """ # noqa: E501
113 |
114 | # instantiate tree lookup
115 | tree = {}
116 |
117 | # iterate over the list of predecessor vertices
118 | for i, p in enumerate(pred):
119 | # if the route begins/ends with itself set the
120 | # root vertex and continue to next iteration
121 | if p == -1:
122 | # tree keyed by root vertex with root vertex as path
123 | tree[i] = [i]
124 | continue
125 |
126 | # set the initial vertex `p` as `idx`
127 | idx = p
128 | # and add it as the first vertex in the path
129 | path = [idx]
130 |
131 | # iterate through the path until back to home vertex
132 | while idx >= 0:
133 | # set the next vertex on the path
134 | next_vertex = pred[idx]
135 | # and redeclare the current `idx`
136 | idx = next_vertex
137 |
138 | # add the vertex to path while not at home vertex
139 | if idx >= 0:
140 | path.append(next_vertex)
141 |
142 | # tree keyed by root vertex with network vertices as path
143 | tree[i] = path
144 |
145 | return tree
146 |
147 |
148 | def dijkstra(ntw, v0, initial_dist=numpy.inf):
149 | """Compute the shortest path between a start vertex and
150 | all other vertices in an origin-destination matrix.
151 |
152 | Parameters
153 | ----------
154 | ntw : spaghetti.Network
155 | A spaghetti network object.
156 | v0 : int
157 | Start vertex ID.
158 | initial_dist : float
159 | Integer break point to stop iteration and return n neighbors.
160 | Default is ``numpy.inf``.
161 |
162 | Returns
163 | -------
164 | distance : list
165 | List of distances from vertex to all other vertices.
166 | pred : list
167 | List of preceeding vertices for traversal route.
168 |
169 | Notes
170 | -----
171 |
172 | Based on :cite:`Dijkstra1959a`.
173 |
174 | Examples
175 | --------
176 |
177 | >>> import spaghetti
178 | >>> from libpysal import examples
179 | >>> ntw = spaghetti.Network(examples.get_path("streets.shp"))
180 | >>> distance, pred = spaghetti.util.dijkstra(ntw, 0)
181 | >>> round(distance[196], 4)
182 | 5505.6682
183 | >>> pred[196]
184 | np.int64(133)
185 |
186 | """
187 |
188 | # cost per arc to travel, e.g. distance
189 | cost = ntw.arc_lengths
190 |
191 | # initialize travel costs as `inf` for all distances
192 | distance = [initial_dist for x in ntw.vertex_list]
193 |
194 | # label distance to self as 0
195 | distance[ntw.vertex_list.index(v0)] = 0
196 |
197 | # instantiate set of unvisited vertices
198 | unvisited = {v0}
199 |
200 | # initially label as predecessor vertices with -1 as path
201 | pred = [-1 for x in ntw.vertex_list]
202 |
203 | # iterate over `unvisited` until all vertices have been visited
204 | while len(unvisited) > 0:
205 | # get vertex with the lowest value from distance
206 | dist = initial_dist
207 |
208 | for vertex in unvisited:
209 | if distance[vertex] < dist:
210 | dist = distance[vertex]
211 | current = vertex
212 |
213 | # remove that vertex from the set
214 | unvisited.remove(current)
215 |
216 | # get the neighbors (and costs) to the current vertex
217 | neighbors = get_neighbor_distances(ntw, current, cost)
218 |
219 | # iterate over neighbors to find least cost along path
220 | for v1, indiv_cost in neighbors.items():
221 | # if the labeled cost is greater than
222 | # the currently calculated cost
223 | if distance[v1] > distance[current] + indiv_cost:
224 | # relabel to the currently calculated cost
225 | distance[v1] = distance[current] + indiv_cost
226 |
227 | # set the current vertex as a predecessor on the path
228 | pred[v1] = current
229 |
230 | # add the neighbor vertex to `unvisted`
231 | unvisited.add(v1)
232 |
233 | # cast preceding vertices list as an array of integers
234 | pred = numpy.array(pred, dtype=int)
235 |
236 | return distance, pred
237 |
238 |
239 | def dijkstra_mp(ntw_vertex):
240 | """Compute the shortest path between a start vertex and all other
241 | vertices in the matrix utilizing multiple cores upon request.
242 |
243 | Parameters
244 | ----------
245 | ntw_vertex : tuple
246 | Tuple of arguments to pass into ``dijkstra()`` as
247 | (1) ``ntw`` - ``spaghetti.Network object``;
248 | (2) ``vertex`` - int (start node ID)
249 |
250 | Returns
251 | -------
252 | distance : list
253 | List of distances from vertex to all other vertices.
254 | pred : list
255 | List of preceeding vertices for traversal route.
256 |
257 | Notes
258 | -----
259 |
260 | Based on :cite:`Dijkstra1959a`.
261 |
262 | Examples
263 | --------
264 |
265 | >>> import spaghetti
266 | >>> from libpysal import examples
267 | >>> ntw = spaghetti.Network(examples.get_path("streets.shp"))
268 | >>> distance, pred = spaghetti.util.dijkstra_mp((ntw, 0))
269 | >>> round(distance[196], 4)
270 | 5505.6682
271 | >>> pred[196]
272 | np.int64(133)
273 |
274 | """
275 |
276 | # unpack network object and source vertex
277 | ntw, vertex = ntw_vertex
278 |
279 | # calculate shortest path distances and predecessor vertices
280 | distance, pred = dijkstra(ntw, vertex)
281 |
282 | return distance, pred
283 |
284 |
285 | def squared_distance_point_link(point, link):
286 | """Find the squared distance between a point and a link.
287 |
288 | Parameters
289 | ----------
290 | point : tuple
291 | Point coordinates (x,y).
292 | link : list
293 | List of 2 point coordinate tuples [(x0, y0), (x1, y1)].
294 |
295 | Returns
296 | -------
297 | sqd : float
298 | The distance squared between the point and edge.
299 | nearp : numpy.ndarray
300 | An array of (xb, yb); the nearest point on the edge.
301 |
302 | Examples
303 | --------
304 |
305 | >>> import spaghetti
306 | >>> point, link = (1,1), ((0,0), (2,0))
307 | >>> spaghetti.util.squared_distance_point_link(point, link)
308 | (np.float64(1.0), array([1., 0.]))
309 |
310 | """
311 |
312 | # cast vertices comprising the network link as an array
313 | p0, p1 = (numpy.array(p) for p in link)
314 |
315 | # cast the observation point as an array
316 | p = numpy.array(point)
317 |
318 | # subtract point 0 coords from point 1
319 | v = p1 - p0
320 | # subtract point 0 coords from the observation coords
321 | w = p - p0
322 |
323 | # if the point 0 vertex is the closest point along the link
324 | c1 = numpy.dot(w, v)
325 | if c1 <= 0.0:
326 | sqd = numpy.dot(w.T, w)
327 | nearp = p0
328 |
329 | return sqd, nearp
330 |
331 | # if the point 1 vertex is the closest point along the link
332 | c2 = numpy.dot(v, v)
333 | if c2 <= c1:
334 | dp1 = p - p1
335 | sqd = numpy.dot(dp1.T, dp1)
336 | nearp = p1
337 |
338 | return sqd, nearp
339 |
340 | # otherwise the closest point along the link lies between p0 and p1
341 | b = c1 / c2
342 | bv = numpy.dot(b, v)
343 | pb = p0 + bv
344 | d2 = p - pb
345 | sqd = numpy.dot(d2, d2)
346 | nearp = pb
347 |
348 | return sqd, nearp
349 |
350 |
351 | def snap_points_to_links(points, links):
352 | """Place points onto closest link in a set of links (arc/edges).
353 |
354 | Parameters
355 | ----------
356 | points : dict
357 | Point ID as key and (x,y) coordinate as value.
358 | links : list
359 | Elements are of type ``libpysal.cg.shapes.Chain``
360 | ** Note ** each element is a link represented as a chain with
361 | *one head and one tail vertex* in other words one link only.
362 |
363 | Returns
364 | -------
365 | point2link : dict
366 | Key [point ID (see points in arguments)]; value [a 2-tuple
367 | ((head, tail), point) where (head, tail) is the target link,
368 | and point is the snapped location on the link.
369 |
370 | Examples
371 | --------
372 |
373 | >>> import spaghetti
374 | >>> from libpysal.cg.shapes import Point, Chain
375 | >>> points = {0: Point((1,1))}
376 | >>> link = [Chain([Point((0,0)), Point((2,0))])]
377 | >>> spaghetti.util.snap_points_to_links(points, link)
378 | {0: ([(0.0, 0.0), (2.0, 0.0)], array([1., 0.]))}
379 |
380 | """
381 |
382 | # instantiate an rtree
383 | rtree = Rtree()
384 | # set the smallest possible float epsilon on machine
385 | small = numpy.finfo(float).eps
386 |
387 | # initialize network vertex to link lookup
388 | vertex_2_link = {}
389 |
390 | # iterate over network links
391 | for i, link in enumerate(links):
392 | # extract network link (x,y) vertex coordinates
393 | head, tail = link.vertices
394 | x0, y0 = head
395 | x1, y1 = tail
396 |
397 | if (x0, y0) not in vertex_2_link:
398 | vertex_2_link[(x0, y0)] = []
399 |
400 | if (x1, y1) not in vertex_2_link:
401 | vertex_2_link[(x1, y1)] = []
402 |
403 | vertex_2_link[(x0, y0)].append(link)
404 | vertex_2_link[(x1, y1)].append(link)
405 |
406 | # minimally increase the bounding box exterior
407 | bx0, by0, bx1, by1 = link.bounding_box
408 | bx0 -= small
409 | by0 -= small
410 | bx1 += small
411 | by1 += small
412 |
413 | # insert the network link and its associated
414 | # rectangle into the rtree
415 | rtree.insert(i, (bx0, by0, bx1, by1), obj=link)
416 |
417 | # build a KDtree on link vertices
418 | kdtree = cg.KDTree(list(vertex_2_link.keys()))
419 |
420 | point2link = {}
421 |
422 | for pt_idx, point in points.items():
423 | # first, find nearest neighbor link vertices for the point
424 | dmin, vertex = kdtree.query(point, k=1)
425 | vertex = tuple(kdtree.data[vertex])
426 | closest = vertex_2_link[vertex][0].vertices
427 |
428 | # Use this link as the candidate closest link: closest
429 | # Use the distance as the distance to beat: dmin
430 | point2link[pt_idx] = (closest, numpy.array(vertex))
431 | x0 = point[0] - dmin
432 | y0 = point[1] - dmin
433 | x1 = point[0] + dmin
434 | y1 = point[1] + dmin
435 |
436 | # Find all links with bounding boxes that intersect
437 | # a query rectangle centered on the point with sides
438 | # of length dmin * dmin
439 | rtree_lookup = rtree.intersection([x0, y0, x1, y1], objects=True)
440 | candidates = [cand.object.vertices for cand in rtree_lookup]
441 |
442 | # Sorting the candidate ensures reproducible results from OS to OS.
443 | # See:
444 | # https://github.com/pysal/spaghetti/pull/595
445 | # https://github.com/pysal/spaghetti/issues/598
446 | # https://github.com/pysal/spaghetti/pull/599
447 | candidates.sort(reverse=True)
448 | dmin += small
449 | dmin2 = dmin * dmin
450 |
451 | # of the candidate arcs, find the nearest to the query point
452 | for candidate in candidates:
453 | dist2cand, nearp = squared_distance_point_link(point, candidate)
454 | if dist2cand <= dmin2:
455 | closest = candidate
456 | dmin2 = dist2cand
457 | point2link[pt_idx] = (closest, nearp)
458 |
459 | return point2link
460 |
461 |
462 | def network_has_cycle(adjacency):
463 | """Searches for a cycle in the complete network/graph.
464 |
465 | Parameters
466 | ----------
467 | adjacency : spaghetti.Network.adjacencylist
468 | Vertex adjacency relationships.
469 |
470 | Returns
471 | -------
472 | network_cycle_found : bool
473 | ``True`` for a cycle being found in the network/graph,
474 | otherwise ``False``.
475 |
476 | """
477 |
478 | def tree_has_cycle(_parent, _v):
479 | """Searches for a cycle in the subtree.
480 |
481 | Parameters
482 | ----------
483 | _parent : int
484 | Root vertex for the subnetwork/graph.
485 | _v : int
486 | Current vertex index of in the complete network.
487 |
488 | Returns
489 | -------
490 | subtree_cycle_found : bool
491 | Current recursion found a cycle in the subtree.
492 |
493 | """
494 |
495 | # Set current cycle tag as False
496 | subtree_cycle_found = False
497 |
498 | # Label the current network vertex as seen
499 | seen[_v] = True
500 |
501 | # Perform recursion for all adjacent network/graph vertices
502 | for rv in adjacency[_v]:
503 | # If vertex already seen, skip it
504 | if not seen[rv]:
505 | # Perform recursion down the depth-first search tree
506 | if tree_has_cycle(_v, rv):
507 | subtree_cycle_found = True
508 | break
509 |
510 | # If an adjacent vertex has not been seen and it is not the
511 | # parent of current vertex, then a cycle is present
512 | elif _parent != rv:
513 | subtree_cycle_found = True
514 | break
515 |
516 | return subtree_cycle_found
517 |
518 | # set initial cycle tag as False
519 | network_cycle_found = False
520 |
521 | # Label all network/graph vertices as not seen
522 | vids = list(adjacency.keys())
523 | seen = {vid: False for vid in vids}
524 |
525 | # Perform depth-first search recursion to isolate cycles
526 | for v in vids:
527 | # If vertex already seen, skip it; or recurse down the depth-first search tree
528 | if not seen[v] and tree_has_cycle(-1, v):
529 | network_cycle_found = True
530 | break
531 |
532 | return network_cycle_found
533 |
534 |
535 | def chain_constr(vcoords, arcs):
536 | """Create the spatial representation of a network arc.
537 |
538 | Parameters
539 | ----------
540 | vcoords : dict
541 | Vertex to coordinate lookup (see ``spaghetti.Network.vertex_coords``).
542 | arcs : list
543 | Arcs represented as start and end vertices.
544 |
545 | Returns
546 | -------
547 | spatial_reps : list
548 | Spatial representations of arcs - ``libpysal.cg.Chain`` objects.
549 |
550 | """
551 | spatial_reps = [_chain_constr(vcoords, vs) for vs in arcs]
552 | return spatial_reps
553 |
554 |
555 | def _chain_constr(_vcoords, _vs):
556 | """Construct a libpysal.cg.Chain object.
557 |
558 | Parameters
559 | ----------
560 | _vcoords : {dict, None}
561 | See ``vcoords`` in ``get_chains()``.
562 | _vs : tuple
563 | Start and end vertex IDs of arc.
564 |
565 | Returns
566 | -------
567 | libpysal.cg.Chain
568 | Spatial representation of the arc.
569 |
570 | """
571 |
572 | return cg.Chain([cg.Point(_vcoords[v]) for v in _vs] if _vcoords else _vs)
573 |
574 |
575 | def build_chains(space_h, space_v, exterior, bounds, h=True):
576 | """Generate line segments for a lattice.
577 |
578 | Parameters
579 | ----------
580 | space_h : list
581 | Horizontal spacing.
582 | space_v : list
583 | Vertical spacing.
584 | exterior : bool
585 | Flag for including the outer bounding box segments.
586 | bounds : list
587 | Area bounds in the form - .
588 | h : bool
589 | Generate horizontal line segments.
590 | Default is ``True``. ``False`` generates vertical segments.
591 |
592 | Returns
593 | -------
594 | chains : list
595 | All horizontal or vertical line segments in the lattice.
596 |
597 | """
598 |
599 | # Initialize starting and ending indices
600 | start_h, end_h, start_v, end_v = 0, len(space_h), 0, len(space_v)
601 |
602 | # set inital index track back to 0
603 | minus_y, minus_x = 0, 0
604 |
605 | if h: # start track back at 1 for horizontal lines
606 | minus_x = 1
607 | if not exterior: # do not include borders
608 | start_v += 1
609 | end_v -= 1
610 |
611 | else: # start track back at 1 for vertical lines
612 | minus_y = 1
613 | if not exterior: # do not include borders
614 | start_h += 1
615 | end_h -= 1
616 |
617 | # Create empty line list and fill
618 | chains = []
619 |
620 | # for element in the horizontal index
621 | for plus_h in range(start_h, end_h):
622 | # for element in the vertical index
623 | for plus_v in range(start_v, end_v):
624 | # ignore if a -1 index
625 | if plus_h - minus_x == -1 or plus_v - minus_y == -1:
626 | continue
627 | else:
628 | # Point 1 (start point + previous slot in
629 | # horizontal or vertical space index)
630 | p1x = bounds[0] + space_h[plus_h - minus_x]
631 | p1y = bounds[1] + space_v[plus_v - minus_y]
632 | p1 = cg.Point((p1x, p1y))
633 |
634 | # Point 2 (start point + current slot in
635 | # horizontal or vertical space index)
636 | p2x = bounds[0] + space_h[plus_h]
637 | p2y = bounds[1] + space_v[plus_v]
638 | p2 = cg.Point((p2x, p2y))
639 |
640 | # libpysal.cg.Chain
641 | chains.append(_chain_constr(None, [p1, p2]))
642 |
643 | return chains
644 |
645 |
646 | def _points_as_gdf(net, vertices, vertices_for_arcs, pp_name, snapped, id_col=None):
647 | """Internal function for returning a point ``geopandas.GeoDataFrame``
648 | called from within ``spaghetti.element_as_gdf()``.
649 |
650 | Parameters
651 | ----------
652 | vertices_for_arcs : bool
653 | Flag for points being an object returned (``False``) or for merely
654 | creating network arcs (``True``). Set from within the parent
655 | function (``spaghetti.element_as_gdf()``).
656 |
657 | Raises
658 | ------
659 |
660 | KeyError
661 | In order to extract a ``network.PointPattern`` it must already
662 | be a part of the network object. This exception is raised
663 | when a ``network.PointPattern`` is being extracted that does not
664 | exist within the network object.
665 |
666 | Returns
667 | -------
668 | points : geopandas.GeoDataFrame
669 | Network point elements (either vertices or ``network.PointPattern``
670 | points) as a simple ``geopandas.GeoDataFrame`` of
671 | ``shapely.geometry.Point`` objects with an ``"id"`` column and
672 | ``"geometry"`` column.
673 |
674 | Notes
675 | -----
676 |
677 | See ``spaghetti.element_as_gdf()`` for description of arguments.
678 |
679 | """
680 |
681 | # vertices / nodes
682 | if vertices or vertices_for_arcs:
683 | pts_dict = net.vertex_coords
684 |
685 | if pp_name:
686 | try:
687 | pp = net.pointpatterns[pp_name]
688 | except KeyError as err:
689 | err_msg = f"Available point patterns are {net.pointpatterns.keys()}"
690 | raise KeyError(err_msg) from err
691 |
692 | # raw point pattern
693 | if not snapped:
694 | pp_pts = pp.points
695 | n_pp_pts = range(len(pp_pts))
696 | pts_dict = {point: pp_pts[point]["coordinates"] for point in n_pp_pts}
697 |
698 | # snapped point pattern
699 | else:
700 | pts_dict = pp.snapped_coordinates
701 |
702 | # instantiate geopandas.GeoDataFrame
703 | points = geopandas.GeoDataFrame(
704 | pts_dict.keys(),
705 | columns=[id_col],
706 | geometry=shapely.points(numpy.asarray(list(pts_dict.values()))),
707 | )
708 |
709 | # additional columns
710 | if not pp_name:
711 | ncv_tag = "network_component_vertices"
712 | if hasattr(net, ncv_tag):
713 | ncv = getattr(net, ncv_tag)
714 | ncv_map = {v: k for k, verts in ncv.items() for v in verts}
715 | points["comp_label"] = points[id_col].map(ncv_map)
716 | if pp_name:
717 | c2o_tag = "component_to_obs"
718 | if hasattr(pp, c2o_tag):
719 | c2o = getattr(pp, c2o_tag)
720 | o2c_map = {o: c for c, obs in c2o.items() for o in obs}
721 | points["comp_label"] = points[id_col].map(o2c_map)
722 |
723 | return points
724 |
725 |
726 | def _arcs_as_gdf(net, points, id_col=None):
727 | """Internal function for returning an arc ``geopandas.GeoDataFrame``
728 | called from within ``spaghetti.element_as_gdf()``.
729 |
730 | Returns
731 | -------
732 | arcs : geopandas.GeoDataFrame
733 | Network arc elements as a ``geopandas.GeoDataFrame`` of
734 | ``shapely.geometry.LineString`` objects with an ``"id"``
735 | column and ``geometry`` column.
736 |
737 | Notes
738 | -----
739 |
740 | See ``spaghetti.element_as_gdf()`` for description of arguments.
741 |
742 | """
743 |
744 | def _line_coords(loc):
745 | indpoints = points.set_index(id_col, inplace=False)
746 | return (
747 | (indpoints.loc[loc[0]].geometry.x, indpoints.loc[loc[0]].geometry.y),
748 | (indpoints.loc[loc[1]].geometry.x, indpoints.loc[loc[1]].geometry.y),
749 | )
750 |
751 | # instantiate GeoDataFrame
752 | arcs = pandas.DataFrame(zip(sorted(net.arcs), strict=True), columns=[id_col])
753 | arcs = arcs.set_geometry(
754 | shapely.linestrings(arcs[id_col].map(_line_coords).values.tolist())
755 | )
756 |
757 | # additional columns
758 | if hasattr(net, "network_component_labels"):
759 | arcs["comp_label"] = net.network_component_labels
760 |
761 | return arcs
762 |
763 |
764 | def _routes_as_gdf(paths, id_col):
765 | """Internal function for returning a shortest paths
766 | ``geopandas.GeoDataFrame`` called from within
767 | ``spaghetti.element_as_gdf()``.
768 |
769 | Returns
770 | -------
771 | paths : geopandas.GeoDataFrame
772 | Network shortest paths as a ``geopandas.GeoDataFrame`` of
773 | ``shapely.geometry.LineString`` objects with an ``"O"`` (origin),
774 | ``D`` (destination), and ``geometry`` column. An additional
775 | column storing the ID as a tuple is available.
776 |
777 | Notes
778 | -----
779 |
780 | See ``spaghetti.element_as_gdf()`` for description of arguments.
781 |
782 | """
783 |
784 | # instantiate as a geodataframe
785 | paths = dict(paths)
786 | ids, geoms = (
787 | zip(paths.keys(), strict=True),
788 | [LineString(g.vertices) for g in paths.values()],
789 | )
790 | paths = geopandas.GeoDataFrame(ids, columns=[id_col], geometry=geoms)
791 |
792 | return paths
793 |
--------------------------------------------------------------------------------