forked from sccn/EEG-BIDS
-
Notifications
You must be signed in to change notification settings - Fork 1
/
bids_writetinfofile.m
92 lines (86 loc) · 3.48 KB
/
bids_writetinfofile.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
% BIDS_WRITETINFOFILE - write tinfo file
%
% Usage:
% bids_writetinfofile(EEG, tinfo, fileOut)
%
% Inputs:
% EEG - [struct] EEGLAB dataset information
% tinfo - [struct] structure containing task information
% notes - [string] notes to store along with the data info
% fileOut - [string] filepath of the desired output location with file basename
% e.g. ~/BIDS_EXPORT/sub-01/ses-01/eeg/sub-01_ses-01_task-GoNogo
%
% Authors: Arnaud Delorme, 2023
function tInfo = bids_writetinfofile( EEG, tInfo, notes, fileOutRed)
[~,channelsCount] = eeg_getchantype(EEG);
% Write task information (eeg.json) Note: depends on channels
% requiredChannelTypes: 'EEG', 'EOG', 'ECG', 'EMG', 'MISC'. Other channel
% types are currently not valid output for eeg.json.
nonEmptyChannelTypes = fieldnames(channelsCount);
for i=1:numel(nonEmptyChannelTypes)
if strcmp(nonEmptyChannelTypes{i}, 'MISC')
tInfo.('MiscChannelCount') = channelsCount.('MISC');
else
tInfo.([nonEmptyChannelTypes{i} 'ChannelCount']) = channelsCount.(nonEmptyChannelTypes{i});
end
end
if ~isfield(tInfo, 'EEGReference')
if ~ischar(EEG.ref) && numel(EEG.ref) > 1 % untested for all cases
refChanLocs = EEG.chanlocs(EEG.ref);
ref = join({refChanLocs.labels},',');
ref = ref{1};
else
ref = EEG.ref;
end
tInfo.EEGReference = ref;
end
if EEG.trials == 1
tInfo.RecordingType = 'continuous';
tInfo.RecordingDuration = EEG.pnts/EEG.srate;
else
tInfo.RecordingType = 'epoched';
tInfo.EpochLength = EEG.pnts/EEG.srate;
tInfo.RecordingDuration = (EEG.pnts/EEG.srate)*EEG.trials;
end
tInfo.SamplingFrequency = EEG.srate;
if ~isempty(notes)
tInfo.SubjectArtefactDescription = notes;
end
tInfoFields = {...
'TaskName' 'REQUIRED' '' '';
'TaskDescription' 'RECOMMENDED' '' '';
'Instructions' 'RECOMMENDED' 'char' '';
'CogAtlasID' 'RECOMMENDED' 'char' '';
'CogPOID' 'RECOMMENDED' 'char' '';
'InstitutionName' 'RECOMMENDED' 'char' '';
'InstitutionAddress' 'RECOMMENDED' 'char' '';
'InstitutionalDepartmentName' ' RECOMMENDED' 'char' '';
'DeviceSerialNumber' 'RECOMMENDED' 'char' '';
'SamplingFrequency' 'REQUIRED' '' '';
'EEGChannelCount' 'RECOMMENDED' '' '';
'EOGChannelCount' 'RECOMMENDED' '' 0;
'ECGChannelCount' 'RECOMMENDED' '' 0;
'EMGChannelCount' 'RECOMMENDED' '' 0;
'EEGReference' 'REQUIRED' 'char' 'Unknown';
'PowerLineFrequency' 'REQUIRED' '' 'n/a';
'EEGGround' 'RECOMMENDED ' 'char' '';
'HeadCircumference' 'OPTIONAL ' '' 0;
'MiscChannelCount' ' OPTIONAL' '' '';
'TriggerChannelCount' 'RECOMMENDED' '' ''; % double in Bucanl's fork
'EEGPlacementScheme' 'RECOMMENDED' 'char' '';
'Manufacturer' 'RECOMMENDED' 'char' '';
'ManufacturersModelName' 'OPTIONAL' 'char' '';
'CapManufacturer' 'RECOMMENDED' 'char' 'Unknown';
'CapManufacturersModelName' 'OPTIONAL' 'char' '';
'HardwareFilters' 'OPTIONAL' 'struct' 'n/a';
'SoftwareFilters' 'REQUIRED' 'struct' 'n/a';
'RecordingDuration' 'RECOMMENDED' '' 'n/a';
'RecordingType' 'RECOMMENDED' 'char' '';
'EpochLength' 'RECOMMENDED' '' 'n/a';
'SoftwareVersions' 'RECOMMENDED' 'char' '';
'SubjectArtefactDescription' 'OPTIONAL' 'char' '' };
tInfo = bids_checkfields(tInfo, tInfoFields, 'tInfo');
if any(contains(tInfo.TaskName, '_')) || any(contains(tInfo.TaskName, ' '))
error('Task name cannot contain underscore or space character(s)');
end
jsonwrite([fileOutRed '_eeg.json' ], tInfo,struct('indent',' '));