Skip to content

Commit

Permalink
Merge pull request #776 from bachlab/pspm_struct2vec_test-pspm_overwr…
Browse files Browse the repository at this point in the history
…ite_new_default

Pspm struct2vec test pspm overwrite new default
  • Loading branch information
dominikbach authored Sep 16, 2024
2 parents d7f2549 + e4ebc8c commit 5012a01
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 22 deletions.
39 changes: 20 additions & 19 deletions src/pspm_options.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
% Introduced in PsPM 6.1
% Written in 2022 by Teddy
% Updated in 2024 by Dominik R Bach (Uni Bonn)
% Updated in 2024 by Bernhard Agoué von Raußendorf

%% 0 Initialise
global settings
Expand Down Expand Up @@ -113,7 +114,7 @@
% 2.15 pspm_data_editor --
% output_file does not have a default value
% epoch_file does not have a default value
options = autofill(options, 'overwrite', 0, 1 );
options = autofill(options, 'overwrite', 2, [0,1] );
case 'dcm'
% 2.16 pspm_dcm --
options = autofill(options, 'aSCR_sigma_offset', 0.1, '>=', 0 );
Expand All @@ -134,7 +135,7 @@
options = autofill(options, 'method', 'dcm' );
options = autofill(options, 'nosave', 0, 1 );
% Don't save dcm structure (e.g. used by pspm_get_rf)
options = autofill(options, 'overwrite', 1, 0 );
options = autofill(options, 'overwrite', 2, [0,1] );
options = autofill(options, 'rf', 0, 1 );
% Call an external file to provide response function (for use when this is previously
% estimated by pspm_get_rf)
Expand Down Expand Up @@ -166,7 +167,7 @@
% only estimate RF, do not do trial-wise DCM
options = autofill(options, 'meanSCR', 0, '*Num' );
% data to adjust the response amplitude priors to
options = autofill(options, 'overwrite', 1, 0 );
options = autofill(options, 'overwrite', 2, [0,1] );
options = autofill(options, 'sclpost', 2, '>=', 0 );
% scl-change-free window after last event (second)
options = autofill(options, 'sclpre', 2.5, '>=', 0 );
Expand All @@ -182,7 +183,7 @@
% use pre-specified RF, provided in file, or as 4-element vector in log parameter space
case 'down'
% 2.18 pspm_down --
options = autofill(options, 'overwrite', 1, 0 );
options = autofill(options, 'overwrite', 2, [0,1] );
case 'ecg_editor'
% 2.19 pspm_down
options = autofill(options, 'factor', 1, '>', 0 );
Expand All @@ -205,7 +206,7 @@
options = autofill(options, 'length', 10, '>', 0 );
options = autofill(options, 'norm', 0, 1 );
options = autofill(options, 'outputfile', '', '*Char' );
options = autofill(options, 'overwrite', 0, 1 );
options = autofill(options, 'overwrite', 2, [0,1] );
options = autofill(options, 'plot', 0, 1 );
options = autofill(options, 'timeunits', 'seconds', {'seconds', ...
'samples',...
Expand Down Expand Up @@ -243,7 +244,7 @@
% 2.26 pspm_get_markerinfo --
options = autofill(options, 'filename', '', '*Char' );
options = autofill(options, 'marker_chan_num', 0, '*Int' );
options = autofill(options, 'overwrite', 0, 1 );
options = autofill(options, 'overwrite', 2, [0,1] );
case 'get_rf'
% 2.27 pspm_get_rf --
options = autofill(options, 'crfupdate', 0, 1 );
Expand All @@ -255,7 +256,7 @@
case 'glm'
% 2.28 pspm_glm --
options = autofill(options, 'norm', 0, 1 );
options = autofill(options, 'overwrite', 0, 1 );
options = autofill(options, 'overwrite', 2, [0,1] );
options = autofill(options, 'marker_chan_num', 'marker', '*Num*Char' );
if ~isfield(options, 'exclude_missing')
options.exclude_missing = struct('segment_length',-1,'cutoff',0);
Expand All @@ -268,7 +269,7 @@
options = fill_glm(options);
case 'import'
%% 2.29 pspm_import
options = autofill(options, 'overwrite', 1, 0 );
options = autofill(options, 'overwrite', 2, [0,1] );
case 'interpolate'
% 2.30 pspm_interpolate --
options = autofill_channel_action(options);
Expand All @@ -281,10 +282,10 @@
'next'} );

