diff --git a/src/pspm_extract_segments.m b/src/pspm_extract_segments.m index dfe5ff06c..bd8ae4bc9 100644 --- a/src/pspm_extract_segments.m +++ b/src/pspm_extract_segments.m @@ -133,6 +133,7 @@ switch method case 'data' data_raw = data; + if isnumeric(data), data_raw = {data}; end case 'file' for i_sn = 1:numel(datafile) [lsts, alldata{i_sn}] = pspm_load_channel(datafile{i_sn}, channel); @@ -152,6 +153,9 @@ case 'model' if strcmpi(data.modeltype, 'glm') data_raw = data.input.data; + timing = data.input.timing; + options.timeunits = data.input.timeunits; + events = data.input.events; elseif strcmpi(data.modeltype, 'dcm') data_raw = data.input.scr; else @@ -181,11 +185,6 @@ session_duration(i_sn, 1) = numel(data_raw{i_sn}); end -if strcmpi(method, 'model') && strcmpi(data.modeltype, 'glm') - timing = data.input.timing; -end - - if strcmpi(method, 'model') && strcmpi(data.modeltype, 'dcm') % DCM has no condition information onsets{1} = cellfun(@(x, y) pspm_time2index(x, sr , y), ... @@ -194,6 +193,7 @@ 'UniformOutput', false); names{1} = 'all'; n_cond = 1; + options.timeunits = 'seconds'; else [lsts, multi] = pspm_get_timing('onsets', timing, options.timeunits); [msts, onsets] = pspm_multi2index(options.timeunits, multi, sr, session_duration, events); @@ -204,6 +204,8 @@ end end +% onsets has the structure: onsets{i_cond}{i_sn} + %% prepare missing if isfield(options, 'missing') missing = options.missing; diff --git a/src/pspm_glm.m b/src/pspm_glm.m index 263ff2127..414cbd9cd 100644 --- a/src/pspm_glm.m +++ b/src/pspm_glm.m @@ -241,7 +241,10 @@ warning('ID:invalid_input', 'Could not load the specified markerchannel'); return end - events{iFile} = data.data(:) * data.header.sr; + % here, data.header.sr correponds to the time resolution of the + % time stamps which should always be 1, but this will convert any + % potentially deviating time stamp resolution to seconds + events{iFile} = data.data(:) / data.header.sr; if strcmp(model.timeunits,'markervalues') model.timing{iFile}.markerinfo = data.markerinfo; end @@ -491,6 +494,7 @@ %% 12 collect data & regressors for output model glm.input.data = y; glm.input.sr = sr; +glm.input.events = events; glm.Y = Y; glm.M = M; % set to 1 if data is missing, otherwise set to 0 glm.infos.sr = newsr; @@ -758,6 +762,7 @@ %% 17 save data % 17.1 overwrite is determined in load1 -- +glm.datetime = datetime; savedata = struct('glm', glm); [sts, data_load1, mdltype_load1] = pspm_load1(model.modelfile, 'save', savedata, options); diff --git a/src/pspm_multi2index.m b/src/pspm_multi2index.m index 0d8ee95bf..e69d816bf 100644 --- a/src/pspm_multi2index.m +++ b/src/pspm_multi2index.m @@ -8,7 +8,7 @@ % [onsets, durations] = pspm_multi2index('markers', multi, sr, session_duration, events) % ● Arguments % * multi : multi structure from pspm_get_timing -% sr : sampling rate, or vector of sampling rates with the same number of +% sr : sampling rate, or vector of sampling rates with the same number of % elements as multi % * sr_ratio : If data was downsampled wrt onset definition, ratio of new_sr/old_sr; or % vector of sampling rate ratios. Otherwise, should be 1. @@ -23,7 +23,7 @@ sr = repmat(sr, numel(multi), 1); end if numel(sr) ~= numel(multi) || numel(session_duration) ~= numel(multi) - warning('ID:invalid_input', 'No event definition provided.'); return; + warning('ID:invalid_input', 'Number of sessions do not match.'); return; end if ~isempty(multi) for iSn = 1:numel(multi) @@ -40,8 +40,8 @@ events = varargin{1}; end % markers are timestamps in seconds - onsets{n}{iSn} = pspm_time2index(multi(iSn).onsets{n}, sr(iSn), session_duration, 0, events{iSn}); - durations{n}{iSn} = pspm_time2index(multi(iSn).durations{n}, sr(iSn), session_duration, 1); + onsets{n}{iSn} = pspm_time2index(multi(iSn).onsets{n}, sr(iSn), session_duration(iSn), 0, events{iSn}); + durations{n}{iSn} = pspm_time2index(multi(iSn).durations{n}, sr(iSn), session_duration(iSn), 1); end end end diff --git a/test/pspm_extract_segments_test.m b/test/pspm_extract_segments_test.m index 55683a038..233c5c19c 100644 --- a/test/pspm_extract_segments_test.m +++ b/test/pspm_extract_segments_test.m @@ -185,9 +185,8 @@ function test_manual_length(this,nr_trial,nan_ratio) function test_auto_mode_glm_with_markers(this) import matlab.unittest.constraints.IsEqualTo import matlab.unittest.constraints.RelativeTolerance - rehash - load(['ImportTestData' filesep 'fitted_models' filesep 'glm_scr_cond_marker.mat'], 'glm'); - load(['ImportTestData' filesep 'fitted_models' filesep 'glm_orig_data.mat'], 'data'); + load(fullfile('ImportTestData', 'fitted_models', 'glm_scr_cond_marker.mat'), 'glm'); + load(fullfile('ImportTestData', 'fitted_models', 'glm_orig_data.mat'), 'data'); if ~isfield(glm.input, 'channel') && isfield(glm.input, 'chan') glm.input.channel = glm.input.chan; glm.input = rmfield(glm.input,'chan'); % rename the field channel to chan @@ -221,13 +220,13 @@ function test_auto_mode_glm_with_markers(this) this.verifyThat(nanmean(seg{3}.data, 1), IsEqualTo(seg{3}.mean, 'Within', RelativeTolerance(1e-10))); this.verifyThat(nanstd(seg{3}.data, 0, 1), IsEqualTo(seg{3}.std, 'Within', RelativeTolerance(1e-10))); % compute statistics from scratch - for i = 1:numel(glm.timing.multi.durations) + for i = 1:numel(glm.timing.multi.onsets) all_vecs = []; seg_len = this.options.length * sr; - onset_i = glm.timing.multi.onsets{i}; - for j = 1:numel(onset_i) - onset = round(onset_i(j) * sr) + 1; - all_vecs = [all_vecs, input_data(onset : onset + seg_len - 1)]; + onsets_i = pspm_time2index(marker(glm.timing.multi.onsets{i}), sr); + for j = 1:numel(onsets_i) + onset = onsets_i(j); + all_vecs = [all_vecs, input_data(onset : onset + seg_len - 1)]; end all_vecs = all_vecs'; expected_mean = nanmean(all_vecs, 1);