GLODAP 0.4__tar.gz → 1.0.0__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.
@@ -1,12 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: glodap
3
- Version: 0.4
3
+ Version: 1.0.0
4
4
  Summary: GLODAP downloader and importer in Python
5
- Classifier: Development Status :: 4 - Beta
5
+ Classifier: Development Status :: 5 - Production/Stable
6
6
  Classifier: Programming Language :: Python :: 3.11
7
7
  Classifier: Programming Language :: Python :: 3.12
8
8
  Classifier: Programming Language :: Python :: 3.13
9
9
  Classifier: Programming Language :: Python :: 3.14
10
+ Classifier: Programming Language :: Python :: 3.15
10
11
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
11
12
  Classifier: Operating System :: OS Independent
12
13
  Classifier: Natural Language :: English
@@ -16,9 +17,9 @@ Classifier: Topic :: Scientific/Engineering :: Oceanography
16
17
  Requires-Python: >=3.11
17
18
  Description-Content-Type: text/markdown
18
19
  License-File: LICENSE
19
- Requires-Dist: pandas<4,>=3.0.3
20
+ Requires-Dist: pandas<4,>=3
20
21
  Requires-Dist: pooch<2,>=1.9.0
21
- Requires-Dist: scipy<2,>=1.17.1
22
+ Requires-Dist: scipy<2,>=1.17
22
23
  Dynamic: license-file
23
24
 
24
25
  # glodap
