VU-Cog-Sci / nideconv

fit response shapes from signal time-courses
MIT License
12 stars 11 forks source link

Design matrix for very short events contains only 0s #6

Closed eort closed 5 years ago

eort commented 6 years ago

Hi,

The events I want to fit are quite short. Most of them have a duration of less than 1 second (I use response time as duration as the stimuli were on screen until a response was given). So far, I used FIRDeconvolution to model my data, and there I got reasonable results. Now, I tried to use nideconv to do the same, but it didn't really work. After diving into the module, I realized that my design matrix contains only 0s for all regressors that are shorter than 1 second.

Just for trying it out, I replaced line 279 in regressor.get_timecourse with this line:

dt = int(math.ceil(d * self.sample_rate * oversample)) # after importing math to make sure that my events at least last for one timepoint, and this seems to help to get at least some results out of the deconvolution. Whether it works properly, I can't say though (e.g. running fytter.get_rsq()still gives NaN).

I also noticed that the oversample_design_matrix keyword in the init of the fytter doesn't seem to really do anything in that part of the deconvolution, that is, when I dropped the shell in regressor.get_timecourse, the variable oversamplewas set to 1, even though I initialized the fitter with the default of 20. Is that intentional, or do I misunderstand what that variable is supposed to be doing?

Eduard

Gilles86 commented 6 years ago

Hey Eduard,

Do you have some example code of when this problem occurs?

-Gilles

eort commented 6 years ago

I think this should do.

import numpy as np
import nideconv
conditions = [u'proSwitch', u'reSwitch', u'proRep', u'reRep', u'error', u'cue']
events = [np.array([  85.57582808,  103.08598518,  110.76642919]),
                 np.array([  5.27240014,  20.01700306,  35.44459915]),
                 np.array([  95.80531907,  101.51998806,  159.41491103]),
                 np.array([  6.7551682 ,   9.68756914,  14.13581014]),
                 np.array([ 11.28709817,  12.70296907,  33.86182809]),
                 np.array([   0.52421617,   76.52920318,  278.52046918])]
durations = [np.array([ 0.314,  0.265,  0.311]),
                 np.array([ 0.342,  0.286,  0.344]),
                 np.array([ 0.306,  0.295,  0.258]),
                 np.array([ 0.292,  0.304,  0.265]),
                 np.array([ 0.28 ,  0.272,  0.271]),
                 np.array([ 2.5,  2.5,  2.5])]
rf = nideconv.ResponseFitter(input_signal=signal,
                            sample_rate=signal_sample_frequency,
                            oversample_design_matrix=20)

for condI, cond in enumerate(conditions):
    rf.add_event(event_name=cond,
             onset_times=events[condI],
             interval=[-5,9],
             basis_set='fourier',
             durations=durations[condI],
             n_regressors=9)
rf.regress('ridge')
# regressor with durations <1
rf.X['proSwitch'].sum()
# regressor with durations > 1
rf.X['cue'].sum()
Gilles86 commented 6 years ago

Cool. What is the sample frequency of the signal?

eort commented 6 years ago

Oh shit, I missed that. It is 0.5.

Gilles86 commented 6 years ago

dt = int(math.ceil(d self.sample_rate oversample)) # after importing math to make sure that my events at least last for one timepoint, and this seems to help to get at least some results out of the deconvolution. Whether it works properly, I can't say though (e.g. running fytter.get_rsq()still gives NaN).

The ceil-solution makes a lot of sense. I never considered the possibility of events that are shorter than the sample duration. I have to say though: if your events are so short, why model the duration at all? It makes the fitted timecourses much hard to interpret in my humble opinion.

What is the range of durations that your stimuli have?

eort commented 6 years ago

Yes, that is very true, and was also one of my concerns. Eventually, I went for it because I wouldn't know which other 'arbitrary' duration to use. And I hoped that if I oversampled the signal, the durations get more meaningful. With FIRDeconvolution, I used a factor of 4 for oversampling. Do you have a better alternative in mind?

What is the range of durations that your stimuli have?

500ms +- 200 maybe. Hardly ever more than 1 second. Those are actually saccade latencies.

Gilles86 commented 6 years ago

Hey Eduard,

There were a couple of things going on here. Indeed, the software did not allow for durations to be shorter than the sample length. To be honest I do not know why you would want this anyway (I had this discussion last week with @JvSlooten88 as well and today with @tknapen. I seem to be a minority).

Another issue is that I think your design matrix was singular and nideconv allows for this. However, you then get very weird results. From now on it will give an Exception.

Could you pull the latest master branch and have another go at your data?

Btw: do you know about 'GroupResponseFytter'? This should makes things a lot easier and now also supports Ridge Regression.

-Gilles

eort commented 6 years ago

Thanks! With the latest master branch it seems to work now.

do you know about 'GroupResponseFytter'? This should makes things a lot easier and now also supports Ridge Regression.

I saw it in the documentation, but it looked incomplete. Is it ready to use already? And what does the input look like? Onsets,durations, signal for each individual run, of the concatenated runs, or either?

And finally just to confirm, the oversampling parameter is primarily used for the visualization/extraction of the results, not for the actual fitting?

Thanks again, Eduard

JvSlooten88 commented 6 years ago

Hi Eduard,

I’m using GroupResponseFytter. If you like I can show you how the inputs should look like etc.

Joanne

On 21 Aug 2018, at 14:24, eort notifications@github.com wrote:

Thanks! With the latest master branch it seems to work now.

do you know about 'GroupResponseFytter'? This should makes things a lot easier and now also supports Ridge Regression.

I saw it in the documentation, but it looked incomplete. Is it ready to use already? And what does the input look like? Onsets,durations, signal for each individual run, of the concatenated runs, or either?

And finally just to confirm, the oversampling parameter is primarily used for the visualization/extraction of the results, not for the actual fitting?

Thanks again, Eduard

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/VU-Cog-Sci/nideconv/issues/6#issuecomment-414655624, or mute the thread https://github.com/notifications/unsubscribe-auth/AILw7hAD9aE0P5LFPJao3joRY-sitMG-ks5uS_wagaJpZM4WFZMh.

eort commented 6 years ago

Thanks! That would be nice. I'll email you about it.

Eduard

Gilles86 commented 6 years ago

And finally just to confirm, the oversampling parameter is primarily used for the visualization/extraction of the results, not for the actual fitting?

No. It is also used when constructing the design matrix. The design matrix gets constructed at the sampling rate of the signal times the oversample factor. However, after this step, it is downsampled again to the sample rate of the signal. To see the difference: https://gist.github.com/11a3d95fcdb0fff78d018e31693fae12

I think it is a really bad idea to oversample your signal when fitting a model: then you sort of use two models. Again, I seem to be weird. If you want that you can do it yourself very easily.

eort commented 6 years ago

OK, I see. Again, coming from FIRDeconvolution I thought that oversampling comes along with the number of betas that correspond to the oversampled signal dimensions (at least when using FIR) and was confused. Thanks.