Skip to content
Commits on Source (7)
{
"projectName": "pyproj",
"projectOwner": "snowman2",
"repoType": "github",
"repoHost": "https://github.com",
"files": [
"README.md"
],
"imageSize": 100,
"commit": true,
"commitConvention": "none",
"contributors": [
{
"login": "jswhit",
"name": "Jeff Whitaker",
"avatar_url": "https://avatars2.githubusercontent.com/u/579593?v=4",
"profile": "https://github.com/jswhit",
"contributions": [
"doc",
"test",
"code",
"example",
"ideas",
"review",
"question",
"maintenance",
"infra"
]
},
{
"login": "snowman2",
"name": "Alan D. Snow",
"avatar_url": "https://avatars3.githubusercontent.com/u/8699967?v=4",
"profile": "https://github.com/snowman2",
"contributions": [
"doc",
"test",
"code",
"example",
"maintenance",
"infra",
"ideas",
"review",
"question"
]
},
{
"login": "micahcochran",
"name": "Micah Cochran",
"avatar_url": "https://avatars0.githubusercontent.com/u/7433104?v=4",
"profile": "https://github.com/micahcochran",
"contributions": [
"doc",
"test",
"code",
"maintenance",
"infra",
"review",
"question"
]
},
{
"login": "jorisvandenbossche",
"name": "Joris Van den Bossche",
"avatar_url": "https://avatars2.githubusercontent.com/u/1020496?v=4",
"profile": "https://jorisvandenbossche.github.io/",
"contributions": [
"doc",
"code",
"ideas",
"review"
]
},
{
"login": "cjmayo",
"name": "Chris Mayo",
"avatar_url": "https://avatars1.githubusercontent.com/u/921089?v=4",
"profile": "https://github.com/cjmayo",
"contributions": [
"test"
]
},
{
"login": "cffk",
"name": "Charles Karney",
"avatar_url": "https://avatars1.githubusercontent.com/u/2298266?v=4",
"profile": "https://www.petrel.org",
"contributions": [
"code",
"test"
]
},
{
"login": "zippy1981",
"name": "Justin Dearing",
"avatar_url": "https://avatars3.githubusercontent.com/u/146930?v=4",
"profile": "http://www.justaprogrammer.net/profile/justin",
"contributions": [
"infra"
]
},
{
"login": "jdkloe",
"name": "Jos de Kloe",
"avatar_url": "https://avatars3.githubusercontent.com/u/1906112?v=4",
"profile": "https://github.com/jdkloe",
"contributions": [
"code",
"test"
]
},
{
"login": "georgeouzou",
"name": "George Ouzounoudis",
"avatar_url": "https://avatars3.githubusercontent.com/u/16732042?v=4",
"profile": "https://github.com/georgeouzou",
"contributions": [
"code",
"ideas"
]
},
{
"login": "djhoese",
"name": "David Hoese",
"avatar_url": "https://avatars3.githubusercontent.com/u/1828519?v=4",
"profile": "https://github.com/djhoese",
"contributions": [
"review",
"ideas"
]
},
{
"login": "mitkin",
"name": "Mikhail Itkin",
"avatar_url": "https://avatars3.githubusercontent.com/u/3927849?v=4",
"profile": "http://mitkin.github.io",
"contributions": [
"code"
]
},
{
"login": "dopplershift",
"name": "Ryan May",
"avatar_url": "https://avatars2.githubusercontent.com/u/221526?v=4",
"profile": "http://dopplershift.github.io",
"contributions": [
"code"
]
},
{
"login": "artttt",
"name": "artttt",
"avatar_url": "https://avatars3.githubusercontent.com/u/4626281?v=4",
"profile": "https://github.com/artttt",
"contributions": [
"ideas"
]
},
{
"login": "ocefpaf",
"name": "Filipe",
"avatar_url": "https://avatars1.githubusercontent.com/u/950575?v=4",
"profile": "http://ocefpaf.github.io/python4oceanographers",
"contributions": [
"infra",
"code",
"platform"
]
},
{
"login": "heitorPB",
"name": "Heitor",
"avatar_url": "https://avatars2.githubusercontent.com/u/13461702?v=4",
"profile": "https://github.com/heitorPB",
"contributions": [
"doc"
]
},
{
"login": "sebastic",
"name": "Bas Couwenberg",
"avatar_url": "https://avatars3.githubusercontent.com/u/4605306?v=4",
"profile": "https://github.com/sebastic",
"contributions": [
"code",
"platform"
]
},
{
"login": "nickeubank",
"name": "Nick Eubank",
"avatar_url": "https://avatars0.githubusercontent.com/u/9683693?v=4",
"profile": "https://github.com/nickeubank",
"contributions": [
"code"
]
},
{
"login": "mdunphy",
"name": "Michael Dunphy",
"avatar_url": "https://avatars3.githubusercontent.com/u/9088426?v=4",
"profile": "https://www.math.uwaterloo.ca/~mdunphy/",
"contributions": [
"doc"
]
},
{
"login": "matthew-brett",
"name": "Matthew Brett",
"avatar_url": "https://avatars2.githubusercontent.com/u/67612?v=4",
"profile": "http://matthew.dynevor.org",
"contributions": [
"infra",
"platform"
]
},
{
"login": "jdemaeyer",
"name": "Jakob de Maeyer ",
"avatar_url": "https://avatars1.githubusercontent.com/u/10531844?v=4",
"profile": "https://naboa.de",
"contributions": [
"code"
]
},
{
"login": "gitter-badger",
"name": "The Gitter Badger",
"avatar_url": "https://avatars2.githubusercontent.com/u/8518239?v=4",
"profile": "https://gitter.im",
"contributions": [
"doc"
]
},
{
"login": "bmwiedemann",
"name": "Bernhard M. Wiedemann",
"avatar_url": "https://avatars3.githubusercontent.com/u/637990?v=4",
"profile": "http://lizards.opensuse.org/author/bmwiedemann/",
"contributions": [
"code"
]
},
{
"login": "ReallyNiceGuy",
"name": "Marco Aurélio da Costa",
"avatar_url": "https://avatars0.githubusercontent.com/u/6545730?v=4",
"profile": "https://github.com/ReallyNiceGuy",
"contributions": [
"code"
]
},
{
"login": "ChrisBarker-NOAA",
"name": "Christopher H. Barker",
"avatar_url": "https://avatars2.githubusercontent.com/u/916576?v=4",
"profile": "https://github.com/ChrisBarker-NOAA",
"contributions": [
"code"
]
},
{
"login": "kbevers",
"name": "Kristian Evers",
"avatar_url": "https://avatars3.githubusercontent.com/u/13132571?v=4",
"profile": "https://evers.dev/",
"contributions": [
"question",
"ideas"
]
},
{
"login": "rouault",
"name": "Even Rouault",
"avatar_url": "https://avatars2.githubusercontent.com/u/1192433?v=4",
"profile": "http://www.spatialys.com/en/about/",
"contributions": [
"question"
]
},
{
"login": "cgohlke",
"name": "Christoph Gohlke",
"avatar_url": "https://avatars3.githubusercontent.com/u/483428?v=4",
"profile": "https://github.com/cgohlke",
"contributions": [
"platform"
]
},
{
"login": "chrrrisw",
"name": "Chris Willoughby",
"avatar_url": "https://avatars0.githubusercontent.com/u/5555320?v=4",
"profile": "https://github.com/chrrrisw",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7
}
......@@ -27,9 +27,6 @@ matrix:
env:
- PYTHON=3.6.8
- PROJSOURCE=6.1.1
- python: 2.7
env:
- PROJSOURCE=6.1.1
- python: 3.5
env:
- PROJSOURCE=6.1.1
......@@ -50,7 +47,9 @@ matrix:
allow_failures:
- python: "nightly"
- env: PROJSOURCE=git
env:
- PROJSOURCE=git
before_install:
- |
......@@ -75,6 +74,23 @@ before_install:
else
sudo apt-get install -qq sqlite3 libsqlite3-dev
fi
- |
if [[ "$TRAVIS_OS_NAME" == "osx" && -n "$PYPROJ_OMP" ]]; then
# install OpenMP not present by default on osx
brew install libomp
# enable OpenMP support for Apple-clang
export CC=/usr/bin/clang
export CXX=/usr/bin/clang++
export CPPFLAGS="$CPPFLAGS -Xpreprocessor -fopenmp"
export CFLAGS="$CFLAGS -I/usr/local/opt/libomp/include"
export CXXFLAGS="$CXXFLAGS -I/usr/local/opt/libomp/include"
export LDFLAGS="$LDFLAGS -L/usr/local/opt/libomp/lib -lomp"
export DYLD_LIBRARY_PATH=/usr/local/opt/libomp/lib
# avoid error due to multiple OpenMP libraries loaded simultaneously
export KMP_DUPLICATE_LIB_OK=TRUE
fi
- echo "PROJSOURCE is $PROJSOURCE"
# Download external PROJ.4 version and compile if not existing already
- export PROJ_DIR=$PROJ_BASE_DIR/proj-${PROJSOURCE:0:5}
......@@ -86,7 +102,7 @@ before_install:
install:
# coverage report requires a local install
- pip install pip>=10.0.1
- pip install 'pip>=10.0.1'
- make install-dev
- pip install coveralls
......
......@@ -192,6 +192,10 @@ running both the unit tests as well as the `flake8` code linter.
Once we're all happy with the pull request, it's time for it to get merged in. Only the
maintainers can merge pull requests and you should never merge a pull request you have commits on as it circumvents the code review. If this is your first or second pull request, we'll likely help by rebasing and cleaning up the commit history for you. As your developement skills increase, we'll help you learn how to do this.
## Allcontributors Recognition
We do our best to recognize contributions, but we may miss some. If we did, please let us know. Also, if you would prefer not to be recognized on the README, please let us know.
## More Questions?
If you're stuck somewhere or are interested in being a part of the community in
......
......@@ -63,7 +63,7 @@ lint: ## check style with flake8
check: lint ## flake8 black isort check
black --check setup.py pyproj/ test/ docs/
isort --recursive -m 3 -w 88 -tc -p test setup.py pyproj/ test/ docs/
isort --check --recursive -m 3 -w 88 -tc -p test setup.py pyproj/ test/ docs/
isort: ## order imports
isort --recursive -m 3 -w 88 -tc -p test setup.py pyproj/ test/ docs/
......
......@@ -4,6 +4,7 @@ Python interface to [PROJ](http://proj.org) (cartographic projections and coordi
<p align="center">
<a href="https://gitter.im/pyproj4-pyproj/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"><img alt="Join the chat at https://gitter.im/pyproj4-pyproj/community" src="https://badges.gitter.im/pyproj4-pyproj/community.svg"></a>
<a href="#contributors"><img alt="All Contributors" src="https://img.shields.io/badge/all_contributors-28-orange.svg?style=flat-square"></a>
<a href="https://travis-ci.org/pyproj4/pyproj"><img alt="Build Status" src="https://travis-ci.org/pyproj4/pyproj.svg"></a>
<a href="https://ci.appveyor.com/project/jswhit/pyproj"><img alt="Build Status" src="https://ci.appveyor.com/api/projects/status/8xkka4s97uwhkc64/branch/master?svg=true"></a>
<a href="https://coveralls.io/github/pyproj4/pyproj?branch=master"><img alt="Coverage Status" src="https://coveralls.io/repos/github/pyproj4/pyproj/badge.svg?branch=master"></a>
......@@ -25,3 +26,52 @@ Python interface to [PROJ](http://proj.org) (cartographic projections and coordi
- Report bugs/ask questions: https://github.com/pyproj4/pyproj/issues
- Ask developer questions: https://gitter.im/pyproj4-pyproj/community
- Ask the community: https://gis.stackexchange.com/questions/tagged/pyproj
## Contributors ✨
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore -->
<table>
<tr>
<td align="center"><a href="https://github.com/jswhit"><img src="https://avatars2.githubusercontent.com/u/579593?v=4" width="100px;" alt="Jeff Whitaker"/><br /><sub><b>Jeff Whitaker</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=jswhit" title="Documentation">📖</a> <a href="https://github.com/snowman2/pyproj/commits?author=jswhit" title="Tests">⚠️</a> <a href="https://github.com/snowman2/pyproj/commits?author=jswhit" title="Code">💻</a> <a href="#example-jswhit" title="Examples">💡</a> <a href="#ideas-jswhit" title="Ideas, Planning, & Feedback">🤔</a> <a href="#review-jswhit" title="Reviewed Pull Requests">👀</a> <a href="#question-jswhit" title="Answering Questions">💬</a> <a href="#maintenance-jswhit" title="Maintenance">🚧</a> <a href="#infra-jswhit" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center"><a href="https://www.linkedin.com/in/alan-snow-55bb8726/"><img src="https://avatars3.githubusercontent.com/u/8699967?v=4" width="100px;" alt="Alan D. Snow"/><br /><sub><b>Alan D. Snow</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=snowman2" title="Documentation">📖</a> <a href="https://github.com/snowman2/pyproj/commits?author=snowman2" title="Tests">⚠️</a> <a href="https://github.com/snowman2/pyproj/commits?author=snowman2" title="Code">💻</a> <a href="#example-snowman2" title="Examples">💡</a> <a href="#maintenance-snowman2" title="Maintenance">🚧</a> <a href="#infra-snowman2" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#ideas-snowman2" title="Ideas, Planning, & Feedback">🤔</a> <a href="#review-snowman2" title="Reviewed Pull Requests">👀</a> <a href="#question-snowman2" title="Answering Questions">💬</a></td>
<td align="center"><a href="https://github.com/micahcochran"><img src="https://avatars0.githubusercontent.com/u/7433104?v=4" width="100px;" alt="Micah Cochran"/><br /><sub><b>Micah Cochran</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=micahcochran" title="Documentation">📖</a> <a href="https://github.com/snowman2/pyproj/commits?author=micahcochran" title="Tests">⚠️</a> <a href="https://github.com/snowman2/pyproj/commits?author=micahcochran" title="Code">💻</a> <a href="#maintenance-micahcochran" title="Maintenance">🚧</a> <a href="#infra-micahcochran" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#review-micahcochran" title="Reviewed Pull Requests">👀</a> <a href="#question-micahcochran" title="Answering Questions">💬</a></td>
<td align="center"><a href="https://jorisvandenbossche.github.io/"><img src="https://avatars2.githubusercontent.com/u/1020496?v=4" width="100px;" alt="Joris Van den Bossche"/><br /><sub><b>Joris Van den Bossche</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=jorisvandenbossche" title="Documentation">📖</a> <a href="https://github.com/snowman2/pyproj/commits?author=jorisvandenbossche" title="Code">💻</a> <a href="#ideas-jorisvandenbossche" title="Ideas, Planning, & Feedback">🤔</a> <a href="#review-jorisvandenbossche" title="Reviewed Pull Requests">👀</a></td>
<td align="center"><a href="https://github.com/cjmayo"><img src="https://avatars1.githubusercontent.com/u/921089?v=4" width="100px;" alt="Chris Mayo"/><br /><sub><b>Chris Mayo</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=cjmayo" title="Tests">⚠️</a></td>
<td align="center"><a href="https://www.petrel.org"><img src="https://avatars1.githubusercontent.com/u/2298266?v=4" width="100px;" alt="Charles Karney"/><br /><sub><b>Charles Karney</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=cffk" title="Code">💻</a> <a href="https://github.com/snowman2/pyproj/commits?author=cffk" title="Tests">⚠️</a></td>
<td align="center"><a href="http://www.justaprogrammer.net/profile/justin"><img src="https://avatars3.githubusercontent.com/u/146930?v=4" width="100px;" alt="Justin Dearing"/><br /><sub><b>Justin Dearing</b></sub></a><br /><a href="#infra-zippy1981" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/jdkloe"><img src="https://avatars3.githubusercontent.com/u/1906112?v=4" width="100px;" alt="Jos de Kloe"/><br /><sub><b>Jos de Kloe</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=jdkloe" title="Code">💻</a> <a href="https://github.com/snowman2/pyproj/commits?author=jdkloe" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/georgeouzou"><img src="https://avatars3.githubusercontent.com/u/16732042?v=4" width="100px;" alt="George Ouzounoudis"/><br /><sub><b>George Ouzounoudis</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=georgeouzou" title="Code">💻</a> <a href="#ideas-georgeouzou" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://github.com/djhoese"><img src="https://avatars3.githubusercontent.com/u/1828519?v=4" width="100px;" alt="David Hoese"/><br /><sub><b>David Hoese</b></sub></a><br /><a href="#review-djhoese" title="Reviewed Pull Requests">👀</a> <a href="#ideas-djhoese" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="http://mitkin.github.io"><img src="https://avatars3.githubusercontent.com/u/3927849?v=4" width="100px;" alt="Mikhail Itkin"/><br /><sub><b>Mikhail Itkin</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=mitkin" title="Code">💻</a></td>
<td align="center"><a href="http://dopplershift.github.io"><img src="https://avatars2.githubusercontent.com/u/221526?v=4" width="100px;" alt="Ryan May"/><br /><sub><b>Ryan May</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=dopplershift" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/artttt"><img src="https://avatars3.githubusercontent.com/u/4626281?v=4" width="100px;" alt="artttt"/><br /><sub><b>artttt</b></sub></a><br /><a href="#ideas-artttt" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="http://ocefpaf.github.io/python4oceanographers"><img src="https://avatars1.githubusercontent.com/u/950575?v=4" width="100px;" alt="Filipe"/><br /><sub><b>Filipe</b></sub></a><br /><a href="#infra-ocefpaf" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/snowman2/pyproj/commits?author=ocefpaf" title="Code">💻</a> <a href="#platform-ocefpaf" title="Packaging/porting to new platform">📦</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/heitorPB"><img src="https://avatars2.githubusercontent.com/u/13461702?v=4" width="100px;" alt="Heitor"/><br /><sub><b>Heitor</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=heitorPB" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/sebastic"><img src="https://avatars3.githubusercontent.com/u/4605306?v=4" width="100px;" alt="Bas Couwenberg"/><br /><sub><b>Bas Couwenberg</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=sebastic" title="Code">💻</a> <a href="#platform-sebastic" title="Packaging/porting to new platform">📦</a></td>
<td align="center"><a href="https://github.com/nickeubank"><img src="https://avatars0.githubusercontent.com/u/9683693?v=4" width="100px;" alt="Nick Eubank"/><br /><sub><b>Nick Eubank</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=nickeubank" title="Code">💻</a></td>
<td align="center"><a href="https://www.math.uwaterloo.ca/~mdunphy/"><img src="https://avatars3.githubusercontent.com/u/9088426?v=4" width="100px;" alt="Michael Dunphy"/><br /><sub><b>Michael Dunphy</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=mdunphy" title="Documentation">📖</a></td>
<td align="center"><a href="http://matthew.dynevor.org"><img src="https://avatars2.githubusercontent.com/u/67612?v=4" width="100px;" alt="Matthew Brett"/><br /><sub><b>Matthew Brett</b></sub></a><br /><a href="#infra-matthew-brett" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#platform-matthew-brett" title="Packaging/porting to new platform">📦</a></td>
<td align="center"><a href="https://naboa.de"><img src="https://avatars1.githubusercontent.com/u/10531844?v=4" width="100px;" alt="Jakob de Maeyer "/><br /><sub><b>Jakob de Maeyer </b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=jdemaeyer" title="Code">💻</a></td>
<td align="center"><a href="https://gitter.im"><img src="https://avatars2.githubusercontent.com/u/8518239?v=4" width="100px;" alt="The Gitter Badger"/><br /><sub><b>The Gitter Badger</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=gitter-badger" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center"><a href="http://lizards.opensuse.org/author/bmwiedemann/"><img src="https://avatars3.githubusercontent.com/u/637990?v=4" width="100px;" alt="Bernhard M. Wiedemann"/><br /><sub><b>Bernhard M. Wiedemann</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=bmwiedemann" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/ReallyNiceGuy"><img src="https://avatars0.githubusercontent.com/u/6545730?v=4" width="100px;" alt="Marco Aurélio da Costa"/><br /><sub><b>Marco Aurélio da Costa</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=ReallyNiceGuy" title="Code">💻</a></td>
<td align="center"><a href="http://response.restoration.noaa.gov"><img src="https://avatars2.githubusercontent.com/u/916576?v=4" width="100px;" alt="Chris Barker"/><br /><sub><b>Chris Barker</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=ChrisBarker-NOAA" title="Code">💻</a></td>
<td align="center"><a href="https://evers.dev/"><img src="https://avatars3.githubusercontent.com/u/13132571?v=4" width="100px;" alt="Kristian Evers"/><br /><sub><b>Kristian Evers</b></sub></a><br /><a href="#question-kbevers" title="Answering Questions">💬</a> <a href="#ideas-kbevers" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="http://www.spatialys.com/en/about/"><img src="https://avatars2.githubusercontent.com/u/1192433?v=4" width="100px;" alt="Even Rouault"/><br /><sub><b>Even Rouault</b></sub></a><br /><a href="#question-rouault" title="Answering Questions">💬</a></td>
<td align="center"><a href="https://github.com/cgohlke"><img src="https://avatars3.githubusercontent.com/u/483428?v=4" width="100px;" alt="Christoph Gohlke"/><br /><sub><b>Christoph Gohlke</b></sub></a><br /><a href="#platform-cgohlke" title="Packaging/porting to new platform">📦</a></td>
<td align="center"><a href="https://github.com/chrrrisw"><img src="https://avatars0.githubusercontent.com/u/5555320?v=4" width="100px;" alt="Chris Willoughby"/><br /><sub><b>Chris Willoughby</b></sub></a><br /><a href="https://github.com/snowman2/pyproj/commits?author=chrrrisw" title="Code">💻</a></td>
</tr>
</table>
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
\ No newline at end of file
......@@ -28,7 +28,7 @@ environment:
VS_VERSION: Visual Studio 14
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
PROJSOURCE: 6.1.1
# - PYTHON: "C:\\Python37-x64"
# - PYTHON: "C:\\Python37-x64"
# PYTHON_VERSION: "3.7"
# PYTHON_ARCH: "64"
# VS_VERSION: Visual Studio 14
......@@ -40,9 +40,14 @@ environment:
# VS_VERSION: Visual Studio 14
# APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
# PROJSOURCE: git
matrix:
allow_failures:
- PROJSOURCE: git
# matrix:
# allow_failures:
# - PYTHON: "C:\\Python36-x64"
# PYTHON_VERSION: "3.6"
# PYTHON_ARCH: "64"
# VS_VERSION: Visual Studio 14
# APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
# PROJSOURCE: git
shallow_clone: true
......@@ -118,6 +123,12 @@ install:
# install wheel, caching
- "%CMD_IN_ENV% pip install wheel"
# update vcpkg
- cmd: |
cd "C:\Tools\vcpkg"
git pull
.\bootstrap-vcpkg.bat
cd %APPVEYOR_BUILD_FOLDER%
test_script:
# Run the project tests
......
python-pyproj (2.3.0+ds-1~exp1) experimental; urgency=medium
* New upstream release.
* Drop Python 2 package, no longer supported upstream.
* Add python3-shapely to build dependencies.
* Ignore test_datadir.py, causes FTBFS, see:
https://github.com/pyproj4/pyproj/issues/400
-- Bas Couwenberg <sebastic@debian.org> Mon, 19 Aug 2019 16:48:49 +0200
python-pyproj (2.2.2+ds-1~exp2) experimental; urgency=medium
* Drop aenum.patch, only required for Python < 3.6.
......
......@@ -10,39 +10,18 @@ Build-Depends: debhelper (>= 9),
cython3,
libproj-dev (>= 6.0.0),
proj-bin (>= 6.0.0),
python-all-dev,
python-setuptools,
python-mock,
python-numpy,
python-pytest,
python-pytest-cov,
python3-all-dev,
python3-setuptools,
python3-mock,
python3-numpy,
python3-pytest,
python3-pytest-cov
python3-pytest-cov,
python3-shapely
Standards-Version: 4.4.0
Vcs-Browser: https://salsa.debian.org/debian-gis-team/python-pyproj
Vcs-Git: https://salsa.debian.org/debian-gis-team/python-pyproj.git
Homepage: https://github.com/pyproj4/pyproj
Package: python-pyproj
Architecture: any
Depends: ${python:Depends},
${shlibs:Depends},
${misc:Depends},
proj-data
Provides: ${python:Provides}
Description: Python interface to PROJ library
PROJ performs cartographic transformations between geographic (lat/lon)
and map projection (x/y) coordinates. It can also transform directly
from one map projection coordinate system to another.
.
This is a Python binding to PROJ, it can receive coordinates as numpy
arrays, Python arrays, lists or scalars. This module is optimized for
numpy arrays.
Package: python3-pyproj
Architecture: any
Depends: ${python3:Depends},
......
......@@ -9,7 +9,7 @@ export DEB_BUILD_MAINT_OPTIONS=hardening=+all
export PYBUILD_NAME=pyproj
export PYBUILD_TEST_PYTEST=1
export PYBUILD_DISABLE=test/python2
export PYBUILD_TEST_ARGS=-v --ignore=test/test_datadir.py
# Path to system installed PROJ data.
export PROJ_DIR=/usr
......@@ -19,7 +19,7 @@ include /usr/share/dpkg/architecture.mk
%:
dh $@ \
--with python2,python3 \
--with python3 \
--buildsystem=pybuild \
--parallel
......@@ -35,10 +35,6 @@ endif
override_dh_install:
dh_install --list-missing
override_dh_python2:
dh_python2 -ppython-pyproj
dh_numpy -ppython-pyproj
override_dh_python3:
dh_python3 -ppython3-pyproj
dh_numpy3 -ppython3-pyproj
......@@ -26,7 +26,7 @@ numpy array objects).
Download: http://python.org/pypi/pyproj
Requirements: Python 2.7 or 3.5+.
Requirements: Python 3.5+.
Example scripts are in 'test' subdirectory of source distribution.
The 'test()' function will run the examples in the docstrings.
......@@ -47,7 +47,7 @@ CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """
__version__ = "2.2.2"
__version__ = "2.3.0"
__all__ = [
"Proj",
"Geod",
......
......@@ -10,7 +10,7 @@ cdef class Axis:
cdef readonly object unit_code
@staticmethod
cdef create(PJ_CONTEXT* projcontext, PJ* projobj, int index)
cdef create(PJ* projobj, int index)
cdef class AreaOfUse:
cdef readonly double west
......@@ -20,12 +20,11 @@ cdef class AreaOfUse:
cdef readonly object name
@staticmethod
cdef create(PJ_CONTEXT* projcontext, PJ* projobj)
cdef create(PJ* projobj)
cdef class Base:
cdef PJ *projobj
cdef PJ_CONTEXT *projctx
cdef readonly object name
......@@ -75,7 +74,7 @@ cdef class Param:
cdef readonly object unit_category
@staticmethod
cdef create(PJ_CONTEXT* projcontext, PJ* projobj, int param_idx)
cdef create(PJ* projobj, int param_idx)
cdef class Grid:
......@@ -88,12 +87,13 @@ cdef class Grid:
cdef readonly object available
@staticmethod
cdef create(PJ_CONTEXT* projcontext, PJ* projobj, int grid_idx)
cdef create(PJ* projobj, int grid_idx)
cdef class CoordinateOperation(Base):
cdef readonly object _params
cdef readonly object _grids
cdef readonly object _area_of_use
cdef readonly object method_name
cdef readonly object method_auth_name
cdef readonly object method_code
......@@ -109,16 +109,15 @@ cdef class CoordinateOperation(Base):
cdef class _CRS(Base):
cdef PJ_TYPE _type
cdef PJ_PROJ_INFO projpj_info
cdef char *pjinitstring
cdef readonly object srs
cdef readonly object type_name
cdef object _ellipsoid
cdef object _area_of_use
cdef object _prime_meridian
cdef object _datum
cdef object _sub_crs_list
cdef object _source_crs
cdef object _target_crs
cdef object _geodetic_crs
cdef object _coordinate_system
cdef object _coordinate_operation
\ No newline at end of file
cdef readonly object _ellipsoid
cdef readonly object _area_of_use
cdef readonly object _prime_meridian
cdef readonly object _datum
cdef readonly object _sub_crs_list
cdef readonly object _source_crs
cdef readonly object _target_crs
cdef readonly object _geodetic_crs
cdef readonly object _coordinate_system
cdef readonly object _coordinate_operation
......@@ -3,7 +3,7 @@ import warnings
from collections import OrderedDict
from pyproj.compat import cstrencode, pystrdecode
from pyproj._datadir cimport get_pyproj_context
from pyproj._datadir cimport PROJ_CONTEXT
from pyproj.enums import WktVersion, ProjVersion
from pyproj.exceptions import CRSError
......@@ -54,13 +54,12 @@ def is_proj(proj_string):
return not is_wkt(proj_string) and "=" in proj_string
cdef _to_wkt(PJ_CONTEXT* projctx, PJ* projobj, version=WktVersion.WKT2_2018, pretty=False):
cdef _to_wkt(PJ* projobj, version=WktVersion.WKT2_2018, pretty=False):
"""
Convert a PJ object to a wkt string.
Parameters
----------
projctx: PJ_CONTEXT*
projobj: PJ*
wkt_out_type: PJ_WKT_TYPE
pretty: bool
......@@ -79,7 +78,7 @@ cdef _to_wkt(PJ_CONTEXT* projctx, PJ* projobj, version=WktVersion.WKT2_2018, pre
WktVersion.WKT1_ESRI: PJ_WKT1_ESRI
}
cdef PJ_WKT_TYPE wkt_out_type
wkt_out_type = supported_wkt_types[WktVersion(version)]
wkt_out_type = supported_wkt_types[WktVersion.create(version)]
cdef const char* options_wkt[2]
multiline = b"MULTILINE=NO"
......@@ -89,14 +88,14 @@ cdef _to_wkt(PJ_CONTEXT* projctx, PJ* projobj, version=WktVersion.WKT2_2018, pre
options_wkt[1] = NULL
cdef const char* proj_string
proj_string = proj_as_wkt(
projctx,
PROJ_CONTEXT.context,
projobj,
wkt_out_type,
options_wkt)
return cstrdecode(proj_string)
cdef _to_proj4(PJ_CONTEXT* projctx, PJ* projobj, version):
cdef _to_proj4(PJ* projobj, version):
"""
Convert the projection to a PROJ string.
......@@ -115,12 +114,12 @@ cdef _to_proj4(PJ_CONTEXT* projctx, PJ* projobj, version):
ProjVersion.PROJ_5: PJ_PROJ_5,
}
cdef PJ_PROJ_STRING_TYPE proj_out_type
proj_out_type = supported_prj_types[ProjVersion(version)]
proj_out_type = supported_prj_types[ProjVersion.create(version)]
# convert projection to string
cdef const char* proj_string
proj_string = proj_as_proj_string(
projctx,
PROJ_CONTEXT.context,
projobj,
proj_out_type,
NULL)
......@@ -136,7 +135,7 @@ cdef PJ* _from_authority(
b_code = cstrencode(str(code))
cdef char *c_code = b_code
return proj_create_from_database(
get_pyproj_context(),
PROJ_CONTEXT.context,
c_auth_name,
c_code,
category,
......@@ -148,7 +147,7 @@ cdef PJ* _from_authority(
cdef PJ* _from_string(proj_string, expected_types):
CRSError.clear()
cdef PJ* base_pj = proj_create(
get_pyproj_context(),
PROJ_CONTEXT.context,
cstrencode(proj_string)
)
if base_pj is NULL:
......@@ -205,7 +204,7 @@ cdef class Axis:
)
@staticmethod
cdef create(PJ_CONTEXT* projcontext, PJ* projobj, int index):
cdef create(PJ* projobj, int index):
cdef Axis axis_info = Axis()
cdef const char * name = NULL
cdef const char * abbrev = NULL
......@@ -214,7 +213,7 @@ cdef class Axis:
cdef const char * unit_auth_code = NULL
cdef const char * unit_code = NULL
if not proj_cs_get_axis_info(
projcontext,
PROJ_CONTEXT.context,
projobj,
index,
&name,
......@@ -275,11 +274,11 @@ cdef class AreaOfUse:
)
@staticmethod
cdef create(PJ_CONTEXT* projcontext, PJ* projobj):
cdef create(PJ* projobj):
cdef AreaOfUse area_of_use = AreaOfUse()
cdef const char * area_name = NULL
if not proj_get_area_of_use(
projcontext,
PROJ_CONTEXT.context,
projobj,
&area_of_use.west,
&area_of_use.south,
......@@ -298,18 +297,13 @@ cdef class AreaOfUse:
cdef class Base:
def __cinit__(self):
self.projobj = NULL
self.projctx = NULL
self.name = "undefined"
def __dealloc__(self):
"""destroy projection definition"""
if self.projobj != NULL:
proj_destroy(self.projobj)
if self.projctx != NULL:
proj_context_destroy(self.projctx)
def __init__(self):
self.projctx = get_pyproj_context()
self.projobj = NULL
def _set_name(self):
"""
......@@ -344,7 +338,7 @@ cdef class Base:
-------
str: The WKT string.
"""
return _to_wkt(self.projctx, self.projobj, version, pretty=pretty)
return _to_wkt(self.projobj, version, pretty=pretty)
def __str__(self):
return self.name
......@@ -403,7 +397,7 @@ cdef class CoordinateSystem(Base):
cdef CoordinateSystem coord_system = CoordinateSystem()
coord_system.projobj = coord_system_pj
cdef PJ_COORDINATE_SYSTEM_TYPE cs_type = proj_cs_get_type(
coord_system.projctx,
PROJ_CONTEXT.context,
coord_system.projobj,
)
try:
......@@ -424,13 +418,12 @@ cdef class CoordinateSystem(Base):
self._axis_list = []
cdef int num_axes = 0
num_axes = proj_cs_get_axis_count(
self.projctx,
PROJ_CONTEXT.context,
self.projobj
)
for axis_idx from 0 <= axis_idx < num_axes:
self._axis_list.append(
Axis.create(
self.projctx,
self.projobj,
axis_idx
)
......@@ -467,7 +460,7 @@ cdef class Ellipsoid(Base):
cdef int is_semi_minor_computed = 0
try:
proj_ellipsoid_get_parameters(
ellips.projctx,
PROJ_CONTEXT.context,
ellips.projobj,
&ellips._semi_major_metre,
&ellips._semi_minor_metre,
......@@ -619,7 +612,7 @@ cdef class PrimeMeridian(Base):
prime_meridian.projobj = prime_meridian_pj
cdef const char * unit_name
proj_prime_meridian_get_parameters(
prime_meridian.projctx,
PROJ_CONTEXT.context,
prime_meridian.projobj,
&prime_meridian.longitude,
&prime_meridian.unit_conversion_factor,
......@@ -820,7 +813,10 @@ cdef class Datum(Base):
"""
if self._ellipsoid is not None:
return None if self._ellipsoid is False else self._ellipsoid
cdef PJ* ellipsoid_pj = proj_get_ellipsoid(self.projctx, self.projobj)
cdef PJ* ellipsoid_pj = proj_get_ellipsoid(
PROJ_CONTEXT.context,
self.projobj,
)
if ellipsoid_pj == NULL:
self._ellipsoid = False
return None
......@@ -836,7 +832,10 @@ cdef class Datum(Base):
"""
if self._prime_meridian is not None:
return None if self._prime_meridian is False else self._prime_meridian
cdef PJ* prime_meridian_pj = proj_get_prime_meridian(self.projctx, self.projobj)
cdef PJ* prime_meridian_pj = proj_get_prime_meridian(
PROJ_CONTEXT.context,
self.projobj,
)
if prime_meridian_pj == NULL:
self._prime_meridian = False
return None
......@@ -883,7 +882,7 @@ cdef class Param:
self.unit_category = "undefined"
@staticmethod
cdef create(PJ_CONTEXT* projcontext, PJ* projobj, int param_idx):
cdef create(PJ* projobj, int param_idx):
cdef Param param = Param()
cdef char *out_name
cdef char *out_auth_name
......@@ -896,7 +895,7 @@ cdef class Param:
cdef char *out_unit_category
cdef double value_double
proj_coordoperation_get_param(
projcontext,
PROJ_CONTEXT.context,
projobj,
param_idx,
&out_name,
......@@ -972,7 +971,7 @@ cdef class Grid:
self.available = False
@staticmethod
cdef create(PJ_CONTEXT* projcontext, PJ* projobj, int grid_idx):
cdef create(PJ* projobj, int grid_idx):
cdef Grid grid = Grid()
cdef char *out_short_name
cdef char *out_full_name
......@@ -982,7 +981,7 @@ cdef class Grid:
cdef int open_license = 0
cdef int available = 0
proj_coordoperation_get_grid_used(
projcontext,
PROJ_CONTEXT.context,
projobj,
grid_idx,
&out_short_name,
......@@ -1046,6 +1045,7 @@ cdef class CoordinateOperation(Base):
def __cinit__(self):
self._params = None
self._grids = None
self._area_of_use = None
self.method_name = "undefined"
self.method_auth_name = "undefined"
self.method_code = "undefined"
......@@ -1062,7 +1062,7 @@ cdef class CoordinateOperation(Base):
cdef char *out_method_auth_name = NULL
cdef char *out_method_code = NULL
proj_coordoperation_get_method_info(
coord_operation.projctx,
PROJ_CONTEXT.context,
coord_operation.projobj,
&out_method_name,
&out_method_auth_name,
......@@ -1073,16 +1073,16 @@ cdef class CoordinateOperation(Base):
coord_operation.method_auth_name = decode_or_undefined(out_method_auth_name)
coord_operation.method_code = decode_or_undefined(out_method_code)
coord_operation.accuracy = proj_coordoperation_get_accuracy(
coord_operation.projctx,
PROJ_CONTEXT.context,
coord_operation.projobj
)
coord_operation.is_instantiable = proj_coordoperation_is_instantiable(
coord_operation.projctx,
PROJ_CONTEXT.context,
coord_operation.projobj
) == 1
coord_operation.has_ballpark_transformation = \
proj_coordoperation_has_ballpark_transformation(
coord_operation.projctx,
PROJ_CONTEXT.context,
coord_operation.projobj
) == 1
......@@ -1185,13 +1185,12 @@ cdef class CoordinateOperation(Base):
self._params = []
cdef int num_params = 0
num_params = proj_coordoperation_get_param_count(
self.projctx,
PROJ_CONTEXT.context,
self.projobj
)
for param_idx from 0 <= param_idx < num_params:
self._params.append(
Param.create(
self.projctx,
self.projobj,
param_idx
)
......@@ -1210,19 +1209,30 @@ cdef class CoordinateOperation(Base):
self._grids = []
cdef int num_grids = 0
num_grids = proj_coordoperation_get_grid_used_count(
self.projctx,
PROJ_CONTEXT.context,
self.projobj
)
for grid_idx from 0 <= grid_idx < num_grids:
self._grids.append(
Grid.create(
self.projctx,
self.projobj,
grid_idx
)
)
return self._grids
@property
def area_of_use(self):
"""
Returns
-------
AreaOfUse: The area of use object with associated attributes.
"""
if self._area_of_use is not None:
return self._area_of_use
self._area_of_use = AreaOfUse.create(self.projobj)
return self._area_of_use
def to_proj4(self, version=ProjVersion.PROJ_5):
"""
Convert the projection to a PROJ string.
......@@ -1237,7 +1247,7 @@ cdef class CoordinateOperation(Base):
-------
str: The PROJ string.
"""
return _to_proj4(self.projctx, self.projobj, version)
return _to_proj4(self.projobj, version)
@property
def towgs84(self):
......@@ -1305,9 +1315,11 @@ cdef class _CRS(Base):
self.type_name = "undefined"
def __init__(self, proj_string):
self.projctx = get_pyproj_context()
# initialize projection
self.projobj = proj_create(self.projctx, cstrencode(proj_string))
self.projobj = proj_create(
PROJ_CONTEXT.context,
cstrencode(proj_string),
)
if self.projobj is NULL:
raise CRSError(
"Invalid projection: {}".format(pystrdecode(proj_string)))
......@@ -1338,7 +1350,7 @@ cdef class _CRS(Base):
"""
if self._area_of_use is not None:
return self._area_of_use
self._area_of_use = AreaOfUse.create(self.projctx, self.projobj)
self._area_of_use = AreaOfUse.create(self.projobj)
return self._area_of_use
@property
......@@ -1350,7 +1362,10 @@ cdef class _CRS(Base):
"""
if self._ellipsoid is not None:
return None if self._ellipsoid is False else self._ellipsoid
cdef PJ* ellipsoid_pj = proj_get_ellipsoid(self.projctx, self.projobj)
cdef PJ* ellipsoid_pj = proj_get_ellipsoid(
PROJ_CONTEXT.context,
self.projobj
)
if ellipsoid_pj == NULL:
self._ellipsoid = False
return None
......@@ -1366,7 +1381,10 @@ cdef class _CRS(Base):
"""
if self._prime_meridian is not None:
return None if self._prime_meridian is True else self._prime_meridian
cdef PJ* prime_meridian_pj = proj_get_prime_meridian(self.projctx, self.projobj)
cdef PJ* prime_meridian_pj = proj_get_prime_meridian(
PROJ_CONTEXT.context,
self.projobj,
)
if prime_meridian_pj == NULL:
self._prime_meridian = False
return None
......@@ -1382,9 +1400,12 @@ cdef class _CRS(Base):
"""
if self._datum is not None:
return None if self._datum is False else self._datum
cdef PJ* datum_pj = proj_crs_get_datum(self.projctx, self.projobj)
cdef PJ* datum_pj = proj_crs_get_datum(PROJ_CONTEXT.context, self.projobj)
if datum_pj == NULL:
datum_pj = proj_crs_get_horizontal_datum(self.projctx, self.projobj)
datum_pj = proj_crs_get_horizontal_datum(
PROJ_CONTEXT.context,
self.projobj,
)
if datum_pj == NULL:
self._datum = False
return None
......@@ -1402,7 +1423,7 @@ cdef class _CRS(Base):
return None if self._coordinate_system is False else self._coordinate_system
cdef PJ* coord_system_pj = proj_crs_get_coordinate_system(
self.projctx,
PROJ_CONTEXT.context,
self.projobj
)
if coord_system_pj == NULL:
......@@ -1423,7 +1444,7 @@ cdef class _CRS(Base):
return None if self._coordinate_operation is False else self._coordinate_operation
cdef PJ* coord_pj = NULL
coord_pj = proj_crs_get_coordoperation(
self.projctx,
PROJ_CONTEXT.context,
self.projobj
)
if coord_pj == NULL:
......@@ -1443,12 +1464,12 @@ cdef class _CRS(Base):
if self._source_crs is not None:
return None if self._source_crs is False else self._source_crs
cdef PJ * projobj
projobj = proj_get_source_crs(self.projctx, self.projobj)
projobj = proj_get_source_crs(PROJ_CONTEXT.context, self.projobj)
if projobj == NULL:
self._source_crs = False
return None
try:
self._source_crs = self.__class__(_to_wkt(self.projctx, projobj))
self._source_crs = self.__class__(_to_wkt(projobj))
finally:
proj_destroy(projobj)
return self._source_crs
......@@ -1463,12 +1484,12 @@ cdef class _CRS(Base):
if self._target_crs is not None:
return None if self._target_crs is False else self._target_crs
cdef PJ * projobj
projobj = proj_get_target_crs(self.projctx, self.projobj)
projobj = proj_get_target_crs(PROJ_CONTEXT.context, self.projobj)
if projobj == NULL:
self._target_crs = False
return None
try:
self._target_crs = self.__class__(_to_wkt(self.projctx, projobj))
self._target_crs = self.__class__(_to_wkt(projobj))
finally:
proj_destroy(projobj)
return self._target_crs
......@@ -1485,15 +1506,19 @@ cdef class _CRS(Base):
if self._sub_crs_list is not None:
return self._sub_crs_list
cdef int iii = 0
cdef PJ * projobj = proj_crs_get_sub_crs(self.projctx, self.projobj, iii)
cdef PJ * projobj = proj_crs_get_sub_crs(
PROJ_CONTEXT.context,
self.projobj,
iii,
)
self._sub_crs_list = []
while projobj != NULL:
try:
self._sub_crs_list.append(self.__class__(_to_wkt(self.projctx, projobj)))
self._sub_crs_list.append(self.__class__(_to_wkt(projobj)))
finally:
proj_destroy(projobj) # deallocate temp proj
iii += 1
projobj = proj_crs_get_sub_crs(self.projctx, self.projobj, iii)
projobj = proj_crs_get_sub_crs(PROJ_CONTEXT.context, self.projobj, iii)
return self._sub_crs_list
......@@ -1507,12 +1532,12 @@ cdef class _CRS(Base):
if self._geodetic_crs is not None:
return self._geodetic_crs if self. _geodetic_crs is not False else None
cdef PJ * projobj
projobj = proj_crs_get_geodetic_crs(self.projctx, self.projobj)
projobj = proj_crs_get_geodetic_crs(PROJ_CONTEXT.context, self.projobj)
if projobj == NULL:
self._geodetic_crs = False
return None
try:
self._geodetic_crs = self.__class__(_to_wkt(self.projctx, projobj))
self._geodetic_crs = self.__class__(_to_wkt(projobj))
return self._geodetic_crs
finally:
proj_destroy(projobj) # deallocate temp proj
......@@ -1536,21 +1561,7 @@ cdef class _CRS(Base):
-------
str: The PROJ string.
"""
return _to_proj4(self.projctx, self.projobj, version)
def to_geodetic(self):
"""
.. note:: This is replaced with :attr:`CRS.geodetic_crs`
Returns
-------
pyproj.CRS: The geodetic CRS from this CRS.
"""
warnings.warn(
"This method is deprecated an has been replaced with `CRS.geodetic_crs`.",
DeprecationWarning,
)
return self.geodetic_crs
return _to_proj4(self.projobj, version)
def to_epsg(self, min_confidence=70):
"""
......@@ -1579,6 +1590,8 @@ cdef class _CRS(Base):
----------
min_confidence: int, optional
A value between 0-100 where 100 is the most confident. Default is 70.
:ref:`min_confidence`
Returns
-------
......@@ -1621,6 +1634,7 @@ cdef class _CRS(Base):
The name of the authority to filter by.
min_confidence: int, optional
A value between 0-100 where 100 is the most confident. Default is 70.
:ref:`min_confidence`
Returns
-------
......@@ -1639,7 +1653,8 @@ cdef class _CRS(Base):
user_auth_name = b_auth_name
try:
proj_list = proj_identify(self.projctx,
proj_list = proj_identify(
PROJ_CONTEXT.context,
self.projobj,
user_auth_name,
NULL,
......@@ -1662,7 +1677,7 @@ cdef class _CRS(Base):
# retrieve the best matching projection
cdef PJ* proj
try:
proj = proj_list_get(self.projctx, proj_list, 0)
proj = proj_list_get(PROJ_CONTEXT.context, proj_list, 0)
finally:
proj_list_destroy(proj_list)
if proj == NULL:
......@@ -1779,19 +1794,6 @@ cdef class _CRS(Base):
"""
return self._type == PJ_TYPE_BOUND_CRS
@property
def is_valid(self):
"""
Returns
-------
bool: True if CRS is valid.
"""
warnings.warn(
"CRS.is_valid is deprecated.",
DeprecationWarning,
)
return self._type != PJ_TYPE_UNKNOWN
@property
def is_engineering(self):
"""
......
include "proj.pxi"
cdef PJ_CONTEXT* get_pyproj_context() except *
cdef ContextManager PROJ_CONTEXT
cdef class ContextManager:
cdef PJ_CONTEXT *context
......@@ -14,24 +14,36 @@ cdef void pyproj_log_function(void *user_data, int level, const char *error_msg)
ProjError.internal_proj_error = pystrdecode(error_msg)
cdef PJ_CONTEXT* get_pyproj_context() except *:
data_dir = get_data_dir()
data_dir_list = data_dir.split(os.pathsep)
cdef PJ_CONTEXT* pyproj_context = NULL
cdef char **c_data_dir = <char **>malloc(len(data_dir_list) * sizeof(char*))
try:
pyproj_context = proj_context_create()
for iii in range(len(data_dir_list)):
b_data_dir = cstrencode(data_dir_list[iii])
c_data_dir[iii] = b_data_dir
proj_context_set_search_paths(pyproj_context, len(data_dir_list), c_data_dir)
except:
if pyproj_context != NULL:
proj_context_destroy(pyproj_context)
raise
finally:
free(c_data_dir)
proj_context_use_proj4_init_rules(pyproj_context, 1)
proj_log_func(pyproj_context, NULL, pyproj_log_function)
return pyproj_context
cdef class ContextManager:
def __cinit__(self):
self.context = NULL
def __dealloc__(self):
if self.context != NULL:
proj_context_destroy(self.context)
self.context = NULL
def __init__(self):
self.context = proj_context_create()
self.set_search_paths()
proj_context_use_proj4_init_rules(self.context, 1)
proj_log_func(self.context, NULL, pyproj_log_function)
def set_search_paths(self):
"""
This method sets the search paths
based on pyproj.datadir.get_data_dir()
"""
data_dir_list = get_data_dir().split(os.pathsep)
cdef char **c_data_dir = <char **>malloc(len(data_dir_list) * sizeof(char*))
try:
for iii in range(len(data_dir_list)):
b_data_dir = cstrencode(data_dir_list[iii])
c_data_dir[iii] = b_data_dir
proj_context_set_search_paths(self.context, len(data_dir_list), c_data_dir)
finally:
free(c_data_dir)
cdef ContextManager PROJ_CONTEXT = ContextManager()
PYPROJ_CONTEXT = PROJ_CONTEXT
......@@ -14,7 +14,11 @@ cdef extern from "geodesic.h":
geod_geodesic* g,
double lat1, double lon1, double azi1, unsigned caps)
void geod_position(geod_geodesicline* l, double s12,
double* plat2, double* plon2, double* pazi2);
double* plat2, double* plon2, double* pazi2)
void geod_polygonarea(geod_geodesic* g,
double lats[], double lons[], int n,
double* pA, double* pP)
cdef enum:
GEODESIC_VERSION_MAJOR
GEODESIC_VERSION_MINOR
......
include "base.pxi"
cimport cython
from pyproj.compat import cstrencode, pystrdecode
from pyproj.exceptions import GeodError
......@@ -28,14 +30,16 @@ cdef class Geod:
"""special method that allows pyproj.Geod instance to be pickled"""
return self.__class__,(self.initstring,)
def _fwd(self, object lons, object lats, object az, object dist, radians=False):
@cython.boundscheck(False)
@cython.wraparound(False)
def _fwd(self, object lons, object lats, object az, object dist, bint radians=False):
"""
forward transformation - determine longitude, latitude and back azimuth
of a terminus point given an initial point longitude and latitude, plus
forward azimuth and distance.
if radians=True, lons/lats are radians instead of degrees.
forward transformation - determine longitude, latitude and back azimuth
of a terminus point given an initial point longitude and latitude, plus
forward azimuth and distance.
if radians=True, lons/lats are radians instead of degrees.
"""
cdef Py_ssize_t buflenlons, buflenlats, buflenaz, buflend, ndim, i
cdef Py_ssize_t buflenlons, buflenlats, buflenaz, buflend, ndim, iii
cdef double lat1,lon1,az1,s12,plon2,plat2,pazi2
cdef double *lonsdata
cdef double *latsdata
......@@ -62,42 +66,44 @@ cdef class Geod:
latsdata = <double *>latdata
azdata = <double *>azdat
distdata = <double *>distdat
for i from 0 <= i < ndim:
for iii in range(ndim):
if not radians:
lon1 = lonsdata[i]
lat1 = latsdata[i]
az1 = azdata[i]
s12 = distdata[i]
lon1 = lonsdata[iii]
lat1 = latsdata[iii]
az1 = azdata[iii]
s12 = distdata[iii]
else:
lon1 = _RAD2DG*lonsdata[i]
lat1 = _RAD2DG*latsdata[i]
az1 = _RAD2DG*azdata[i]
s12 = distdata[i]
lon1 = _RAD2DG * lonsdata[iii]
lat1 = _RAD2DG * latsdata[iii]
az1 = _RAD2DG * azdata[iii]
s12 = distdata[iii]
geod_direct(&self._geod_geodesic, lat1, lon1, az1, s12,\
&plat2, &plon2, &pazi2)
# back azimuth needs to be flipped 180 degrees
# to match what proj4 geod utility produces.
if pazi2 > 0:
pazi2 = pazi2-180.
pazi2 = pazi2 - 180.
elif pazi2 <= 0:
pazi2 = pazi2+180.
pazi2 = pazi2 + 180.
if not radians:
lonsdata[i] = plon2
latsdata[i] = plat2
azdata[i] = pazi2
lonsdata[iii] = plon2
latsdata[iii] = plat2
azdata[iii] = pazi2
else:
lonsdata[i] = _DG2RAD*plon2
latsdata[i] = _DG2RAD*plat2
azdata[i] = _DG2RAD*pazi2
lonsdata[iii] = _DG2RAD * plon2
latsdata[iii] = _DG2RAD * plat2
azdata[iii] = _DG2RAD * pazi2
def _inv(self, object lons1, object lats1, object lons2, object lats2, radians=False):
@cython.boundscheck(False)
@cython.wraparound(False)
def _inv(self, object lons1, object lats1, object lons2, object lats2, bint radians=False):
"""
inverse transformation - return forward and back azimuths, plus distance
between an initial and terminus lat/lon pair.
if radians=True, lons/lats are radians instead of degrees.
inverse transformation - return forward and back azimuths, plus distance
between an initial and terminus lat/lon pair.
if radians=True, lons/lats are radians instead of degree
"""
cdef double lat1,lon1,lat2,lon2,pazi1,pazi2,ps12
cdef Py_ssize_t buflenlons, buflenlats, buflenaz, buflend, ndim, i
cdef Py_ssize_t buflenlons, buflenlats, buflenaz, buflend, ndim, iii
cdef double *lonsdata
cdef double *latsdata
cdef double *azdata
......@@ -123,19 +129,22 @@ cdef class Geod:
latsdata = <double *>latdata
azdata = <double *>azdat
distdata = <double *>distdat
for i from 0 <= i < ndim:
for iii in range(ndim):
if radians:
lon1 = _RAD2DG*lonsdata[i]
lat1 = _RAD2DG*latsdata[i]
lon2 = _RAD2DG*azdata[i]
lat2 = _RAD2DG*distdata[i]
lon1 = _RAD2DG * lonsdata[iii]
lat1 = _RAD2DG * latsdata[iii]
lon2 = _RAD2DG * azdata[iii]
lat2 = _RAD2DG * distdata[iii]
else:
lon1 = lonsdata[i]
lat1 = latsdata[i]
lon2 = azdata[i]
lat2 = distdata[i]
geod_inverse(&self._geod_geodesic, lat1, lon1, lat2, lon2,
&ps12, &pazi1, &pazi2)
lon1 = lonsdata[iii]
lat1 = latsdata[iii]
lon2 = azdata[iii]
lat2 = distdata[iii]
geod_inverse(
&self._geod_geodesic,
lat1, lon1, lat2, lon2,
&ps12, &pazi1, &pazi2,
)
# back azimuth needs to be flipped 180 degrees
# to match what proj4 geod utility produces.
if pazi2 > 0:
......@@ -143,47 +152,179 @@ cdef class Geod:
elif pazi2 <= 0:
pazi2 = pazi2+180.
if radians:
lonsdata[i] = _DG2RAD*pazi1
latsdata[i] = _DG2RAD*pazi2
lonsdata[iii] = _DG2RAD * pazi1
latsdata[iii] = _DG2RAD * pazi2
else:
lonsdata[i] = pazi1
latsdata[i] = pazi2
azdata[i] = ps12
lonsdata[iii] = pazi1
latsdata[iii] = pazi2
azdata[iii] = ps12
def _npts(self, double lon1, double lat1, double lon2, double lat2, int npts, radians=False):
@cython.boundscheck(False)
@cython.wraparound(False)
def _npts(self, double lon1, double lat1, double lon2, double lat2, int npts, bint radians=False):
"""
given initial and terminus lat/lon, find npts intermediate points.
"""
given initial and terminus lat/lon, find npts intermediate points."""
cdef int i
cdef Py_ssize_t iii
cdef double del_s,ps12,pazi1,pazi2,s12,plon2,plat2
cdef geod_geodesicline line
if radians:
lon1 = _RAD2DG*lon1
lat1 = _RAD2DG*lat1
lon2 = _RAD2DG*lon2
lat2 = _RAD2DG*lat2
lon1 = _RAD2DG * lon1
lat1 = _RAD2DG * lat1
lon2 = _RAD2DG * lon2
lat2 = _RAD2DG * lat2
# do inverse computation to set azimuths, distance.
# in proj 4.9.3 and later the next two steps can be replace by a call
# to geod_inverseline with del_s = line.s13/(npts+1)
geod_inverse(&self._geod_geodesic, lat1, lon1, lat2, lon2,
&ps12, &pazi1, &pazi2)
geod_inverse(
&self._geod_geodesic,
lat1, lon1, lat2, lon2,
&ps12, &pazi1, &pazi2,
)
geod_lineinit(&line, &self._geod_geodesic, lat1, lon1, pazi1, 0u)
# distance increment.
del_s = ps12/(npts+1)
del_s = ps12 / (npts + 1)
# initialize output tuples.
lats = ()
lons = ()
# loop over intermediate points, compute lat/lons.
for i from 1 <= i < npts+1:
s12 = i*del_s
for iii in range(1, npts + 1):
s12 = iii * del_s
geod_position(&line, s12, &plat2, &plon2, &pazi2);
if radians:
lats = lats + (_DG2RAD*plat2,)
lons = lons + (_DG2RAD*plon2,)
lats = lats + (_DG2RAD * plat2,)
lons = lons + (_DG2RAD * plon2,)
else:
lats = lats + (plat2,)
lons = lons + (plon2,)
return lons, lats
@cython.boundscheck(False)
@cython.wraparound(False)
def _line_length(self, object lons, object lats, bint radians=False):
"""
Calculate the distance between points along a line.
Parameters
----------
lons: array
The longitude points along a line.
lats: array
The latitude points along a line.
radians: bool, optional
If True, the input data is assumed to be in radians.
Returns
-------
float: The total distance.
"""
cdef double lat1,lon1,lat2,lon2,pazi1,pazi2,ps12
cdef double total_distance = 0.0
cdef Py_ssize_t buflenlons, buflenlats, ndim, iii
cdef double *lonsdata
cdef double *latsdata
cdef void *londata
cdef void *latdata
# if buffer api is supported, get pointer to data buffers.
if PyObject_AsWriteBuffer(lons, &londata, &buflenlons) <> 0:
raise GeodError
if PyObject_AsWriteBuffer(lats, &latdata, &buflenlats) <> 0:
raise GeodError
# process data in buffer
if buflenlons != buflenlats:
raise GeodError("Buffer lengths not the same")
ndim = buflenlons//_DOUBLESIZE
lonsdata = <double *>londata
latsdata = <double *>latdata
if ndim == 1:
lonsdata[0] = 0
return 0.0
for iii in range(ndim - 1):
if radians:
lon1 = _RAD2DG * lonsdata[iii]
lat1 = _RAD2DG * latsdata[iii]
lon2 = _RAD2DG * lonsdata[iii + 1]
lat2 = _RAD2DG * latsdata[iii + 1]
else:
lon1 = lonsdata[iii]
lat1 = latsdata[iii]
lon2 = lonsdata[iii + 1]
lat2 = latsdata[iii + 1]
geod_inverse(
&self._geod_geodesic,
lat1, lon1, lat2, lon2,
&ps12, &pazi1, &pazi2,
)
lonsdata[iii] = ps12
total_distance += ps12
return total_distance
@cython.boundscheck(False)
@cython.wraparound(False)
def _polygon_area_perimeter(self, object lons, object lats, bint radians=False):
"""
A simple interface for computing the area of a geodesic polygon.
lats should be in the range [-90 deg, 90 deg].
Only simple polygons (which are not self-intersecting) are allowed.
There's no need to "close" the polygon by repeating the first vertex.
The area returned is signed with counter-clockwise traversal being treated as
positive.
Parameters
----------
lons: array
An array of longitude values.
lats: array
An array of latitude values.
radians: bool, optional
If True, the input data is assumed to be in radians.
Returns
-------
(float, float): The area (meter^2) and permimeter (meters) of the polygon.
"""
cdef Py_ssize_t buflenlons, buflenlats, ndim, iii
cdef void *londata
cdef void *latdata
cdef double *lonsdata
cdef double *latsdata
# if buffer api is supported, get pointer to data buffers.
if PyObject_AsWriteBuffer(lons, &londata, &buflenlons) <> 0:
raise GeodError
if PyObject_AsWriteBuffer(lats, &latdata, &buflenlats) <> 0:
raise GeodError
# process data in buffer
if not buflenlons == buflenlats:
raise GeodError("Buffer lengths not the same")
cdef double polygon_area
cdef double polygon_perimeter
ndim = buflenlons//_DOUBLESIZE
lonsdata = <double *>londata
latsdata = <double *>latdata
if radians:
for iii in range(ndim):
lonsdata[iii] *= _RAD2DG
latsdata[iii] *= _RAD2DG
geod_polygonarea(
&self._geod_geodesic,
latsdata, lonsdata, ndim,
&polygon_area, &polygon_perimeter
)
return (polygon_area, polygon_perimeter)
def __repr__(self):
return "{classname}({init!r})".format(classname=self.__class__.__name__,
init=self.initstring)
return "{classname}({init!r})".format(
classname=self.__class__.__name__,
init=self.initstring,
)
......@@ -2,8 +2,5 @@ include "proj.pxi"
cdef class Proj:
cdef PJ * projpj
cdef PJ_CONTEXT * projctx
cdef PJ_PROJ_INFO projpj_info
cdef char *pjinitstring
cdef object _proj_version
cdef readonly srs
......@@ -2,8 +2,10 @@ include "base.pxi"
import warnings
cimport cython
from pyproj.compat import cstrencode, pystrdecode
from pyproj._datadir cimport get_pyproj_context
from pyproj._datadir cimport PROJ_CONTEXT
from pyproj.exceptions import ProjError
......@@ -16,35 +18,21 @@ proj_version_str = "{0}.{1}.{2}".format(
cdef class Proj:
def __cinit__(self):
self.projctx = NULL
self.projpj = NULL
def __init__(self, const char *projstring):
self.srs = pystrdecode(projstring)
# setup the context
self.projctx = get_pyproj_context()
# initialize projection
self.projpj = proj_create(self.projctx, projstring)
self.projpj = proj_create(PROJ_CONTEXT.context, projstring)
if self.projpj is NULL:
raise ProjError("Invalid projection {}.".format(projstring))
self.projpj_info = proj_pj_info(self.projpj)
self._proj_version = PROJ_VERSION_MAJOR
def __dealloc__(self):
"""destroy projection definition"""
if self.projpj is not NULL:
proj_destroy(self.projpj)
if self.projctx is not NULL:
proj_context_destroy(self.projctx)
@property
def proj_version(self):
warnings.warn(
"'Proj.proj_version' is deprecated. "
"Please use `pyproj.proj_version_str` instead.",
DeprecationWarning,
)
return self._proj_version
self.projpj = NULL
@property
def definition(self):
......@@ -59,7 +47,9 @@ cdef class Proj:
"""special method that allows pyproj.Proj instance to be pickled"""
return self.__class__,(self.crs.srs,)
def _fwd(self, object lons, object lats, errcheck=False):
@cython.boundscheck(False)
@cython.wraparound(False)
def _fwd(self, object lons, object lats, bint errcheck=False):
"""
forward transformation - lons,lats to x,y (done in place).
if errcheck=True, an exception is raised if the forward transformation is invalid.
......@@ -68,7 +58,7 @@ cdef class Proj:
"""
cdef PJ_COORD projxyout
cdef PJ_COORD projlonlatin
cdef Py_ssize_t buflenx, bufleny, ndim, i
cdef Py_ssize_t buflenx, bufleny, ndim, iii
cdef double *lonsdata
cdef double *latsdata
cdef void *londata
......@@ -85,24 +75,24 @@ cdef class Proj:
ndim = buflenx//_DOUBLESIZE
lonsdata = <double *>londata
latsdata = <double *>latdata
for i from 0 <= i < ndim:
for iii in range(ndim):
# if inputs are nan's, return big number.
if lonsdata[i] != lonsdata[i] or latsdata[i] != latsdata[i]:
lonsdata[i]=1.e30; latsdata[i]=1.e30
if lonsdata[iii] != lonsdata[iii] or latsdata[iii] != latsdata[iii]:
lonsdata[iii]=1.e30; latsdata[iii]=1.e30
if errcheck:
raise ProjError('projection undefined')
raise ProjError("projection_undefined")
continue
if proj_angular_input(self.projpj, PJ_FWD):
projlonlatin.uv.u = _DG2RAD*lonsdata[i]
projlonlatin.uv.v = _DG2RAD*latsdata[i]
projlonlatin.uv.u = _DG2RAD * lonsdata[iii]
projlonlatin.uv.v = _DG2RAD * latsdata[iii]
else:
projlonlatin.uv.u = lonsdata[i]
projlonlatin.uv.v = latsdata[i]
projlonlatin.uv.u = lonsdata[iii]
projlonlatin.uv.v = latsdata[iii]
projxyout = proj_trans(self.projpj, PJ_FWD, projlonlatin)
if errcheck:
err = proj_errno(self.projpj)
if err != 0:
raise ProjError(pystrdecode(proj_errno_string(err)))
raise ProjError(pystrdecode(proj_errno_string(err)))
# since HUGE_VAL can be 'inf',
# change it to a real (but very large) number.
# also check for NaNs.
......@@ -111,14 +101,20 @@ cdef class Proj:
projxyout.xy.y == HUGE_VAL or\
projxyout.xy.x != projxyout.xy.x:
if errcheck:
raise ProjError('projection undefined')
lonsdata[i] = 1.e30
latsdata[i] = 1.e30
raise ProjError("projection_undefined")
lonsdata[iii] = 1.e30
latsdata[iii] = 1.e30
elif proj_angular_output(self.projpj, PJ_FWD):
lonsdata[iii] = _RAD2DG * projxyout.xy.x
latsdata[iii] = _RAD2DG * projxyout.xy.y
else:
lonsdata[i] = projxyout.xy.x
latsdata[i] = projxyout.xy.y
lonsdata[iii] = projxyout.xy.x
latsdata[iii] = projxyout.xy.y
def _inv(self, object x, object y, errcheck=False):
@cython.boundscheck(False)
@cython.wraparound(False)
def _inv(self, object x, object y, bint errcheck=False):
"""
inverse transformation - x,y to lons,lats (done in place).
if errcheck=True, an exception is raised if the inverse transformation is invalid.
......@@ -130,11 +126,13 @@ cdef class Proj:
cdef PJ_COORD projxyin
cdef PJ_COORD projlonlatout
cdef Py_ssize_t buflenx, bufleny, ndim, i
cdef Py_ssize_t buflenx, bufleny, ndim, iii
cdef void *xdata
cdef void *ydata
cdef double *xdatab
cdef double *ydatab
cdef int err
# if buffer api is supported, get pointer to data buffers.
if PyObject_AsWriteBuffer(x, &xdata, &buflenx) <> 0:
raise ProjError
......@@ -147,20 +145,24 @@ cdef class Proj:
ndim = buflenx//_DOUBLESIZE
xdatab = <double *>xdata
ydatab = <double *>ydata
for i from 0 <= i < ndim:
for iii in range(ndim):
# if inputs are nan's, return big number.
if xdatab[i] != xdatab[i] or ydatab[i] != ydatab[i]:
xdatab[i]=1.e30; ydatab[i]=1.e30
if xdatab[iii] != xdatab[iii] or ydatab[iii] != ydatab[iii]:
xdatab[iii]=1.e30; ydatab[iii]=1.e30
if errcheck:
raise ProjError('projection undefined')
raise ProjError("projection_undefined")
continue
projxyin.uv.u = xdatab[i]
projxyin.uv.v = ydatab[i]
if proj_angular_input(self.projpj, PJ_INV):
projxyin.uv.u = _DG2RAD * xdatab[iii]
projxyin.uv.v = _DG2RAD * ydatab[iii]
else:
projxyin.uv.u = xdatab[iii]
projxyin.uv.v = ydatab[iii]
projlonlatout = proj_trans(self.projpj, PJ_INV, projxyin)
if errcheck:
err = proj_errno(self.projpj)
if err != 0:
raise ProjError(pystrdecode(proj_errno_string(err)))
raise ProjError(pystrdecode(proj_errno_string(err)))
# since HUGE_VAL can be 'inf',
# change it to a real (but very large) number.
# also check for NaNs.
......@@ -169,15 +171,15 @@ cdef class Proj:
projlonlatout.uv.v == HUGE_VAL or \
projlonlatout.uv.v != projlonlatout.uv.v:
if errcheck:
raise ProjError('projection undefined')
xdatab[i] = 1.e30
ydatab[i] = 1.e30
raise ProjError("projection_undefined")
xdatab[iii] = 1.e30
ydatab[iii] = 1.e30
elif proj_angular_output(self.projpj, PJ_INV):
xdatab[i] = _RAD2DG*projlonlatout.uv.u
ydatab[i] = _RAD2DG*projlonlatout.uv.v
xdatab[iii] = _RAD2DG * projlonlatout.uv.u
ydatab[iii] = _RAD2DG * projlonlatout.uv.v
else:
xdatab[i] = projlonlatout.uv.u
ydatab[i] = projlonlatout.uv.v
xdatab[iii] = projlonlatout.uv.u
ydatab[iii] = projlonlatout.uv.v
def __repr__(self):
return "Proj('{srs}', preserve_units=True)".format(srs=self.srs)
......
......@@ -53,7 +53,7 @@ def _get_deps_info():
deps_info: dict
version information on relevant Python libraries
"""
deps = ["pyproj", "pip", "setuptools", "Cython", "aenum"]
deps = ["pyproj", "pip", "setuptools", "Cython"]
def get_version(module):
try:
......