PyESPER 1.0.0__py3-none-any.whl
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.
- PyESPER/__init__.py +28 -0
- PyESPER/adjust_pH_DIC.py +73 -0
- PyESPER/coefs_AAinds.py +53 -0
- PyESPER/defaults.py +71 -0
- PyESPER/define_polygons.py +68 -0
- PyESPER/emlr_estimate.py +156 -0
- PyESPER/emlr_nn.py +54 -0
- PyESPER/errors.py +39 -0
- PyESPER/fetch_data.py +54 -0
- PyESPER/fetch_polys_NN.py +16 -0
- PyESPER/final_formatting.py +25 -0
- PyESPER/input_AAinds.py +113 -0
- PyESPER/inputdata_organize.py +56 -0
- PyESPER/interpolate.py +62 -0
- PyESPER/iterations.py +254 -0
- PyESPER/lir.py +191 -0
- PyESPER/lir_uncertainties.py +99 -0
- PyESPER/mixed.py +37 -0
- PyESPER/nn.py +134 -0
- PyESPER/organize_data.py +378 -0
- PyESPER/organize_nn_output.py +266 -0
- PyESPER/pH_DIC_nn_adjustment.py +189 -0
- PyESPER/pH_adjcalc.py +36 -0
- PyESPER/pH_adjustment.py +179 -0
- PyESPER/process_netresults.py +105 -0
- PyESPER/run_nets.py +85 -0
- PyESPER/simplecantestimatelr.py +43 -0
- PyESPER/temperature_define.py +48 -0
- pyesper-1.0.0.dist-info/METADATA +16 -0
- pyesper-1.0.0.dist-info/RECORD +33 -0
- pyesper-1.0.0.dist-info/WHEEL +5 -0
- pyesper-1.0.0.dist-info/entry_points.txt +4 -0
- pyesper-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
def organize_nn_output(Path, DesiredVariables, OutputCoordinates={}, PredictorMeasurements={}, **kwargs):
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Iteratively calculate uncertainties
|
|
5
|
+
|
|
6
|
+
Inputs:
|
|
7
|
+
Path: User-defined computer path
|
|
8
|
+
Desired Variables: List of variables requested
|
|
9
|
+
OutputCoordinates: Dictionary of geographic coordinates
|
|
10
|
+
PredictorMeasurements: Dictionary of predictor measurements
|
|
11
|
+
**kwargs: Please see README
|
|
12
|
+
|
|
13
|
+
Outputs:
|
|
14
|
+
Uncertainties: Dictionary of uncertainty estimates for each
|
|
15
|
+
equation-variable combination
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import numpy as np
|
|
19
|
+
from PyESPER.defaults import defaults
|
|
20
|
+
from PyESPER.lir_uncertainties import measurement_uncertainty_defaults
|
|
21
|
+
from PyESPER.inputdata_organize import inputdata_organize
|
|
22
|
+
from PyESPER.temperature_define import temperature_define
|
|
23
|
+
from PyESPER.iterations import iterations
|
|
24
|
+
from PyESPER.define_polygons import define_polygons
|
|
25
|
+
from PyESPER.run_nets import run_nets
|
|
26
|
+
from PyESPER.process_netresults import process_netresults
|
|
27
|
+
from PyESPER.emlr_nn import emlr_nn
|
|
28
|
+
|
|
29
|
+
# Predefine output lists
|
|
30
|
+
PD_final, DPD_final, Unc_final, DUnc_final = [], [], [], []
|
|
31
|
+
emlr = []
|
|
32
|
+
|
|
33
|
+
# Rerun nets for each variable
|
|
34
|
+
for d, var in enumerate(DesiredVariables):
|
|
35
|
+
Pertdv, DPertdv, Unc, DUnc = [], [], [], []
|
|
36
|
+
var = [var] # Wrap single variable in a list
|
|
37
|
+
keys = ["sal_u", "temp_u", "phosphate_u", "nitrate_u", "silicate_u", "oxygen_u"]
|
|
38
|
+
|
|
39
|
+
Equations, n, VerboseTF, EstDates, C, PerKgSwTF, MeasUncerts = defaults(
|
|
40
|
+
var,
|
|
41
|
+
PredictorMeasurements,
|
|
42
|
+
OutputCoordinates,
|
|
43
|
+
**kwargs
|
|
44
|
+
)
|
|
45
|
+
Uncertainties_pre, DUncertainties_pre = measurement_uncertainty_defaults(
|
|
46
|
+
n,
|
|
47
|
+
PredictorMeasurements,
|
|
48
|
+
MeasUncerts
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
InputAll = inputdata_organize(
|
|
52
|
+
EstDates,
|
|
53
|
+
C,
|
|
54
|
+
PredictorMeasurements,
|
|
55
|
+
Uncertainties_pre
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
PredictorMeasurements, InputAll = temperature_define(
|
|
59
|
+
var,
|
|
60
|
+
PredictorMeasurements,
|
|
61
|
+
InputAll,
|
|
62
|
+
**kwargs
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
code, unc_combo_dict, dunc_combo_dict = iterations(
|
|
66
|
+
var,
|
|
67
|
+
Equations,
|
|
68
|
+
PerKgSwTF,
|
|
69
|
+
C,
|
|
70
|
+
PredictorMeasurements,
|
|
71
|
+
InputAll,
|
|
72
|
+
Uncertainties_pre,
|
|
73
|
+
DUncertainties_pre
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
df = define_polygons(C)
|
|
77
|
+
|
|
78
|
+
EstAtl, EstOther = run_nets(var, Equations, code)
|
|
79
|
+
|
|
80
|
+
Estimate = process_netresults(
|
|
81
|
+
Equations,
|
|
82
|
+
code,
|
|
83
|
+
df,
|
|
84
|
+
EstAtl,
|
|
85
|
+
EstOther
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
EMLR = emlr_nn(
|
|
89
|
+
Path,
|
|
90
|
+
var,
|
|
91
|
+
Equations,
|
|
92
|
+
OutputCoordinates,
|
|
93
|
+
PredictorMeasurements
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
emlr.append(EMLR)
|
|
97
|
+
names = list(PredictorMeasurements.keys())
|
|
98
|
+
PMs = list(PredictorMeasurements.values())
|
|
99
|
+
|
|
100
|
+
# Replace "nan" with 0 in PMs using list comprehensions
|
|
101
|
+
PMs_nonan = [[0 if val == "nan" else val for val in pm] for pm in PMs]
|
|
102
|
+
|
|
103
|
+
# Transpose PMs_nonan
|
|
104
|
+
PMs = np.transpose(PMs_nonan)
|
|
105
|
+
|
|
106
|
+
PMs3, DMs3 = {}, {}
|
|
107
|
+
|
|
108
|
+
for pred in range(len(PredictorMeasurements)):
|
|
109
|
+
num_coords = len(OutputCoordinates["longitude"])
|
|
110
|
+
num_preds = len(PredictorMeasurements)
|
|
111
|
+
|
|
112
|
+
# Initialize perturbation arrays
|
|
113
|
+
Pert = np.zeros((num_coords, num_preds))
|
|
114
|
+
DefaultPert = np.zeros((num_coords, num_preds))
|
|
115
|
+
|
|
116
|
+
# Populate perturbation arrays
|
|
117
|
+
Pert[:, pred] = Uncertainties_pre[keys[pred]]
|
|
118
|
+
DefaultPert[:, pred] = DUncertainties_pre[keys[pred]]
|
|
119
|
+
|
|
120
|
+
# Apply perturbations
|
|
121
|
+
PMs2 = PMs + Pert
|
|
122
|
+
DMs2 = PMs + DefaultPert
|
|
123
|
+
|
|
124
|
+
# Update PMs3 and DMs3 dictionaries
|
|
125
|
+
for col, name in enumerate(names):
|
|
126
|
+
PMs3[name] = PMs2[:, col].tolist()
|
|
127
|
+
DMs3[name] = DMs2[:, col].tolist()
|
|
128
|
+
|
|
129
|
+
# Run preprocess_applynets for perturbed and default data
|
|
130
|
+
VTF = False
|
|
131
|
+
Eqs2, n2, VerbTF2, EstDates2, C2, PerKgSwTF2, MeasUncerts2 = defaults(
|
|
132
|
+
var,
|
|
133
|
+
PMs2,
|
|
134
|
+
OutputCoordinates,
|
|
135
|
+
Equations=Equations,
|
|
136
|
+
EstDates=EstDates,
|
|
137
|
+
VerboseTF = VTF,
|
|
138
|
+
)
|
|
139
|
+
U_pre2, DU_pre2 = measurement_uncertainty_defaults(
|
|
140
|
+
n2,
|
|
141
|
+
PMs3,
|
|
142
|
+
MeasUncerts2
|
|
143
|
+
)
|
|
144
|
+
InputAll2 = inputdata_organize(
|
|
145
|
+
EstDates2,
|
|
146
|
+
C2,
|
|
147
|
+
PMs3,
|
|
148
|
+
U_pre2
|
|
149
|
+
)
|
|
150
|
+
InputAll3 = inputdata_organize(
|
|
151
|
+
EstDates2,
|
|
152
|
+
C2,
|
|
153
|
+
DMs3,
|
|
154
|
+
U_pre2
|
|
155
|
+
)
|
|
156
|
+
PMs3, InputAll2 = temperature_define(
|
|
157
|
+
var,
|
|
158
|
+
PMs3,
|
|
159
|
+
InputAll2,
|
|
160
|
+
**kwargs
|
|
161
|
+
)
|
|
162
|
+
DMs3, InputAll3 = temperature_define(
|
|
163
|
+
var,
|
|
164
|
+
DMs3,
|
|
165
|
+
InputAll3,
|
|
166
|
+
**kwargs
|
|
167
|
+
)
|
|
168
|
+
code2, unc_combo_dict2, dunc_combo_dict2 = iterations(
|
|
169
|
+
var,
|
|
170
|
+
Eqs2,
|
|
171
|
+
PerKgSwTF2,
|
|
172
|
+
C2,
|
|
173
|
+
PMs3,
|
|
174
|
+
InputAll2,
|
|
175
|
+
U_pre2,
|
|
176
|
+
DU_pre2
|
|
177
|
+
)
|
|
178
|
+
code3, unc_combo_dict3, dunc_combo_dict3 = iterations(
|
|
179
|
+
var,
|
|
180
|
+
Eqs2,
|
|
181
|
+
PerKgSwTF2,
|
|
182
|
+
C2,
|
|
183
|
+
DMs3,
|
|
184
|
+
InputAll3,
|
|
185
|
+
U_pre2,
|
|
186
|
+
DU_pre2
|
|
187
|
+
)
|
|
188
|
+
df2 = define_polygons(C2)
|
|
189
|
+
EstAtl2, EstOther2 = run_nets(
|
|
190
|
+
var,
|
|
191
|
+
Eqs2,
|
|
192
|
+
code2
|
|
193
|
+
)
|
|
194
|
+
EstAtl3, EstOther3 = run_nets(
|
|
195
|
+
var,
|
|
196
|
+
Eqs2,
|
|
197
|
+
code3
|
|
198
|
+
)
|
|
199
|
+
PertEst = process_netresults(
|
|
200
|
+
Eqs2,
|
|
201
|
+
code2,
|
|
202
|
+
df2,
|
|
203
|
+
EstAtl2,
|
|
204
|
+
EstOther2
|
|
205
|
+
)
|
|
206
|
+
DefaultPertEst = process_netresults(
|
|
207
|
+
Eqs2,
|
|
208
|
+
code3,
|
|
209
|
+
df2,
|
|
210
|
+
EstAtl3,
|
|
211
|
+
EstOther3
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
# Extract estimates and perturbation results
|
|
215
|
+
estimates = [np.array(v) for v in Estimate.values()]
|
|
216
|
+
pertests = [np.array(v) for v in PertEst.values()]
|
|
217
|
+
defaultpertests = [np.array(v) for v in DefaultPertEst.values()]
|
|
218
|
+
|
|
219
|
+
# Initialize result lists
|
|
220
|
+
PertDiff, DefaultPertDiff, Unc_sub2, DUnc_sub2 = [], [], [], []
|
|
221
|
+
|
|
222
|
+
for c in range(len(Equations)):
|
|
223
|
+
# Compute differences and squared differences using numpy
|
|
224
|
+
PD = estimates[c] - pertests[c]
|
|
225
|
+
DPD = estimates[c] - defaultpertests[c]
|
|
226
|
+
Unc_sub1 = (estimates[c] - pertests[c])**2
|
|
227
|
+
DUnc_sub1 = (estimates[c] - defaultpertests[c])**2
|
|
228
|
+
|
|
229
|
+
# Append results
|
|
230
|
+
PertDiff.append(PD)
|
|
231
|
+
DefaultPertDiff.append(DPD)
|
|
232
|
+
Unc_sub2.append(Unc_sub1)
|
|
233
|
+
DUnc_sub2.append(DUnc_sub1)
|
|
234
|
+
Pertdv.append(PertDiff)
|
|
235
|
+
DPertdv.append(DefaultPertDiff)
|
|
236
|
+
Unc.append(Unc_sub2)
|
|
237
|
+
DUnc.append(DUnc_sub2)
|
|
238
|
+
PD_final.append(Pertdv)
|
|
239
|
+
DPD_final.append(DPertdv)
|
|
240
|
+
Unc_final.append(Unc)
|
|
241
|
+
DUnc_final.append(DUnc)
|
|
242
|
+
|
|
243
|
+
# Compute final uncertainty propagation
|
|
244
|
+
|
|
245
|
+
est = [np.array(v) for v in Estimate.values()]
|
|
246
|
+
emlr_combined = {k: v for d in emlr for k, v in d.items()}
|
|
247
|
+
Uncertainties = {}
|
|
248
|
+
for dv in range(0, len(DesiredVariables)):
|
|
249
|
+
dvu = []
|
|
250
|
+
for eq in range(0, len(Equations)):
|
|
251
|
+
sumu = []
|
|
252
|
+
name = DesiredVariables[dv] + str(Equations[eq])
|
|
253
|
+
for n in range(0, len(est[0])):
|
|
254
|
+
# Collect uncertainty contributions from each perturbation
|
|
255
|
+
u = np.array([Unc_final[dv][pre][eq][n] for pre in range(len(PredictorMeasurements))])
|
|
256
|
+
du = np.array([DUnc_final[dv][pre][eq][n] for pre in range(len(PredictorMeasurements))])
|
|
257
|
+
eu = emlr_combined[name][n]
|
|
258
|
+
# Final uncertainty formula
|
|
259
|
+
total_uncertainty = np.sqrt(np.sum(u) - np.sum(du) + eu**2)
|
|
260
|
+
sumu.append(total_uncertainty)
|
|
261
|
+
dvu.append(sumu)
|
|
262
|
+
|
|
263
|
+
Uncertainties[name] = dvu[0]
|
|
264
|
+
|
|
265
|
+
return Uncertainties
|
|
266
|
+
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
def pH_DIC_nn_adjustment(Path, DesiredVariables, Estimates, YouHaveBeenWarnedCanth, OutputCoordinates={}, PredictorMeasurements={}, **kwargs):
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Calculating the anthropogenic carbon component for DIC and pH, if needed
|
|
5
|
+
|
|
6
|
+
Inputs:
|
|
7
|
+
Path: Path for user computer
|
|
8
|
+
DesiredVariables: List of variables for which estimates are requested
|
|
9
|
+
Estimates: Dictionary of estimates for each equation-variable combination
|
|
10
|
+
YouHaveBeenWarnedCanth: Boolean for avoiding repeat warnings
|
|
11
|
+
OutputCoordinates: Dictionary of coordinates for requested estimates
|
|
12
|
+
PredictorMeasurements: Dictionary of measurements for calculations
|
|
13
|
+
**kwargs: Please see README for full information
|
|
14
|
+
|
|
15
|
+
Outputs:
|
|
16
|
+
Cant_adjusted: Dictionary of estimates adjusted for anthropogenic carbon
|
|
17
|
+
for each equation-variable combination
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from PyESPER.simplecantestimatelr import simplecantestimatelr
|
|
21
|
+
import numpy as np
|
|
22
|
+
from PyESPER.defaults import defaults
|
|
23
|
+
from PyESPER.lir_uncertainties import measurement_uncertainty_defaults
|
|
24
|
+
from PyESPER.inputdata_organize import inputdata_organize
|
|
25
|
+
from PyESPER.temperature_define import temperature_define
|
|
26
|
+
from PyESPER.iterations import iterations
|
|
27
|
+
from PyESPER.define_polygons import define_polygons
|
|
28
|
+
from PyESPER.run_nets import run_nets
|
|
29
|
+
from PyESPER.process_netresults import process_netresults
|
|
30
|
+
import seawater as sw
|
|
31
|
+
import PyCO2SYS as pyco2
|
|
32
|
+
|
|
33
|
+
# Interpreting kwargs and setting defaults if needed
|
|
34
|
+
VerboseTF = kwargs.get("VerboseTF", True)
|
|
35
|
+
n = max(len(v) for v in OutputCoordinates.values())
|
|
36
|
+
if "EstDates" in kwargs:
|
|
37
|
+
d = np.array(kwargs["EstDates"])
|
|
38
|
+
EstDates = (
|
|
39
|
+
[item for sublist in [kwargs["EstDates"]] * (n + 1) for item in sublist]
|
|
40
|
+
if len(d) != n else list(d)
|
|
41
|
+
)
|
|
42
|
+
else:
|
|
43
|
+
EstDates = [2002.0] * n
|
|
44
|
+
|
|
45
|
+
# Predefining empty dictionary for results and parsing out estimates
|
|
46
|
+
Cant_adjusted = {}
|
|
47
|
+
combos2 = list(Estimates.keys())
|
|
48
|
+
values2 = list(Estimates.values())
|
|
49
|
+
|
|
50
|
+
# Only if dates are available and if needed, continue
|
|
51
|
+
if "EstDates" in kwargs and ("DIC" in DesiredVariables or "pH" in DesiredVariables):
|
|
52
|
+
if not YouHaveBeenWarnedCanth:
|
|
53
|
+
if VerboseTF:
|
|
54
|
+
print("Estimating anthropogenic carbon for PyESPER_NN.")
|
|
55
|
+
longitude = np.mod(OutputCoordinates["longitude"], 360)
|
|
56
|
+
latitude = np.array(OutputCoordinates["latitude"])
|
|
57
|
+
depth = np.array(OutputCoordinates["depth"])
|
|
58
|
+
Cant, Cant2002 = simplecantestimatelr(EstDates, longitude, latitude, depth)
|
|
59
|
+
YouHaveBeenWarnedCanth = True
|
|
60
|
+
|
|
61
|
+
for combo, a in zip(combos2, values2):
|
|
62
|
+
a = np.array(a, dtype=float)
|
|
63
|
+
if combo.startswith("DIC"):
|
|
64
|
+
a = np.where(np.isnan(a), "nan", a + Cant - Cant2002)
|
|
65
|
+
Cant_adjusted[combo] = a.tolist()
|
|
66
|
+
else:
|
|
67
|
+
Cant_adjusted[combo] = a.tolist()
|
|
68
|
+
|
|
69
|
+
# Extra perturbation for pH
|
|
70
|
+
if "pH" in DesiredVariables:
|
|
71
|
+
warning = []
|
|
72
|
+
for combo, values in zip (combos2, values2):
|
|
73
|
+
if combo.startswith("pH"):
|
|
74
|
+
salinity = PredictorMeasurements["salinity"]
|
|
75
|
+
PM_pH = {"salinity": salinity}
|
|
76
|
+
eq = [16]
|
|
77
|
+
_, n, _, EstDates, C, PerKgSwTF, MeasUncerts = defaults(
|
|
78
|
+
["TA"],
|
|
79
|
+
PM_pH,
|
|
80
|
+
OutputCoordinates,
|
|
81
|
+
**kwargs
|
|
82
|
+
)
|
|
83
|
+
U_pre, DU_pre = measurement_uncertainty_defaults(
|
|
84
|
+
n,
|
|
85
|
+
PM_pH,
|
|
86
|
+
MeasUncerts
|
|
87
|
+
)
|
|
88
|
+
InputAll = inputdata_organize(
|
|
89
|
+
EstDates,
|
|
90
|
+
C,
|
|
91
|
+
PM_pH,
|
|
92
|
+
U_pre
|
|
93
|
+
)
|
|
94
|
+
PM_pH, InputAll = temperature_define(
|
|
95
|
+
["TA"],
|
|
96
|
+
PM_pH,
|
|
97
|
+
InputAll,
|
|
98
|
+
**kwargs
|
|
99
|
+
)
|
|
100
|
+
code, unc_combo_dict, dunc_combo_dict = iterations(
|
|
101
|
+
["TA"],
|
|
102
|
+
eq,
|
|
103
|
+
PerKgSwTF,
|
|
104
|
+
C,
|
|
105
|
+
PM_pH,
|
|
106
|
+
InputAll,
|
|
107
|
+
U_pre,
|
|
108
|
+
DU_pre
|
|
109
|
+
)
|
|
110
|
+
df = define_polygons(C)
|
|
111
|
+
EstAtl, EstOther = run_nets(
|
|
112
|
+
["TA"],
|
|
113
|
+
eq,
|
|
114
|
+
code
|
|
115
|
+
)
|
|
116
|
+
alkest = process_netresults(
|
|
117
|
+
eq,
|
|
118
|
+
code,
|
|
119
|
+
df,
|
|
120
|
+
EstAtl,
|
|
121
|
+
EstOther
|
|
122
|
+
)
|
|
123
|
+
EstAlk = np.array(alkest["TA16"])
|
|
124
|
+
EstSi = EstP = [0] * len(EstAlk)
|
|
125
|
+
Pressure = sw.pres(OutputCoordinates["depth"], OutputCoordinates["latitude"])
|
|
126
|
+
Est = np.array(values)
|
|
127
|
+
|
|
128
|
+
# CO2SYS calculations
|
|
129
|
+
Out = pyco2.sys(
|
|
130
|
+
par1=EstAlk,
|
|
131
|
+
par2=Est,
|
|
132
|
+
par1_type=1,
|
|
133
|
+
par2_type=3,
|
|
134
|
+
salinity=salinity,
|
|
135
|
+
temperature=PredictorMeasurements["temperature"],
|
|
136
|
+
temperature_out=PredictorMeasurements["temperature"],
|
|
137
|
+
pressure=Pressure,
|
|
138
|
+
pressure_out=Pressure,
|
|
139
|
+
total_silicate=EstSi,
|
|
140
|
+
total_phosphate=EstP,
|
|
141
|
+
opt_total_borate= 2
|
|
142
|
+
)
|
|
143
|
+
DICadj = Out["dic"] + Cant - Cant2002
|
|
144
|
+
OutAdj = pyco2.sys(
|
|
145
|
+
par1=EstAlk,
|
|
146
|
+
par2=DICadj,
|
|
147
|
+
par1_type=1,
|
|
148
|
+
par2_type=2,
|
|
149
|
+
salinity=salinity,
|
|
150
|
+
temperature=PredictorMeasurements["temperature"],
|
|
151
|
+
temperature_out=PredictorMeasurements["temperature"],
|
|
152
|
+
pressure=Pressure,
|
|
153
|
+
pressure_out=Pressure,
|
|
154
|
+
total_silicate=EstSi,
|
|
155
|
+
total_phosphate=EstP,
|
|
156
|
+
opt_total_borate=2
|
|
157
|
+
)
|
|
158
|
+
pHadj = OutAdj["pH"]
|
|
159
|
+
|
|
160
|
+
if any(np.isnan(pHadj)):
|
|
161
|
+
warning_message = (
|
|
162
|
+
"Warning: CO2SS took >20 iterations to converge. The correcponding estimate(s) will be NaN. "
|
|
163
|
+
"This typically happens when ESPER_NN is pooorly suited for estimating water with the given properties "
|
|
164
|
+
"(e.g., very high or low salinity or estimates in marginal seas)."
|
|
165
|
+
)
|
|
166
|
+
warning.append(warning_message)
|
|
167
|
+
else:
|
|
168
|
+
pHadj = np.array(values)
|
|
169
|
+
|
|
170
|
+
Cant_adjusted[combo] = pHadj.tolist()
|
|
171
|
+
|
|
172
|
+
# Print warnings if any
|
|
173
|
+
if warning:
|
|
174
|
+
print(warning[0])
|
|
175
|
+
|
|
176
|
+
elif "EstDates" not in kwargs and ("DIC" or "pH" in DesiredVariables) and VerboseTF and not YouHaveBeenWarnedCanth:
|
|
177
|
+
print("Warning: DIC or pH is a requested output but the user did not provide dates for the desired estimates. The estimates will be specific to 2002.0 unless the optional EstDates input is provided (recommended).")
|
|
178
|
+
YouHaveBeenWarnedCanth = True
|
|
179
|
+
|
|
180
|
+
if kwargs.get("pHCalcTF") and "pH" in DesiredVariables:
|
|
181
|
+
if VerboseTF:
|
|
182
|
+
print("Recalculating the pH to be appropriate for pH values calculated from TA and DIC.")
|
|
183
|
+
for combo, pH_values in zip(combos2, values2):
|
|
184
|
+
if combo.startswith("pH"):
|
|
185
|
+
pH_adjcalc_Est = [(pH + 0.3168) / 1.0404 for pH in pH_values]
|
|
186
|
+
Cant_adjusted[combo] = pH_adjcalc_Est
|
|
187
|
+
|
|
188
|
+
return Cant_adjusted
|
|
189
|
+
|
PyESPER/pH_adjcalc.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
def pH_adjcalc(DesiredVariables, VerboseTF, Est_pre={}, Cant_adjusted={}, **kwargs):
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Calculating pH adjustment if units are not in molal format
|
|
5
|
+
|
|
6
|
+
Inputs:
|
|
7
|
+
DesiredVariables: List of variables requested
|
|
8
|
+
VerboseTF: Boolean option to suppress warnings
|
|
9
|
+
Est_pre: Dictionary of estimates thus far for each variable equation combination
|
|
10
|
+
Cant_adjusted: Dictionary of estimates adjusted for anthropogenic carbon for each
|
|
11
|
+
combination
|
|
12
|
+
**kwargs: Please see README for full information
|
|
13
|
+
|
|
14
|
+
Outputs:
|
|
15
|
+
Cant_adjusted: Dictionary of estimates adjusted for anthropogenic carbon
|
|
16
|
+
combos2: List of equation case-desired variable combinations
|
|
17
|
+
values2: List of estimates
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
combos2 = list(Est_pre.keys())
|
|
21
|
+
values2 = list(Est_pre.values())
|
|
22
|
+
|
|
23
|
+
if kwargs.get("pHCalcTF") and "pH" in DesiredVariables:
|
|
24
|
+
if VerboseTF:
|
|
25
|
+
print("Recalculating the pH to be appropriate for pH values calculated from TA and DIC.")
|
|
26
|
+
|
|
27
|
+
for combo in range(0, len(combos2)):
|
|
28
|
+
if combos2[combo].startswith("pH"):
|
|
29
|
+
pH_adjcalc_Est = []
|
|
30
|
+
pH_adjcalc = values2[combo]
|
|
31
|
+
for v in pH_adjcalc:
|
|
32
|
+
pH_adjcalc_Est.append((pH_adjcalc[v]+0.3168)/1.0404)
|
|
33
|
+
Cant_adjusted[combos2[combo]] = pH_adjcalc_Est
|
|
34
|
+
|
|
35
|
+
return Cant_adjusted, combos2, values2
|
|
36
|
+
|
PyESPER/pH_adjustment.py
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
def pH_adjustment(
|
|
2
|
+
Path,
|
|
3
|
+
DesiredVariables,
|
|
4
|
+
Dates,
|
|
5
|
+
Cant,
|
|
6
|
+
Cant2002,
|
|
7
|
+
PerKgSwTF,
|
|
8
|
+
Cant_adjusted={},
|
|
9
|
+
Est_pre={},
|
|
10
|
+
PredictorMeasurements={},
|
|
11
|
+
OutputCoordinates={},
|
|
12
|
+
C={},
|
|
13
|
+
Uncertainties_pre={},
|
|
14
|
+
DUncertainties_pre={},
|
|
15
|
+
**kwargs
|
|
16
|
+
):
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
Adjusting pH for anthropogenic carbon in the second of three Cant adjustment
|
|
20
|
+
scripts
|
|
21
|
+
|
|
22
|
+
Inputs:
|
|
23
|
+
Path: User-defined computer path
|
|
24
|
+
DesiredVariables: List of desired variables to estimate
|
|
25
|
+
Dates: List of dates for measurements
|
|
26
|
+
Cant: Numpy array of anthropogenic carbon estimates for each estimate
|
|
27
|
+
Cant2002: Numpy array of anthropogenic carbon estimates for each
|
|
28
|
+
estimate for the year 2002
|
|
29
|
+
PerKgSwTF: Boolean for whether measurements were in molar or molal units
|
|
30
|
+
Cant_adjusted: Dictionary of estimates adjusted for Cant
|
|
31
|
+
Est_pre: Dictionary of estimates for each combination
|
|
32
|
+
PredictorMeasurements: Dictionary of measurements for estimates
|
|
33
|
+
OutputCoordinates: Dictionary of geographic coordinates for estimates
|
|
34
|
+
C: Dictionary of adjusted coordinates for estimates
|
|
35
|
+
Uncertainties_pre: Dictionary of measurement uncertainties for estimates
|
|
36
|
+
DUncertainties_pre: Dictionary of default measurement uncertainties for
|
|
37
|
+
estimates
|
|
38
|
+
**kwargs: Please see README
|
|
39
|
+
|
|
40
|
+
Output:
|
|
41
|
+
Cant_adjusted: Dictionary of adjusted values for Cant for each combination
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
import numpy as np
|
|
45
|
+
import seawater as sw
|
|
46
|
+
import PyCO2SYS as pyco2
|
|
47
|
+
from PyESPER.inputdata_organize import inputdata_organize
|
|
48
|
+
from PyESPER.temperature_define import temperature_define
|
|
49
|
+
from PyESPER.iterations import iterations
|
|
50
|
+
from PyESPER.fetch_data import fetch_data
|
|
51
|
+
from PyESPER.input_AAinds import input_AAinds
|
|
52
|
+
from PyESPER.coefs_AAinds import coefs_AAinds
|
|
53
|
+
from PyESPER.interpolate import interpolate
|
|
54
|
+
from PyESPER.organize_data import organize_data
|
|
55
|
+
|
|
56
|
+
# Finding the estimates within the dictionary
|
|
57
|
+
combos2 = list(Est_pre.keys())
|
|
58
|
+
values2 = list(Est_pre.values())
|
|
59
|
+
|
|
60
|
+
# Setting the default warning message boolean and Verbose
|
|
61
|
+
YouHaveBeenWarnedCanth = False
|
|
62
|
+
VerboseTF = kwargs.get("VerboseTF", True)
|
|
63
|
+
|
|
64
|
+
# Proceed only if dates are provided and DIC or pH is requested
|
|
65
|
+
if "EstDates" in kwargs and ("DIC" in DesiredVariables or "pH" in DesiredVariables):
|
|
66
|
+
if "pH" in DesiredVariables:
|
|
67
|
+
warning = []
|
|
68
|
+
for combo, values in zip(combos2, values2):
|
|
69
|
+
if combo.startswith("pH"):
|
|
70
|
+
# Rerunning LIRs for when pH is requested to obtain TA estimates
|
|
71
|
+
# based only on salinity input
|
|
72
|
+
salinity = PredictorMeasurements["salinity"]
|
|
73
|
+
PM_pH = {"salinity": salinity}
|
|
74
|
+
eq = [16]
|
|
75
|
+
InputAll2 = inputdata_organize(
|
|
76
|
+
Dates,
|
|
77
|
+
C,
|
|
78
|
+
PM_pH,
|
|
79
|
+
Uncertainties_pre
|
|
80
|
+
)
|
|
81
|
+
PredictorMeasurements2, InputAll2 = temperature_define(
|
|
82
|
+
["TA"],
|
|
83
|
+
PM_pH,
|
|
84
|
+
InputAll2,
|
|
85
|
+
**kwargs
|
|
86
|
+
)
|
|
87
|
+
code, unc_combo_dict, dunc_combo_dict = iterations(
|
|
88
|
+
["TA"],
|
|
89
|
+
eq,
|
|
90
|
+
PerKgSwTF,
|
|
91
|
+
C,
|
|
92
|
+
PredictorMeasurements2,
|
|
93
|
+
InputAll2,
|
|
94
|
+
Uncertainties_pre,
|
|
95
|
+
DUncertainties_pre
|
|
96
|
+
)
|
|
97
|
+
LIR_data = fetch_data(["TA"], Path)
|
|
98
|
+
AAdata, Elsedata = input_AAinds(C, code)
|
|
99
|
+
Gdf, CsDesired = coefs_AAinds(eq, LIR_data)
|
|
100
|
+
aaLCs, aaInterpolants_pre, elLCs, elInterpolants_pre = interpolate(
|
|
101
|
+
Gdf,
|
|
102
|
+
AAdata,
|
|
103
|
+
Elsedata
|
|
104
|
+
)
|
|
105
|
+
alkest, _ = organize_data(
|
|
106
|
+
aaLCs,
|
|
107
|
+
elLCs,
|
|
108
|
+
aaInterpolants_pre,
|
|
109
|
+
elInterpolants_pre,
|
|
110
|
+
Gdf,
|
|
111
|
+
AAdata,
|
|
112
|
+
Elsedata
|
|
113
|
+
)
|
|
114
|
+
EstAlk = np.array(alkest["TA16"])
|
|
115
|
+
EstAlk = np.transpose(EstAlk)
|
|
116
|
+
EstSi = EstP = [0] * len(EstAlk)
|
|
117
|
+
# Calculating pressure using the sw package
|
|
118
|
+
Pressure = sw.pres(OutputCoordinates["depth"], OutputCoordinates["latitude"])
|
|
119
|
+
Est = np.array(values)
|
|
120
|
+
Est = np.transpose(Est)
|
|
121
|
+
Est = Est[0]
|
|
122
|
+
temperature = np.array(PredictorMeasurements["temperature"])
|
|
123
|
+
# Now using CO2SYS to calculate DIC based on the above LIR results for TA
|
|
124
|
+
# CO2SYS calculations
|
|
125
|
+
kwargCO2 = {
|
|
126
|
+
"par1":EstAlk,
|
|
127
|
+
"par2":Est,
|
|
128
|
+
"par1_type":1,
|
|
129
|
+
"par2_type":3,
|
|
130
|
+
"salinity":salinity,
|
|
131
|
+
"temperature":temperature,
|
|
132
|
+
"temperature_out":temperature,
|
|
133
|
+
"pressure":Pressure,
|
|
134
|
+
"pressure_out":Pressure,
|
|
135
|
+
"total_silicate":EstSi,
|
|
136
|
+
"total_phosphate":EstP,
|
|
137
|
+
"opt_total_borate":2}
|
|
138
|
+
Out = pyco2.sys(**kwargCO2)
|
|
139
|
+
DICadj = Out["dic"] + Cant - Cant2002
|
|
140
|
+
|
|
141
|
+
# Using this DIC to calculate pH from CO2SYS
|
|
142
|
+
kwargCO2_2 = {
|
|
143
|
+
"par1":EstAlk,
|
|
144
|
+
"par2":DICadj,
|
|
145
|
+
"par1_type":1,
|
|
146
|
+
"par2_type":2,
|
|
147
|
+
"salinity":salinity,
|
|
148
|
+
"temperature":temperature,
|
|
149
|
+
"temperature_out":temperature,
|
|
150
|
+
"pressure":Pressure,
|
|
151
|
+
"pressure_out":Pressure,
|
|
152
|
+
"total_silicate":EstSi,
|
|
153
|
+
"total_phosphate":EstP,
|
|
154
|
+
"opt_total_borate":2}
|
|
155
|
+
OutAdj = pyco2.sys(**kwargCO2_2)
|
|
156
|
+
pHadj = OutAdj["pH"]
|
|
157
|
+
|
|
158
|
+
# Check for convergence warnings
|
|
159
|
+
if np.isnan(pHadj).any():
|
|
160
|
+
warning_message = (
|
|
161
|
+
"Warning: CO2SYS took >20 iterations to converge. The corresponding estimate(s) will be NaN. "
|
|
162
|
+
"This typically happens when ESPER_LIR is poorly suited for estimating water with the given properties "
|
|
163
|
+
"(e.g., very high or low salinity or estimates in marginal seas)."
|
|
164
|
+
)
|
|
165
|
+
warning.append(warning_message)
|
|
166
|
+
# Append to adjusted Cant dictionary
|
|
167
|
+
Cant_adjusted[combo] = pHadj.tolist()
|
|
168
|
+
|
|
169
|
+
# Print warnings if any
|
|
170
|
+
if warning:
|
|
171
|
+
print(warning[0])
|
|
172
|
+
|
|
173
|
+
elif "EstDates" not in kwargs and ("DIC" or "pH" in DesiredVariables) and not VerboseTF and YouHaveBeenWarnedCanth:
|
|
174
|
+
print("Warning: DIC or pH is a requested output but the user did not provide dates for the desired esimtates. The estimates "
|
|
175
|
+
"will be specific to 2002.0 unless the optional EstDates input is provided (recommended).")
|
|
176
|
+
|
|
177
|
+
YouHaveBeenWarnedCanth = True
|
|
178
|
+
|
|
179
|
+
return Cant_adjusted
|