Fitting
NTECARS.fit_spectrum — Function
fit_spectrum(; spec_exp, sim, parameter_update_function!, initial, lower, upper,
intensity_eval_function = x -> abs.(x ./ maximum(x)).^(1/2) , parameter_scaling_factor = initial,
solver::Symbol = :LM, maxiters= 200, compute_uncertainties = true) -> FitResultFits the the model to a measured spectrum and returns a collection of results in a FitResult.
Arguments
spec_exp::Spectrum: The measured spectrum that should be fittedsim::CARSSimulator: Should contain all required inputs such as linewidthsparameter_update_function!::Function: A function with the signaturef(sim::CARSSimulator, param)that take aparamarray of lengthNand updatessimusing these parameters.initial::Vector{Float64}: Initial values of the fit parameters. Has to be of lengthN.lower::Vector{Float64}: Lower boundary of the fit parameters. Has to be of lengthN.upper::Vector{Float64}: upper boundary of the fit parameters. Has to be of lengthN.weights::Union{Spectrum, Nothing}=nothing: weights used for weighted least squares (formular:residuals = weights .* (I_exp - I_sim).^2). For absolute uncertainties, the weights represent w=1/σ^2 where σ is standard deviation of the measured intensity.absolute_sigma::Bool: Iftrue`, then the weights (sigmas) are used to give absolute uncertainties. Otherwise, sigma is scaled to match the sample variance between the fitted and experimenal spectral.solver::Symbol: Options are:LMfor LevenbergMarquardt and:IPOPTfor the IPOPT solver.maxiters::Int64: Maximum number of iterationscompute_uncertainties::Bool = true: Mostly an option to disable for cases is which the SVD throws an error.tolerance::Float64 = 1e-5: Tolerance that is passed to the solver.
return
FitResult: contains parameters, spectra, uncertainties etc...
Example
Which parameters are fitted toegther is determined by the parameter_update_function!.
For a sim::CARSSimulator that contains the species N2Species as the first element in sim.species, the rotational and vibrational temperature can for example be fitted by defining the update function
function update_function!(sim::CARSSimulator, param)
T_vib, T_rot = param
sim.conditions.T_gas = T_rot
sim.species[1].distribution = N2.MultiTemperatureDistribution(
T_vib = T_vib, T_rot = T_rot)
end
result = fit_spectrum(;
spec_exp = experimental_spectrum,
sim = sim,
initial = [500.0, 500.0],
lower = [0.0, 0.0],
upper = [3000.0, 3000.0],
parameter_update_function! = update_function!
)NTECARS.FitResult — Type
FitResultStores the complete result of a fit_spectrum call.
Fields
param::Vector{Float64}: Optimal fit parameters found by the solver.uncertainties::Vector{Float64}: Parameter uncertainties estimated from the Jacobian SVD at the optimal solution. Set to zeros ifcompute_uncertainties = falsewas passed tofit_spectrum.fitted_spectrum::Spectrum: Simulated spectrum evaluated on the simulator's internal wavenumber grid.fitted_spectrum_at_measurement::Spectrum: Simulated spectrum evaluated at the wavenumber positions of the experimental spectrum. Use this for direct comparison withexperimental_spectrum.sim::CARSSimulator: Deep copy of the simulator after convergence, updated with the optimal parameters viaparameter_update_function!.experimental_spectrum::Spectrum: The measured spectrum passed tofit_spectrum. Stored to allow serialization and later re-evaluation of the result.parameter_update_function!::Function: The update function used during fitting. Stored to allow re-simulation or re-fitting from the result.weights::Function: The weights used for weighted least-squares
Notes
fitted_spectrumandfitted_spectrum_at_measurementdiffer only in their wavenumber grids. For plotting against measured data, preferfitted_spectrum_at_measurement.- All fields needed to reproduce or serialize the fit are stored directly in the struct, so no reference to the original
simor functions is required after fitting.
NTECARS.save_fit_results — Function
save_fit_results(folderpath, result::FitResult,
parameter_labels=["fit param $(i)" for i in eachindex(result.param)])Saves the complete results of a FitResult to a folder structure of CSV files, including the fitted and experimental spectra, fit parameters with uncertainties, and rovibrational populations for each species.
Arguments
folderpath: Path to the output folder.result::FitResult: The fit result returned byfit_spectrum.parameter_labels: Labels for the fit parameters used in the output file. Defaults to["fit param 1", "fit param 2", ...].
Output files
fit_and_experiment_at_measurement_points.csv: Fitted and experimental√(I_CARS)at the experimental wavenumber grid, including the residual. Contains anti-Stokes wavelength and Raman shift columns relative to both lasers.fit_at_simulated_resolution.csv: Fitted√(I_CARS)at the full simulation resolution, which is typically finer than the experimental grid.fit_parameters.csv: Fitted parameter values with absolute and relative uncertainties (%) for each parameter.covariance_matrix.csv: The covaraince matrix of the fit. Ifabsolute_chi=false, the covariance matrix was rescaled with the redced chi squared.reduced_chi2.csv: The value of the reduced chi squared.CO2_rovibrational_populations/: Created if aCO2Speciesis present inresult.sim.species. Contains one CSV per vibrational state with rotational populations[CO2(v,J)]/[CO2]and their uncertainties, plus a summaryvibrational_populations.csv.N2_rovibrational_populations/: Created if anN2Speciesis present inresult.sim.species. Contains one CSV per vibrational level with rotational populations[N2(v,J)]/[N2]and their uncertainties, plus a summaryvibrational_populations.csv.
Notes
- Rovibrational populations are computed with uncertainty propagation via the
Measurements.jlpackage. Only the uncertainties of fit parameters and not the uncertainties of the polarizabilities and linewidths are considered.
Examples
save_fit_results("results/measurement_01", result)
# With custom parameter labels
save_fit_results("results/measurement_01", result,
["T_12 (K)", "T_3 (K)", "T_N2vib (K)", "T_rot (K)", "CO2 molar fraction"])