@@ -26,6 +27,7 @@ Dynamic: license-file
26
27
  [![Tests](https://github.com/mvdh7/glodap/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/mvdh7/glodap/actions)
27
28
  [![pypi badge](https://img.shields.io/pypi/v/glodap.svg?style=popout)](https://pypi.org/project/glodap/)
28
29
  [![Conda Version](https://img.shields.io/conda/vn/conda-forge/glodap.svg)](https://anaconda.org/conda-forge/glodap)
30
+ [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.21295574-informational)](https://doi.org/10.5281/zenodo.21295574)
29
31
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
30
32
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
31
33
 
@@ -48,8 +50,21 @@ df_atlantic = glodap.atlantic()
48
50
  Files are saved by default at `"~/.glodap"`, but this can be controlled with the
49
51
  kwarg `gpath`. See the function docstrings for more information.
50
52
 
51
- The columns of the imported DataFrames can be passed
52
- directly into [PyCO2SYS v2](https://mvdh.xyz/PyCO2SYS):
53
+ The columns are the same as in the original GLODAP .mat files available from [glodap.info](https://glodap.info), except:
54
+ * The `"G2"` at the start of each parameter has been removed.
55
+ * Flags end with `"_f"` instead of just `"f"`.
56
+ * There is a `"datetime"` column, which combines the `"year"`, `"month"` and `"day"` but NOT the `"hour"` and `"minute"` (because some of these are missing).
57
+
58
+ The functions `download` and `read` can also be used for finer control, such as
59
+ specifying a particular GLODAP version rather than using the latest one (currently `v3.2026`). See
60
+ their function docstrings for more information.
61
+
62
+ The files from the GEOMAR mirrors are downloaded (v2: .mat files; v3: .csv.zip files), and the SHA256 checksum
63
+ of each downloaded file is checked before the file is written to disk.
64
+
65
+ ### With PyCO2SYS
66
+
67
+ The columns of the imported DataFrames can be passed directly into [PyCO2SYS v2](https://mvdh.xyz/PyCO2SYS):
53
68
 
54
69
  ```python
55
70
  import PyCO2SYS as pyco2
@@ -63,21 +78,9 @@ equilibrium, its equilibrium constant is valid only under lab conditions.
63
78
  Because of how the columns are named, and because we dropped the `"fco2"` column, when passing the DataFrame directly to
64
79
  PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH nor fCO<sub>2</sub>.
65
80
 
66
- The columns are the same as in the original GLODAP .mat files available from [glodap.info](https://glodap.info), except:
67
- * The `"G2"` at the start of each parameter has been removed.
68
- * Flags end with `"_f"` instead of just `"f"`.
69
- * There is a `"datetime"` column, which combines the `"year"`, `"month"` and `"day"` but NOT the `"hour"` and `"minute"` (because some of these are missing).
70
-
71
- The functions `download` and `read` can also be used for finer control, such as
72
- specifying a particular GLODAP version rather than using the latest one. See
73
- their function docstrings for more information.
74
-
75
- The .mat files from the GEOMAR mirrors are downloaded, and the SHA256 checksum
76
- of each downloaded file is checked before the file is written to disk.
77
-
78
- # Citation
81
+ ## Cite
79
82
 
80
- If using GLODAP data, please cite the paper corresponding to the version you used:
83
+ If you use GLODAP data, please cite the paper corresponding to the version you used:
81
84
 
82
85
  * `v3.2026`: TBC (submitted to *Earth System Science Data*)
83
86
  * `v2.2023`: https://doi.org/10.5194/essd-16-2047-2024
@@ -86,3 +89,9 @@ If using GLODAP data, please cite the paper corresponding to the version you use
86
89
  * `v2.2020`: https://doi.org/10.5194/essd-12-3653-2020
87
90
  * `v2.2019`: https://doi.org/10.5194/essd-11-1437-2019
88
91
  * `v2.2016`: https://doi.org/10.5194/essd-8-297-2016
92
+
93
+ If your analysis leans heavily on a specific subset of GLODAP, please consider inviting the PIs of the relevant datasets to be contribute as co-authors.
94
+
95
+ If you would also like to cite this tool directly:
96
+
97
+ > Humphreys, M. P. (2026). GLODAP downloader and importer in Python [Computer software]. *Zenodo.* https://doi.org/10.5281/zenodo.21295574
@@ -13,4 +13,5 @@ glodap.egg-info/dependency_links.txt
13
13
  glodap.egg-info/requires.txt
14
14
  glodap.egg-info/top_level.txt
15
15
  tests/test_download_and_read.py
16
- tests/test_regions.py
16
+ tests/test_regions.py
17
+ tests/test_versions.py
@@ -0,0 +1,3 @@
1
+ pandas<4,>=3
2
+ pooch<2,>=1.9.0
3
+ scipy<2,>=1.17
@@ -1,12 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: glodap
3
- Version: 0.4
3
+ Version: 1.0.0
4
4
  Summary: GLODAP downloader and importer in Python
5
- Classifier: Development Status :: 4 - Beta
5
+ Classifier: Development Status :: 5 - Production/Stable
6
6
  Classifier: Programming Language :: Python :: 3.11
7
7
  Classifier: Programming Language :: Python :: 3.12
8
8
  Classifier: Programming Language :: Python :: 3.13
9
9
  Classifier: Programming Language :: Python :: 3.14
10
+ Classifier: Programming Language :: Python :: 3.15
10
11
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
11
12
  Classifier: Operating System :: OS Independent
12
13
  Classifier: Natural Language :: English
@@ -16,9 +17,9 @@ Classifier: Topic :: Scientific/Engineering :: Oceanography
16
17
  Requires-Python: >=3.11
17
18
  Description-Content-Type: text/markdown
18
19
  License-File: LICENSE
19
- Requires-Dist: pandas<4,>=3.0.3
20
+ Requires-Dist: pandas<4,>=3
20
21
  Requires-Dist: pooch<2,>=1.9.0
21
- Requires-Dist: scipy<2,>=1.17.1
22
+ Requires-Dist: scipy<2,>=1.17
22
23
  Dynamic: license-file
23
24
 
24
25
  # glodap
@@ -26,6 +27,7 @@ Dynamic: license-file
26
27
  [![Tests](https://github.com/mvdh7/glodap/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/mvdh7/glodap/actions)
27
28
  [![pypi badge](https://img.shields.io/pypi/v/glodap.svg?style=popout)](https://pypi.org/project/glodap/)
28
29
  [![Conda Version](https://img.shields.io/conda/vn/conda-forge/glodap.svg)](https://anaconda.org/conda-forge/glodap)
30
+ [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.21295574-informational)](https://doi.org/10.5281/zenodo.21295574)
29
31
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
30
32
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
31
33
 
@@ -48,8 +50,21 @@ df_atlantic = glodap.atlantic()
48
50
  Files are saved by default at `"~/.glodap"`, but this can be controlled with the
49
51
  kwarg `gpath`. See the function docstrings for more information.
50
52
 
51
- The columns of the imported DataFrames can be passed
52
- directly into [PyCO2SYS v2](https://mvdh.xyz/PyCO2SYS):
53
+ The columns are the same as in the original GLODAP .mat files available from [glodap.info](https://glodap.info), except:
54
+ * The `"G2"` at the start of each parameter has been removed.
55
+ * Flags end with `"_f"` instead of just `"f"`.
56
+ * There is a `"datetime"` column, which combines the `"year"`, `"month"` and `"day"` but NOT the `"hour"` and `"minute"` (because some of these are missing).
57
+
58
+ The functions `download` and `read` can also be used for finer control, such as
59
+ specifying a particular GLODAP version rather than using the latest one (currently `v3.2026`). See
60
+ their function docstrings for more information.
61
+
62
+ The files from the GEOMAR mirrors are downloaded (v2: .mat files; v3: .csv.zip files), and the SHA256 checksum
63
+ of each downloaded file is checked before the file is written to disk.
64
+
65
+ ### With PyCO2SYS
66
+
67
+ The columns of the imported DataFrames can be passed directly into [PyCO2SYS v2](https://mvdh.xyz/PyCO2SYS):
53
68
 
54
69
  ```python
55
70
  import PyCO2SYS as pyco2
@@ -63,21 +78,9 @@ equilibrium, its equilibrium constant is valid only under lab conditions.
63
78
  Because of how the columns are named, and because we dropped the `"fco2"` column, when passing the DataFrame directly to
64
79
  PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH nor fCO<sub>2</sub>.
65
80
 
66
- The columns are the same as in the original GLODAP .mat files available from [glodap.info](https://glodap.info), except:
67
- * The `"G2"` at the start of each parameter has been removed.
68
- * Flags end with `"_f"` instead of just `"f"`.
69
- * There is a `"datetime"` column, which combines the `"year"`, `"month"` and `"day"` but NOT the `"hour"` and `"minute"` (because some of these are missing).
70
-
71
- The functions `download` and `read` can also be used for finer control, such as
72
- specifying a particular GLODAP version rather than using the latest one. See
73
- their function docstrings for more information.
74
-
75
- The .mat files from the GEOMAR mirrors are downloaded, and the SHA256 checksum
76
- of each downloaded file is checked before the file is written to disk.
77
-
78
- # Citation
81
+ ## Cite
79
82
 
80
- If using GLODAP data, please cite the paper corresponding to the version you used:
83
+ If you use GLODAP data, please cite the paper corresponding to the version you used:
81
84
 
82
85
  * `v3.2026`: TBC (submitted to *Earth System Science Data*)
83
86
  * `v2.2023`: https://doi.org/10.5194/essd-16-2047-2024
@@ -86,3 +89,9 @@ If using GLODAP data, please cite the paper corresponding to the version you use
86
89
  * `v2.2020`: https://doi.org/10.5194/essd-12-3653-2020
87
90
  * `v2.2019`: https://doi.org/10.5194/essd-11-1437-2019
88
91
  * `v2.2016`: https://doi.org/10.5194/essd-8-297-2016
92
+
93
+ If your analysis leans heavily on a specific subset of GLODAP, please consider inviting the PIs of the relevant datasets to be contribute as co-authors.
94
+
95
+ If you would also like to cite this tool directly:
96
+
97
+ > Humphreys, M. P. (2026). GLODAP downloader and importer in Python [Computer software]. *Zenodo.* https://doi.org/10.5281/zenodo.21295574
@@ -3,6 +3,7 @@
3
3
  [![Tests](https://github.com/mvdh7/glodap/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/mvdh7/glodap/actions)
4
4
  [![pypi badge](https://img.shields.io/pypi/v/glodap.svg?style=popout)](https://pypi.org/project/glodap/)
5
5
  [![Conda Version](https://img.shields.io/conda/vn/conda-forge/glodap.svg)](https://anaconda.org/conda-forge/glodap)
6
+ [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.21295574-informational)](https://doi.org/10.5281/zenodo.21295574)
6
7
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
7
8
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
8
9
 
@@ -25,8 +26,21 @@ df_atlantic = glodap.atlantic()
25
26
  Files are saved by default at `"~/.glodap"`, but this can be controlled with the
26
27
  kwarg `gpath`. See the function docstrings for more information.
27
28
 
28
- The columns of the imported DataFrames can be passed
29
- directly into [PyCO2SYS v2](https://mvdh.xyz/PyCO2SYS):
29
+ The columns are the same as in the original GLODAP .mat files available from [glodap.info](https://glodap.info), except:
30
+ * The `"G2"` at the start of each parameter has been removed.
31
+ * Flags end with `"_f"` instead of just `"f"`.
32
+ * There is a `"datetime"` column, which combines the `"year"`, `"month"` and `"day"` but NOT the `"hour"` and `"minute"` (because some of these are missing).
33
+
34
+ The functions `download` and `read` can also be used for finer control, such as
35
+ specifying a particular GLODAP version rather than using the latest one (currently `v3.2026`). See
36
+ their function docstrings for more information.
37
+
38
+ The files from the GEOMAR mirrors are downloaded (v2: .mat files; v3: .csv.zip files), and the SHA256 checksum
39
+ of each downloaded file is checked before the file is written to disk.
40
+
41
+ ### With PyCO2SYS
42
+
43
+ The columns of the imported DataFrames can be passed directly into [PyCO2SYS v2](https://mvdh.xyz/PyCO2SYS):
30
44
 
31
45
  ```python
32
46
  import PyCO2SYS as pyco2
@@ -40,21 +54,9 @@ equilibrium, its equilibrium constant is valid only under lab conditions.
40
54
  Because of how the columns are named, and because we dropped the `"fco2"` column, when passing the DataFrame directly to
41
55
  PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH nor fCO<sub>2</sub>.
42
56
 
43
- The columns are the same as in the original GLODAP .mat files available from [glodap.info](https://glodap.info), except:
44
- * The `"G2"` at the start of each parameter has been removed.
45
- * Flags end with `"_f"` instead of just `"f"`.
46
- * There is a `"datetime"` column, which combines the `"year"`, `"month"` and `"day"` but NOT the `"hour"` and `"minute"` (because some of these are missing).
47
-
48
- The functions `download` and `read` can also be used for finer control, such as
49
- specifying a particular GLODAP version rather than using the latest one. See
50
- their function docstrings for more information.
51
-
52
- The .mat files from the GEOMAR mirrors are downloaded, and the SHA256 checksum
53
- of each downloaded file is checked before the file is written to disk.
54
-
55
- # Citation
57
+ ## Cite
56
58
 
57
- If using GLODAP data, please cite the paper corresponding to the version you used:
59
+ If you use GLODAP data, please cite the paper corresponding to the version you used:
58
60
 
59
61
  * `v3.2026`: TBC (submitted to *Earth System Science Data*)
60
62
  * `v2.2023`: https://doi.org/10.5194/essd-16-2047-2024
@@ -63,3 +65,9 @@ If using GLODAP data, please cite the paper corresponding to the version you use
63
65
  * `v2.2020`: https://doi.org/10.5194/essd-12-3653-2020
64
66
  * `v2.2019`: https://doi.org/10.5194/essd-11-1437-2019
65
67
  * `v2.2016`: https://doi.org/10.5194/essd-8-297-2016
68
+
69
+ If your analysis leans heavily on a specific subset of GLODAP, please consider inviting the PIs of the relevant datasets to be contribute as co-authors.
70
+
71
+ If you would also like to cite this tool directly:
72
+
73
+ > Humphreys, M. P. (2026). GLODAP downloader and importer in Python [Computer software]. *Zenodo.* https://doi.org/10.5281/zenodo.21295574
@@ -0,0 +1,406 @@
1
+ """
2
+ GLODAP
3
+ ======
4
+ Download Global Ocean Data Analysis Project (https://glodap.info)
5
+ version 2 and 3 datasets and import them as pandas DataFrames.
6
+
7
+ FUNCTIONS
8
+ ---------
9
+ The functions `arctic`, `atlantic`, `indian`, `pacific` and `world`
10
+ import the latest version (by default) of the GLODAP dataset for the
11
+ corresponding region, first downloading the file if it's not already
12
+ saved locally. For example:
13
+
14
+ >>> import glodap
15
+ >>> df_atlantic = glodap.atlantic()
16
+
17
+ Function kwargs
18
+ ---------------
19
+ All functions (`arctic`, `atlantic`, `indian`, `pacific` and `world`)
20
+ have the same kwargs:
21
+
22
+ version : str or None, optional
23
+ Which GLODAP version to download. All of the options are listed in
24
+ `glodap.versions`. If `None`, then the most recent version is used,
25
+ which is given by `glodap.version_latest`.
26
+ gpath : str or pathlib.Path or None, optional
27
+ Where to look for the GLODAP file and to download it to if not
28
+ found there. If `None`, then `"~/.glodap"` is used.
29
+
30
+ When files are missing, the .mat (v2) or zipped CSV (v3) files from the
31
+ GEOMAR mirrors (i.e., from https://glodap.info) are downloaded. After
32
+ download, the SHA256 checksum of each file is verified and the download
33
+ is rejected in case of mismatch.
34
+
35
+ Function return values
36
+ ----------------------
37
+ The requested GLODAP dataset is returned as a pandas DataFrame.
38
+
39
+ The columns are the same as in the original GLODAP files, except:
40
+ - v2 datasets only: the "G2" at the start of each column name has been
41
+ removed.
42
+ - Flags end with `"_f"` instead of just `"f"`.
43
+ - A `"datetime"` column has been added, which combines the `"year"`,
44
+ `"month"` and `"day"`, but NOT the `"hour"` and `"minute"` (because
45
+ some of these are missing).
46
+
47
+ ATTRIBUTES
48
+ ----------
49
+ versions : list[str]
50
+ All possible GLODAP dataset version strings.
51
+ version_latest : str
52
+ The current latest version, which will be used if the `version`
53
+ kwarg is not provided.
54
+ """
55
+
56
+ from pathlib import Path
57
+ from typing import NamedTuple
58
+ from urllib.parse import quote
59
+
60
+ import numpy as np
61
+ import pandas as pd
62
+ import pooch
63
+ from scipy.io import loadmat
64
+
65
+
66
+ # Package metadata
67
+ __author__ = "Matthew P. Humphreys"
68
+ __version__ = "1.0.0"
69
+ __all__ = [
70
+ "arctic",
71
+ "atlantic",
72
+ "indian",
73
+ "pacific",
74
+ "version_latest",
75
+ "versions",
76
+ "world",
77
+ ]
78
+
79
+ # GLODAP metadata
80
+ version_latest = "v3.2026"
81
+ versions = [
82
+ "v3.2026",
83
+ "v2.2023",
84
+ "v2.2022",
85
+ "v2.2021",
86
+ "v2.2020",
87
+ "v2.2019",
88
+ "v2.2016",
89
+ ]
90
+ _regions = {
91
+ "arctic": "Arctic_Ocean",
92
+ "atlantic": "Atlantic_Ocean",
93
+ "indian": "Indian_Ocean",
94
+ "pacific": "Pacific_Ocean",
95
+ "world": "Merged_Master_File",
96
+ }
97
+ _checksums = {
98
+ "v3.2026": {
99
+ "arctic": "03dfcf59525931065247e142439d97c0ed88d8f572e87df919476deebdc57d5c",
100
+ "atlantic": "a4577bbb676c30327b185fc5bf0ddc0e302464d5332b6d630922faf536dbe68c",
101
+ "indian": "79d655bd203e4579007b7224fc53b87ee8a5d70bb733550f0acac260a6baa0d8",
102
+ "pacific": "1a5afbb6be199773e00772ca3b1b84241dfc52a591b3f6b85786180f5711a9b4",
103
+ "world": "214aeb49c618474bf92622a37d2795a10160954ab49a94f9052cff1dd41947fd",
104
+ },
105
+ "v2.2023": {
106
+ "arctic": "a998a8d99db84e9357b21a7e345bbfde62eae77870e651119b4c1929a2f1e2fd",
107
+ "atlantic": "a3ff7bc4f4ff3a1b0f540886a0eb7c9b3ec52aa4eae2dea57d47ae61f56da56f",
108
+ "indian": "8c9c21d4af9db506b09fdec79e2a311c2dbbf41b8fc4e6a7a855d1d50b3ccb51",
109
+ "pacific": "9891160dba6211d2f13923171564a06bbea34cda799f3091148061c32fc6070c",
110
+ "world": "002881fa71923d15c1bd5aca3b99bc220ad5d1c77a90f130ba1ff0d3910d8766",
111
+ },
112
+ "v2.2022": {
113
+ "arctic": "b2cdeeebfb3ff75701ccc15edb22b5c8e1153623aefc6463f9699ae8780edf15",
114
+ "atlantic": "cffdb28aca195e189b16834a4f9711b90a995ea2b99d95bc6fe498049f975631",
115
+ "indian": "00381b0542ed4e8a39c33ee071fcb2388c1e3b3fb13f76c75fc342b26f4c8a13",
116
+ "pacific": "4037f093d89ea422aa62524273ab40ca147934e34637496372e83f2e34fe9a66",
117
+ "world": "3d7ba5bcf59b0c1f513b6fa8140df0618d984fa7b320899e7f188dd7c6cef565",
118
+ },
119
+ "v2.2021": {
120
+ "arctic": "21e511e808b9cc9f5b8532bf3b1c6754bb4ad6c344adb4a498b71967a0b6d217",
121
+ "atlantic": "22731e474a33d10c3efd3cc6748aafca7e1488495acefe1bbbd26b4105973a21",
122
+ "indian": "d3c43da540e606091a981958b4ce674dbe1ef9777ffee4c90de29bcc74f010a2",
123
+ "pacific": "925cf0424f4cd1caad30cfbe57bdc19740c85e715bee06bd298893915cfc5a01",
124
+ "world": "8329acd8722a3c198455642f8fca29b05f460b149e178fef9e1041f2caa19453",
125
+ },
126
+ "v2.2020": {
127
+ "arctic": "de52e1086b61f68d46cb0142e4bcffae18b578f41c2a00bda40a8960959a94b7",
128
+ "atlantic": "e927d87d873e089311ed5b747195aa150880f59559831bab27a54dcc0ff7ff69",
129
+ "indian": "1d8dfbefb820541d9b10f73d3785dae8653e67166b94666dbb433d3ddfa4e255",
130
+ "pacific": "9a75bf66b38341117afaae947af465f8f7e4082a9f773355c1fbadf26484d544",
131
+ "world": "51e1000101aa61712edb9c0074289bb83c105d17ee8cea575f8e18fa05bde953",
132
+ },
133
+ "v2.2019": {
134
+ "arctic": "f972a835601a5b00ac5ffc5093414d5fd2a520bbc7b1c7ff0a7d343852302284",
135
+ "atlantic": "6ac0826bacbaa43a9813fe18bcb84b1786efb44538b7a2d24e8a0c993ff23193",
136
+ "indian": "aa6695b715cce7658f94911d38a344f1e835ff6bbed8f9dc1548b167983a2967",
137
+ "pacific": "88df995e272dd63db55421b911be1f99bfec4cac6f97a73e017c9e275bf29db2",
138
+ "world": "4637ce5eb560fe020e9fccf0370156bfe19498fc74c2e8b66dee190cc44cff63",
139
+ },
140
+ "v2.2016": {
141
+ "arctic": "f2214409e0526052903da2427f3f8c6fd433b1759ba2a1be3a61181b4b0d04b7",
142
+ "atlantic": "fb26a86ca1135a0afc94157ba7963bc1cb8138523bcba36360595641175f8da1",
143
+ "indian": "ba162aa6f1fa7209f586e503581d3cc05cdffbfa6f72bdc535824f7a78d694f9",
144
+ "pacific": "0d1666de27ad6853533651027459d2525f75c6681d540f129df705b018d3c931",
145
+ "world": "aa202e330d5e77b98d0062e40a40665b8397b83ebbfa00424532139c53814f5e",
146
+ },
147
+ }
148
+
149
+ _keys_flags = [
150
+ "salinityf",
151
+ "oxygenf",
152
+ "aouf",
153
+ "nitratef",
154
+ "nitritef",
155
+ "silicatef",
156
+ "phosphatef",
157
+ "tco2f",
158
+ "talkf",
159
+ "fco2f",
160
+ "phts25p0f",
161
+ "phtsinsitutpf",
162
+ "cfc11f",
163
+ "cfc12f",
164
+ "cfc113f",
165
+ "ccl4f",
166
+ "sf6f",
167
+ "c13f",
168
+ "c14f",
169
+ "h3f",
170
+ "he3f",
171
+ "hef",
172
+ "neonf",
173
+ "o18f",
174
+ "tocf",
175
+ "docf",
176
+ "donf",
177
+ "tdnf",
178
+ "chlaf",
179
+ ]
180
+ _renamer_flags = {k: k[:-1] + "_f" for k in _keys_flags}
181
+
182
+
183
+ class ParsedInputs(NamedTuple):
184
+ gpath: Path
185
+ region: str
186
+ fileregion: str
187
+ filename: str
188
+ version: str
189
+
190
+
191
+ def _parse_inputs(
192
+ region: str,
193
+ version: str | None,
194
+ gpath: str | Path | None,
195
+ ) -> ParsedInputs:
196
+ region = region.lower()
197
+ if region not in _regions:
198
+ raise ValueError("`region` not valid!")
199
+ if version is None:
200
+ version = version_latest
201
+ version = version.lower()
202
+ if version not in versions:
203
+ raise ValueError("`version` not valid!")
204
+ if gpath is None:
205
+ gpath = "~/.glodap"
206
+ gpath = Path(gpath).expanduser()
207
+ fileregion = _regions[region]
208
+ if version.startswith("v2"):
209
+ filename = f"{fileregion}_{version}.mat"
210
+ elif version.startswith("v3"):
211
+ filename = f"{fileregion}_{version}.csv.zip"
212
+ return ParsedInputs(gpath, region, fileregion, filename, version)
213
+
214
+
215
+ def _download(
216
+ region: str = "world",
217
+ version: str | None = None,
218
+ gpath: str | Path | None = None,
219
+ ) -> None:
220
+ """Download a GLODAP data file and save it locally, after checking
221
+ that it has the expected checksum (SHA256).
222
+
223
+ Parameters
224
+ ----------
225
+ region : str, optional
226
+ Which GLODAP region to download, by default "world", which is
227
+ the Merged Master File. The options are:
228
+ "arctic" Arctic Ocean
229
+ "atlantic" Atlantic Ocean
230
+ "indian" Indian Ocean
231
+ "pacific" Pacific Ocean
232
+ "world" Merged Master File
233
+ version : str or None, optional
234
+ Which GLODAP version to download, by default `None`, in which
235
+ case the most recent version is downloaded. The options are
236
+ given in `glodap.versions`.
237
+ gpath : str or pathlib.Path or None, optional
238
+ Where to check for or save the downloaded file, by default
239
+ `None`, in which case "~/.glodap" is used.
240
+ """
241
+ gpath, region, fileregion, filename, version = _parse_inputs(
242
+ region, version, gpath
243
+ )
244
+ gpath.mkdir(parents=True, exist_ok=True)
245
+ if version == "v2.2016":
246
+ fr = fileregion.replace("_", " ")
247
+ url = f"{version}/GLODAPv2 {fr}.mat"
248
+ elif version.startswith("v2"):
249
+ url = f"{version}/GLODAP{version}_{fileregion}.mat"
250
+ elif version.startswith("v3"):
251
+ url = f"v3/GLODAPv3_{fileregion}.csv.zip"
252
+ checksum = _checksums[version][region]
253
+ pooch.retrieve(
254
+ "https://glodap.info/glodap_files/" + quote(url, safe="/"),
255
+ known_hash=f"sha256:{checksum}",
256
+ fname=filename,
257
+ path=gpath,
258
+ )
259
+
260
+
261
+ def _read(
262
+ region: str = "world",
263
+ version: str | None = None,
264
+ gpath: str | Path | None = None,
265
+ ) -> pd.DataFrame:
266
+ """Import a GLODAP data file as a pandas DataFrame, downloading it
267
+ first if it's not already available locally.
268
+
269
+ Parameters
270
+ ----------
271
+ region : str, optional
272
+ Which GLODAP region to import, by default "world", which is the
273
+ Merged Master File. The options are:
274
+ "arctic" Arctic Ocean
275
+ "atlantic" Atlantic Ocean
276
+ "indian" Indian Ocean
277
+ "pacific" Pacific Ocean
278
+ "world" Merged Master File
279
+ version : str or None, optional
280
+ Which GLODAP version to import, by default `None`, in which case
281
+ the most recent version is imported. The options are given in
282
+ `glodap.versions`.
283
+ gpath : str or pathlib.Path or None, optional
284
+ Where the downloaded file is or should be saved, by default
285
+ `None`, in which case the file is imported from or saved at
286
+ "~/.glodap".
287
+
288
+ Returns
289
+ -------
290
+ pd.DataFrame
291
+ The GLODAP dataset as a pandas DataFrame.
292
+ """
293
+ gpath, region, _, filename, version = _parse_inputs(region, version, gpath)
294
+ # _download checks if the file is already there before downloading,
295
+ # so it's fine to always run it here. It's also useful to have in
296
+ # because it checks the checksum of already-downloaded files.
297
+ _download(region=region, version=version, gpath=gpath)
298
+ if version.startswith("v2"):
299
+ df = loadmat(gpath / filename)
300
+ df = pd.DataFrame(
301
+ {
302
+ k[2:]: [w[0][0] for w in v] if v.dtype == object else v.ravel()
303
+ for k, v in df.items()
304
+ if k.startswith("G2")
305
+ }
306
+ )
307
+ elif version.startswith("v3"):
308
+ df = pd.read_csv(
309
+ gpath / filename,
310
+ compression="zip",
311
+ dtype={
312
+ "expocode": str,
313
+ "ph_scale": str,
314
+ },
315
+ na_values=[-9999, "-9999"],
316
+ )
317
+ # Correct fatal datetime errors and missing flags in v2.2016
318
+ if version == "v2.2016":
319
+ if region in ["indian", "world"]:
320
+ L = (df.cruise == 696) & (df.station == 15537)
321
+ df.loc[L, "month"] = 12
322
+ df.loc[L, "day"] = 1
323
+ ks = [k for k in _keys_flags if k in df]
324
+ df[ks] = df[ks].fillna(9)
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
329
+ # Convert columns that should be integers into integers
330
+ # Can't convert "cast", "hour" or "minute" to integers because they
331
+ # have missing values
332
+ dtypes = {
333
+ k: np.uint8 # 0 to 255
334
+ for k in _keys_flags + ["region", "month", "day"]
335
+ if k in df
336
+ }
337
+ dtypes["year"] = np.uint16 # 0 to 65535
338
+ dtypes["cruise"] = int
339
+ dtypes["station"] = int
340
+ df = df.astype(dtypes)
341
+ # Rename flag columns and defragment
342
+ df = df.rename(columns=_renamer_flags).copy()
343
+ # Calculate datetime for convenience - but exclude hour and minute,
344
+ # because some are missing
345
+ df["datetime"] = pd.to_datetime(df[["year", "month", "day"]])
346
+ return df
347
+
348
+
349
+ def arctic(
350
+ version: str | None = None,
351
+ gpath: str | Path | None = None,
352
+ ) -> pd.DataFrame:
353
+ """Import the latest version of the GLODAP Arctic Ocean dataset,
354
+ downloading it first if it's not already available locally.
355
+
356
+ See the `glodap` module docstring for info on the optional kwargs.
357
+ """
358
+ return _read(region="arctic", version=version, gpath=gpath)
359
+
360
+
361
+ def atlantic(
362
+ version: str | None = None,
363
+ gpath: str | Path | None = None,
364
+ ) -> pd.DataFrame:
365
+ """Import the latest version of the GLODAP Atlantic Ocean dataset,
366
+ downloading it first if it's not already available locally.
367
+
368
+ See the `glodap` module docstring for info on the optional kwargs.
369
+ """
370
+ return _read(region="atlantic", version=version, gpath=gpath)
371
+
372
+
373
+ def indian(
374
+ version: str | None = None,
375
+ gpath: str | Path | None = None,
376
+ ) -> pd.DataFrame:
377
+ """Import the latest version of the GLODAP Indian Ocean dataset,
378
+ downloading it first if it's not already available locally.
379
+
380
+ See the `glodap` module docstring for info on the optional kwargs.
381
+ """
382
+ return _read(region="indian", version=version, gpath=gpath)
383
+
384
+
385
+ def pacific(
386
+ version: str | None = None,
387
+ gpath: str | Path | None = None,
388
+ ) -> pd.DataFrame:
389
+ """Import the latest version of the GLODAP Pacific Ocean dataset,
390
+ downloading it first if it's not already available locally.
391
+
392
+ See the `glodap` module docstring for info on the optional kwargs.
393
+ """
394
+ return _read(region="pacific", version=version, gpath=gpath)
395
+
396
+
397
+ def world(
398
+ version: str | None = None,
399
+ gpath: str | Path | None = None,
400
+ ) -> pd.DataFrame:
401
+ """Import the latest version of the GLODAP Merged Master File
402
+ dataset, downloading it first if it's not already available locally.
403
+
404
+ See the `glodap` module docstring for info on the optional kwargs.
405
+ """
406
+ return _read(region="world", version=version, gpath=gpath)
@@ -10,16 +10,17 @@ description = "GLODAP downloader and importer in Python"
10
10
  readme = "README.md"
11
11
  requires-python = ">= 3.11"
12
12
  dependencies = [
13
- "pandas>=3.0.3,<4",
13
+ "pandas>=3,<4",
14
14
  "pooch>=1.9.0,<2",
15
- "scipy>=1.17.1,<2",
15
+ "scipy>=1.17,<2",
16
16
  ]
17
17
  classifiers = [
18
- "Development Status :: 4 - Beta",
18
+ "Development Status :: 5 - Production/Stable",
19
19
  "Programming Language :: Python :: 3.11",
20
20
  "Programming Language :: Python :: 3.12",
21
21
  "Programming Language :: Python :: 3.13",
22
22
  "Programming Language :: Python :: 3.14",
23
+ "Programming Language :: Python :: 3.15",
23
24
  "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
24
25
  "Operating System :: OS Independent",
25
26
  "Natural Language :: English",
@@ -46,4 +47,6 @@ lines-after-imports = 2
46
47
  [dependency-groups]
47
48
  dev = [
48
49
  "ipykernel>=7.3.0",
50
+ "pytest>=9.2.0",
51
+ "pytest-xdist>=3.8.0",
49
52
  ]
@@ -10,9 +10,9 @@ import glodap
10
10
  def test_download_and_read():
11
11
  with tempfile.TemporaryDirectory() as tdir:
12
12
  for region, version in itertools.product(
13
- glodap.regions, glodap.versions
13
+ glodap._regions, glodap.versions
14
14
  ):
15
- df = glodap.read(region=region, version=version, gpath=tdir)
15
+ df = glodap._read(region=region, version=version, gpath=tdir)
16
16
  assert isinstance(df, pd.DataFrame)
17
17
 
18
18
 
@@ -4,12 +4,6 @@ import pandas as pd
4
4
  import glodap
5
5
 
6
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
7
  def test_regions_latest():
14
8
  df = glodap.arctic()
15
9
  assert isinstance(df, pd.DataFrame)
@@ -23,5 +17,4 @@ def test_regions_latest():
23
17
  assert isinstance(df, pd.DataFrame)
24
18
 
25
19
 
26
- # test_region_names()
27
20
  # test_regions_latest()
@@ -0,0 +1,21 @@
1
+ # %%
2
+ import glodap
3
+
4
+
5
+ def test_version_latest():
6
+ assert glodap.version_latest in glodap.versions
7
+
8
+
9
+ def test_checksum_versions_and_regions():
10
+ for v, rs in glodap._checksums.items():
11
+ assert v in glodap.versions
12
+ for r in rs:
13
+ assert r in glodap._regions
14
+ for r in glodap._regions:
15
+ assert r in rs
16
+ for v in glodap.versions:
17
+ assert v in glodap._checksums
18
+
19
+
20
+ # test_version_latest()
21
+ # test_checksum_versions_and_regions()
@@ -1,3 +0,0 @@
1
- pandas<4,>=3.0.3
2
- pooch<2,>=1.9.0
3
- scipy<2,>=1.17.1
@@ -1,502 +0,0 @@
1
- """
2
- GLODAP
3
- ======
4
- Download Global Ocean Data Analysis Project (GLODAP; https://glodap.info)
5
- datasets and import them as pandas DataFrames.
6
-
7
- The functions `arctic`, `atlantic`, `indian`, `pacific` and `world` import the
8
- latest version of the GLODAP dataset for the corresponding region, first
9
- downloading the file if it's not already saved locally. For example:
10
-
11
- >>> import glodap
12
- >>> df_atlantic = glodap.atlantic()
13
-
14
- Files are saved by default at "~/.glodap", but this can be controlled with the
15
- kwarg `gpath`. See the function docstrings for more information.
16
-
17
- The columns of the imported DataFrames can be passed directly into PyCO2SYS v2:
18
-
19
- >>> import PyCO2SYS as pyco2
20
- >>> co2s_atlantic = pyco2.sys(data=df_atlantic, nitrite=None)
21
-
22
- Note `nitrite=None` - this means PyCO2SYS will ignore the "nitrite" column,
23
- which is necessary because while PyCO2SYS includes the nitrite-nitrous acid
24
- equilibrium, its equilibrium constant is valid only under lab conditions.
25
-
26
- Because of how the columns are named, when passing the DataFrame directly to
27
- PyCO2SYS as above, the system will be solved from DIC and alkalinity, not pH.
28
-
29
- The columns are the same as in the original GLODAP .mat files, except:
30
- * The "G2" at the start of each parameter has been removed.
31
- * Flags end with "_f" instead of just "f".
32
- * There is a "datetime" column, which combines the "year", "month" and "day"
33
- but NOT the "hour" and "minute" (because some of these are missing).
34
-
35
- The functions `download` and `read` can also be used for finer control, such as
36
- specifying a particular GLODAP version rather than using the latest one. See
37
- their function docstrings for more information.
38
-
39
- The .mat files from the GEOMAR mirrors are downloaded, and the SHA256 checksum
40
- of each downloaded file is checked before the file is written to disk.
41
- """
42
-
43
- import os
44
- import shutil
45
- import tempfile
46
- from pathlib import Path
47
-
48
- import numpy as np
49
- import pandas as pd
50
- import pooch
51
- from scipy.io import loadmat
52
-
53
-
54
- # Package metadata
55
- __author__ = "Humphreys, Matthew P."
56
- __version__ = "0.4"
57
-
58
- # GLODAP metadata
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
- ]
69
- regions = {
70
- "arctic": "Arctic_Ocean",
71
- "atlantic": "Atlantic_Ocean",
72
- "indian": "Indian_Ocean",
73
- "pacific": "Pacific_Ocean",
74
- "world": "Merged_Master_File",
75
- }
76
- regions_full = regions.copy()
77
- for k, v in regions.items():
78
- regions_full[k[:3]] = v
79
- regions_short_to_long = {k[:3]: k for k in regions}
80
- checksums = {
81
- "v3.2026": {
82
- "arc": "03dfcf59525931065247e142439d97c0ed88d8f572e87df919476deebdc57d5c",
83
- "atl": "a4577bbb676c30327b185fc5bf0ddc0e302464d5332b6d630922faf536dbe68c",
84
- "ind": "79d655bd203e4579007b7224fc53b87ee8a5d70bb733550f0acac260a6baa0d8",
85
- "pac": "1a5afbb6be199773e00772ca3b1b84241dfc52a591b3f6b85786180f5711a9b4",
86
- "wor": "214aeb49c618474bf92622a37d2795a10160954ab49a94f9052cff1dd41947fd",
87
- },
88
- "v2.2023": {
89
- "arc": "a998a8d99db84e9357b21a7e345bbfde62eae77870e651119b4c1929a2f1e2fd",
90
- "atl": "a3ff7bc4f4ff3a1b0f540886a0eb7c9b3ec52aa4eae2dea57d47ae61f56da56f",
91
- "ind": "8c9c21d4af9db506b09fdec79e2a311c2dbbf41b8fc4e6a7a855d1d50b3ccb51",
92
- "pac": "9891160dba6211d2f13923171564a06bbea34cda799f3091148061c32fc6070c",
93
- "wor": "002881fa71923d15c1bd5aca3b99bc220ad5d1c77a90f130ba1ff0d3910d8766",
94
- },
95
- "v2.2022": {
96
- "arc": "b2cdeeebfb3ff75701ccc15edb22b5c8e1153623aefc6463f9699ae8780edf15",
97
- "atl": "cffdb28aca195e189b16834a4f9711b90a995ea2b99d95bc6fe498049f975631",
98
- "ind": "00381b0542ed4e8a39c33ee071fcb2388c1e3b3fb13f76c75fc342b26f4c8a13",
99
- "pac": "4037f093d89ea422aa62524273ab40ca147934e34637496372e83f2e34fe9a66",
100
- "wor": "3d7ba5bcf59b0c1f513b6fa8140df0618d984fa7b320899e7f188dd7c6cef565",
101
- },
102
- "v2.2021": {
103
- "arc": "21e511e808b9cc9f5b8532bf3b1c6754bb4ad6c344adb4a498b71967a0b6d217",
104
- "atl": "22731e474a33d10c3efd3cc6748aafca7e1488495acefe1bbbd26b4105973a21",
105
- "ind": "d3c43da540e606091a981958b4ce674dbe1ef9777ffee4c90de29bcc74f010a2",
106
- "pac": "925cf0424f4cd1caad30cfbe57bdc19740c85e715bee06bd298893915cfc5a01",
107
- "wor": "8329acd8722a3c198455642f8fca29b05f460b149e178fef9e1041f2caa19453",
108
- },
109
- "v2.2020": {
110
- "arc": "de52e1086b61f68d46cb0142e4bcffae18b578f41c2a00bda40a8960959a94b7",
111
- "atl": "e927d87d873e089311ed5b747195aa150880f59559831bab27a54dcc0ff7ff69",
112
- "ind": "1d8dfbefb820541d9b10f73d3785dae8653e67166b94666dbb433d3ddfa4e255",
113
- "pac": "9a75bf66b38341117afaae947af465f8f7e4082a9f773355c1fbadf26484d544",
114
- "wor": "51e1000101aa61712edb9c0074289bb83c105d17ee8cea575f8e18fa05bde953",
115
- },
116
- "v2.2019": {
117
- "arc": "f972a835601a5b00ac5ffc5093414d5fd2a520bbc7b1c7ff0a7d343852302284",
118
- "atl": "6ac0826bacbaa43a9813fe18bcb84b1786efb44538b7a2d24e8a0c993ff23193",
119
- "ind": "aa6695b715cce7658f94911d38a344f1e835ff6bbed8f9dc1548b167983a2967",
120
- "pac": "88df995e272dd63db55421b911be1f99bfec4cac6f97a73e017c9e275bf29db2",
121
- "wor": "4637ce5eb560fe020e9fccf0370156bfe19498fc74c2e8b66dee190cc44cff63",
122
- },
123
- "v2.2016": {
124
- "arc": "f2214409e0526052903da2427f3f8c6fd433b1759ba2a1be3a61181b4b0d04b7",
125
- "atl": "fb26a86ca1135a0afc94157ba7963bc1cb8138523bcba36360595641175f8da1",
126
- "ind": "ba162aa6f1fa7209f586e503581d3cc05cdffbfa6f72bdc535824f7a78d694f9",
127
- "pac": "0d1666de27ad6853533651027459d2525f75c6681d540f129df705b018d3c931",
128
- "wor": "aa202e330d5e77b98d0062e40a40665b8397b83ebbfa00424532139c53814f5e",
129
- },
130
- }
131
-
132
-
133
- def _get_paths(region, version, gpath):
134
- assert region in regions_full, "`region` not valid!"
135
- if version is None:
136
- version = version_latest
137
- version = version.lower()
138
- assert version in versions, "`version` not valid!"
139
- if gpath is None:
140
- gpath = Path(Path.home(), ".glodap")
141
- fileregion = regions_full[region.lower()]
142
- if version.startswith("v2"):
143
- filename = f"{fileregion}_{version}.mat"
144
- elif version.startswith("v3"):
145
- filename = f"{fileregion}_{version}.csv.zip"
146
- return gpath, fileregion, filename, version
147
-
148
-
149
- def download(region="world", version=None, gpath=None):
150
- """Download a GLODAP data file and save it locally, after checking that it
151
- has the expected checksum (SHA256).
152
-
153
- Parameters
154
- ----------
155
- region : str, optional
156
- Which GLODAP region to download, by default "world", which is the
157
- Merged Master File. The options are:
158
- "arctic" "arc" Arctic Ocean
159
- "atlantic" "atl" Atlantic Ocean
160
- "indian" "ind" Indian Ocean
161
- "pacific" "pac" Pacific Ocean
162
- "world" "wor" Merged Master File
163
- version : str or None, optional
164
- Which GLODAP version to download, by default `None`, in which case the
165
- most recent version is downloaded. The options are:
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).
173
- gpath : str of None, optional
174
- Where to save the downloaded file, by default `None`, in which case the
175
- file is saved at "~/.glodap".
176
- chunk_size : int, optional
177
- Chunk size for streamed file download, by default 8192.
178
- """
179
- gpath, fileregion, filename, version = _get_paths(region, version, gpath)
180
- if not os.path.isdir(gpath):
181
- os.makedirs(gpath)
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
- )
198
- checksum = checksums[version][region[:3].lower()]
199
- pooch.retrieve(
200
- url,
201
- known_hash=f"sha256:{checksum}",
202
- fname=filename,
203
- path=gpath,
204
- )
205
-
206
-
207
- def read(region="world", version=None, gpath=None):
208
- """Import a GLODAP data file as a pandas DataFrame, downloading it first
209
- if it's not already available locally.
210
-
211
- Parameters
212
- ----------
213
- region : str, optional
214
- Which GLODAP region to import, by default "world", which is the
215
- Merged Master File. The options are:
216
- "arctic" "arc" Arctic Ocean
217
- "atlantic" "atl" Atlantic Ocean
218
- "indian" "ind" Indian Ocean
219
- "pacific" "pac" Pacific Ocean
220
- "world" "wor" Merged Master File
221
- version : str or None, optional
222
- Which GLODAP version to import, by default `None`, in which case the
223
- most recent version is imported. The options are:
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).
231
- gpath : str of None, optional
232
- Where to the downloaded file is or should be saved, by default `None`,
233
- in which case the file is imported from or saved at "~/.glodap".
234
-
235
- Returns
236
- -------
237
- pd.DataFrame
238
- The GLODAP dataset as a pandas DataFrame.
239
- """
240
- if region.lower() in regions_short_to_long:
241
- region = regions_short_to_long[region.lower()]
242
- gpath, _, filename, version = _get_paths(region, version, gpath)
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)
264
- # Convert columns that should be integers into integers
265
- # Can't convert cast, hour, minute to integers because they have missing
266
- # values
267
- keys_integers = [
268
- "cruise",
269
- "station",
270
- "region",
271
- # "cast",
272
- "year",
273
- "month",
274
- "day",
275
- # "hour",
276
- # "minute",
277
- ]
278
- keys_flags = [
279
- "salinityf",
280
- "oxygenf",
281
- "aouf",
282
- "nitratef",
283
- "nitritef",
284
- "silicatef",
285
- "phosphatef",
286
- "tco2f",
287
- "talkf",
288
- "fco2f",
289
- "phts25p0f",
290
- "phtsinsitutpf",
291
- "cfc11f",
292
- "cfc12f",
293
- "cfc113f",
294
- "ccl4f",
295
- "sf6f",
296
- "c13f",
297
- "c14f",
298
- "h3f",
299
- "he3f",
300
- "hef",
301
- "neonf",
302
- "o18f",
303
- "tocf",
304
- "docf",
305
- "donf",
306
- "tdnf",
307
- "chlaf",
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
313
- for k in keys_integers + keys_flags:
314
- if k in df:
315
- df[k] = df[k].astype(int)
316
- # Rename columns for PyCO2SYS, if requested
317
- renamer_flags = {k: k[:-1] + "_f" for k in keys_flags}
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
329
- # Calculate datetime for convenience - don't include hour and minute
330
- # because some are missing
331
- df["datetime"] = pd.to_datetime(
332
- df[
333
- [
334
- "year",
335
- "month",
336
- "day",
337
- # "hour",
338
- # "minute",
339
- ]
340
- ]
341
- )
342
- return df
343
-
344
-
345
- def arctic(version=None, gpath=None):
346
- """Import the latest version of the GLODAP Arctic Ocean dataset,
347
- downloading it first if it's not already available locally.
348
-
349
- Parameters
350
- ----------
351
- version : str or None, optional
352
- Which GLODAP version to import, by default `None`, in which case the
353
- most recent version is imported. The options are:
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).
361
- gpath : str of None, optional
362
- Where to the downloaded file is or should be saved, by default `None`,
363
- in which case the file is imported from or saved at "~/.glodap".
364
-
365
- Returns
366
- -------
367
- pd.DataFrame
368
- The GLODAP Arctic Ocean dataset as a pandas DataFrame.
369
- """
370
- return read(
371
- region="arctic",
372
- version=version,
373
- gpath=gpath,
374
- )
375
-
376
-
377
- def atlantic(version=None, gpath=None):
378
- """Import the latest version of the GLODAP Atlantic Ocean dataset,
379
- downloading it first if it's not already available locally.
380
-
381
- Parameters
382
- ----------
383
- version : str or None, optional
384
- Which GLODAP version to import, by default `None`, in which case the
385
- most recent version is imported. The options are:
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).
393
- gpath : str of None, optional
394
- Where to the downloaded file is or should be saved, by default `None`,
395
- in which case the file is imported from or saved at "~/.glodap".
396
-
397
- Returns
398
- -------
399
- pd.DataFrame
400
- The GLODAP Atlantic Ocean dataset as a pandas DataFrame.
401
- """
402
- return read(
403
- region="atlantic",
404
- version=version,
405
- gpath=gpath,
406
- )
407
-
408
-
409
- def indian(version=None, gpath=None):
410
- """Import the latest version of the GLODAP Indian Ocean dataset,
411
- downloading it first if it's not already available locally.
412
-
413
- Parameters
414
- ----------
415
- version : str or None, optional
416
- Which GLODAP version to import, by default `None`, in which case the
417
- most recent version is imported. The options are:
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).
425
- gpath : str of None, optional
426
- Where to the downloaded file is or should be saved, by default `None`,
427
- in which case the file is imported from or saved at "~/.glodap".
428
-
429
- Returns
430
- -------
431
- pd.DataFrame
432
- The GLODAP Indian Ocean dataset as a pandas DataFrame.
433
- """
434
- return read(
435
- region="indian",
436
- version=version,
437
- gpath=gpath,
438
- )
439
-
440
-
441
- def pacific(version=None, gpath=None):
442
- """Import the latest version of the GLODAP Pacific Ocean dataset,
443
- downloading it first if it's not already available locally.
444
-
445
- Parameters
446
- ----------
447
- version : str or None, optional
448
- Which GLODAP version to import, by default `None`, in which case the
449
- most recent version is imported. The options are:
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).
457
- gpath : str of None, optional
458
- Where to the downloaded file is or should be saved, by default `None`,
459
- in which case the file is imported from or saved at "~/.glodap".
460
-
461
- Returns
462
- -------
463
- pd.DataFrame
464
- The GLODAP Pacific Ocean dataset as a pandas DataFrame.
465
- """
466
- return read(
467
- region="pacific",
468
- version=version,
469
- gpath=gpath,
470
- )
471
-
472
-
473
- def world(version=None, gpath=None):
474
- """Import the latest version of the GLODAP Merged Master File dataset,
475
- downloading it first if it's not already available locally.
476
-
477
- Parameters
478
- ----------
479
- version : str or None, optional
480
- Which GLODAP version to import, by default `None`, in which case the
481
- most recent version is imported. The options are:
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).
489
- gpath : str of None, optional
490
- Where to the downloaded file is or should be saved, by default `None`,
491
- in which case the file is imported from or saved at "~/.glodap".
492
-
493
- Returns
494
- -------
495
- pd.DataFrame
496
- The GLODAP Merged Master File as a pandas DataFrame dataset.
497
- """
498
- return read(
499
- region="world",
500
- version=version,
501
- gpath=gpath,
502
- )
File without changes
File without changes