cryoswath 0.2.1.post4__tar.gz → 0.2.2.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/.gitignore +1 -0
  2. cryoswath-0.2.2.dev0/.readthedocs.yaml +25 -0
  3. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/LICENSE.txt +2 -1
  4. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/PKG-INFO +55 -38
  5. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/README.md +47 -32
  6. cryoswath-0.2.2.dev0/cryoswath/__init__.py +22 -0
  7. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/cryoswath/gis.py +105 -46
  8. cryoswath-0.2.2.dev0/cryoswath/l1b.py +1249 -0
  9. cryoswath-0.2.2.dev0/cryoswath/l2.py +616 -0
  10. cryoswath-0.2.2.dev0/cryoswath/l3.py +548 -0
  11. cryoswath-0.2.2.dev0/cryoswath/l4.py +1317 -0
  12. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/cryoswath/misc.py +1044 -475
  13. cryoswath-0.2.2.dev0/cryoswath/test_plots/maps.py +65 -0
  14. cryoswath-0.2.2.dev0/cryoswath/test_plots/timeseries.py +71 -0
  15. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/docs/conf.py +72 -7
  16. cryoswath-0.2.2.dev0/docs/prerequisites.rst +61 -0
  17. cryoswath-0.2.2.dev0/docs/requirements.in +2 -0
  18. cryoswath-0.2.2.dev0/docs/requirements.txt +59 -0
  19. cryoswath-0.2.2.dev0/docs/tests.rst +25 -0
  20. cryoswath-0.2.2.dev0/docs/tutorials.rst +27 -0
  21. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/pyproject.toml +10 -6
  22. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/tests/reports/l1b_swath_start.ipynb +2 -2
  23. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/tests/reports/l1b_waveform.ipynb +2 -2
  24. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/tests/reports/l2_tested_data_comparison.ipynb +2 -2
  25. cryoswath-0.2.2.dev0/tests/test_l1b.py +25 -0
  26. cryoswath-0.2.1.post4/cryoswath/__init__.py +0 -6
  27. cryoswath-0.2.1.post4/cryoswath/l1b.py +0 -903
  28. cryoswath-0.2.1.post4/cryoswath/l2.py +0 -424
  29. cryoswath-0.2.1.post4/cryoswath/l3.py +0 -641
  30. cryoswath-0.2.1.post4/cryoswath/l4.py +0 -197
  31. cryoswath-0.2.1.post4/cryoswath/test_plots/maps.py +0 -41
  32. cryoswath-0.2.1.post4/cryoswath/test_plots/timeseries.py +0 -55
  33. cryoswath-0.2.1.post4/docs/prerequisites.rst +0 -50
  34. cryoswath-0.2.1.post4/docs/tests.rst +0 -15
  35. cryoswath-0.2.1.post4/docs/tutorials.rst +0 -23
  36. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/.gitattributes +0 -0
  37. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  38. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  39. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/.github/ISSUE_TEMPLATE/question.md +0 -0
  40. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/cryoswath/test_plots/__init__.py +0 -0
  41. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/cryoswath/test_plots/waveform.py +0 -0
  42. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/docker/Dockerfile +0 -0
  43. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/docs/Makefile +0 -0
  44. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/docs/cryoswath.gis.rst +0 -0
  45. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/docs/cryoswath.l1b.rst +0 -0
  46. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/docs/cryoswath.l2.rst +0 -0
  47. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/docs/cryoswath.l3.rst +0 -0
  48. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/docs/cryoswath.l4.rst +0 -0
  49. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/docs/cryoswath.misc.rst +0 -0
  50. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/docs/cryoswath.test_plots.rst +0 -0
  51. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/docs/getting_started.rst +0 -0
  52. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/docs/index.rst +0 -0
  53. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/requirements.txt +0 -0
  54. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/tests/reports/.gitignore +0 -0
  55. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/tests/reports/l2_dem_comparison.ipynb +0 -0
  56. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/tests/reports/reference_data/L2_reference_data_20220521T110815.csv +0 -0
  57. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/tests/reports/reference_figures/waveform_2014-05-17T22:54:51.839752960.png +0 -0
  58. {cryoswath-0.2.1.post4 → cryoswath-0.2.2.dev0}/tests/void_filling_results_smell_test.ipynb +0 -0
