PyESPER 1.0.1__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.
Potentially problematic release.
This version of PyESPER might be problematic. Click here for more details.
- pyesper-1.0.1/PKG-INFO +228 -0
- pyesper-1.0.1/PyESPER/__init__.py +28 -0
- pyesper-1.0.1/PyESPER/adjust_pH_DIC.py +73 -0
- pyesper-1.0.1/PyESPER/coefs_AAinds.py +53 -0
- pyesper-1.0.1/PyESPER/defaults.py +71 -0
- pyesper-1.0.1/PyESPER/define_polygons.py +68 -0
- pyesper-1.0.1/PyESPER/emlr_estimate.py +156 -0
- pyesper-1.0.1/PyESPER/emlr_nn.py +54 -0
- pyesper-1.0.1/PyESPER/errors.py +39 -0
- pyesper-1.0.1/PyESPER/fetch_data.py +54 -0
- pyesper-1.0.1/PyESPER/fetch_polys_NN.py +16 -0
- pyesper-1.0.1/PyESPER/final_formatting.py +25 -0
- pyesper-1.0.1/PyESPER/input_AAinds.py +113 -0
- pyesper-1.0.1/PyESPER/inputdata_organize.py +56 -0
- pyesper-1.0.1/PyESPER/interpolate.py +62 -0
- pyesper-1.0.1/PyESPER/iterations.py +254 -0
- pyesper-1.0.1/PyESPER/lir.py +191 -0
- pyesper-1.0.1/PyESPER/lir_uncertainties.py +99 -0
- pyesper-1.0.1/PyESPER/mixed.py +37 -0
- pyesper-1.0.1/PyESPER/nn.py +134 -0
- pyesper-1.0.1/PyESPER/organize_data.py +378 -0
- pyesper-1.0.1/PyESPER/organize_nn_output.py +266 -0
- pyesper-1.0.1/PyESPER/pH_DIC_nn_adjustment.py +189 -0
- pyesper-1.0.1/PyESPER/pH_adjcalc.py +36 -0
- pyesper-1.0.1/PyESPER/pH_adjustment.py +179 -0
- pyesper-1.0.1/PyESPER/process_netresults.py +105 -0
- pyesper-1.0.1/PyESPER/run_nets.py +85 -0
- pyesper-1.0.1/PyESPER/simplecantestimatelr.py +43 -0
- pyesper-1.0.1/PyESPER/temperature_define.py +48 -0
- pyesper-1.0.1/PyESPER.egg-info/PKG-INFO +228 -0
- pyesper-1.0.1/PyESPER.egg-info/SOURCES.txt +36 -0
- pyesper-1.0.1/PyESPER.egg-info/dependency_links.txt +1 -0
- pyesper-1.0.1/PyESPER.egg-info/entry_points.txt +4 -0
- pyesper-1.0.1/PyESPER.egg-info/requires.txt +6 -0
- pyesper-1.0.1/PyESPER.egg-info/top_level.txt +1 -0
- pyesper-1.0.1/README.md +208 -0
- pyesper-1.0.1/setup.cfg +4 -0
- pyesper-1.0.1/setup.py +30 -0
pyesper-1.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: PyESPER
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: Python version of ESPERv1
|
|
5
|
+
Author: LMD
|
|
6
|
+
Author-email: lmdias@uw.edu
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: numpy
|
|
9
|
+
Requires-Dist: seawater
|
|
10
|
+
Requires-Dist: scipy
|
|
11
|
+
Requires-Dist: matplotlib
|
|
12
|
+
Requires-Dist: PyCO2SYS
|
|
13
|
+
Requires-Dist: pandas
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: author-email
|
|
16
|
+
Dynamic: description
|
|
17
|
+
Dynamic: description-content-type
|
|
18
|
+
Dynamic: requires-dist
|
|
19
|
+
Dynamic: summary
|
|
20
|
+
|
|
21
|
+
# PyESPER
|
|
22
|
+
version 1.0.0
|
|
23
|
+
|
|
24
|
+
<ins>Note:</ins>
|
|
25
|
+
This is for use of the [PyESPER](https://github.com/LarissaMDias/PyESPER/blob/main) package. This package is being developed in parallel with [pyTRACE](https://github.com/d-sandborn/pyTRACE/tree/main).
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
Please see the associated [Examples](https://github.com/LarissaMDias/PyESPER/blob/main/examples.py) for a quick example of use of the preliminary PyESPER. To run this code, you will need to first make sure that you have downloaded the required associated files from the GitHub page as follows. You will also need to ensure that the installed package [requirements](https://github.com/LarissaMDias/PyESPER/blob/main/requirements.txt) are met. The example uses the [GLODAPv2.2023](https://glodap.info) dataset and requires the [glodap](https://github.com/BjerknesClimateDataCentre/glodap/tree/master) package be installed.
|
|
29
|
+
|
|
30
|
+
To install PyESPER to your remote depository, simply run the following in your terminal:
|
|
31
|
+
|
|
32
|
+
pip install git+https://github.com/LarissaMDias/PyESPER
|
|
33
|
+
|
|
34
|
+
Mat_fullgrid folder:
|
|
35
|
+
Folder of .mat files needed for each variable to be estimated, necessary for PyESPER_LIR or PyESPER_Mixed
|
|
36
|
+
|
|
37
|
+
NeuralNetworks folder:
|
|
38
|
+
Folder of .py files needed for each variable to be estimated, necessary for running PyESPER_NN or PyESPER_Mixed. These currently must be unpacked into the main directory.
|
|
39
|
+
|
|
40
|
+
Uncertainty_Polys folder:
|
|
41
|
+
Folder of .mat files needed for ach variable to be estimated, necessary for running PyESPER_NN or PyESPER_Mixed
|
|
42
|
+
|
|
43
|
+
SimpleCantEstimateLR.csv:
|
|
44
|
+
File necessary for estimating anthropogenic carbon component for pH or DIC
|
|
45
|
+
|
|
46
|
+
## Introduction
|
|
47
|
+
PyESPER is a Python implementation of MATLAB Empirical Seawater Property Estimation Routines ([ESPERs](https://github.com/BRCScienceProducts/ESPER)), and the present version consists of a preliminary package which implements these routines. These routines provide estimates of seawater biogeochemical properties at user-provided sets of coordinates, depth, and available biogeochemical properties. Three algorithm options are available through these routines:
|
|
48
|
+
|
|
49
|
+
1. Locally interpolated regressions (LIRs)
|
|
50
|
+
2. Neural networks (NNs)
|
|
51
|
+
3. Mixed
|
|
52
|
+
|
|
53
|
+
The routines predict coefficient and intercept values for a set of up to 16 equations, as follows:
|
|
54
|
+
(S=salinity, T=temperature, oxygen=dissolved oxygen molecule... see "PredictorMeasurements" for units).
|
|
55
|
+
1. S, T, A, B, C
|
|
56
|
+
2. S, T, A, C
|
|
57
|
+
3. S, T, B, C
|
|
58
|
+
4. S, T, C
|
|
59
|
+
5. S, T, A, B
|
|
60
|
+
6. S, T, A
|
|
61
|
+
7. S, T, B
|
|
62
|
+
8. S, T
|
|
63
|
+
9. S, A, B, C
|
|
64
|
+
10. S, A, C
|
|
65
|
+
11. S, B, C
|
|
66
|
+
12. S, C
|
|
67
|
+
13. S, A, B
|
|
68
|
+
14. S, A
|
|
69
|
+
15. S, B
|
|
70
|
+
16. S
|
|
71
|
+
|
|
72
|
+
<ins>DesiredVariable: A, B, C</ins>
|
|
73
|
+
|
|
74
|
+
-TA: nitrate, oxygen, silicate
|
|
75
|
+
|
|
76
|
+
-DIC: nitrate, oxygen, silicate
|
|
77
|
+
|
|
78
|
+
-pH: nitrate, oxygen, silicate
|
|
79
|
+
|
|
80
|
+
-phosphate: nitrate, oxygen, silicate
|
|
81
|
+
|
|
82
|
+
-nitrate: phosphate, oxygen, silicate
|
|
83
|
+
|
|
84
|
+
-silicate: phosphate, oxygen, nitrate
|
|
85
|
+
|
|
86
|
+
-oxygen: phosphate, nitrate, silicate
|
|
87
|
+
|
|
88
|
+
### Documentation and citations:
|
|
89
|
+
LIARv1: Carter et al., 2016, doi: 10.1002/lom3.10087
|
|
90
|
+
|
|
91
|
+
LIARv2, LIPHR, LINR citation: Carter et al., 2018, doi: 10.1002/lom3.10232
|
|
92
|
+
|
|
93
|
+
LIPR, LISIR, LIOR, first described/used: Carter et al., 2021, doi: 10.1002/lom3/10232
|
|
94
|
+
|
|
95
|
+
LIRv3 and ESPER_NN (ESPERv1.1): Carter, 2021, doi: 10.5281/ZENODO.5512697
|
|
96
|
+
|
|
97
|
+
PyESPER is a Python implementation is ESPER:
|
|
98
|
+
Carter et al., 2021, doi: 10.1002/lom3/10461
|
|
99
|
+
|
|
100
|
+
ESPER_NN is inspired by CANYON-B, which also uses neural networks:
|
|
101
|
+
Bittig et al., 2018, doi: 10.3389/fmars.2018.00328
|
|
102
|
+
|
|
103
|
+
### PyESPER_LIR
|
|
104
|
+
These are the first version of Python implementation of LIRv.3; ESPERv1.1, which use collections of interpolated linear networks.
|
|
105
|
+
|
|
106
|
+
### PyESPER_NN
|
|
107
|
+
These are the first version of Python implementation of ESPERv1.1, which uses neural networks.
|
|
108
|
+
|
|
109
|
+
### PyESPER_Mixed
|
|
110
|
+
These are the first version of Python implementation of ESPERv1.1, which is an average of the LIR and NN estimates.
|
|
111
|
+
|
|
112
|
+
## Basic Use
|
|
113
|
+
|
|
114
|
+
### Requirements
|
|
115
|
+
For the present version, you will need to download the repository along with the affiliated neural network files within the [NeuralNetworks](https://github.com/LarissaMDias/PyESPER/tree/main/NeuralNetworks) folder, and the [SimpleCantEstimateLR_full.csv](https://github.com/LarissaMDias/PyESPER/blob/main/SimpleCantEstimateLR_full.csv) file for estimates involving anthropogenic carbon calculations (pH and dissolved inorganic carbon).
|
|
116
|
+
|
|
117
|
+
To run the code, you will need numpy, pandas, seawater (now deprecated but necessary for consistency with ESPERv1), scipy, time, matplotlib, PyCO2SYS, importlib, statistics, and os packages.
|
|
118
|
+
|
|
119
|
+
Please refer to the examples .py file for proper use.
|
|
120
|
+
|
|
121
|
+
### Organization and Units
|
|
122
|
+
The measurements are provided in molar units or if potential temperature or AOU are needed but not provided by the user. Scale differences from TEOS-10 are a negligible component of alkalinity estimate error. PyCO2SYS is required if pH on the total scale is a desired output variable.
|
|
123
|
+
|
|
124
|
+
#### Input/Output dimensions:
|
|
125
|
+
p: Integer number of desired property estimate types (e.g., TA, pH, NO3-)
|
|
126
|
+
|
|
127
|
+
n: Integer number of desired estimate locations
|
|
128
|
+
|
|
129
|
+
e: Integer number of equations used at each location
|
|
130
|
+
|
|
131
|
+
y: Integer number of parameter measurement types provided by the user
|
|
132
|
+
|
|
133
|
+
n*e: Total number of estimates returned as an n by e array
|
|
134
|
+
|
|
135
|
+
#### Required Inputs:
|
|
136
|
+
|
|
137
|
+
##### DesiredVariables (required 1 by p list, where p specifies the desired variable(x) in string format):
|
|
138
|
+
List elements specify which variables will be returned. Excepting unitless pH, all outputs are in micromol per kg seawater. Naming of list elements must be exactly as demonstrated below (excamples ["TA"], ["DIC", "phosphate", "oxygen"]).
|
|
139
|
+
|
|
140
|
+
<ins>Desired Variable: List Element Name (String Format):</ins>
|
|
141
|
+
|
|
142
|
+
Total Titration Seawater Alkalinity: TA
|
|
143
|
+
|
|
144
|
+
Total Dissolved Inorganic Carbon: DIC
|
|
145
|
+
|
|
146
|
+
in situ pH on the total scale: pH
|
|
147
|
+
|
|
148
|
+
Phosphate: phosphate
|
|
149
|
+
|
|
150
|
+
Nitrate: nitrate
|
|
151
|
+
|
|
152
|
+
Silicate: silicate
|
|
153
|
+
|
|
154
|
+
Dissolved Oxygen (O<sub>2</sub>): oxygen
|
|
155
|
+
|
|
156
|
+
##### Path (required string):
|
|
157
|
+
Path directing Python to the location of saved/downloaded LIR files on the user's computer, if not in the current working directory (otherwise blank; e.g., '/Users/lara/Documents/Python' or '').
|
|
158
|
+
|
|
159
|
+
##### OutputCoordinates (required n by 3 dictionary, where n are the number of desired estimate locations and the three dicstionary keys are longitude, latitude, and depth):
|
|
160
|
+
Coordinates at which estimates are desired. The keys should be longitude (degrees E), latitude (degrees N), and positive integer depth (m), with dictionary keys named 'longitude', 'latitude', and 'depth' (ex: OutputCoordinates={"longitude": [0, 180, -50, 10], "latitude": [85, -20, 18, 0.5], "depth": [10, 1000, 0, 0]} or OutputCoordinates={"longitude": long, "latitude": lat, "depth": depth} when referring to a set of predefined lists or numpy arrays of latitude, longitude, and depth information.
|
|
161
|
+
|
|
162
|
+
##### PredictorMeasurements (required n by y dictionary, where n are the number of desired estimate locations and y are the dictionary keys representing each possible input):
|
|
163
|
+
Parameter measurements that will be used to estimate desired variables. Concentrations should be expressed as micromol per kg seawater unless PerKgSwTF is set to false in which case they should be expressed as micromol per L, temperature should be expressed as degrees C, and salinity should be specified with the unitless convention. NaN inputs are acceptable, but will lead to NaN estimates for any equations that depend on that parameter. The key order (y columns) is arbitrary, but naming of keys must adhere to the following convention (ex: PredictorMeasurements={"salinity": [35, 34.1, 32, 33], "temperature": [0.1, 10, 0.5, 2], "oxygen": [202.3, 214.7, 220.5, 224.2]} or PredictorMeasurements={'salinity': sal, 'temperature: temp, 'phosphate': phos, 'nitrate': nitrogen} when referring to predefined lists or numpy arrays of measurements:
|
|
164
|
+
|
|
165
|
+
<ins>Input Parameter: Dictionary Key Name</ins>
|
|
166
|
+
|
|
167
|
+
-Salinity: salinity
|
|
168
|
+
|
|
169
|
+
-Temperature: temperature
|
|
170
|
+
|
|
171
|
+
-Phosphate: phosphate
|
|
172
|
+
|
|
173
|
+
-Nitrate: nitrate
|
|
174
|
+
|
|
175
|
+
-Silicate: silicate
|
|
176
|
+
|
|
177
|
+
-O<sub>2</sub>: oxygen
|
|
178
|
+
|
|
179
|
+
#### Optional Inputs:
|
|
180
|
+
All remaining inputs must be specified as sequential input argument pairs (e.g., "EstDates"=EstDates when referring to a predefined list of dates, 'Equations'=[1:16], pHCalcTF=True, etc.)
|
|
181
|
+
|
|
182
|
+
##### EstDates (optional but recommended n by 1 list or 1 by 1 value, default 2002.0):
|
|
183
|
+
A list of decimal dates for the estimates (e.g., July 1 2020 would be 2020.5). If only a single date is supplied that value is used for all estimates. It is highly recommended that date(s) be provided for estimates of DIC and pH. This version of the code will accept 1 by n inputs as well.
|
|
184
|
+
|
|
185
|
+
##### Equations (optional 1 by e list, default [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]):
|
|
186
|
+
List indicating which equations will be used to estimate desired variables. If [] is input or the input is not specified then all 16 equations will be used.
|
|
187
|
+
|
|
188
|
+
#### Optional Inputs
|
|
189
|
+
|
|
190
|
+
##### MeasUncerts (Optional n by y dictionary or 1 by y dictionary, default: [0.003 S, 0.003 degrees C T or potential temperature, 2% phosphate, 2% nitrate, 2% silicate, 1% AOU or O<sub>2</sub>]):
|
|
191
|
+
Dictionary of measurement uncertainties (see 'PredictorMeasurements' for units). Providing these estimates will improve PyESPER estimate uncertainties. Measurement uncertainties are a small p0art of PyESPER estimate uncertainties for WOCE-quality measurements. However, estimate uncertainty scales with measurement uncertainty, so it is recommended that measurement uncertainties be specified for sensor measurements. If this optional input argument is not provided, the default WOCE-quality uncertainty is assumed. If a 1 by y array is provided then the uncertainty estimates are assumed to apply uniformly to all input parameter measurements. Uncertainties should be presented with the following naming convention:
|
|
192
|
+
|
|
193
|
+
<ins>Input Uncertainties: Key Name</ins>
|
|
194
|
+
|
|
195
|
+
-Salinity: sal_u
|
|
196
|
+
|
|
197
|
+
-Temperature: temp_u
|
|
198
|
+
|
|
199
|
+
-Phosphate: phosphate_u
|
|
200
|
+
|
|
201
|
+
-Nitrate: nitrate_u
|
|
202
|
+
|
|
203
|
+
-Silicate: silicate_u
|
|
204
|
+
|
|
205
|
+
-Oxygen: oxygen_u
|
|
206
|
+
|
|
207
|
+
##### pHCalcTF (Optional boolean, default false):
|
|
208
|
+
If set to true, PyESPER will recalculate the pH to be a better estimate of what the seawater pH value would be if calculated from TA and DIC instead of measured with purified m-cresol dye. This is arguably also a better estimate of the pH than would be obtained from pre-2011 measurements with impure dyes. See LIPHR paper for details.
|
|
209
|
+
|
|
210
|
+
##### PerKgSwTF (Optional boolean, default true):
|
|
211
|
+
Many sensors provide measurements in micromol per L (molarity) instead of micromol per kg seawater. Indicate false if provided measurements are expressed in molar units (concentrations must be micromol per L if so). Outputs will remain in molal units regardless.
|
|
212
|
+
|
|
213
|
+
##### VerboseTF (Optional boolean, default true):
|
|
214
|
+
Setting this to false will reduce the number of updates, warnings, and errors printed by PyESPER. An additional step can be taken before executing the PyESPER function (see examples) that will further reduce updates, warnings, and errors, if desired.
|
|
215
|
+
|
|
216
|
+
#### Outputs:
|
|
217
|
+
|
|
218
|
+
##### Estimates:
|
|
219
|
+
An n by e dictionary of estimates specific to the coordinates and parameter measurements provided as inputs. Units are micromoles per kg (equivalent to the deprecated microeq per kg seawater). Column names are the unique desired variable-equation combinations requested by the user.
|
|
220
|
+
|
|
221
|
+
##### Coefficients (LIRs only):
|
|
222
|
+
An n by e dictionary of dictionaries of equation intercepts and coefficients specific to the coordinates and parameter measurements provided as inputs. Column names are the unique desired variable-equation combinations requested by the user.
|
|
223
|
+
|
|
224
|
+
##### Uncertainties:
|
|
225
|
+
An n by e dictionary of uncertainty estimates specific to the coordinates, parameter measurements, and parameter uncertaineis provided. Units are micromoles per kg (equivalent to the deprecated microeq per kg seawater). Column names are the unique desired variable-equation combinations requested by the user.
|
|
226
|
+
|
|
227
|
+
#### Missing Data:
|
|
228
|
+
Should be indicated with a NaN. A NaN coordinate will yield NaN estimates for all equations at that coordinate. A NaN parameter value will yield NaN esitmates for all equations that require that parameter.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from .final_formatting import final_formatting
|
|
2
|
+
from .organize_nn_output import organize_nn_output
|
|
3
|
+
from .adjust_pH_DIC import adjust_pH_DIC
|
|
4
|
+
from .input_AAinds import input_AAinds
|
|
5
|
+
from .pH_adjcalc import pH_adjcalc
|
|
6
|
+
from .coefs_AAinds import coefs_AAinds
|
|
7
|
+
from .inputdata_organize import inputdata_organize
|
|
8
|
+
from .pH_adjustment import pH_adjustment
|
|
9
|
+
from .defaults import defaults
|
|
10
|
+
from .interpolate import interpolate
|
|
11
|
+
from .pH_DIC_nn_adjustment import pH_DIC_nn_adjustment
|
|
12
|
+
from .define_polygons import define_polygons
|
|
13
|
+
from .iterations import iterations
|
|
14
|
+
from .process_netresults import process_netresults
|
|
15
|
+
from .emlr_estimate import emlr_estimate
|
|
16
|
+
from .lir_uncertainties import process_uncertainties
|
|
17
|
+
from .lir_uncertainties import measurement_uncertainty_defaults
|
|
18
|
+
from .run_nets import run_nets
|
|
19
|
+
from .emlr_nn import emlr_nn
|
|
20
|
+
from .simplecantestimatelr import simplecantestimatelr
|
|
21
|
+
from .errors import errors
|
|
22
|
+
from .temperature_define import temperature_define
|
|
23
|
+
from .fetch_data import fetch_data
|
|
24
|
+
from .fetch_polys_NN import fetch_polys_NN
|
|
25
|
+
from .organize_data import organize_data
|
|
26
|
+
from .lir import lir
|
|
27
|
+
from .nn import nn
|
|
28
|
+
from .mixed import mixed
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
def adjust_pH_DIC(DesiredVariables, VerboseTF, Dates, Est_pre={}, PredictorMeasurements={}, OutputCoordinates={}, **kwargs):
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
If present, adjusting pH and DIC for anthropogenic carbon (Cant) within LIRs. Cant adjustment methods
|
|
5
|
+
are based on those from ESPERv1, which is a TTD-based assumption/simplification but does not
|
|
6
|
+
use the Tracer-based Rapid Anthropogenic Carbon Estimation data product, TRACE. Rather,
|
|
7
|
+
interpolation from a gridded product is used to produce estimates for the year 2002 and data is
|
|
8
|
+
adjusted to/from this reference year. This is the first of three steps for Cant adjustment
|
|
9
|
+
|
|
10
|
+
Inputs:
|
|
11
|
+
DesiredVariables: List of desired variables to estimate
|
|
12
|
+
VerboseTF: Boolean indicating whether the user wants suppression of warnings
|
|
13
|
+
Dates: List of dates for estimates
|
|
14
|
+
Est_pre: Dictionary of preliminary estimates for each variable-equation case scenario
|
|
15
|
+
PredictorMeasurements: Dictionary of input measurements for each variable-equation case scenario
|
|
16
|
+
OutputCoordinates: Dictionary of coordinates for locations of estimates
|
|
17
|
+
**kwargs: Please see README for full informations
|
|
18
|
+
|
|
19
|
+
Outputs:
|
|
20
|
+
Cant_adjusted: Dictionary of values adjusted for anthropogenic carbon for each combination
|
|
21
|
+
Cant: Numpy array of estimates for anthropogenic carbon for each estimate
|
|
22
|
+
Cant2002: Numpy array of estimates for anthropogenic carbon in the year 2002 for each estimate
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
import numpy as np
|
|
26
|
+
from PyESPER.simplecantestimatelr import simplecantestimatelr
|
|
27
|
+
|
|
28
|
+
# Predefining output dictionary and formatting estimates
|
|
29
|
+
Cant_adjusted={}
|
|
30
|
+
combos2 = list(Est_pre.keys())
|
|
31
|
+
values2 = []
|
|
32
|
+
for c, v in Est_pre.items():
|
|
33
|
+
vals = np.array([v])
|
|
34
|
+
vals = vals.flatten()
|
|
35
|
+
values2.append(vals)
|
|
36
|
+
values2 = np.array(values2)
|
|
37
|
+
|
|
38
|
+
# Predefining anthropogenic carbon numpy arrays
|
|
39
|
+
n = len(Dates)
|
|
40
|
+
Cant, Cant2002 = np.zeros(n), np.zeros(n)
|
|
41
|
+
|
|
42
|
+
# Only proceed if adjustment is needed
|
|
43
|
+
if "EstDates" in kwargs and ("DIC" in DesiredVariables or "pH" in DesiredVariables):
|
|
44
|
+
if VerboseTF:
|
|
45
|
+
print("Estimating anthropogenic carbon for PyESPER_LIR.")
|
|
46
|
+
|
|
47
|
+
# Normalize longitude to [0, 360]
|
|
48
|
+
longitude = np.mod(np.array(OutputCoordinates["longitude"]), 360)
|
|
49
|
+
latitude = np.array(OutputCoordinates["latitude"])
|
|
50
|
+
depth = np.array(OutputCoordinates["depth"])
|
|
51
|
+
|
|
52
|
+
# Estimate anthropogenic carbon (Cant) and anthropogenic carbon for the year 2002 (Cant2002)
|
|
53
|
+
Cant, Cant2002 = simplecantestimatelr(Dates, longitude, latitude, depth)
|
|
54
|
+
Cant, Cant2002 = np.array(Cant), np.array(Cant2002)
|
|
55
|
+
|
|
56
|
+
for combo in range(0, len(combos2)):
|
|
57
|
+
comb = combos2[combo]
|
|
58
|
+
val = values2[combo]
|
|
59
|
+
est1 = []
|
|
60
|
+
|
|
61
|
+
# Only adjust if combo is DIC
|
|
62
|
+
if "dic" in comb.lower():
|
|
63
|
+
adjusted = np.where(val == "nan", np.nan, val + Cant - Cant2002)
|
|
64
|
+
est1.append(adjusted)
|
|
65
|
+
|
|
66
|
+
if "dic" not in comb.lower():
|
|
67
|
+
nanfix = np.where(val == "nan", np.nan, val)
|
|
68
|
+
est1.append(nanfix)
|
|
69
|
+
|
|
70
|
+
Cant_adjusted[combos2[combo]] = est1
|
|
71
|
+
|
|
72
|
+
return Cant_adjusted, Cant, Cant2002
|
|
73
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
def coefs_AAinds(Equations, LIR_data):
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Separates coefficients from MATLAB ESPERv1 into Atlantic and Arctic or other regions.
|
|
5
|
+
|
|
6
|
+
Inputs:
|
|
7
|
+
Equations: List of equations for use in ESPERs
|
|
8
|
+
LIR_data: List of dictionaries of data from MATLAB trainings (pre-processed)
|
|
9
|
+
|
|
10
|
+
Outputs:
|
|
11
|
+
Gdf: Dictionary of pre-trained and processed LIR data for grid of coordinates
|
|
12
|
+
CsDesired: Dictionary of equation coefficients based on user-defined output
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
|
|
17
|
+
# Use boolean for AA or Else to separate coefficients into Atlantic or not
|
|
18
|
+
GridCoords, Cs, AAInds = LIR_data[:3]
|
|
19
|
+
DVs, CsVs = list(Cs.keys()), list(Cs.values())
|
|
20
|
+
ListVars = np.arange(len(AAInds))
|
|
21
|
+
GridValues = np.array(list(GridCoords.values())[0], dtype=float)
|
|
22
|
+
AAIndValues = np.array(list(AAInds.values())[0], dtype=float)
|
|
23
|
+
|
|
24
|
+
lon_grid, lat_grid, d2d_grid, aainds = np.array((GridValues[:,0])), np.array((GridValues[:,1])), \
|
|
25
|
+
np.array(GridValues[:,2])/25, np.array(AAIndValues[:,0])
|
|
26
|
+
|
|
27
|
+
names = ['lon', 'lat', 'd2d', "C_alpha", "C_S", "C_T", "C_A", "C_B", "C_C", 'AAInds']
|
|
28
|
+
Gdf, CsDesired = {}, {}
|
|
29
|
+
|
|
30
|
+
# Moving data into pre-defined dictionaries
|
|
31
|
+
for lvar, name in zip(ListVars, DVs):
|
|
32
|
+
Cs2 = CsVs[:][lvar][:]
|
|
33
|
+
for e in Equations:
|
|
34
|
+
CsName = f'Cs{name}{e}'
|
|
35
|
+
CsDesired[CsName] = Cs2[e-1][:]
|
|
36
|
+
Cs3 = Cs2[e-1][:]
|
|
37
|
+
C_alpha, C_S, C_T, C_A, C_B, C_C = np.array(Cs3[:,0]), np.array(Cs3[:,1]), np.array(Cs3[:,2]), np.array(Cs3[:,3]), \
|
|
38
|
+
np.array(Cs3[:,4]), np.array(Cs3[:,5])
|
|
39
|
+
Gdf[f"{name}{e}"] = {
|
|
40
|
+
names[0]: np.array(lon_grid),
|
|
41
|
+
names[1]: np.array(lat_grid),
|
|
42
|
+
names[2]: np.array(d2d_grid),
|
|
43
|
+
names[3]: np.array(C_alpha),
|
|
44
|
+
names[4]: np.array(C_S),
|
|
45
|
+
names[5]: np.array(C_T),
|
|
46
|
+
names[6]: np.array(C_A),
|
|
47
|
+
names[7]: np.array(C_B),
|
|
48
|
+
names[8]: np.array(C_C),
|
|
49
|
+
names[9]: np.array(aainds)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return Gdf, CsDesired
|
|
53
|
+
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
def defaults (DesiredVariables, PredictorMeasurements={}, OutputCoordinates={}, **kwargs):
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Set default values and bookkeep inputs.
|
|
5
|
+
|
|
6
|
+
Inputs:
|
|
7
|
+
DesiredVariables: List of desired output variables (user-requested)
|
|
8
|
+
PredictorMeasurements: Dictionary of user-provided predictor mesasurements (salinity, etc.)
|
|
9
|
+
OutputCoordinates: Dictionary of user-provided coordinates
|
|
10
|
+
**kwargs: Please see README for more information
|
|
11
|
+
|
|
12
|
+
Outputs:
|
|
13
|
+
Equations: numpy array of equations (either user-defined or default)
|
|
14
|
+
n: Scalar representing number of required estimates for each variable-equation comination
|
|
15
|
+
e: Scalar representing number of requested equations
|
|
16
|
+
p: Scalar representing number of requested output variables
|
|
17
|
+
VerboseTF: Boolean read-in of whether user wants to suppress optional warnings
|
|
18
|
+
C: Dictionary of processed geographic coordinates
|
|
19
|
+
PerKgSwTF: Boolean representing whether user input is in molal or molar units
|
|
20
|
+
MeasUncerts: Dictionary of user input measurement uncertainty values or empty
|
|
21
|
+
dictionary if not provided
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import numpy as np
|
|
25
|
+
|
|
26
|
+
# Check and define Equations based on user-defined kwargs, or use default values
|
|
27
|
+
Equations = kwargs.get("Equations", list(range(1, 17)))
|
|
28
|
+
|
|
29
|
+
# Reading dimensions of user input
|
|
30
|
+
n = max(len(v) for v in OutputCoordinates.values())
|
|
31
|
+
|
|
32
|
+
# Checking kwargs for presence of VerboseTF and EstDates, and Equations, and defining defaults, as needed
|
|
33
|
+
VerboseTF = kwargs.get("VerboseTF", True)
|
|
34
|
+
|
|
35
|
+
# Set EstDates based on kwargs, defaulting to 2002.0 if not provided
|
|
36
|
+
if "EstDates" in kwargs:
|
|
37
|
+
d = np.array(kwargs["EstDates"])
|
|
38
|
+
if len(d) != n:
|
|
39
|
+
EstDates = np.tile(d, (n + 1, 1)).reshape(-1)
|
|
40
|
+
else:
|
|
41
|
+
EstDates = d
|
|
42
|
+
else:
|
|
43
|
+
EstDates = np.full(n, 2002.0)
|
|
44
|
+
|
|
45
|
+
# Bookkeeping coordinates
|
|
46
|
+
C = {}
|
|
47
|
+
longitude = np.array(OutputCoordinates["longitude"])
|
|
48
|
+
longitude[longitude > 360] = np.remainder(longitude[longitude > 360], 360)
|
|
49
|
+
longitude[longitude < 0] = longitude[longitude<0] + 360
|
|
50
|
+
C["longitude"] = longitude
|
|
51
|
+
C["latitude"] = OutputCoordinates["latitude"]
|
|
52
|
+
C["depth"] = OutputCoordinates["depth"]
|
|
53
|
+
|
|
54
|
+
# Defining or reading in PerKgSwTF
|
|
55
|
+
PerKgSwTF = kwargs.get("PerKgSwTF", True)
|
|
56
|
+
|
|
57
|
+
# Defining Measurement Uncertainties
|
|
58
|
+
MeasUncerts = kwargs.get("MeasUncerts", {})
|
|
59
|
+
|
|
60
|
+
# Validate MeasUncerts dimensions
|
|
61
|
+
if MeasUncerts:
|
|
62
|
+
if max(len(v) for v in MeasUncerts.values()) != n:
|
|
63
|
+
if min(len(v) for v in MeasUncerts.values()) != 1:
|
|
64
|
+
raise CustomError(
|
|
65
|
+
"MeasUncerts must be undefined, a vector with the same number of elements as "
|
|
66
|
+
"PredictorMeasurements has columns, or a matrix of identical dimension to PredictorMeasurements."
|
|
67
|
+
)
|
|
68
|
+
if len(MeasUncerts) != len(PredictorMeasurements):
|
|
69
|
+
print("Warning: Different numbers of input uncertainties and input measurements.")
|
|
70
|
+
|
|
71
|
+
return Equations, n, VerboseTF, EstDates, C, PerKgSwTF, MeasUncerts
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
def define_polygons(C={}):
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Defining and structuring indexing within ocean region polygons.
|
|
5
|
+
First defines the polygons, then assesses the location of user-provided
|
|
6
|
+
coordinates within polygons.
|
|
7
|
+
|
|
8
|
+
Inputs:
|
|
9
|
+
C: Dictionary of adjusted coordinates
|
|
10
|
+
|
|
11
|
+
Output:
|
|
12
|
+
df: Dictionary of adjusted coordinates with boolean indicators for specific
|
|
13
|
+
ocean regions
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
import matplotlib.path as mpltPath
|
|
18
|
+
|
|
19
|
+
# Define polygons for Atlantic and Arctic (AA) or other (Else) ocean basins
|
|
20
|
+
LNAPoly = np.array([[300, 0], [260, 20], [240, 67], [260, 40], [361, 40], [361, 0], [298, 0]])
|
|
21
|
+
LSAPoly = np.array([[298, 0], [292, -40.01], [361, -40.01], [361, 0], [298, 0]])
|
|
22
|
+
LNAPolyExtra = np.array([[-1, 50], [40, 50], [40, 0], [-1, 0], [-1, 50]])
|
|
23
|
+
LSAPolyExtra = np.array([[-1, 0], [20, 0], [20, -40], [-1, -40], [-1, 0]])
|
|
24
|
+
LNOPoly = np.array([[361, 40], [361, 91], [-1, 91], [-1, 50], [40, 50], [40, 40], [104, 40], [104, 67], [240, 67],
|
|
25
|
+
[280, 40], [361, 40]])
|
|
26
|
+
xtra = np.array([[0.5, -39.9], [.99, -39.9], [0.99, -40.001], [0.5, -40.001]])
|
|
27
|
+
polygons = [LNAPoly, LSAPoly, LNAPolyExtra, LSAPolyExtra, LNOPoly, xtra]
|
|
28
|
+
|
|
29
|
+
# Create Paths
|
|
30
|
+
paths = [mpltPath.Path(poly) for poly in polygons]
|
|
31
|
+
|
|
32
|
+
# Extract coordinates
|
|
33
|
+
longitude, latitude, depth = np.array(C["longitude"]), np.array(C["latitude"]), np.array(C["depth"])
|
|
34
|
+
|
|
35
|
+
# Check if coordinates are within each polygon
|
|
36
|
+
conditions = [path.contains_points(np.column_stack((longitude, latitude))) for path in paths]
|
|
37
|
+
|
|
38
|
+
# Combine conditions
|
|
39
|
+
AAIndsM = np.logical_or.reduce(conditions)
|
|
40
|
+
|
|
41
|
+
# Adding Bering Sea, S. Atl., and S. African Polygons separately
|
|
42
|
+
Bering = np.array([[173, 70], [210, 70], [210, 62.5], [173, 62.5], [173, 70]])
|
|
43
|
+
beringpath = mpltPath.Path(Bering)
|
|
44
|
+
beringconditions = beringpath.contains_points(np.column_stack((longitude, latitude)))
|
|
45
|
+
SAtlInds, SoAfrInds = [], []
|
|
46
|
+
for i, z in zip(longitude, latitude):
|
|
47
|
+
# Check if the conditions are met for Southern Atlantic
|
|
48
|
+
if (-34 > z > -44): # Check latitude first to reduce unnecessary checks
|
|
49
|
+
if i > 290 or i < 20:
|
|
50
|
+
SAtlInds.append('True')
|
|
51
|
+
else:
|
|
52
|
+
SAtlInds.append('False')
|
|
53
|
+
|
|
54
|
+
# Check if the condition is met for Southern Africa
|
|
55
|
+
if 19 < i < 27:
|
|
56
|
+
SoAfrInds.append('True')
|
|
57
|
+
else:
|
|
58
|
+
SoAfrInds.append('False')
|
|
59
|
+
else:
|
|
60
|
+
SAtlInds.append('False')
|
|
61
|
+
SoAfrInds.append('False')
|
|
62
|
+
|
|
63
|
+
# Create Dictionary with boolean indicators
|
|
64
|
+
df = {'AAInds': AAIndsM, 'BeringInds': beringconditions, 'SAtlInds': SAtlInds, \
|
|
65
|
+
'SoAfrInds': SoAfrInds, 'Lat': latitude, 'Lon': longitude, 'Depth': depth}
|
|
66
|
+
|
|
67
|
+
return df
|
|
68
|
+
|