Miscellaneous
Generate mock datasets
In some case it is useful to test a model for robustness before the emprical data are available for fitting. This can be achieved via the GModelFit.mock()
function, whose purpose is to generate a mock dataset which simulates a measurement process by adding random noise to the foreseen ground-truth.
Example
using GModelFit
model = Model(:main => @fd (x, T=3.14) -> sin.(x ./ T) ./ (x ./ T))
# Generate a mock dataset on a specific domain
dom = Domain(1:0.1:50)
data = GModelFit.mock(Measures, model, dom, seed=1)
# Fit model against the mock dataset
bestfit, stats = fit(model, data)
(Components:
╭───────────┬───────┬───────┬─────────────┬───────────┬───────────┬───────────┬─────────╮
│ Component │ Type │ #Free │ Eval. count │ Min │ Max │ Mean │ NaN/Inf │
├───────────┼───────┼───────┼─────────────┼───────────┼───────────┼───────────┼─────────┤
│ main │ FComp │ 1 │ 29 │ -0.2172 │ 0.9831 │ 0.08502 │ 0 │
╰───────────┴───────┴───────┴─────────────┴───────────┴───────────┴───────────┴─────────╯
Parameters:
╭───────────┬───────┬────────┬──────────┬───────────┬───────────┬────────┬───────╮
│ Component │ Type │ Param. │ Range │ Value │ Uncert. │ Actual │ Patch │
├───────────┼───────┼────────┼──────────┼───────────┼───────────┼────────┼───────┤
│ main │ FComp │ T │ -Inf:Inf │ 3.137 │ 0.01237 │ │ │
╰───────────┴───────┴────────┴──────────┴───────────┴───────────┴────────┴───────╯
, Fit results: #data: 491, #free pars: 1, red. fit stat.: 1.0613, Status: OK
)
Serialization
A few structures, namely GModelFit.ModelSnapshot
, GModelFit.FitStats
and Measures{N}
, as well as Vector
(s) of such structures can be serialized, i.e. stored in a file using a dedicated JSON format. The structures can lated be de-serialized in a separata Julia session without the need to re-run the fitting process used to create them in the first place.
Example
In the following we will generate a few GModelFit.jl objects and serialized them in a file.
using GModelFit
dom = Domain(1:0.1:50)
model = Model(:main => @fd (x, T=3.14) -> sin.(x ./ T) ./ (x ./ T))
data = GModelFit.mock(Measures, model, dom, seed=1)
bestfit, stats = fit(model, data)
# Serialize objects and save in a file
GModelFit.serialize("save_for_future_use.json", bestfit, stats, data)
The same objects can be de-serialized in a different Julia session:
using GModelFit
bestfit, stats, data = GModelFit.deserialize("save_for_future_use.json")
3-element Vector{Any}:
Components:
╭───────────┬───────┬───────┬─────────────┬───────────┬───────────┬───────────┬─────────╮
│ Component │ Type │ #Free │ Eval. count │ Min │ Max │ Mean │ NaN/Inf │
├───────────┼───────┼───────┼─────────────┼───────────┼───────────┼───────────┼─────────┤
│ main │ FComp │ 1 │ 29 │ -0.2172 │ 0.9831 │ 0.08502 │ 0 │
╰───────────┴───────┴───────┴─────────────┴───────────┴───────────┴───────────┴─────────╯
Parameters:
╭───────────┬───────┬────────┬──────────┬───────────┬───────────┬────────┬───────╮
│ Component │ Type │ Param. │ Range │ Value │ Uncert. │ Actual │ Patch │
├───────────┼───────┼────────┼──────────┼───────────┼───────────┼────────┼───────┤
│ main │ FComp │ T │ -Inf:Inf │ 3.137 │ 0.01237 │ │ │
╰───────────┴───────┴────────┴──────────┴───────────┴───────────┴────────┴───────╯
Fit results: #data: 491, #free pars: 1, red. fit stat.: 1.0613, Status: OK
Measures{1}: (length: 491)
╭─────────┬───────────┬───────────┬───────────┬───────────┬───────────┬─────────╮
│ │ Min │ Max │ Mean │ Median │ Std. dev. │ Nan/Inf │
├─────────┼───────────┼───────────┼───────────┼───────────┼───────────┼─────────┤
│ values │ -0.3882 │ 1.117 │ 0.08193 │ 0.02601 │ 0.275 │ │
│ uncerts │ 0.06002 │ 0.06985 │ 0.06166 │ 0.06082 │ 0.00229 │ │
╰─────────┴───────────┴───────────┴───────────┴───────────┴───────────┴─────────╯
Quick plot (1D)
The GModelFit.jl package implements Gnuplot.jl recipes to display plots of Measures{1}
and ModelSnapshot
objects., e.g.:
Example
Create a model, a mock dataset and run a fit:
using GModelFit
dom = Domain(0:0.01:5)
model = Model(:bkg => GModelFit.OffsetSlope(1, 1, 0.1),
:l1 => GModelFit.Gaussian(1, 2, 0.2),
:l2 => GModelFit.Gaussian(1, 3, 0.4),
:main => SumReducer(:bkg, :l1, :l2))
data = GModelFit.mock(Measures, model, dom)
bestfit, stats = fit(model, data)
A plot of the dataset and of the best fit model can be simply obtained with
using Gnuplot
@gp data bestfit
You may also specify axis range, labels, title, etc. using the standard Gnuplot.jl keyword syntax, e.g.:
using Gnuplot
@gp xr=[1, 4.5] xlabel="Wavelength" ylab="Flux" "set key outside" data bestfit
GModelFit internals
(This section deals with GModelFit.jl internals, feel free to skip if not interested.)
During minimization a number of internal data structures are created to avoid reallocating heap memory at each iteration. The most important of such structures are:
GModelFit.CompEval
: a container to perform component evaluation on a specific domain. This structure is relevant when defining Custom components as it is used to dispatch component evaluation to the properevaluate!
method;GModelFit.ModelEval
: a container for aModel
evaluation on a specific domain. This structure contains a dictionary ofCompEval
structures for all components in a model, as well as the values of patched parameters (see Parameter constraints), and is updated at each iteration of the minimizer to reflect the current model evaluaion.An important functionality of the
ModelEval
structure is that it detects the changes in the originalModel
even after it has been created, e.g.:# Create a Model model = Model(:comp1 => @fd (x, p1=1) -> p1 .* x) # Wrap the model into a ModelEval to perform evaluation on a specific domain dom = Domain(1:5) meval = GModelFit.ModelEval(model, dom) # Evaluate and print the maximum value GModelFit.update!(meval) println(maximum(GModelFit.last_evaluation(meval))) # Add a second component to the original model model[:comp2] = @fd (x, comp1, p2=1) -> comp1 .+ p2 .* x.^2 # Re-evaluate the ModelEval (it will automatically detect the addition of :comp2) GModelFit.update!(meval) println(maximum(GModelFit.last_evaluation(meval)))
5.0 30.0
GModelFit.Residuals
: container for aModelEval
object, aMeasures
object, aVector{Float64}
to store the normalized residuals, and a minimizer instance. AResiduals
object contains all the relevant informations to perform minimization, and is therefore the only argument required for theGModelFit.minimize!
function. SinceResiduals
wraps aModelEval
object it is also able to detect changes in the original model.An example of its usage is as follows:
data = GModelFit.mock(Measures, model, dom) resid = GModelFit.Residuals(meval, data, GModelFit.lsqfit()) GModelFit.minimize!(resid)
The
GModelFit.MultiResiduals
has the same purpose in the Multi-dataset fitting case.