Skip to content

[Bug] Issues with Unfold.splinebasis() #333

Description

@jordandeakin

Description

This arose from trying to implement splinebasis functions as discussed in this thread.

1. designmatrix.jl indexing error.
Using Unfold.splinebasis() to specify a design causes an error in line 424 of designmatrix.jl, since onsets comes in as a dataframe. As Rene says in the thread, the issue can be corrected by adding ,1 to the onset index.

for r in eachindex(rows)
rows[r] .+= floor(onsets[r,1] - 1) .+ shift
end

Anything that involves printing the splinebasis also results in an error which was discussed in the above linked thread.

2. Effects() function
After the model is fit by correcting the above, the effects function does not work on the model object (m).

julia> eff = effects(Dict(:absVA => [.01,.05]), m)
ERROR: AssertionError: size(evts_tbl) == size(time_event)
Stacktrace:
 [1] result_to_table(eff::Vector{Array{…}}, events::Vector{DataFrame}, times::Vector{Vector{…}}, eventnames::Vector{String})
   @ Unfold /nfs/ssd2.0/u/bbe3300/julia_depot/dev/Unfold/src/condense.jl:277
 [2] effects(design::Dict{Symbol, Vector{…}}, model::UnfoldLinearModelContinuousTime{Union{…}}; typical::Function)
   @ Unfold /nfs/ssd2.0/u/bbe3300/julia_depot/dev/Unfold/src/effects.jl:52
 [3] effects(design::Dict{Symbol, Vector{Float64}}, model::UnfoldLinearModelContinuousTime{Union{Missing, Float64}})
   @ Unfold /nfs/ssd2.0/u/bbe3300/julia_depot/dev/Unfold/src/effects.jl:30
 [4] top-level scope
   @ REPL[45]:1
Some type information was truncated. Use `show(err)` to see complete types.

3a. One estimate per spline instead of per time point.
After correcting (1), the fit runs, but coeftable(m), produces one estimate per spline/channel/coef and does not return an estimate for all time points, since Unfold doesn't currently multiply out the betas to allow this. I was able to this with a few adjustments using the code here.

3b (Extra, maybe not a bug)
However, the resulting estimates seem shifted backwards in time (shift_onset seems correct given the time points for both basis functions). Perhaps I reconstruct incorrectly but, here is an example using the predef_eeg() function in UnfoldSim.

import BSplineKit
using Unfold
using UnfoldSim
using Plots
using DataFrames
## Multiply out betas function
function undoBasis(d,m,formidx)
    # formidx is a quick fix for me incase i model multiple events
        bname = unique(d.coefname) # the current coefficient basename
        @assert(length(bname)==1)
        @assert(length(unique(d.channel))==1)
        bnames = unique(d.coefname) # all model basenames

        # find out which formula / basisfunction we have
        #k = findfirst(bname .== bnames)

        bf = designmatrix(m)[formidx].formula.rhs.basisfunction
                println(d)

        estimate= bf.kernel.(0) *d.estimate
       return DataFrame(:time=>Unfold.times(bf),:estimate=>estimate)

end

## FIR BASIS
data,evts = UnfoldSim.predef_eeg()
evts.event .= "stimulus"

  design = [
        "stimulus" => (@formula(0 ~ 1), firbasis(τ=(-0.2, 1.2), sfreq=100))
    ]

m_fir_basis = fit(UnfoldModel, design, evts, data; eventcolumn=:event)
coef_fir_basis = coeftable(m_fir_basis)
fir_estimate = coef_fir_basis.estimate;
times = coef_fir_basis.time;

## SPLINE BASIS
  design_spline = [
        "stimulus" => (@formula(0 ~ 1), Unfold.splinebasis(τ=(-0.2, 1.2), sfreq=100,nsplines=30,name="stimulus"))
    ]

m_spline_basis = fit(UnfoldModel, design_spline, evts, data; eventcolumn=:event)
coef_spline_basis = coeftable(m_spline_basis)
outSpline = undoBasis(coef_spline_basis, m_spline_basis,1)
spline_estimate = outSpline.estimate

plot(times,fir_estimate)
plot!(times,spline_estimate)
Image

Thanks!

Package Version

v0.8.9

Julia Version

v1.11.5

Reproduction steps

  1. (error in design matrix)
    Unfold.splinebasis((-.2,.8), 100, 5, "")

  2. (effects function)
    Calling effects() using model object created with splinebasis.

3a. (coeftable produces one estimate per spline instead of per time point)
Calling coeftable() using model object created with splinebasis.

3b. I included a snippet

Relevant log output

Operating System

Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions