This page was generated from docs/Examples/Error_propagation/Cpx_only_contour_plot.ipynb. Interactive online version: Binder badge.

Python Notebook Download

Error propagation - Cpx-only

  • This notebook gives a worked example showing how to propagate uncertainty for Cpx-only thermometry for different amounts of EPMA-based error on Na\(_2\)O measurements.

  • We use the functionality provided by Pyrolite to contour the results from Monte Carlo simulations, as well as hexplot.

  • If you use the pyroplot.density command, please remember to cite Pyrolite! (Williams et al., (2020). pyrolite: Python for geochemistry. Journal of Open Source Software, 5(50), 2314, doi: 10.21105/joss.02314)

  • This builds on from the notebook showing how to consider error in a single phase (Liquid_Thermometry_error_prop.ipynb). We suggest you look at that first, as its simpler when you don’t have to worry about two separate phases

  • We consider an example Cpx composition from Gleeson et al. (2020) - https://doi.org/10.1093/petrology/egaa094

  • You can download the Excel spreadsheet here: https://github.com/PennyWieser/Thermobar/blob/main/docs/Examples/Error_propagation/Gleeson2020_Cpx_Comps.xlsx

You need to install Thermobar once on your machine, if you haven’t done this yet, uncomment the line below (remove the #)

[1]:
#!pip install Thermobar

You will also need to install pyrolite for this example, if you haven’t done so already, uncomment the line below

[2]:
#!pip install pyrolite
[3]:
# Import other python stuff
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import Thermobar as pt
import sympy as sym
pd.options.display.max_columns = None
import pyrolite

Importing data

  • Note, we haven’t bothered to add the “_Cpx” names after each oxide, so we simply use “suffix=”_Cpx” when we load the data

[4]:
out=pt.import_excel('Gleeson2020_Cpx_Comps.xlsx', sheet_name="Sheet1", suffix="_Cpx")
my_input=out['my_input']
myCpxs1=out['Cpxs']

Lets select 1 Cpx to run the calculations on

  • The [[ ]] keeps it as a dataframe

[5]:
myCpxs1.iloc[[0]]
[5]:
SiO2_Cpx TiO2_Cpx Al2O3_Cpx FeOt_Cpx MnO_Cpx MgO_Cpx CaO_Cpx Na2O_Cpx K2O_Cpx Cr2O3_Cpx Sample_ID_Cpx
0 51.3863 0.467 4.1961 3.8654 0.12 16.3137 21.3039 0.378 0.0007 1.0191 0

Work out errors

  • The Cameca software used to analyse these Cpxs returns the error as absolute elemental wt%, ignoring Oxygen, for each element (helpful!). These are loaded in as Na_Err, Si_Err….

  • This means that you need to do some steps to work out the analytical error on each Cpx. We show these steps below.

  • First, we decide it easiest to use the convert_oxide_percent_to_element_weight_percent function to convert measured Cpx compositions as oxides into wt% to compare to these errors. Without oxygen = True, does the calculations without oxygen. You can use this function for any phase, just specify what suffix your phase has.

[6]:
Cpx_conv=pt.convert_oxide_percent_to_element_weight_percent(df=myCpxs1, suffix='_Cpx', without_oxygen=True)
Cpx_conv.head()
[6]:
Si_wt_noO2 Mg_wt_noO2 Fe_wt_noO2 Ca_wt_noO2 Al_wt_noO2 Na_wt_noO2 K_wt_noO2 Mn_wt_noO2 Ti_wt_noO2 Cr_wt_noO2 P_wt_noO2 F_wt_noO2 H_wt_noO2 Cl_wt_noO2
0 43.155184 17.675115 5.398069 27.354400 3.989980 0.503819 0.001044 0.166972 0.502666 1.252750 0.0 0.0 0.0 0.0
1 42.432683 17.004438 5.468846 27.558497 4.967044 0.507369 0.000447 0.121440 0.625890 1.313346 0.0 0.0 0.0 0.0
2 42.399838 16.694183 5.608834 27.398388 5.209677 0.523472 0.022141 0.141541 0.681296 1.320631 0.0 0.0 0.0 0.0
3 42.649103 17.224819 5.638033 27.496627 4.631102 0.538772 0.004336 0.097927 0.632681 1.086601 0.0 0.0 0.0 0.0
4 41.057438 15.479289 7.324030 26.604851 6.874709 0.702197 0.025343 0.188588 1.005908 0.737648 0.0 0.0 0.0 0.0
  • Now we calculate the % error for each element. For example, for Na, we take the Cameca error (column Na_Err), and compare it to the concentration we just calculated in wt% for Na (column Na_wt_noO2 in the Cpx_conv dataframe)

[7]:
Perc_Err_Na=100*my_input['Na_Err']/Cpx_conv['Na_wt_noO2']
Perc_Err_Na.head()
[7]:
0    8.534819
1    8.553938
2    8.520041
3    8.315210
4    7.049307
dtype: float64
[8]:
# We now need to re-arrange these into a form that we can load into the function.
# We make a new dataframe of these errors
df_Cpx_Err=pd.DataFrame(data={'SiO2_Cpx_Err': 100*my_input['Si_Err']/Cpx_conv['Si_wt_noO2'],
                            'TiO2_Cpx_Err':100*my_input['Ti_Err']/Cpx_conv['Ti_wt_noO2'],
                             'Al2O3_Cpx_Err':100*my_input['Al_Err']/Cpx_conv['Al_wt_noO2'],
                             'FeOt_Cpx_Err':100*my_input['Fe_Err']/Cpx_conv['Fe_wt_noO2'],
                            'MnO_Cpx_Err':100*my_input['Mn_Err']/Cpx_conv['Mn_wt_noO2'],
                            'MgO_Cpx_Err':100*my_input['Mg_Err']/Cpx_conv['Mg_wt_noO2'],
                            'CaO_Cpx_Err':100*my_input['Ca_Err']/Cpx_conv['Ca_wt_noO2'],
                            'Na2O_Cpx_Err':100*my_input['Na_Err']/Cpx_conv['Na_wt_noO2'],
                            'Cr2O3_Cpx_Err':100*my_input['Cr_Err']/Cpx_conv['Cr_wt_noO2'],
                               'K2O_Cpx_Err': 100*my_input['K_Err']/Cpx_conv['K_wt_noO2']}, index=[0])

Lets select 1 Cpx, and its corresponding error as an example

  • using [[ ]] keeps it as a dataframe, we reset the index because sometimes this can cause python mayhem.

[9]:
Cpx_1=myCpxs1.iloc[[0]].reset_index(drop=True)
Cpx_1_Err=df_Cpx_Err.iloc[[0]].reset_index(drop=True)
Cpx_1_Err
[9]:
SiO2_Cpx_Err TiO2_Cpx_Err Al2O3_Cpx_Err FeOt_Cpx_Err MnO_Cpx_Err MgO_Cpx_Err CaO_Cpx_Err Na2O_Cpx_Err Cr2O3_Cpx_Err K2O_Cpx_Err
0 1.186416 2.148544 0.907273 3.056648 27.309951 1.129271 0.858363 8.534819 5.172622 1934.77739

Lets calculate the errors for this Cpx

  • You could do this for all Cpxs, rather than just this 1 sample, but it’ll take longer, so we do a cut down version here!

  • 20,000 iterations may seem like a lot, but it really helps with the contouring

[10]:
Calc_Cpx_dist=pt.add_noise_sample_1phase(phase_comp=Cpx_1, phase_err=Cpx_1_Err,
                                            phase_err_type="Perc", duplicates=20000, err_dist="normal")
All negative numbers replaced with zeros. If you wish to keep these, set positive=False

Lets calculate pressures and temperatures using a wide variety of equations for Cpx-only thermobarometry

  • This cell takes abit of time, its 20,000 calculations using a wide variety of P and T equations!

[11]:
Calc_PT=pt.calculate_cpx_only_press_all_eqs(cpx_comps=Calc_Cpx_dist)
Calc_PT.head()
[11]:
P_Wang21_eq1 T_Wang21_eq2 T_Jorgenson22 P_Jorgenson22 T_Petrelli20 T_Put_Teq32d_Peq32a T_Put_Teq32d_Peq32b P_Petrelli20 P_Put_Teq32d_Peq32a P_Put_Teq32d_Peq32b Jd_from 0=Na, 1=Al SiO2_Cpx TiO2_Cpx Al2O3_Cpx FeOt_Cpx MnO_Cpx MgO_Cpx CaO_Cpx Na2O_Cpx K2O_Cpx Cr2O3_Cpx Sample_ID_Cpx_Num Sample_ID_Cpx Si_Cpx_cat_6ox Mg_Cpx_cat_6ox Fet_Cpx_cat_6ox Ca_Cpx_cat_6ox Al_Cpx_cat_6ox Na_Cpx_cat_6ox K_Cpx_cat_6ox Mn_Cpx_cat_6ox Ti_Cpx_cat_6ox Cr_Cpx_cat_6ox oxy_renorm_factor Al_IV_cat_6ox Al_VI_cat_6ox En_Simple_MgFeCa_Cpx Fs_Simple_MgFeCa_Cpx Wo_Simple_MgFeCa_Cpx Cation_Sum_Cpx Ca_CaMgFe Lindley_Fe3_Cpx Lindley_Fe2_Cpx Lindley_Fe3_Cpx_prop CrCaTs a_cpx_En Mgno_Cpx Jd CaTs CaTi DiHd_1996 EnFs DiHd_2003 Di_Cpx FeIII_Wang21 FeII_Wang21 H2O_Liq T_Put_Teq32d_subsol_Peq32a T_Put_Teq32d_subsol_Peq32b P_Put_Teq32d_subsol_Peq32a P_Put_Teq32d_subsol_Peq32b
0 5.298283 1495.270546 1462.955933 6.266479 1433.501587 1499.862431 1490.210316 3.676231 6.457578 5.314680 0 51.434957 0.472438 4.174971 3.801613 0.130219 16.309334 21.147857 0.349307 0.000000 0.976087 0.0 0 1.896576 0.896513 0.117229 0.835510 0.181435 0.024973 0.000000 0.004067 0.013103 0.028455 0.0 0.103424 0.078012 0.484798 0.063393 0.451809 3.997862 0.451809 0.000000 0.117229 0.000000 0.014227 0.123134 0.884357 0.024973 0.053039 0.025192 0.743051 0.135346 0.743051 0.654499 -0.004277 0.121506 0 1242.728053 1196.499937 5.135329 0.357257
1 5.653239 1501.279659 1450.841553 6.104247 1442.768066 1503.368823 1494.296353 3.903188 6.959813 5.885026 0 51.547228 0.470622 4.213829 3.918778 0.082694 16.210466 21.097138 0.386442 0.000000 1.035990 0.0 0 1.897759 0.889692 0.120654 0.832209 0.182839 0.027585 0.000000 0.002579 0.013033 0.030154 0.0 0.102241 0.080598 0.482858 0.065482 0.451660 3.996504 0.451660 0.000000 0.120654 0.000000 0.015077 0.123341 0.880578 0.027585 0.053014 0.024614 0.739505 0.135421 0.739505 0.649536 -0.006992 0.127646 0 1245.302199 1200.315002 5.417295 0.766908
2 5.264089 1484.098940 1442.657593 7.011894 1437.181274 1485.307199 1472.272972 4.864007 5.893007 4.339467 0 50.638955 0.485152 4.216327 3.795194 0.174312 16.213989 21.452416 0.466125 0.021847 1.013315 0.0 0 1.880076 0.897406 0.117837 0.853375 0.184494 0.033554 0.001035 0.005482 0.013549 0.029743 0.0 0.119924 0.064570 0.480251 0.063061 0.456688 4.016551 0.456688 0.032066 0.085770 0.272126 0.014872 0.098097 0.883929 0.033554 0.031017 0.044454 0.763034 0.126105 0.763034 0.670848 0.032066 0.085770 0 1203.071834 1145.408596 6.679745 0.449275
3 4.724478 1485.415208 1462.886108 6.668314 1445.388184 1490.610038 1479.008293 3.835582 5.745320 4.368585 0 51.018414 0.477835 4.234044 3.829236 0.133773 16.510645 21.339216 0.371491 0.001249 1.043586 0.0 0 1.882223 0.908064 0.118144 0.843520 0.184101 0.026573 0.000059 0.004180 0.013260 0.030439 0.0 0.117777 0.066324 0.485666 0.063188 0.451146 4.010563 0.451146 0.021068 0.097076 0.178322 0.015219 0.114190 0.884870 0.026573 0.039751 0.039013 0.749537 0.138336 0.749537 0.660555 0.021068 0.097076 0 1226.783508 1175.241288 5.337022 -0.068022
4 3.586955 1464.061123 1450.816528 5.917033 1425.601196 1470.142740 1459.676731 3.619591 4.266036 3.017315 0 49.889533 0.464504 4.194231 4.055550 0.172077 16.485519 21.457441 0.393813 0.000000 0.958231 0.0 0 1.864857 0.918644 0.126777 0.859384 0.184776 0.028541 0.000000 0.005448 0.013060 0.028318 0.0 0.135143 0.049633 0.482277 0.066557 0.451166 4.029806 0.451166 0.059612 0.067165 0.470212 0.014159 0.098534 0.878727 0.028541 0.021092 0.057025 0.767108 0.139157 0.767108 0.670586 0.059612 0.067165 0 1195.862431 1137.912057 5.905188 -0.356520

Lets plot these calculations using the Wang et al. (2021) thermometer and barometer

  • You can see that despite random input errors, P and T end up correlated in the resulting distribution

  • You can also see that pressure is controlled predominantly by the error on the Na2O component, with scatter around this trend

[12]:
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10,5))
ax1.plot(Calc_PT['P_Wang21_eq1'], Calc_PT['T_Wang21_eq2'], '.r' )
ax2.plot(Calc_PT['P_Wang21_eq1'], Calc_PT['Na2O_Cpx'], '.b' )
ax1.set_xlabel('Calc P (kbar)')
ax2.set_xlabel('Calc P (kbar)')
ax1.set_ylabel('Calc T (K)')
ax1.set_ylabel('Na$_2$O Cpx')

