import numpy as np
import matplotlib.pyplot as plt
from functools import partial
import inspect
import warnings as w
import numbers
import pandas as pd
from pathlib import Path
from Thermobar.core import *
## This specifies the default order for each dataframe type used in calculations
df_ideal_liq = pd.DataFrame(columns=['SiO2_Liq', 'TiO2_Liq', 'Al2O3_Liq',
'FeOt_Liq', 'MnO_Liq', 'MgO_Liq', 'CaO_Liq', 'Na2O_Liq', 'K2O_Liq',
'Cr2O3_Liq', 'P2O5_Liq', 'H2O_Liq', 'Fe3Fet_Liq', 'NiO_Liq', 'CoO_Liq',
'CO2_Liq'])
df_ideal_liq = pd.DataFrame(columns=['SiO2_Liq', 'TiO2_Liq', 'Al2O3_Liq',
'FeOt_Liq', 'MnO_Liq', 'MgO_Liq', 'CaO_Liq', 'Na2O_Liq', 'K2O_Liq',
'Cr2O3_Liq', 'P2O5_Liq', 'H2O_Liq', 'Fe3Fet_Liq', 'NiO_Liq', 'CoO_Liq',
'CO2_Liq'])
df_ideal_oxide = pd.DataFrame(columns=['SiO2', 'TiO2', 'Al2O3',
'FeOt', 'MnO', 'MgO', 'CaO', 'Na2O', 'K2O',
'Cr2O3', 'P2O5'])
df_ideal_cpx = pd.DataFrame(columns=['SiO2_Cpx', 'TiO2_Cpx', 'Al2O3_Cpx',
'FeOt_Cpx','MnO_Cpx', 'MgO_Cpx', 'CaO_Cpx', 'Na2O_Cpx', 'K2O_Cpx',
'Cr2O3_Cpx'])
df_ideal_ol = pd.DataFrame(columns=['SiO2_Ol', 'TiO2_Ol', 'Al2O3_Ol',
'FeOt_Ol', 'MnO_Ol', 'MgO_Ol', 'CaO_Ol', 'Na2O_Ol', 'K2O_Ol', 'Cr2O3_Ol',
'NiO_Ol'])
df_ideal_gt = pd.DataFrame(columns=['SiO2_Gt', 'TiO2_Gt', 'Al2O3_Gt',
'Cr2O3_Gt', 'FeOt_Gt', 'MnO_Gt', 'MgO_Gt', 'CaO_Gt', 'Na2O_Gt', 'K2O_Gt',
'Ni_Gt', 'Ti_Gt', 'Zr_Gt', 'Zn_Gt', 'Ga_Gt', 'Sr_Gt', 'Y_Gt'])
df_ideal_sp = pd.DataFrame(columns=['SiO2_Sp', 'TiO2_Sp', 'Al2O3_Sp',
'FeOt_Sp', 'MnO_Sp', 'MgO_Sp', 'CaO_Sp', 'Na2O_Sp', 'K2O_Sp', 'Cr2O3_Sp',
'NiO_Sp'])
df_ideal_opx = pd.DataFrame(columns=['SiO2_Opx', 'TiO2_Opx', 'Al2O3_Opx',
'FeOt_Opx', 'MnO_Opx', 'MgO_Opx', 'CaO_Opx', 'Na2O_Opx', 'K2O_Opx',
'Cr2O3_Opx'])
df_ideal_plag = pd.DataFrame(columns=['SiO2_Plag', 'TiO2_Plag', 'Al2O3_Plag',
'FeOt_Plag', 'MnO_Plag', 'MgO_Plag', 'CaO_Plag', 'Na2O_Plag', 'K2O_Plag',
'Cr2O3_Plag'])
df_ideal_kspar = pd.DataFrame(columns=['SiO2_Kspar', 'TiO2_Kspar',
'Al2O3_Kspar', 'FeOt_Kspar','MnO_Kspar', 'MgO_Kspar', 'CaO_Kspar',
'Na2O_Kspar', 'K2O_Kspar', 'Cr2O3_Kspar'])
df_ideal_amp = pd.DataFrame(columns=['SiO2_Amp', 'TiO2_Amp', 'Al2O3_Amp',
'FeOt_Amp', 'MnO_Amp', 'MgO_Amp', 'CaO_Amp', 'Na2O_Amp', 'K2O_Amp',
'Cr2O3_Amp', 'F_Amp', 'Cl_Amp'])
# Same, but order for errors
df_ideal_liq_Err = pd.DataFrame(columns=['SiO2_Liq_Err', 'TiO2_Liq_Err',
'Al2O3_Liq_Err', 'FeOt_Liq_Err', 'MnO_Liq_Err', 'MgO_Liq_Err', 'CaO_Liq_Err',
'Na2O_Liq_Err', 'K2O_Liq_Err', 'Cr2O3_Liq_Err', 'P2O5_Liq_Err', 'H2O_Liq_Err',
'Fe3Fet_Liq_Err', 'NiO_Liq_Err', 'CoO_Liq_Err', 'CO2_Liq_Err'])
df_ideal_cpx_Err = pd.DataFrame(columns=['SiO2_Cpx_Err', 'TiO2_Cpx_Err',
'Al2O3_Cpx_Err', 'FeOt_Cpx_Err', 'MnO_Cpx_Err', 'MgO_Cpx_Err', 'CaO_Cpx_Err',
'Na2O_Cpx_Err', 'K2O_Cpx_Err', 'Cr2O3_Cpx_Err', 'P_kbar_Err', 'T_K_Err'])
df_ideal_ol_Err = pd.DataFrame(columns=['SiO2_Ol_Err', 'TiO2_Ol_Err',
'Al2O3_Ol_Err', 'FeOt_Ol_Err', 'MnO_Ol_Err', 'MgO_Ol_Err', 'CaO_Ol_Err',
'Na2O_Ol_Err', 'K2O_Ol_Err', 'Cr2O3_Ol_Err', 'NiO_Ol_Err', 'P_kbar_Err',
'T_K_Err'])
df_ideal_sp_Err = pd.DataFrame(columns=['SiO2_Sp_Err', 'TiO2_Sp_Err',
'Al2O3_Sp_Err', 'FeOt_Sp_Err', 'MnO_Sp_Err', 'MgO_Sp_Err', 'CaO_Sp_Err',
'Na2O_Sp_Err', 'K2O_Sp_Err', 'Cr2O3_Sp_Err', 'NiO_Sp_Err', 'P_kbar_Err',
'T_K_Err'])
df_ideal_opx_Err = pd.DataFrame(columns=['SiO2_Opx_Err', 'TiO2_Opx_Err',
'Al2O3_Opx_Err', 'FeOt_Opx_Err', 'MnO_Opx_Err', 'MgO_Opx_Err', 'CaO_Opx_Err',
'Na2O_Opx_Err', 'K2O_Opx_Err', 'Cr2O3_Opx_Err', 'P_kbar_Err', 'T_K_Err'])
df_ideal_plag_Err = pd.DataFrame(columns=['SiO2_Plag_Err', 'TiO2_Plag_Err',
'Al2O3_Plag_Err', 'FeOt_Plag_Err', 'MnO_Plag_Err', 'MgO_Plag_Err',
'CaO_Plag_Err', 'Na2O_Plag_Err', 'K2O_Plag_Err', 'Cr2O3_Plag_Err',
'P_kbar_Err', 'T_K_Err'])
df_ideal_kspar_Err = pd.DataFrame(columns=['SiO2_Kspar_Err', 'TiO2_Kspar_Err',
'Al2O3_Kspar_Err', 'FeOt_Kspar_Err', 'MnO_Kspar_Err', 'MgO_Kspar_Err',
'CaO_Kspar_Err', 'Na2O_Kspar_Err', 'K2O_Kspar_Err', 'Cr2O3_Kspar_Err',
'P_kbar_Err', 'T_K_Err'])
df_ideal_amp_Err = pd.DataFrame(columns=['SiO2_Amp_Err', 'TiO2_Amp_Err',
'Al2O3_Amp_Err', 'FeOt_Amp_Err', 'MnO_Amp_Err', 'MgO_Amp_Err',
'CaO_Amp_Err', 'Na2O_Amp_Err', 'K2O_Amp_Err', 'Cr2O3_Amp_Err',
'F_Amp_Err', 'Cl_Amp_Err', 'P_kbar_Err', 'T_K_Err'])
# Used to store variables.
df_ideal_exp = pd.DataFrame(columns=['P_kbar', 'T_K'])
df_ideal_exp_Err = pd.DataFrame(columns=['P_kbar_Err', 'T_K_Err'])
[docs]
def import_lepr_file(file_name):
"""
Reads in data from the outputs from the Caltech LEPR site (where oxides are followed by the word "value")
Splits the data into phases, as for the read_excel function.
Parameters
-------
file_name: str
Excel file_name from LEPR
Returns
-------
pandas DataFrames stored in a dictionary. E.g., Access Cpxs using output.Cpxs
my_input = pandas dataframe of the entire spreadsheet
mylabels = sample labels
Experimental_PT = User-entered PT
Fluid=pandas dataframe of fluid compositions
Liqs=pandas dataframe of liquid oxides
Ols=pandas dataframe of olivine oxides
Cpxs=pandas dataframe of cpx oxides
Plags=pandas dataframe of plagioclase oxides
Kspars=pandas dataframe of kspar oxides
Opxs=pandas dataframe of opx oxides
Amps=pandas dataframe of amphibole oxides
Sps=pandas dataframe of spinel oxides
"""
my_input = pd.ExcelFile(file_name)
sheet_names = my_input.sheet_names
if "Experiment" in sheet_names:
my_input_Exp = pd.read_excel(file_name, sheet_name="Experiment")
myExp = pd.DataFrame(data={'Citation': my_input_Exp['Citation'], 'Experiment': my_input_Exp['Experiment'],
'T_K': my_input_Exp['T (C)']+273.15, 'P_kbar': 10*my_input_Exp['P (GPa)'],
'Duration': my_input_Exp['Duration (hours)'],
'Laboratory': my_input_Exp['Laboratory']
}
)
if "Experiment" not in sheet_names:
myExp = pd.DataFrame()
if "Fluid" in sheet_names:
my_input_Fluid = pd.read_excel(file_name, sheet_name="Fluid").fillna(0)
myFluid = pd.DataFrame(data={'Experiment': my_input_Fluid['Experiment'],
'H2O_Val': my_input_Fluid['H2O value'],
'CO2_Val': my_input_Fluid['CO2 value']})
myFluid_Exp = pd.merge(myFluid, myExp, on="Experiment")
if "Fluid" not in sheet_names:
myFluid = pd.DataFrame()
myFluid_Exp = pd.DataFrame()
if "Plagioclase" in sheet_names:
my_input_Plag = pd.read_excel(
file_name, sheet_name="Plagioclase").fillna(0)
my_input_Plag['FeOT value'] = my_input_Plag['FeO value'] + \
0.89998*my_input_Plag['Fe2O3 value']
myPlag = pd.DataFrame(data={'Experiment': my_input_Plag['Experiment'],
'SiO2_Plag': my_input_Plag['SiO2 value'],
'TiO2_Plag': my_input_Plag['TiO2 value'],
'Al2O3_Plag': my_input_Plag['Al2O3 value'],
'FeOt_Plag': my_input_Plag['FeOT value'],
'MnO_Plag': my_input_Plag['MnO value'],
'MgO_Plag': my_input_Plag['MgO value'],
'CaO_Plag': my_input_Plag['CaO value'],
'Na2O_Plag': my_input_Plag['Na2O value'],
'K2O_Plag': my_input_Plag['K2O value'],
'Cr2O3_Plag': my_input_Plag['Cr2O3 value'],
'P2O5_Plag': my_input_Plag['P2O5 value']})
myPlag_Exp = pd.merge(myPlag, myExp, on="Experiment")
if "Plagioclase" not in sheet_names:
myPlag = pd.DataFrame()
myPlag_Exp = pd.DataFrame()
if "Clinopyroxene" in sheet_names:
my_input_Cpx = pd.read_excel(
file_name, sheet_name="Clinopyroxene").fillna(0)
my_input_Cpx['FeOT value'] = my_input_Cpx['FeO value'] + \
0.89998*my_input_Cpx['Fe2O3 value']
myCpx = pd.DataFrame(data={'Experiment': my_input_Cpx['Experiment'],
'SiO2_Cpx': my_input_Cpx['SiO2 value'],
'TiO2_Cpx': my_input_Cpx['TiO2 value'],
'TiO2_Cpx_Err': my_input_Cpx['TiO2 error'],
'Al2O3_Cpx': my_input_Cpx['Al2O3 value'],
'Al2O3_Cpx_Err': my_input_Cpx['Al2O3 error'],
'FeOt_Cpx': my_input_Cpx['FeOT value'],
'MnO_Cpx': my_input_Cpx['MnO value'],
'MgO_Cpx': my_input_Cpx['MgO value'],
'CaO_Cpx': my_input_Cpx['CaO value'],
'Na2O_Cpx': my_input_Cpx['Na2O value'],
'Na2O_Cpx_Err': my_input_Cpx['Na2O error'],
'K2O_Cpx': my_input_Cpx['K2O value'],
'Cr2O3_Cpx': my_input_Cpx['Cr2O3 value'],
'P2O5_Cpx': my_input_Cpx['P2O5 value']})
if 'n' in my_input_Cpx.columns:
myCpx['N_meas_Cpx']=my_input_Cpx['n']
if 'Number of analyses' in my_input_Cpx.columns:
myCpx['N_meas_Cpx']=my_input_Cpx['Number of analyses']
myCpx_Exp = pd.merge(myCpx, myExp, on="Experiment")
if "Clinopyroxene" not in sheet_names:
myCpx = pd.DataFrame()
myCpx_Exp = pd.DataFrame()
if "Orthopyroxene" in sheet_names:
my_input_Opx = pd.read_excel(
file_name, sheet_name="Orthopyroxene").fillna(0)
my_input_Opx['FeOT value'] = my_input_Opx['FeO value'] + \
0.89998*my_input_Opx['Fe2O3 value']
myOpx = pd.DataFrame(data={'Experiment': my_input_Opx['Experiment'],
'SiO2_Opx': my_input_Opx['SiO2 value'],
'TiO2_Opx': my_input_Opx['TiO2 value'],
'Al2O3_Opx': my_input_Opx['Al2O3 value'],
'FeOt_Opx': my_input_Opx['FeOT value'],
'MnO_Opx': my_input_Opx['MnO value'],
'MgO_Opx': my_input_Opx['MgO value'],
'CaO_Opx': my_input_Opx['CaO value'],
'Na2O_Opx': my_input_Opx['Na2O value'],
'K2O_Opx': my_input_Opx['K2O value'],
'Cr2O3_Opx': my_input_Opx['Cr2O3 value'],
'P2O5_Opx': my_input_Opx['P2O5 value']})
myOpx_Exp = pd.merge(myOpx, myExp, on="Experiment")
if "Orthopyroxene" not in sheet_names:
myOpx = pd.DataFrame()
myOpx_Exp = pd.DataFrame()
if "Liquid" in sheet_names:
my_input_Liq = pd.read_excel(file_name, sheet_name="Liquid").fillna(0)
my_input_Liq['FeOT value'] = my_input_Liq['FeO value'] + \
0.89998*my_input_Liq['Fe2O3 value']
myLiq = pd.DataFrame(data={'Experiment': my_input_Liq['Experiment'],
'SiO2_Liq': my_input_Liq['SiO2 value'],
'TiO2_Liq': my_input_Liq['TiO2 value'],
'Al2O3_Liq': my_input_Liq['Al2O3 value'],
'FeOt_Liq': my_input_Liq['FeOT value'],
'MnO_Liq': my_input_Liq['MnO value'],
'MgO_Liq': my_input_Liq['MgO value'],
'CaO_Liq': my_input_Liq['CaO value'],
'Na2O_Liq': my_input_Liq['Na2O value'],
'K2O_Liq': my_input_Liq['K2O value'],
'Cr2O3_Liq': my_input_Liq['Cr2O3 value'],
'P2O5_Liq': my_input_Liq['P2O5 value'],
'H2O_Liq': my_input_Liq['H2O value'],
'Total_Liq': my_input_Liq['total value']})
if 'n' in my_input_Liq.columns:
myLiq['N_meas_Liq']=my_input_Liq['n']
myLiq_Exp = pd.merge(myLiq, myExp, on="Experiment")
if "Liquid" not in sheet_names:
myLiq = pd.DataFrame()
myLiq_Exp = pd.DataFrame()
if "Amphibole" in sheet_names:
my_input_Amp = pd.read_excel(
file_name, sheet_name="Amphibole").fillna(0)
my_input_Amp['FeOT value'] = my_input_Amp['FeO value'] + \
0.89998*my_input_Amp['Fe2O3 value']
myAmp = pd.DataFrame(data={'Experiment': my_input_Amp['Experiment'],
'SiO2_Amp': my_input_Amp['SiO2 value'],
'TiO2_Amp': my_input_Amp['TiO2 value'],
'Al2O3_Amp': my_input_Amp['Al2O3 value'],
'FeOt_Amp': my_input_Amp['FeOT value'],
'MnO_Amp': my_input_Amp['MnO value'],
'MgO_Amp': my_input_Amp['MgO value'],
'CaO_Amp': my_input_Amp['CaO value'],
'Na2O_Amp': my_input_Amp['Na2O value'],
'K2O_Amp': my_input_Amp['K2O value'],
'Cr2O3_Amp': my_input_Amp['Cr2O3 value'],
'P2O5_Amp': my_input_Amp['P2O5 value']})
myAmp_Exp = pd.merge(myAmp, myExp, on="Experiment")
if "Amphibole" not in sheet_names:
myAmp = pd.DataFrame()
myAmp_Exp = pd.DataFrame()
if "Olivine" in sheet_names:
my_input_Ol = pd.read_excel(file_name, sheet_name="Olivine").fillna(0)
my_input_Ol['FeOT value'] = my_input_Ol['FeO value'] + \
0.89998*my_input_Ol['Fe2O3 value']
myOl = pd.DataFrame(data={'Experiment': my_input_Ol['Experiment'],
'SiO2_Ol': my_input_Ol['SiO2 value'],
'TiO2_Ol': my_input_Ol['TiO2 value'],
'Al2O3_Ol': my_input_Ol['Al2O3 value'],
'FeOt_Ol': my_input_Ol['FeOT value'],
'MnO_Ol': my_input_Ol['MnO value'],
'MgO_Ol': my_input_Ol['MgO value'],
'CaO_Ol': my_input_Ol['CaO value'],
'Na2O_Ol': my_input_Ol['Na2O value'],
'K2O_Ol': my_input_Ol['K2O value'],
'Cr2O3_Ol': my_input_Ol['Cr2O3 value'],
'P2O5_Ol': my_input_Ol['P2O5 value']})
myOl_Exp = pd.merge(myOl, myExp, on="Experiment")
if "Olivine" not in sheet_names:
myOl = pd.DataFrame()
myOl_Exp = pd.DataFrame()
return {'Experimental_PT': myExp, 'Liquids': myLiq, 'Liqs_Exp': myLiq_Exp, 'Fluids': myFluid, 'Fluids_Exp': myFluid_Exp, 'Plags': myPlag, 'Plags_Exp': myPlag_Exp,
'Cpxs': myCpx, 'Cpxs_Exp': myCpx_Exp, 'Opxs': myOpx, 'Opxs_Exp': myOpx_Exp, 'Amps': myAmp, 'Amps_Exp': myAmp_Exp, 'Ols_Exp': myOl_Exp}
# Loading Excel, returns a dictionary
[docs]
def import_excel(file_name, sheet_name, path=None, sample_label=None, GEOROC=False, suffix=None, df=None):
'''
Import excel sheet of oxides in wt%, headings should be of the form SiO2_Liq (for the melt/liquid), SiO2_Ol (for olivine comps), SiO2_Cpx (for clinopyroxene compositions). Order doesn't matter
Parameters
-------
file_name: .xlsx, .csv, .xls file
Compositional data as an Excel spreadsheet (.xlsx, .xls) or a comma separated values (.csv) file with columns labelled SiO2_Liq, SiO2_Ol, SiO2_Cpx etc, and each row corresponding to an analysis.
file_name: str
specifies the file name (e.g., Python_OlLiq_Thermometers_Test.xlsx)
OR
enter a dataframe instead of an excel file.
Optional:
path: provide a pathlib path to where the file is stored
GEOROC: bool (defualt False) - reads in GEOROC files
suffix: default None, can be '_Liq' etc. Used to add a suffix onto all column headings.
Returns
-------
pandas DataFrames stored in a dictionary. E.g., Access Cpxs using output.Cpxs
my_input = pandas dataframe of the entire spreadsheet
mylabels = sample labels
Experimental_press_temp = User-entered PT
Liqs=pandas dataframe of liquid oxides
Ols=pandas dataframe of olivine oxides
Cpxs=pandas dataframe of cpx oxides
Plags=pandas dataframe of plagioclase oxides
Kspars=pandas dataframe of kspar oxides
Opxs=pandas dataframe of opx oxides
Amps=pandas dataframe of amphibole oxides
Sps=pandas dataframe of spinel oxides
'''
if df is None:
if path is not None:
file_path = Path(path) / file_name
else:
file_path = Path(file_name)
# Convert to string if needed
if isinstance(file_path, Path):
file_path = str(file_path)
# Check the file extension and read the file accordingly
if file_path.endswith('.csv'):
my_input = pd.read_csv(file_path)
elif file_path.endswith(('.xls', '.xlsx')):
if sheet_name is not None:
my_input = pd.read_excel(file_path, sheet_name=sheet_name)
else:
my_input = pd.read_excel(file_path)
else:
raise ValueError(f"Unsupported file extension: {Path(file_path).suffix}")
else:
my_input=df
if any(my_input.columns.str.startswith(' ')):
w.warn('your input file has some columns that start with spaces. This could cause you big problems if they are at the start of oxide names. Please ammend your file and reload.')
if suffix is not None:
if any(my_input.columns.str.contains(suffix)):
w.warn('We notice you have specified a suffix, but some of your columns already have this suffix. '
'e.g., If you already have _Liq in the file, you shouldnt specify suffix="_Liq" during the import')
my_input_c = my_input.copy()
if suffix is not None:
my_input_c=my_input_c.add_suffix(suffix)
if any(my_input.columns.str.contains("_cpx")):
w.warn("You've got a column heading with a lower case _cpx, this is okay if this column is for your"
" own use, but if its an input to Thermobar, it needs to be capitalized (_Cpx)" )
if any(my_input.columns.str.contains("_opx")):
w.warn("You've got a column heading with a lower case _opx, this is okay if this column is for your"
" own use, but if its an input to Thermobar, it needs to be capitalized (_Opx)" )
if any(my_input.columns.str.contains("_plag")):
w.warn("You've got a column heading with a lower case _plag, this is okay if this column is for your"
" own use, but if its an input to Thermobar, it needs to be capitalized (_Plag)" )
if any(my_input.columns.str.contains("_kspar")):
w.warn("You've got a column heading with a lower case _kspar, this is okay if this column is for your"
" own use, but if its an input to Thermobar, it needs to be capitalized (_Kspar)" )
if any(my_input.columns.str.contains("_sp")):
w.warn("You've got a column heading with a lower case _sp, this is okay if this column is for your"
" own use, but if its an input to Thermobar, it needs to be capitalized (_Sp)" )
if any(my_input.columns.str.contains("_ol")):
w.warn("You've got a column heading with a lower case _ol, this is okay if this column is for your"
" own use, but if its an input to Thermobar, it needs to be capitalized (_Ol)" )
if any(my_input.columns.str.contains("_amp")):
w.warn("You've got a column heading with a lower case _amp, this is okay if this campumn is for your"
" own use, but if its an input to Thermobar, it needs to be capitalized (_Amp)" )
if any(my_input.columns.str.contains("_liq")):
w.warn("You've got a column heading with a lower case _liq, this is okay if this column is for your"
" own use, but if its an input to Thermobar, it needs to be capitalized (_Liq)" )
if suffix is not None:
if any(my_input.columns.str.contains("FeO")) and (all(my_input.columns.str.contains("FeOt")==False)):
raise ValueError("No FeOt found. You've got a column heading with FeO. To avoid errors based on common EPMA outputs"
" thermobar only recognises columns with FeOt for all phases except liquid"
" where you can also enter a Fe3Fet_Liq heading used for equilibrium tests")
if any(my_input.columns.str.contains("FeO_")) and (all(my_input.columns.str.contains("FeOt_")==False)):
if any(my_input.columns.str.contains("FeO_Liq")) and any(my_input.columns.str.contains("Fe2O3_Liq")):
my_input_c['FeOt_Liq']=my_input_c['FeO_Liq']+my_input_c['Fe2O3_Liq']*0.89998
else:
raise ValueError("No FeOt found. You've got a column heading with FeO. To avoid errors based on common EPMA outputs"
" thermobar only recognises columns with FeOt for all phases except liquid"
" where you can also enter a Fe3Fet_Liq heading used for equilibrium tests")
# if any(my_input.columns.str.contains("Fe2O3_")) and (all(my_input.columns.str.contains("FeOt_")==False)):
# raise ValueError("No FeOt column found. You've got a column heading with Fe2O3. To avoid errors based on common EPMA outputs"
# " thermobar only recognises columns with FeOt for all phases except liquid"
# " where you can also enter a Fe3Fet_Liq heading used for equilibrium tests")
if any(my_input.columns.str.contains("FeOT_")) and (all(my_input.columns.str.contains("FeOt_")==False)):
raise ValueError("No FeOt column found. You've got a column heading with FeOT. Change to a lower case t")
# myLabels=my_input.Sample_ID
duplicates = df_ideal_exp.columns[df_ideal_exp.columns.duplicated()]
# If duplicates are found, return them to the user
if not duplicates.empty:
print("Duplicate columns found:", duplicates)
return "Duplicate columns detected. Please handle them before reindexing."
# Proceed with reindexing if no duplicates are found
Experimental_press_temp1 = my_input.reindex(df_ideal_exp.columns, axis=1)
if GEOROC is True:
my_input_c.loc[np.isnan(my_input_c['FeOt_Liq']) is True, 'FeOt_Liq'] = my_input_c.loc[np.isnan(
my_input_c['FeOt_Liq']) is True, 'FeO_Liq'] + my_input_c.loc[np.isnan(my_input_c['FeOt_Liq']) is True, 'Fe2O3_Liq'] * 0.8999998
myOxides1 = my_input_c.reindex(df_ideal_oxide.columns, axis=1).fillna(0)
myOxides1 = myOxides1.apply(pd.to_numeric, errors='coerce').fillna(0)
myOxides1[myOxides1 < 0] = 0
myLiquids1 = my_input_c.reindex(df_ideal_liq.columns, axis=1).fillna(0)
myLiquids1 = myLiquids1.apply(pd.to_numeric, errors='coerce').fillna(0)
myLiquids1[myLiquids1 < 0] = 0
myCPXs1 = my_input_c.reindex(df_ideal_cpx.columns, axis=1).fillna(0)
myCPXs1 = myCPXs1.apply(pd.to_numeric, errors='coerce').fillna(0)
myCPXs1[myCPXs1 < 0] = 0
myOls1 = my_input_c.reindex(df_ideal_ol.columns, axis=1).fillna(0)
myOls1 = myOls1.apply(pd.to_numeric, errors='coerce').fillna(0)
myOls1[myOls1 < 0] = 0
myPlags1 = my_input_c.reindex(df_ideal_plag.columns, axis=1).fillna(0)
myPlags1 = myPlags1.apply(pd.to_numeric, errors='coerce').fillna(0)
myPlags1[myPlags1 < 0] = 0
myKspars1 = my_input_c.reindex(df_ideal_kspar.columns, axis=1).fillna(0)
myKspars1 = myKspars1.apply(pd.to_numeric, errors='coerce').fillna(0)
myKspars1[myKspars1 < 0] = 0
myOPXs1 = my_input_c.reindex(df_ideal_opx.columns, axis=1).fillna(0)
myOPXs1 = myOPXs1.apply(pd.to_numeric, errors='coerce').fillna(0)
myOPXs1[myOPXs1 < 0] = 0
mySps1 = my_input_c.reindex(df_ideal_sp.columns, axis=1).fillna(0)
mySps1 = mySps1.apply(pd.to_numeric, errors='coerce').fillna(0)
mySps1[mySps1 < 0] = 0
myAmphs1 = my_input_c.reindex(df_ideal_amp.columns, axis=1).fillna(0)
myAmphs1 = myAmphs1.apply(pd.to_numeric, errors='coerce').fillna(0)
myAmphs1[myAmphs1 < 0] = 0
myGts1 = my_input_c.reindex(df_ideal_gt.columns, axis=1).fillna(0)
myGts1 = myGts1.apply(pd.to_numeric, errors='coerce').fillna(0)
myGts1[myGts1 < 0] = 0
# Adding sample Names
if "Sample_ID_Cpx" in my_input_c:
myCPXs1['Sample_ID_Cpx'] = my_input_c['Sample_ID_Cpx']
else:
myCPXs1['Sample_ID_Cpx'] = my_input.index
if "Sample_ID_Opx" in my_input_c:
myOPXs1['Sample_ID_Opx'] = my_input_c['Sample_ID_Opx']
else:
myOPXs1['Sample_ID_Opx'] = my_input.index
if "Sample_ID_Liq" in my_input_c:
myLiquids1['Sample_ID_Liq'] = my_input_c['Sample_ID_Liq']
else:
myLiquids1['Sample_ID_Liq'] = my_input.index
if "Sample_ID_Plag" in my_input_c:
myPlags1['Sample_ID_Plag'] = my_input_c['Sample_ID_Plag']
else:
myPlags1['Sample_ID_Plag'] = my_input.index
if "Sample_ID_Amp" in my_input_c:
myAmphs1['Sample_ID_Amp'] = my_input_c['Sample_ID_Amp']
else:
myAmphs1['Sample_ID_Amp'] = my_input.index
if "Sample_ID_Gt" in my_input_c:
myGts1['Sample_ID_Gt'] = my_input_c['Sample_ID_Gt']
else:
myGts1['Sample_ID_Gt'] = my_input.index
if "Sample_ID_Ol" in my_input_c:
myOls1['Sample_ID_Ol'] = my_input_c['Sample_ID_Ol']
else:
myOls1['Sample_ID_Ol'] = my_input.index
if "Sample_ID_Kspar" in my_input_c:
myKspars1['Sample_ID_Kspar'] = my_input_c['Sample_ID_Kspar']
else:
myKspars1['Sample_ID_Kspar'] = my_input.index
if "Sample_ID_Sp" in my_input_c:
mySps1['Sample_ID_Sp'] = my_input_c['Sample_ID_Sp']
else:
mySps1['Sample_ID_Sp'] = my_input.index
# if "P_kbar" in my_input:
# myAmphs1['P_kbar'] = my_input['P_kbar']
# myPlags1['P_kbar'] = my_input['P_kbar']
# myOls1['P_kbar'] = my_input['P_kbar']
# myCPXs1['P_kbar'] = my_input['P_kbar']
# myOPXs1['P_kbar'] = my_input['P_kbar']
# mySps1['P_kbar'] = my_input['P_kbar']
# myLiquids1['P_kbar'] = my_input['P_kbar']
#
# if "T_K" in my_input:
# myAmphs1['T_K'] = my_input['T_K']
# myPlags1['T_K'] = my_input['T_K']
# myOls1['T_K'] = my_input['T_K']
# myCPXs1['T_K'] = my_input['T_K']
# myOPXs1['T_K'] = my_input['T_K']
# mySps1['T_K'] = my_input['T_K']
# myLiquids1['T_K'] = my_input['T_K']
return {'my_input': my_input, 'my_oxides': myOxides1, 'Experimental_press_temp': Experimental_press_temp1, 'Cpxs': myCPXs1, 'Opxs': myOPXs1, 'Liqs': myLiquids1, 'Gts': myGts1,
'Plags': myPlags1, 'Kspars': myKspars1, 'Amps': myAmphs1, 'Ols': myOls1, 'Sps': mySps1} # , 'y1': y1 ,'y2': y2}
[docs]
def import_excel_errors(file_name, sheet_name, GEOROC=False):
'''
Import excel sheet of oxide errors in wt%, headings should be of the form SiO2_Liq_Err (for the melt/liquid), SiO2_Ol_Err (for olivine comps), SiO2_Cpx_Err (for clinopyroxene compositions).
Parameters
-------
file_name: pExcel file
Excel file of oxides in wt% with columns labelled SiO2_Liq, SiO2_Ol, SiO2_Cpx etc.
file_name: str
specifies the file name (e.g., Python_OlLiq_Thermometers_Test.xlsx)
Returns
-------
pandas DataFrames stored in a dictionary. E.g., Access Cpxs using output.Cpxs
my_input_Err = pandas dataframe of the entire spreadsheet
Experimental_press_temp_Err = User-entered PT errors.
Liqs_Err=pandas dataframe of liquid oxide errors
Ols_Err=pandas dataframe of olivine oxide errors
Cpxs_Err=pandas dataframe of cpx oxide errors
Plags_Err=pandas dataframe of plagioclase oxide errors
Kspars_Err=pandas dataframe of kspar oxide errors
Opxs_Err=pandas dataframe of opx oxide errors
Amps_Err=pandas dataframe of amphibole oxide errors
Sps_Err=pandas dataframe of spinel oxide errors
'''
if 'csv' in file_name:
my_input = pd.read_csv(file_name)
#my_input[my_input < 0] = 0
elif 'xls' in file_name:
if sheet_name is not None:
my_input = pd.read_excel(file_name, sheet_name=sheet_name)
#my_input[my_input < 0] = 0
else:
my_input = pd.read_excel(file_name)
#my_input[my_input < 0] = 0
my_input_c = my_input.copy()
# myLabels=my_input.Sample_ID
my_input.fillna(0)
Experimental_press_temp1 = my_input.reindex(df_ideal_exp_Err.columns)
# This deals with the fact almost everyone will enter as FeO, but the code uses FeOt for these minerals.
# E.g., if users only enter FeO (not FeOt and Fe2O3), allocates a FeOt
# column. If enter FeO and Fe2O3, put a FeOt column
# Give warnings if no FeOt
cols=my_input.columns
if any(cols.str.startswith(" ")):
w.warn('We have found some spaces at the start of your column headings. Check these arent oxide headings, it wont read them')
if ("FeOt_Cpx" not in my_input) and (any(cols.str.contains('_Cpx'))):
w.warn('No FeOt_Cpx column, please check of you wanted any Fe in calcs')
if ("FeOt_Opx" not in my_input) and (any(cols.str.contains('_Opx'))):
w.warn('No FeOt_Opx column, please check of you wanted any Fe in calcs')
if ("FeOt_Amp" not in my_input) and (any(cols.str.contains('_Amp'))):
w.warn('No FeOt_Amp column, please check of you wanted any Fe in calcs')
if ("FeOt_Sp" not in my_input) and (any(cols.str.contains('_Sp'))):
w.warn('No FeOt_Sp column, please check of you wanted any Fe in calcs')
if ("FeOt_Ol" not in my_input) and (any(cols.str.contains('_Ol'))):
w.warn('No FeOt_Ol column, please check of you wanted any Fe in calcs')
if ("FeOt_Plag" not in my_input) and (any(cols.str.contains('_Plag'))):
w.warn('No FeOt_Plag column, please check of you wanted any Fe in calcs')
if ("FeOt_Kspar" not in my_input) and (any(cols.str.contains('_Kspar'))):
w.warn('No FeOt_Kspar column, please check of you wanted any Fe in calcs')
if "FeO_Cpx_Err" in my_input and "FeOt_Cpx" not in my_input and "Fe2O3_Cpx" not in my_input:
my_input_c['FeOt_Cpx_Err'] = my_input_c['FeO_Cpx_Err']
print('Only FeO_Cpx found in input, the code has allocated this to FeOt_Cpx')
if "FeO_Cpx_Err" in my_input and "Fe2O3_Cpx_Err" in my_input and 'FeOt_Cpx' not in my_input:
my_input_c['FeOt_Cpx_Err'] = my_input_c['FeO_Cpx_Err'] + \
0.8998 * my_input_c['Fe2O3_Cpx_Err']
if "FeO_Opx_Err" in my_input and "FeOt_Opx" not in my_input and "Fe2O3_Opx" not in my_input:
my_input_c['FeOt_Opx_Err'] = my_input_c['FeO_Opx_Err']
print('Only FeO_Opx found in input, the code has allocated this to FeOt_Opx')
if "FeO_Opx_Err" in my_input and "Fe2O3_Opx_Err" in my_input and 'FeOt_Opx' not in my_input:
my_input_c['FeOt_Opx_Err'] = my_input_c['FeO_Opx_Err'] + \
0.8998 * my_input_c['Fe2O3_Opx_Err']
if "FeO_Plag_Err" in my_input and "FeOt_Plag" not in my_input and "Fe2O3_Plag" not in my_input:
my_input_c['FeOt_Plag_Err'] = my_input_c['FeO_Plag_Err']
print('Only FeO_Plag found in input, the code has allocated this to FeOt_Plag')
if "FeO_Plag_Err" in my_input and "Fe2O3_Plag_Err" in my_input and 'FeOt_Plag' not in my_input:
my_input_c['FeOt_Plag_Err'] = my_input_c['FeO_Plag_Err'] + \
0.8998 * my_input_c['Fe2O3_Plag_Err']
if "FeO_Kspar_Err" in my_input and "FeOt_Kspar" not in my_input and "Fe2O3_Kspar" not in my_input:
my_input_c['FeOt_Kspar_Err'] = my_input_c['FeO_Kspar_Err']
print('Only FeO_Kspar found in input, the code has allocated this to FeOt_Kspar')
if "FeO_Kspar_Err" in my_input and "Fe2O3_Kspar_Err" in my_input and 'FeOt_Kspar' not in my_input:
my_input_c['FeOt_Kspar_Err'] = my_input_c['FeO_Kspar_Err'] + \
0.8998 * my_input_c['Fe2O3_Kspar_Err']
if "FeO_Amp_Err" in my_input and "FeOt_Amp" not in my_input and "Fe2O3_Amp" not in my_input:
my_input_c['FeOt_Amp_Err'] = my_input_c['FeO_Amp_Err']
print('Only FeO_Amp found in input, the code has allocated this to FeOt_Amp')
if "FeO_Amp_Err" in my_input and "Fe2O3_Amp_Err" in my_input and 'FeOt_Amp' not in my_input:
my_input_c['FeOt_Amp_Err'] = my_input_c['FeO_Amp_Err'] + \
0.8998 * my_input_c['Fe2O3_Amp_Err']
if "FeO_Sp_Err" in my_input and "FeOt_Sp" not in my_input and "Fe2O3_Sp" not in my_input:
my_input_c['FeOt_Sp_Err'] = my_input_c['FeO_Sp_Err']
print('Only FeO_Sp found in input, the code has allocated this to FeOt_Sp')
if "FeO_Sp_Err" in my_input and "Fe2O3_Sp_Err" in my_input and 'FeOt_Sp' not in my_input:
my_input_c['FeOt_Sp_Err'] = my_input_c['FeO_Sp_Err'] + \
0.8998 * my_input_c['Fe2O3_Sp_Err']
if "FeO_Ol_Err" in my_input and "FeOt_Ol" not in my_input and "Fe2O3_Ol" not in my_input:
my_input_c['FeOt_Ol_Err'] = my_input_c['FeO_Ol_Err']
print('Only FeO_Ol found in input, the code has allocated this to FeOt_Ol')
if "FeO_Ol_Err" in my_input and "Fe2O3_Ol_Err" in my_input and 'FeOt_Ol' not in my_input:
my_input_c['FeOt_Ol_Err'] = my_input_c['FeO_Ol_Err'] + \
0.8998 * my_input_c['Fe2O3_Ol_Err']
# For liquids, users have an option to specify Fe3Fet_Liq.
# 1st scenario, users only enter FeOt, code sets Fe3FeT to 0.
if "FeOt_Err_Liq_Err" in my_input and "Fe2O3_Err_Liq" not in my_input and "Fe3Fet_Err_Liq" not in my_input:
my_input_c['Fe3Fet_Liq_Err'] = 0
print('We have set Fe3Fet_Liq_Err to zero, as you only entered FeOt. You can input a Fe3Fet_Liq_Er column to specify this value instead')
# 2nd scenario, user only enteres FeO. Code sets FeO=FeOt, sets Fe3FeT to 0
if "FeO_Err_Liq_Err" in my_input and "Fe2O3_Err_Liq" not in my_input and 'FeOt_Liq' not in my_input and "Fe3Fet_Err_Liq" not in my_input:
my_input_c['FeOt_Liq_Err'] = my_input_c['FeO_Liq_Err']
my_input_c['Fe3Fet_Liq_Err'] = 0
print('Only FeO_Ol found in input, the code has allocated this to FeOt_Ol')
# 3rd scenario, user only enteres Fe2O3. code calculates FeOt
if "Fe2O3_Err_Liq_Err" in my_input and "FeO_Err_Liq" not in my_input and 'FeOt_Liq' not in my_input and "Fe3Fet_Err_Liq" not in my_input:
my_input_c['FeOt_Liq_Err'] = 0.8998 * my_input_c['Fe2O3_Liq_Err']
my_input_c['Fe3Fet_Liq_Err'] = 1
print('Only Fe2O3_Ol found in input, the code has allocated this to FeOt_Ol, and set Fe3Fet_Liq=1')
# 4th scenario, users enter only FeO and Fe2O3
if "Fe2O3_Err_Liq_Err" in my_input and "FeO_Err_Liq_Err" in my_input and 'FeOt_Liq' not in my_input and "Fe3Fet_Err_Liq" not in my_input:
my_input_c['FeOt_Liq_Err'] = my_input_c['FeO_Liq_Err'] + \
0.8998 * my_input_c['Fe2O3_Liq_Err']
my_input_c['Fe3Fet_Liq_Err'] = (0.89998 * my_input_c['Fe2O3_Liq_Err']) / (
(0.89998 * my_input_c['Fe2O3_Liq_Err'] + my_input_c['FeO_Liq_Err']))
if "Fe2O3_Err_Liq_Err" in my_input and "FeO_Err_Liq_Err" in my_input and 'FeOt_Liq' in my_input:
w.warn('You have entered FeO, Fe2O3, AND FeOt. The code uses FeO and Fe2O3 to recalculate FeOt and Fe3FeT ')
my_input_c['FeOt_Liq_Err'] = my_input_c['FeO_Liq_Err'] + \
0.8998 * my_input_c['Fe2O3_Liq_Err']
my_input_c['Fe3Fet_Liq_Err'] = (0.89998 * my_input_c['Fe2O3_Liq_Err']) / (
(0.89998 * my_input_c['Fe2O3_Liq_Err'] + my_input_c['FeO_Liq_Err']))
myLiquids1 = my_input.reindex(df_ideal_liq_Err.columns, axis=1).fillna(0)
myLiquids1 = myLiquids1.apply(pd.to_numeric, errors='coerce').fillna(0)
myCPXs1 = my_input_c.reindex(df_ideal_cpx_Err.columns, axis=1).fillna(0)
myCPXs1 = myCPXs1.apply(pd.to_numeric, errors='coerce').fillna(0)
myOls1 = my_input_c.reindex(df_ideal_ol_Err.columns, axis=1).fillna(0)
myOls1 = myOls1.apply(pd.to_numeric, errors='coerce').fillna(0)
myPlags1 = my_input_c.reindex(df_ideal_plag_Err.columns, axis=1).fillna(0)
myPlags1 = myPlags1.apply(pd.to_numeric, errors='coerce').fillna(0)
myKspars1 = my_input_c.reindex(
df_ideal_kspar_Err.columns, axis=1).fillna(0)
myKspars1 = myKspars1.apply(pd.to_numeric, errors='coerce').fillna(0)
myOPXs1 = my_input_c.reindex(df_ideal_opx_Err.columns, axis=1).fillna(0)
myOPXs1 = myOPXs1.apply(pd.to_numeric, errors='coerce').fillna(0)
mySps1 = my_input_c.reindex(df_ideal_sp_Err.columns, axis=1).fillna(0)
mySps1 = mySps1.apply(pd.to_numeric, errors='coerce').fillna(0)
myAmphs1 = my_input_c.reindex(df_ideal_amp_Err.columns, axis=1).fillna(0)
myAmphs1 = myAmphs1.apply(pd.to_numeric, errors='coerce').fillna(0)
# Adding sample Names
if "Sample_ID_Cpx_Err" in my_input:
myCPXs1['Sample_ID_Cpx_Err'] = my_input['Sample_ID_Cpx_Err']
else:
myCPXs1['Sample_ID_Cpx_Err'] = my_input.index
if "Sample_ID_Opx_Err" in my_input:
myOPXs1['Sample_ID_Opx_Err'] = my_input['Sample_ID_Opx_Err']
else:
myOPXs1['Sample_ID_Opx_Err'] = my_input.index
if "Sample_ID_Err_Liq_Err" in my_input:
myLiquids1['Sample_ID_Liq_Err'] = my_input['Sample_ID_Liq_Err']
else:
myLiquids1['Sample_ID_Liq_Err'] = my_input.index
if "Sample_ID_Plag_Err" in my_input:
myPlags1['Sample_ID_Plag_Err'] = my_input['Sample_ID_Plag_Err']
else:
myPlags1['Sample_ID_Plag_Err'] = my_input.index
if "Sample_ID_Amp_Err" in my_input:
myAmphs1['Sample_ID_Amp_Err'] = my_input['Sample_ID_Amp_Err']
else:
myAmphs1['Sample_ID_Amp_Err'] = my_input.index
if "P_kbar_Err" in my_input:
myAmphs1['P_kbar_Err'] = my_input['P_kbar_Err']
myPlags1['P_kbar_Err'] = my_input['P_kbar_Err']
myOls1['P_kbar_Err'] = my_input['P_kbar_Err']
myCPXs1['P_kbar_Err'] = my_input['P_kbar_Err']
myOPXs1['P_kbar_Err'] = my_input['P_kbar_Err']
mySps1['P_kbar_Err'] = my_input['P_kbar_Err']
myLiquids1['P_kbar_Err'] = my_input['P_kbar_Err']
if "T_K_Err" in my_input:
myAmphs1['T_K_Err'] = my_input['T_K_Err']
myPlags1['T_K_Err'] = my_input['T_K_Err']
myOls1['T_K_Err'] = my_input['T_K_Err']
myCPXs1['T_K_Err'] = my_input['T_K_Err']
myOPXs1['T_K_Err'] = my_input['T_K_Err']
mySps1['T_K_Err'] = my_input['T_K_Err']
myLiquids1['T_K_Err'] = my_input['T_K_Err']
return {'my_input_Err': my_input,
'Experimental_press_temp_Err': Experimental_press_temp1,
'Cpxs_Err': myCPXs1,
'Opxs_Err': myOPXs1,
'Liqs_Err': myLiquids1,
'Plags_Err': myPlags1,
'Kspars_Err': myKspars1,
'Amps_Err': myAmphs1,
'Ols_Err': myOls1,
'Sps_Err': mySps1}
# Gets liquid dataframe into a format that can be used in VESical. Have to
# have VESIcal installed for the final step, which we do in the script for
# simplicity
[docs]
def convert_to_vesical(liq_comps, T1, unit='Kelvin', Fe3Fet_Liq=None):
''' Takes liquid dataframe in the format used for PyMME, and strips the _Liq string so that it can be input into VESical. Also removes the Fe3FeTcolumn, and appends temperature (converted from Kevlin to celcius)
Parameters
-------
liq_comps: pandas.DataFrame
DataFrame of liquid compositions.
T1: Panda series, int, float
Temperature in Kelvin by default (e.g., from a thermometer of choice)
unit: Kelvin or Celcius
What unit supplied temperature is in
Returns
-------
DataFrame formatted so that it can be inputted into VESIcal.
'''
df = liq_comps.copy()
if unit=='Kelvin':
df['Temp'] = T1 - 273.15
else:
df['Temp'] = T1
if Fe3Fet_Liq is None:
Fe3Fet_Liq=df['Fe3Fet_Liq']
FeOt=df['FeOt_Liq']
df.drop(['Fe3Fet_Liq', 'FeOt_Liq'], inplace=True, axis=1)
df.columns = [str(col).replace('_Liq', '') for col in df.columns]
df['FeO']=FeOt*(1-Fe3Fet_Liq)
df['Fe2O3']=FeOt*Fe3Fet_Liq*1.111111
# This bit gets rid of Fe3Fet_Liq
return df
[docs]
def convert_from_vesical(data):
'''
Takes liquid compositions from VESIcal, and converts it into a panda dataframe that can be inputted into the thermobaromety functions in PyMME
Parameters
-------
data:
VESIcal data formatted, obtained from myfile.get_Data
Returns
-------
pandas dataframe formatted wtih column headings suitable for PyMME
'''
df = data.copy()
df = df.rename(columns={col: col + '_Liq' for col in df.columns if col in
['SiO2', 'TiO2', 'Al2O3', 'FeO', 'Fe2O3', 'MnO', 'MgO', 'CaO',
'K2O', 'Na2O', 'Cr2O3', 'P2O5', 'H2O', 'NiO']})
df['FeOt_Liq'] = df['FeO_Liq'] + 0.8999998 * df['Fe2O3_Liq']
df['Fe3Fet_Liq'] = df['Fe2O3_Liq'] * 1.111111 / \
(df['Fe2O3_Liq'] * 1.111111 + df['FeO_Liq'])
df['Sample_ID_Liq'] = df.index
return df