In[2]:=
halitevideo=Import["https://www.wolframcloud.com/obj/cc68f9d0-4eb7-4557-aae7-74e96863a18d"]
Out[3]=
(Debug) In[3]:=
Export["C:\\Users\\Manu\\Documents\\Wolfram Summer School\\Project\\haliteimgfromvideo.jpeg",halitevideo]
(Debug) Out[3]=
C:\Users\Manu\Documents\Wolfram Summer School\Project\haliteimgfromvideo.jpeg
Video of an initially all-liquid halite fluid inclusion, in which a vapor bubble is nucleated by means of a femtosecond laser pulse.
Background​
​
Fluid inclusions are tiny water pockets (~1 - 100 µm) trapped in crystals. Their density informs on the temperature of the parent water at the moment of crystal formation. Fluid inclusions in minerals formed at the Earth’s surface could be used to unravel the evolution of the Earth’s climate throughout geological time. Attempts to recover paleo-temperatures (“paleo” meaning “past”) from halite (NaCl) fluid inclusions have been led for 30+ years, but, until recently, techniques that were applied tended to alter the fluid inclusions and yield spurious results. Collaborative work between the University of Lyon, France, the University of Bergen, Norway and Binghamton University, USA, has led to major experimental developments. These breakthroughs now allow to circumvent the issue of fluid inclusion alteration, opening the way to physically-based reconstructions of paleo-temperatures.
​
Halite fluid inclusion paleothermometry relies on finding the temperature at which the vapor-saturated liquid fills the cavity. From the temperature obtained in the lab
T
obs
to the actual paleo-temperature of the parent water
T
f
, correction terms accounting for (i) the liquid surface tension and (ii) the weight of the parent water column must be applied. Before this project, we created a model to calculate these corrections. However, as these corrections depend on the chemical composition of the parent water, the corrections are different for every halite sample. Moreover, the model includes relatively numerous and long equations that are not easily handled.
​
​Project description
​​
We develop a code that automatizes the formatting of the input data, the calculation of the corrections and the generation of a notebook containing the output dataset and various graphs necessary for halite fluid inclusion paleo-thermometry. The input is a series of spreadsheet (csv) containing the information of each fluid inclusion (
T
obs
, size, composition, water column height) for each sample. The computational result is a standardized data structure including the input data and the analysis results.

Input Data

To make this code work, you need to import one or more csv files with the following structure:
(Debug) Out[12]//TableForm=
Fluid inclusion
NaCl (molal)
KCl (molal)
MgCl2 (molal)
CaCl2 (molal)
Na2SO4 (molal)
NaHCO3 (molal)
water column height (m)
length (?m)
width (?m)
Tobs (°C)
1
1.93
0.2
2
0.45
0
0
250
11
10
45
7
1.93
0.2
2
0.45
0
0
250
12
11
19
foo
1.93
0.2
2
0.45
0
0
250
16
10
2
bar
1.93
0.2
2
0.45
0
0
250
10
8
26
All elements must be numbers except the first column (fluid inclusion name) and the first line (headers). The file(s) must contain “Brillouin” or “Microthermometry” in its (their) name(s). Several files can be imported in the same run, but a mix of “Brillouin” and “Microthermometry” cannot be processed.

Import Button