[12]:
Text(0, 0.5, 'Na$_2$O Cpx')
../../_images/Examples_Error_propagation_Cpx_only_contour_plot_22_1.png

A more robust way to show this

  • If you play around with duplicates = , you’ll see that the more points you ask for, the more spread in pressure space.

  • It is more robust to contour results

  • First, we show how to do this using hexbin (matplotlib)

  • We underlie the published error on the barometer, at the average calculated composition.

[13]:
fig, (ax1)  = plt.subplots(1, 1, figsize=(6,5))

ax1.hexbin(Calc_PT['P_Wang21_eq1'],
           Calc_PT['T_Wang21_eq2'],
            cmap=plt.cm.BuPu,
            linewidths=0.2, bins=10)
ax1.set_xlabel('Calc P (kbar)')
ax1.set_xlabel('Calc T (K)')


ax1.errorbar(np.mean(Calc_PT['P_Wang21_eq1']),
             np.mean(Calc_PT['T_Wang21_eq2']),
             xerr=1.52, yerr=35.2,
             fmt='.', ecolor='k', elinewidth=0.8, mfc='k', ms=1)
[13]:
<ErrorbarContainer object of 3 artists>
../../_images/Examples_Error_propagation_Cpx_only_contour_plot_24_1.png

But this is still hard to visualize!

  • We can add contours using pyrolite, so we can visualize where 67% of simulations lie, and where 95% of simulations lie

  • You will have to play around a bit with the number of bins, and the extent parameter.

  • We always plot PT first, then use that to work out the extent, which tells the code where to look for contours in. This only needs to be approximate.

  • This step can be slow, if you are using 4-8 Gb of Ram, you might want to reduce the number of duplicates when you make the samples.

  • Remember to cite Pyrolite if you use these contours!

