Effects.effects
โ Methodeffects(design::AbstractDict, model::UnfoldModel; typical = mean)
Calculates marginal effects for all term combinations in design
.
Implementation based on Effects.jl package; likely could repackage in UnfoldEffects.jl; somebody wants to do it? This would make it easier to cross-maintain it to changes/bug fixes in the Effects.jl package. design
is a dictionary containing those predictors (as keys) with levels (as values), that you want to evaluate. The typical
refers to the value, which other predictors that are not specified in the dictionary, should take on.
For MixedModels, the returned effects are based on the "typical" subject, i.e. all random effects are put to 0.
Example
julia> f = @formula 0 ~ categoricalA + continuousA + continuousB
julia> uf = fit(UnfoldModel, (Any => (f, times)), data, events)
julia> d = Dict(:categorical => ["levelA", "levelB"], :continuous => [-2, 0, 2])
julia> effects(d, uf)
will result in 6 predicted values: A/-2, A/0, A/2, B/-2, B/0, B/2.
FileIO.load
โ MethodFileIO.load(file, ::Type{<:UnfoldModel}; generate_Xs=true)
Load UnfoldModel from a .jld2 file.
By default, the designmatrix is reconstructed. If it is not needed set generate_Xs=false
which improves time-efficiency.
FileIO.save
โ MethodFileIO.save(file, uf::T; compress=false) where {T<:UnfoldModel}
Save UnfoldModel in a (by default uncompressed) .jld2 file.
For memory efficiency the designmatrix is set to missing. If needed, it can be reconstructed when loading the model.
StatsAPI.coefnames
โ Methodcoefnames(term)
coefnames of a TimeExpandedTerm concatenates the basis-function name with the kronecker product of the term name and the basis-function colnames. Separator is ' : ' Some examples for a firbasis: basis313 : (Intercept) : 0.1 basis313 : (Intercept) : 0.2 basis_313 : (Intercept) : 0.3 ...
StatsAPI.fit
โ Methodfit(type::UnfoldModel,d::Vector{Pair},tbl::AbstractDataFrame,data::Array)
fit(type::UnfoldModel,f::FormulaTerm,tbl::AbstractDataFrame,data::Array{T,3},times)
fit(type::UnfoldModel,f::FormulaTerm,tbl::AbstractDataFrame,data::Array{T,2},basisfunction::BasisFunction)
Generates Designmatrix & fits model, either mass-univariate (one model per epoched-timepoint) or time-expanded (modeling linear overlap).
eventcolumn
(Symbol/String, default :event) - the column intbl::AbstractDataFrame
to differentiate the basisfunctions as defined ind::Vector{Pair}
show_progress
(Bool, default true) - show Progress via ProgressMeter
If a Vector[Pairs]
is provided, it has to have one of the following structures: [:A=>(f,basisfunction), :B=>(f2,bf2)]
- for deconvolutin analyses (use Any=>(f,bf)
to match all rows of tbl
in one basis functins) [:A=>(f,timesvector), :B=>(f2,timesvector)]
- for mass univariate analyses. If multiple rERPs are calculated at the same time, the timesvectors must be the same
Notes
- The
type
can be specified directly as well e.g.fit(type::UnfoldLinearModel)
instead of inferred - The data is reshaped if it is missing one dimension to have the first dimesion then
1
"Channel".
Examples
Mass Univariate Linear
julia> data,evts = loadtestdata("testCase1")
julia> data_r = reshape(data,(1,:))
julia> data_e,times = Unfold.epoch(data=data_r,tbl=evts,ฯ=(-1.,1.9),sfreq=10) # cut the data into epochs. data_e is now ch x times x epoch
julia> f = @formula 0~1+continuousA+continuousB # 1
julia> model = fit(UnfoldModel,f,evts,data_e,times)
Timexpanded Univariate Linear
julia> basisfunction = firbasis(ฯ=(-1,1),sfreq=10,name="A")
julia> model = fit(UnfoldModel,[Any=>(f,basisfunction],evts,data_r)
StatsAPI.modelmatrix
โ Methodmodelmatrix(uf::UnfoldLinearModel)
returns the modelmatrix of the model. Concatenates them, except in the MassUnivariate cases, where a vector of modelmatrices is return
Compare with modelmatrices
which returns a vector of modelmatrices, one per event
StatsAPI.predict
โ Methodfunction predict(
uf::UnfoldModel,
f::Vector{<:FormulaTerm},
evts::Vector{<:DataFrame};
overlap::Bool = true,
kwargs...
)
Returns a predicted ("y_hat = X*b") Array
.
uf
is an<:UnfoldModel
f
is a (vector of) formulas, typicallyUnfold.formulas(uf)
, but formulas can be modified e.g. byeffects
.evts
is a (vector of) events, can beUnfold.events(uf)
to return the (possibly continuous-time) predictions of the model. Can be a custom even
kwargs:
if overlap = true
(default), overlap based on the latency
column of evts
will be simulated, or in the case of !ContinuousTimeTrait
just X*coef is returned.
if overlap = false
, returns predictions without overlap (models with ContinuousTimeTrait
(=> with basisfunction / deconvolution) only), via predict_no_overlap
if keep_basis
or exclude_basis
is defined, then predict_partial_overlap
is called, which allows to selective introduce overlap based on specified (or excluded respective) events/basisfunctions
epoch_to
and epoch_timewindow
: calculate (partial) overlap controlled predictions, but returns them at the specified epoch_at
event, with the times epoch_timewindow
(default is taken from the basisfunction) in samples.
eventcolumn
can be specified as well if different from the default event
.
Hint: all kwargs
can be Vector
, or if e.g. string
types are provided, will be put into a length==1
vector.
Output
- If
overlap=false
, returns a 3D-Array - If
overlap=true
andepoch_to = nothing
(default), returns a 2D-array - If
overlap=true
andepoch_to != nothing
, returns a 3D array
StatsModels.modelcols
โ Methodmodelcols(term, tbl)
calculates the actual designmatrix for a timeexpandedterm. Multiple dispatch on StatsModels.modelcols
Unfold._modelcols
โ Method_modelcols(form::FormulaTerm, events)
Unfold._modelcols
โ Method_modelcols(forms::Vector,events::Vector)
A wrapper around StatsModels.modelcols that is only needed for easy multiple dispatch
Unfold.apply_basisfunction
โ Methodapply_basisfunction(
form,
basisfunction,
eventfields,
eventname
)
timeexpand the rhs-term of the formula with the basisfunction
Unfold.combine_yhat!
โ Methodcombine_yhat(list,single)
combines single into list, if either list or single contains missing, automatically casts the respective counter-part to allow missings as well
Unfold.designmatrix
โ Methoddesignmatrix(type, f, tbl; kwargs...)
call without basis function, continue with basisfunction = nothing
Unfold.designmatrix
โ Methoddesignmatrix(
unfoldmodeltype,
f,
tbl,
basisfunction;
contrasts,
eventname,
kwargs...
)
designmatrix(type, f, tbl; kwargs...) Return a DesignMatrix used to fit the models.
Arguments
- type::UnfoldModel
- f::FormulaTerm: Formula to be used in this designmatrix
- tbl: Events (usually a data frame) to be modelled
- basisfunction::BasisFunction: basisfunction to be used in modeling (if specified)
- contrasts::Dict: (optional) contrast to be applied to formula
- eventfields::Array: (optional) Array of symbols which are passed to basisfunction event-wise.
First field of array always defines eventonset in samples. Default is [:latency]
Examples
julia> designmatrix(UnfoldLinearModelContinuousTime,Dict(Any=>(f,basisfunction1),tbl)
Unfold.designmatrix
โ Methoddesignmatrix(
uf::UnfoldModel,
tbl;
eventcolumn = :event,
contrasts = Dict{Symbol,Any}(),
kwargs...,
Main function, generates the designmatrix, returns a list of <:AbstractDesignMatrix
Unfold.drop_missing_epochs
โ Method[X,y] = drop_missing_epochs(X, y::Array)
Helper function to remove epochs of y
that contain missings. Drops them from both X
and y
. Often used in combination with Unfold.epoch
X can be anything that has two dimensions (Matrix, DataFrame etc)
Unfold.epoch
โ Methodepoch(data::Array{T,1},evts::DataFrame,ฯ::Tuple/Vector,sfreq;kwargs...,
Basic function to epoch data; all input also available as kwargs.
Additional kwarg: eventtime
=:latency, which defines the column in evts
that is used to cut the data (in samples). For uneven sample-times we use round()
`
Unfold.equalize_size
โ Methodequalize_size(X, data)
Equates the length of data and designmatrix by cutting the shorter one
The reason we need this is because when generating the designmatrix, we do not know how long the data actually are. We only assume that event-latencies are synchronized with the data
Unfold.firbasis
โ Functionfirbasis(ฯ, sfreq; ...)
firbasis(ฯ, sfreq, name; interpolate)
Generate a sparse FIR basis around the ฯ timevector at sampling rate sfreq. This is useful if you cannot make any assumptions on the shape of the event responses. If unrounded events are supplied, they are split between samples. E.g. event-latency = 1.2 will result in a "0.8" and a "0.2" entry.
keyword arguments
interpolate
(Bool, default false): if true, interpolates events between samples linearly. This results in predict
functions to return a trailling 0
Examples
Generate a FIR basis function from -0.1s to 0.3s at 100Hz
julia> f = firbasis([-0.1,0.3],100)
Evaluate at an event occuring at sample 103.3
julia> f(103.3)
Unfold.firkernel
โ Methodfirkernel(e, times; interpolate)
Calculate a sparse firbasis
Examples
julia> f = firkernel(103.3,range(-0.1,step=0.01,stop=0.31))
Unfold.formulas
โ Methodformulas(design::Vector{<:Pair})
returns vector of formulas, no schema has been applied (those formulas never saw the data). Also no timeexpansion has been applied (in the case of timecontinuous models)
Unfold.get_basis_colnames
โ Methodget_basis_colnames(m)
get_basis_colnames(formulas)
returns list of colnames - e.g. times for firbasis.
Unfold.get_basis_indices
โ Methodget_basis_indices(uf, basisnames::Vector)
returns a boolean vector with length spanning all coefficients, which coefficient is defined by basisnames
(vector of names)
Unfold.get_basis_names
โ Methodget_basisnames(model::UnfoldModel)
Return the basisnames for all predictor terms as a vector.
The returned vector contains the name of the event type/basis, repeated by their actual coefficient number (after StatsModels.apply_schema / timeexpansion). If a model has more than one event type (e.g. stimulus and fixation), the vectors are concatenated.
Unfold.hrfbasis
โ Methodhrfbasis(TR; parameters, name)
Generate a Hemodynamic-Response-Functio (HRF) basis with inverse-samplingrate "TR" (=1/FS)
Optional Parameters p: defaults {seconds} p(1) - delay of response (relative to onset) 6 p(2) - delay of undershoot (relative to onset) 16 p(3) - dispersion of response 1 p(4) - dispersion of undershoot 1 p(5) - ratio of response to undershoot 6 p(6) - onset {seconds} 0 p(7) - length of kernel {seconds} 32
Examples
Generate a HRF basis function object with Sampling rate 1/TR. And evaluate it at an event occuring at TR 103.3 with duration of 4.1 TRs
julia> f = hrfbasis(2.3)
julia> f(103.3,4.1)
Unfold.hrfkernel
โ Methodhrfkernel(e, TR, p)
Calculate a HRF kernel. Input e can be [onset duration]
Examples
julia> f = hrfkernel(103.3,2.3,[6. 16. 1. 1. 6. 0. 32.])
Unfold.linearize
โ Methodlinearize(x)
Flatten a 1D array from of a 2D/3D array. Also drops the empty dimension
Unfold.matrix_by_basisname
โ MethodReturns a view of the Matrix y
, according to the indices of the timeexpanded basisname
Unfold.modelmatrices
โ Methodmodelmatrices(X::AbstractDesignMatrix)
modelmatrices(X::Vector{<:AbstractDesignMatrix})
modelmatrices(modelmatrix::AbstractMatrix)
Returns the modelmatrices (also called designmatrices) separately for the events. This is similar to StatsModels.modelcols
, but merely access the precomputed designmatrix. If the designmatrix needs to be computed, please use modelcols
Compare to modelmatrix
which further concatenates the designmatrices (in the ContinuousTime case).
Unfold.predicttable
โ Functionpredicttable(model<:UnfoldModel,events=Unfold.events(model),args...;kwargs...)
Shortcut to call efficiently call (pseudocode) result_to_table(predict(...))
.
Returns a tidy DataFrame with the predicted results. Loops all input to predict
, but really only makes sense to use if you specify either:
overlap = false
(the default) or epoch_to = "eventname"
.
Unfold.result_to_table
โ Methodresult_to_table(model<:UnfoldModel, eff::AbstractArray, events::Vector{<:DataFrame})
result_to_table(
eff::AbstractArray,
events::Vector{<:DataFrame},
times::Vector{<:Vector{<:Number}},
eventnames::Vector)
Converts an array-result (prediction or coefficient) together with the events, to a tidy dataframe
Unfold.spdiagm_diag
โ MethodSpeed improved version of spdiagm, takes a single float value instead of a vector, like a version of spdiagm that takes in a UniformScaling
e.g.
sz = 5 ix = [1,3,10] spdiagm_diag(sz,(.-ix.=>1)...)
Unfold.time_expand_allBasesSameCols
โ MethodHelper function to decide whether all bases have the same number of columns per event
Unfold.timeexpand_cols
โ Methodtimeexpand_cols(basisfunction, bases, ncolsBasis, ncolsX)
calculates in which rows the individual event-basisfunctions should go in Xdc
see also timeexpandrows timeexpandvals
Unfold.timeexpand_rows
โ Methodtimeexpand_rows(onsets, bases, shift, ncolsX)
calculates in which rows the individual event-basisfunctions should go in Xdc
timeexpandrows timeexpandvals
Unfold.times
โ Methodtimes(model<:UnfoldModel)
returns arrays of time-vectors, one for each basisfunction / parallel-fitted-model (MassUnivarite case)
Unfold.unfold_apply_schema
โ Methodwrapper to make apply_schema mixed models as extension possible
Note: type is not necessary here, but for LMM it is for multiple dispatch reasons!