We created a button that imports the files. Error messages are returned if the files do not have the correct structure, correct names, and numbers at the expected locations. Two different types of experimental data can be imported, depending on what technique was used to obtain the data (Brillouin spectroscopy or Microthermometry). They are processed differently in the remainder of this notebook.
(Debug) In[1]:=
ClearAll[{file,data,importButton,haliteFIdataset,haliteFIsamplenames}]​​importButton[textbutton_String,filefmt:{___String}(*":"means"only in the case of the following pattern"*)]:=Button[textbutton,​​​​nCol=11;​​errorDim=Quantity[1,"Micrometers"];​​​​(file=SystemDialogInput["FileOpen",{Directory[],{"Data files"->filefmt}}]);​​filedepth=Depth[file];​​​​If[file=!=$Canceled,​​data=If[filedepth>1,Table[Import[file[[i]]],{i,1,Length[file]}],Import[file]];​​​​If[filedepth>1,​​fileNcol=Map[Length,data,{2}],​​fileNcol=Map[Length,data,{1}]];​​​​If[MatchQ[fileNcol,{{nCol..}..}|{nCol..}],​​​​haliteFIsamplenames=​​If[filedepth>1,​​Map[StringTake[#,StringPosition[#,"\\"][[-1,1]]+1;;-5]&,file],​​{StringTake[file,StringPosition[file,"\\"][[-1,1]]+1;;-5]}​​]//Echo;​​​​brillouinQ=AllTrue[StringContainsQ[haliteFIsamplenames,"Brillouin"],TrueQ,1];​​microthermoQ=AllTrue[StringContainsQ[haliteFIsamplenames,"Microthermometry"],TrueQ,1];​​If[TrueQ[brillouinQ]||TrueQ[microthermoQ],​​​​If[AllTrue[If[filedepth>1,data[[All,2;;,2;;]],data[[2;;,2;;]]],NumberQ,If[filedepth>1,3,2]],​​​​,​​​​Print[​​Style["File data error. All but one columns and all but one lines must contain numbers. Exception: first line (headers) and first column (fluid inclusions name).",Directive[Red]]]​​],​​​​Print[​​Style["File name error. All files must contain the mention 'Brillouin' or 'Microthermometry'. Note that the program cannot process a mix of 'Brillouin' and 'Microthermometry' files.",Directive[Red]]]​​],​​​​Print[​​Style["File structure error. All imported files must have "<>ToString[nCol]<>" columns.",Directive[Red]]]​​],​​Print["Canceled"]​​],​​Method->"Queued"​​]
(Debug) In[3]:=
importButton["Import sample files (csv)",{"*.csv"}]
(Debug) Out[3]=
Import sample files (csv)
»
{MicrothermometrySample7,MicrothermometrySample6,MicrothermometrySample5,MicrothermometrySample4,MicrothermometrySample3,MicrothermometrySample2,MicrothermometrySample1}

Define Keys

We defined headers (to become association “Keys”) for the input and output data
(Debug) In[4]:=
keyslvl1=​​If[Depth[data]>3,​​Table[""<>ToString[i],{j,1,Length@data},{i,1,Length@data[[j]]-1}],​​Table[""<>ToString[i],{i,1,Length@data-1}]​​];​​Switch[microthermoQ,​​True,​​keyslvl2=<|"FluidInclusion"->"Fluid inclusion",Entity["Chemical","SodiumChloride"]->Identity,Entity["Chemical","PotassiumChloride"]->Identity,Entity["Chemical","MagnesiumChloride"]->Identity,Entity["Chemical","CalciumChloride"]->Identity,Entity["Chemical","SodiumSulfate"]->Identity,Entity["Chemical","SodiumHydrogencarbonate"]->Identity,"WaterColumnHeight"->"Water column height","Length"->Identity,"Width"->Identity,"ObservedHomogenizationTemperature"->"Th,obs","Size"->"Size","Area"->"Area","Volume"->"Volume","deltaTLaplacePressure"->"ΔTL","InfiniteHomogenizationTemperature"->"Th,inf","deltaTHydrostaticPressure"->"ΔTP","FormationTemperature"->"Tf"|>,​​False,​​keyslvl2=<|"FluidInclusion"->"Fluid inclusion",Entity["Chemical","SodiumChloride"]->Identity,Entity["Chemical","PotassiumChloride"]->Identity,Entity["Chemical","MagnesiumChloride"]->Identity,Entity["Chemical","CalciumChloride"]->Identity,Entity["Chemical","SodiumSulfate"]->Identity,Entity["Chemical","SodiumHydrogencarbonate"]->Identity,"WaterColumnHeight"->"Water column height","Length"->Identity,"Width"->Identity,"BrillouinIntersectionTemperature"->"Tx","Size"->"Size","Area"->"Area","Volume"->"Volume","InfiniteHomogenizationTemperature"->"Th,inf","deltaTHydrostaticPressure"->"ΔTP","FormationTemperature"->"Tf"|>​​];

Make Association

Create Fourth Level in the Association

The concentrations of every salt in the fluid inclusion make up a group of characteristics that can be gathered in an overarching one: “Concentration”. We created a fourth level of association.

Define Quantities and Uncertainties

Process Data

Calculate Fluid Inclusion Dimensions (Average Size, Area, Volume)

Laplace Pressure Correction Term

Water Column Pressure Correction Term

The we calculate the temperature correction to take into account the effect of the weight of the water column during the entrapment of the fluid inclusion.
Same as for deltaTLaplacePressure: The use of the real deltaTHydrostaticPressureNum function would involve several packages dependencies; as this community post’s purpose is purely illustrative, here we just define a simple, non accurate deltaTHydrostaticPressureNum function.

Output Dataset

Output Graphs

The output graphs show Tf vs. size. In halite fluid inclusion paleo-thermometry, Tf-size trends are indicative of damage or wrong surface tension correction.

Output Notebook

The output notebook contains all the output data (dataset + graphs) as well as the input file names.

Concluding Remarks

The purpose of this work is too facilitate the processing of halite fluid inclusion temperature data and the production of standardized datasets. In a later phase, the code will be deployed to the cloud to allow anyone working on halite fluid inclusion paleo-thermometry to easily generate standardized and corrected paleo-temperature data.

Acknowledgments

This project would not have been possible without the constant support and help of my mentors, Bob Nachbar and Eric James Parfitt. They taught me countless tricks, gave me numerous ideas and greatly improved my coding and Wolfram Language abilities. This project has also largely benefitted from the insightful advice of Stephen Wolfram. I thank all the lecturers of the Wolfram Summer School 2024, I have learnt more in three weeks than I had ever learnt in several years of using Mathematica. This study is part of the CROSSROADS project and has received funding from the European Union’s Horizon 2020 research and innovation programme under the Marie Skłodowska-Curie Action grant agreement No 101029939.

Access the Full Code

These are a short URL and a QR code used to condense large blocks of code. They will lead to the Wolfram Community version of your project where the full code can be found. Our publishing team will provide these for you. They can be placed anywhere in your project where we want to condense code for print.

Cite This Notebook

“Automated experimental data processing - example of halite fluid inclusion paleo-temperatures”
​by Emmanuel Guillerm​
​https://community.wolfram.com/groups/-/m/t/3209864