[19]:

[20]:
from pyrolite.plot import pyroplot

fig, (ax1)  = plt.subplots(1, 1, figsize=(6,5))

# This parameter helps pyrolite converge on the contour positions faster,
# e.g. saying look for contours between 3.5 and 7 kbar
# and between 1470 and 1540 K. You'll need to change this for your particular system
extent1=(3.5, 7, 1470, 1540)
ax1.hexbin(Calc_PT['P_Wang21_eq1'],
           Calc_PT['T_Wang21_eq2'],
            cmap=plt.cm.BuPu,
            linewidths=0.2, bins=10)
ax1.set_xlabel('Calc P (kbar)')
ax1.set_xlabel('Calc T (K)')


Calc_PT.loc[:,
["P_Wang21_eq1", "T_Wang21_eq2"]].pyroplot.density(ax=ax1, contours=[0.67, 0.95], colors=['m', 'c'],
                                                   extent=extent1, cmap="viridis",
                                                   bins=30, label_contours=False)
# Adjust axes limits
ax1.set_xlim([3.5, 7.1])
ax1.set_ylim([1450,  1520])

ax1.errorbar(np.mean(Calc_PT['P_Wang21_eq1']),
             np.mean(Calc_PT['T_Wang21_eq2']),
             xerr=1.52, yerr=35.2,
             fmt='.', ecolor='k', elinewidth=0.8, mfc='k', ms=1)

ax1.set_xlabel('Calc P (kbar)')
ax1.set_ylabel('Calc T (K)')
[20]:
Text(0, 0.5, 'Calc T (K)')
../../_images/Examples_Error_propagation_Cpx_only_contour_plot_27_1.png

Lets work out what would happen if we doubled the analytical error on Na2O

  • Be patient, this takes a bit of time, its 20,000 calculations!

[21]:
# First, lets duplicate the error dataframe
df_Cpx_Err_2Na=df_Cpx_Err.copy()
# Lets set Na2O error to 2* what it was
df_Cpx_Err_2Na['Na2O_Cpx_Err']=2*df_Cpx_Err['Na2O_Cpx_Err']
# And lets take sample 0 again
Cpx_1_Err_2Na=df_Cpx_Err_2Na.iloc[[0]].reset_index(drop=True)
# Lets simulate some new Cpxs.
Calc_Cpx_dist_2Na=pt.add_noise_sample_1phase(phase_comp=Cpx_1, phase_err=Cpx_1_Err_2Na,
                                             phase_err_type="Perc", duplicates=20000, err_dist="normal")
# And lets calculate pressures
Calc_PT_2Na=pt.calculate_cpx_only_press_all_eqs(cpx_comps=Calc_Cpx_dist_2Na)
All negative numbers replaced with zeros. If you wish to keep these, set positive=False

