unfoldtoolbox / UnfoldBIDS.jl

MIT License
4 stars 2 forks source link

"helper" functions I used #52

Open behinger opened 1 year ago

behinger commented 1 year ago

I now analyzed two datasets with UnfoldBids and these are some of the helpers. I am not super happy with them right now, I dont know a good interface to do this properly.

preprocessing / resampling

    for k  = 1:length(eeg_df.data)
        if pyconvert(Float64,eeg_df.data[k].info["sfreq"]) == fs_new
            continue
        end
        eeg_df.data[k].resample(fs_new)
        eeg_df.data[k].filter(0.1,nothing)

    end

epoching

requires #47

    function processData(raw,events;kwargs...)
        d = UnfoldBIDS.rawToData(raw,events)
        d_epoch,t = Unfold.epoch(d,events,[-0.1,0.3],fs_new)
        return d_epoch
    end
resultsAll = runUnfold(eeg_df, events_tuned, bfDict;importfunction = processData,importkwargs=(;channels="Oz"))#fitkwargs=(;solver=))

parallel effects

(this should likely be an option in effects in Unfold) basically this allows you NOT to calculate all combinations of the effects, which doesnt make sense for spliines, as there are no interactions possible (except splines2d which is right now not implemented)

d = [
    Dict(:f_ori => 0:1:3),
    Dict(:f_sf => 0:1:3),
    Dict(:f_color => 0:1:3),
    Dict(:f_contrast => 0:1:3),
    #Dict(:CLOSESTENEMY=>0:0.1:1)
    ]
function calc_effects(x)

eff =   allowmissing!.(effects.(d,Ref(x[1]))) # needed to allow some subjects to have predicts outside their ranges
for (ix,e) in enumerate(eff)

    varname = first(keys(d[ix]))
    #@show unique(e[:,varname])
    e.key .= varname
    rename!(e,varname => "value")
end
return vcat(eff...)
end
effectsAll = combine(groupby(resultsAll,:subject),:model=>(x->
calc_effects(x)) =>AsTable, threads=false)  

coeftable for all subj

I couldnt find a nicer way to do this. Should be a function we provide imho.

We should provide a Unfold.coeftable(::DataFrame) function that simply runs this - what do you think @ReneSkukies ?

    function myFun(m,s)
        r = coeftable(m)
        r[!,:subject] .= s
        return r
    end
b2b_d = combine(groupby(b2b_resultsAll,:subject),:model=>ByRow(x->(coeftable(x)|>columntable))=>AsTable, threads=false) 
b2b_d = flatten(b2b_d,[n for n in names(b2b_d) if n != "subject"])

averaging

most likely I would add a functionality to bootstrap CI's as well here

b2b_d_avg = groupby(b2b_d,[:coefname,:time])|>x-> combine(x,:estimate=>(x->mean(abs.(skipmissing(x))))=>:estimate) 

it is a bit tricky, a different case would look like this:

effectsAvg = groupby(effectsAll,[:time,:key,:value,:channel])|>x-> combine(x,:yhat=>(x->median(skipmissing(x)))=>:yhat) 

so it is not entirely clear, what to group by values to use - depending on output of coeftable, effects or non-gridded-effects (see above) we would want to use different ones