options = autofill(options, 'newfile', 0, 1 );
options = autofill(options, 'overwrite', 0, 1 );
options = autofill(options, 'overwrite', 2, [0,1] );
case 'load1'
% 2.31 pspm_load1 --
options = autofill(options, 'overwrite', 0, 1 );
options = autofill(options, 'overwrite', 2, [0,1] );
options = autofill(options, 'zscored', 0, 1 );
case 'merge'
%% 2.32 pspm_merge
Expand All @@ -295,10 +296,10 @@
return
end
end
options = autofill(options, 'overwrite', 0, 1 );
options = autofill(options, 'overwrite', 2, [0,1] );
case 'tam'
% 2.33 pspm_tam --
options = autofill(options, 'overwrite', 0, 1 );
options = autofill(options, 'overwrite', 2, [0,1] );
case 'pp'
% 2.34 pspm_pp --
options = autofill_channel_action(options);
Expand All @@ -308,7 +309,7 @@
% 2.35 pspm_process_illuminance --
options = autofill(options, 'bf', struct(), '*Struct' );
options = autofill(options, 'fn', '', '*Char' );
options = autofill(options, 'overwrite', 0, [1, 2] );
options = autofill(options, 'overwrite', 2, [0,1] );
options = autofill(options, 'transfer', [49.79,...
-1.05,...
-0.50], '*Num' );
Expand Down Expand Up @@ -348,7 +349,7 @@
options = autofill_channel_action(options);
case 'rename'
% pspm_ren
options = autofill(options, 'overwrite', 0, 1 );
options = autofill(options, 'overwrite', 2, [0,1] );
case 'resp_pp'
% 2.39 pspm_resp_pp --
options = autofill_channel_action(options);
Expand Down Expand Up @@ -377,7 +378,7 @@
options = autofill(options, 'min', 0.05, '>', 0 );
options = autofill(options, 'missing_epochs_filename','', '*Char' );
options = autofill(options, 'slope', 10, '*Num' );
options = autofill(options, 'overwrite', 0, 1 );
options = autofill(options, 'overwrite', 2, [0,1] );
if ~isempty(options.missing_epochs_filename)
[pth, ~, ~] = fileparts(options.missing_epochs_filename);
if ~isempty(pth) && exist(pth,'dir')~=7
Expand All @@ -391,7 +392,7 @@
% 2.41 pspm_segment_mean --
options = autofill(options, 'adjust_method', 'none', {'downsample', ...
'interpolate'} );
options = autofill(options, 'overwrite', 0, 1 );
options = autofill(options, 'overwrite', 2, [0,1] );
options = autofill(options, 'newfile', '', '*Char' );
options = autofill(options, 'plot', 0, 1 );
case 'sf'
Expand All @@ -400,7 +401,7 @@
options = autofill(options,'dispwin', 1, 0 );
options = autofill(options,'fresp', 0.5, '>=', 0 );
options = autofill(options,'marker_chan_num', 'marker', '*Int*Char' );
options = autofill(options,'overwrite', 1, 0 );
options = autofill(options, 'overwrite', 2, [0,1] );
options = autofill(options,'threshold', 0.1, '>', 0 );
options = autofill(options,'missingthresh', 2, '>', 0 );
options = autofill(options,'theta', [0.923581, ...
Expand Down Expand Up @@ -443,7 +444,7 @@
'>', 0 );
% minimum ratio of session break to normal inter marker interval (default 3)
options = autofill(options, 'missing', [], '*Char' );
options = autofill(options, 'overwrite', 0, 1 );
options = autofill(options, 'overwrite', 2, [0,1] );
options = autofill(options, 'prefix', 0, '<=', 0 );
options = autofill(options, 'randomITI', 0, 1 );
options = autofill(options, 'splitpoints', [], '*Num' );
Expand All @@ -453,7 +454,7 @@
% 2.46 pspm_trim --
options = autofill(options, 'drop_offset_markers', 0, '*Int' );
options = autofill(options, 'marker_chan_num', 'marker', '*Int*Char' );
options = autofill(options, 'overwrite', 0, 1 );
options = autofill(options, 'overwrite', 2, [0,1] );
options = autofill(options, 'missing', [], '*Char' );
case 'write_channel'
% 2.47 pspm_write_channel --
Expand Down
4 changes: 2 additions & 2 deletions src/pspm_struct2vec.m
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
v(k) = S(k).(field);
elseif numel(S(k).(field)) > 1
v(k) = S(k).(field)(1);
warning('%s #%01.0f contained more than one entry. Only the first one will be retained.\n', warningstr, k);
warning('pspm_struct2vec:MultiField','%s #%01.0f contained more than one entry. Only the first one will be retained.\n', warningstr, k);
else
warning('%s #%01.0f contained no entry and will be assigned NaN.\n', warningstr, k);
warning('pspm_struct2vec:EmptyField','%s #%01.0f contained no entry and will be assigned NaN.\n', warningstr, k);
end
end

Expand Down
2 changes: 2 additions & 0 deletions test/pspm_convert_gaze_test.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ function backup(this)
import{end + 1}.type = 'gaze_y_l';
import{end + 1}.type = 'marker';
options = struct();
options.overwrite = 1; % to always overwrite

[sts, this.fn] = pspm_import(this.raw_input_filename, 'eyelink', import, options);
end
end
Expand Down
4 changes: 3 additions & 1 deletion test/pspm_gaze_pp_test.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ function backup(this)
import{end}.eyelink_trackdist = 600;
import{end}.distance_unit = 'mm';
import{end + 1}.type = 'marker';
options = struct();
options.overwrite = 1; % to always overwrite
[sts, this.pspm_input_fn] = pspm_import(...
this.raw_input_fn, 'eyelink', import, struct());
this.raw_input_fn, 'eyelink', import, options);
end
end
methods(Test)
Expand Down
25 changes: 25 additions & 0 deletions test/pspm_get_biosemi_test.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
testcases;
fhandle = @pspm_get_biosemi;
end



