GLODAP 0.3__tar.gz → 0.4__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.
- {glodap-0.3 → glodap-0.4}/GLODAP.egg-info/PKG-INFO +22 -10
- {glodap-0.3 → glodap-0.4}/GLODAP.egg-info/SOURCES.txt +2 -3
- glodap-0.4/GLODAP.egg-info/requires.txt +3 -0
- {glodap-0.3 → glodap-0.4}/PKG-INFO +22 -10
- {glodap-0.3 → glodap-0.4}/README.md +16 -4
- {glodap-0.3 → glodap-0.4}/glodap/__init__.py +148 -48
- {glodap-0.3 → glodap-0.4}/pyproject.toml +18 -5
- glodap-0.3/tests/test_response.py → glodap-0.4/tests/test_download_and_read.py +6 -4
- glodap-0.4/tests/test_regions.py +27 -0
- glodap-0.3/GLODAP.egg-info/requires.txt +0 -3
- glodap-0.3/tests/test_import.py +0 -12
- glodap-0.3/tests/test_regions.py +0 -11
- {glodap-0.3 → glodap-0.4}/GLODAP.egg-info/dependency_links.txt +0 -0
- {glodap-0.3 → glodap-0.4}/GLODAP.egg-info/top_level.txt +0 -0
- {glodap-0.3 → glodap-0.4}/LICENSE +0 -0
- {glodap-0.3 → glodap-0.4}/setup.cfg +0 -0
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: glodap
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4
|
|
4
4
|
Summary: GLODAP downloader and importer in Python
|
|
5
5
|
Classifier: Development Status :: 4 - Beta
|
|
6
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
7
6
|
Classifier: Programming Language :: Python :: 3.11
|
|
8
7
|
Classifier: Programming Language :: Python :: 3.12
|
|
9
8
|
Classifier: Programming Language :: Python :: 3.13
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
10
10
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
11
11
|
Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Natural Language :: English
|
|
13
13
|
Classifier: Intended Audience :: Science/Research
|
|
14
14
|
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
15
15
|
Classifier: Topic :: Scientific/Engineering :: Oceanography
|
|
16
|
-
Requires-Python: >=3.
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
|
-
Requires-Dist: pandas
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist: scipy
|
|
19
|
+
Requires-Dist: pandas<4,>=3.0.3
|
|
20
|
+
Requires-Dist: pooch<2,>=1.9.0
|
|
21
|
+
Requires-Dist: scipy<2,>=1.17.1
|
|
22
22
|
Dynamic: license-file
|
|
23
23
|
|
|
24
24
|
# glodap
|
|
@@ -53,15 +53,15 @@ directly into [PyCO2SYS v2](https://mvdh.xyz/PyCO2SYS):
|
|
|
53
53
|
|
|
54
54
|
```python
|
|
55
55
|
import PyCO2SYS as pyco2
|
|
56
|
-
co2s_atlantic = pyco2.sys(data=df_atlantic, nitrite=
|
|
56
|
+
co2s_atlantic = pyco2.sys(data=df_atlantic.drop(columns="fco2"), nitrite=0)
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
Note `nitrite=
|
|
59
|
+
Note `nitrite=0` - this means PyCO2SYS will ignore the `"nitrite"` column,
|
|
60
60
|
which is necessary because while PyCO2SYS includes the nitrite-nitrous acid
|
|
61
61
|
equilibrium, its equilibrium constant is valid only under lab conditions.
|
|
62
62
|
|
|
63
|
-
Because of how the columns are named, when passing the DataFrame directly to
|
|
64
|
-
PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH
|
|
63
|
+
Because of how the columns are named, and because we dropped the `"fco2"` column, when passing the DataFrame directly to
|
|
64
|
+
PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH nor fCO<sub>2</sub>.
|
|
65
65
|
|
|
66
66
|
The columns are the same as in the original GLODAP .mat files available from [glodap.info](https://glodap.info), except:
|
|
67
67
|
* The `"G2"` at the start of each parameter has been removed.
|
|
@@ -74,3 +74,15 @@ their function docstrings for more information.
|
|
|
74
74
|
|
|
75
75
|
The .mat files from the GEOMAR mirrors are downloaded, and the SHA256 checksum
|
|
76
76
|
of each downloaded file is checked before the file is written to disk.
|
|
77
|
+
|
|
78
|
+
# Citation
|
|
79
|
+
|
|
80
|
+
If using GLODAP data, please cite the paper corresponding to the version you used:
|
|
81
|
+
|
|
82
|
+
* `v3.2026`: TBC (submitted to *Earth System Science Data*)
|
|
83
|
+
* `v2.2023`: https://doi.org/10.5194/essd-16-2047-2024
|
|
84
|
+
* `v2.2022`: https://doi.org/10.5194/essd-14-5543-2022
|
|
85
|
+
* `v2.2021`: https://doi.org/10.5194/essd-13-5565-2021
|
|
86
|
+
* `v2.2020`: https://doi.org/10.5194/essd-12-3653-2020
|
|
87
|
+
* `v2.2019`: https://doi.org/10.5194/essd-11-1437-2019
|
|
88
|
+
* `v2.2016`: https://doi.org/10.5194/essd-8-297-2016
|
|
@@ -12,6 +12,5 @@ glodap.egg-info/SOURCES.txt
|
|
|
12
12
|
glodap.egg-info/dependency_links.txt
|
|
13
13
|
glodap.egg-info/requires.txt
|
|
14
14
|
glodap.egg-info/top_level.txt
|
|
15
|
-
tests/
|
|
16
|
-
tests/test_regions.py
|
|
17
|
-
tests/test_response.py
|
|
15
|
+
tests/test_download_and_read.py
|
|
16
|
+
tests/test_regions.py
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: glodap
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4
|
|
4
4
|
Summary: GLODAP downloader and importer in Python
|
|
5
5
|
Classifier: Development Status :: 4 - Beta
|
|
6
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
7
6
|
Classifier: Programming Language :: Python :: 3.11
|
|
8
7
|
Classifier: Programming Language :: Python :: 3.12
|
|
9
8
|
Classifier: Programming Language :: Python :: 3.13
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
10
10
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
11
11
|
Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Natural Language :: English
|
|
13
13
|
Classifier: Intended Audience :: Science/Research
|
|
14
14
|
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
15
15
|
Classifier: Topic :: Scientific/Engineering :: Oceanography
|
|
16
|
-
Requires-Python: >=3.
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
|
-
Requires-Dist: pandas
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist: scipy
|
|
19
|
+
Requires-Dist: pandas<4,>=3.0.3
|
|
20
|
+
Requires-Dist: pooch<2,>=1.9.0
|
|
21
|
+
Requires-Dist: scipy<2,>=1.17.1
|
|
22
22
|
Dynamic: license-file
|
|
23
23
|
|
|
24
24
|
# glodap
|
|
@@ -53,15 +53,15 @@ directly into [PyCO2SYS v2](https://mvdh.xyz/PyCO2SYS):
|
|
|
53
53
|
|
|
54
54
|
```python
|
|
55
55
|
import PyCO2SYS as pyco2
|
|
56
|
-
co2s_atlantic = pyco2.sys(data=df_atlantic, nitrite=
|
|
56
|
+
co2s_atlantic = pyco2.sys(data=df_atlantic.drop(columns="fco2"), nitrite=0)
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
Note `nitrite=
|
|
59
|
+
Note `nitrite=0` - this means PyCO2SYS will ignore the `"nitrite"` column,
|
|
60
60
|
which is necessary because while PyCO2SYS includes the nitrite-nitrous acid
|
|
61
61
|
equilibrium, its equilibrium constant is valid only under lab conditions.
|
|
62
62
|
|
|
63
|
-
Because of how the columns are named, when passing the DataFrame directly to
|
|
64
|
-
PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH
|
|
63
|
+
Because of how the columns are named, and because we dropped the `"fco2"` column, when passing the DataFrame directly to
|
|
64
|
+
PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH nor fCO<sub>2</sub>.
|
|
65
65
|
|
|
66
66
|
The columns are the same as in the original GLODAP .mat files available from [glodap.info](https://glodap.info), except:
|
|
67
67
|
* The `"G2"` at the start of each parameter has been removed.
|
|
@@ -74,3 +74,15 @@ their function docstrings for more information.
|
|
|
74
74
|
|
|
75
75
|
The .mat files from the GEOMAR mirrors are downloaded, and the SHA256 checksum
|
|
76
76
|
of each downloaded file is checked before the file is written to disk.
|
|
77
|
+
|
|
78
|
+
# Citation
|
|
79
|
+
|
|
80
|
+
If using GLODAP data, please cite the paper corresponding to the version you used:
|
|
81
|
+
|
|
82
|
+
* `v3.2026`: TBC (submitted to *Earth System Science Data*)
|
|
83
|
+
* `v2.2023`: https://doi.org/10.5194/essd-16-2047-2024
|
|
84
|
+
* `v2.2022`: https://doi.org/10.5194/essd-14-5543-2022
|
|
85
|
+
* `v2.2021`: https://doi.org/10.5194/essd-13-5565-2021
|
|
86
|
+
* `v2.2020`: https://doi.org/10.5194/essd-12-3653-2020
|
|
87
|
+
* `v2.2019`: https://doi.org/10.5194/essd-11-1437-2019
|
|
88
|
+
* `v2.2016`: https://doi.org/10.5194/essd-8-297-2016
|
|
@@ -30,15 +30,15 @@ directly into [PyCO2SYS v2](https://mvdh.xyz/PyCO2SYS):
|
|
|
30
30
|
|
|
31
31
|
```python
|
|
32
32
|
import PyCO2SYS as pyco2
|
|
33
|
-
co2s_atlantic = pyco2.sys(data=df_atlantic, nitrite=
|
|
33
|
+
co2s_atlantic = pyco2.sys(data=df_atlantic.drop(columns="fco2"), nitrite=0)
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
Note `nitrite=
|
|
36
|
+
Note `nitrite=0` - this means PyCO2SYS will ignore the `"nitrite"` column,
|
|
37
37
|
which is necessary because while PyCO2SYS includes the nitrite-nitrous acid
|
|
38
38
|
equilibrium, its equilibrium constant is valid only under lab conditions.
|
|
39
39
|
|
|
40
|
-
Because of how the columns are named, when passing the DataFrame directly to
|
|
41
|
-
PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH
|
|
40
|
+
Because of how the columns are named, and because we dropped the `"fco2"` column, when passing the DataFrame directly to
|
|
41
|
+
PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH nor fCO<sub>2</sub>.
|
|
42
42
|
|
|
43
43
|
The columns are the same as in the original GLODAP .mat files available from [glodap.info](https://glodap.info), except:
|
|
44
44
|
* The `"G2"` at the start of each parameter has been removed.
|
|
@@ -51,3 +51,15 @@ their function docstrings for more information.
|
|
|
51
51
|
|
|
52
52
|
The .mat files from the GEOMAR mirrors are downloaded, and the SHA256 checksum
|
|
53
53
|
of each downloaded file is checked before the file is written to disk.
|
|
54
|
+
|
|
55
|
+
# Citation
|
|
56
|
+
|
|
57
|
+
If using GLODAP data, please cite the paper corresponding to the version you used:
|
|
58
|
+
|
|
59
|
+
* `v3.2026`: TBC (submitted to *Earth System Science Data*)
|
|
60
|
+
* `v2.2023`: https://doi.org/10.5194/essd-16-2047-2024
|
|
61
|
+
* `v2.2022`: https://doi.org/10.5194/essd-14-5543-2022
|
|
62
|
+
* `v2.2021`: https://doi.org/10.5194/essd-13-5565-2021
|
|
63
|
+
* `v2.2020`: https://doi.org/10.5194/essd-12-3653-2020
|
|
64
|
+
* `v2.2019`: https://doi.org/10.5194/essd-11-1437-2019
|
|
65
|
+
* `v2.2016`: https://doi.org/10.5194/essd-8-297-2016
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"""
|
|
2
2
|
GLODAP
|
|
3
3
|
======
|
|
4
|
-
Download GLODAP
|
|
5
|
-
DataFrames.
|
|
4
|
+
Download Global Ocean Data Analysis Project (GLODAP; https://glodap.info)
|
|
5
|
+
datasets and import them as pandas DataFrames.
|
|
6
6
|
|
|
7
7
|
The functions `arctic`, `atlantic`, `indian`, `pacific` and `world` import the
|
|
8
8
|
latest version of the GLODAP dataset for the corresponding region, first
|
|
@@ -40,23 +40,32 @@ The .mat files from the GEOMAR mirrors are downloaded, and the SHA256 checksum
|
|
|
40
40
|
of each downloaded file is checked before the file is written to disk.
|
|
41
41
|
"""
|
|
42
42
|
|
|
43
|
-
import hashlib
|
|
44
43
|
import os
|
|
44
|
+
import shutil
|
|
45
45
|
import tempfile
|
|
46
|
-
from
|
|
46
|
+
from pathlib import Path
|
|
47
47
|
|
|
48
|
+
import numpy as np
|
|
48
49
|
import pandas as pd
|
|
49
|
-
import
|
|
50
|
+
import pooch
|
|
50
51
|
from scipy.io import loadmat
|
|
51
52
|
|
|
52
53
|
|
|
53
54
|
# Package metadata
|
|
54
55
|
__author__ = "Humphreys, Matthew P."
|
|
55
|
-
__version__ = "0.
|
|
56
|
+
__version__ = "0.4"
|
|
56
57
|
|
|
57
58
|
# GLODAP metadata
|
|
58
|
-
version_latest = "
|
|
59
|
-
versions = [
|
|
59
|
+
version_latest = "v3.2026"
|
|
60
|
+
versions = [
|
|
61
|
+
"v3.2026",
|
|
62
|
+
"v2.2023",
|
|
63
|
+
"v2.2022",
|
|
64
|
+
"v2.2021",
|
|
65
|
+
"v2.2020",
|
|
66
|
+
"v2.2019",
|
|
67
|
+
"v2.2016",
|
|
68
|
+
]
|
|
60
69
|
regions = {
|
|
61
70
|
"arctic": "Arctic_Ocean",
|
|
62
71
|
"atlantic": "Atlantic_Ocean",
|
|
@@ -67,7 +76,15 @@ regions = {
|
|
|
67
76
|
regions_full = regions.copy()
|
|
68
77
|
for k, v in regions.items():
|
|
69
78
|
regions_full[k[:3]] = v
|
|
79
|
+
regions_short_to_long = {k[:3]: k for k in regions}
|
|
70
80
|
checksums = {
|
|
81
|
+
"v3.2026": {
|
|
82
|
+
"arc": "03dfcf59525931065247e142439d97c0ed88d8f572e87df919476deebdc57d5c",
|
|
83
|
+
"atl": "a4577bbb676c30327b185fc5bf0ddc0e302464d5332b6d630922faf536dbe68c",
|
|
84
|
+
"ind": "79d655bd203e4579007b7224fc53b87ee8a5d70bb733550f0acac260a6baa0d8",
|
|
85
|
+
"pac": "1a5afbb6be199773e00772ca3b1b84241dfc52a591b3f6b85786180f5711a9b4",
|
|
86
|
+
"wor": "214aeb49c618474bf92622a37d2795a10160954ab49a94f9052cff1dd41947fd",
|
|
87
|
+
},
|
|
71
88
|
"v2.2023": {
|
|
72
89
|
"arc": "a998a8d99db84e9357b21a7e345bbfde62eae77870e651119b4c1929a2f1e2fd",
|
|
73
90
|
"atl": "a3ff7bc4f4ff3a1b0f540886a0eb7c9b3ec52aa4eae2dea57d47ae61f56da56f",
|
|
@@ -103,6 +120,13 @@ checksums = {
|
|
|
103
120
|
"pac": "88df995e272dd63db55421b911be1f99bfec4cac6f97a73e017c9e275bf29db2",
|
|
104
121
|
"wor": "4637ce5eb560fe020e9fccf0370156bfe19498fc74c2e8b66dee190cc44cff63",
|
|
105
122
|
},
|
|
123
|
+
"v2.2016": {
|
|
124
|
+
"arc": "f2214409e0526052903da2427f3f8c6fd433b1759ba2a1be3a61181b4b0d04b7",
|
|
125
|
+
"atl": "fb26a86ca1135a0afc94157ba7963bc1cb8138523bcba36360595641175f8da1",
|
|
126
|
+
"ind": "ba162aa6f1fa7209f586e503581d3cc05cdffbfa6f72bdc535824f7a78d694f9",
|
|
127
|
+
"pac": "0d1666de27ad6853533651027459d2525f75c6681d540f129df705b018d3c931",
|
|
128
|
+
"wor": "aa202e330d5e77b98d0062e40a40665b8397b83ebbfa00424532139c53814f5e",
|
|
129
|
+
},
|
|
106
130
|
}
|
|
107
131
|
|
|
108
132
|
|
|
@@ -113,13 +137,16 @@ def _get_paths(region, version, gpath):
|
|
|
113
137
|
version = version.lower()
|
|
114
138
|
assert version in versions, "`version` not valid!"
|
|
115
139
|
if gpath is None:
|
|
116
|
-
gpath =
|
|
140
|
+
gpath = Path(Path.home(), ".glodap")
|
|
117
141
|
fileregion = regions_full[region.lower()]
|
|
118
|
-
|
|
142
|
+
if version.startswith("v2"):
|
|
143
|
+
filename = f"{fileregion}_{version}.mat"
|
|
144
|
+
elif version.startswith("v3"):
|
|
145
|
+
filename = f"{fileregion}_{version}.csv.zip"
|
|
119
146
|
return gpath, fileregion, filename, version
|
|
120
147
|
|
|
121
148
|
|
|
122
|
-
def download(region="world", version=None, gpath=None
|
|
149
|
+
def download(region="world", version=None, gpath=None):
|
|
123
150
|
"""Download a GLODAP data file and save it locally, after checking that it
|
|
124
151
|
has the expected checksum (SHA256).
|
|
125
152
|
|
|
@@ -136,7 +163,13 @@ def download(region="world", version=None, gpath=None, chunk_size=8192):
|
|
|
136
163
|
version : str or None, optional
|
|
137
164
|
Which GLODAP version to download, by default `None`, in which case the
|
|
138
165
|
most recent version is downloaded. The options are:
|
|
139
|
-
"
|
|
166
|
+
"v3.2026" (the original GLODAPv3)
|
|
167
|
+
"v2.2023",
|
|
168
|
+
"v2.2022",
|
|
169
|
+
"v2.2021",
|
|
170
|
+
"v2.2020",
|
|
171
|
+
"v2.2019",
|
|
172
|
+
"v2.2016" (the original GLODAPv2).
|
|
140
173
|
gpath : str of None, optional
|
|
141
174
|
Where to save the downloaded file, by default `None`, in which case the
|
|
142
175
|
file is saved at "~/.glodap".
|
|
@@ -146,24 +179,29 @@ def download(region="world", version=None, gpath=None, chunk_size=8192):
|
|
|
146
179
|
gpath, fileregion, filename, version = _get_paths(region, version, gpath)
|
|
147
180
|
if not os.path.isdir(gpath):
|
|
148
181
|
os.makedirs(gpath)
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
182
|
+
if version == "v2.2016":
|
|
183
|
+
fr = fileregion.replace("_", " ")
|
|
184
|
+
url = (
|
|
185
|
+
f"https://glodap.info/glodap_files/{version}/"
|
|
186
|
+
+ f"GLODAPv2 {fr}.mat"
|
|
187
|
+
)
|
|
188
|
+
elif version.startswith("v2"):
|
|
189
|
+
url = (
|
|
190
|
+
f"https://glodap.info/glodap_files/{version}/"
|
|
191
|
+
+ f"GLODAP{version}_{fileregion}.mat"
|
|
192
|
+
)
|
|
193
|
+
elif version.startswith("v3"):
|
|
194
|
+
url = (
|
|
195
|
+
"https://glodap.info/glodap_files/v3/"
|
|
196
|
+
+ f"GLODAPv3_{fileregion}.csv.zip"
|
|
197
|
+
)
|
|
154
198
|
checksum = checksums[version][region[:3].lower()]
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
f.write(chunk)
|
|
162
|
-
hasher.update(chunk)
|
|
163
|
-
if hasher.hexdigest() == checksum:
|
|
164
|
-
os.rename(temp_path, os.path.join(gpath, filename))
|
|
165
|
-
else:
|
|
166
|
-
warn("File checksum not as expected - download failed.")
|
|
199
|
+
pooch.retrieve(
|
|
200
|
+
url,
|
|
201
|
+
known_hash=f"sha256:{checksum}",
|
|
202
|
+
fname=filename,
|
|
203
|
+
path=gpath,
|
|
204
|
+
)
|
|
167
205
|
|
|
168
206
|
|
|
169
207
|
def read(region="world", version=None, gpath=None):
|
|
@@ -183,7 +221,13 @@ def read(region="world", version=None, gpath=None):
|
|
|
183
221
|
version : str or None, optional
|
|
184
222
|
Which GLODAP version to import, by default `None`, in which case the
|
|
185
223
|
most recent version is imported. The options are:
|
|
186
|
-
"
|
|
224
|
+
"v3.2026" (the original GLODAPv3)
|
|
225
|
+
"v2.2023",
|
|
226
|
+
"v2.2022",
|
|
227
|
+
"v2.2021",
|
|
228
|
+
"v2.2020",
|
|
229
|
+
"v2.2019",
|
|
230
|
+
"v2.2016" (the original GLODAPv2).
|
|
187
231
|
gpath : str of None, optional
|
|
188
232
|
Where to the downloaded file is or should be saved, by default `None`,
|
|
189
233
|
in which case the file is imported from or saved at "~/.glodap".
|
|
@@ -193,19 +237,30 @@ def read(region="world", version=None, gpath=None):
|
|
|
193
237
|
pd.DataFrame
|
|
194
238
|
The GLODAP dataset as a pandas DataFrame.
|
|
195
239
|
"""
|
|
240
|
+
if region.lower() in regions_short_to_long:
|
|
241
|
+
region = regions_short_to_long[region.lower()]
|
|
196
242
|
gpath, _, filename, version = _get_paths(region, version, gpath)
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
243
|
+
download(region=region, version=version, gpath=gpath)
|
|
244
|
+
if version.startswith("v2"):
|
|
245
|
+
df = loadmat(Path(gpath, filename))
|
|
246
|
+
df = pd.DataFrame(
|
|
247
|
+
{
|
|
248
|
+
k[2:]: [w[0][0] for w in v] if v.dtype == "O" else v.ravel()
|
|
249
|
+
for k, v in df.items()
|
|
250
|
+
if k.startswith("G2")
|
|
251
|
+
}
|
|
252
|
+
)
|
|
253
|
+
elif version.startswith("v3"):
|
|
254
|
+
with tempfile.TemporaryDirectory() as tdir:
|
|
255
|
+
shutil.unpack_archive(Path(gpath, filename), tdir)
|
|
256
|
+
tfilename = [f for f in os.listdir(tdir) if f.endswith(".csv")][0]
|
|
257
|
+
df = pd.read_csv(
|
|
258
|
+
Path(tdir, tfilename),
|
|
259
|
+
dtype={
|
|
260
|
+
"expocode": str,
|
|
261
|
+
"ph_scale": str,
|
|
262
|
+
},
|
|
263
|
+
).replace([-9999, "-9999"], np.nan)
|
|
209
264
|
# Convert columns that should be integers into integers
|
|
210
265
|
# Can't convert cast, hour, minute to integers because they have missing
|
|
211
266
|
# values
|
|
@@ -251,11 +306,26 @@ def read(region="world", version=None, gpath=None):
|
|
|
251
306
|
"tdnf",
|
|
252
307
|
"chlaf",
|
|
253
308
|
]
|
|
309
|
+
if region in ["indian", "world"] and version == "v2.2016":
|
|
310
|
+
for k in keys_flags:
|
|
311
|
+
if k in df:
|
|
312
|
+
df.loc[df[k].isnull(), k] = 9
|
|
254
313
|
for k in keys_integers + keys_flags:
|
|
255
|
-
|
|
314
|
+
if k in df:
|
|
315
|
+
df[k] = df[k].astype(int)
|
|
256
316
|
# Rename columns for PyCO2SYS, if requested
|
|
257
317
|
renamer_flags = {k: k[:-1] + "_f" for k in keys_flags}
|
|
258
318
|
df = df.rename(columns=renamer_flags)
|
|
319
|
+
# Correct fatal datetime errors in v2.2016
|
|
320
|
+
if version == "v2.2016":
|
|
321
|
+
if region in ["indian", "world"]:
|
|
322
|
+
L = (df.cruise == 696) & (df.station == 15537)
|
|
323
|
+
df.loc[L, "month"] = 12
|
|
324
|
+
df.loc[L, "day"] = 1
|
|
325
|
+
if region in ["pacific", "world"]:
|
|
326
|
+
L = (df.cruise == 270) & (df.station == 113)
|
|
327
|
+
df.loc[L, "month"] = 4
|
|
328
|
+
df.loc[L, "day"] = 30
|
|
259
329
|
# Calculate datetime for convenience - don't include hour and minute
|
|
260
330
|
# because some are missing
|
|
261
331
|
df["datetime"] = pd.to_datetime(
|
|
@@ -281,7 +351,13 @@ def arctic(version=None, gpath=None):
|
|
|
281
351
|
version : str or None, optional
|
|
282
352
|
Which GLODAP version to import, by default `None`, in which case the
|
|
283
353
|
most recent version is imported. The options are:
|
|
284
|
-
"
|
|
354
|
+
"v3.2026" (the original GLODAPv3)
|
|
355
|
+
"v2.2023",
|
|
356
|
+
"v2.2022",
|
|
357
|
+
"v2.2021",
|
|
358
|
+
"v2.2020",
|
|
359
|
+
"v2.2019",
|
|
360
|
+
"v2.2016" (the original GLODAPv2).
|
|
285
361
|
gpath : str of None, optional
|
|
286
362
|
Where to the downloaded file is or should be saved, by default `None`,
|
|
287
363
|
in which case the file is imported from or saved at "~/.glodap".
|
|
@@ -307,7 +383,13 @@ def atlantic(version=None, gpath=None):
|
|
|
307
383
|
version : str or None, optional
|
|
308
384
|
Which GLODAP version to import, by default `None`, in which case the
|
|
309
385
|
most recent version is imported. The options are:
|
|
310
|
-
"
|
|
386
|
+
"v3.2026" (the original GLODAPv3)
|
|
387
|
+
"v2.2023",
|
|
388
|
+
"v2.2022",
|
|
389
|
+
"v2.2021",
|
|
390
|
+
"v2.2020",
|
|
391
|
+
"v2.2019",
|
|
392
|
+
"v2.2016" (the original GLODAPv2).
|
|
311
393
|
gpath : str of None, optional
|
|
312
394
|
Where to the downloaded file is or should be saved, by default `None`,
|
|
313
395
|
in which case the file is imported from or saved at "~/.glodap".
|
|
@@ -333,7 +415,13 @@ def indian(version=None, gpath=None):
|
|
|
333
415
|
version : str or None, optional
|
|
334
416
|
Which GLODAP version to import, by default `None`, in which case the
|
|
335
417
|
most recent version is imported. The options are:
|
|
336
|
-
"
|
|
418
|
+
"v3.2026" (the original GLODAPv3)
|
|
419
|
+
"v2.2023",
|
|
420
|
+
"v2.2022",
|
|
421
|
+
"v2.2021",
|
|
422
|
+
"v2.2020",
|
|
423
|
+
"v2.2019",
|
|
424
|
+
"v2.2016" (the original GLODAPv2).
|
|
337
425
|
gpath : str of None, optional
|
|
338
426
|
Where to the downloaded file is or should be saved, by default `None`,
|
|
339
427
|
in which case the file is imported from or saved at "~/.glodap".
|
|
@@ -359,7 +447,13 @@ def pacific(version=None, gpath=None):
|
|
|
359
447
|
version : str or None, optional
|
|
360
448
|
Which GLODAP version to import, by default `None`, in which case the
|
|
361
449
|
most recent version is imported. The options are:
|
|
362
|
-
"
|
|
450
|
+
"v3.2026" (the original GLODAPv3)
|
|
451
|
+
"v2.2023",
|
|
452
|
+
"v2.2022",
|
|
453
|
+
"v2.2021",
|
|
454
|
+
"v2.2020",
|
|
455
|
+
"v2.2019",
|
|
456
|
+
"v2.2016" (the original GLODAPv2).
|
|
363
457
|
gpath : str of None, optional
|
|
364
458
|
Where to the downloaded file is or should be saved, by default `None`,
|
|
365
459
|
in which case the file is imported from or saved at "~/.glodap".
|
|
@@ -385,7 +479,13 @@ def world(version=None, gpath=None):
|
|
|
385
479
|
version : str or None, optional
|
|
386
480
|
Which GLODAP version to import, by default `None`, in which case the
|
|
387
481
|
most recent version is imported. The options are:
|
|
388
|
-
"
|
|
482
|
+
"v3.2026" (the original GLODAPv3)
|
|
483
|
+
"v2.2023",
|
|
484
|
+
"v2.2022",
|
|
485
|
+
"v2.2021",
|
|
486
|
+
"v2.2020",
|
|
487
|
+
"v2.2019",
|
|
488
|
+
"v2.2016" (the original GLODAPv2).
|
|
389
489
|
gpath : str of None, optional
|
|
390
490
|
Where to the downloaded file is or should be saved, by default `None`,
|
|
391
491
|
in which case the file is imported from or saved at "~/.glodap".
|
|
@@ -8,18 +8,18 @@ build-backend = "setuptools.build_meta"
|
|
|
8
8
|
name = "glodap"
|
|
9
9
|
description = "GLODAP downloader and importer in Python"
|
|
10
10
|
readme = "README.md"
|
|
11
|
-
requires-python = ">= 3.
|
|
11
|
+
requires-python = ">= 3.11"
|
|
12
12
|
dependencies = [
|
|
13
|
-
"pandas",
|
|
14
|
-
"
|
|
15
|
-
"scipy",
|
|
13
|
+
"pandas>=3.0.3,<4",
|
|
14
|
+
"pooch>=1.9.0,<2",
|
|
15
|
+
"scipy>=1.17.1,<2",
|
|
16
16
|
]
|
|
17
17
|
classifiers = [
|
|
18
18
|
"Development Status :: 4 - Beta",
|
|
19
|
-
"Programming Language :: Python :: 3.10",
|
|
20
19
|
"Programming Language :: Python :: 3.11",
|
|
21
20
|
"Programming Language :: Python :: 3.12",
|
|
22
21
|
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Programming Language :: Python :: 3.14",
|
|
23
23
|
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
|
24
24
|
"Operating System :: OS Independent",
|
|
25
25
|
"Natural Language :: English",
|
|
@@ -34,3 +34,16 @@ include = ["glodap*"]
|
|
|
34
34
|
|
|
35
35
|
[tool.setuptools.dynamic]
|
|
36
36
|
version = {attr = "glodap.__version__"}
|
|
37
|
+
|
|
38
|
+
[tool.ruff]
|
|
39
|
+
line-length = 79
|
|
40
|
+
|
|
41
|
+
[tool.ruff.lint.isort]
|
|
42
|
+
combine-as-imports = true
|
|
43
|
+
force-single-line = false
|
|
44
|
+
lines-after-imports = 2
|
|
45
|
+
|
|
46
|
+
[dependency-groups]
|
|
47
|
+
dev = [
|
|
48
|
+
"ipykernel>=7.3.0",
|
|
49
|
+
]
|
|
@@ -2,16 +2,18 @@
|
|
|
2
2
|
import itertools
|
|
3
3
|
import tempfile
|
|
4
4
|
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
5
7
|
import glodap
|
|
6
8
|
|
|
7
9
|
|
|
8
|
-
def
|
|
10
|
+
def test_download_and_read():
|
|
9
11
|
with tempfile.TemporaryDirectory() as tdir:
|
|
10
12
|
for region, version in itertools.product(
|
|
11
13
|
glodap.regions, glodap.versions
|
|
12
14
|
):
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
df = glodap.read(region=region, version=version, gpath=tdir)
|
|
16
|
+
assert isinstance(df, pd.DataFrame)
|
|
15
17
|
|
|
16
18
|
|
|
17
|
-
#
|
|
19
|
+
# test_download_and_read()
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# %%
|
|
2
|
+
import pandas as pd
|
|
3
|
+
|
|
4
|
+
import glodap
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_region_names():
|
|
8
|
+
# Check that the first 3 letters of each region name are unique
|
|
9
|
+
regions_short = {k[:3] for k in glodap.regions}
|
|
10
|
+
assert len(regions_short) == len(glodap.regions)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_regions_latest():
|
|
14
|
+
df = glodap.arctic()
|
|
15
|
+
assert isinstance(df, pd.DataFrame)
|
|
16
|
+
df = glodap.atlantic()
|
|
17
|
+
assert isinstance(df, pd.DataFrame)
|
|
18
|
+
df = glodap.indian()
|
|
19
|
+
assert isinstance(df, pd.DataFrame)
|
|
20
|
+
df = glodap.pacific()
|
|
21
|
+
assert isinstance(df, pd.DataFrame)
|
|
22
|
+
df = glodap.world()
|
|
23
|
+
assert isinstance(df, pd.DataFrame)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# test_region_names()
|
|
27
|
+
# test_regions_latest()
|
glodap-0.3/tests/test_import.py
DELETED
glodap-0.3/tests/test_regions.py
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|