diff --git a/Project.toml b/Project.toml index 344f6bd..9200379 100644 --- a/Project.toml +++ b/Project.toml @@ -1,4 +1,4 @@ -name = "GFit" +name = "GModelFit" uuid = "ac42e6ba-c0bf-4fcf-827d-deea44b16255" authors = ["Giorgio Calderone "] version = "0.1.0" diff --git a/README.md b/README.md index 34f512b..afae41d 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,21 @@ -# GFit.jl +# GModelFit.jl [![License](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](LICENSE.md) -[![DocumentationStatus](https://img.shields.io/badge/docs-stable-blue.svg?style=flat)](https://gcalderone.github.io/GFit.jl/) +[![DocumentationStatus](https://img.shields.io/badge/docs-stable-blue.svg?style=flat)](https://gcalderone.github.io/GModelFit.jl/) -`GFit` is a general purpose, data-driven model fitting framework for Julia. +`GModelFit` is a general purpose, data-driven model fitting framework for Julia. ## Installation Install with: ```julia -]add GFit +]add GModelFit ``` ## Example ```julia -using GFit +using GModelFit # Prepare vectors with domain points, empirical measures and uncertainties x = [0.1, 1.1, 2.1, 3.1, 4.1] @@ -38,7 +38,7 @@ The output is as follows: ╭───────────┬────────────┬─────────────┬───────────┬───────────┬───────────┬─────────╮ │ Component │ Type │ Eval. count │ Min │ Max │ Mean │ NaN/Inf │ ├───────────┼────────────┼─────────────┼───────────┼───────────┼───────────┼─────────┤ -│ main │ GFit.FComp │ 76 │ 6.088 │ 25.84 │ 13.56 │ 0 │ +│ main │ GModelFit.FComp │ 76 │ 6.088 │ 25.84 │ 13.56 │ 0 │ ╰───────────┴────────────┴─────────────┴───────────┴───────────┴───────────┴─────────╯ Parameters: diff --git a/docs/src/api.md b/docs/src/api.md index 90e7f1f..458b72a 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -5,7 +5,7 @@ ``` ## Exported symbols -The list of **GFit.jl** exported symbols is as follows: +The list of **GModelFit.jl** exported symbols is as follows: ```@docs CartesianDomain{N} @@ -32,14 +32,14 @@ values ## Non-exported symbols -The following symbols are not exported by the **GFit.jl** package since they are typically not used in every day work, or aimed to debugging purposes. Still, they can be useful in some case, hence they are documented here. +The following symbols are not exported by the **GModelFit.jl** package since they are typically not used in every day work, or aimed to debugging purposes. Still, they can be useful in some case, hence they are documented here. ```@docs -GFit.FitStats -GFit.FunctDesc -GFit.ModelSnapshot -GFit.Parameter -GFit.comptypes -GFit.mock -GFit.serialize +GModelFit.FitStats +GModelFit.FunctDesc +GModelFit.ModelSnapshot +GModelFit.Parameter +GModelFit.comptypes +GModelFit.mock +GModelFit.serialize ``` diff --git a/docs/src/builtincomp.md b/docs/src/builtincomp.md index 7b73c59..a401bd4 100644 --- a/docs/src/builtincomp.md +++ b/docs/src/builtincomp.md @@ -5,7 +5,7 @@ include("setup.jl") # Built-in components -The **GFit.jl** provides several built-in components which may be used to build arbitrarily complex models. +The **GModelFit.jl** provides several built-in components which may be used to build arbitrarily complex models. ## FComp @@ -20,7 +20,7 @@ In the first constructor `funct` is the Julia function, `deps` is a vector of de #### Example ```@example abc -using GFit +using GModelFit # Define a simple Julia function to evaluate a linear relationship myfunc(x, b, m) = b .+ x .* m @@ -28,7 +28,7 @@ myfunc(x, b, m) = b .+ x .* m # Prepare domain and a model with a FComp wrapping the previously defined function. # Also specify the initial guess parameters. dom = Domain(1:5) -model = Model(dom, :linear => GFit.FComp(myfunc, [:x], b=2, m=0.5)) +model = Model(dom, :linear => GModelFit.FComp(myfunc, [:x], b=2, m=0.5)) # Fit model against data data = Measures(dom, [4.01, 7.58, 12.13, 19.78, 29.04], 0.4) @@ -37,7 +37,7 @@ dumpjson("ex_FComp", best, fitstats, data) # hide show((best, fitstats)) # hide ``` -In the second constructor a [`GFit.FunctDesc`](@ref) object is accepted, as generated by the [`@λ`](@ref) macro). The function is typically a mathematical expression combining any number of parameters and/or other component evaluations within the same model. The expression should be given in the form: +In the second constructor a [`GModelFit.FunctDesc`](@ref) object is accepted, as generated by the [`@λ`](@ref) macro). The function is typically a mathematical expression combining any number of parameters and/or other component evaluations within the same model. The expression should be given in the form: ``` @λ (x, [y, [further domain dimensions...],] [comp1, [comp2, [further components ...],]] @@ -50,7 +50,7 @@ The previous example can be rewritten as follows: #### Examples ```@example abc -using GFit +using GModelFit # Prepare domain and a linear model (with initial guess parameters) dom = Domain(1:5) @@ -105,7 +105,7 @@ println() # hide To define the model we will rewrite the equation as `Ax - b = 0`, and define a model as follows ```@example abc dom = Domain(length(b)) # dummy domain -model = Model(dom, GFit.FCompv(x -> A*x - b, +model = Model(dom, GModelFit.FCompv(x -> A*x - b, [1, 1, 1])) println() # hide ``` @@ -124,8 +124,8 @@ An offset and slope component for 1D and 2D domains. The constructors are defined as follows: -- 1D: `GFit.Components.OffsetSlope(offset, x0, slope)`; -- 2D: `GFit.Components.OffsetSlope(offset, x0, y0, slopeX, slopeY)`; +- 1D: `GModelFit.Components.OffsetSlope(offset, x0, slope)`; +- 2D: `GModelFit.Components.OffsetSlope(offset, x0, y0, slopeX, slopeY)`; The parameters are: @@ -143,11 +143,11 @@ The parameters are: #### Examples ```@example abc -using GFit +using GModelFit # Prepare domain and a linear model using the OffsetSlope component dom = Domain(1:5) -model = Model(dom, :linear => GFit.OffsetSlope(2, 0, 0.5)) +model = Model(dom, :linear => GModelFit.OffsetSlope(2, 0, 0.5)) # Fit model against data data = Measures(dom, [4.01, 7.58, 12.13, 19.78, 29.04], 0.4) @@ -161,11 +161,11 @@ Note that the numerical results are identical to the previous example (where an A similar example in 2D is as follows: ```@example abc -using GFit +using GModelFit # Prepare domain and a linear model using the OffsetSlope component dom = CartesianDomain(1:5, 1:5) -model = Model(dom, :plane => GFit.OffsetSlope(2, 0, 0, 0.5, 0.5)) +model = Model(dom, :plane => GModelFit.OffsetSlope(2, 0, 0, 0.5, 0.5)) # Fit model against data data = Measures(dom, [ 3.08403 3.46719 4.07612 4.25611 5.04716 @@ -186,18 +186,18 @@ A *n*-th degree polynomial function (*n > 1*) for 1D domains. The constructor is defined as follows: -- `GFit.Polynomial(p1, p2, ...)`; +- `GModelFit.Polynomial(p1, p2, ...)`; where `p1`, `p2`, etc. are the guess values for the coefficients of each degree of the polynomial. The parameters are accessible via the `p` vector, as: `p[1]`, `p[2]`, etc. #### Examples ```@example abc -using GFit +using GModelFit # Prepare domain and a linear model using the Polynomial component dom = Domain(1:5) -model = Model(dom, GFit.Polynomial(2, 0.5)) +model = Model(dom, GModelFit.Polynomial(2, 0.5)) # Fit model against data data = Measures(dom, [4.01, 7.58, 12.13, 19.78, 29.04], 0.4) @@ -208,7 +208,7 @@ show((best, fitstats)) # hide Note again that the numerical results are identical to the previous examples. Also note that the default name for a component (if none is provided) is `:main`. To use a 2nd degree polynomial we can simply replace the `:main` component with a new one: ```@example abc -model[:main] = GFit.Polynomial(2, 0.5, 1) +model[:main] = GModelFit.Polynomial(2, 0.5, 1) best, fitstats = fit(model, data) dumpjson("ex_Polynomial2", best, fitstats, data) # hide show((best, fitstats)) # hide @@ -222,9 +222,9 @@ A normalized Gaussian component for 1D and 2D domains. The constructors are defined as follows: -- 1D: `GFit.Components.Gaussian(norm, center, sigma)`; -- 2D: `GFit.Components.Gaussian(norm, centerX, centerY, sigma)` (implies `sigmaX=sigmaY`, `angle=0`); -- 2D: `GFit.Components.Gaussian(norm, centerX, centerY, sigmaX, sigmaY, angle)`; +- 1D: `GModelFit.Components.Gaussian(norm, center, sigma)`; +- 2D: `GModelFit.Components.Gaussian(norm, centerX, centerY, sigma)` (implies `sigmaX=sigmaY`, `angle=0`); +- 2D: `GModelFit.Components.Gaussian(norm, centerX, centerY, sigmaX, sigmaY, angle)`; The parameters are: @@ -247,11 +247,11 @@ The parameters are: #### Examples ```@example abc -using GFit +using GModelFit # Prepare domain and model dom = Domain(1:0.5:5) -model = Model(dom, GFit.Gaussian(1, 3, 0.5)) +model = Model(dom, GModelFit.Gaussian(1, 3, 0.5)) # Fit model against data data = Measures(dom, [0, 0.3, 6.2, 25.4, 37.6, 23., 7.1, 0.4, 0], 0.6) @@ -263,7 +263,7 @@ show((best, fitstats)) # hide A very common problem is to fit the histogram of a distribution with a Gaussian model. In the following example we will generate such distribution with `Random.randn`, and use the [Gnuplot.jl](https://github.com/gcalderone/Gnuplot.jl/) package to calculate the histogram and display the plot: ```@example abc -using Random, GFit, Gnuplot +using Random, GModelFit, Gnuplot # Calculate histogram of the distribution hh = hist(randn(10000), bs=0.25) @@ -271,7 +271,7 @@ hh = hist(randn(10000), bs=0.25) # Prepare domain and data and fit a model dom = Domain(hh.bins) data = Measures(dom, hh.counts, 1.) -model = Model(dom, GFit.Gaussian(1e3, 0, 1)) +model = Model(dom, GModelFit.Gaussian(1e3, 0, 1)) best, fitstats = fit(model, data) dumpjson("ex_Gaussian2", best, fitstats, data) # hide show((best, fitstats)) # hide @@ -289,7 +289,7 @@ saveas("gaussian") # hide A similar problem in 2D can be handled as follows: ```@example abc -using Random, GFit, Gnuplot +using Random, GModelFit, Gnuplot # Calculate histogram of the distribution hh = hist(1 .+ randn(10000), 2 .* randn(10000)) @@ -297,7 +297,7 @@ hh = hist(1 .+ randn(10000), 2 .* randn(10000)) # Prepare domain and data and fit a model dom = CartesianDomain(hh.bins1, hh.bins2) data = Measures(dom, hh.counts, 1.) -model = Model(dom, GFit.Gaussian(1e3, 0, 0, 1, 1, 0)) +model = Model(dom, GModelFit.Gaussian(1e3, 0, 0, 1, 1, 0)) best, fitstats = fit(model, data) dumpjson("ex_Gaussian2D", best, fitstats, data) # hide show((best, fitstats)) # hide @@ -324,7 +324,7 @@ The `SumReducer` component has no parameter. #### Example ```@example abc -using GFit +using GModelFit # Prepare domain and a linear model (with initial guess parameters) dom = Domain(1:5) diff --git a/docs/src/concepts.md b/docs/src/concepts.md index 5366ff3..597e848 100644 --- a/docs/src/concepts.md +++ b/docs/src/concepts.md @@ -1,6 +1,6 @@ # Basic concepts and data types -In order to exploit the **GFit.jl** model expressiveness we need to introduce a few concepts, and the associated data types: +In order to exploit the **GModelFit.jl** model expressiveness we need to introduce a few concepts, and the associated data types: - *Domain*: an N-dimensional grid of points where the model is to be evaluated, it is analogous to the independent varible $\vec{x}$ in the $f(\vec{x})$ notation. It is represented by either: - a [`Domain{N}`](@ref) object for linear domains, i.e. where the coordinates for each of the N dimensions are explicitly specified for all the points; @@ -9,40 +9,40 @@ In order to exploit the **GFit.jl** model expressiveness we need to introduce a - *Measures*: a container for the N-dimensional empirical data and their associated $1\sigma$ Gaussian uncertainties, represented by an object of type [`Measures{N}`](@ref) (further options may be available in the future, such as Poisson counts); -- *Model component*: the atomic building block of a (potentially very complex) model, it is essentially a function used to map a `Domain` or `CartesianDomain` object into a `Vector{Float64}` representing the component evaluation. A component is a structure inheriting from `GFit.AbstractComponent` and is typically characterized by one or more *parameters* (see below). One component's evaluation can also be used as input for another one's calculation, thus inducing a dependency between the two. The **GFit.jl** package provides several [Built-in components](@ref), and new ones can be implemented by the user (see [Custom components](@ref)). The memoization mechanism operates at the component level and aims to avoid unnecessary re-evaluation of the component if none of its parameter values has changed since last evaluation; +- *Model component*: the atomic building block of a (potentially very complex) model, it is essentially a function used to map a `Domain` or `CartesianDomain` object into a `Vector{Float64}` representing the component evaluation. A component is a structure inheriting from `GModelFit.AbstractComponent` and is typically characterized by one or more *parameters* (see below). One component's evaluation can also be used as input for another one's calculation, thus inducing a dependency between the two. The **GModelFit.jl** package provides several [Built-in components](@ref), and new ones can be implemented by the user (see [Custom components](@ref)). The memoization mechanism operates at the component level and aims to avoid unnecessary re-evaluation of the component if none of its parameter values has changed since last evaluation; -- *Parameter*: a single floating point number characterizing a specific aspect for the evaluation of a component (e.g. the slope of a power law or the width of a Gaussian profile). The parameter values are automatically varied during the fitting process until the residuals between the global model evaluation and the empirical data are minimized. A parameter can be fixed to a specific value, limited in an interval, and/or be dynamically calculated (patched) according to the values of other parameters. All parameters are represented by an object of type [`GFit.Parameter`](@ref); +- *Parameter*: a single floating point number characterizing a specific aspect for the evaluation of a component (e.g. the slope of a power law or the width of a Gaussian profile). The parameter values are automatically varied during the fitting process until the residuals between the global model evaluation and the empirical data are minimized. A parameter can be fixed to a specific value, limited in an interval, and/or be dynamically calculated (patched) according to the values of other parameters. All parameters are represented by an object of type [`GModelFit.Parameter`](@ref); - *Model*: is the overall model description, whose evaluation is supposed to be compared to a single `Measures` objects and whose parameters are varied during fitting to reduce the residuals. All models are represented by an object of type [`Model`](@ref) containing a single `Domain` or `CartesianDomain` object representing the domain where the model will be evaluated, and one or more *components* characterizing the model itself. Each component is identified by a unique name (actually a `Symbol`) within a model. - Component dependencies and *main component*: the evaluation of a component, say `A`, may use the output of another component, say `B`, to calculate its output. In this case we say that `A` *depends* on `B`, and therefore `B` needs to be evaluated before `A` (circular dependencies are not allowed, and would raise an error if attempted). The dependencies are automatically identified, and the last component being evaluated is dubbed *main component* since its output represent the overall model evaluation; - *Multi-model*: a `Vector{Model}` containing two or more models, suitable to be compared to a corresponding number of `Measures` objects to perform [Multi-dataset fitting](@ref); -- *Fit statistics*: the purpose of fitting is to minimize the *distance* between the model and the data, as quantified by a proper fit statistic (typically a reduced $\chi^2$ for the Gaussian uncertainties case). Such statistic, as well as other information concerning the fit, are returned by the [`fit()`](@ref) function in a [`GFit.FitStats`](@ref) structure. +- *Fit statistics*: the purpose of fitting is to minimize the *distance* between the model and the data, as quantified by a proper fit statistic (typically a reduced $\chi^2$ for the Gaussian uncertainties case). Such statistic, as well as other information concerning the fit, are returned by the [`fit()`](@ref) function in a [`GModelFit.FitStats`](@ref) structure. -- *Model snapshot*: the best fit model, as well as the best fit parameter values and associated uncertainties, are returned by the [`fit()`](@ref) function as a [`GFit.ModelSnapshot`](@ref) structure, namely a *frozen snapshot* of a `Model` object. +- *Model snapshot*: the best fit model, as well as the best fit parameter values and associated uncertainties, are returned by the [`fit()`](@ref) function as a [`GModelFit.ModelSnapshot`](@ref) structure, namely a *frozen snapshot* of a `Model` object. -- Standard Julia functions can be used by **GFit.jl** in two different contexts: +- Standard Julia functions can be used by **GModelFit.jl** in two different contexts: - to calculate the value of a `Parameter` as a function of other `Parameter`'s values. In this case the parameters are said to be *patched*, or linked, since there is a constraint between their values. Two (or more) parameters may be patched within the same model, or across models when performing [Multi-dataset fitting](@ref); - to define a model component using a standard Julia mathematical expression involving `Parameter`s values or other components. - In both cases the Julia function should be properly encapsulated in a [`GFit.FunctDesc`](@ref) structure, which is typically generated using the [`@λ`](@ref) convenience macro. + In both cases the Julia function should be properly encapsulated in a [`GModelFit.FunctDesc`](@ref) structure, which is typically generated using the [`@λ`](@ref) convenience macro. -- *Minimizer*: the **GFit.jl** package provides just the tools to define and manipulate a model, but the actual fitting (namely, the minimization of the residuals) is performed by an external *minimizer* library. Two minimizers are currently available: +- *Minimizer*: the **GModelFit.jl** package provides just the tools to define and manipulate a model, but the actual fitting (namely, the minimization of the residuals) is performed by an external *minimizer* library. Two minimizers are currently available: - [LsqFit](https://github.com/JuliaNLSolvers/LsqFit.jl): a pure-Julia minimizer; - [CMPFit](https://github.com/gcalderone/CMPFit.jl): a C minimizer wrapped in a Julia package. - Both are automatically installed with **GFit.jl**, and `LsqFit` is the default choice (unless otherwise specified in the [`fit()`](@ref) function call). + Both are automatically installed with **GModelFit.jl**, and `LsqFit` is the default choice (unless otherwise specified in the [`fit()`](@ref) function call). -- *Mock data*: evaluating a a model may be useful even before actual data are available, e.g. to test its robustness and capabilities. To this purpose **GFit.jl** provides the [`GFit.mock()`](@ref) function which is able to generate mock data set(s) using a (multi-)model as ground truth, and add a random noise to simulate the measurement process. This functionality is used in some of the examples presented in the next sections. +- *Mock data*: evaluating a a model may be useful even before actual data are available, e.g. to test its robustness and capabilities. To this purpose **GModelFit.jl** provides the [`GModelFit.mock()`](@ref) function which is able to generate mock data set(s) using a (multi-)model as ground truth, and add a random noise to simulate the measurement process. This functionality is used in some of the examples presented in the next sections. -- *Serialization*: a few structures (such as [`GFit.ModelSnapshot`](@ref), [`GFit.FitStats`](@ref) and [`Measures{N}`](@ref)) can be *serialized*, i.e. stored in a file, and later *de-serialized* in a separata Julia session. This is useful when the best fit model and associated informations must be saved for a later use, without the need to re-run the fitting. +- *Serialization*: a few structures (such as [`GModelFit.ModelSnapshot`](@ref), [`GModelFit.FitStats`](@ref) and [`Measures{N}`](@ref)) can be *serialized*, i.e. stored in a file, and later *de-serialized* in a separata Julia session. This is useful when the best fit model and associated informations must be saved for a later use, without the need to re-run the fitting. ## How to access the data structures -**GFit.jl** interface aims to be easy to use and remember, and the number of exported function is purposely kept to a minimum. As a consequence, many of the above mentioned data structures are accessible using either indexing (as in dictionary or vectors) or as field of a `struct`-like interface, starting from a single [`Model`](@ref) or a `Vector{Model}` object. In particular: +**GModelFit.jl** interface aims to be easy to use and remember, and the number of exported function is purposely kept to a minimum. As a consequence, many of the above mentioned data structures are accessible using either indexing (as in dictionary or vectors) or as field of a `struct`-like interface, starting from a single [`Model`](@ref) or a `Vector{Model}` object. In particular: - a *Multi-model* is a `Vector{Model}` with the inidividual elements accessible via the usual indexing syntax; - a `Model` object can be considered as a dictionary of components, with `Symbol` keys. The `keys()` function will return the name of components in the model; -- a component is a structure, either built-in (see [Built-in components](@ref)) or implemented by the user ([Custom components](@ref)). One or more structure fields are supposed to represent the component parameters (with objects of type [`GFit.Parameter`](@ref)); -- The fields of a component structure, as well as the fields of the [`GFit.Parameter`](@ref)) structures are accessed using the standard dot (`.`) notation. +- a component is a structure, either built-in (see [Built-in components](@ref)) or implemented by the user ([Custom components](@ref)). One or more structure fields are supposed to represent the component parameters (with objects of type [`GModelFit.Parameter`](@ref)); +- The fields of a component structure, as well as the fields of the [`GModelFit.Parameter`](@ref)) structures are accessed using the standard dot (`.`) notation. As an example, the syntax to access the value of a parameter in a single model case is: `model[:Component].param.val`. In a multi-model case it is: `multi[1][:Component].param.val`. diff --git a/docs/src/customcomp.md b/docs/src/customcomp.md index ed2cb10..7dffbdb 100644 --- a/docs/src/customcomp.md +++ b/docs/src/customcomp.md @@ -18,7 +18,7 @@ struct MyComponent <: AbstractComponent end ``` (see below for a complete example). -Alternatively, the parameters may be specified as a single field of type `OrderedDict{Symbol, Parameter}` (see the [`Polynomial`](https://github.com/gcalderone/GFit.jl/blob/master/src/components/Polynomial.jl) component for an example); +Alternatively, the parameters may be specified as a single field of type `OrderedDict{Symbol, Parameter}` (see the [`Polynomial`](https://github.com/gcalderone/GModelFit.jl/blob/master/src/components/Polynomial.jl) component for an example); - the `evaluate!` function shall be extended to provide the component-specific code for evaluation. Specifically, the `evaluate!` function should replace the content of a `buffer::Vector{Float64}` with the outcome of the new component evaluation, given the numerical values for the parameters, e.g. @@ -65,18 +65,18 @@ println() # hide The following example shows how to implement a component aimed to interpolate the theoretical model onto a specific empirical domain, with the only parameter being a global scaling factor: ```@example abc -using GFit, Interpolations -import GFit.prepare!, GFit.evaluate! +using GModelFit, Interpolations +import GModelFit.prepare!, GModelFit.evaluate! # Define the component structure and constructor -struct Interpolator <: GFit.AbstractComponent +struct Interpolator <: GModelFit.AbstractComponent theory_x::Vector{Float64} theory_y::Vector{Float64} interp_y::Vector{Float64} # will contain the interpolated values - scale::GFit.Parameter + scale::GModelFit.Parameter function Interpolator(theory_x, theory_y) - scale = GFit.Parameter(1) + scale = GModelFit.Parameter(1) scale.low = 0 # ensure scale parameter is positive interp_y = Vector{Float64}() # this will be populated in prepare!() return new(theory_x, theory_y, interp_y, scale) @@ -104,7 +104,7 @@ The following code shows how to prepare a `Model` including the interpolated the ```@example abc dom = Domain(obs_x) model = Model(dom, :theory => Interpolator(theory_x, theory_y), - :background => GFit.OffsetSlope(1., 0., 0.2), + :background => GModelFit.OffsetSlope(1., 0., 0.2), :main => SumReducer(:theory, :background)) data = Measures(dom, obs_y, 0.2) best, fitstats = fit(model, data) diff --git a/docs/src/examples.md b/docs/src/examples.md index 15b35b7..b75f7ad 100644 --- a/docs/src/examples.md +++ b/docs/src/examples.md @@ -6,8 +6,8 @@ x = Domain(1:0.05:10) model = Model(x, :offset => 4, - :line1 => GFit.Gaussian(1.1 , 4.4, 0.51), - :line2 => GFit.Gaussian(0.52, 5.5, 1.2 )) + :line1 => GModelFit.Gaussian(1.1 , 4.4, 0.51), + :line2 => GModelFit.Gaussian(0.52, 5.5, 1.2 )) using Random rng = MersenneTwister(0); @@ -33,10 +33,10 @@ using Gnuplot ```julia dom = CartesianDomain(-5:0.1:5, -4:0.1:4) model = Model(dom, - :background => GFit.OffsetSlope(0, 0, 0., 2., 3.), - :psf => GFit.Gaussian(100., 0., 0., 1, 0.3, 15), + :background => GModelFit.OffsetSlope(0, 0, 0., 2., 3.), + :psf => GModelFit.Gaussian(100., 0., 0., 1, 0.3, 15), :main => SumReducer(:background, :psf)) -data = GFit.mock(Measures, model) +data = GModelFit.mock(Measures, model) ret1 = fit(model, data) ``` diff --git a/docs/src/index.md b/docs/src/index.md index 87b6c34..79bb3ab 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -2,12 +2,12 @@ include("setup.jl") ``` -# Gfit.jl +# GModelFit.jl ## A model fitting framework for Julia. -[![Stars](https://img.shields.io/github/stars/gcalderone/GFit.jl?style=social)](https://github.com/gcalderone/GFit.jl) +[![Stars](https://img.shields.io/github/stars/gcalderone/GModelFit.jl?style=social)](https://github.com/gcalderone/GModelFit.jl) -**Gfit.jl** is a general purpose, data-driven model fitting framework for Julia. +**GModelFit.jl** is a general purpose, data-driven model fitting framework for Julia. It provides the basic tools to define, interactively manipulate and efficiently evaluate a (possibly very complex) model, and to fit the latter to empirical data. The main functionalities are: - it handles datasets of any dimensionality; @@ -20,16 +20,16 @@ It provides the basic tools to define, interactively manipulate and efficiently - it supports different minimizers ([LsqFit](https://github.com/JuliaNLSolvers/LsqFit.jl) and [CMPFit](https://github.com/gcalderone/CMPFit.jl)), both aimed to carry out [non-linear least squares](https://en.wikipedia.org/wiki/Non-linear_least_squares) minimization (see [Minimizers](@ref)); - it provides facilities for interactive fitting and quick plotting (see [Quick plot (1D)](@ref)). -The fitting process involves the automatic variation of the parameter values, subject to the user defined constraints, until the differences between the evaluated model and the empirical data are minimized. The implementation details depends on the chosen minimizer. The purpose of **Gfit.jl** is thus to act as an interface between the high-level model definition and manipulation (facing the user), and the low-level implementation details (facing the minimizer). +The fitting process involves the automatic variation of the parameter values, subject to the user defined constraints, until the differences between the evaluated model and the empirical data are minimized. The implementation details depends on the chosen minimizer. The purpose of **GModelFit.jl** is thus to act as an interface between the high-level model definition and manipulation (facing the user), and the low-level implementation details (facing the minimizer). -Note that the main purpose of **GFit.jl** is to allow easy manipulation of complex models, and that there may be little advantage in using it for a simple linear regression or for models involving just a single parameter, although it is definitely possible to use it also in these cases. +Note that the main purpose of **GModelFit.jl** is to allow easy manipulation of complex models, and that there may be little advantage in using it for a simple linear regression or for models involving just a single parameter, although it is definitely possible to use it also in these cases. ## Installation In the Julia REPL type: ```julia-repl -julia> ]add GFit +julia> ]add GModelFit ``` The `]` character starts the Julia [package manager](https://julialang.github.io/Pkg.jl/v1/getting-started.html#Basic-Usage-1). Hit backspace key to return to Julia prompt. @@ -41,7 +41,7 @@ julia> ]add Gnuplot ## Workflow -The typical workflow to use **GFit.jl** is as follows: +The typical workflow to use **GModelFit.jl** is as follows: - Wrap empirical data domain and measures into one (ore more) `Domain` and `Measures` object(s); - Create a `Model` object and build it by adding components or mathematical expressions, each representing a specific *aspect* of the theoretical model; - Optionally set initial guess parameter values, define constraints between model parameters, etc.; @@ -51,14 +51,14 @@ The typical workflow to use **GFit.jl** is as follows: A very simple example showing the above workflow is: ```@example abc -using GFit +using GModelFit # Prepare vectors with domain points, empirical measures and their uncertainties x = [0.1, 1.1, 2.1, 3.1, 4.1] meas = [6.29, 7.27, 10.41, 18.67, 25.3] unc = [1.1, 1.1, 1.1, 1.2, 1.2] -# Prepare GFit input objects +# Prepare GModelFit input objects dom = Domain(x) data = Measures(dom, meas, unc) @@ -71,7 +71,7 @@ best, fitstats = fit(model, data) nothing # hide ``` -The **GFit.jl** package implements a `show` method for many of the data types involved, hence the above code results in the following output: +The **GModelFit.jl** package implements a `show` method for many of the data types involved, hence the above code results in the following output: ```@example abc show((best, fitstats)) # hide ``` diff --git a/docs/src/minimizers.md b/docs/src/minimizers.md index 94b9ee1..182a831 100644 --- a/docs/src/minimizers.md +++ b/docs/src/minimizers.md @@ -1,30 +1,30 @@ # Minimizers -The **GFit.jl** main purpose is to act as an high-level interface between the user and the underlying minimizer. +The **GModelFit.jl** main purpose is to act as an high-level interface between the user and the underlying minimizer. Currently, two [non-linear least squares](https://en.wikipedia.org/wiki/Non-linear_least_squares) minimizers are supported: - [LsqFit](https://github.com/JuliaNLSolvers/LsqFit.jl); - [CMPFit](https://github.com/gcalderone/CMPFit.jl); and more may be added in the future. -To specify a minimizer simply use the `minimizer=` keyword when invoking the [`fit()`](@ref) function, e.g. `minimizer=GFit.lsqfit()` or `minimizer=GFit.cmpfit()`. If the keyword is not provided the `lsqfit()` minimizer is used. +To specify a minimizer simply use the `minimizer=` keyword when invoking the [`fit()`](@ref) function, e.g. `minimizer=GModelFit.lsqfit()` or `minimizer=GModelFit.cmpfit()`. If the keyword is not provided the `lsqfit()` minimizer is used. -There is also a dummy minimizer, `GFit.dry()`, whose purpose is to compare the model and the data, and to generate a `FitStats` object without modifying the model parameters. The dry minimizer is used by the [`compare()`](@ref) function. +There is also a dummy minimizer, `GModelFit.dry()`, whose purpose is to compare the model and the data, and to generate a `FitStats` object without modifying the model parameters. The dry minimizer is used by the [`compare()`](@ref) function. ### Examples ```@example abc -using GFit +using GModelFit dom = Domain(1:0.1:50) model = Model(dom, :main => @λ (x, T=3.14) -> sin.(x ./ T) ./ (x ./ T)) -data = GFit.mock(Measures, model, seed=1) -best, fitstats = fit(model, data, minimizer=GFit.lsqfit()) +data = GModelFit.mock(Measures, model, seed=1) +best, fitstats = fit(model, data, minimizer=GModelFit.lsqfit()) println(); # hide ``` or ```@example abc -best, fitstats = fit(model, data, minimizer=GFit.cmpfit()) +best, fitstats = fit(model, data, minimizer=GModelFit.cmpfit()) println(); # hide ``` @@ -38,13 +38,13 @@ The `cmpfit()` minimizer allows to specify several options to fine-tune the mini - the `Δfitstat_threshold` allows to specify a threshold on the difference in fit statistics before and after the `mpfit()` execution to stop the fitting. If such difference is greater than the `Δfitstat_threshold` the minimization process continue regardless of the number of iterations. ```@example abc -using GFit +using GModelFit dom = Domain(1:0.1:50) model = Model(dom, :main => @λ (x, T=3.14) -> sin.(x ./ T) ./ (x ./ T)) -data = GFit.mock(Measures, model, seed=1) +data = GModelFit.mock(Measures, model, seed=1) # Set minimizer options -mzer = GFit.cmpfit() +mzer = GModelFit.cmpfit() mzer.config.maxiter = 1000 mzer.Δfitstat_threshold = 1e-8 diff --git a/docs/src/misc.md b/docs/src/misc.md index 9a7817d..6e44532 100644 --- a/docs/src/misc.md +++ b/docs/src/misc.md @@ -6,18 +6,18 @@ include("setup.jl") ## 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 [`GFit.mock()`](@ref) function, whose purpose is to generate a mock dataset which simulates a measurement process by adding random noise to the foreseen ground-truth. +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()`](@ref) function, whose purpose is to generate a mock dataset which simulates a measurement process by adding random noise to the foreseen ground-truth. ### Example ```@example abc -using GFit +using GModelFit dom = Domain(1:0.1:50) model = Model(dom, :main => @λ (x, T=3.14) -> sin.(x ./ T) ./ (x ./ T)) # Generate a mock dataset -data = GFit.mock(Measures, model, seed=1) +data = GModelFit.mock(Measures, model, seed=1) # Fit model against the mock dataset best, fitstats = fit(model, data) @@ -27,48 +27,48 @@ best, fitstats = fit(model, data) ## Serialization -A few structures, namely [`GFit.ModelSnapshot`](@ref), [`GFit.FitStats`](@ref) and [`Measures{N}`](@ref), 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. +A few structures, namely [`GModelFit.ModelSnapshot`](@ref), [`GModelFit.FitStats`](@ref) and [`Measures{N}`](@ref), 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 **GFit.jl** objects and serialized them in a file. +In the following we will generate a few **GModelFit.jl** objects and serialized them in a file. ```@example abc -using GFit +using GModelFit dom = Domain(1:0.1:50) model = Model(dom, :main => @λ (x, T=3.14) -> sin.(x ./ T) ./ (x ./ T)) -data = GFit.mock(Measures, model, seed=1) +data = GModelFit.mock(Measures, model, seed=1) best, fitstats = fit(model, data) # Serialize objects and save in a file -GFit.serialize("save_for_future_use.json", best, fitstats, data) +GModelFit.serialize("save_for_future_use.json", best, fitstats, data) println(); # hide ``` The same objects can be de-serialized in a different Julia session: ```@example abc -using GFit -best, fitstats, data = GFit.deserialize("save_for_future_use.json") +using GModelFit +best, fitstats, data = GModelFit.deserialize("save_for_future_use.json") ``` ## Quick plot (1D) -The **GFit.jl** package implements [**Gnuplot.jl**](https://github.com/gcalderone/Gnuplot.jl/) recipes to display plots of `Measures{1}` and `ModelSnapshot` objects., e.g.: +The **GModelFit.jl** package implements [**Gnuplot.jl**](https://github.com/gcalderone/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: ```@example abc -using GFit +using GModelFit dom = Domain(0:0.01:5) -model = Model(dom, :bkg => GFit.OffsetSlope(1, 1, 0.1), - :l1 => GFit.Gaussian(1, 2, 0.2), - :l2 => GFit.Gaussian(1, 3, 0.4), +model = Model(dom, :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 = GFit.mock(Measures, model) +data = GModelFit.mock(Measures, model) best, res = fit(model, data) println(); # hide ``` diff --git a/docs/src/multifit.md b/docs/src/multifit.md index f93717c..a068ec2 100644 --- a/docs/src/multifit.md +++ b/docs/src/multifit.md @@ -5,7 +5,7 @@ include("setup.jl") # Multi-dataset fitting -**GFit.jl** is able to simultaneously fit several models against a corresponding number of datasets, while placing constraints among the models. Typical use cases are: +**GModelFit.jl** is able to simultaneously fit several models against a corresponding number of datasets, while placing constraints among the models. Typical use cases are: - a single phenomenon is observed with two (or more) instruments/detectors; - a single phenomenon is observed at different times; @@ -13,12 +13,12 @@ Fitting multiple datasets simultaneously may provide tighter constraints on the To perform a multi-dataset fitting we should create one `Model` for each dataset in the usual way, collect them in a `Vector{Model}`, and define patch constraints among models. The following example shows how to fit two Gaussian curves under the hypotesis that the center and normalization parameters are the same: ```@example abc -using GFit +using GModelFit # Create domain, individual models and the Vector{Model} container dom = Domain(-5.:5) -model1 = Model(dom, GFit.Gaussian(1, 0., 1.)) -model2 = Model(dom, GFit.Gaussian(1, 0., 1.)) +model1 = Model(dom, GModelFit.Gaussian(1, 0., 1.)) +model2 = Model(dom, GModelFit.Gaussian(1, 0., 1.)) multi = [model1, model2] # Patch parameters diff --git a/docs/src/parameter.md b/docs/src/parameter.md index 12583be..374acf2 100644 --- a/docs/src/parameter.md +++ b/docs/src/parameter.md @@ -4,13 +4,13 @@ include("setup.jl") # Parameter constraints -Models are characterized by *parameters* (see [Basic concepts and data types](@ref)) whose values are modified during fitting until a convergence criterion is met, and the *best fit* values are identified. In many cases, however, the parameters can not vary arbitrarily but should satisfy some constraints for their values to be meaningful. **GFit.jl** supports the definition of constraints by fixing the parameter to a specific value, limiting the value in a user defined range, or by dynamically calculating its value using a mathematical expression involving other parameter values. In the latter case the parameter is not free to vary in the fit since its actual value is determined by the patch constraint, hence it is dubbed a *patched* parameter. Such unused parameter can optionally be repurposed as a new free parameter in a *parametrized patch expression* (see example below). +Models are characterized by *parameters* (see [Basic concepts and data types](@ref)) whose values are modified during fitting until a convergence criterion is met, and the *best fit* values are identified. In many cases, however, the parameters can not vary arbitrarily but should satisfy some constraints for their values to be meaningful. **GModelFit.jl** supports the definition of constraints by fixing the parameter to a specific value, limiting the value in a user defined range, or by dynamically calculating its value using a mathematical expression involving other parameter values. In the latter case the parameter is not free to vary in the fit since its actual value is determined by the patch constraint, hence it is dubbed a *patched* parameter. Such unused parameter can optionally be repurposed as a new free parameter in a *parametrized patch expression* (see example below). -An important concept to bear in mind is that the [`GFit.Parameter`](@ref) structure provides two field for the associated numerical value: +An important concept to bear in mind is that the [`GModelFit.Parameter`](@ref) structure provides two field for the associated numerical value: - `val`: is the parameter value which is being varied by the minimizer during fitting. The value set before the fitting is the *guess* value. The value after fitting is the *best fit* one; - `actual`: is the result of the patch expression evaluation, and the actual value used when evaluating a component. Note that this value will be overwitten at each model evaluation, hence setting this field has no effect. The `val` and `actual` values are identical if no patch constraint has been defined. -A parameter constraint is defined by explicitly modifiying the fields of the corresponding [`GFit.Parameter`](@ref) structure. More specifically: +A parameter constraint is defined by explicitly modifiying the fields of the corresponding [`GModelFit.Parameter`](@ref) structure. More specifically: 1. to set a parameter to a specific value: set the `val` field to the numeric value and set the `fixed` field to `true`; 1. to set a parameter value range: set one or both the `low` and `high` fields (default values are `-Inf` and `+Inf` respectively); 1. to constraint a parameter to have the same numerical value as another one with the same name (but in another component): set the `patch` value to the component name (it must be a `Symbol`). In this case the parameter is assumed to be fixed; @@ -24,12 +24,12 @@ The following examples show how to define constraints for each of the afore-ment We will consider a model for a 1D domain consisting of the sum of a linear background component (named `bkg`) and two Gaussian-shaped features (`l1` and `l2`): ```@example abc -using GFit +using GModelFit dom = Domain(0:0.1:5) -model = Model(dom, :bkg => GFit.OffsetSlope(1, 1, 0.1), - :l1 => GFit.Gaussian(1, 2, 0.2), - :l2 => GFit.Gaussian(1, 3, 0.4), +model = Model(dom, :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)) println() # hide ``` @@ -64,7 +64,7 @@ println() # hide We can fit the model against a mock dataset (see [Generate mock datasets](@ref)): ```@example abc -data = GFit.mock(Measures, model) +data = GModelFit.mock(Measures, model) best, fitstats = fit(model, data) dumpjson("ex_Parameter", best, fitstats, data) # hide show((best, fitstats)) # hide diff --git a/docs/src/setup.jl b/docs/src/setup.jl index b641536..5670f83 100644 --- a/docs/src/setup.jl +++ b/docs/src/setup.jl @@ -56,6 +56,6 @@ end function dumpjson(file, args...) - restored = GFit.deserialize(GFit.serialize("assets/$(file).json", args...)) + restored = GModelFit.deserialize(GModelFit.serialize("assets/$(file).json", args...)) # comparedata(restored, [args...]) end diff --git a/src/GFit.jl b/src/GFit.jl index 67a911f..07bd04e 100644 --- a/src/GFit.jl +++ b/src/GFit.jl @@ -1,4 +1,4 @@ -module GFit +module GModelFit using Printf, PrettyTables using Statistics, Distributions @@ -43,7 +43,7 @@ A "Julia function" descriptor containing the reference to the function itself, a ### Example: ``` -julia> f = GFit.FunctDesc((x, p=0) -> x + p, # actual function definition +julia> f = GModelFit.FunctDesc((x, p=0) -> x + p, # actual function definition "(x, p=0) -> x + p", # string representation [:x], # vector of argument namess [:(p = 0)]) # vector of `Expr` with arguments default values @@ -84,7 +84,7 @@ macro λ(_expr) def = splitdef(expr) args = convert(Vector{Symbol}, filter(x -> isa(x, Symbol), def[:args])) optargs = convert(Vector{Expr} , filter(x -> isa(x, Expr) , def[:args])) - return esc(:(GFit.FunctDesc($expr, string($(QuoteNode(expr))), $args, $optargs))) + return esc(:(GModelFit.FunctDesc($expr, string($(QuoteNode(expr))), $args, $optargs))) end @@ -640,7 +640,7 @@ end """ ModelSnapshot -A structure containing a *snapshot* (i.e. a "*frozen*" state) of a `Model`. A snapshot contains the same parameters and component evaluations of the original model, and provide the same user interface. Moreover, a `ModelSnapshot` can be serialized to a file and de-serialized in another Julia session (see `GFit.serialize()`). +A structure containing a *snapshot* (i.e. a "*frozen*" state) of a `Model`. A snapshot contains the same parameters and component evaluations of the original model, and provide the same user interface. Moreover, a `ModelSnapshot` can be serialized to a file and de-serialized in another Julia session (see `GModelFit.serialize()`). The best fit model and best fit parameter values returned as a `ModelSnapshot` object by the `fit()` function. """ diff --git a/src/components/FComp.jl b/src/components/FComp.jl index 5ea1771..35f4d29 100644 --- a/src/components/FComp.jl +++ b/src/components/FComp.jl @@ -47,7 +47,7 @@ end # ==================================================================== -struct FCompv <: GFit.AbstractComponent +struct FCompv <: GModelFit.AbstractComponent funct::Function deps::Vector{Symbol} params::OrderedDict{Symbol, Parameter} diff --git a/src/gnuplot_recipe.jl b/src/gnuplot_recipe.jl index c1022af..7be724c 100644 --- a/src/gnuplot_recipe.jl +++ b/src/gnuplot_recipe.jl @@ -6,14 +6,14 @@ Gnuplot.recipe(data::Measures{1}) = data=Gnuplot.DatasetBin(coords(domain(data)), values(data), uncerts(data)), plot="with yerr t 'Data' lc rgb 'gray'") -Gnuplot.recipe(model::Model) = Gnuplot.recipe(GFit.ModelSnapshot(model)) +Gnuplot.recipe(model::Model) = Gnuplot.recipe(GModelFit.ModelSnapshot(model)) -function Gnuplot.recipe(model::GFit.ModelSnapshot) +function Gnuplot.recipe(model::GModelFit.ModelSnapshot) @assert ndims(domain(model)) == 1 out = Vector{Gnuplot.PlotElement}() for (k,v) in model.buffers (k == model.maincomp) && continue - #isa(v.comp, GFit.FComp) || isa(v.comp, GFit.SumReducer) || continue + #isa(v.comp, GModelFit.FComp) || isa(v.comp, GModelFit.SumReducer) || continue push!(out, Gnuplot.PlotElement( data=Gnuplot.DatasetBin(coords(domain(model)), model(k)), plot="with lines t '$(k)'")) diff --git a/src/serialize.jl b/src/serialize.jl index 3d0b7d1..bb45653 100644 --- a/src/serialize.jl +++ b/src/serialize.jl @@ -67,35 +67,35 @@ end """ - GFit.serialize(filename::String, ::ModelSnapshot[, ::FitStats[, ::Measures]]; compress=false) - GFit.serialize(filename::String, ::Vector{ModelSnapshot}[, ::FitStats[, ::Vector{Measures}]]; compress=false) + GModelFit.serialize(filename::String, ::ModelSnapshot[, ::FitStats[, ::Measures]]; compress=false) + GModelFit.serialize(filename::String, ::Vector{ModelSnapshot}[, ::FitStats[, ::Vector{Measures}]]; compress=false) -Serialize GFit object(s) using a JSON format. The serializable objects are: +Serialize GModelFit object(s) using a JSON format. The serializable objects are: - `ModelSnapshot` and `Vector{ModelSnapshot}` (mandatory argument); - `FitStats` (optional); - `Measures` and and `Vector{Measures}` (optional); If `compress=true` the resulting JSON file will be compressed using GZip. -Objects can later be deserialized in a different Julia session with `GFit.deserialize`. +Objects can later be deserialized in a different Julia session with `GModelFit.deserialize`. -Note: The `GFit.serialize` function also accepts `Model` and `Vector{Model}` but they will be internally converted to `ModelSnapshot`(s). +Note: The `GModelFit.serialize` function also accepts `Model` and `Vector{Model}` but they will be internally converted to `ModelSnapshot`(s). ## Example: ```julia-repl -# Create GFit objects -using GFit +# Create GModelFit objects +using GModelFit dom = Domain(1:5) model = Model(dom, :linear => @λ (x, b=2, m=0.5) -> (b .+ x .* m)) data = Measures(dom, [4.01, 7.58, 12.13, 19.78, 29.04], 0.4) best, fitstats = fit(model, data) # Serialize objects and save in a file -GFit.serialize("my_snapshot.json", best, fitstats, data) +GModelFit.serialize("my_snapshot.json", best, fitstats, data) # Restore objects (possibly in a different Julia session) -using GFit -(best, fitstats, data) = GFit.deserialize("my_snapshot.json") +using GModelFit +(best, fitstats, data) = GModelFit.deserialize("my_snapshot.json") ``` """ function serialize(filename::String, args...; compress=false) @@ -158,24 +158,24 @@ function _deserialize(dd::AbstractDict) end if "_structtype" in keys(dd) - if dd["_structtype"] == "GFit.PV.PVComp{GFit.Parameter}" + if dd["_structtype"] == "GModelFit.PV.PVComp{GModelFit.Parameter}" # tmp = OrderedDict{Symbol, Int}() # for (k, v) in dd["params"] # tmp[Symbol(k)] = v # end return PVComp{Parameter}(_deserialize(dd["params"]), _deserialize(dd["data"])) - elseif dd["_structtype"] == "GFit.PV.PVModel{GFit.Parameter}" - # tmp = OrderedDict{Symbol, PV.PVComp{GFit.Parameter}}() + elseif dd["_structtype"] == "GModelFit.PV.PVModel{GModelFit.Parameter}" + # tmp = OrderedDict{Symbol, PV.PVComp{GModelFit.Parameter}}() # for (k, v) in dd["comps"] # tmp[Symbol(k)] = _deserialize(v) # end return PVModel{Parameter}(_deserialize(dd["comps"]), _deserialize(dd["data"])) - elseif dd["_structtype"] == "GFit.FunctDesc" + elseif dd["_structtype"] == "GModelFit.FunctDesc" return FunctDesc(deserialized_function, _deserialize(dd["display"]), _deserialize(dd["args"]), _deserialize(dd["optargs"])) - elseif dd["_structtype"] == "GFit.Parameter" + elseif dd["_structtype"] == "GModelFit.Parameter" return Parameter(_deserialize(dd["val"]), _deserialize(dd["low"]), _deserialize(dd["high"]), @@ -184,14 +184,14 @@ function _deserialize(dd::AbstractDict) _deserialize(dd["mpatch"]), _deserialize(dd["actual"]), _deserialize(dd["unc"])) - elseif dd["_structtype"] == "GFit.ModelSnapshot" + elseif dd["_structtype"] == "GModelFit.ModelSnapshot" return ModelSnapshot(_deserialize(dd["domain"]), _deserialize(dd["params"]), _deserialize(dd["buffers"]), _deserialize(dd["maincomp"]), _deserialize(dd["comptypes"]), _deserialize(dd["show"])) - elseif dd["_structtype"] == "GFit.FitStats" + elseif dd["_structtype"] == "GModelFit.FitStats" return FitStats(_deserialize(dd["timestamp"]), _deserialize(dd["elapsed"]), _deserialize(dd["ndata"]), @@ -199,7 +199,7 @@ function _deserialize(dd::AbstractDict) _deserialize(dd["dof"]), _deserialize(dd["fitstat"]), _deserialize(dd["status"])) - elseif dd["_structtype"] == "GFit.MinimizerStatus" + elseif dd["_structtype"] == "GModelFit.MinimizerStatus" return MinimizerStatus(MinimizerStatusCode(_deserialize(dd["code"])), _deserialize(dd["message"]), _deserialize(dd["internal"])) diff --git a/src/show.jl b/src/show.jl index 75b759b..2325a91 100644 --- a/src/show.jl +++ b/src/show.jl @@ -107,7 +107,7 @@ function preparetable(comp::AbstractComponent; cname::String="?", cfixed=false) fixed = Vector{Bool}() ctype = split(string(typeof(comp)), ".") - (ctype[1] == "GFit") && (ctype = ctype[2:end]) + (ctype[1] == "GModelFit") && (ctype = ctype[2:end]) ctype = join(ctype, ".") for (pname, param) in getparams(comp) diff --git a/src/utils.jl b/src/utils.jl index fc78931..44bd460 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -1,4 +1,4 @@ -version() = Pkg.TOML.parsefile(joinpath(pkgdir(GFit), "Project.toml"))["version"] +version() = Pkg.TOML.parsefile(joinpath(pkgdir(GModelFit), "Project.toml"))["version"] function ensure_file_extension(_filename, _ext) @@ -20,7 +20,7 @@ function print_param_covariance(fitres::FitStats; @assert isa(fitres.status.internal, CMPFit.Result) "Minimizer is not CMPFit" parnames = String[] - if isa(fitres.bestfit, Vector{GFit.HashHashVector{GFit.Parameter}}) + if isa(fitres.bestfit, Vector{GModelFit.HashHashVector{GModelFit.Parameter}}) for i in 1:length(fitres.bestfit) for (cname, hv) in fitres.bestfit[i] for (pname, par) in hv diff --git a/test/runtests.jl b/test/runtests.jl index fea7ef4..d3a3adf 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,4 @@ -using Random, Test, GFit, GFit.PV +using Random, Test, GModelFit, GModelFit.PV # Test Model mm = PVModel{Float64}() @@ -52,14 +52,14 @@ res = fit(model, data) # ==================================================================== x = 0:0.1:5 model = Model(Domain(x), :parabola => @λ (x, a2=1, a1=1, a0=5) -> @. (a2 * x^2 + a1 * x + a0)) -res = fit(model, GFit.mock(Measures, model, seed=1)) +res = fit(model, GModelFit.mock(Measures, model, seed=1)) # @gp x y "w l t 'True model'" x values(data) uncerts(data) "w yerr t 'Data'" x model() "w l t 'Best fit'" # ==================================================================== x = 0:0.1:5 model = Model(Domain(x), @λ (x, a2=1, a1=1, a0=5) -> @. (a2 * x^2 + a1 * x + a0)) -res = fit(model, GFit.mock(Measures, model, seed=1)) +res = fit(model, GModelFit.mock(Measures, model, seed=1)) # ==================================================================== @@ -67,7 +67,7 @@ f = @λ (x, p1=1, p2=1.e-3, p3=1e-6, p4=4, p5=5) -> @. (p1 + p2 * x + p3 * x^2 + p4 * sin(p5 * x)) * cos(x) x = 1.:50:10000 model = Model(Domain(x), f) -res = fit(model, GFit.mock(Measures, model, seed=1)) +res = fit(model, GModelFit.mock(Measures, model, seed=1)) # ==================================================================== @@ -81,56 +81,56 @@ model = Model(Domain(x), :f2 => f2, :f3 => f3, :main => @λ (x, f1, f2, f3) -> (f1 .+ f2) .* f3) -res = fit(model, GFit.mock(Measures, model, seed=1)) +res = fit(model, GModelFit.mock(Measures, model, seed=1)) # Same results with model = Model(Domain(x), :f1 => f1) model[:f2] = f2 model[:f3] = f3 model[:main] = @λ (x, f1, f2, f3) -> (f1 .+ f2) .* f3 -res = fit(model, GFit.mock(Measures, model, seed=1)) +res = fit(model, GModelFit.mock(Measures, model, seed=1)) # ==================================================================== x = 0:0.05:6 model = Model(Domain(x), - :l1 => GFit.Gaussian(1, 2, 0.2), - :l2 => GFit.Gaussian(1, 3, 0.5), - :bkg => GFit.OffsetSlope(0.5, 1, 0.1), + :l1 => GModelFit.Gaussian(1, 2, 0.2), + :l2 => GModelFit.Gaussian(1, 3, 0.5), + :bkg => GModelFit.OffsetSlope(0.5, 1, 0.1), :main => SumReducer(:l1, :l2, :bkg)); -res = fit(model, GFit.mock(Measures, model, seed=1)) +res = fit(model, GModelFit.mock(Measures, model, seed=1)) # Tie two parameters model[:l2].norm.patch = :l1 -res = fit(model, GFit.mock(Measures, model, seed=1)) +res = fit(model, GModelFit.mock(Measures, model, seed=1)) # Patch one parameter to another via a λ function model[:l2].norm.patch = @λ (m, v) -> v + m[:l1].norm -res = fit(model, GFit.mock(Measures, model, seed=1)) +res = fit(model, GModelFit.mock(Measures, model, seed=1)) # ==================================================================== x = 0:0.05:6 model1 = Model(Domain(x), - :l1 => GFit.Gaussian(1, 2, 0.2), - :l2 => GFit.Gaussian(1, 3, 0.5), - :bkg => GFit.OffsetSlope(0.5, 1, 0.1), + :l1 => GModelFit.Gaussian(1, 2, 0.2), + :l2 => GModelFit.Gaussian(1, 3, 0.5), + :bkg => GModelFit.OffsetSlope(0.5, 1, 0.1), :main => SumReducer(:l1, :l2, :bkg)); model2 = Model(Domain(x), - :l1 => GFit.Gaussian(0.8, 2.1, 0.1), - :l2 => GFit.Gaussian(1.2, 2.5, 0.4), - :bkg => GFit.OffsetSlope(0.5, 1, 0.1), + :l1 => GModelFit.Gaussian(0.8, 2.1, 0.1), + :l2 => GModelFit.Gaussian(1.2, 2.5, 0.4), + :bkg => GModelFit.OffsetSlope(0.5, 1, 0.1), :main => SumReducer(:l1, :l2, :bkg)); model = [model1, model2] freeze!(model[1], :bkg); freeze!(model[2], :bkg); -data = GFit.mock(Measures, model, seed=1) -res = fit(model, data, minimizer=GFit.cmpfit()) -# GFit.print_param_covariance(res, sort=true, select=["[2][l1].norm"]) +data = GModelFit.mock(Measures, model, seed=1) +res = fit(model, data, minimizer=GModelFit.cmpfit()) +# GModelFit.print_param_covariance(res, sort=true, select=["[2][l1].norm"])