def calc_myami_Csys(dat): cols = ['pHtot', 'DIC', 'HCO3', 'CO3', 'TA'] dic = dat.loc[:, 'DIC'].copy() # pHNBS and DIC ind = ~np.isnan(dat.loc[:, 'pHNBS']) & ~np.isnan(dic) if any(ind): cs = cb.Csys( pHNBS=dat.loc[ind, 'pHNBS'], DIC=dic.loc[ind], BT=dat.loc[ind, 'B umol/kg'], Ca=dat.loc[ind, '[Ca]sw'] * 1e-3, Mg=dat.loc[ind, '[Mg]sw'] * 1e-3, T_in=dat.loc[ind, 'Temp'], S_in=dat.loc[ind, 'Salinity'], ) for c in cols: dat.loc[ind, c.replace('_out', '')] = cs[c] dat.loc[ind, 'omega'] = cs.CO3 * 1e-6 * cs.Ca / cs.Ks.KspC # pHTOT and DIC ind = ~np.isnan(dat.loc[:, 'pHTOTAL']) & ~np.isnan(dic) if any(ind): cs = cb.Csys( pHtot=dat.loc[ind, 'pHTOTAL'], DIC=dic.loc[ind], BT=dat.loc[ind, 'B umol/kg'], Ca=dat.loc[ind, '[Ca]sw'] * 1e-3, Mg=dat.loc[ind, '[Mg]sw'] * 1e-3, T_in=dat.loc[ind, 'Temp'], S_in=dat.loc[ind, 'Salinity'], ) for c in cols: dat.loc[ind, c.replace('_out', '')] = cs[c] dat.loc[ind, 'omega'] = cs.CO3 * 1e-6 * cs.Ca / cs.Ks.KspC # pHTOT and TA ind = ~np.isnan(dat.loc[:, 'pHTOTAL']) & ~np.isnan(dat.loc[:, 'Alk']) if any(ind): cs = cb.Csys( pHtot=dat.loc[ind, 'pHTOTAL'], TA=dat.loc[ind, 'Alk'], BT=dat.loc[ind, 'B umol/kg'], Ca=dat.loc[ind, '[Ca]sw'] * 1e-3, Mg=dat.loc[ind, '[Mg]sw'] * 1e-3, T_in=dat.loc[ind, 'Temp'], S_in=dat.loc[ind, 'Salinity'], ) for c in cols: dat.loc[ind, c.replace('_out', '')] = cs[c] dat.loc[ind, 'omega'] = cs.CO3 * 1e-6 * cs.Ca / cs.Ks.KspC # pHNBS and TA ind = ~np.isnan(dat.loc[:, 'pHNBS']) & ~np.isnan(dat.loc[:, 'Alk']) if any(ind): cs = cb.Csys( pHNBS=dat.loc[ind, 'pHNBS'], TA=dat.loc[ind, 'Alk'], BT=dat.loc[ind, 'B umol/kg'], Ca=dat.loc[ind, '[Ca]sw'] * 1e-3, Mg=dat.loc[ind, '[Mg]sw'] * 1e-3, T_in=dat.loc[ind, 'Temp'], S_in=dat.loc[ind, 'Salinity'], ) for c in cols: dat.loc[ind, c.replace('_out', '')] = cs[c] dat.loc[ind, 'omega'] = cs.CO3 * 1e-6 * cs.Ca / cs.Ks.KspC return dat
Si : `numpy.array` or `xarray.DataArray` or `pd.core.series.Series` Silicate (umol/kg) AOU : `numpy.array` or `xarray.DataArray` or `pd.core.series.Series` Apparent Oxygen Utilization (umol/kg) Returns ------- dcstar : `numpy.array` or `xarray.DataArray` or `pd.core.series.Series` An array of ∆C* values (umol/kg) """ if Gruber == True: Alk_pre_calc = 367.5 + 54.9*S + 0.074*PO(P,O) out = cb.Csys(fCO2=280,TA=Alk_pre_calc.ravel(),T=theta.ravel(),S=S.ravel()) DICpi_eq = np.reshape(out.DIC,DIC.shape) dcstar = DIC-R_co*AOU-0.5*(Alk-Alk_pre_calc+(16/170)*(AOU))-DICpi_eq else: Alk_pre_calc = Alk_pre(N,O,P,Si,S,theta,AOU,Alk_pre_eomp) out = cb.Csys(fCO2=280,TA=Alk_pre_calc.ravel(),T=theta.ravel()) DICpi_eq = np.reshape(out.DIC,DIC.shape) dcstar = DIC-R_co*AOU-dCa(N,O,P,Si,Alk,S,theta)-DICpi_eq
def calc_pitzer_Csys( dat, database='/home/oscar/phreeqc/iphreeqc-3.3.9-11951/database/pitzer.dat', phreeq_path='/usr/local/lib/libiphreeqc.so'): """ Function to calculate C specitation, corrected for [Mg] and [Ca] using PHREEQC. Parameters ---------- d : pandas.DataFrame Output of mg_data load function. database : str Path to PITZER database file. phreeq_path : str Path to PHREEQC executable. """ # remove data without [Mg] and [Ca] dat = dat.loc[~dat.loc[:, ['[Mg]sw', '[Ca]sw']].isnull().any(1)] # create working copy d = dat.copy() # rename columns d.columns = pd.MultiIndex.from_product([['Measured'], d.columns]) # define standard seawater composition (mol/kg SW) # ================================================ sw = { 'pH': 8.2, 'Temp': 25, 'units': 'mol/kgw', 'density': 1.026, 'Ca': 10.28e-3, 'Cl': 0.54586, 'K': 10.21e-3, 'Mg': 52.82e-3, 'Na': 0.46906, 'S(6)': 0.02824, 'B': 416e-6, 'C': 2.3e-3, 'Br': 0.84e-3, 'F': 0.7e-4 } # calculate ambient Ks at 25C (measurement temperature) # ===================================================== ks = {} TempC = 25 TempK = TempC + 273.15 Sal = d.loc[:, ('Measured', 'Salinity')] par = cb.MyAMI_V2.start_params fns = cb.MyAMI_V2.fn_dict for k in ['K0', 'K1', 'K2', 'KB', 'KW', 'KspC', 'KspA', 'KSO4']: ks[k] = fns[k]((TempK, Sal), *par[k]) # calculate other Ks ks.update(cb.non_MyAMI_constants.calc_KF(TempC, Sal)) ks.update(cb.non_MyAMI_constants.calc_KPs(TempC, Sal)) ks.update(cb.non_MyAMI_constants.calc_KSi(TempC, Sal)) # calculate correction factors at 25C # =================================== fKs = {} isw = sw.copy() salsc = ['Cl', 'K', 'Na', 'S(6)', 'Br', 'F'] for i, v in tqdm(d.iterrows(), total=d.shape[0], desc='Calculating 25C Corrections'): v = v.Measured isw.update({ 'Mg': v.loc['[Mg]sw'] * 1e-3, 'Ca': v.loc['[Ca]sw'] * 1e-3, 'Temp': 25, 'B': v.loc['B umol/kg'] * 1e-6 }) sal_f = v.Salinity / 35. isw.update({k: sw[k] * sal_f for k in salsc}) fks = ph.calc_pitzer_fKs(sw, isw, database=database, phreeq_path=phreeq_path) for k, f in fks.items(): if k not in fKs: fKs[k] = [] fKs[k].append(f) # apply correction factors to 25C Ks # ================================== cKs = ks.copy() for k, f in fKs.items(): cKs[k] = ks[k] * f # convert all pH scales to Total # ============================== pHs = cb.helpers.calc_pH_scales(pHtot=None, pHfree=None, pHsws=None, pHNBS=d.loc[:, ('Measured', 'pHNBS')], TS=cb.calc_TS(Sal), TF=cb.calc_TF(Sal), TempK=TempK, Sal=Sal, Ks=cb.Bunch(cKs)) ind = d.loc[:, ('Measured', 'pHTOTAL')].isnull() d.loc[ind, ('Measured', 'pHTOTAL')] = pHs['pHtot'][ind] # Calculate DIC/Alk at MEASURED conditions (25C) # ============================================== # calculate carbon system using 25C Ks, pH and either DIC or Alk carb = cb.Csys(d.loc[:, ('Measured', 'pHTOTAL')], TA=d.loc[:, ('Measured', 'Alk')], BT=d.loc[:, ('Measured', 'B umol/kg')], Ks=cKs) d.loc[:, ('pitzer_25C', 'DIC')] = carb.DIC carb = cb.Csys(d.loc[:, ('Measured', 'pHTOTAL')], DIC=d.loc[:, ('Measured', 'DIC')], BT=d.loc[:, ('Measured', 'B umol/kg')], Ks=cKs) d.loc[:, ('pitzer_25C', 'Alk')] = carb.TA # whichever of DIC or Alk wasn't calculated, transfer the # measured value to the pitzer_25C column for in-situ condition calculation dicnull = d.loc[:, ('pitzer_25C', 'DIC')].isnull() d.loc[dicnull, ('pitzer_25C', 'DIC')] = d.loc[dicnull, ('Measured', 'DIC')] alknull = d.loc[:, ('pitzer_25C', 'Alk')].isnull() d.loc[alknull, ('pitzer_25C', 'Alk')] = d.loc[alknull, ('Measured', 'Alk')] # calculate empirical Ks for ambient Mg and Ca, and experiment Sal and Temp # ========================================================================= eKs = cb.calc_Ks(d.loc[:, ('Measured', 'Temp')], d.loc[:, ('Measured', 'Salinity')], 0, sw['Mg'], sw['Ca'], cb.calc_TS(d.loc[:, ('Measured', 'Salinity')]), cb.calc_TF(d.loc[:, ('Measured', 'Salinity')])) # calculate correction factors at experimental temperature # ======================================================== fKs = {} isw = sw.copy() salsc = ['Cl', 'K', 'Na', 'S(6)', 'Br', 'F'] for i, v in tqdm(d.iterrows(), total=d.shape[0], desc='Calculating Experimental T Corrections'): v = v.Measured isw.update({ 'Mg': v.loc['[Mg]sw'] * 1e-3, 'Ca': v.loc['[Ca]sw'] * 1e-3, 'Temp': v.Temp, 'B': v.loc['B umol/kg'] * 1e-6 }) sal_f = v.Salinity / 35. isw.update({k: sw[k] * sal_f for k in salsc}) fks = ph.calc_pitzer_fKs(sw, isw, database=database, phreeq_path=phreeq_path) for k, f in fks.items(): if k not in fKs: fKs[k] = [] fKs[k].append(f) # apply correction factors for k, f in fKs.items(): eKs[k] = ks[k] * f # calculate carbon system at experimental conditions using pitzer-calculated DIC/Alk pairs carb = cb.Csys(DIC=d.loc[:, ('pitzer_25C', 'DIC')], TA=d.loc[:, ('pitzer_25C', 'Alk')], BT=d.loc[:, ('Measured', 'B umol/kg')], Ks=cKs) # store outputs! for c in ['DIC', 'TA', 'CO3', 'HCO3', 'CO2', 'pHtot']: d.loc[:, ('pitzer_expT', c)] = carb[c] dat.loc[:, c] = carb[c] return dat
def GLODAPv2_comparison(figdir='.'): print("\n********************************************") print("Generating GLODAPv2 Comparison Plots") print("********************************************") # if the data file is missing, get it. if not os.path.exists('./GLODAPv2_pH_DIC_ALK_subset.csv'): print('Getting GLODAPv2 Data...') from get_GLODAP_data import get_GLODAP get_GLODAP() # Load data print('Importing GLODAPv2 Data...') gd = pd.read_csv('./GLODAPv2_pH_DIC_ALK_subset.csv') gd.dropna(subset=[ 'phtsinsitutp', 'temperature', 'salinity', 'tco2', 'talk', 'pressure', 'phosphate', 'silicate' ], inplace=True) gd.pressure /= 10 # convert pressure to bar # exclude weird cruise 270 data gd = gd.loc[gd.cruise != 270] # Do the work... print('Calculating pH from DIC and TA...') cpH = cb.Csys(TA=gd.talk, DIC=gd.tco2, T=gd.temperature, S=gd.salinity, P=gd.pressure, TP=gd.phosphate, TSi=gd.silicate, BT=415.7) print(' Making plots...') fig, axs = cplot(gd.phtsinsitutp, cpH.pH, 'pH', 'Depth', gd.depth) fig.savefig(figdir + '/Figures/pH_comparison.png', dpi=200) print('Calculating TA from pH and DIC...') cTA = cb.Csys(pH=gd.phtsinsitutp, DIC=gd.tco2, T=gd.temperature, S=gd.salinity, P=gd.pressure, TP=gd.phosphate, TSi=gd.silicate, BT=415.7) print(' Making plots...') fig, ax = cplot(gd.talk, cTA.TA, 'Alk', 'Depth', gd.depth) fig.savefig('Figures/TA_comparison.png', dpi=200) print('Calculating DIC from pH and TA...') cDIC = cb.Csys(pH=gd.phtsinsitutp, TA=gd.talk, T=gd.temperature, S=gd.salinity, P=gd.pressure, TP=gd.phosphate, TSi=gd.silicate, BT=415.7) print(' Making plots...') fig, ax = cplot(gd.tco2, cDIC.DIC, 'DIC', 'Depth', gd.depth) fig.savefig('Figures/DIC_comparison.png', dpi=200) print("Done.") print() print(' > Plots are saved in : ' + figdir + '/Figures/') print("********************************************")
def GLODAPv2_comparison(figdir="."): print("\n********************************************") print("Generating GLODAPv2 Comparison Plots") print("********************************************") # if the data file is missing, get it. if not os.path.exists("./GLODAPv2_pH_DIC_ALK_subset.csv"): print("Getting GLODAPv2 Data...") from get_GLODAP_data import get_GLODAP get_GLODAP() # Load data print("Importing GLODAPv2 Data...") gd = pd.read_csv("./GLODAPv2_pH_DIC_ALK_subset.csv") gd.dropna( subset=[ "phtsinsitutp", "temperature", "salinity", "tco2", "talk", "pressure", "phosphate", "silicate", ], inplace=True, ) gd.pressure /= 10 # convert pressure to bar # exclude weird cruise 270 data gd = gd.loc[gd.cruise != 270] # Do the work... print("Calculating pH from DIC and TA...") cpH = cb.Csys( TA=gd.talk, DIC=gd.tco2, T=gd.temperature, S=gd.salinity, P=gd.pressure, TP=gd.phosphate, TSi=gd.silicate, BT=415.7, ) print(" Making plots...") fig, axs = cplot(gd.phtsinsitutp, cpH.pH, "pH", "Depth", gd.depth) fig.savefig(figdir + "/Figures/pH_comparison.png", dpi=200) print("Calculating TA from pH and DIC...") cTA = cb.Csys( pH=gd.phtsinsitutp, DIC=gd.tco2, T=gd.temperature, S=gd.salinity, P=gd.pressure, TP=gd.phosphate, TSi=gd.silicate, BT=415.7, ) print(" Making plots...") fig, ax = cplot(gd.talk, cTA.TA, "Alk", "Depth", gd.depth) fig.savefig("Figures/TA_comparison.png", dpi=200) print("Calculating DIC from pH and TA...") cDIC = cb.Csys( pH=gd.phtsinsitutp, TA=gd.talk, T=gd.temperature, S=gd.salinity, P=gd.pressure, TP=gd.phosphate, TSi=gd.silicate, BT=415.7, ) print(" Making plots...") fig, ax = cplot(gd.tco2, cDIC.DIC, "DIC", "Depth", gd.depth) fig.savefig("Figures/DIC_comparison.png", dpi=200) print("Done.") print() print(" > Plots are saved in : " + figdir + "/Figures/") print("********************************************")
def calc_pitzer_Csys(d, database='./mg_funks/db_phreeqc/pitzer.dat', phreeq_path='/usr/local/lib/libiphreeqc.so'): # define standard seawater composition (mol/kg SW) # ================================================ sw = { 'pH': 8.2, 'Temp': 25, 'units': 'mol/kgw', 'density': 1.026, 'Ca': 10.28e-3, 'Cl': 0.54586, 'K': 10.21e-3, 'Mg': 52.82e-3, 'Na': 0.46906, 'S(6)': 0.02824, 'B': 416e-6, 'C': 2.3e-3, 'Br': 0.84e-3, 'F': 0.7e-4 } # calculate ambient Ks at measurement temperatures # ===================================================== ks = {} TempC = d.loc[:, ('Measured', 'pH_Temp')] TempK = TempC + 273.15 Sal = d.loc[:, ('Measured', 'Salinity')] par = cb.MyAMI_V2.start_params fns = cb.MyAMI_V2.fn_dict for k in ['K0', 'K1', 'K2', 'KB', 'KW', 'KspC', 'KspA', 'KSO4']: ks[k] = fns[k]((TempK, Sal), *par[k]) # calculate other Ks ks.update(cb.non_MyAMI_constants.calc_KF(TempC, Sal)) ks.update(cb.non_MyAMI_constants.calc_KPs(TempC, Sal)) ks.update(cb.non_MyAMI_constants.calc_KSi(TempC, Sal)) # calculate correction factors at 25C # =================================== fKs = {} isw = sw.copy() salsc = ['Cl', 'K', 'Na', 'S(6)', 'Br', 'F'] for i, v in tqdm(d.iterrows(), total=d.shape[0], desc='Calculating 25C Corrections'): v = v.Measured isw.update({ 'Mg': v.loc['[Mg]sw'] * 1e-3, 'Ca': v.loc['[Ca]sw'] * 1e-3, 'Temp': v.loc['pH_Temp'], 'B': v.loc['B umol/kg'] * 1e-6 }) sal_f = v.Salinity / 35. isw.update({k: sw[k] * sal_f for k in salsc}) fks = calc_pitzer_fKs(sw, isw, database=database, phreeq_path=phreeq_path) for k, f in fks.items(): if k not in fKs: fKs[k] = [] fKs[k].append(f) # apply correction factors to measurement temperature Ks # ================================== cKs = ks.copy() for k, f in fKs.items(): cKs[k] = ks[k] * f # convert all pH scales to Total # ============================== pHs = cb.helpers.calc_pH_scales(pHtot=None, pHfree=None, pHsws=None, pHNBS=d.loc[:, ('Measured', 'pHNBS')], TS=cb.calc_TS(Sal), TF=cb.calc_TF(Sal), TempK=TempK, Sal=Sal, Ks=cb.Bunch(cKs)) d.loc[:, ('pitzer_25C', 'pHTOTAL')] = d.loc[:, ('Measured', 'pHTOTAL')] ind = d.loc[:, ('Measured', 'pHTOTAL')].isnull() d.loc[ind, ('pitzer_25C', 'pHTOTAL')] = pHs['pHtot'][ind] # Calculate DIC/Alk at MEASURED conditions # ============================================== # calculate carbon system using measured temp Ks, pH and either DIC or Alk carb = cb.Csys(d.loc[:, ('pitzer_25C', 'pHTOTAL')], TA=d.loc[:, ('Measured', 'Alk')], BT=d.loc[:, ('Measured', 'B umol/kg')], Ks=cKs) d.loc[:, ('pitzer_25C', 'DIC')] = carb.DIC carb = cb.Csys(d.loc[:, ('pitzer_25C', 'pHTOTAL')], DIC=d.loc[:, ('Measured', 'DIC')], BT=d.loc[:, ('Measured', 'B umol/kg')], Ks=cKs) d.loc[:, ('pitzer_25C', 'Alk')] = carb.TA # whichever of DIC or Alk wasn't calculated, transfer the # measured value to the pitzer_25C column for in-situ condition calculation dicnull = d.loc[:, ('pitzer_25C', 'DIC')].isnull() d.loc[dicnull, ('pitzer_25C', 'DIC')] = d.loc[dicnull, ('Measured', 'DIC')] alknull = d.loc[:, ('pitzer_25C', 'Alk')].isnull() d.loc[alknull, ('pitzer_25C', 'Alk')] = d.loc[alknull, ('Measured', 'Alk')] # calculate empirical Ks for ambient Mg and Ca, and experiment Sal and Temp # ========================================================================= eKs = cb.calc_Ks(d.loc[:, ('Measured', 'Temp')], d.loc[:, ('Measured', 'Salinity')], 0, sw['Mg'], sw['Ca'], cb.calc_TS(d.loc[:, ('Measured', 'Salinity')]), cb.calc_TF(d.loc[:, ('Measured', 'Salinity')])) # calculate correction factors at experimental temperature # ======================================================== fKs = {} isw = sw.copy() salsc = ['Cl', 'K', 'Na', 'S(6)', 'Br', 'F'] for i, v in tqdm(d.iterrows(), total=d.shape[0], desc='Calculating Experimental T Corrections'): v = v.Measured isw.update({ 'Mg': v.loc['[Mg]sw'] * 1e-3, 'Ca': v.loc['[Ca]sw'] * 1e-3, 'Temp': v.Temp, 'B': v.loc['B umol/kg'] * 1e-6 }) sal_f = v.Salinity / 35. isw.update({k: sw[k] * sal_f for k in salsc}) fks = calc_pitzer_fKs(sw, isw, database=database, phreeq_path=phreeq_path) for k, f in fks.items(): if k not in fKs: fKs[k] = [] fKs[k].append(f) # apply correction factors for k, f in fKs.items(): eKs[k] = ks[k] * f # calculate carbon system at experimental conditions using pitzer-calculated DIC/Alk pairs carb = cb.Csys(DIC=d.loc[:, ('pitzer_25C', 'DIC')], TA=d.loc[:, ('pitzer_25C', 'Alk')], BT=d.loc[:, ('Measured', 'B umol/kg')], Ks=eKs) # store outputs! for c in ['DIC', 'TA', 'CO3', 'HCO3', 'CO2', 'pHtot']: d.loc[:, ('pitzer', c)] = carb[c] return d
def calc_MyAMI_Csys(d): out_cols = ['DIC', 'TA', 'CO3', 'HCO3', 'CO2', 'pHtot'] # for pHNBS and Alk ind = ~d.loc[:, ('Measured', 'pHNBS')].isnull() & ~d.loc[:, ('Measured', 'Alk')].isnull() if any(ind): cs = cb.Csys(pHNBS=d.loc[ind, ('Measured', 'pHNBS')], TA=d.loc[ind, ('Measured', 'Alk')], T_in=d.loc[ind, ('Measured', 'pH_Temp')], T_out=d.loc[ind, ('Measured', 'Temp')], S_in=d.loc[ind, ('Measured', 'Salinity')], Mg=d.loc[ind, ('Measured', '[Mg]sw')] / 1e3, Ca=d.loc[ind, ('Measured', '[Ca]sw')] / 1e3, BT=d.loc[ind, ('Measured', 'B umol/kg')]) for c in out_cols: d.loc[ind, ('MyAMI', c)] = cs[c] d.loc[ind, ('MyAMI', 'KspC')] = cs['Ks']['KspC'] # for pHNBS and DIC ind = ~d.loc[:, ('Measured', 'pHNBS')].isnull() & ~d.loc[:, ('Measured', 'DIC')].isnull() if any(ind): cs = cb.Csys(pHNBS=d.loc[ind, ('Measured', 'pHNBS')], DIC=d.loc[ind, ('Measured', 'DIC')], T_in=d.loc[ind, ('Measured', 'pH_Temp')], T_out=d.loc[ind, ('Measured', 'Temp')], S_in=d.loc[ind, ('Measured', 'Salinity')], Mg=d.loc[ind, ('Measured', '[Mg]sw')] / 1e3, Ca=d.loc[ind, ('Measured', '[Ca]sw')] / 1e3, BT=d.loc[ind, ('Measured', 'B umol/kg')]) for c in out_cols: d.loc[ind, ('MyAMI', c)] = cs[c] d.loc[ind, ('MyAMI', 'KspC')] = cs['Ks']['KspC'] # for pHTOTAL and Alk ind = ~d.loc[:, ('Measured', 'pHTOTAL')].isnull() & ~d.loc[:, ('Measured', 'Alk')].isnull() if any(ind): cs = cb.Csys(pHtot=d.loc[ind, ('Measured', 'pHTOTAL')], TA=d.loc[ind, ('Measured', 'Alk')], T_in=d.loc[ind, ('Measured', 'pH_Temp')], T_out=d.loc[ind, ('Measured', 'Temp')], S_in=d.loc[ind, ('Measured', 'Salinity')], Mg=d.loc[ind, ('Measured', '[Mg]sw')] / 1e3, Ca=d.loc[ind, ('Measured', '[Ca]sw')] / 1e3, BT=d.loc[ind, ('Measured', 'B umol/kg')]) for c in out_cols: d.loc[ind, ('MyAMI', c)] = cs[c] d.loc[ind, ('MyAMI', 'KspC')] = cs['Ks']['KspC'] # for pHTOTAL and DIC ind = ~d.loc[:, ('Measured', 'pHTOTAL')].isnull() & ~d.loc[:, ('Measured', 'DIC')].isnull() if any(ind): cs = cb.Csys(pHtot=d.loc[ind, ('Measured', 'pHTOTAL')], DIC=d.loc[ind, ('Measured', 'DIC')], T_in=d.loc[ind, ('Measured', 'pH_Temp')], T_out=d.loc[ind, ('Measured', 'Temp')], S_in=d.loc[ind, ('Measured', 'Salinity')], Mg=d.loc[ind, ('Measured', '[Mg]sw')] / 1e3, Ca=d.loc[ind, ('Measured', '[Ca]sw')] / 1e3, BT=d.loc[ind, ('Measured', 'B umol/kg')]) for c in out_cols: d.loc[ind, ('MyAMI', c)] = cs[c] d.loc[ind, ('MyAMI', 'KspC')] = cs['Ks']['KspC'] return d