Skip to content

Commit 991994e

Browse files
Merge branch 'master' into marco_refactor-ET
2 parents 40d5950 + 3673a4f commit 991994e

17 files changed

+296
-26
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
[![](https://img.shields.io/badge/Octave-CI-blue?logo=Octave&logoColor=white)](https://github.com/cpp-lln-lab/CPP_PTB/actions)
22
![](https://github.com/cpp-lln-lab/CPP_PTB/workflows/CI/badge.svg)
33

4-
[![Build Status](https://travis-ci.com/cpp-lln-lab/CPP_BIDS.svg?branch=master)](https://travis-ci.com/cpp-lln-lab/CPP_PTB)
4+
[![Build Status](https://travis-ci.com/cpp-lln-lab/CPP_PTB.svg?branch=master)](https://travis-ci.com/cpp-lln-lab/CPP_PTB)
5+
6+
[![codecov](https://codecov.io/gh/cpp-lln-lab/CPP_PTB/branch/master/graph/badge.svg)](https://codecov.io/gh/cpp-lln-lab/CPP_PTB)
57

68
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
79
[![All Contributors](https://img.shields.io/badge/all_contributors-3-orange.svg?style=flat-square)](#contributors-)

docs/functions_description.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* 1.6. [eyeTracker](#eyeTracker)
1111
* 1.7. [standByScreen](#standByScreen)
1212
* 1.8. [waitForTrigger](#waitForTrigger)
13+
* 1.9. [readAndFilterLogfile](#readAndFilterLogfile)
1314
* 2. [Keyboard functions: response collection and aborting experiment](#Keyboardfunctions:responsecollectionandabortingexperiment)
1415
* 2.1. [testKeyboards](#testKeyboards)
1516
* 2.2. [getResponse](#getResponse)
@@ -18,6 +19,10 @@
1819
* 3.1. [drawFixationCross](#drawFixationCross)
1920
* 4. [Drawing dots](#Drawingdots)
2021
* 5. [Drawing apertures](#Drawingapertures)
22+
* 6. [Randomization](#Randomization)
23+
* 6.1. [shuffle](#shuffle)
24+
* 6.2. [setTargetPositionInSequence](#setTargetPositionInSequence)
25+
* 6.3. [repeatShuffleConditions](#repeatShuffleConditions)
2126

2227
<!-- vscode-markdown-toc-config
2328
numbering=true
@@ -82,6 +87,9 @@ It shows a basic one-page instruction stored in `cfg.task.instruction` and wait
8287
Counts a certain number of triggers coming from the mri/scanner before returning.
8388
Requires number of triggers to wait for.
8489

90+
### 1.9. <a name='readAndFilterLogfile'></a>readAndFilterLogfile
91+
92+
Displays in the command window part of the `*events.tsv` file filterd by an element (e.g. 'trigger'). It can take the last output produced (through `cfg`) or any output BIDS compatible (through file path).
8593

8694
## 2. <a name='Keyboardfunctions:responsecollectionandabortingexperiment'></a>Keyboard functions: response collection and aborting experiment
8795

@@ -130,3 +138,19 @@ Define the parameters of the fixation cross in `cfg` and `expParameters` and thi
130138
## 4. <a name='Drawingdots'></a>Drawing dots
131139

132140
## 5. <a name='Drawingapertures'></a>Drawing apertures
141+
142+
## 6. <a name='Randomization'></a>Randomization
143+
144+
Functions that can be used to create random stimuli sequences.
145+
146+
### 6.1. <a name='shuffle'></a>shuffle
147+
148+
Is just there to replace the Shuffle function from PTB in case it is not in the path. Can be useful for testing or for continuous integration.
149+
150+
### 6.2. <a name='setTargetPositionInSequence'></a>setTargetPositionInSequence
151+
152+
For a sequence of length `seqLength` where we want to insert `nbTarget` targets, this will return `nbTarget` random position in that sequence and make sure that they are not in consecutive positions.
153+
154+
### 6.3. <a name='repeatShuffleConditions'></a>repeatShuffleConditions
155+
156+
Given `baseConditionVector`, a vector of conditions (coded as numbers), this will create a longer vector made of `nbRepeats` of this base vector and make sure that a given condition is not repeated one after the other.

manualTests/miss_hit.cfg

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# style guide (https://florianschanda.github.io/miss_hit/style_checker.html)
2+
line_length: 100
3+
regex_function_name: "((test_[a-z]+)|[a-z]+)(([A-Z]){1}[A-Za-z]+)*"
4+
suppress_rule: "copyright_notice"
5+
6+
# metrics limit for the code quality (https://florianschanda.github.io/miss_hit/metrics.html)
7+
metric "cnest": limit 4
8+
metric "file_length": limit 500
9+
metric "cyc": limit 15
10+
metric "parameters": limit 5
File renamed without changes.

miss_hit.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# styly guide (https://florianschanda.github.io/miss_hit/style_checker.html)
1+
# style guide (https://florianschanda.github.io/miss_hit/style_checker.html)
22
line_length: 100
33
regex_function_name: "[a-z]+(([A-Z]){1}[A-Za-z]+)*"
44
suppress_rule: "copyright_notice"

src/isOctave.m

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
function retval = isOctave
2+
% Return: true if the environment is Octave.
3+
persistent cacheval % speeds up repeated calls
4+
5+
if isempty (cacheval)
6+
cacheval = (exist ('OCTAVE_VERSION', 'builtin') > 0);
7+
end
8+
9+
retval = cacheval;
10+
end
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
function shuffledRepeats = repeatShuffleConditions(baseConditionVector, nbRepeats)
2+
% shuffledRepeats = repeatShuffleConditions(baseConditionVector, nbRepeats)
3+
%
4+
% given baseConditionVector, a vector of conditions (coded as numbers), this will
5+
% create a longer vector made of nbRepeats of this base vector and make sure
6+
% that a given condition is not repeated one after the other
7+
8+
% TODO
9+
% - needs some input checks to make sure that there is actually a solution
10+
% for this randomization (e.g having [1 1 1 1 1 2] as input will lead to an
11+
% infinite loop)
12+
13+
if numel(unique(baseConditionVector)) == 1
14+
error('There should be more than one condition to shuffle');
15+
end
16+
17+
baseConditionVector = baseConditionVector(:)';
18+
19+
while 1
20+
tmp = [];
21+
for iRepeat = 1:nbRepeats
22+
23+
tmp = [tmp, shuffle(baseConditionVector)];
24+
25+
end
26+
if ~any(diff(tmp, [], 2) == 0)
27+
break
28+
end
29+
end
30+
31+
shuffledRepeats = tmp;
32+
33+
end
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
function chosenPositions = setTargetPositionInSequence(seqLength, nbTarget, forbiddenPos)
2+
% chosenPositions = setTargetPositionInSequence(seqLength, nbTarget, forbiddenPos)
3+
%
4+
% For a sequence of length seqLength where we want to insert nbTarget targets, this
5+
% will return nbTarget random position in that sequence and make sure that,
6+
% they are not consecutive positions.
7+
8+
REPLACE = false;
9+
10+
allowedPositions = setxor(forbiddenPos, 1:seqLength);
11+
12+
chosenPositions = [];
13+
14+
if nbTarget < 1
15+
return
16+
17+
elseif nbTarget == 1
18+
19+
chosenPositions = randsample(allowedPositions, nbTarget, REPLACE);
20+
21+
else
22+
23+
targetDifference = 0;
24+
25+
while any(abs(targetDifference) < 2)
26+
chosenPositions = randsample(allowedPositions, nbTarget, REPLACE);
27+
chosenPositions = sort(chosenPositions);
28+
targetDifference = diff(chosenPositions, [], 2);
29+
end
30+
31+
end
32+
33+
end

src/randomization/shuffle.m

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function shuffled = shuffle(unshuffled)
2+
% in case PTB is not in the path
3+
% mostly for unit test
4+
%
5+
6+
try
7+
shuffled = Shuffle(unshuffled);
8+
catch
9+
shuffled = unshuffled(randperm(length(unshuffled)));
10+
end
11+
end

src/readAndFilterLogfile.m

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
function outputFiltered = readAndFilterLogfile(columnName, filterBy, varargin)
2+
% outputFiltered = readOutputFilter(filterHeader, filterContent, varargin)
3+
%
4+
% It will display in the command window the content of the `output.tsv' filtered by one element
5+
% of a target column.
6+
%
7+
% DEPENDENCIES:
8+
% - bids_matlab (from CPP_BIDS)
9+
%
10+
% INPUT:
11+
%
12+
% - columnName: string, the header of the column where the content of insterest is stored
13+
% (e.g., for 'trigger' will be 'trial type')
14+
% - filterBy: string, the content of the column you want to filter out. It can take just
15+
% part of the content name (e.g., you want to display the triggers and you have
16+
% 'trigger_motion' and 'trigger_static', 'trigger' as input will do)
17+
% - varargin: either cfg (to display the last run output) or the file path as string
18+
%
19+
% OUTPUT:
20+
%
21+
% - outputFiltered: dataset with only the specified content, to see it in the command window
22+
% use display(outputFiltered)
23+
24+
% Checke if input is cfg or the file path
25+
if ischar(varargin{1})
26+
tsvFile = varargin{1};
27+
elseif isstruct(varargin{1})
28+
tsvFile = fullfile(varargin{1}.dir.outputSubject, ...
29+
varargin{1}.fileName.modality, ...
30+
varargin{1}.fileName.events);
31+
end
32+
33+
% Check if the file exists
34+
if ~exist(tsvFile, 'file')
35+
error([newline 'Input file does not exist']);
36+
end
37+
38+
% Read the the tsv file and store each column in a field of `output` structure
39+
output = bids.util.tsvread(tsvFile);
40+
41+
% Get the index of the target contentent to filter and display
42+
filterIdx = find(strncmp(output.(columnName), filterBy, length(filterBy)));
43+
44+
% Convert the structure to dataset
45+
outputDataset = struct2dataset(output);
46+
47+
% Get the dataset with the content of intereset
48+
outputFiltered = outputDataset(filterIdx, :);
49+
50+
end

0 commit comments

Comments
 (0)