Lets plot these new errors vs. the old errors

  • Again, the contours can take ~30s to appear (with 16 Gb of RAM)

[22]:
fig, (ax1, ax2)  = plt.subplots(1, 2, figsize=(10,5), sharex=True, sharey=True)


extent1=(3.5, 7, 1470, 1540)
ax1.hexbin(Calc_PT['P_Wang21_eq1'],
           Calc_PT['T_Wang21_eq2'],
            cmap=plt.cm.BuPu,
            linewidths=0.2, bins=10)
ax1.set_xlabel('Calc P (kbar)')
ax1.set_xlabel('Calc T (K)')




extent2=(3.5, 7, 1470, 1540)
ax2.hexbin(Calc_PT_2Na['P_Wang21_eq1'],
           Calc_PT_2Na['T_Wang21_eq2'],
            cmap=plt.cm.BuPu,
            linewidths=0.2, bins=10)
ax2.set_xlabel('Calc P (kbar)')
ax2.set_xlabel('Calc T (K)')


Calc_PT.loc[:,
["P_Wang21_eq1", "T_Wang21_eq2"]].pyroplot.density(ax=ax1, contours=[0.67, 0.95], colors=['m', 'c'],
                                                   extent=extent1, cmap="viridis",
                                                   bins=70, label_contours=False)

Calc_PT.loc[:,
["P_Wang21_eq1", "T_Wang21_eq2"]].pyroplot.density(ax=ax2, contours=[0.67, 0.95], colors=['m', 'c'],
                                                   extent=extent1, cmap="viridis",
                                                   bins=70, label_contours=False, width=0.5)

Calc_PT_2Na.loc[:,
["P_Wang21_eq1", "T_Wang21_eq2"]].pyroplot.density(ax=ax2, contours=[0.67, 0.95], colors=['r', 'blue'],
                                                   extent=extent2, cmap="viridis",
                                                   bins=70, label_contours=False)

ax1.errorbar(np.mean(Calc_PT['P_Wang21_eq1']),
             np.mean(Calc_PT['T_Wang21_eq2']),
             xerr=1.52, yerr=35.2,
             fmt='.', ecolor='k', elinewidth=0.8, mfc='k', ms=1)

