diff --git a/.github/workflows/check_md_links.yml b/.github/workflows/check_md_links.yml
new file mode 100644
index 00000000..c54aac1c
--- /dev/null
+++ b/.github/workflows/check_md_links.yml
@@ -0,0 +1,18 @@
+name: Check Markdown links
+
+# checking for any dead links in markdown files
+
+on:
+ push:
+ branches:
+ - master
+ - dev
+ pull_request:
+ branches: '*'
+
+jobs:
+ markdown-link-check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ - uses: gaurav-nelson/github-action-markdown-link-check@v1
\ No newline at end of file
diff --git a/.github/workflows/miss_hit.yml b/.github/workflows/miss_hit.yml
new file mode 100644
index 00000000..d4cb7ae8
--- /dev/null
+++ b/.github/workflows/miss_hit.yml
@@ -0,0 +1,39 @@
+name: miss_hit
+
+on:
+ push:
+ branches:
+ - master
+ - dev
+ pull_request:
+ branches: '*'
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+
+ - uses: actions/checkout@v2
+ with:
+ submodules: true
+ fetch-depth: 1
+
+ - name: Set up Python 3.6
+ uses: actions/setup-python@v2
+ with:
+ python-version: 3.6
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip setuptools
+ pip3 install install miss_hit
+
+ - name: Miss_hit code quality
+ run: |
+ mh_metric . --ci
+
+ - name: Miss_hit code style
+ run: |
+ mh_style .
diff --git a/.gitignore b/.gitignore
index da011f09..3a9f5620 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,13 +7,14 @@
# exclude content of logfiles folders
*output*
-*.tsv
*.mat
# exclude temp files from tests and coverage
*test_code_report.txt
*coverage*
+*filteredBy*
+
tests/*.nii*
tests/*.json*
tests/*.tsv*
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 00000000..6e0d1ce8
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,13 @@
+{
+ "parser": "markdown",
+ "proseWrap": "always",
+ "tabWidth": 2,
+ "overrides": [
+ {
+ "files": "*.md",
+ "options": {
+ "tabWidth": 4
+ }
+ }
+ ]
+}
diff --git a/.remarkrc b/.remarkrc
new file mode 100644
index 00000000..201ce70e
--- /dev/null
+++ b/.remarkrc
@@ -0,0 +1,11 @@
+{
+ "plugins": [
+ "preset-lint-consistent",
+ "preset-lint-markdown-style-guide",
+ "preset-lint-recommended",
+ ["lint-no-duplicate-headings", false],
+ ["lint-list-item-indent", "tab-size"],
+ ["lint-maximum-line-length", true],
+ ["lint-maximum-heading-length", false]
+ ]
+}
diff --git a/.travis.yml b/.travis.yml
index 73839af7..d5cfa910 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,12 +6,19 @@
dist: bionic
# Language and version
-language: python
-python:
- - "3.6" # current default Python on Travis CI
+language: node_js
+node_js:
+ - "10"
cache:
apt: true # only works with Pro version
+ directories:
+ - node_modules # NPM packages for the remark markdown linter
+
+branches:
+ only: # only run the CI for those branches
+ - master
+ - dev
env:
global: # Define environment variables for bash
@@ -26,9 +33,7 @@ before_install:
- travis_retry sudo apt-get -y install nodejs
- travis_retry sudo apt-get -y install npm
# Install BIDS-Validator
- - sudo npm install -g bids-validator
- # Install miss_hit linter
- - pip3 install miss_hit
+ - sudo npm install -g bids-validator@1.5.4
install:
# make octave file the JSONio submodule
@@ -43,9 +48,15 @@ before_script:
jobs:
include:
+
- name: "BIDS validator: create and check dataset"
script: octave $OCTFLAGS --eval "test_makeRawDataset" && bids-validator `pwd`/output/raw/ --ignoreNiftiHeaders
- - name: "miss_hit: checking code quality"
- script: mh_metric . --ci
- - name: "miss_hit: checking code style"
- script: mh_style .
+
+ - name: "Check markdown"
+ before_script:
+ - npm install `cat npm-requirements.txt`
+ script:
+ - remark README.md --frail
+ - remark ./notebooks/ --frail
+ - remark ./tests/ --frail
+ - remark ./docs/ --frail
diff --git a/README.md b/README.md
index 4db24351..1a21bbd2 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+
+
**Try it**
[](https://mybinder.org/v2/gh/cpp-lln-lab/CPP_BIDS/master?filepath=notebooks%2Fbasic_usage.ipynb)
@@ -5,7 +7,7 @@
**Unit tests and coverage**
[](https://github.com/cpp-lln-lab/CPP_BIDS/actions)
-
+
[](https://codecov.io/gh/cpp-lln-lab/CPP_BIDS)
@@ -15,64 +17,81 @@
**Contributors**
-[](#contributors-)
+[](#contributors-)
+
+* * *
----
-
# CPP_BIDS
-
-* 1. [Output format](#Outputformat)
- * 1.1. [Modality agnostic aspect](#Modalityagnosticaspect)
-* 2. [Documentation](#Documentation)
-* 3. [Contributing](#Contributing)
- * 3.1. [Guidestyle](#Guidestyle)
- * 3.2. [BIDS naming convention](#BIDSnamingconvention)
- * 3.3. [Contributors ✨](#Contributors)
+
+
+- [CPP_BIDS](#cpp_bids)
+- [Output format](#output-format)
+ - [Modality agnostic aspect](#modality-agnostic-aspect)
+- [Documentation](#documentation)
+- [Contributing](#contributing)
+ - [Guidestyle](#guidestyle)
+ - [BIDS naming convention](#bids-naming-convention)
+ - [Change log](#change-log)
+ - [Contributors ✨](#contributors-)
+
+
-
-
+
-A set of function for matlab and octave to create [BIDS-compatible](https://bids-specification.readthedocs.io/en/stable/) folder structure and filenames for the output of behavioral, EEG, fMRI, eyetracking studies.
+A set of function for matlab and octave to create
+[BIDS-compatible](https://bids-specification.readthedocs.io/en/stable/) folder
+structure and filenames for the output of behavioral, EEG, fMRI, eyetracking
+studies.
-## 1. Output format
+## Output format
-### 1.1. Modality agnostic aspect
+### Modality agnostic aspect
-Subjects, session and run number labels will be numbers with zero padding up to 3 values (e.g subject 1 will become `sub-001`).
+Subjects, session and run number labels will be numbers with zero padding up to
+3 values (e.g subject 1 will become `sub-001`).
-A session folder will ALWAYS be created even if not requested (default will be `ses-001`).
+A session folder will ALWAYS be created even if not requested (default will be
+`ses-001`).
Task labels will be printed in camelCase in the filenames.
-Time stamps are added directly in the filename by adding a suffix `_date-YYYYMMDDHHMM` which makes the file name non-BIDS compliant. This was added to prevent overwriting files in case a certain run needs to be done a second time because of a crash (Some of us are paranoid about keeping even cancelled runs during my experiments). This suffix should be removed to make the data set BIDS compliant. See `convertSourceToRaw.m` for more details.
+Time stamps are added directly in the filename by adding a suffix
+`_date-YYYYMMDDHHMM` which makes the file name non-BIDS compliant. This was
+added to prevent overwriting files in case a certain run needs to be done a
+second time because of a crash (Some of us are paranoid about keeping even
+cancelled runs during my experiments). This suffix should be removed to make the
+data set BIDS compliant. See `convertSourceToRaw.m` for more details.
For example:
-```
+```bash
sub-090/ses-003/sub-090_ses-003_task-auditoryTask_run-023_events_date-202007291536.tsv
```
-## 2. Documentation
+## Documentation
-- [Installation](./docs/installation.md)
-- [How to use it: jupyter notebooks](./notebooks)
-- [Functions description](./docs/functions_description.md)
+- [Installation](./docs/installation.md)
+- [How to use it: jupyter notebooks](./notebooks)
+- [Functions description](./docs/functions-description.md)
-## 3. Contributing
+## Contributing
Feel free to open issues to report a bug and ask for improvements.
-### 3.1. Guidestyle
+### Guidestyle
- We use camelCase.
-- We keep the McCabe complexity as reported by the [check_my_code function](https://github.com/Remi-Gau/check_my_code) below 15.
-- We use the [MISS_HIT linter](https://florianschanda.github.io/miss_hit/style_checker.html) to automatically fix some linting issues.
-### 3.2. BIDS naming convention
+- We keep the McCabe complexity as reported by the
+ [check_my_code function](https://github.com/Remi-Gau/check_my_code)
+ below 15.
+
+- We use the
+ [MISS_HIT linter](https://florianschanda.github.io/miss_hit/style_checker.html)
+ to automatically fix some linting issues.
+
+### BIDS naming convention
Here are the naming templates used.
@@ -104,16 +123,13 @@ The format used by the MATLAB toolbox EEGLAB (Each recording consisting of a .se
Biosemi data format (Each recording consisting of a .bdf file) -->
-
-
- MEG
???
- Eyetracker
-current format
-`_recording-eyetracking_physio.tsv.gz`
+current format `_recording-eyetracking_physio.tsv.gz`
future BEP format in a dedicated eyetracker folder
`sub-[_ses-][_acq-]_task-_eyetrack.`
@@ -125,17 +141,21 @@ future BEP format in a dedicated eyetracker folder
`[_recording-]_stim.tsv.gz`
`[_recording-]_stim.json`
-### change log
+### Change log
-### 3.3. Contributors ✨
+### Contributors ✨
-Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
+Thanks goes to these wonderful people
+([emoji key](https://allcontributors.org/docs/en/emoji-key)):
+
+
+
CerenB 💻 🎨 📖 📓 🤔 🐛
@@ -145,7 +165,11 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
+
+
-This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
+This project follows the
+[all-contributors](https://github.com/all-contributors/all-contributors)
+specification. Contributions of any kind welcome!
diff --git a/docs/functions_description.md b/docs/functions-description.md
similarity index 64%
rename from docs/functions_description.md
rename to docs/functions-description.md
index e8fefe33..b6c3ab0d 100644
--- a/docs/functions_description.md
+++ b/docs/functions-description.md
@@ -1,63 +1,74 @@
# functions description
-
-* 1. [userInputs](#userInputs)
-* 2. [createFilename](#createFilename)
-* 3. [saveEventsFile](#saveEventsFile)
-* 4. [checkCFG](#checkCFG)
- * 4.1. [CFG content](#CFGcontent)
-* 5. [createBoldJson](#createBoldJson)
+
-
-
+
-## 1. userInputs
+- [functions description](#functions-description)
+ - [userInputs](#userinputs)
+ - [createFilename](#createfilename)
+ - [saveEventsFile](#saveeventsfile)
+ - [checkCFG](#checkcfg)
+ - [CFG content](#cfg-content)
+ - [createBoldJson](#createboldjson)
-Get subject, run and session number and make sure they are positive integer values.
+
-By default this will return `cfg.subject.session = 1` even if you asked it to omit enquiring about sessions. This means
-that the folder tree will always include a session folder.
+
+
+## userInputs
+
+Get subject, run and session number and make sure they are positive integer
+values.
+
+By default this will return `cfg.subject.session = 1` even if you asked it to
+omit enquiring about sessions. This means that the folder tree will always
+include a session folder.
```matlab
[cfg] = userInputs(cfg)
```
-If you use it with `cfg.subject.askGrpSess = [0 0]`, it won't ask you about group or session.
-
-If you use it with `cfg.subject.askGrpSess = [1]`, it will only ask you about group
+If you use it with `cfg.subject.askGrpSess = [0 0]`, it won't ask you about
+group or session.
-If you use it with `cfg.subject.askGrpSess = [0 1]`, it will only ask you about session
+If you use it with `cfg.subject.askGrpSess = [1]`, it will only ask you about
+group
-If you use it with `cfg.subject.askGrpSess = [1 1]`, it will ask you about both. This is the default behavior.
+If you use it with `cfg.subject.askGrpSess = [0 1]`, it will only ask you about
+session
+If you use it with `cfg.subject.askGrpSess = [1 1]`, it will ask you about both.
+This is the default behavior.
-## 2. createFilename
+## createFilename
-Create the BIDS compliant directories and filenames (but not the files) for the behavioral output for this subject / session / run.
+Create the BIDS compliant directories and filenames (but not the files) for the
+behavioral output for this subject / session / run.
The folder tree will always include a session folder.
-It will also create the right filename for the eye-tracking data file if you ask it.
+It will also create the right filename for the eye-tracking data file if you ask
+it.
For the moment the date of acquisition is appended to the filename
+
- can work for behavioral experiment if `cfg.testingDevice` is set to `pc`,
- can work for fMRI experiment if `cfg.testingDevice` is set to `mri`,
- can work for simple eyetracking data if `cfg.eyeTracker.do` is set to 1.
-## 3. saveEventsFile
+## saveEventsFile
Function to save output files for events that will be BIDS compliant.
-If the user DOES NOT provide `onset`, `trial_type`, this events will be skipped. `duration` will be set to `n/a` if no value is provided.
+If the user DOES NOT provide `onset`, `trial_type`, this events will be skipped.
+`duration` will be set to `n/a` if no value is provided.
-## 4. checkCFG
+## checkCFG
Check that we have all the fields that we need in the experiment parameters.
-### 4.1. CFG content
+### CFG content
```matlab
% The following can be modified by users but their effect might
@@ -123,22 +134,33 @@ cfg.fileName.datasetDescription
```
-## 5. createBoldJson
+## createBoldJson
-```
+```bash
createBoldJson(cfg)
```
-This function creates a very light-weight version of the side-car JSON file for a BOLD functional run.
+This function creates a very light-weight version of the side-car JSON file for
+a BOLD functional run.
-This will only contain the minimum BIDS requirement and will likely be less complete than the info you could from DICOM conversion.
+This will only contain the minimum BIDS requirement and will likely be less
+complete than the info you could from DICOM conversion.
-If you put the following line at the end of your experiment script, it will dump the content of the `extraInfo` structure in the json file.
+If you put the following line at the end of your experiment script, it will dump
+the content of the `extraInfo` structure in the json file.
-```
+```bash
createBoldJson(cfg, extraInfo)
```
-This allows to add all the parameters that you used to run your experiment in a human readable format: so that when you write your methods sections 2 years later ("the reviewer asked me for the size of my fixation cross... FML"), the info you used WHEN you ran the experiment is saved in an easily accessible text format. For the love of the flying spaghetti monster do not save all your parameters in a `.mat` file: think of the case when you won't have matlab or octave installed on a computer (plus not everyone uses those).
-
-Also to reading your experiment parameters, you won't have to read it from the `setParameters.m` file and wonder if those might have been modified when running the experiment and you did not commit and tagged that change with git.
\ No newline at end of file
+This allows to add all the parameters that you used to run your experiment in a
+human readable format: so that when you write your methods sections 2 years
+later ("the reviewer asked me for the size of my fixation cross... FML"), the
+info you used WHEN you ran the experiment is saved in an easily accessible text
+format. For the love of the flying spaghetti monster do not save all your
+parameters in a `.mat` file: think of the case when you won't have matlab or
+octave installed on a computer (plus not everyone uses those).
+
+Also to reading your experiment parameters, you won't have to read it from the
+`setParameters.m` file and wonder if those might have been modified when running
+the experiment and you did not commit and tagged that change with git.
diff --git a/docs/installation.md b/docs/installation.md
index 756a88ab..89ed6d1c 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -1,20 +1,22 @@
# Installation
-
-* 1. [Download with git](#Downloadwithgit)
-* 2. [Add as a submodule](#Addasasubmodule)
- * 2.1. [Example for submodule usage](#Exampleforsubmoduleusage)
-* 3. [Direct download](#Directdownload)
+
-
-
+
-## 1. Download with git
+- [Installation](#installation)
+ - [Download with git](#download-with-git)
+ - [Add as a submodule](#add-as-a-submodule)
+ - [Example for submodule usage](#example-for-submodule-usage)
+ - [Direct download](#direct-download)
-``` bash
+
+
+
+
+## Download with git
+
+```bash
cd fullpath_to_directory_where_to_install
# use git to download the code
@@ -28,22 +30,25 @@ matlab -nojvm -nosplash -r "addpath(fullfile(pwd, 'src')); savepath ();"
```
Then get the latest commit:
+
```bash
# from the directory where you downloaded the code
git pull origin master
```
-To work with a specific version, create a branch at a specific version tag number
+To work with a specific version, create a branch at a specific version tag
+number
+
```bash
# creating and checking out a branch that will be called version1 at the version tag v0.0.1
git checkout -b version1 v0.0.1
```
-## 2. Add as a submodule
+## Add as a submodule
Add it as a submodule in the repo you are working on.
-``` bash
+```bash
cd fullpath_to_directory_where_to_install
# use git to download the code
@@ -56,17 +61,21 @@ cd CPP_BIDS
matlab -nojvm -nosplash -r "addpath(fullfile(pwd, 'src'))"
```
-To get the latest commit you then need to update the submodule with the information
-on its remote repository and then merge those locally.
+To get the latest commit you then need to update the submodule with the
+information on its remote repository and then merge those locally.
+
```bash
git submodule update --remote --merge
```
Remember that updates to submodules need to be committed as well.
-### 2.1. Example for submodule usage
+### Example for submodule usage
+
+So say you want to clone a repo that has some nested submodules, then you would
+type this to get the content of all the submodules at once (here with assumption
+that you want to clone my experiment repo):
-So say you want to clone a repo that has some nested submodules, then you would type this to get the content of all the submodules at once (here with assumption that you want to clone my experiment repo):
```bash
# clone the repo
git clone https://github.com/user_name/myExperiment.git
@@ -83,15 +92,13 @@ git submodule foreach --recursive 'git submodule init'
git submodule foreach --recursive 'git submodule update'
```
-
-## 3. Direct download
+## Direct download
Download the code. Unzip. And add to the matlab path.
-Pick a specific version:
-
-https://github.com/cpp-lln-lab/CPP_BIDS/releases
-
-Or take the latest commit (NOT RECOMMENDED):
+Pick a specific version from
+[HERE](https://github.com/cpp-lln-lab/CPP_BIDS/releases)
-https://github.com/cpp-lln-lab/CPP_BIDS/archive/master.zip
\ No newline at end of file
+Or take the
+[latest commit](https://github.com/cpp-lln-lab/CPP_BIDS/archive/master.zip) (NOT
+RECOMMENDED).
diff --git a/lib/bids-matlab b/lib/bids-matlab
index 71257b51..bda01141 160000
--- a/lib/bids-matlab
+++ b/lib/bids-matlab
@@ -1 +1 @@
-Subproject commit 71257b51986f5075bb903eb090fe28b9b6dc3ebf
+Subproject commit bda011411defe36c00d1d501b6842fd677af32fc
diff --git a/manualTests/test_createDataDictionary.m b/manualTests/test_createDataDictionary.m
index d1f71138..48611447 100644
--- a/manualTests/test_createDataDictionary.m
+++ b/manualTests/test_createDataDictionary.m
@@ -37,7 +37,7 @@ function test_createDataDictionaryBasic()
funcDir = fullfile(outputDir, 'source', 'sub-001', 'ses-001', 'func');
jsonFilename = ['sub-001_ses-001_task-testtask_run-001_events_date-' ...
- cfg.fileName.date '.json'];
+ cfg.fileName.date '.json'];
% test
assertTrue(exist(fullfile(funcDir, jsonFilename), 'file') == 2);
@@ -47,7 +47,7 @@ function test_createDataDictionaryBasic()
% data to test against
expectedStruct = bids.util.jsondecode( ...
- fullfile(pwd, 'testData', 'eventsDataDictionary.json'));
+ fullfile(pwd, 'testData', 'eventsDataDictionary.json'));
% test
assertTrue(isequal(expectedStruct, actualStruct));
diff --git a/manualTests/test_createJson.m b/manualTests/test_createJson.m
index c2fd031f..47fbd6ad 100644
--- a/manualTests/test_createJson.m
+++ b/manualTests/test_createJson.m
@@ -36,13 +36,13 @@ function test_createJsonExtra()
fileName = strrep(fileName, '.tsv', '.json');
actualStruct = bids.util.jsondecode(fullfile( ...
- cfg.dir.outputSubject, ...
- cfg.fileName.modality, ...
- fileName));
+ cfg.dir.outputSubject, ...
+ cfg.fileName.modality, ...
+ fileName));
% data to test against
expectedStruct = bids.util.jsondecode( ...
- fullfile(pwd, 'testData', 'extra_bold.json'));
+ fullfile(pwd, 'testData', 'extra_bold.json'));
% test
assertEqual(expectedStruct, actualStruct);
diff --git a/manualTests/test_makeRawDataset.m b/manualTests/test_makeRawDataset.m
index 896b9caf..485a912d 100644
--- a/manualTests/test_makeRawDataset.m
+++ b/manualTests/test_makeRawDataset.m
@@ -205,16 +205,16 @@ function test_makeRawDataset()
boldFilename = 'sub-001_ses-001_task-testtask_run-001_bold.nii.gz';
copyfile( ...
- fullfile('dummyData', 'dummyData.nii.gz'), ...
- fullfile(funcDir, boldFilename));
+ fullfile('dummyData', 'dummyData.nii.gz'), ...
+ fullfile(funcDir, boldFilename));
boldFilename = ['sub-001_ses-001_task-rest', ...
- '_acq-newTYpe_ce-test_dir-yPos_rec-fastRecon', ...
- '_run-001_echo-1_bold.nii.gz'];
+ '_acq-newTYpe_ce-test_dir-yPos_rec-fastRecon', ...
+ '_run-001_echo-1_bold.nii.gz'];
copyfile( ...
- fullfile('dummyData', 'dummyData.nii.gz'), ...
- fullfile(funcDir, boldFilename));
+ fullfile('dummyData', 'dummyData.nii.gz'), ...
+ fullfile(funcDir, boldFilename));
eegDir = fullfile(subjectDir, 'eeg');
megDir = fullfile(subjectDir, 'meg');
@@ -227,20 +227,20 @@ function test_makeRawDataset()
behFilename = 'sub-001_ses-001_task-easyTargetPractice_run-001_beh.tsv';
copyfile( ...
- fullfile('dummyData', 'dummyData.nii.gz'), ...
- fullfile(eegDir, eegFilename));
+ fullfile('dummyData', 'dummyData.nii.gz'), ...
+ fullfile(eegDir, eegFilename));
copyfile( ...
- fullfile('dummyData', 'dummyData.nii.gz'), ...
- fullfile(megDir, megFilename));
+ fullfile('dummyData', 'dummyData.nii.gz'), ...
+ fullfile(megDir, megFilename));
copyfile( ...
- fullfile('dummyData', 'dummyData.nii.gz'), ...
- fullfile(ieegDir, ieegFilename));
+ fullfile('dummyData', 'dummyData.nii.gz'), ...
+ fullfile(ieegDir, ieegFilename));
copyfile( ...
- fullfile('dummyData', 'dummyData.nii.gz'), ...
- fullfile(behDir, behFilename));
+ fullfile('dummyData', 'dummyData.nii.gz'), ...
+ fullfile(behDir, behFilename));
%% actually do the conversion of the source data thus created
clear;
diff --git a/miss_hit.cfg b/miss_hit.cfg
index f784081c..60976e52 100644
--- a/miss_hit.cfg
+++ b/miss_hit.cfg
@@ -1,8 +1,8 @@
# style guide (https://florianschanda.github.io/miss_hit/style_checker.html)
line_length: 100
regex_function_name: "[a-z]+(([A-Z]){1}[A-Za-z]+)*"
-suppress_rule: "copyright_notice"
exclude_dir: "lib"
+copyright_entity: "CPP_BIDS developers"
# metrics limit for the code quality (https://florianschanda.github.io/miss_hit/metrics.html)
metric "cnest": limit 4
diff --git a/notebooks/README.md b/notebooks/README.md
index 9ec8cd6d..21a5da9f 100644
--- a/notebooks/README.md
+++ b/notebooks/README.md
@@ -1,11 +1,17 @@
# README
-1. Make sure that you have Octave installed.
-2. If you have Conda/Jupyter/pip installed, go to step 4.
-3. Download the [Anaconda Installer](https://www.anaconda.com/products/individual) and install it.
-4. Install [Octave kernel](https://pypi.org/project/octave-kernel/):
- ```
- pip install octave_kernel
- ```
-5. Run `jupyter notebook` in your terminal. `Octave` should appear on the list
- for creating a new notebook.
+1. Make sure that you have Octave installed.
+
+1. If you have Conda/Jupyter/pip installed, go to step 4. Check if Conda is
+ installed properly by typing `conda list` into your terminal
+
+1. Download the
+ [Anaconda Installer](https://www.anaconda.com/products/individual) and
+ install it. If using miniconda, run `conda install jupyter` to download and
+ install the Jupyter Notebook package.
+
+1. Install [Octave kernel](https://pypi.org/project/octave-kernel/):
+ `pip install octave_kernel`
+
+1. Run `jupyter notebook` in your terminal. `Octave` should appear on the list
+ for creating a new notebook.
diff --git a/npm-requirements.txt b/npm-requirements.txt
new file mode 100644
index 00000000..061f9ade
--- /dev/null
+++ b/npm-requirements.txt
@@ -0,0 +1,6 @@
+remark-cli@5.0.0
+remark-lint@6.0.2
+remark-preset-lint-recommended@3.0.2
+remark-preset-lint-markdown-style-guide@2.1.2
+remark-preset-lint-consistent
+
diff --git a/src/checkCFG.m b/src/checkCFG.m
index b6666647..df2a69a8 100644
--- a/src/checkCFG.m
+++ b/src/checkCFG.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function cfg = checkCFG(cfg)
% cfg = checkCFG(cfg)
%
@@ -21,9 +23,9 @@
fieldsToSet.fileName.dateFormat = 'yyyymmddHHMM';
fieldsToSet.dir.output = fullfile( ...
- fileparts(mfilename('fullpath')), ...
- '..', ...
- 'output');
+ fileparts(mfilename('fullpath')), ...
+ '..', ...
+ 'output');
fieldsToSet.subject.askGrpSess = [true true];
fieldsToSet.subject.sessionNb = 1; % in case no session was provided
@@ -31,11 +33,9 @@
fieldsToSet.testingDevice = 'pc';
- fieldsToSet.eyeTracker = struct();
-
- fieldsToSet.eyeTracker.do = false;
+ fieldsToSet = eyetrackerDefaults(fieldsToSet);
- fieldsToSet = mriDefaults(fieldsToSet);
+ fieldsToSet = setSuffixes(fieldsToSet);
%% BIDS
@@ -53,7 +53,7 @@
end
-function fieldsToSet = mriDefaults(fieldsToSet)
+function fieldsToSet = setSuffixes(fieldsToSet)
% for file naming and JSON
fieldsToSet.suffix.contrastEnhancement = [];
@@ -246,3 +246,21 @@
fieldsToSet.bids.ieeg = orderfields(fieldsToSet.bids.beh);
end
+
+function fieldsToSet = eyetrackerDefaults(fieldsToSet)
+
+ fieldsToSet.eyeTracker.do = false;
+ fieldsToSet.eyeTracker.SamplingFrequency = [];
+ fieldsToSet.eyeTracker.PupilPositionType = '';
+ fieldsToSet.eyeTracker.RawSamples = [];
+ fieldsToSet.eyeTracker.Manufacturer = '';
+ fieldsToSet.eyeTracker.ManufacturersModelName = '';
+ fieldsToSet.eyeTracker.SoftwareVersions = '';
+ fieldsToSet.eyeTracker.CalibrationType = 'HV5';
+ fieldsToSet.eyeTracker.CalibrationPosition = '';
+ fieldsToSet.eyeTracker.CalibrationDistance = '';
+ fieldsToSet.eyeTracker.MaximalCalibrationError = [];
+ fieldsToSet.eyeTracker.AverageCalibrationError = [];
+ fieldsToSet.eyeTracker.RawDataFilters = {};
+
+end
diff --git a/src/convertSourceToRaw.m b/src/convertSourceToRaw.m
index bfc846ba..f4b4ea4f 100644
--- a/src/convertSourceToRaw.m
+++ b/src/convertSourceToRaw.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function convertSourceToRaw(cfg)
% convertSourceToRaw(cfg)
%
@@ -14,14 +16,17 @@ function convertSourceToRaw(cfg)
% add dummy README and CHANGE file
copyfile(fullfile( ...
- fileparts(mfilename('fullpath')), '..', 'manualTests', 'dummyData', 'README'), ...
- sourceDir);
+ fileparts(mfilename('fullpath')), '..', 'manualTests', 'dummyData', ...
+ 'README'), ...
+ sourceDir);
copyfile(fullfile( ...
- fileparts(mfilename('fullpath')), '..', 'manualTests', 'dummyData', 'CHANGES'), ...
- sourceDir);
+ fileparts(mfilename('fullpath')), '..', 'manualTests', 'dummyData', ...
+ 'CHANGES'), ...
+ sourceDir);
copyfile(fullfile( ...
- fileparts(mfilename('fullpath')), '..', 'manualTests', 'dummyData', '.bidsignore'), ...
- sourceDir);
+ fileparts(mfilename('fullpath')), '..', 'manualTests', 'dummyData', ...
+ '.bidsignore'), ...
+ sourceDir);
copyfile(sourceDir, rawDir);
diff --git a/src/createDataDictionary.m b/src/createDataDictionary.m
index f424dfc4..62639f0d 100644
--- a/src/createDataDictionary.m
+++ b/src/createDataDictionary.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function createDataDictionary(cfg, logFile)
% createDataDictionary(cfg, logFile)
%
@@ -7,24 +9,24 @@ function createDataDictionary(cfg, logFile)
opts.Indent = ' ';
- fileName = strrep(cfg.fileName.events, '.tsv', '.json');
+ fileName = strrep(logFile(1).filename, '.tsv', '.json');
fileName = fullfile( ...
- cfg.dir.outputSubject, ...
- cfg.fileName.modality, ...
- fileName);
+ cfg.dir.outputSubject, ...
+ cfg.fileName.modality, ...
+ fileName);
jsonContent = struct( ...
- 'onset', struct( ...
- 'Description', 'time elapsed since experiment start', ...
- 'Unit', 's'), ...
- 'trial_type', struct( ...
- 'Description', 'types of trial', ...
- 'Levels', ''), ...
- 'duration', struct( ...
- 'Description', 'duration of the event or the block', ...
- 'Unit', 's') ...
- );
+ 'onset', struct( ...
+ 'Description', 'time elapsed since experiment start', ...
+ 'Unit', 's'), ...
+ 'trial_type', struct( ...
+ 'Description', 'types of trial', ...
+ 'Levels', ''), ...
+ 'duration', struct( ...
+ 'Description', 'duration of the event or the block', ...
+ 'Unit', 's') ...
+ );
% transfer content of extra fields to json content
namesExtraColumns = returnNamesExtraColumns(logFile);
diff --git a/src/createDatasetDescription.m b/src/createDatasetDescription.m
index 4240d5ec..38e44fa2 100644
--- a/src/createDatasetDescription.m
+++ b/src/createDatasetDescription.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function createDatasetDescription(cfg)
% createDatasetDescription(cfg)
%
@@ -7,8 +9,8 @@ function createDatasetDescription(cfg)
opts.Indent = ' ';
fileName = fullfile( ...
- cfg.dir.output, 'source', ...
- 'dataset_description.json');
+ cfg.dir.output, 'source', ...
+ 'dataset_description.json');
jsonContent = cfg.bids.datasetDescription;
diff --git a/src/createFilename.m b/src/createFilename.m
index cf4e350f..4f6addb7 100644
--- a/src/createFilename.m
+++ b/src/createFilename.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function cfg = createFilename(cfg)
% cfg = createFilename(cfg)
%
@@ -82,10 +84,10 @@
% output dir
cfg.dir.outputSubject = fullfile ( ...
- cfg.dir.output, ...
- 'source', ...
- ['sub-' subjectGrp, sprintf(pattern, subjectNb)], ...
- ['ses-', sprintf(pattern, sessionNb)]);
+ cfg.dir.output, ...
+ 'source', ...
+ ['sub-' subjectGrp, sprintf(pattern, subjectNb)], ...
+ ['ses-', sprintf(pattern, sessionNb)]);
[~, ~, ~] = mkdir(cfg.dir.output);
[~, ~, ~] = mkdir(cfg.dir.outputSubject);
@@ -100,22 +102,22 @@
%% MRI
% set values for the suffixes for the different fields in the BIDS name
fields2Check = { ...
- 'acquisition', ...
- 'contrastEnhancement', ...
- 'echo', ...
- 'phaseEncodingDirection', ...
- 'reconstruction', ...
- 'recording' ...
- };
+ 'acquisition', ...
+ 'contrastEnhancement', ...
+ 'echo', ...
+ 'phaseEncodingDirection', ...
+ 'reconstruction', ...
+ 'recording' ...
+ };
targetFields = { ...
- 'acq', ...
- 'ce', ...
- 'echo', ...
- 'dir', ...
- 'rec', ...
- 'recording' ...
- };
+ 'acq', ...
+ 'ce', ...
+ 'echo', ...
+ 'dir', ...
+ 'rec', ...
+ 'recording' ...
+ };
for iField = 1:numel(fields2Check)
@@ -156,14 +158,14 @@
thisDate = cfg.fileName.date;
cfg.fileName.datasetDescription = fullfile ( ...
- cfg.dir.output, ...
- 'dataset_description.json');
+ cfg.dir.output, ...
+ 'dataset_description.json');
% create base fileName
fileNameBase = ...
['sub-', subjectGrp, sprintf(pattern, subjectNb), ...
- '_ses-', sprintf(pattern, sessionNb), ...
- '_task-', taskName];
+ '_ses-', sprintf(pattern, sessionNb), ...
+ '_task-', taskName];
cfg.fileName.base = fileNameBase;
switch modality
@@ -171,16 +173,16 @@
case 'func'
basename = [fileNameBase, ...
- acqSuffix, ceSuffix, ...
- dirSuffix, recSuffix, ...
- runSuffix, echoSuffix];
+ acqSuffix, ceSuffix, ...
+ dirSuffix, recSuffix, ...
+ runSuffix, echoSuffix];
case 'beh'
basename = ...
[fileNameBase, ...
- acqSuffix, ...
- runSuffix];
+ acqSuffix, ...
+ runSuffix];
otherwise
@@ -204,18 +206,18 @@ function talkToMe(cfg)
if cfg.verbose > 0
fprintf(1, '\nData will be saved in this directory:\n\t%s\n', ...
- fullfile(cfg.dir.outputSubject, cfg.fileName.modality));
+ fullfile(cfg.dir.outputSubject, cfg.fileName.modality));
fprintf(1, '\nData will be saved in this file:\n\t%s\n', ...
- cfg.fileName.events);
+ cfg.fileName.events);
if cfg.eyeTracker.do
fprintf(1, '\nEyetracking data will be saved in this directory:\n\t%s\n', ...
- fullfile(cfg.dir.outputSubject, 'eyetracker'));
+ fullfile(cfg.dir.outputSubject, 'eyetracker'));
fprintf(1, '\nEyetracking data will be saved in this file:\n\t%s\n', ...
- cfg.fileName.eyetracker);
+ cfg.fileName.eyetracker);
end
diff --git a/src/createJson.m b/src/createJson.m
index 15bbbe1e..fdc42a35 100644
--- a/src/createJson.m
+++ b/src/createJson.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function createJson(varargin)
% createBoldJson(cfg, varargin)
%
@@ -37,9 +39,9 @@ function createJson(varargin)
fileName = strrep(fileName, '.tsv', '.json');
fileName = fullfile( ...
- cfg.dir.outputSubject, ...
- modality, ...
- fileName);
+ cfg.dir.outputSubject, ...
+ modality, ...
+ fileName);
%% add content of extraInfo to the JSON content
@@ -113,11 +115,12 @@ function errorCreateJson(identifier, varargin)
case 'wrongInputType'
errorStruct.message = ['The second input must be a string (modality)' ...
- 'or a structure (extraInfo)'];
+ 'or a structure (extraInfo)'];
case 'wrongModalityInput'
errorStruct.message = sprintf(['The given modality is not valid: %s.\n', ...
- 'Only the following string are accepted: beh, func, eeg, ieeg, meg'], ...
- varargin{1});
+ 'Only the following string are accepted: ' ...
+ 'beh, func, eeg, ieeg, meg'], ...
+ varargin{1});
end
diff --git a/src/miss_hit.cfg b/src/miss_hit.cfg
deleted file mode 100644
index 25cb5611..00000000
--- a/src/miss_hit.cfg
+++ /dev/null
@@ -1,10 +0,0 @@
-# style guide (https://florianschanda.github.io/miss_hit/style_checker.html)
-line_length: 100
-regex_function_name: "[a-z]+(([A-Z]){1}[A-Za-z]+)*"
-suppress_rule: "copyright_notice"
-
-# metrics limit for the code quality (https://florianschanda.github.io/miss_hit/metrics.html)
-metric "cnest": limit 4
-metric "file_length": limit 500
-metric "cyc": limit 15
-metric "parameters": limit 6
\ No newline at end of file
diff --git a/src/readAndFilterLogfile.m b/src/readAndFilterLogfile.m
new file mode 100644
index 00000000..1f791bab
--- /dev/null
+++ b/src/readAndFilterLogfile.m
@@ -0,0 +1,101 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
+function outputFiltered = readAndFilterLogfile(columnName, filterBy, saveOutputTsv, varargin)
+ % outputFiltered = readAndFilterLogfile(columnName, filterBy, saveOutputTsv, varargin)
+ %
+ % It will display in the command window the content of the `output.tsv' filtered by one element
+ % of a target column.
+ %
+ % INPUT:
+ %
+ % - columnName: string, the header of the column where the content of insterest is stored
+ % (e.g., for 'trigger' will be 'trial type')
+ % - filterBy: string, the content of the column you want to filter out. It can take just
+ % part of the content name (e.g., you want to display the triggers and you have
+ % 'trigger_motion' and 'trigger_static', 'trigger' as input will do)
+ % - saveOutputTsv: boolean to save the filtered ouput
+ % - varargin: either cfg (to display the last run output) or the file path as string
+ %
+ % OUTPUT:
+ %
+ % - outputFiltered: dataset with only the specified content, to see it in the command window
+ % use display(outputFiltered)
+
+ % Create tag to add to output file in case you want to save it
+ outputFilterTag = ['_filteredBy-' columnName '_' filterBy '.tsv'];
+
+ % Checke if input is cfg or the file path and assign the output filename for later saving
+ if ischar(varargin{1})
+
+ tsvFile = varargin{1};
+
+ elseif isstruct(varargin{1})
+
+ tsvFile = fullfile(varargin{1}.dir.outputSubject, ...
+ varargin{1}.fileName.modality, ...
+ varargin{1}.fileName.events);
+
+ end
+
+ % Create output file name
+ outputFileName = strrep(tsvFile, '.tsv', outputFilterTag);
+
+ % Check if the file exists
+ if ~exist(tsvFile, 'file')
+ error([newline 'Input file does not exist: %s'], tsvFile);
+ end
+
+ try
+ % Read the the tsv file and store each column in a field of `output` structure
+ output = bids.util.tsvread(tsvFile);
+ catch
+ % Add the 'bids-matlab' in case is not in the path
+ addpath(genpath(fullfile(pwd, '..', 'lib')));
+ % Read the the tsv file and store each column in a field of `output` structure
+ output = bids.util.tsvread(tsvFile);
+ end
+
+ % Get the index of the target contentent to filter and display
+ filterIdx = strncmp(output.(columnName), filterBy, length(filterBy));
+
+ % apply the filter
+ listFields = fieldnames(output);
+ for iField = 1:numel(listFields)
+ output.(listFields{iField})(~filterIdx) = [];
+ end
+
+ output = convertStruct(output);
+
+ % Convert the structure to dataset
+ try
+ outputFiltered = struct2dataset(output);
+ catch
+ % dataset not yet supported by octave
+ outputFiltered = output;
+ end
+
+ if saveOutputTsv
+
+ bids.util.tsvwrite(outputFileName, output);
+
+ end
+
+end
+
+function structure = convertStruct(structure)
+ % changes the structure
+ %
+ % from struct.field(i,1) to struct(i,1).field(1)
+
+ fieldsList = fieldnames(structure);
+ tmp = struct();
+
+ for iField = 1:numel(fieldsList)
+ for i = 1:numel(structure.(fieldsList{iField}))
+ tmp(i, 1).(fieldsList{iField}) = structure.(fieldsList{iField})(i, 1);
+ end
+ end
+
+ structure = tmp;
+
+end
diff --git a/src/saveEventsFile.m b/src/saveEventsFile.m
index 949161ff..42976359 100644
--- a/src/saveEventsFile.m
+++ b/src/saveEventsFile.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function [logFile] = saveEventsFile(action, cfg, logFile)
% [logFile] = saveEventsFile(action, cfg, logFile)
%
@@ -152,11 +154,11 @@
% Initialize txt logfiles and empty fields for the standard BIDS
% event file
logFile(1).fileID = fopen( ...
- fullfile( ...
- cfg.dir.outputSubject, ...
- cfg.fileName.modality, ...
- logFile.filename), ...
- 'w');
+ fullfile( ...
+ cfg.dir.outputSubject, ...
+ cfg.fileName.modality, ...
+ logFile.filename), ...
+ 'w');
% print the basic BIDS columns
fprintf(logFile(1).fileID, '%s\t%s\t%s', 'onset', 'duration', 'trial_type');
@@ -217,7 +219,7 @@ function printHeaderExtraColumns(logFile)
if ~ischar(data) && any(isnan(data))
warning('saveEventsFile:missingData', ...
- 'Missing some %s data for this event.', namesExtraColumns{iExtraColumn});
+ 'Missing some %s data for this event.', namesExtraColumns{iExtraColumn});
if cfg.verbose > 1
disp(logFile(iEvent));
@@ -267,7 +269,7 @@ function printHeaderExtraColumns(logFile)
data(end + 1:end + padding) = nan(1, padding);
elseif ~isempty(expectedLength) && isnumeric(data) && max(size(data)) > expectedLength
warning('saveEventsFile:arrayTooLong', ...
- 'A field for this event is longer than expected. Truncating the extra values.');
+ 'A field for this event is longer than expected. Truncating the extra values.');
data = data(1:expectedLength);
end
@@ -291,9 +293,9 @@ function printHeaderExtraColumns(logFile)
any(isempty({onset duration}))
warning('saveEventsFile:emptyEvent', ...
- '\nSkipping saving this event.\n onset: %s \n duration: %s\n', ...
- onset, ...
- duration);
+ '\nSkipping saving this event.\n onset: %s \n duration: %s\n', ...
+ onset, ...
+ duration);
else
@@ -393,10 +395,10 @@ function talkToMe(cfg, logFile)
if cfg.verbose > 0
fprintf(1, '\nData were saved in this file:\n\n%s\n\n', ...
- fullfile( ...
- cfg.dir.outputSubject, ...
- cfg.fileName.modality, ...
- logFile.filename));
+ fullfile( ...
+ cfg.dir.outputSubject, ...
+ cfg.fileName.modality, ...
+ logFile.filename));
end
diff --git a/src/subfun/askForGroupAndOrSession.m b/src/subfun/askForGroupAndOrSession.m
index faad823c..bac91022 100644
--- a/src/subfun/askForGroupAndOrSession.m
+++ b/src/subfun/askForGroupAndOrSession.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function cfg = askForGroupAndOrSession(cfg)
askGrpSess = [true true];
diff --git a/src/subfun/askUserCli.m b/src/subfun/askUserCli.m
index a2222eef..46491136 100644
--- a/src/subfun/askUserCli.m
+++ b/src/subfun/askUserCli.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function responses = askUserCli(questions, responses)
% response = askUserCli(questions)
%
diff --git a/src/subfun/askUserGui.m b/src/subfun/askUserGui.m
index ddf42103..a141c637 100644
--- a/src/subfun/askUserGui.m
+++ b/src/subfun/askUserGui.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function responses = askUserGui(questions, responses)
% boolean for which question should be asked
@@ -10,9 +12,9 @@
% keep asking the question till we get a positive integer value for each
for iQuestion = 1:size(questions.questionsToAsk)
questions.questionsToAsk{iQuestion} = sprintf('%s %s\n %s', ...
- '\color{red}', ...
- questions.questionsToAsk{iQuestion}, ...
- questions.mustBePositiveInteger);
+ '\color{red}', ...
+ questions.questionsToAsk{iQuestion}, ...
+ questions.mustBePositiveInteger);
end
while 1
@@ -32,10 +34,10 @@
fieldDim = repmat([1 50], sum(isQuestionToAsk), 1);
currentResp = inputdlg(quest.questionsToAsk(isQuestionToAsk, 1), ...
- 'Subject info', ...
- fieldDim, ...
- resp(isQuestionToAsk), ...
- opts);
+ 'Subject info', ...
+ fieldDim, ...
+ resp(isQuestionToAsk), ...
+ opts);
resp(isQuestionToAsk) = currentResp;
diff --git a/src/subfun/checkCppBidsDependencies.m b/src/subfun/checkCppBidsDependencies.m
index dc752114..c0d794ff 100644
--- a/src/subfun/checkCppBidsDependencies.m
+++ b/src/subfun/checkCppBidsDependencies.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function checkCppBidsDependencies(cfg)
% checkCppBidsDependencies()
%
@@ -31,8 +33,8 @@ function checkSubmodule(pth)
% and ask user to update submodules.
if numel(dir(pth)) <= 2 % Means that the external is empty
error(['Git submodules are not cloned!', ...
- 'Try this in your terminal:', ...
- ' git submodule update --recursive ']);
+ 'Try this in your terminal:', ...
+ ' git submodule update --recursive ']);
else
addpath(pth);
end
diff --git a/src/subfun/createQuestionList.m b/src/subfun/createQuestionList.m
index 8d3b55c9..fc2c43b0 100644
--- a/src/subfun/createQuestionList.m
+++ b/src/subfun/createQuestionList.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function questions = createQuestionList(cfg)
cfg = askForGroupAndOrSession(cfg);
diff --git a/src/subfun/createValidName.m b/src/subfun/createValidName.m
index ef216ef1..57b905d4 100644
--- a/src/subfun/createValidName.m
+++ b/src/subfun/createValidName.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function [name, nameValid] = createValidName(name)
% [taskName, taskNameValid] = createTaskName(taskName)
%
diff --git a/src/subfun/getIsQuestionToAsk.m b/src/subfun/getIsQuestionToAsk.m
index 8da55b03..a8446235 100644
--- a/src/subfun/getIsQuestionToAsk.m
+++ b/src/subfun/getIsQuestionToAsk.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function isQuestionToAsk = getIsQuestionToAsk(questions, responses)
isQuestionToAsk = cell2mat(questions.questionsToAsk(:, 2));
diff --git a/src/subfun/initializeExtraColumns.m b/src/subfun/initializeExtraColumns.m
index cfbb1c34..ef1dad32 100644
--- a/src/subfun/initializeExtraColumns.m
+++ b/src/subfun/initializeExtraColumns.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function logFile = initializeExtraColumns(logFile)
% logFile = initializeExtraColumns(logFile)
% initialize the fields for the extra columns
@@ -20,7 +22,7 @@
for iExtraColumn = 1:nbExtraColumns
extraColumnName = logFile(1).extraColumns{iExtraColumn};
tmp.(extraColumnName) = struct( ...
- 'length', 1);
+ 'length', 1);
tmp.(extraColumnName) = setDefaultFields(tmp.(extraColumnName), fieldsToSet);
end
@@ -33,8 +35,8 @@
logFile(1).extraColumns.(namesExtraColumns{iExtraColumn}) = ...
setDefaultFields( ...
- logFile(1).extraColumns.(namesExtraColumns{iExtraColumn}), ...
- fieldsToSet);
+ logFile(1).extraColumns.(namesExtraColumns{iExtraColumn}), ...
+ fieldsToSet);
end
diff --git a/src/subfun/isPositiveInteger.m b/src/subfun/isPositiveInteger.m
index f44bc872..e3598544 100644
--- a/src/subfun/isPositiveInteger.m
+++ b/src/subfun/isPositiveInteger.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function trueOrFalse = isPositiveInteger(input2check)
% trueOrFalse = isPositiveInteger(input2check)
%
@@ -5,10 +7,10 @@
%
trueOrFalse = ~any([ ...
- ~isnumeric(input2check), ...
- isnan(input2check), ...
- fix(input2check) ~= input2check, ...
- input2check < 0 ...
- ]);
+ ~isnumeric(input2check), ...
+ isnan(input2check), ...
+ fix(input2check) ~= input2check, ...
+ input2check < 0 ...
+ ]);
end
diff --git a/src/subfun/printCreditsCppBids.m b/src/subfun/printCreditsCppBids.m
index e9ff763a..03947463 100644
--- a/src/subfun/printCreditsCppBids.m
+++ b/src/subfun/printCreditsCppBids.m
@@ -1,8 +1,10 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function printCreditsCppBids(cfg)
try
version = fileread(fullfile(fileparts(mfilename('fullpath')), ...
- '..', '..', 'version.txt'));
+ '..', '..', 'version.txt'));
catch
version = 'v1.0.0';
end
@@ -15,9 +17,9 @@ function printCreditsCppBids(cfg)
if verbose > 1
contributors = { ...
- 'Rémi Gau', ...
- 'Marco Barilari', ...
- 'Ceren Battal'};
+ 'Rémi Gau', ...
+ 'Marco Barilari', ...
+ 'Ceren Battal'};
DOI_URL = 'https://doi.org/10.5281/zenodo.4007674';
diff --git a/src/subfun/removeAllDateSuffix.m b/src/subfun/removeAllDateSuffix.m
index 1f0bf0c3..d7ddba32 100644
--- a/src/subfun/removeAllDateSuffix.m
+++ b/src/subfun/removeAllDateSuffix.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function removeAllDateSuffix(rawDir, subjName, sesName)
% removeAllDateSuffix(rawDir, subjName, sesName)
%
@@ -12,23 +14,28 @@ function removeAllDateSuffix(rawDir, subjName, sesName)
% do events
filenames = file_utils('List', subjectPath, ...
- sprintf('^%s.*_task-.*_events_date-.*$', subjName));
+ sprintf('^%s.*_task-.*_events_date-.*$', subjName));
removeDateSuffix(filenames, subjectPath);
for iLabel = 1:numel(labels)
filenames = file_utils('List', subjectPath, ...
- sprintf('^%s.*_task-.*_%s_date-.*$', subjName, labels{iLabel}));
+ sprintf('^%s.*_task-.*_%s_date-.*$', ...
+ subjName, labels{iLabel}));
removeDateSuffix(filenames, subjectPath);
end
% do stim
filenames = file_utils('List', subjectPath, ...
- sprintf('^%s.*_task-.*_stim_date-.*tsv$', subjName));
+ sprintf('^%s.*_task-.*_stim_date-.*json$', subjName));
+ removeDateSuffix(filenames, subjectPath);
+
+ filenames = file_utils('List', subjectPath, ...
+ sprintf('^%s.*_task-.*_stim_date-.*tsv$', subjName));
compressFiles(filenames, subjectPath);
filenames = file_utils('List', subjectPath, ...
- sprintf('^%s.*_task-.*_stim_date-.*tsv.gz$', subjName));
+ sprintf('^%s.*_task-.*_stim_date-.*tsv.gz$', subjName));
removeDateSuffix(filenames, subjectPath);
end
diff --git a/src/subfun/removeDateSuffix.m b/src/subfun/removeDateSuffix.m
index d06af305..ab04cbb2 100644
--- a/src/subfun/removeDateSuffix.m
+++ b/src/subfun/removeDateSuffix.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function removeDateSuffix(filenames, subjectPath)
% removeDateSuffix(filenames, subjectPath)
%
@@ -23,7 +25,7 @@ function removeDateSuffix(filenames, subjectPath)
% remove suffix file if there was one
if ~strcmp(filenames{i}, [parts{1} ext])
movefile(fullfile(subjectPath, filenames{i}), ...
- fullfile(subjectPath, [parts{1} ext]));
+ fullfile(subjectPath, [parts{1} ext]));
end
end
diff --git a/src/subfun/returnHeaderName.m b/src/subfun/returnHeaderName.m
index e78865f1..fe59cbc3 100644
--- a/src/subfun/returnHeaderName.m
+++ b/src/subfun/returnHeaderName.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function headerName = returnHeaderName(columnName, nbCol, iCol)
% headerName = returnHeaderName(columnName, nbCol, iCol)
%
diff --git a/src/subfun/returnNamesExtraColumns.m b/src/subfun/returnNamesExtraColumns.m
index ada0791c..39b17629 100644
--- a/src/subfun/returnNamesExtraColumns.m
+++ b/src/subfun/returnNamesExtraColumns.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function [namesExtraColumns, logFile] = returnNamesExtraColumns(logFile)
% [namesExtraColumns, logFile] = returnNamesExtraColumns(logFile)
%
diff --git a/src/subfun/returnNbColumns.m b/src/subfun/returnNbColumns.m
index 1a603bb4..18234a7d 100644
--- a/src/subfun/returnNbColumns.m
+++ b/src/subfun/returnNbColumns.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function nbCol = returnNbColumns(logFile, nameExtraColumn)
% nbCol = returnNbColumns(logFile, nameExtraColumn)
%
diff --git a/src/subfun/setDefaultFields.m b/src/subfun/setDefaultFields.m
index e54f805f..6cfad781 100644
--- a/src/subfun/setDefaultFields.m
+++ b/src/subfun/setDefaultFields.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function structure = setDefaultFields(structure, fieldsToSet)
% structure = setDefaultFields(structure, fieldsToSet)
%
@@ -20,9 +22,9 @@
else
structure = setFieldToIfNotPresent( ...
- structure, ...
- names{i}, ...
- thisField);
+ structure, ...
+ names{i}, ...
+ thisField);
end
end
diff --git a/src/subfun/setDefaultResponses.m b/src/subfun/setDefaultResponses.m
index 1d8074ea..d9814c45 100644
--- a/src/subfun/setDefaultResponses.m
+++ b/src/subfun/setDefaultResponses.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function [cfg, responses] = setDefaultResponses(cfg)
if nargin < 1
diff --git a/src/subfun/transferInfoToBids.m b/src/subfun/transferInfoToBids.m
index c2267e41..f21950fd 100644
--- a/src/subfun/transferInfoToBids.m
+++ b/src/subfun/transferInfoToBids.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function fieldsToSet = transferInfoToBids(fieldsToSet, cfg)
% fieldsToSet = transferInfoToBids(fieldsToSet, cfg)
%
diff --git a/src/subfun/utilsForTests/setUp.m b/src/subfun/utilsForTests/setUp.m
new file mode 100644
index 00000000..fa29d4f4
--- /dev/null
+++ b/src/subfun/utilsForTests/setUp.m
@@ -0,0 +1,20 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
+function [cfg, logFile] = setUp()
+
+ cfg.verbose = true;
+
+ cfg.subject.subjectNb = 1;
+ cfg.subject.runNb = 1;
+
+ cfg.task.name = 'testtask';
+
+ cfg.testingDevice = 'mri';
+
+ cfg = createFilename(cfg);
+
+ logFile.extraColumns.Speed.length = 1;
+ logFile.extraColumns.LHL24.length = 12;
+ logFile.extraColumns.is_Fixation.length = 1;
+
+end
diff --git a/src/userInputs.m b/src/userInputs.m
index 1d9c3481..9264bf8b 100644
--- a/src/userInputs.m
+++ b/src/userInputs.m
@@ -1,3 +1,5 @@
+% (C) Copyright 2020 CPP_BIDS developers
+
function cfg = userInputs(cfg)
% cfg = userInputs(cfg)
%
diff --git a/tests/README.md b/tests/README.md
index 673cc339..9d8452e4 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -1,18 +1,24 @@
# how to run the tests
-- Install [MOxUnit for matlab and octave](https://github.com/MOxUnit/MOxUnit) to run the tests
-- Install [MOcov for matlab and octave](https://github.com/MOcov/MOcov) to get the code coverage
-- Make sure you are in the `tests` directory.
-- Run `moxunit_runtests` or `moxunit_runtests -verbose` to run the tests.
+- Install [MOxUnit for matlab and octave](https://github.com/MOxUnit/MOxUnit)
+ to run the tests
+
+- Install [MOcov for matlab and octave](https://github.com/MOcov/MOcov) to get
+ the code coverage
+
+- Make sure you are in the `tests` directory.
+
+- Run `moxunit_runtests` or `moxunit_runtests -verbose` to run the tests.
This should tell you which tests pass or fail.
-
+
## code coverage
-The following command would give more info and will give you HTML output in a `coverage_html` folder
-showing you which lines of code is or is not checked by your test suite.
+The following command would give more info and will give you HTML output in a
+`coverage_html` folder showing you which lines of code is or is not checked by
+your test suite.
-``` matlab
+```matlab
success = moxunit_runtests(pwd, ... % the path where the tests are
'-verbose', ...
'-with_coverage', ...
@@ -20,12 +26,15 @@ success = moxunit_runtests(pwd, ... % the path where the tests are
'-cover_xml_file','coverage.xml', ...
'-cover_html_dir','coverage_html');
```
-This will return a clear underestimation of the code coverage as the the code in dependencies in the `lib` folder
-are also included in this report.
-If you want to get a slightly more accurate estimate you should run the following.
+This will return a clear underestimation of the code coverage as the the code in
+dependencies in the `lib` folder are also included in this report.
+
+If you want to get a slightly more accurate estimate you should run the
+following.
-I have not been able to find a way to exclude certain files without breaking some tests.
+I have not been able to find a way to exclude certain files without breaking
+some tests.
```matlab
coverage = mocov( ...
@@ -47,15 +56,13 @@ coverage = mocov( ...
'-cover_html_dir','coverage_html')
```
-
## Adding more tests
You can use the following function template to write more tests.
-
```matlab
function test_suite = test_functionToTest()
- % This top function is necessary for mox unit to run tests.
+ % This top function is necessary for mox unit to run tests.
% DO NOT CHANGE IT except to adapt the name of the function.
try % assignment of 'localfunctions' is necessary in Matlab >= 2016
test_functions = localfunctions(); %#ok<*NASGU>
@@ -70,7 +77,7 @@ function test_functionToTestBasic()
%% data to test against
-
+
%% test
% assertTrue( );
@@ -85,7 +92,7 @@ function test_functionToTestUseCase1()
%% data to test against
-
+
%% test
% assertTrue( );
@@ -94,4 +101,3 @@ function test_functionToTestUseCase1()
end
```
-
diff --git a/tests/dummyData/sub-blind01_ses-01_task-vislocalizer_events.tsv b/tests/dummyData/sub-blind01_ses-01_task-vislocalizer_events.tsv
new file mode 100644
index 00000000..eef890c1
--- /dev/null
+++ b/tests/dummyData/sub-blind01_ses-01_task-vislocalizer_events.tsv
@@ -0,0 +1,3 @@
+onset duration trial_type
+2 15 VisMot
+25 15 VisStat
diff --git a/tests/test_checkCFG.m b/tests/test_checkCFG.m
index 94ec3e34..dc2edc90 100644
--- a/tests/test_checkCFG.m
+++ b/tests/test_checkCFG.m
@@ -148,6 +148,20 @@ function test_checkCfgBasic()
expectedCfgStructure.bids.datasetDescription.ReferencesAndLinks = {''};
expectedCfgStructure.bids.datasetDescription.DatasetDOI = '';
+ expectedCfgStructure.eyeTracker.do = false;
+ expectedCfgStructure.eyeTracker.SamplingFrequency = [];
+ expectedCfgStructure.eyeTracker.PupilPositionType = '';
+ expectedCfgStructure.eyeTracker.RawSamples = [];
+ expectedCfgStructure.eyeTracker.Manufacturer = '';
+ expectedCfgStructure.eyeTracker.ManufacturersModelName = '';
+ expectedCfgStructure.eyeTracker.SoftwareVersions = '';
+ expectedCfgStructure.eyeTracker.CalibrationType = 'HV5';
+ expectedCfgStructure.eyeTracker.CalibrationPosition = '';
+ expectedCfgStructure.eyeTracker.CalibrationDistance = '';
+ expectedCfgStructure.eyeTracker.MaximalCalibrationError = [];
+ expectedCfgStructure.eyeTracker.AverageCalibrationError = [];
+ expectedCfgStructure.eyeTracker.RawDataFilters = {};
+
expectedCfgStructure.bids = orderfields(expectedCfgStructure.bids);
expectedCfgStructure = orderfields(expectedCfgStructure);
diff --git a/tests/test_createFilename.m b/tests/test_createFilename.m
index 336eef0c..36f5b546 100644
--- a/tests/test_createFilename.m
+++ b/tests/test_createFilename.m
@@ -18,10 +18,10 @@ function test_createFilenameBasic()
behDir = fullfile(cfg.dir.output, 'source', 'sub-001', 'ses-001', 'beh');
eventFilename = ['sub-001_ses-001_task-testTask_run-001_events_date-'...
- cfg.fileName.date '.tsv'];
+ cfg.fileName.date '.tsv'];
stimFilename = ['sub-001_ses-001_task-testTask_run-001_stim_date-'...
- cfg.fileName.date '.tsv'];
+ cfg.fileName.date '.tsv'];
%% test
@@ -55,12 +55,12 @@ function test_createFilenameMriEyetracker()
baseFilename = 'sub-001_ses-001_task-testTask';
- eventFilename = ['sub-001_ses-001_task-testTask_run-001_events_date-' ...
- cfg.fileName.date '.tsv'];
+ eventFilename = [baseFilename '_run-001_events_date-' ...
+ cfg.fileName.date '.tsv'];
eyetrackerFilename = [ ...
- 'sub-001_ses-001_task-testTask_run-001_recording-eyetracking_physio_date-' ...
- cfg.fileName.date '.edf'];
+ baseFilename '_run-001_recording-eyetracking_physio_date-' ...
+ cfg.fileName.date '.edf'];
%% tests
% make sure the func dir is created
@@ -100,14 +100,14 @@ function test_createFilenameMriSuffix()
baseFilename = 'sub-001_ses-001_task-testTask';
eventFilename = ['sub-001_ses-001_task-testTask', ...
- '_acq-newTYpe_ce-test_dir-yPos_rec-fastRecon', ...
- '_run-001_echo-1_events_date-' ...
- cfg.fileName.date '.tsv'];
+ '_acq-newTYpe_ce-test_dir-yPos_rec-fastRecon', ...
+ '_run-001_echo-1_events_date-' ...
+ cfg.fileName.date '.tsv'];
stimFilename = ['sub-001_ses-001_task-testTask', ...
- '_acq-newTYpe_ce-test_dir-yPos_rec-fastRecon', ...
- '_run-001_echo-1_recording-respiPulse_stim_date-' ...
- cfg.fileName.date '.tsv'];
+ '_acq-newTYpe_ce-test_dir-yPos_rec-fastRecon', ...
+ '_run-001_echo-1_recording-respiPulse_stim_date-' ...
+ cfg.fileName.date '.tsv'];
%% tests
% make sure the func dir is created
@@ -144,14 +144,14 @@ function test_createFilenameBehSuffix()
baseFilename = 'sub-001_ses-001_task-testTask';
eventFilename = ['sub-001_ses-001_task-testTask', ...
- '_acq-newTYpe', ...
- '_run-001_events_date-' ...
- cfg.fileName.date '.tsv'];
+ '_acq-newTYpe', ...
+ '_run-001_events_date-' ...
+ cfg.fileName.date '.tsv'];
stimFilename = ['sub-001_ses-001_task-testTask', ...
- '_acq-newTYpe', ...
- '_run-001_recording-respiPulse_stim_date-' ...
- cfg.fileName.date '.tsv'];
+ '_acq-newTYpe', ...
+ '_run-001_recording-respiPulse_stim_date-' ...
+ cfg.fileName.date '.tsv'];
%% tests
% make sure the func dir is created
@@ -188,12 +188,12 @@ function test_createFilenameEegSuffix()
baseFilename = 'sub-001_ses-001_task-testTask';
eventFilename = ['sub-001_ses-001_task-testTask', ...
- '_run-001_events_date-' ...
- cfg.fileName.date '.tsv'];
+ '_run-001_events_date-' ...
+ cfg.fileName.date '.tsv'];
stimFilename = ['sub-001_ses-001_task-testTask', ...
- '_run-001_recording-respiPulse_stim_date-' ...
- cfg.fileName.date '.tsv'];
+ '_run-001_recording-respiPulse_stim_date-' ...
+ cfg.fileName.date '.tsv'];
%% tests
% make sure the func dir is created
@@ -220,7 +220,7 @@ function test_createFilenameEeg()
eegDir = fullfile(cfg.dir.output, 'source', 'sub-001', 'ses-001', 'eeg');
eventFilename = ['sub-001_ses-001_task-testTask_run-001_events_date-'...
- cfg.fileName.date '.tsv'];
+ cfg.fileName.date '.tsv'];
%% test
% make sure the func dir is created
@@ -249,7 +249,7 @@ function test_createFilenameIeeg()
assertTrue(exist(ieegDir, 'dir') == 7);
eventFilename = ['sub-001_ses-001_task-testTask_run-001_events_date-'...
- cfg.fileName.date '.tsv'];
+ cfg.fileName.date '.tsv'];
end
@@ -271,7 +271,7 @@ function test_createFilenameMeg()
assertTrue(exist(megDir, 'dir') == 7);
eventFilename = ['sub-001_ses-001_task-testTask_run-001_events_date-'...
- cfg.fileName.date '.tsv'];
+ cfg.fileName.date '.tsv'];
end
diff --git a/tests/test_createJson.m b/tests/test_createJson.m
index aace3715..e4f67b2b 100644
--- a/tests/test_createJson.m
+++ b/tests/test_createJson.m
@@ -23,7 +23,7 @@ function test_createJsonFunc()
funcDir = fullfile(cfg.dir.output, 'source', 'sub-001', 'ses-001', 'func');
eventFilename = ['sub-001_ses-001_task-testtask_run-001_bold_date-' ...
- cfg.fileName.date '.json'];
+ cfg.fileName.date '.json'];
%% test
assertTrue(exist(fullfile(funcDir, eventFilename), 'file') == 2);
@@ -47,7 +47,7 @@ function test_createJsonBeh()
funcDir = fullfile(cfg.dir.output, 'source', 'sub-001', 'ses-001', 'beh');
eventFilename = ['sub-001_ses-001_task-testtask_run-001_beh_date-' ...
- cfg.fileName.date '.json'];
+ cfg.fileName.date '.json'];
%% test
assertTrue(exist(fullfile(funcDir, eventFilename), 'file') == 2);
@@ -71,7 +71,7 @@ function test_createJsonEeg()
funcDir = fullfile(cfg.dir.output, 'source', 'sub-001', 'ses-001', 'eeg');
eventFilename = ['sub-001_ses-001_task-testtask_run-001_eeg_date-' ...
- cfg.fileName.date '.json'];
+ cfg.fileName.date '.json'];
%% test
assertTrue(exist(fullfile(funcDir, eventFilename), 'file') == 2);
@@ -95,7 +95,7 @@ function test_createJsonMeg()
funcDir = fullfile(cfg.dir.output, 'source', 'sub-001', 'ses-001', 'meg');
eventFilename = ['sub-001_ses-001_task-testtask_run-001_meg_date-' ...
- cfg.fileName.date '.json'];
+ cfg.fileName.date '.json'];
%% test
assertTrue(exist(fullfile(funcDir, eventFilename), 'file') == 2);
@@ -119,7 +119,7 @@ function test_createJsonIeeg()
funcDir = fullfile(cfg.dir.output, 'source', 'sub-001', 'ses-001', 'ieeg');
eventFilename = ['sub-001_ses-001_task-testtask_run-001_ieeg_date-' ...
- cfg.fileName.date '.json'];
+ cfg.fileName.date '.json'];
%% test
assertTrue(exist(fullfile(funcDir, eventFilename), 'file') == 2);
diff --git a/tests/test_createQuestionList.m b/tests/test_createQuestionList.m
index 999110ee..88a9e08c 100644
--- a/tests/test_createQuestionList.m
+++ b/tests/test_createQuestionList.m
@@ -14,10 +14,10 @@ function test_createQuestionListBasic()
questions = createQuestionList(cfg);
expectedCell = { ...
- 'Enter subject group (leave empty if none): ', false;
- 'Enter subject number (1-999): ', true;
- 'Enter the session number (i.e day ; 1-999): ', true;
- 'Enter the run number (1-999): ', true};
+ 'Enter subject group (leave empty if none): ', false
+ 'Enter subject number (1-999): ', true
+ 'Enter the session number (i.e day ; 1-999): ', true
+ 'Enter the run number (1-999): ', true};
assertEqual(expectedCell(3, 1), questions.questionsToAsk(3, 1));
diff --git a/tests/test_getIsQuestionToAsk.m b/tests/test_getIsQuestionToAsk.m
index 632668c6..a53b0892 100644
--- a/tests/test_getIsQuestionToAsk.m
+++ b/tests/test_getIsQuestionToAsk.m
@@ -9,18 +9,18 @@
function test_isPositiveIntegerBasic()
questions.questionsToAsk = { ...
- [], 1; ...
- [], 0; ...
- [], 1; ...
- [], 0; ...
- };
+ [], 1; ...
+ [], 0; ...
+ [], 1; ...
+ [], 0 ...
+ };
responses = { ...
- '1';
- '1';
- '-1';
- '-1';
- };
+ '1'
+ '1'
+ '-1'
+ '-1'
+ };
isQuestionToAsk = getIsQuestionToAsk(questions, responses);
diff --git a/tests/test_readAndFilterLogfile.m b/tests/test_readAndFilterLogfile.m
new file mode 100644
index 00000000..81406ed5
--- /dev/null
+++ b/tests/test_readAndFilterLogfile.m
@@ -0,0 +1,93 @@
+function test_suite = test_readAndFilterLogfile %#ok<*STOUT>
+ try % assignment of 'localfunctions' is necessary in Matlab >= 2016
+ test_functions = localfunctions(); %#ok<*NASGU>
+ catch % no problem; early Matlab versions can use initTestSuite fine
+ end
+ initTestSuite;
+end
+
+function test_readAndFilterLogfileBasic()
+
+ %% set up
+ cfg.dir.output = fullfile(fileparts(mfilename('fullpath')), '..', 'output');
+ [cfg, logFile] = setUp();
+
+ % create the events file and header
+ logFile = saveEventsFile('open', cfg, logFile);
+
+ % ROW 2: normal events : all info is there
+ logFile(1, 1).onset = 2;
+ logFile(end, 1).trial_type = 'motion_up';
+ logFile(end, 1).duration = 3;
+ logFile(end, 1).Speed = 2;
+ logFile(end, 1).is_Fixation = true;
+ logFile(end, 1).LHL24 = 1:12;
+
+ logFile(2, 1).onset = 2;
+ logFile(end, 1).trial_type = 'motion_down';
+ logFile(end, 1).duration = 3;
+ logFile(end, 1).Speed = 2;
+ logFile(end, 1).is_Fixation = true;
+ logFile(end, 1).LHL24 = 2:13;
+
+ logFile(3, 1).onset = 2;
+ logFile(end, 1).trial_type = 'motion_up';
+ logFile(end, 1).duration = 3;
+ logFile(end, 1).Speed = 2;
+ logFile(end, 1).is_Fixation = true;
+ logFile(end, 1).LHL24 = 1:12;
+
+ logFile(4, 1).onset = 2;
+ logFile(end, 1).trial_type = 'motion_down';
+ logFile(end, 1).duration = 3;
+ logFile(end, 1).Speed = 2;
+ logFile(end, 1).is_Fixation = true;
+ logFile(end, 1).LHL24 = 2:13;
+
+ logFile = saveEventsFile('save', cfg, logFile);
+
+ % close the file
+ saveEventsFile('close', cfg, logFile);
+
+ % filter file
+ outputFiltered = readAndFilterLogfile('trial_type', 'motion_down', true, cfg);
+
+ %% test
+ expectedFilename = strrep(cfg.fileName.events, '.tsv', ...
+ ['_filteredBy-' 'trial_type' '_' 'motion_down' '.tsv']);
+ expectedFile = fullfile(cfg.dir.outputSubject, ...
+ cfg.fileName.modality, ...
+ expectedFilename);
+
+ assertEqual(exist(expectedFile, 'file'), 2);
+
+ content = bids.util.tsvread(expectedFile);
+
+ assertEqual(size(content.trial_type), [2, 1]);
+
+ assertEqual(content.trial_type{1}, 'motion_down');
+ assertEqual(content.trial_type{2}, 'motion_down');
+
+end
+
+function test_readAndFilterLogfileFromFile()
+
+ %% set up
+
+ inputFile = fullfile(fileparts(mfilename('fullpath')), 'dummyData', ...
+ 'sub-blind01_ses-01_task-vislocalizer_events.tsv');
+
+ % filter file
+ outputFiltered = readAndFilterLogfile('trial_type', 'VisStat', true, inputFile);
+
+ %% test
+ expectedFile = strrep(inputFile, '.tsv', ...
+ ['_filteredBy-' 'trial_type' '_' 'VisStat' '.tsv']);
+
+ assertEqual(exist(expectedFile, 'file'), 2);
+
+ content = bids.util.tsvread(expectedFile);
+
+ assertEqual(content.trial_type{1}, 'VisStat');
+
+end
diff --git a/tests/test_removeDateSuffix.m b/tests/test_removeDateSuffix.m
index 67aa2a43..edb360af 100644
--- a/tests/test_removeDateSuffix.m
+++ b/tests/test_removeDateSuffix.m
@@ -21,16 +21,18 @@ function test_removeDateSuffixBasic()
eventsName = 'test_events_date-202008050730.tsv';
stimName = 'test_stim_date-202008050730.tsv';
stimNameZipped = 'test2_stim_date-202008050730.tsv.gz';
+ stimJsonName = 'test_stim_date-202008050730.json';
filesToProcess = { ...
- boldName;
- boldName2;
- boldName3;
- jsonName;
- eventsName;
- stimName;
- stimNameZipped;
- };
+ boldName
+ boldName2
+ boldName3
+ jsonName
+ eventsName
+ stimName
+ stimNameZipped
+ stimJsonName
+ };
% create new files for new tests
for iFile = 1:numel(filesToProcess)
@@ -48,6 +50,7 @@ function test_removeDateSuffixBasic()
expectedEventsName = 'test_events.tsv';
expectedStimName = 'test_stim.tsv';
expectedStimNameZipped = 'test2_stim.tsv.gz';
+ expectedStimJson = 'test_stim.json';
removeDateSuffix(filenames, outputDir);
@@ -61,6 +64,7 @@ function test_removeDateSuffixBasic()
assertEqual(exist(fullfile(outputDir, expectedStimNameZipped), 'file'), 2);
assertEqual(exist(fullfile(outputDir, expectedBoldName2), 'file'), 2);
assertEqual(exist(fullfile(outputDir, expectedBoldName), 'file'), 2);
+ assertEqual(exist(fullfile(outputDir, expectedStimJson), 'file'), 2);
% clean up
delete('*.nii*');
diff --git a/tests/test_saveEventsFileOpen.m b/tests/test_saveEventsFileOpen.m
index d04b2874..d09d9aaa 100644
--- a/tests/test_saveEventsFileOpen.m
+++ b/tests/test_saveEventsFileOpen.m
@@ -34,10 +34,11 @@ function test_saveEventsFileOpenBasic()
%% data to test against
funcDir = fullfile(outputDir, 'source', 'sub-001', 'ses-001', 'func');
eventFilename = ['sub-001_ses-001_task-testtask_run-001_events_date-' ...
- cfg.fileName.date '.tsv'];
+ cfg.fileName.date '.tsv'];
% check that the file has the right path and name
assert(exist(fullfile(funcDir, eventFilename), 'file') == 2);
+ assert(exist(fullfile(funcDir, strrep(eventFilename, '.tsv', '.json')), 'file') == 2);
FID = fopen(fullfile(funcDir, eventFilename), 'r');
C = textscan(FID, repmat('%s', 1, 3), 'Delimiter', '\t', 'EndOfLine', '\n');
@@ -78,10 +79,11 @@ function test_saveEventsFileOpenStimfile()
%% data to test against
funcDir = fullfile(outputDir, 'source', 'sub-001', 'ses-001', 'func');
eventFilename = ['sub-001_ses-001_task-testtask_run-001_stim_date-' ...
- cfg.fileName.date '.tsv'];
+ cfg.fileName.date '.tsv'];
% check that the file has the right path and name
assert(exist(fullfile(funcDir, eventFilename), 'file') == 2);
+ assert(exist(fullfile(funcDir, strrep(eventFilename, '.tsv', '.json')), 'file') == 2);
FID = fopen(fullfile(funcDir, eventFilename), 'r');
C = textscan(FID, repmat('%s', 1, 3), 'Delimiter', '\t', 'EndOfLine', '\n');
diff --git a/tests/test_saveEventsFileSave.m b/tests/test_saveEventsFileSave.m
index 251df236..971000bd 100644
--- a/tests/test_saveEventsFileSave.m
+++ b/tests/test_saveEventsFileSave.m
@@ -187,10 +187,10 @@ function test_saveEventsFileSaveErrors()
logFile = struct();
assertExceptionThrown(@()saveEventsFile('error', cfg, logFile), ...
- 'saveEventsFile:unknownActionType');
+ 'saveEventsFile:unknownActionType');
assertExceptionThrown(@()saveEventsFile('save', cfg, logFile), ...
- 'saveEventsFile:missingFileID');
+ 'saveEventsFile:missingFileID');
[cfg, logFile] = setUp();
@@ -203,30 +203,7 @@ function test_saveEventsFileSaveErrors()
logFile(end, end).LHL24 = rand(1, 10);
assertExceptionThrown(@()saveEventsFile('save', cfg, logFile), ...
- 'saveEventsFile:wrongLogSize');
-
-end
-
-function [cfg, logFile] = setUp()
-
- outputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'output');
-
- cfg.verbose = true;
-
- cfg.subject.subjectNb = 1;
- cfg.subject.runNb = 1;
-
- cfg.task.name = 'testtask';
-
- cfg.dir.output = outputDir;
-
- cfg.testingDevice = 'mri';
-
- cfg = createFilename(cfg);
-
- logFile.extraColumns.Speed.length = 1;
- logFile.extraColumns.LHL24.length = 12;
- logFile.extraColumns.is_Fixation.length = 1;
+ 'saveEventsFile:wrongLogSize');
end