Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pspm struct2vec test pspm overwrite new default #776

Merged
merged 8 commits into from
Sep 16, 2024
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
Loading