ax2.errorbar(np.mean(Calc_PT['P_Wang21_eq1']),
             np.mean(Calc_PT['T_Wang21_eq2']),
             xerr=1.52, yerr=35.2,
             fmt='.', ecolor='k', elinewidth=0.8, mfc='k', ms=1)

ax1.set_xlim([3, 8])
ax1.set_ylim([1470,  1550])

ax1.set_xlabel('Calc P (kbar)')
ax1.set_ylabel('Calc T (K)')

ax2.set_xlabel('Calc P (kbar)')
ax2.set_ylabel('Calc T (K)')
ax2.yaxis.set_tick_params(which='both', labelbottom=True)
c:\Users\penny\anaconda3\Lib\site-packages\pyrolite\util\plot\density.py:202: UserWarning: The following kwargs were not used by contour: 'width'
  cs = contour(
../../_images/Examples_Error_propagation_Cpx_only_contour_plot_31_1.png

Lets make a pretty figure for publication with just the stated errors for Wang and Putirka thermobarometers, but overlay an additional contour for bigger Na2O errors

[23]:
# Wang thermobarometers
fig, (ax1)  = plt.subplots(1, figsize=(6,5), sharex=True, sharey=True)

## LHS, Wang et al. 2021
extent1=(3.5, 7, 1470, 1540)
ax1.hexbin(Calc_PT['P_Wang21_eq1'],
           Calc_PT['T_Wang21_eq2'],
            cmap=plt.cm.BuPu,
            linewidths=0.2, bins=10)
ax1.set_xlabel('Calc P (kbar)')
ax1.set_xlabel('Calc T (K)')


Calc_PT.loc[:,
["P_Wang21_eq1", "T_Wang21_eq2"]].pyroplot.density(ax=ax1, contours=[0.67, 0.95], colors=['m', 'c'],
                                                   extent=extent1, cmap="viridis",
                                                   bins=70, label_contours=False)


Calc_PT_2Na.loc[:,
["P_Wang21_eq1", "T_Wang21_eq2"]].pyroplot.density(ax=ax1, contours=[0.95], colors=['c'],
                                                   extent=extent2, cmap="viridis",
                                                   bins=70, label_contours=False,
                                                  linestyles=['-.'])

ax1.errorbar(np.mean(Calc_PT['P_Wang21_eq1']),
             np.mean(Calc_PT['T_Wang21_eq2']),
             xerr=1.52, yerr=35.2,
             fmt='.', ecolor='k', elinewidth=0.8, mfc='k', ms=1)


ax1.set_xlim([3, 8])
ax1.set_ylim([1450,  1530])

ax1.set_xlabel('Calc P (kbar)')
ax1.set_ylabel('Calc T (K)')

ax2.set_xlabel('Calc P (kbar)')
ax2.set_ylabel('Calc T (K)')

ax2.yaxis.set_tick_params(which='both', labelbottom=True)
fig.savefig('Cpx_only_Error.png', dpi=200)
../../_images/Examples_Error_propagation_Cpx_only_contour_plot_33_0.png
[ ]:
# Putirka Cpx-only barometers
fig, (ax1)  = plt.subplots(1, figsize=(6,5), sharex=True, sharey=True)

## LHS, Wang et al. 2021
extent1=(1, 10, 1430, 1540)
ax1.hexbin(Calc_PT['P_Put_Teq32d_Peq32b'],
           Calc_PT['T_Put_Teq32d_Peq32b'],
            cmap=plt.cm.BuPu,
            linewidths=0.2, bins=10)
ax1.set_xlabel('Calc P (kbar)')
ax1.set_xlabel('Calc T (K)')


Calc_PT.loc[:,
["P_Put_Teq32d_Peq32b", "T_Put_Teq32d_Peq32b"]].pyroplot.density(ax=ax1, contours=[0.67, 0.95], colors=['m', 'c'],
                                                   extent=extent1, cmap="viridis",
                                                   bins=70, label_contours=False)

extent2=(1, 10, 1430, 1540)

Calc_PT_2Na.loc[:,
["P_Put_Teq32d_Peq32b", "T_Put_Teq32d_Peq32b"]].pyroplot.density(ax=ax1, contours=[0.95], colors=['c'],
                                                   extent=extent2, cmap="viridis",
                                                   bins=70, label_contours=False,
                                                  linestyles=['-.'])

ax1.errorbar(np.mean(Calc_PT['P_Put_Teq32d_Peq32b']),
             np.mean(Calc_PT['T_Put_Teq32d_Peq32b']),
             xerr=2.6, yerr=58,
             fmt='.', ecolor='k', elinewidth=0.8, mfc='k', ms=1)


ax1.set_xlim([1.5, 8])
ax1.set_ylim([1430,  1520])

ax1.set_xlabel('Calc P (kbar)')
ax1.set_ylabel('Calc T (K)')

ax2.set_xlabel('Calc P (kbar)')
ax2.set_ylabel('Calc T (K)')

ax2.yaxis.set_tick_params(which='both', labelbottom=True)
fig.savefig('Cpx_only_Error_Put.png', dpi=200)
../../_images/Examples_Error_propagation_Cpx_only_contour_plot_34_0.png

Lets calculate the statistics for various noise simulations

[24]:
Stats_P=pt.av_noise_samples_series(Calc_PT['P_Wang21_eq1'], Calc_PT['Sample_ID_Cpx_Num'])
Stats_P
[24]:
Sample # averaged Mean_calc Median_calc St_dev_calc St_dev_calc_from_percentiles Max_calc Min_calc
0 0.0 20000 5.224174 5.243925 0.581436 0.574622 7.112735 2.418245
[25]:
Stats_T=pt.av_noise_samples_series(Calc_PT['T_Wang21_eq2'], Calc_PT['Sample_ID_Cpx_Num'])
Stats_T
[25]:
Sample # averaged Mean_calc Median_calc St_dev_calc St_dev_calc_from_percentiles Max_calc Min_calc
0 0.0 20000 1493.217726 1493.365316 8.596538 8.501955 1525.253951 1453.330584
[26]:
Stats_T=pt.av_noise_samples_series(Calc_PT_2Na['T_Wang21_eq2'], Calc_PT_2Na['Sample_ID_Cpx_Num'])
Stats_T
[26]:
Sample # averaged Mean_calc Median_calc St_dev_calc St_dev_calc_from_percentiles Max_calc Min_calc
0 0.0 20000 1493.243792 1493.461736 9.229113 9.180253 1530.644994 1453.990044
[27]:
Stats_P=pt.av_noise_samples_series(Calc_PT_2Na['P_Wang21_eq1'], Calc_PT_2Na['Sample_ID_Cpx_Num'])
Stats_P
[27]:
Sample # averaged Mean_calc Median_calc St_dev_calc St_dev_calc_from_percentiles Max_calc Min_calc
0 0.0 20000 5.22653 5.244425 0.721283 0.713538 8.01063 2.172848
[28]:
Stats_P_Put=pt.av_noise_samples_series(Calc_PT_2Na['P_Put_Teq32d_Peq32b'], Calc_PT_2Na['Sample_ID_Cpx_Num'])
Stats_P_Put
[28]:
Sample # averaged Mean_calc Median_calc St_dev_calc St_dev_calc_from_percentiles Max_calc Min_calc
0 0.0 20000 5.00325 5.019843 0.952609 0.947076 8.946914 0.761413
[29]:
Stats_P_Put=pt.av_noise_samples_series(Calc_PT['P_Put_Teq32d_Peq32b'], Calc_PT['Sample_ID_Cpx_Num'])
Stats_P_Put
[29]:
Sample # averaged Mean_calc Median_calc St_dev_calc St_dev_calc_from_percentiles Max_calc Min_calc
0 0.0 20000 5.035922 5.036038 0.844282 0.83978 8.088378 1.862193
[30]:
Stats_P_Put=pt.av_noise_samples_series(Calc_PT['T_Put_Teq32d_Peq32b'], Calc_PT['Sample_ID_Cpx_Num'])
Stats_P_Put
[30]:
Sample # averaged Mean_calc Median_calc St_dev_calc St_dev_calc_from_percentiles Max_calc Min_calc
0 0.0 20000 1485.247841 1485.337527 9.574996 9.55245 1520.120853 1443.237187
[ ]:

[ ]: