Mercury Calibration Spectra

Data from Mercury pencil lamp, Hg-200-650.txt scan (but with some higher res scans to hone in on peaks).  Standard values are taken from “Wavelengths of spectral lines in mercury pencil lamps”, Craig J. Sansonetti, Marc L. Salit, and Joseph Reader, Applied Optics, Vol 35. No. 1, 1 January 1996, pg. 74-77

Clear["Global`*"]; DateString[]

SetDirectory[NotebookDirectory[]]; (* Tell Mathematica to look in this directory for files. *)

Here is a simple function to read in a .CSV file from the spectrometer.  There are a couple of header lines with text, followed by two columns of data:  (nm) and (Counts per Second).

readSpectrum[filename_]:= Select[Import[filename], VectorQ[#, NumericQ] &]

Hg = readSpectrum["Hg-2024-02-21-400-600-0.050nm.csv"];

ListLinePlot[Hg, ImageSize -> 1200, AspectRatio-> 1/3, AxesStyle -> Larger, PlotRange -> All, AxesLabel -> {"wavelength (nm)", "Counts"}]

Interactively zoom in on different peaks.

Manipulate[
small = Select[Hg, min <= #[[1]] <=  max &];ListPlot[small, ImageSize->Scaled[0.9], AspectRatio->1/3, AxesStyle->Larger, AxesLabel->{"wavelength (nm)", "Counts"}, PlotRange -> All], 
{{min, 400}, 400, 599, 1, Appearance->"Open"},
 {{max, 600}, 401, 600, 1, Appearance->"Open"}]

Here, you would import individual peak files to find individual peaks.

peak[x_, A_, μ_, σ_, B_] := B + A Exp[((-(((x - μ))^2))/(2 (σ^2)))]

findpeak[filename_] := Module[{zoom, λmin, λmax, λpeakest, Aest, peakfit},
zoom = readSpectrum[filename];
λmin = zoom[[1, 1]];
λmax = zoom[[-1, 1]];
{λpeakest, Aest}  = MaximalBy[zoom, Last][[1]];
peakfit = NonlinearModelFit[zoom, peak[λ, A, λp, σ, B], 
{{A,Aest}, {λp, λpeakest}, {σ, 0.1}, {B, 1 }}, λ];
Print[Show[{ListPlot[zoom], Plot[peakfit[λ], {λ, zoom[[1, 1]], zoom[[-1, 1]]}, PlotStyle -> Red, PlotRange -> All]}, 
LabelStyle -> Larger, AxesLabel -> {"λ (nm)", "CPS"}, PlotRange -> All, ImageSize->Scaled[0.5]]];
peakfit["BestFitParameters"]
]

peaks = {}; (* Create a list of peaks. *)

filenames = {
"Hg-2024-02-21-405-0.001nm.csv",
"Hg-2024-02-21-436-0.001nm.csv",
"Hg-2024-02-21-507-0.001nm.csv",
"Hg-2024-02-21-546-0.001nm.csv",
"Hg-2024-02-21-577-0.001nm.csv",
"Hg-2024-02-21-579-0.001nm.csv"
};

peaks = Table[findpeak[filenames[[i]]], {i, 1, Length[filenames]}]

measuredλ = λp /. peaks

(* Adjust these based on the imported data *)
standardλ = {404.6565, 435.8335, 2 * 253.6521, 546.0750,576.9610, 579.0670};
calibλ = Table[{measuredλ[[i]], standardλ[[i]]}, {i, 1, Length[measuredλ]}];

Note that some of the peaks are actually second-order diffraction peaks:  d sin(θ) = (2 λ), in particular the 253.63 nm and 296.72 nm peaks are sufficiently bright to be seen clearly in second order.  The peaks are not symmetric; there is a long “shoulder” on the right-hand side of each peak.  This seems to be an artifact of this spectrometer.

λplot = ListPlot[calibλ, AxesLabel -> {"Measured wavelength (nm)", "Standard wavelength (nm)"}, ImageSize -> Scaled[0.8], LabelStyle -> Larger];
λfit = LinearModelFit[calibλ, {1, x}, x]
λfit["ParameterConfidenceIntervalTable"]
Sqrt[λfit["EstimatedVariance"]]
Show[{λplot, Plot[λfit[λ], {λ, 400, 600}, PlotStyle -> Red]}]