methods
function define_testcases(this)
% testcase 1
Expand All @@ -32,5 +35,27 @@ function invalid_datafile(this)
import = this.assign_chantype_number(import);
this.verifyWarning(@()pspm_get_biosemi(fn, import), 'ID:channel_not_contained_in_file');
end

function pspm_struct2vec_empty_field_warning(this)
% Test that importing markers with empty 'value' fields triggers the empty field warning
fn = 'ImportTestData/biosemi/part1.bdf';
import{1} = struct('type', 'marker', 'channel', 0);
import = this.assign_chantype_number(import);

% Verify that the 'pspm_struct2vec:EmptyField' warning is issued
warningID = 'pspm_struct2vec:EmptyField';
this.verifyWarning(@()pspm_get_biosemi(fn, import), warningID);
end
%% No multifiel in part1.bdf
% function pspm_struct2vec_multi_field_warning(this)
% % Test that importing markers with empty 'value' fields triggers the empty field warning
% fn = 'ImportTestData/biosemi/part1.bdf';
% import{1} = struct('type', 'marker', 'channel', 0);
% import = this.assign_chantype_number(import);
%
% % Verify that the 'pspm_struct2vec:EmptyField' warning is issued
% warningID = 'pspm_struct2vec:MultiField';
% this.verifyWarning(@()pspm_get_biosemi(fn, import), warningID);
% end
end
end
56 changes: 56 additions & 0 deletions test/pspm_struct2vec_test.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
classdef pspm_struct2vec_test < matlab.unittest.TestCase
% unittest class for the pspm_struct2vec function
% PsPM TestEnvironment
% ● Authorship
% (C) 2024 Bernhard Agoué von Raußendorf

methods (TestMethodSetup)
function addFunctionPath(testCase)
% Add the path to the source directory
srcPath = fullfile(pwd, '..', 'src');
addpath(srcPath);
end
end

methods (TestMethodTeardown)
function removeFunctionPath(testCase)
% Remove the path to the source directory after each test
srcPath = fullfile(pwd, '..', 'src');
rmpath(srcPath);
end
end

methods (Test)

% Test case for basic functionality with scalar fields
function testBasicFunctionality(testCase)
S = struct('field', {1, 2, 3});
actualOutput = pspm_struct2vec(S, 'field', 'generic');

% Expected output
expectedOutput = [1; 2; 3];
testCase.verifyEqual(actualOutput, expectedOutput, ...
'The output vector is incorrect for scalar fields.');
end

% Test case for handling multiple elements in a field
function testMultipleElements(testCase)
S = struct('field', {[1,2,3], 5, 7});
actualOutput = pspm_struct2vec(S, 'field', 'generic');

expectedOutput = [1; 5; 7]; % first element of [1,2,3]
testCase.verifyEqual(actualOutput, expectedOutput, ...
'The output vector is incorrect when a field contains multiple elements.');
end

% Test case for handling empty fields
function testEmptyFields(testCase)
S = struct('field', {[], 5, 7});
actualOutput = pspm_struct2vec(S, 'field', 'generic');

expectedOutput = [NaN; 5; 7];
testCase.verifyEqual(actualOutput, expectedOutput, ...
'The output vector is incorrect for empty fields.');
end
end
end

0 comments on commit 5012a01

Please sign in to comment.