@@ -9,6 +9,7 @@ tests/reports/*.pdf
9
9
  tests/reports/0-*
10
10
  tmp_*
11
11
  paper_ESSD
12
+ tox.ini
12
13
 
13
14
  # below follows a generated list of files one typically wants to exclude
14
15
 
@@ -0,0 +1,25 @@
1
+ # Read the Docs configuration file
2
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3
+
4
+ # Required
5
+ version: 2
6
+
7
+ # Set the OS, Python version, and other tools you might need
8
+ build:
9
+ os: ubuntu-24.04
10
+ tools:
11
+ python: "3.13"
12
+
13
+ # Build documentation in the "docs/" directory with Sphinx
14
+ sphinx:
15
+ configuration: docs/conf.py
16
+
17
+ # Optionally, but recommended,
18
+ # declare the Python requirements required to build your documentation
19
+ # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
20
+ python:
21
+ install:
22
+ - requirements: docs/requirements.txt
23
+ - method: pip
24
+ path: .
25
+
@@ -1,5 +1,6 @@
1
1
  The MIT License (MIT)
2
- Copyright (c) 2023 Delft University of Technology
2
+ Copyright (c) 2023-2024 Delft University of Technology
3
+ Copyright (c) 2024-2025 Jan Haacker
3
4
 
4
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: cryoswath
3
- Version: 0.2.1.post4
3
+ Version: 0.2.2.dev0
4
4
  Summary: Swath processing toolbox for CryoSat-2
5
5
  Keywords: glacier,altimetry,swath,cryosat
6
6
  Author-email: Jan Haacker <j.m.haacker@tudelft.nl>
@@ -9,9 +9,10 @@ Description-Content-Type: text/markdown
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Operating System :: OS Independent
11
11
  Classifier: License :: OSI Approved :: MIT License
12
+ Requires-Dist: Bottleneck
12
13
  Requires-Dist: dask
13
14
  Requires-Dist: defusedxml
14
- Requires-Dist: geopandas
15
+ Requires-Dist: geopandas>=1.0.1
15
16
  Requires-Dist: gitpython
16
17
  Requires-Dist: h5netcdf
17
18
  Requires-Dist: h5py
@@ -33,20 +34,21 @@ Requires-Dist: statsmodels
33
34
  Requires-Dist: tqdm
34
35
  Requires-Dist: xarray
35
36
  Requires-Dist: zarr
36
- Requires-Dist: sphinx ; extra == "doc"
37
+ Requires-Dist: black ; extra == "dev"
38
+ Requires-Dist: sphinx ; extra == "dev"
39
+ Requires-Dist: sphinx-rtd-theme ; extra == "dev"
37
40
  Requires-Dist: ipykernel ; extra == "notebooks"
38
- Project-URL: Documentation, https://j-haacker.github.io/cryoswath
39
- Project-URL: Homepage, https://github.com/j-haacker/cryoswath
41
+ Project-URL: Documentation, https://cryoswath.readthedocs.io/
40
42
  Project-URL: Issues, https://github.com/j-haacker/cryoswath/issues
41
43
  Project-URL: Repository, https://github.com/j-haacker/cryoswath.git
42
- Provides-Extra: doc
44
+ Provides-Extra: dev
43
45
  Provides-Extra: notebooks
44
46
 
45
47
  # cryoswath
46
48
 
47
49
  ![GitHub top language](https://img.shields.io/github/languages/top/j-haacker/cryoswath)
48
- ![PyPI - Version](https://img.shields.io/pypi/v/cryoswath)
49
- [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.14837018.svg)](https://doi.org/10.5281/zenodo.14837018)
50
+ ![Conda Version](https://img.shields.io/conda/vn/conda-forge/cryoswath)
51
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.14825358.svg)](https://doi.org/10.5281/zenodo.14825358)
50
52
  ![GitHub License](https://img.shields.io/github/license/j-haacker/cryoswath)
51
53
 
52
54
  cryoswath is a python package containing processing pipelines, a tool
@@ -59,11 +61,11 @@ changing the concerned function or adding a new one.
59
61
 
60
62
  ## 🌱 state
61
63
 
62
- cryoswath is being developed. Branch `main` contains the
63
- "pip"-installable package, `scripts` contains tutorials, and `data`
64
- contains auxiliary data and the required directory structure. You can
65
- have everything setup automatically (see "getting started"). Other
66
- branches are for development.
64
+ cryoswath is being developed. Branch `main` is the release branch,
65
+ `scripts` contains tutorials, and `data` contains auxiliary data and the
66
+ required directory structure. You can have everything setup
67
+ automatically (see "getting started"). Other branches are for
68
+ development.
67
69
 
68
70
  ## ✨ features
69
71
 
@@ -81,16 +83,26 @@ instructions for UNIX systems. Make sure to use python 3.11 or higher.
81
83
  Further, I recommend to use a virtual environment and will involve
82
84
  python-venv in the instructions (however, conda works similar).
83
85
 
86
+ All of the following instructions consist of three main steps:
87
+
88
+ 1. making cryoswath available
89
+ 2. setting up a project directory
90
+ 3. initializing cryoswath
91
+
92
+ The instructions will use the variable `$proj_dir` for the project
93
+ directory. Please set it to a path that suits you like
94
+ `proj_dir=altimetry-project`.
95
+
96
+ In all cases, consider to download the data dependencies ArcticDEM and
97
+ the RGI glacier and complex shape files into the
98
+ `$proj_dir/data/auxiliary/DEM` and `$proj_dir/data/auxiliary/RGI`
99
+ directories (more in the [docs](https://j-haacker.github.io/cryoswath/prerequisites.html)).
100
+
84
101
  ### with git 🐙
85
102
 
86
103
  advantage: easy pulling bugfixes
87
104
 
88
- Set up a project directory, pull this repo, create virtual
89
- environment, initialize, and download ArcticDEM and the RGI glacier and complex
90
- shape files into the `data/auxiliary/DEM` and -`RGI` directories.
91
-
92
105
  ```sh
93
- proj_dir=altimetry-project
94
106
  git clone https://github.com/j-haacker/cryoswath.git $proj_dir
95
107
  cd $proj_dir
96
108
  python3.11 -m venv .venv
@@ -103,13 +115,7 @@ cryoswath-init
103
115
 
104
116
  advantage: easy installation
105
117
 
106
- Set up a project directory, create virtual environment, install
107
- cryoswath, initialize, and download ArcticDEM and the RGI glacier and
108
- complex shape files into the `data/auxiliary/DEM` and -`RGI`
109
- directories.
110
-
111
118
  ```sh
112
- proj_dir=altimetry-project
113
119
  mkdir $proj_dir
114
120
  cd $proj_dir
115
121
  python3.11 -m venv .venv
@@ -118,30 +124,40 @@ pip install cryoswath
118
124
  cryoswath-init
119
125
  ```
120
126
 
127
+ ### with conda 🐍
128
+
129
+ advantage: most stable dependency resolution
130
+
131
+ First, choose an environment name and either define `$env_name`, e.g.,
132
+ `env_name=cryoswath`, or adapt the create and activate commands
133
+ accordingly.
134
+
135
+ ```sh
136
+ conda create -n $env_name conda-forge::cryoswath
137
+ conda activate $env_name
138
+ mkdir $proj_dir
139
+ cd $proj_dir
140
+ cryoswath-init
141
+ ```
142
+
121
143
  ### with Docker 🐳
122
144
 
123
145
  advantage: will almost always work
124
146
 
125
147
  *note*: the first time running the docker image require to download ~ 1 Gb
126
148
 
127
- 1. If you don't yet have a designated project directory, make one. I will assume its relative path is `pro/ject`
128
- 2. Then execute `docker run -it -p 8888:8888 -v pro/ject:/home/jovyan cryoswath/jupyterlab:v0.2.1`
129
- 3. You will receive an address including a token with which you can connect to the jupyterlab using your browser
130
- 4. Open a regular shell and execute `cryoswath-init`
131
- 5. Open the scripts folder in the explorer and select one of the notebooks or create your own (inside the scripts folder)
132
-
133
- ### conda
134
-
135
- New setup instructions coming soon.
149
+ 1. `docker run -it -p 8888:8888 -v $proj_dir$:/home/jovyan cryoswath/jupyterlab:v0.2.1`
150
+ 2. You will receive an address including a token with which you can connect to the jupyterlab using your browser
151
+ 3. In jupyterlab, open a regular shell and execute `cryoswath-init`
152
+ 4. Open the scripts folder in the explorer and select one of the notebooks or create your own (inside the scripts folder)
136
153
 
137
154
  ### multiple projects
138
155
 
139
- Similar to the above, set up a virtual environment but rather locate it
140
- in a neutral directory. For each project, run `cryoswath-init`.
156
+ For each project, run `cryoswath-init` from the project directory.
141
157
 
142
158
  ## 📖 documentation
143
159
 
144
- [j-haacker.github.io/cryoswath](https://j-haacker.github.io/cryoswath/)
160
+ [j-haacker.github.io/cryoswath](https://cryoswath.readthedocs.io/)
145
161
 
146
162
  ## dependencies
147
163
 
@@ -153,6 +169,7 @@ cryoswath will point you to the required resources.
153
169
 
154
170
  ## 🐛 known issues
155
171
 
172
+ - ESA's data server is not available from all internet service providers
156
173
  - projected RGI basins sometimes "invalid"
157
174
  -> add `.make_valid()` if it is missing somewhere
158
175
  - it has mostly been tested for the Arctic
@@ -166,11 +183,11 @@ You can cite this package using bibtex:
166
183
  ```bibtex
167
184
  @software{cryoswath,
168
185
  author = {Haacker, Jan},
169
- title = {cryoswath: v0.2.1},
186
+ title = {cryoswath: v0.2.2},
170
187
  month = feb,
171
188
  year = 2025,
172
189
  publisher = {Zenodo},
173
- version = {v0.2.1},
190
+ version = {v0.2.2},
174
191
  doi = {10.5281/zenodo.14837018}
175
192
  }
176
193
  ```
@@ -1,8 +1,8 @@
1
1
  # cryoswath
2
2
 
3
3
  ![GitHub top language](https://img.shields.io/github/languages/top/j-haacker/cryoswath)
4
- ![PyPI - Version](https://img.shields.io/pypi/v/cryoswath)
5
- [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.14837018.svg)](https://doi.org/10.5281/zenodo.14837018)
4
+ ![Conda Version](https://img.shields.io/conda/vn/conda-forge/cryoswath)
5
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.14825358.svg)](https://doi.org/10.5281/zenodo.14825358)
6
6
  ![GitHub License](https://img.shields.io/github/license/j-haacker/cryoswath)
7
7
 
8
8
  cryoswath is a python package containing processing pipelines, a tool
@@ -15,11 +15,11 @@ changing the concerned function or adding a new one.
15
15
 
16
16
  ## 🌱 state
17
17
 
18
- cryoswath is being developed. Branch `main` contains the
19
- "pip"-installable package, `scripts` contains tutorials, and `data`
20
- contains auxiliary data and the required directory structure. You can
21
- have everything setup automatically (see "getting started"). Other
22
- branches are for development.
18
+ cryoswath is being developed. Branch `main` is the release branch,
19
+ `scripts` contains tutorials, and `data` contains auxiliary data and the
20
+ required directory structure. You can have everything setup
21
+ automatically (see "getting started"). Other branches are for
22
+ development.
23
23
 
24
24
  ## ✨ features
25
25
 
@@ -37,16 +37,26 @@ instructions for UNIX systems. Make sure to use python 3.11 or higher.
37
37
  Further, I recommend to use a virtual environment and will involve
38
38
  python-venv in the instructions (however, conda works similar).
39
39
 
40
+ All of the following instructions consist of three main steps:
41
+
42
+ 1. making cryoswath available
43
+ 2. setting up a project directory
44
+ 3. initializing cryoswath
45
+
46
+ The instructions will use the variable `$proj_dir` for the project
47
+ directory. Please set it to a path that suits you like
48
+ `proj_dir=altimetry-project`.
49
+
50
+ In all cases, consider to download the data dependencies ArcticDEM and
51
+ the RGI glacier and complex shape files into the
52
+ `$proj_dir/data/auxiliary/DEM` and `$proj_dir/data/auxiliary/RGI`
53
+ directories (more in the [docs](https://j-haacker.github.io/cryoswath/prerequisites.html)).
54
+
40
55
  ### with git 🐙
41
56
 
42
57
  advantage: easy pulling bugfixes
43
58
 
44
- Set up a project directory, pull this repo, create virtual
45
- environment, initialize, and download ArcticDEM and the RGI glacier and complex
46
- shape files into the `data/auxiliary/DEM` and -`RGI` directories.
47
-
48
59
  ```sh
49
- proj_dir=altimetry-project
50
60
  git clone https://github.com/j-haacker/cryoswath.git $proj_dir
51
61
  cd $proj_dir
52
62
  python3.11 -m venv .venv
@@ -59,13 +69,7 @@ cryoswath-init
59
69
 
60
70
  advantage: easy installation
61
71
 
62
- Set up a project directory, create virtual environment, install
63
- cryoswath, initialize, and download ArcticDEM and the RGI glacier and
64
- complex shape files into the `data/auxiliary/DEM` and -`RGI`
65
- directories.
66
-
67
72
  ```sh
68
- proj_dir=altimetry-project
69
73
  mkdir $proj_dir
70
74
  cd $proj_dir
71
75
  python3.11 -m venv .venv
@@ -74,30 +78,40 @@ pip install cryoswath
74
78
  cryoswath-init
75
79
  ```
76
80
 
81
+ ### with conda 🐍
82
+
83
+ advantage: most stable dependency resolution
84
+
85
+ First, choose an environment name and either define `$env_name`, e.g.,
86
+ `env_name=cryoswath`, or adapt the create and activate commands
87
+ accordingly.
88
+
89
+ ```sh
90
+ conda create -n $env_name conda-forge::cryoswath
91
+ conda activate $env_name
92
+ mkdir $proj_dir
93
+ cd $proj_dir
94
+ cryoswath-init
95
+ ```
96
+
77
97
  ### with Docker 🐳
78
98
 
79
99
  advantage: will almost always work
80
100
 
81
101
  *note*: the first time running the docker image require to download ~ 1 Gb
82
102
 
83
- 1. If you don't yet have a designated project directory, make one. I will assume its relative path is `pro/ject`
84
- 2. Then execute `docker run -it -p 8888:8888 -v pro/ject:/home/jovyan cryoswath/jupyterlab:v0.2.1`
85
- 3. You will receive an address including a token with which you can connect to the jupyterlab using your browser
86
- 4. Open a regular shell and execute `cryoswath-init`
87
- 5. Open the scripts folder in the explorer and select one of the notebooks or create your own (inside the scripts folder)
88
-
89
- ### conda
90
-
91
- New setup instructions coming soon.
103
+ 1. `docker run -it -p 8888:8888 -v $proj_dir$:/home/jovyan cryoswath/jupyterlab:v0.2.1`
104
+ 2. You will receive an address including a token with which you can connect to the jupyterlab using your browser
105
+ 3. In jupyterlab, open a regular shell and execute `cryoswath-init`
106
+ 4. Open the scripts folder in the explorer and select one of the notebooks or create your own (inside the scripts folder)
92
107
 
93
108
  ### multiple projects
94
109
 
95
- Similar to the above, set up a virtual environment but rather locate it
96
- in a neutral directory. For each project, run `cryoswath-init`.
110
+ For each project, run `cryoswath-init` from the project directory.
97
111
 
98
112
  ## 📖 documentation
99
113
 
100
- [j-haacker.github.io/cryoswath](https://j-haacker.github.io/cryoswath/)
114
+ [j-haacker.github.io/cryoswath](https://cryoswath.readthedocs.io/)
101
115
 
102
116
  ## dependencies
103
117
 
@@ -109,6 +123,7 @@ cryoswath will point you to the required resources.
109
123
 
110
124
  ## 🐛 known issues
111
125
 
126
+ - ESA's data server is not available from all internet service providers
112
127
  - projected RGI basins sometimes "invalid"
113
128
  -> add `.make_valid()` if it is missing somewhere
114
129
  - it has mostly been tested for the Arctic
@@ -122,11 +137,11 @@ You can cite this package using bibtex:
122
137
  ```bibtex
123
138
  @software{cryoswath,
124
139
  author = {Haacker, Jan},
125
- title = {cryoswath: v0.2.1},
140
+ title = {cryoswath: v0.2.2},
126
141
  month = feb,
127
142
  year = 2025,
128
143
  publisher = {Zenodo},
129
- version = {v0.2.1},
144
+ version = {v0.2.2},
130
145
  doi = {10.5281/zenodo.14837018}
131
146
  }
132
147
  ```
@@ -0,0 +1,22 @@
1
+ __all__ = [
2
+ "__version__",
3
+ "misc",
4
+ "gis",
5
+ "l1b",
6
+ "l2",
7
+ "l3",
8
+ "l4",
9
+ "test_plots", # subpackage
10
+ ]
11
+
12
+ from importlib.metadata import version as _version
13
+ from . import gis, misc, l1b, l2, l3, l4, test_plots
14
+
15
+
16
+ # copied from xarray
17
+ try:
18
+ __version__ = _version("cryoswath")
19
+ except Exception:
20
+ # Local copy or not installed with setuptools.
21
+ # Disable minimum version checks on downstream libraries.
22
+ __version__ = "9999"
@@ -1,3 +1,17 @@
1
+ """Geospatial processing focused helper functions"""
2
+
3
+ __all__ = [
4
+ "find_planar_crs",
5
+ "buffer_4326_shp",
6
+ "simplify_4326_shp",
7
+ "get_4326_to_dem_Transformer",
8
+ "ensure_pyproj_crs",
9
+ "points_on_glacier",
10
+ "subdivide_region",
11
+ "esri_to_feather",
12
+ "get_lon_origin",
13
+ ]
14
+
1
15
  import geopandas as gpd
2
16
  import numpy as np
3
17
  import os
@@ -8,27 +22,37 @@ import rasterio
8
22
  import shapely
9
23
  import warnings
10
24
 
11
- from .misc import *
12
-
13
- __all__ = list()
25
+ from .misc import (
26
+ load_glacier_outlines,
27
+ rgi_path,
28
+ )
14
29
 
15
30
  # ! tbi:
16
31
  rgi_o1_epsg_dict = dict()
17
32
 
18
33
 
19
- def buffer_4326_shp(shp: shapely.Geometry, radius: float, simplify: bool = True) -> shapely.MultiPolygon:
34
+ def buffer_4326_shp(
35
+ shp: shapely.Geometry, radius: float, simplify: bool = True
36
+ ) -> shapely.MultiPolygon:
20
37
  # the algorithm splits a multi-geomerty like MultiPolygon into its
21
38
  # parts, simplifies them if requested, buffers them, and joins them
22
39
  # finally.
23
40
  # the splitting is necessary to work around issue #13
24
- if shp is None: # this will occasionally fail, as it will be 'GEOMETRYCOLLECTION EMPTY'
25
- warnings.warn("shp=None passed to buffer_4326_shp, returning empty MultiPolygon.")
41
+ if (
42
+ shp is None
43
+ ): # this will occasionally fail, as it will be 'GEOMETRYCOLLECTION EMPTY'
44
+ warnings.warn(
45
+ "shp=None passed to buffer_4326_shp, returning empty MultiPolygon."
46
+ )
26
47
  return shapely.MultiPolygon()
27
48
  # # below does not take the geopandas detour. while more straight forward,
28
49
  # # geopandas used to be more stable. however the below was improved and
29
50
  # # may be equally good now.
30
51
  # transformer = Transformer.from_crs("EPSG:4326", planar_crs)
31
- # shp = shapely.ops.transform(transformer.invert().transform, shapely.ops.transform(transformer.transform, shp).simplify(100).buffer(radius)).make_valid()
52
+ # shp = shapely.ops.transform(transformer.invert().transform,
53
+ # shapely.ops.transform(
54
+ # transformer.transform, shp
55
+ # ).simplify(100).buffer(radius)).make_valid()
32
56
  if isinstance(shp, shapely.geometry.base.BaseMultipartGeometry):
33
57
  shp = list(shp.geoms)
34
58
  elif isinstance(shp, shapely.geometry.base.BaseGeometry):
@@ -45,13 +69,17 @@ def buffer_4326_shp(shp: shapely.Geometry, radius: float, simplify: bool = True)
45
69
  buffered_planar = []
46
70
  for poly in shp:
47
71
  buffered_planar.append(
48
- gpd.GeoSeries(poly, crs=4326).to_crs(planar_crs).make_valid().simplify(100).buffer(radius))
72
+ gpd.GeoSeries(poly, crs=4326)
73
+ .to_crs(planar_crs)
74
+ .make_valid()
75
+ .simplify(100)
76
+ .buffer(radius)
77
+ )
49
78
  buffered_planar = pd.concat(buffered_planar)
50
79
  if simplify:
51
- buffered_planar = buffered_planar.simplify(radius/3)
80
+ buffered_planar = buffered_planar.simplify(radius / 3)
52
81
  buffered_planar = buffered_planar.to_crs(4326)
53
82
  return shapely.make_valid(buffered_planar.union_all(method="unary"))
54
- __all__.append("buffer_4326_shp")
55
83
 
56
84
 
57
85
  def ensure_pyproj_crs(crs: CRS) -> CRS:
@@ -64,17 +92,21 @@ def ensure_pyproj_crs(crs: CRS) -> CRS:
64
92
  epsg = crs
65
93
  crs = CRS.from_epsg(epsg)
66
94
  return crs
67
- __all__.append("ensure_pyproj_crs")
68
95
 
69
96
 
70
97
  def esri_to_feather(file_path: str = None) -> None:
71
98
  if file_path.split(os.path.extsep)[-1].lower() == "shp":
72
99
  basename = os.path.extsep.join(file_path.split(os.path.extsep)[:-1])
73
- gpd.read_file(file_path).to_feather(basename+os.path.extsep+"feather")
74
- __all__.append("esri_to_feather")
100
+ gpd.read_file(file_path).to_feather(basename + os.path.extsep + "feather")
75
101
 
76
102
 
77
- def find_planar_crs(*, shp: shapely.Geometry = None, lat: float = None, lon: float = None, region_id: str = None):
103
+ def find_planar_crs(
104
+ *,
105
+ shp: shapely.Geometry = None,
106
+ lat: float = None,
107
+ lon: float = None,
108
+ region_id: str = None,
109
+ ):
78
110
  if region_id is not None:
79
111
  with warnings.catch_warnings(action="ignore"):
80
112
  shp = load_glacier_outlines(region_id)
@@ -87,57 +119,74 @@ def find_planar_crs(*, shp: shapely.Geometry = None, lat: float = None, lon: flo
87
119
  return CRS.from_epsg(3976)
88
120
  else:
89
121
  return gpd.GeoSeries(shp, crs=4326).to_frame().estimate_utm_crs()
90
- __all__.append("find_planar_crs")
122
+
91
123
 
92
124
  def get_lon_origin(crs):
93
125
  # Extract Longitude of origin
94
126
  # May turn out not to be very robust.
95
127
  return ensure_pyproj_crs(crs).coordinate_operation.params[1].value
96
- __all__.append("get_lon_origin")
97
-
128
+
98
129
 
99
130
  def get_4326_to_dem_Transformer(dem_reader: rasterio.DatasetReader) -> Transformer:
100
131
  return Transformer.from_crs("EPSG:4326", ensure_pyproj_crs(dem_reader.crs))
101
- __all__.append("get_4326_to_dem_Transformer")
102
132
 
103
133
 
104
134
  def points_on_glacier(points: gpd.GeoSeries) -> pd.Index:
105
- o2regions = gpd.read_feather(os.path.join(rgi_path, "RGI2000-v7.0-o2regions.feather"))
106
- o2code = o2regions[o2regions.geometry.contains(shapely.box(*points.total_bounds))]["o2region"].values[0]
107
- buffered_glaciered_area_polygon = load_o2region(o2code)
135
+ o2regions = gpd.read_feather(
136
+ os.path.join(rgi_path, "RGI2000-v7.0-o2regions.feather")
137
+ )
138
+ o2code = o2regions[o2regions.geometry.contains(shapely.box(*points.total_bounds))][
139
+ "o2region"
140
+ ].values[0]
141
+ buffered_glaciered_area_polygon = load_glacier_outlines(o2code)
108
142
  import time
143
+
109
144
  print(time.time(), "building union")
110
145
  union = buffered_glaciered_area_polygon.unary_union
111
146
  print(time.time(), "building geoseries")
112
- buffered_glaciered_area_polygon = gpd.GeoSeries(union,
113
- # ! the buffering below works only for the arctic
114
- crs=buffered_glaciered_area_polygon.crs)
147
+ buffered_glaciered_area_polygon = gpd.GeoSeries(
148
+ union,
149
+ # ! the buffering below works only for the arctic
150
+ crs=buffered_glaciered_area_polygon.crs,
151
+ )
115
152
  print(time.time(), "buffering")
116
- buffered_glaciered_area_polygon = buffered_glaciered_area_polygon.to_crs(3413).buffer(30_000)
153
+ buffered_glaciered_area_polygon = buffered_glaciered_area_polygon.to_crs(
154
+ 3413
155
+ ).buffer(30_000)
117
156
  print(time.time(), "simplifying")
118
- buffered_glaciered_area_polygon = buffered_glaciered_area_polygon.simplify(1000).to_crs(4326)
157
+ buffered_glaciered_area_polygon = buffered_glaciered_area_polygon.simplify(
158
+ 1000
159
+ ).to_crs(4326)
119
160
  return points[points.within(buffered_glaciered_area_polygon[0])].index
120
- __all__.append("points_on_glacier")
121
161
 
122
162
 
123
- def simplify_4326_shp(shp: shapely.Geometry, tolerance: float = None) -> shapely.Geometry:
163
+ def simplify_4326_shp(
164
+ shp: shapely.Geometry, tolerance: float = None
165
+ ) -> shapely.Geometry:
124
166
  if tolerance is None:
125
- if shp.length >= 20_000: # 5 x 5 km
167
+ if shp.length >= 20_000: # 5 x 5 km
126
168
  tolerance = 1000
127
169
  else:
128
170
  tolerance = 300
129
171
  planar_crs = find_planar_crs(shp=shp)
130
- # simplify can create holes outside of the polygon. this is fixed by buffer(0) or make_valid()
172
+ # simplify can create holes outside of the polygon. this is fixed by
173
+ # buffer(0) or make_valid()
131
174
  if isinstance(shp, shapely.Geometry):
132
175
  shp = gpd.GeoSeries(shp, crs=4326)
133
- return shp.to_crs(planar_crs).simplify(tolerance).to_crs(4326).make_valid().union_all(method="unary")
134
- __all__.append("simplify_4326_shp")
135
-
136
-
137
- def subdivide_region(basin_gdf: gpd.GeoDataFrame,
138
- lat_bin_width_degree: float = 1,
139
- lon_bin_width_degree: float = 1,
140
- ) -> list[gpd.GeoDataFrame]:
176
+ return (
177
+ shp.to_crs(planar_crs)
178
+ .simplify(tolerance)
179
+ .to_crs(4326)
180
+ .make_valid()
181
+ .union_all(method="unary")
182
+ )
183
+
184
+
185
+ def subdivide_region(
186
+ basin_gdf: gpd.GeoDataFrame,
187
+ lat_bin_width_degree: float = 1,
188
+ lon_bin_width_degree: float = 1,
189
+ ) -> list[gpd.GeoDataFrame]:
141
190
  """Devides GeoDataFrame of basins into smaller GeoDataFrame based on
142
191
  their central lat/lon coords.
143
192
 
@@ -153,15 +202,25 @@ def subdivide_region(basin_gdf: gpd.GeoDataFrame,
153
202
  """
154
203
  return_list = []
155
204
  # cut latitude into degree slices
156
- n_lat_bins = max(1, round((basin_gdf.cenlat.max()-basin_gdf.cenlat.min())/lat_bin_width_degree))
205
+ n_lat_bins = max(
206
+ 1,
207
+ round((basin_gdf.cenlat.max() - basin_gdf.cenlat.min()) / lat_bin_width_degree),
208
+ )
157
209
  # below, `observed=True` to grant compatibility with future pandas versions.
158
- for lat_label, lat_group in basin_gdf.groupby(pd.cut(basin_gdf.cenlat, bins=n_lat_bins), observed=True):
210
+ for lat_label, lat_group in basin_gdf.groupby(
211
+ pd.cut(basin_gdf.cenlat, bins=n_lat_bins), observed=True
212
+ ):
159
213
  # similarly, cut longitude
160
- n_lon_bins = max(1, round((lat_group.cenlon.max()-lat_group.cenlon.min())
161
- / lon_bin_width_degree
162
- * np.cos(np.deg2rad(lat_label.mid))))
163
- for _, lon_group in lat_group.groupby(pd.cut(lat_group.cenlon, bins=n_lon_bins), observed=True):
214
+ n_lon_bins = max(
215
+ 1,
216
+ round(
217
+ (lat_group.cenlon.max() - lat_group.cenlon.min())
218
+ / lon_bin_width_degree
219
+ * np.cos(np.deg2rad(lat_label.mid))
220
+ ),
221
+ )
222
+ for _, lon_group in lat_group.groupby(
223
+ pd.cut(lat_group.cenlon, bins=n_lon_bins), observed=True
224
+ ):
164
225
  return_list.append(lon_group)
165
226
  return return_list
166
- __all__.append("subdivide_region")
167
-