This page was generated from
docs/examples/mineralML_mapping.ipynb.
Interactive online version:
.
[1]:
""" Created on November 13, 2023 // Updated on March 20, 2026 // @author: Sarah Shi """
import os
import numpy as np
import pandas as pd
import mineralML as mm
import matplotlib.pyplot as plt
%matplotlib inline
%config InlineBackend.figure_format = 'png'
mineralML Quickstart for Mapped EDS Data
This notebook shows how to load and run your quantitative EDS data through mineralML with an example gabbroic nodule from the Galapagos: 09g3. These data are from Gleeson et al., 2024 (find the paper here: https://doi.org/10.1093/petrology/egaf031) in this GitHub repository (https://github.com/gleesonm1/GleesonEtAl_JPet_2024_supplement/tree/main/Code_Figures/Data/LargeScaleMaps/Gabbro%20Samples). Please refer to the paper for more information about this sample.
This is a five step process:
Load a directory containing all your CSVs of mapped chemical data with
mm.load_df(orpd.read_csvdirectly). [Optional] Convert the input from element to oxide wt%.Predict the mineral class with mineralML and automatically plot the mineral phase map, mineral phase counts, and prediction score histograms
Plot prediction score map and individual oxide maps.
Plot compositions of mapped minerals in various classification diagrams (ternary, quadrilateral).
Plot chemical variation maps.
I have conveniently (I hope!) wrapped all of these bits into one function, called mm.run_map.
We loaded in the mineralML Python package as mm. mineralML has trained machine learning models for classifying minerals. This implementation aims to get your electron microprobe or quantitative EDS compositions classified and processed. We remove some degrees of freedom to simplify the process as much as possible. The minerals considered for this study include: Amphibole, Apatite, Biotite, Calcite, Chlorite, Epidote, Feldspar (Alkali Feldspar and Plagioclase), Garnet, Glass,
Kalsilite, Leucite, Melilite, Muscovite, Nepheline, Olivine, Oxide (Rhombohedral_Oxides including Hematite-Ilmenite, Spinel_Group including Magnetite-Spinel), Pyroxene (Clinopyroxene, Orthopyroxene, Na-Pyroxene), Quartz, Rutile, Serpentine, Titanite, Tourmaline, and Zircon.
CSV files containing your mapped data in oxide weight percentages (or converted to) is necessary. Find an example here, reproduced from the Gleeson et al., 2024 GitHub linked above. The necessary oxides are SiO\(_2\), TiO\(_2\), Al\(_2\)O\(_3\), FeO\(_t\), MnO, MgO, CaO, Na\(_2\)O, K\(_2\)O, Cr\(_2\)O\(_3\), P\(_2\)O\(_5\), and ZrO\(_2\) (if you are aiming to classify zircon). For the oxides not analyzed for specific minerals, the preprocessing will fill in the nan values as 0.
1. Load and prepare data for analysis
Here, we will work with data that are in elemental weight percent. This means that we will have to do a conversion to oxide weight percent. The data directory is Maps/09g3.
[2]:
# Find your directory of mapped mineral data, stored in Maps/09g3.
# This code identifies any file with CSV and appends it to the map.
base = "Maps"
map_dirs = []
for root, subdirs, files in os.walk(base):
# Skip any path that includes 'Ignore' in its folder names
if "Ignore" in root.split(os.sep):
continue
if any(f.lower().endswith(".csv") for f in files):
map_dirs.append(root)
print(map_dirs)
['Maps/09g3', 'Maps/MountHood_MH0811b']
2. Apply the trained neural network with mm.run_map
We will use mm.run_map which will return all you need!
[3]:
# Inspect the inputs and outputs of mm.run_map
help(mm.run_map)
Help on function run_map in module mineralML.mapping:
run_map(sample_input, renormalize=False, total_threshold=None, n_iterations=50, min_frac=1e-05, pred_score_threshold=0.6, units='element_wt%', top_k=None, phases=None, exclude_phases=None, phase_colors=None, bar_style='vertical', components_spec=None, remove_islands_flag=False, fill_holes_flag=False, hole_size=10, scalebar_um=None, pixel_size_um=None, scalebar_loc='lower left', scalebar_col='black', show=True)
Load, convert, predict, and plot for one folder of CSV maps.
Always computes mineral components and returns a full results dictionary.
Use ``remove_islands_flag`` and ``fill_holes_flag`` to clean the phase map
before plotting and downstream analysis.
Parameters:
sample_input (str | Path | dict): Directory path or a dict of oxide maps.
renormalize (bool): If True, scale each pixel so oxides sum to 100 wt%.
Applied after total masking.
total_threshold (float | None): Pixels with oxide total below this
value (wt%) are set to NaN before renormalization and prediction.
Use this to mask epoxy/background.
n_iterations (int): MC forward passes for prediction.
min_frac (float): Minimum pixel fraction required to keep a phase.
pred_score_threshold (float): Label NaN where max prediction score <
threshold.
units (str): Input format — 'element_wt%' or 'oxide_wt%'.
top_k (int|None): Cap displayed phases after filtering.
phases (list[str]|None): Explicit phases to plot (overrides auto-pick).
exclude_phases (list[str]|None): Phases to remove from auto-pick.
phase_colors (dict|None): Manual color mapping {PhaseName: HexColor}.
bar_style (str): "vertical" for the default bar chart
(``plot_phase_counts``), or "stacked" for a stacked horizontal
bar (``plot_phase_proportions``).
components_spec (dict|None): Custom mineral formula logic.
remove_islands_flag (bool): If True, removes isolated pixel clusters
smaller than 2 pixels (4-connected) from the phase map. Useful
for cleaning up salt-and-pepper noise in the epoxy region.
fill_holes_flag (bool): If True, fills enclosed background holes within
continuous phase regions up to ``hole_size`` pixels. Useful for
patching small gaps inside large mineral grains.
hole_size (int): Maximum hole area (in pixels) to fill when
``fill_holes_flag`` is True.
scalebar_um (float, optional): Length of the scale bar in micrometers.
pixel_size_um (float): Physical size of a single pixel in micrometers.
scalebar_loc (str): Location of the scale bar (e.g., 'lower left').
scalebar_col (str): Color of the scale bar text/line.
show (bool): If True, calls plt.show().
Returns:
result (dict): Dictionary with keys 'figs', 'shape', 'oxide_maps',
'df_pred', 'mineral_map', 'pred_score_map', 'kept_phases',
'component_maps', 'component_frames'. ``oxide_maps`` includes a
``'Total'`` key with the per-pixel oxide sum.
[4]:
# Here is our all in one function! Read the inputs and outputs provided above.
output = mm.run_map(next((s for s in map_dirs if '09g3' in s), None), # provide the directory of interest. alternatively, you can provide the preloaded dictionary of oxides.
renormalize=False, # optionally renormalize totals to 100 wt%.
total_threshold=None, # optionally filter out SiO2 values below a given value, for when EDS picks up epoxy pixels
pred_score_threshold=0.6, # provide a prediction score threshold. here, i only want values with >= 0.6 prediction score.
min_frac=0.01, # provide a minimum pixel fraction for the phase to be displayed
units='element_wt%', # provide the unit. can choose 'element_wt%' or 'oxide_wt%'
phases=['Plagioclase', 'Clinopyroxene', 'Orthopyroxene', 'Oxide', 'Olivine', 'Glass'], # phases of interest
scalebar_um=50, # define size of scalebar desired, in microns
pixel_size_um=2, # define size of each pixel of scalebar, in microns
scalebar_loc='upper right', # specify location for scalebar
scalebar_col='white', # specify color for scalebar
)
[ok] Si Wt%Montaged Map Data.csv → Si (329, 283)
[ok] Ca Wt%Montaged Map Data.csv → Ca (329, 283)
[ok] Cr Wt%Montaged Map Data.csv → Cr (329, 283)
[ok] Mg Wt%Montaged Map Data.csv → Mg (329, 283)
[ok] Mn Wt%Montaged Map Data.csv → Mn (329, 283)
[ok] Al Wt%Montaged Map Data.csv → Al (329, 283)
[ok] Ti Wt%Montaged Map Data.csv → Ti (329, 283)
[ok] Na Wt%Montaged Map Data.csv → Na (329, 283)
[ok] Fe Wt%Montaged Map Data.csv → Fe (329, 283)
[ok] K Wt%Montaged Map Data.csv → K (329, 283)
mineralML: 93107 rows — 57725 classified by neural network, 7 by empirical rules (Zircon: 0, SiO2 polymorph: 0, Carbonate: 7), 35375 skipped (invalid/empty)
prep_df: 57725 row(s) processed (of 57725 input, 0 dropped).
/home/docs/checkouts/readthedocs.org/user_builds/mineralml/checkouts/stable/src/mineralML/hybrid.py:313: UserWarning: The following columns were missing and have been filled with NaN: ['Mineral']
df = prep_df(df)
[5]:
# Inspect what is in the outputs
output.keys()
[5]:
dict_keys(['figs', 'shape', 'oxide_maps', 'df_pred', 'mineral_map', 'pred_score_map', 'kept_phases', 'component_maps', 'component_frames'])
Let’s say you now want to work with these data in dataframe form rather than dictionary form. How would you do this? Access output['df_pred'] to retrieve the predictions dataframe.
[6]:
# Pull the dataframe of predictions
df_pred = output['df_pred']
display(df_pred)
| SiO2 | TiO2 | Al2O3 | FeOt | MnO | MgO | CaO | Na2O | K2O | Cr2O3 | P2O5 | ZrO2 | Predict_Mineral | Prediction_Score | Prediction_Score_Sigma | Second_Predict_Mineral | Second_Prediction_Score | Submineral | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 49.263735 | 0.246671 | 31.267656 | -0.141366 | -0.133547 | -0.041928 | 11.384471 | 3.906129 | 0.287173 | 0.206763 | NaN | NaN | Plagioclase | 0.998627 | 0.005443 | Muscovite | 0.001223 | Labradorite |
| 1 | 52.781465 | 1.223476 | 29.213528 | 1.751936 | -0.008407 | 0.353991 | 13.811718 | 3.613949 | 0.326185 | 0.009850 | NaN | NaN | Plagioclase | 0.999909 | 0.000345 | Titanite | 0.000041 | Labradorite |
| 2 | 49.582496 | -0.666395 | 31.217623 | 0.669667 | 0.312345 | 0.135481 | 13.362425 | 2.559899 | 0.404478 | -0.008271 | NaN | NaN | Plagioclase | 0.999078 | 0.002773 | Muscovite | 0.000342 | Bytownite |
| 3 | 49.766286 | -0.061016 | 30.748715 | -0.049472 | 0.052490 | -0.063224 | 13.924789 | 3.722859 | 0.031619 | -0.244754 | NaN | NaN | Plagioclase | 0.987317 | 0.083828 | Leucite | 0.007627 | Labradorite |
| 4 | 50.775667 | 0.283931 | 29.405951 | 0.363973 | 0.161280 | 0.434312 | 12.246722 | 2.495524 | 0.260420 | 0.922368 | NaN | NaN | Plagioclase | 0.997432 | 0.005905 | Glass | 0.001690 | Bytownite |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 93102 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | NaN | NaN | None | NaN | NaN | NaN | NaN | NaN |
| 93103 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | NaN | NaN | None | NaN | NaN | NaN | NaN | NaN |
| 93104 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | NaN | NaN | None | NaN | NaN | NaN | NaN | NaN |
| 93105 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | NaN | NaN | None | NaN | NaN | NaN | NaN | NaN |
| 93106 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | None | NaN | NaN | NaN | NaN | NaN |
93107 rows × 18 columns
3. Plot oxide concentration maps and prediction score maps
Let’s plot the original oxide maps loaded from the directory. We can examine how well the predicted phase map matches some of the observations made in oxide space. We have a handy function for doing so, with mm.plot_oxide_map.
[7]:
fig, ax = mm.plot_oxide_map(
output, # take the output from run_map
oxide_name='SiO2', # specify the oxide of interest
scalebar_um=50, # define size of scalebar desired, in microns
pixel_size_um=2, # define size of each pixel of scalebar, in microns
scalebar_loc='upper right', # specify location for scalebar
scalebar_col='black', # specify color for scalebar
)
Let’s plot the prediction scores from the output, in mapped form. This allows for further investigation to determine where predictions are more and less certain.
[8]:
fig, ax = mm.plot_score_map(
output, # take the output from run_map
scalebar_um=50, # define size of scalebar desired, in microns
pixel_size_um=2, # define size of each pixel of scalebar, in microns
scalebar_loc='upper right', # specify location for scalebar
scalebar_col='black', # specify color for scalebar
)
4. Plot compositions of mapped minerals in various classification diagrams (ternary, quadrilateral).
We can do some more with mineralML now. Let’s plot all the feldspars, pyroxenes, and spinels in ternary space.
Identify the phases present.
[9]:
# Here are all our feldspars
fspars = df_pred[df_pred.Predict_Mineral == 'Plagioclase']
display('Feldspars:', fspars)
# Here are all our pyroxenes
pxs_names = ['Clinopyroxene', 'Orthopyroxene']
pxs = df_pred[df_pred.Predict_Mineral.isin(pxs_names)]
display('Pyroxenes:', pxs)
# Here are all our oxides
ox_names = ['Oxide']
oxs = df_pred[df_pred.Predict_Mineral.isin(ox_names)]
display('Oxides:', oxs)
'Feldspars:'
| SiO2 | TiO2 | Al2O3 | FeOt | MnO | MgO | CaO | Na2O | K2O | Cr2O3 | P2O5 | ZrO2 | Predict_Mineral | Prediction_Score | Prediction_Score_Sigma | Second_Predict_Mineral | Second_Prediction_Score | Submineral | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 49.263735 | 0.246671 | 31.267656 | -0.141366 | -0.133547 | -0.041928 | 11.384471 | 3.906129 | 0.287173 | 0.206763 | NaN | NaN | Plagioclase | 0.998627 | 0.005443 | Muscovite | 0.001223 | Labradorite |
| 1 | 52.781465 | 1.223476 | 29.213528 | 1.751936 | -0.008407 | 0.353991 | 13.811718 | 3.613949 | 0.326185 | 0.009850 | NaN | NaN | Plagioclase | 0.999909 | 0.000345 | Titanite | 0.000041 | Labradorite |
| 2 | 49.582496 | -0.666395 | 31.217623 | 0.669667 | 0.312345 | 0.135481 | 13.362425 | 2.559899 | 0.404478 | -0.008271 | NaN | NaN | Plagioclase | 0.999078 | 0.002773 | Muscovite | 0.000342 | Bytownite |
| 3 | 49.766286 | -0.061016 | 30.748715 | -0.049472 | 0.052490 | -0.063224 | 13.924789 | 3.722859 | 0.031619 | -0.244754 | NaN | NaN | Plagioclase | 0.987317 | 0.083828 | Leucite | 0.007627 | Labradorite |
| 4 | 50.775667 | 0.283931 | 29.405951 | 0.363973 | 0.161280 | 0.434312 | 12.246722 | 2.495524 | 0.260420 | 0.922368 | NaN | NaN | Plagioclase | 0.997432 | 0.005905 | Glass | 0.001690 | Bytownite |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 92980 | 50.751835 | 0.053460 | 30.892806 | 0.040494 | -0.461759 | 0.181496 | 13.219259 | 4.255093 | 0.562793 | 0.125117 | NaN | NaN | Plagioclase | 0.998067 | 0.008614 | Glass | 0.001712 | Labradorite |
| 92981 | 47.055855 | 0.435257 | 28.540332 | 0.088852 | -0.089822 | 0.027772 | 10.548025 | 3.540654 | 0.550766 | 0.032374 | NaN | NaN | Plagioclase | 0.980982 | 0.046478 | Glass | 0.012173 | Labradorite |
| 92982 | 49.572227 | 0.371584 | 32.248626 | 0.873017 | -0.285326 | 0.130899 | 12.215584 | 4.380849 | 0.471066 | 0.514502 | NaN | NaN | Plagioclase | 0.999816 | 0.000423 | Muscovite | 0.000078 | Labradorite |
| 92983 | 49.374082 | -0.392758 | 32.780453 | 0.389758 | 0.339789 | 0.275332 | 13.295722 | 4.352765 | 0.428836 | 0.269782 | NaN | NaN | Plagioclase | 0.997028 | 0.018393 | Leucite | 0.001778 | Labradorite |
| 92984 | 47.506399 | 0.326601 | 30.147186 | 0.261584 | -0.122220 | -0.125815 | 12.209264 | 4.127070 | 0.188657 | -0.821505 | NaN | NaN | Plagioclase | 0.990222 | 0.040914 | Glass | 0.007537 | Labradorite |
32058 rows × 18 columns
'Pyroxenes:'
| SiO2 | TiO2 | Al2O3 | FeOt | MnO | MgO | CaO | Na2O | K2O | Cr2O3 | P2O5 | ZrO2 | Predict_Mineral | Prediction_Score | Prediction_Score_Sigma | Second_Predict_Mineral | Second_Prediction_Score | Submineral | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 49 | 46.703956 | 2.306829 | 8.091728 | 7.608155 | 0.179336 | 10.411849 | 18.795262 | 2.432519 | 0.532825 | 0.203853 | NaN | NaN | Clinopyroxene | 0.907966 | 0.130830 | Glass | 0.059600 | Diopside |
| 610 | 48.659501 | 1.695958 | 7.334367 | 7.926977 | -0.333935 | 10.416438 | 17.438423 | 2.285797 | 1.183322 | 0.106932 | NaN | NaN | Clinopyroxene | 0.921416 | 0.161371 | Glass | 0.050355 | Diopside |
| 616 | 48.778790 | 1.189971 | 2.368374 | 9.717480 | -0.178262 | 19.703388 | 16.359033 | 0.808957 | 0.195681 | 0.046046 | NaN | NaN | Clinopyroxene | 0.796175 | 0.219379 | Amphibole | 0.191745 | Augite |
| 626 | 43.817565 | 1.304287 | 4.129765 | 5.646358 | -0.037404 | 11.766227 | 22.258578 | 1.406237 | 0.008721 | 0.322146 | NaN | NaN | Clinopyroxene | 0.974739 | 0.057883 | Melilite | 0.013015 | Wollastonite |
| 900 | 48.447279 | 1.397534 | 3.416259 | 9.859029 | 0.064421 | 16.668941 | 17.343585 | 1.357627 | 0.303317 | 0.192969 | NaN | NaN | Clinopyroxene | 0.955462 | 0.122916 | Amphibole | 0.043007 | Augite |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 93026 | 48.531633 | 1.086635 | 6.924229 | 5.679027 | 0.897636 | 13.753107 | 20.414549 | 0.316232 | 0.073446 | 0.035749 | NaN | NaN | Clinopyroxene | 0.926149 | 0.175677 | Garnet | 0.032151 | Diopside |
| 93027 | 46.290230 | 1.380040 | 7.945115 | 7.235223 | 0.274338 | 11.797178 | 19.396081 | 0.955456 | -0.142047 | 0.399850 | NaN | NaN | Clinopyroxene | 0.887151 | 0.191542 | Glass | 0.055837 | Diopside |
| 93028 | 48.117886 | 0.149082 | 8.696416 | 5.671712 | 0.169030 | 13.621192 | 20.402754 | 1.625494 | 0.058249 | -0.174842 | NaN | NaN | Clinopyroxene | 0.971680 | 0.096162 | Melilite | 0.015869 | Diopside |
| 93029 | 46.544554 | 0.287509 | 7.870030 | 6.250091 | 0.117071 | 12.650849 | 19.429830 | -0.016576 | 0.135432 | -0.335588 | NaN | NaN | Clinopyroxene | 0.868953 | 0.225773 | Garnet | 0.056096 | Diopside |
| 93030 | 45.316298 | 0.119567 | 7.955299 | 6.887216 | 0.233471 | 11.919362 | 19.708412 | 0.945937 | 0.133037 | 0.141968 | NaN | NaN | Clinopyroxene | 0.951828 | 0.099333 | Amphibole | 0.025499 | Diopside |
14067 rows × 18 columns
'Oxides:'
| SiO2 | TiO2 | Al2O3 | FeOt | MnO | MgO | CaO | Na2O | K2O | Cr2O3 | P2O5 | ZrO2 | Predict_Mineral | Prediction_Score | Prediction_Score_Sigma | Second_Predict_Mineral | Second_Prediction_Score | Submineral | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 596 | 14.170745 | 0.458430 | 47.168928 | 17.851108 | 0.157325 | 8.807434 | 2.364795 | 1.613537 | 0.231962 | 0.909729 | NaN | NaN | Oxide | 0.974216 | 0.141011 | Chlorite | 2.158251e-02 | Spinel_Group |
| 597 | -0.541988 | -0.226758 | 59.577095 | 22.761509 | 0.261160 | 16.543655 | 0.178530 | -0.327176 | -0.002519 | 0.596073 | NaN | NaN | Oxide | 0.999999 | 0.000000 | Chlorite | 6.135478e-07 | Spinel_Group |
| 598 | 0.328607 | 0.192199 | 60.074062 | 22.531151 | -0.581629 | 16.206175 | -0.071793 | 0.404589 | -0.041741 | 1.762033 | NaN | NaN | Oxide | 0.999997 | 0.000000 | Rhombohedral_Oxides | 3.225375e-06 | Spinel_Group |
| 599 | 0.419032 | -0.416014 | 59.597162 | 20.757558 | -0.198876 | 16.481142 | -0.157663 | 0.094932 | 0.114364 | 1.412415 | NaN | NaN | Oxide | 0.999999 | 0.000244 | Rhombohedral_Oxides | 6.114131e-07 | Spinel_Group |
| 879 | -0.283622 | -0.329943 | 58.807763 | 21.683161 | 0.131220 | 15.814531 | -0.270460 | 0.445707 | 0.113306 | 0.450210 | NaN | NaN | Oxide | 0.999537 | 0.003239 | Chlorite | 4.634696e-04 | Spinel_Group |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 92992 | -0.972727 | 0.199933 | 61.268541 | 19.730463 | 0.777305 | 16.862860 | 0.416785 | 0.532657 | 0.209819 | 1.072017 | NaN | NaN | Oxide | 0.999999 | 0.000244 | Chlorite | 5.719100e-07 | Spinel_Group |
| 92993 | -0.754471 | -0.316257 | 58.986714 | 21.457833 | 0.307136 | 14.984843 | -0.049067 | -0.382976 | -0.506373 | 0.888524 | NaN | NaN | Oxide | 0.961885 | 0.186700 | Chlorite | 3.811476e-02 | Spinel_Group |
| 92994 | -0.476960 | 0.326008 | 59.845682 | 20.725138 | 0.091979 | 16.190988 | 0.066551 | 0.394945 | 0.127746 | 0.985187 | NaN | NaN | Oxide | 0.999744 | 0.001777 | Rhombohedral_Oxides | 2.553134e-04 | Spinel_Group |
| 92995 | 5.724564 | 0.254216 | 55.985948 | 19.883002 | -0.329296 | 15.163671 | 0.563598 | 1.013702 | 0.281037 | 1.044170 | NaN | NaN | Oxide | 0.996396 | 0.024116 | Chlorite | 3.439376e-03 | Spinel_Group |
| 92999 | -0.771758 | -0.311966 | 61.128154 | 23.235195 | -0.302034 | 16.418883 | 0.084923 | 0.164328 | 0.299144 | 1.515729 | NaN | NaN | Oxide | 0.980000 | 0.140000 | Nepheline | 1.999995e-02 | Spinel_Group |
1902 rows × 18 columns
Plot these feldspars, pyroxenes, and spinels!
[10]:
# Use FeldsparClassifier to examine at the component space (XAn, XAb, XOr)
fspar_comp = mm.FeldsparClassifier(fspars).calculate_components()
display(fspar_comp)
# Use FeldsparClassifier to plot up these data.
fig = mm.FeldsparClassifier(fspars).plot()
| Sample | SiO2 | TiO2 | Al2O3 | FeOt | MnO | MgO | CaO | Na2O | K2O | ... | Prediction_Score | Prediction_Score_Sigma | Second_Predict_Mineral | Second_Prediction_Score | Cation_Sum | M_site | T_site | An | Ab | Or | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | NaN | 49.263735 | 0.246671 | 31.267656 | 0.000000 | 0.000000 | 0.000000 | 11.384471 | 3.906129 | 0.287173 | ... | 0.998627 | 0.005443 | Muscovite | 0.001223 | 4.999206 | 0.944346 | 4.038491 | 0.605725 | 0.376083 | 0.018192 |
| 1 | NaN | 52.781465 | 1.223476 | 29.213528 | 1.751936 | 0.000000 | 0.353991 | 13.811718 | 3.613949 | 0.326185 | ... | 0.999909 | 0.000345 | Titanite | 0.000041 | 5.005620 | 0.989984 | 3.885500 | 0.665953 | 0.315321 | 0.018726 |
| 2 | NaN | 49.582496 | 0.000000 | 31.217623 | 0.669667 | 0.312345 | 0.135481 | 13.362425 | 2.559899 | 0.404478 | ... | 0.999078 | 0.002773 | Muscovite | 0.000342 | 4.973277 | 0.918395 | 4.007258 | 0.723219 | 0.250716 | 0.026065 |
| 3 | NaN | 49.766286 | 0.000000 | 30.748715 | 0.000000 | 0.052490 | 0.000000 | 13.924789 | 3.722859 | 0.031619 | ... | 0.987317 | 0.083828 | Leucite | 0.007627 | 5.019679 | 1.028596 | 3.989021 | 0.672721 | 0.325460 | 0.001819 |
| 4 | NaN | 50.775667 | 0.283931 | 29.405951 | 0.363973 | 0.161280 | 0.434312 | 12.246722 | 2.495524 | 0.260420 | ... | 0.997432 | 0.005905 | Glass | 0.001690 | 4.923061 | 0.851499 | 3.977005 | 0.717332 | 0.264506 | 0.018162 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 92980 | NaN | 50.751835 | 0.053460 | 30.892806 | 0.040494 | 0.000000 | 0.181496 | 13.219259 | 4.255093 | 0.562793 | ... | 0.998067 | 0.008614 | Glass | 0.001712 | 5.053574 | 1.055605 | 3.977727 | 0.612308 | 0.356653 | 0.031038 |
| 92981 | NaN | 47.055855 | 0.435257 | 28.540332 | 0.088852 | 0.000000 | 0.027772 | 10.548025 | 3.540654 | 0.550766 | ... | 0.980982 | 0.046478 | Glass | 0.012173 | 4.987109 | 0.940703 | 4.023037 | 0.598951 | 0.363812 | 0.037237 |
| 92982 | NaN | 49.572227 | 0.371584 | 32.248626 | 0.873017 | 0.000000 | 0.130899 | 12.215584 | 4.380849 | 0.471066 | ... | 0.999816 | 0.000423 | Muscovite | 0.000078 | 5.065717 | 1.008939 | 3.983479 | 0.590014 | 0.382896 | 0.027090 |
| 92983 | NaN | 49.374082 | 0.000000 | 32.780453 | 0.389758 | 0.339789 | 0.275332 | 13.295722 | 4.352765 | 0.428836 | ... | 0.997028 | 0.018393 | Leucite | 0.001778 | 5.089961 | 1.051290 | 3.982672 | 0.613189 | 0.363263 | 0.023548 |
| 92984 | NaN | 47.506399 | 0.326601 | 30.147186 | 0.261584 | 0.000000 | 0.000000 | 12.209264 | 4.127070 | 0.188657 | ... | 0.990222 | 0.040914 | Glass | 0.007537 | 5.045055 | 1.026253 | 3.996449 | 0.613466 | 0.375247 | 0.011287 |
32058 rows × 58 columns
[11]:
# Use PyroxeneClassifier to examine at the component space (En, Wo, Fs). If sodic pyroxenes are also within this input, this will plot them up in the sodic pyroxene ternary
pxs_comp = mm.PyroxeneClassifier(pxs).calculate_components()
display(pxs_comp)
# Use PyroxeneClassifier to plot up these data.
fig = mm.PyroxeneClassifier(pxs).plot()
| Sample | SiO2 | TiO2 | Al2O3 | FeOt | MnO | MgO | CaO | Na2O | K2O | ... | EnFs | DiHd_2003 | Di | Fe3_Wang21 | Fe2_Wang21 | Di_h | Hd_h | Aeg_h | Jd_h | En_h | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 49 | NaN | 46.703956 | 2.306829 | 8.091728 | 7.608155 | 0.179336 | 10.411849 | 18.795262 | 2.432519 | 0.532825 | ... | 0.086829 | 0.666407 | 0.469393 | 0.089679 | 0.154568 | 0.595819 | 0.009059 | 0.115772 | 0.018559 | 0.034919 |
| 610 | NaN | 48.659501 | 1.695958 | 7.334367 | 7.926977 | 0.000000 | 10.416438 | 17.438423 | 2.285797 | 1.183322 | ... | 0.107573 | 0.632821 | 0.443486 | 0.013317 | 0.240387 | 0.594261 | 0.014598 | 0.071088 | 0.104224 | 0.066707 |
| 616 | NaN | 48.778790 | 1.189971 | 2.368374 | 9.717480 | 0.000000 | 19.703388 | 16.359033 | 0.808957 | 0.195681 | ... | 0.417242 | 0.575877 | 0.451074 | 0.155597 | 0.150052 | 0.457241 | 0.000000 | 0.033339 | 0.000000 | 0.323735 |
| 626 | NaN | 43.817565 | 1.304287 | 4.129765 | 5.646358 | 0.000000 | 11.766227 | 22.258578 | 1.406237 | 0.008721 | ... | 0.015722 | 0.891255 | 0.702211 | 0.187016 | 0.008697 | 0.726986 | 0.114188 | 0.062239 | 0.000000 | 0.000000 |
| 900 | NaN | 48.447279 | 1.397534 | 3.416259 | 9.859029 | 0.064421 | 16.668941 | 17.343585 | 1.357627 | 0.303317 | ... | 0.317609 | 0.617466 | 0.462866 | 0.180335 | 0.131760 | 0.522099 | 0.000000 | 0.068710 | 0.000000 | 0.213817 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 93026 | NaN | 48.531633 | 1.086635 | 6.924229 | 5.679027 | 0.897636 | 13.753107 | 20.414549 | 0.316232 | 0.073446 | ... | 0.135029 | 0.681486 | 0.537139 | -0.004870 | 0.183839 | 0.683252 | 0.000000 | 0.000000 | 0.000000 | 0.148472 |
| 93027 | NaN | 46.290230 | 1.380040 | 7.945115 | 7.235223 | 0.274338 | 11.797178 | 19.396081 | 0.955456 | 0.000000 | ... | 0.131225 | 0.653965 | 0.481823 | 0.026500 | 0.208089 | 0.634156 | 0.000000 | 0.019312 | 0.000000 | 0.125825 |
| 93028 | NaN | 48.117886 | 0.149082 | 8.696416 | 5.671712 | 0.169030 | 13.621192 | 20.402754 | 1.625494 | 0.058249 | ... | 0.125932 | 0.684517 | 0.551743 | 0.128591 | 0.048722 | 0.597250 | 0.000000 | 0.116397 | 0.000000 | 0.083585 |
| 93029 | NaN | 46.544554 | 0.287509 | 7.870030 | 6.250091 | 0.117071 | 12.650849 | 19.429830 | 0.000000 | 0.135432 | ... | 0.162218 | 0.623032 | 0.485826 | -0.043900 | 0.249511 | 0.639871 | 0.000000 | 0.000000 | 0.000000 | 0.155748 |
| 93030 | NaN | 45.316298 | 0.119567 | 7.955299 | 6.887216 | 0.233471 | 11.919362 | 19.708412 | 0.945937 | 0.133037 | ... | 0.124045 | 0.687473 | 0.514851 | 0.084473 | 0.144554 | 0.623202 | 0.000000 | 0.071634 | 0.000000 | 0.092467 |
14067 rows × 86 columns
/home/docs/checkouts/readthedocs.org/user_builds/mineralml/conda/stable/lib/python3.9/site-packages/ternary/plotting.py:148: UserWarning: No data for colormapping provided via 'c'. Parameters 'vmin', 'vmax' will be ignored
ax.scatter(xs, ys, vmin=vmin, vmax=vmax, **kwargs)
[12]:
# Use OxideClassifier to examine at the component space.
oxs_comp = mm.OxideClassifier(oxs).calculate_components()
display(oxs_comp)
# Use OxideClassifier to plot up these data.
fig = mm.OxideClassifier(oxs).plot()
| SiO2 | TiO2 | Al2O3 | FeOt | MnO | MgO | CaO | Na2O | K2O | Cr2O3 | ... | Cation_Sum | A_site | A_site_expanded | B_site | A_B_site | Fe_Ti | Fe3_prop | XR2 | XR3 | XTi | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 596 | 14.170745 | 0.458430 | 47.168928 | 17.851108 | 0.157325 | 8.807434 | 2.364795 | 1.613537 | 0.231962 | 0.909729 | ... | 3.0 | 0.801846 | 0.805654 | 1.619091 | 2.424745 | 0.436489 | 0.000000 | 0.332263 | 0.663672 | 0.004065 |
| 597 | 0.000000 | 0.000000 | 59.577095 | 22.761509 | 0.261160 | 16.543655 | 0.178530 | 0.000000 | 0.000000 | 0.596073 | ... | 3.0 | 0.989221 | 0.995001 | 2.000000 | 2.995001 | 0.497456 | 0.307035 | 0.332221 | 0.667779 | 0.000000 |
| 598 | 0.328607 | 0.192199 | 60.074062 | 22.531151 | 0.000000 | 16.206175 | 0.000000 | 0.404589 | 0.000000 | 1.762033 | ... | 3.0 | 0.971775 | 0.971775 | 1.999551 | 2.971326 | 0.489140 | 0.280194 | 0.327051 | 0.671696 | 0.001254 |
| 599 | 0.419032 | 0.000000 | 59.597162 | 20.757558 | 0.000000 | 16.481142 | 0.000000 | 0.094932 | 0.114364 | 1.412415 | ... | 3.0 | 0.993664 | 0.993664 | 1.986631 | 2.980295 | 0.456697 | 0.239540 | 0.333411 | 0.666589 | 0.000000 |
| 879 | 0.000000 | 0.000000 | 58.807763 | 21.683161 | 0.131220 | 15.814531 | 0.000000 | 0.445707 | 0.113306 | 0.450210 | ... | 3.0 | 0.943236 | 0.946200 | 2.026900 | 2.973100 | 0.483592 | 0.349607 | 0.318254 | 0.681746 | 0.000000 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 92992 | 0.000000 | 0.199933 | 61.268541 | 19.730463 | 0.777305 | 16.862860 | 0.416785 | 0.532657 | 0.209819 | 1.072017 | ... | 3.0 | 0.909033 | 0.925878 | 2.029424 | 2.955302 | 0.426036 | 0.370311 | 0.313294 | 0.685404 | 0.001302 |
| 92993 | 0.000000 | 0.000000 | 58.986714 | 21.457833 | 0.307136 | 14.984843 | 0.000000 | 0.000000 | 0.000000 | 0.888524 | ... | 3.0 | 0.992954 | 1.000000 | 2.000000 | 3.000000 | 0.486031 | 0.201826 | 0.333333 | 0.666667 | 0.000000 |
| 92994 | 0.000000 | 0.326008 | 59.845682 | 20.725138 | 0.091979 | 16.190988 | 0.066551 | 0.394945 | 0.127746 | 0.985187 | ... | 3.0 | 0.953691 | 0.955739 | 2.017969 | 2.973708 | 0.462154 | 0.299782 | 0.321396 | 0.676435 | 0.002168 |
| 92995 | 5.724564 | 0.254216 | 55.985948 | 19.883002 | 0.000000 | 15.163671 | 0.563598 | 1.013702 | 0.281037 | 1.044170 | ... | 3.0 | 1.017350 | 1.017350 | 1.756704 | 2.774054 | 0.439204 | 0.016451 | 0.366738 | 0.631462 | 0.001800 |
| 92999 | 0.000000 | 0.000000 | 61.128154 | 23.235195 | 0.000000 | 16.418883 | 0.084923 | 0.164328 | 0.299144 | 1.515729 | ... | 3.0 | 0.962063 | 0.962063 | 2.017811 | 2.979874 | 0.494272 | 0.313183 | 0.322854 | 0.677146 | 0.000000 |
1902 rows × 70 columns
/home/docs/checkouts/readthedocs.org/user_builds/mineralml/conda/stable/lib/python3.9/site-packages/ternary/plotting.py:148: UserWarning: No data for colormapping provided via 'c'. Parameters 'vmin', 'vmax' will be ignored
ax.scatter(xs, ys, vmin=vmin, vmax=vmax, **kwargs)
You might note that the structure of these three ...Classifier classes is identical. That is intentional! mm.FeldsparClassifier, mm.PyroxeneClassifier, and mm.OxideClassifier all have calculate_components and plot methods embedded.
5. Plot chemical variation maps
We know the mineralogy now. What if you now want to inspect the chemical variation within the individual crystals? Pull the component maps created for each sample and plot this up with mm.plot_component_composite.
This function currently does this calculation for feldspars, pyroxenes, olivines, and amphibole. This can easily be expanded with all the stoichiometric mineral functions. Here, I will just show this for these common igneous phases.
[13]:
# Inspect what’s available:
print(sorted(output["component_maps"].keys()))
# Plot map highlighting internal compositional variation
fig = mm.plot_component_composite(output, # specify output from above
title="09g3", # optionally add a title to this plot
phases=['Plagioclase', 'Clinopyroxene', 'Orthopyroxene', 'Oxide', 'Olivine', 'Glass'], # phases of interest
smooth_sigma=0.25, # add a Gaussian blur to smooth compositional data, usually turned off.
scalebar_um=50, # define size of scalebar desired, in microns
pixel_size_um=2, # define size of each pixel of scalebar, in microns
scalebar_loc='upper right', # specify location for scalebar
scalebar_col='black', # specify color for scalebar
)
['Clinopyroxene.En', 'Clinopyroxene.Fs', 'Clinopyroxene.Wo', 'Feldspar.Ab', 'Feldspar.An', 'Feldspar.Or', 'Orthopyroxene.En', 'Orthopyroxene.Fs', 'Orthopyroxene.Wo']
One could alternatively use all the functions within mineralML.mapping to do these same things, in a more stepwise manner. Look through the documentation if you would like to use individual bits of this code.