From 4829d52971d16ace5f84c224bd73538357b320d5 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Tue, 1 Mar 2022 16:24:41 +0100 Subject: [PATCH 01/64] add some infra --- CITATION.cff | 57 ++++++++++++++++++++++++++++++ Makefile | 22 ++++++++++++ README.md | 95 ++++++++++++++++++++++++++++++++++---------------- docs/README.md | 1 - runTests.m | 43 +++++++++++++++++++++++ version.txt | 2 +- 6 files changed, 188 insertions(+), 32 deletions(-) create mode 100644 CITATION.cff create mode 100644 Makefile delete mode 100644 docs/README.md create mode 100644 runTests.m diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..9ba1bff --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,57 @@ +cff-version: 1.2.0 + +title: "CPP localizer visual motion" + +version: 0.4.0dev + +abstract: A localizer for visual motion sensitive brain regions using RDK. + +message: "If you use this software, please cite it as below." + +repository-code: "https://github.com/cpp-lln-lab/localizer_visual_motion.git" + +identifiers: + - description: This is the collection of archived snapshots of all releases + type: doi + value: "10.5281/zenodo.4007674" + +contact: + - affiliation: "Université catholique de Louvain" + email: remi.gau@uclouvain.be + family-names: Gau + given-names: Rémi + +authors: + - family-names: "Gau" + given-names: "Rémi" + orcid: "https://orcid.org/0000-0002-1535-9767" + affiliation: "Université catholique de Louvain" + + - family-names: "Barilari" + given-names: "Marco" + orcid: "https://orcid.org/0000-0002-3313-3120" + affiliation: "Université catholique de Louvain" + + - family-names: "Battal" + given-names: "Ceren" + orcid: "https://orcid.org/0000-0002-9844-7630" + affiliation: "Université catholique de Louvain" + + - family-names: "Rezk" + given-names: "Mohamed" + orcid: "https://orcid.org/0000-0002-1866-8645" + affiliation: "Université catholique de Louvain" + + - family-names: "Shahzad" + given-names: "Iqra" + orcid: "https://orcid.org/0000-0002-8724-7668" + affiliation: "Université catholique de Louvain" + +license: MIT license + +keywords: + - BIDS + - brain imaging data structure + - neuroscience + - MATLAB + - Octave diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d630a2e --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +# TODO make more general to use the local matlab version +MATLAB = /usr/local/MATLAB/R2017a/bin/matlab +ARG = -nodisplay -nosplash -nodesktop + +.PHONY: clean manual fix_submodule +clean: clean + rm -rf version.txt + +fix_submodule: + git submodule update --init --recursive && git submodule update --recursive + +lint: + mh_style --fix && mh_metric --ci && mh_lint + +test: + $(MATLAB) $(ARG) -r "runTests; exit()" + +version.txt: CITATION.cff + grep -w "^version" CITATION.cff | sed "s/version: /v/g" > version.txt + +validate_cff: CITATION.cff + cffconvert --validate diff --git a/README.md b/README.md index 1a1a1b1..4a2ead7 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,8 @@ [![](https://img.shields.io/badge/Octave-CI-blue?logo=Octave&logoColor=white)](https://github.com/cpp-lln-lab/localizer_visual_motion/actions) ![](https://github.com/cpp-lln-lab/localizer_visual_motion/workflows/CI/badge.svg) [![codecov](https://codecov.io/gh/cpp-lln-lab/localizer_visual_motion/branch/master/graph/badge.svg)](https://codecov.io/gh/cpp-lln-lab/localizer_visual_motion) - [![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors-) - - - [fMRI localizers for visual motion](#fmri-localizers-for-visual-motion) - [Requirements](#requirements) - [Installation](#installation) @@ -22,13 +19,13 @@ - [Input:](#input-1) - [Output:](#output-1) - [Contributors ✨](#contributors-) - # fMRI localizers for visual motion ## Requirements -Make sure that the following toolboxes are installed and added to the matlab / octave path. See the next section on how to install the submodule toolboxes. +Make sure that the following toolboxes are installed and added to the matlab / +octave path. See the next section on how to install the submodule toolboxes. For instructions see the following links: @@ -42,8 +39,8 @@ For instructions see the following links: ## Installation -The CPP_BIDS and CPP_PTB dependencies are already set up as submodule to this repository. -You can install it all with git by doing. +The CPP_BIDS and CPP_PTB dependencies are already set up as submodule to this +repository. You can install it all with git by doing. ```bash git clone --recurse-submodules https://github.com/cpp-lln-lab/localizer_visual_motion.git @@ -53,15 +50,21 @@ git clone --recurse-submodules https://github.com/cpp-lln-lab/localizer_visual_m ### visualMotionLocalizer -Running this script will show blocks of motion dots and static dots. Motion blocks will show dots moving in one of four directions (up-, down-, left-, and right-ward) (MT+ localizer) or dots moving inward and outward in the peripheral of the screen (MT/MST localizer). +Running this script will show blocks of motion dots and static dots. Motion +blocks will show dots moving in one of four directions (up-, down-, left-, and +right-ward) (MT+ localizer) or dots moving inward and outward in the peripheral +of the screen (MT/MST localizer). -Run in `Debug mode` (see `setParameters.m`) it does not care about subjID, run n., Eye Tracker (soon, at the moment it needs to be set off manually), etc.. +Run in `Debug mode` (see `setParameters.m`) it does not care about subjID, run +n., Eye Tracker (soon, at the moment it needs to be set off manually), etc.. -Any details of the experiment can be changed in `setParameters.m` (e.g., experiment mode, motion stimuli details, exp. design, etc.) +Any details of the experiment can be changed in `setParameters.m` (e.g., +experiment mode, motion stimuli details, exp. design, etc.) ### setParameters -`setParameters.m` is the core engine of the experiment. It contains the following tweakable sections: +`setParameters.m` is the core engine of the experiment. It contains the +following tweakable sections: - Debug mode setting - MRI settings @@ -77,7 +80,8 @@ Any details of the experiment can be changed in `setParameters.m` (e.g., experim #### Let the scanner pace the experiment -Set `cfg.pacedByTriggers.do` to `true` and you can then set all the details in this `if` block +Set `cfg.pacedByTriggers.do` to `true` and you can then set all the details in +this `if` block ```matlab % Time is here in terms of `repetition time (TR)` (i.e. MRI volumes) @@ -106,10 +110,13 @@ Wrapper function that present the dot stimulation (static or motion) per event. #### Input -- `cfg`: PTB/machine and experiment configurations returned by `setParameters` and `initPTB` +- `cfg`: PTB/machine and experiment configurations returned by `setParameters` + and `initPTB` - `logFile`: structure that stores the experiment logfile to be saved -- `thisEvent`: structure that stores information about the event to present regarding the dots (static or motion, direction, etc.) -- `thisFixation`: structure that stores information about the fixation cross task to present +- `thisEvent`: structure that stores information about the event to present + regarding the dots (static or motion, direction, etc.) +- `thisFixation`: structure that stores information about the fixation cross + task to present - `dots`: [...] - `iEvent`: index of the event of the block at the moment of the presentation @@ -119,52 +126,78 @@ Wrapper function that present the dot stimulation (static or motion) per event. - Event `duration` - `dots`: [...] -> NB: The dots are drawn on a square that contains the round aperture, then any dots outside of the aperture is turned into a NaN so effectively the actual number of dots on the screen at any given time is not the one that you input but a smaller number (nDots / Area of aperture) on average. +> NB: The dots are drawn on a square that contains the round aperture, then any +> dots outside of the aperture is turned into a NaN so effectively the actual +> number of dots on the screen at any given time is not the one that you input +> but a smaller number (nDots / Area of aperture) on average. ### subfun/design/expDesign -This function and its companions creates the sequence of blocks (static/motion) and the events (the single directions) for MT+ and MT/MST localizers. The conditions are consecutive static and motion blocks (fixed in this order gives better results than randomised). +This function and its companions creates the sequence of blocks (static/motion) +and the events (the single directions) for MT+ and MT/MST localizers. The +conditions are consecutive static and motion blocks (fixed in this order gives +better results than randomised). -It can be run as a stand alone without inputs and displays a visual example of the possible design. See `getMockConfig` to set up the mock configuration. +It can be run as a stand alone without inputs and displays a visual example of +the possible design. See `getMockConfig` to set up the mock configuration. It computes the directions to display and the task(s), at the moment: + 1. detection of change in the color of the fixation target -2. detection of different speed of the moving dots [ W I P - if selected as a task it will give the same null output as if not selected ie no difference in speed] +2. detection of different speed of the moving dots [ W I P - if selected as a + task it will give the same null output as if not selected ie no difference in + speed] #### Events -The ``nbEventsPerBlock`` should be a multiple of the number of motion directions requested in ``motionDirections`` (which should be more than 1) e.g.: -- MT localizer: `cfg.design.motionDirections = [ 0 90 180 270 ]; % right down left up` +The `nbEventsPerBlock` should be a multiple of the number of motion directions +requested in `motionDirections` (which should be more than 1) e.g.: + +- MT localizer: + `cfg.design.motionDirections = [ 0 90 180 270 ]; % right down left up` - MT_MST localizer: `cfg.design.motionDirections = [666 -666]; % outward inward` #### Pseudorandomization rules: - Directions: -1. Directions are all presented in random orders in `numEventsPerBlock/nDirections` consecutive chunks. This evenly distribute the directions across the block. + +1. Directions are all presented in random orders in + `numEventsPerBlock/nDirections` consecutive chunks. This evenly distribute + the directions across the block. 2. No same consecutive direction - Color change detection of the fixation cross: -1. If there are 2 targets per block we make sure that they are at least 2 events apart. + +1. If there are 2 targets per block we make sure that they are at least 2 events + apart. 2. Targets cannot be on the first or last event of a block. 3. No less than 1 target per event position in the whole run #### Input: + - `cfg`: parameters returned by setParameters -- `displayFigs`: a boolean to decide whether to show the basic design matrix of the design +- `displayFigs`: a boolean to decide whether to show the basic design matrix of + the design #### Output: -- `cfg.design.blockNames`: cell array (nbBlocks, 1) with the condition name for each block + +- `cfg.design.blockNames`: cell array (nbBlocks, 1) with the condition name for + each block - `cfg.design.nbBlocks`: integer for th etotal number of blocks in the run -- `cfg.design.directions`: array (nbBlocks, nbEventsPerBlock) with the direction to present in a given event of a block. +- `cfg.design.directions`: array (nbBlocks, nbEventsPerBlock) with the direction + to present in a given event of a block. - 0 90 180 270 indicate the angle for translational motion direction - 666 -666 indicate in/out-ward direction in radial motion - -1 indicates static -- `cfg.design.speeds`: array (nbBlocks, nbEventsPerBlock) indicate the dots speed in each event, the target is represented by a higher/lower value -- `cfg.design.fixationTargets`: array (nbBlocks, numEventsPerBlock) showing for each event if it should be accompanied by a target +- `cfg.design.speeds`: array (nbBlocks, nbEventsPerBlock) indicate the dots + speed in each event, the target is represented by a higher/lower value +- `cfg.design.fixationTargets`: array (nbBlocks, numEventsPerBlock) showing for + each event if it should be accompanied by a target ## 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)): @@ -184,4 +217,6 @@ 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/README.md b/docs/README.md deleted file mode 100644 index 25f8d45..0000000 --- a/docs/README.md +++ /dev/null @@ -1 +0,0 @@ -# Documentation diff --git a/runTests.m b/runTests.m new file mode 100644 index 0000000..fdbb821 --- /dev/null +++ b/runTests.m @@ -0,0 +1,43 @@ +function runTests() + % + % (C) Copyright 2022 CPP_BIDS developers + + % Elapsed time is ??? seconds. + + tic; + + cd(fileparts(mfilename('fullpath'))); + + cfg.verbose = 0; + checkCppBidsDependencies(cfg); + + if bids.internal.is_github_ci + fprintf(1, '\nThis is github CI\n'); + else + fprintf(1, '\nThis is not github CI\n'); + end + + fprintf('\nHome is %s\n', getenv('HOME')); + + warning('OFF'); + + folderToCover = fullfile(pwd, 'src'); + testFolder = fullfile(pwd, 'tests'); + + addpath(fullfile(testFolder, 'utils')); + + success = moxunit_runtests(testFolder, ... + '-verbose', '-recursive', '-with_coverage', ... + '-cover', folderToCover, ... + '-cover_xml_file', 'coverage.xml', ... + '-cover_html_dir', fullfile(pwd, 'coverage_html')); + + if success + system('echo 0 > test_report.log'); + else + system('echo 1 > test_report.log'); + end + + toc; + +end diff --git a/version.txt b/version.txt index fb7a04c..c8d7ef2 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -v0.4.0 +v0.4.0dev From 6dfb8f2601876739bbd8a0414e3d8233d5e83dd7 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Tue, 1 Mar 2022 16:36:29 +0100 Subject: [PATCH 02/64] update submodules and runTests --- .gitignore | 4 ++++ lib/CPP_BIDS | 2 +- lib/CPP_PTB | 2 +- runTests.m | 9 ++------- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 419f9b5..e9f81a4 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,10 @@ venv/ ## visual studio code .vscode +# exclude temp files from tests and coverage +test_report.log +*coverage* + ## MATLAB / OCTAVE gitignore template # From : https://github.com/github/gitignore/blob/master/Global/MATLAB.gitignore diff --git a/lib/CPP_BIDS b/lib/CPP_BIDS index 46b475f..8735318 160000 --- a/lib/CPP_BIDS +++ b/lib/CPP_BIDS @@ -1 +1 @@ -Subproject commit 46b475f33f26df088a7c6f8a61ed5a540c9bdcfb +Subproject commit 87353186f2e5f60561e8c1221cdf68f217a3d25a diff --git a/lib/CPP_PTB b/lib/CPP_PTB index f4f5519..9f3ada3 160000 --- a/lib/CPP_PTB +++ b/lib/CPP_PTB @@ -1 +1 @@ -Subproject commit f4f5519cb5e0661b8559921d3b71a18351250a09 +Subproject commit 9f3ada3b53d456ac6fd471ee4191246136670322 diff --git a/runTests.m b/runTests.m index fdbb821..fe01db4 100644 --- a/runTests.m +++ b/runTests.m @@ -6,10 +6,7 @@ function runTests() tic; - cd(fileparts(mfilename('fullpath'))); - - cfg.verbose = 0; - checkCppBidsDependencies(cfg); + initEnv(); if bids.internal.is_github_ci fprintf(1, '\nThis is github CI\n'); @@ -21,11 +18,9 @@ function runTests() warning('OFF'); - folderToCover = fullfile(pwd, 'src'); + folderToCover = fullfile(pwd, 'subfun'); testFolder = fullfile(pwd, 'tests'); - addpath(fullfile(testFolder, 'utils')); - success = moxunit_runtests(testFolder, ... '-verbose', '-recursive', '-with_coverage', ... '-cover', folderToCover, ... From 3cbd37562509bcc05c50584525a54ea9e21fef39 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Tue, 1 Mar 2022 16:37:56 +0100 Subject: [PATCH 03/64] fix typo in copyright --- initEnv.m | 2 +- miss_hit.cfg | 2 +- runTests.m | 2 +- setParameters.m | 2 +- subfun/design/diplayDesign.m | 2 +- subfun/design/expDesign.m | 2 +- subfun/design/getDesignInput.m | 2 +- subfun/design/getDirectionBaseVectors.m | 2 +- subfun/design/getMockConfig.m | 2 +- subfun/design/setBlocksConditions.m | 2 +- subfun/design/setDirections.m | 2 +- subfun/design/setFixationPosition.m | 2 +- subfun/design/setFixationTargets.m | 2 +- subfun/design/setSpeedTargets.m | 2 +- subfun/doDotMo.m | 2 +- subfun/postInitializationSetup.m | 2 +- subfun/preSaveSetup.m | 2 +- subfun/preTrialSetup.m | 2 +- subfun/saveResponsesAndTriggers.m | 2 +- tests/test_expDesign.m | 2 +- tests/test_getDesignInput.m | 2 +- tests/test_getDirectionBaseVectors.m | 2 +- tests/test_setBlocksConditions.m | 2 +- tests/test_setDirections.m | 2 +- tests/test_setFixationTargets.m | 2 +- tests/test_setSpeedTargets.m | 2 +- visualMotionLocalizer.m | 2 +- 27 files changed, 27 insertions(+), 27 deletions(-) diff --git a/initEnv.m b/initEnv.m index 7685413..2ef23d0 100644 --- a/initEnv.m +++ b/initEnv.m @@ -1,5 +1,5 @@ % (C) Copyright 2020 Agah Karakuzu -% (C) Copyright 2019 CPP visual motion localizer developpers +% (C) Copyright 2019 CPP visual motion localizer developers function initEnv % 1 - Check if version requirements diff --git a/miss_hit.cfg b/miss_hit.cfg index 147dd54..aa34923 100644 --- a/miss_hit.cfg +++ b/miss_hit.cfg @@ -8,7 +8,7 @@ regex_script_name: "[a-z]+(([A-Z]){1}[A-Za-z]+)*" exclude_dir: "lib" copyright_entity: "Mohamed Rezk" copyright_entity: "Agah Karakuzu" -copyright_entity: "CPP visual motion localizer developpers" +copyright_entity: "CPP visual motion localizer developers" # metrics limit for the code quality (https://florianschanda.github.io/miss_hit/metrics.html) metric "cnest": limit 4 diff --git a/runTests.m b/runTests.m index fe01db4..ad48f59 100644 --- a/runTests.m +++ b/runTests.m @@ -1,6 +1,6 @@ function runTests() % - % (C) Copyright 2022 CPP_BIDS developers + % (C) Copyright 2022 CPP visual motion localizer developers % Elapsed time is ??? seconds. diff --git a/setParameters.m b/setParameters.m index c2c7b83..7ba0fb7 100755 --- a/setParameters.m +++ b/setParameters.m @@ -1,4 +1,4 @@ -% (C) Copyright 2020 CPP visual motion localizer developpers +% (C) Copyright 2020 CPP visual motion localizer developers function [cfg] = setParameters() diff --git a/subfun/design/diplayDesign.m b/subfun/design/diplayDesign.m index f971cf3..6ab0f7d 100644 --- a/subfun/design/diplayDesign.m +++ b/subfun/design/diplayDesign.m @@ -3,7 +3,7 @@ function diplayDesign(cfg, displayFigs) % diplayDesign(cfg, displayFigs) % % - % (C) Copyright 2020 CPP visual motion localizer developpers + % (C) Copyright 2020 CPP visual motion localizer developers %% Visualize the design matrix if displayFigs diff --git a/subfun/design/expDesign.m b/subfun/design/expDesign.m index 428c2b8..c7aae94 100644 --- a/subfun/design/expDesign.m +++ b/subfun/design/expDesign.m @@ -56,7 +56,7 @@ % for each event if it should be accompanied by a target % % - % (C) Copyright 2020 CPP visual motion localizer developpers + % (C) Copyright 2020 CPP visual motion localizer developers %% Check inputs diff --git a/subfun/design/getDesignInput.m b/subfun/design/getDesignInput.m index 2cee9b5..0b52de7 100644 --- a/subfun/design/getDesignInput.m +++ b/subfun/design/getDesignInput.m @@ -3,7 +3,7 @@ % [nbRepetitions, nbEventsPerBlock, maxNbPerBlock, nbBlocks] = getDesignInput(cfg) % % - % (C) Copyright 2020 CPP visual motion localizer developpers + % (C) Copyright 2020 CPP visual motion localizer developers nbRepetitions = cfg.design.nbRepetitions; diff --git a/subfun/design/getDirectionBaseVectors.m b/subfun/design/getDirectionBaseVectors.m index 3c13d13..6548d1f 100644 --- a/subfun/design/getDirectionBaseVectors.m +++ b/subfun/design/getDirectionBaseVectors.m @@ -3,7 +3,7 @@ % [directionsCondition1, directionsCondition2] = getDirectionBaseVectors(cfg) % % - % (C) Copyright 2020 CPP visual motion localizer developpers + % (C) Copyright 2020 CPP visual motion localizer developers % Set directions for static and motion condition diff --git a/subfun/design/getMockConfig.m b/subfun/design/getMockConfig.m index e0c6218..81ff764 100644 --- a/subfun/design/getMockConfig.m +++ b/subfun/design/getMockConfig.m @@ -7,7 +7,7 @@ % this may make the tests on GitHub fail, so be careful. % % - % (C) Copyright 2020 CPP visual motion localizer developpers + % (C) Copyright 2020 CPP visual motion localizer developers if nargin < 1 isMT = true; diff --git a/subfun/design/setBlocksConditions.m b/subfun/design/setBlocksConditions.m index eccae83..d00b09d 100644 --- a/subfun/design/setBlocksConditions.m +++ b/subfun/design/setBlocksConditions.m @@ -3,7 +3,7 @@ % [conditionNamesVector, idxCondition1, idxCondition2] = setBlocksConditions(cfg) % % - % (C) Copyright 2020 CPP visual motion localizer developpers + % (C) Copyright 2020 CPP visual motion localizer developers nbRepetitions = getDesignInput(cfg); diff --git a/subfun/design/setDirections.m b/subfun/design/setDirections.m index 3eccf1f..2c4017b 100644 --- a/subfun/design/setDirections.m +++ b/subfun/design/setDirections.m @@ -9,7 +9,7 @@ % condition2 = 'motion'; % % - % (C) Copyright 2020 CPP visual motion localizer developpers + % (C) Copyright 2020 CPP visual motion localizer developers % Get the directions we should work with [directionsCondition1, directionsCondition2] = getDirectionBaseVectors(cfg); diff --git a/subfun/design/setFixationPosition.m b/subfun/design/setFixationPosition.m index 22a80e2..3b3ccb3 100644 --- a/subfun/design/setFixationPosition.m +++ b/subfun/design/setFixationPosition.m @@ -6,7 +6,7 @@ % in a matrix of size ``nbBlocks`` by ``nbEventsPerBlock`` % % - % (C) Copyright 2022 CPP visual motion localizer developpers + % (C) Copyright 2022 CPP visual motion localizer developers % Get the parameter to compute the design with [~, ~, ~, nbBlocks] = getDesignInput(cfg); diff --git a/subfun/design/setFixationTargets.m b/subfun/design/setFixationTargets.m index 9284a94..cfcd73f 100644 --- a/subfun/design/setFixationTargets.m +++ b/subfun/design/setFixationTargets.m @@ -11,7 +11,7 @@ % If the fixation target task is not required, it outputs a matrix with only zeros % % - % (C) Copyright 2021 CPP visual motion localizer developpers + % (C) Copyright 2021 CPP visual motion localizer developers % Get the parameter to compute the design with [nbRepetitions, nbEventsPerBlock, maxNbPerBlock, nbBlocks] = getDesignInput(cfg); diff --git a/subfun/design/setSpeedTargets.m b/subfun/design/setSpeedTargets.m index 386233d..c421571 100644 --- a/subfun/design/setSpeedTargets.m +++ b/subfun/design/setSpeedTargets.m @@ -10,7 +10,7 @@ % set speed in ``cfg.dot.speed`` (computed in pixels per frame). % % - % (C) Copyright 2021 CPP visual motion localizer developpers + % (C) Copyright 2021 CPP visual motion localizer developers [~, nbEventsPerBlock, ~, nbBlocks] = getDesignInput(cfg); speeds = ones(nbBlocks, nbEventsPerBlock) * cfg.dot.speedPixPerFrame; diff --git a/subfun/doDotMo.m b/subfun/doDotMo.m index ad02761..feca37f 100644 --- a/subfun/doDotMo.m +++ b/subfun/doDotMo.m @@ -19,7 +19,7 @@ % % % (C) Copyright 2018 Mohamed Rezk - % (C) Copyright 2020 CPP visual motion localizer developpers + % (C) Copyright 2020 CPP visual motion localizer developers %% Get parameters if isempty(dots) diff --git a/subfun/postInitializationSetup.m b/subfun/postInitializationSetup.m index ab1d7fc..2d84998 100644 --- a/subfun/postInitializationSetup.m +++ b/subfun/postInitializationSetup.m @@ -6,7 +6,7 @@ % initialized % % - % (C) Copyright 2020 CPP visual motion localizer developpers + % (C) Copyright 2020 CPP visual motion localizer developers cfg.dot.matrixWidth = cfg.screen.winWidth; diff --git a/subfun/preSaveSetup.m b/subfun/preSaveSetup.m index dbb688c..aecd103 100755 --- a/subfun/preSaveSetup.m +++ b/subfun/preSaveSetup.m @@ -4,7 +4,7 @@ % duration, onset, cfg, logFile) % % - % (C) Copyright 2020 CPP visual motion localizer developpers + % (C) Copyright 2020 CPP visual motion localizer developers % generic function to prepare structures before saving diff --git a/subfun/preTrialSetup.m b/subfun/preTrialSetup.m index ce3cbd3..76a27aa 100644 --- a/subfun/preTrialSetup.m +++ b/subfun/preTrialSetup.m @@ -3,7 +3,7 @@ % [thisEvent, thisFixation, cfg] = postInitializatinSetup(cfg, iBlock, iEvent) % % - % (C) Copyright 2020 CPP visual motion localizer developpers + % (C) Copyright 2020 CPP visual motion localizer developers % generic function to prepare some structure before each trial diff --git a/subfun/saveResponsesAndTriggers.m b/subfun/saveResponsesAndTriggers.m index 5da624b..02bdbd5 100755 --- a/subfun/saveResponsesAndTriggers.m +++ b/subfun/saveResponsesAndTriggers.m @@ -3,7 +3,7 @@ function saveResponsesAndTriggers(responseEvents, cfg, logFile, triggerString) % saveResponsesAndTriggers(responseEvents, cfg, logFile, triggerString) % % - % (C) Copyright 2020 CPP visual motion localizer developpers + % (C) Copyright 2020 CPP visual motion localizer developers if isfield(responseEvents(1), 'onset') && ~isempty(responseEvents(1).onset) diff --git a/tests/test_expDesign.m b/tests/test_expDesign.m index 38f0368..c57f453 100644 --- a/tests/test_expDesign.m +++ b/tests/test_expDesign.m @@ -1,5 +1,5 @@ function test_suite = test_expDesign %#ok<*STOUT> - % (C) Copyright 2021 CPP visual motion localizer developpers + % (C) Copyright 2021 CPP visual motion localizer developers try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_getDesignInput.m b/tests/test_getDesignInput.m index 830c35f..3fa7381 100644 --- a/tests/test_getDesignInput.m +++ b/tests/test_getDesignInput.m @@ -1,5 +1,5 @@ function test_suite = test_getDesignInput %#ok<*STOUT> - % (C) Copyright 2021 CPP visual motion localizer developpers + % (C) Copyright 2021 CPP visual motion localizer developers try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_getDirectionBaseVectors.m b/tests/test_getDirectionBaseVectors.m index c16303c..c49eb19 100644 --- a/tests/test_getDirectionBaseVectors.m +++ b/tests/test_getDirectionBaseVectors.m @@ -1,5 +1,5 @@ function test_suite = test_getDirectionBaseVectors %#ok<*STOUT> - % (C) Copyright 2021 CPP visual motion localizer developpers + % (C) Copyright 2021 CPP visual motion localizer developers try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_setBlocksConditions.m b/tests/test_setBlocksConditions.m index 23e7820..ee2dbc5 100644 --- a/tests/test_setBlocksConditions.m +++ b/tests/test_setBlocksConditions.m @@ -1,5 +1,5 @@ function test_suite = test_setBlocksConditions %#ok<*STOUT> - % (C) Copyright 2021 CPP visual motion localizer developpers + % (C) Copyright 2021 CPP visual motion localizer developers try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_setDirections.m b/tests/test_setDirections.m index 8388e5c..d7952c0 100644 --- a/tests/test_setDirections.m +++ b/tests/test_setDirections.m @@ -1,5 +1,5 @@ function test_suite = test_setDirections %#ok<*STOUT> - % (C) Copyright 2021 CPP visual motion localizer developpers + % (C) Copyright 2021 CPP visual motion localizer developers try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_setFixationTargets.m b/tests/test_setFixationTargets.m index cfe8e8f..5a6aaf8 100644 --- a/tests/test_setFixationTargets.m +++ b/tests/test_setFixationTargets.m @@ -1,5 +1,5 @@ function test_suite = test_setFixationTargets %#ok<*STOUT> - % (C) Copyright 2021 CPP visual motion localizer developpers + % (C) Copyright 2021 CPP visual motion localizer developers try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/tests/test_setSpeedTargets.m b/tests/test_setSpeedTargets.m index c294634..30a5547 100644 --- a/tests/test_setSpeedTargets.m +++ b/tests/test_setSpeedTargets.m @@ -1,5 +1,5 @@ function test_suite = test_setSpeedTargets %#ok<*STOUT> - % (C) Copyright 2021 CPP visual motion localizer developpers + % (C) Copyright 2021 CPP visual motion localizer developers try % assignment of 'localfunctions' is necessary in Matlab >= 2016 test_functions = localfunctions(); %#ok<*NASGU> catch % no problem; early Matlab versions can use initTestSuite fine diff --git a/visualMotionLocalizer.m b/visualMotionLocalizer.m index fad8952..65d709a 100755 --- a/visualMotionLocalizer.m +++ b/visualMotionLocalizer.m @@ -1,5 +1,5 @@ % (C) Copyright 2018 Mohamed Rezk -% (C) Copyright 2020 CPP visual motion localizer developpers +% (C) Copyright 2020 CPP visual motion localizer developers %% Visual motion localizer From 9878666652e13148810e78b6f58275f75703388e Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Tue, 1 Mar 2022 22:27:08 +0100 Subject: [PATCH 04/64] update defaults --- setParameters.m => checkParameters.m | 41 ++-- defaultParameters.m | 4 + lib/CPP_PTB | 2 +- subfun/postInitializationSetup.m | 16 +- visualMotionLocalizer.m | 289 +++++++++++++-------------- 5 files changed, 164 insertions(+), 188 deletions(-) rename setParameters.m => checkParameters.m (89%) create mode 100644 defaultParameters.m diff --git a/setParameters.m b/checkParameters.m similarity index 89% rename from setParameters.m rename to checkParameters.m index 7ba0fb7..e3b4e55 100755 --- a/setParameters.m +++ b/checkParameters.m @@ -1,17 +1,16 @@ -% (C) Copyright 2020 CPP visual motion localizer developers - -function [cfg] = setParameters() - - % VISUAL LOCALIZER +function [cfg] = checkParameters(cfg) + % + % (C) Copyright 2020 CPP visual motion localizer developers % Initialize the general configuration variables structure - cfg = struct(); + if nargin < 1 + cfg = struct(); + end % by default the data will be stored in an output folder created where the % setParamters.m file is % change that if you want the data to be saved somewhere else - cfg.dir.output = fullfile( ... - fileparts(mfilename('fullpath')), 'output'); + cfg.dir.output = fullfile(fileparts(mfilename('fullpath')), 'output'); %% Debug mode settings @@ -36,7 +35,7 @@ % MRI settings cfg = setMRI(cfg); - % cfg.suffix.acquisition = ''; + % cfg.suffix.acquisition = ''; cfg.pacedByTriggers.do = false; @@ -151,8 +150,7 @@ cfg.fixation.colorTarget = cfg.color.red; end - cfg.extraColumns = { ... - 'direction', ... + cfg.extraColumns = {'direction', ... 'speedDegVA', ... 'target', ... 'event', ... @@ -167,46 +165,37 @@ end function cfg = setKeyboards(cfg) - cfg.keyboard.escapeKey = 'ESCAPE'; - cfg.keyboard.responseKey = { ... - 'r', 'g', 'y', 'b', ... + + cfg.keyboard = cppPtbDefaults('keyboard'); + + cfg.keyboard.responseKey = {'r', 'g', 'y', 'b', ... 'd', 'n', 'z', 'e', ... 't'}; - cfg.keyboard.keyboard = []; - cfg.keyboard.responseBox = []; - if strcmpi(cfg.testingDevice, 'mri') - cfg.keyboard.keyboard = []; - cfg.keyboard.responseBox = []; - end end function cfg = setMRI(cfg) % letter sent by the trigger to sync stimulation and volume acquisition cfg.mri.triggerKey = 't'; + cfg.mri.triggerNb = 5; cfg.mri.repetitionTime = 1.8; cfg.bids.MRI.Instructions = 'Detect the RED fixation cross'; cfg.bids.MRI.TaskDescription = []; - end function cfg = setMonitor(cfg) % Monitor parameters for PTB - cfg.color.white = [255 255 255]; - cfg.color.black = [0 0 0]; - cfg.color.red = [255 0 0]; - cfg.color.grey = mean([cfg.color.black; cfg.color.white]); + cfg.color = cppPtbDefaults('color'); cfg.color.background = cfg.color.black; cfg.text.color = cfg.color.white; % Monitor parameters cfg.screen.monitorWidth = 50; % in cm cfg.screen.monitorDistance = 40; % distance from the screen in cm - if strcmpi(cfg.testingDevice, 'mri') cfg.screen.monitorWidth = 25; cfg.screen.monitorDistance = 95; diff --git a/defaultParameters.m b/defaultParameters.m new file mode 100644 index 0000000..5bc32d7 --- /dev/null +++ b/defaultParameters.m @@ -0,0 +1,4 @@ +function defaultParameters() + % + % (C) Copyright 2020 CPP visual motion localizer developers +end diff --git a/lib/CPP_PTB b/lib/CPP_PTB index 9f3ada3..11a7b10 160000 --- a/lib/CPP_PTB +++ b/lib/CPP_PTB @@ -1 +1 @@ -Subproject commit 9f3ada3b53d456ac6fd471ee4191246136670322 +Subproject commit 11a7b101fe998367a0b023decc4d250c9a8edb95 diff --git a/subfun/postInitializationSetup.m b/subfun/postInitializationSetup.m index 2d84998..0a2d63b 100644 --- a/subfun/postInitializationSetup.m +++ b/subfun/postInitializationSetup.m @@ -8,20 +8,6 @@ % % (C) Copyright 2020 CPP visual motion localizer developers - cfg.dot.matrixWidth = cfg.screen.winWidth; - - % Convert some values from degrees to pixels - cfg.dot = degToPix('size', cfg.dot, cfg); - cfg.dot = degToPix('speed', cfg.dot, cfg); - - % Get dot speeds in pixels per frame - cfg.dot.speedPixPerFrame = cfg.dot.speedPix / cfg.screen.monitorRefresh; - - cfg.aperture = degToPix('xPos', cfg.aperture, cfg); - - % dots are displayed on a square with a length in visual angle equal to the - % field of view - cfg.dot.number = round(cfg.dot.density * ... - (cfg.dot.matrixWidth / cfg.screen.ppd)^2); + cfg = postInitDots(cfg); end diff --git a/visualMotionLocalizer.m b/visualMotionLocalizer.m index 65d709a..7cda12e 100755 --- a/visualMotionLocalizer.m +++ b/visualMotionLocalizer.m @@ -1,211 +1,208 @@ -% (C) Copyright 2018 Mohamed Rezk -% (C) Copyright 2020 CPP visual motion localizer developers +function visualMotionLocalizer(cfg) + % + % (C) Copyright 2018 Mohamed Rezk + % (C) Copyright 2020 CPP visual motion localizer developers -%% Visual motion localizer - -getOnlyPress = 1; + if nargin < 1 + cfg = struct(); + end -more off; + getOnlyPress = 1; -% Clear all the previous stuff -clc; -if ~ismac - close all; - clear Screen; -end + % Clear all the previous stuff + clc; + if ~ismac + close all; + clear Screen; + end -% make sure we got access to all the required functions and inputs -initEnv(); + % make sure we got access to all the required functions and inputs + initEnv(); -% set and load all the parameters to run the experiment -cfg = setParameters; -cfg = userInputs(cfg); -cfg = createFilename(cfg); + % set and load all the parameters to run the experiment + cfg = checkParameters(cfg); + cfg = userInputs(cfg); + cfg = createFilename(cfg); -%% Experiment + %% Experiment -% Safety loop: close the screen if code crashes -try + % Safety loop: close the screen if code crashes + try - %% Init the experiment - [cfg] = initPTB(cfg); + [cfg] = initPTB(cfg); - cfg = postInitializationSetup(cfg); + cfg = postInitializationSetup(cfg); - [el] = eyeTracker('Calibration', cfg); + [el] = eyeTracker('Calibration', cfg); - [cfg] = expDesign(cfg); + [cfg] = expDesign(cfg); - % Prepare for the output logfiles with all - logFile.extraColumns = cfg.extraColumns; - logFile = saveEventsFile('init', cfg, logFile); - logFile = saveEventsFile('open', cfg, logFile); + % Prepare for the output logfiles with all + logFile.extraColumns = cfg.extraColumns; + logFile = saveEventsFile('init', cfg, logFile); + logFile = saveEventsFile('open', cfg, logFile); - % prepare textures - cfg = apertureTexture('init', cfg); - cfg = dotTexture('init', cfg); + % prepare textures + cfg = apertureTexture('init', cfg); + cfg = dotTexture('init', cfg); - disp(cfg); + disp(cfg); - % Show experiment instruction - standByScreen(cfg); + % Show experiment instruction + standByScreen(cfg); - % prepare the KbQueue to collect responses - getResponse('init', cfg.keyboard.responseBox, cfg); + % prepare the KbQueue to collect responses + getResponse('init', cfg.keyboard.responseBox, cfg); - % Wait for Trigger from Scanner - waitForTrigger(cfg); + waitForTrigger(cfg); - %% Experiment Start + % Start + eyeTracker('StartRecording', cfg); - eyeTracker('StartRecording', cfg); + cfg = getExperimentStart(cfg); - cfg = getExperimentStart(cfg); + getResponse('start', cfg.keyboard.responseBox); - getResponse('start', cfg.keyboard.responseBox); + waitFor(cfg, cfg.timing.onsetDelay); - waitFor(cfg, cfg.timing.onsetDelay); + for iBlock = 1:cfg.design.nbBlocks - %% For Each Block + fprintf('\n - Running Block %.0f \n', iBlock); - for iBlock = 1:cfg.design.nbBlocks + eyeTracker('Message', cfg, ['start_block-', num2str(iBlock)]); - fprintf('\n - Running Block %.0f \n', iBlock); + dots = []; + previousEvent.target = 0; - eyeTracker('Message', cfg, ['start_block-', num2str(iBlock)]); + for iEvent = 1:cfg.design.nbEventsPerBlock - dots = []; - previousEvent.target = 0; + checkAbort(cfg, cfg.keyboard.keyboard); - % For each event in the block - for iEvent = 1:cfg.design.nbEventsPerBlock + [thisEvent, thisFixation, cfg] = preTrialSetup(cfg, iBlock, iEvent); - % Check for experiment abortion from operator - checkAbort(cfg, cfg.keyboard.keyboard); + % we wait for a trigger every 2 events + if cfg.pacedByTriggers.do && mod(iEvent, 2) == 1 + waitForTrigger( ... + cfg, ... + cfg.keyboard.responseBox, ... + cfg.pacedByTriggers.quietMode, ... + cfg.pacedByTriggers.nbTriggers); + end - [thisEvent, thisFixation, cfg] = preTrialSetup(cfg, iBlock, iEvent); + eyeTracker('Message', cfg, ... + ['start_trial-', num2str(iEvent), '_', thisEvent.trial_type]); - % we wait for a trigger every 2 events - if cfg.pacedByTriggers.do && mod(iEvent, 2) == 1 - waitForTrigger( ... - cfg, ... - cfg.keyboard.responseBox, ... - cfg.pacedByTriggers.quietMode, ... - cfg.pacedByTriggers.nbTriggers); - end + % we only reuse the dots position for targets that consists of + % presenting static dots with the same position as those of the + % previous trial + % + % TODO does not take into account what to do if 3 or more targets in a row + if strcmp(cfg.target.type, 'static_repeat') && ... + strcmp(thisEvent.trial_type, 'static') && ... + thisEvent.target == 1 && ... + thisEvent.target == previousEvent.target + else + dots = []; + end - eyeTracker('Message', cfg, ... - ['start_trial-', num2str(iEvent), '_', thisEvent.trial_type]); - - % we only reuse the dots position for targets that consists of - % presenting static dots with the same position as those of the - % previous trial - % - % TODO does not take into account what to do if 3 or more targets in a row - if strcmp(cfg.target.type, 'static_repeat') && ... - strcmp(thisEvent.trial_type, 'static') && ... - thisEvent.target == 1 && ... - thisEvent.target == previousEvent.target - else - dots = []; - end + % play the dots and collect onset and duraton of the event + [onset, duration, dots] = doDotMo(cfg, thisEvent, thisFixation, dots, iEvent); - % play the dots and collect onset and duraton of the event - [onset, duration, dots] = doDotMo(cfg, thisEvent, thisFixation, dots, iEvent); + thisEvent = preSaveSetup( ... + thisEvent, ... + thisFixation, ... + iBlock, iEvent, ... + duration, onset, ... + cfg, ... + logFile); - thisEvent = preSaveSetup( ... - thisEvent, ... - thisFixation, ... - iBlock, iEvent, ... - duration, onset, ... - cfg, ... - logFile); + saveEventsFile('save', cfg, thisEvent); - saveEventsFile('save', cfg, thisEvent); + % collect the responses and appends to the event structure for + % saving in the tsv file + responseEvents = getResponse('check', cfg.keyboard.responseBox, cfg, ... + getOnlyPress); - % collect the responses and appends to the event structure for - % saving in the tsv file - responseEvents = getResponse('check', cfg.keyboard.responseBox, cfg, ... - getOnlyPress); + triggerString = ['trigger_' cfg.design.blockNames{iBlock}]; + saveResponsesAndTriggers(responseEvents, cfg, logFile, triggerString); - triggerString = ['trigger_' cfg.design.blockNames{iBlock}]; - saveResponsesAndTriggers(responseEvents, cfg, logFile, triggerString); + eyeTracker('Message', cfg, ... + ['end_trial-', num2str(iEvent), '_', thisEvent.trial_type]); - eyeTracker('Message', cfg, ... - ['end_trial-', num2str(iEvent), '_', thisEvent.trial_type]); + previousEvent = thisEvent; - previousEvent = thisEvent; + waitFor(cfg, cfg.timing.ISI); - waitFor(cfg, cfg.timing.ISI); + end - end + % "prepare" cross for the baseline block + % if MT / MST this allows us to set the cross at the position of the next block + if iBlock < cfg.design.nbBlocks + nextBlock = iBlock + 1; + else + nextBlock = cfg.design.nbBlocks; + end - % "prepare" cross for the baseline block - % if MT / MST this allows us to set the cross at the position of the next block - if iBlock < cfg.design.nbBlocks - nextBlock = iBlock + 1; - else - nextBlock = cfg.design.nbBlocks; - end + [~, thisFixation] = preTrialSetup(cfg, nextBlock, 1); + drawFixation(thisFixation); + Screen('Flip', cfg.screen.win); - [~, thisFixation] = preTrialSetup(cfg, nextBlock, 1); - drawFixation(thisFixation); - Screen('Flip', cfg.screen.win); + eyeTracker('Message', cfg, ['end_block-', num2str(iBlock)]); - eyeTracker('Message', cfg, ['end_block-', num2str(iBlock)]); + waitFor(cfg, cfg.timing.IBI); - waitFor(cfg, cfg.timing.IBI); + % IBI trigger paced + if cfg.pacedByTriggers.do + waitForTrigger( ... + cfg, ... + cfg.keyboard.responseBox, ... + cfg.pacedByTriggers.quietMode, ... + cfg.timing.triggerIBI); + end - % IBI trigger paced - if cfg.pacedByTriggers.do - waitForTrigger( ... - cfg, ... - cfg.keyboard.responseBox, ... - cfg.pacedByTriggers.quietMode, ... - cfg.timing.triggerIBI); - end + if isfield(cfg.design, 'localizer') && ... + strcmpi(cfg.design.localizer, 'MT_MST') && ... + iBlock == cfg.design.nbBlocks / 2 - if isfield(cfg.design, 'localizer') && ... - strcmpi(cfg.design.localizer, 'MT_MST') && ... - iBlock == cfg.design.nbBlocks / 2 + waitFor(cfg, cfg.timing.changeFixationPosition); - waitFor(cfg, cfg.timing.changeFixationPosition); + end - end + % trigger monitoring + triggerEvents = getResponse('check', cfg.keyboard.responseBox, cfg, ... + getOnlyPress); - % trigger monitoring - triggerEvents = getResponse('check', cfg.keyboard.responseBox, cfg, ... - getOnlyPress); + triggerString = 'trigger_baseline'; + saveResponsesAndTriggers(triggerEvents, cfg, logFile, triggerString); - triggerString = 'trigger_baseline'; - saveResponsesAndTriggers(triggerEvents, cfg, logFile, triggerString); + end - end + % End of the run for the BOLD to go down + waitFor(cfg, cfg.timing.endDelay); - % End of the run for the BOLD to go down - waitFor(cfg, cfg.timing.endDelay); + cfg = getExperimentEnd(cfg); - cfg = getExperimentEnd(cfg); + eyeTracker('StopRecordings', cfg); - eyeTracker('StopRecordings', cfg); + % Close the logfiles + saveEventsFile('close', cfg, logFile); - % Close the logfiles - saveEventsFile('close', cfg, logFile); + getResponse('stop', cfg.keyboard.responseBox); + getResponse('release', cfg.keyboard.responseBox); - getResponse('stop', cfg.keyboard.responseBox); - getResponse('release', cfg.keyboard.responseBox); + eyeTracker('Shutdown', cfg); - eyeTracker('Shutdown', cfg); + createJson(cfg, cfg); - createJson(cfg, cfg); + farewellScreen(cfg); - farewellScreen(cfg); + cleanUp(); - cleanUp(); + catch -catch + cleanUp(); + psychrethrow(psychlasterror); - cleanUp(); - psychrethrow(psychlasterror); + end end From 42c8b3996b01a35d1829a33cf7db1a7d77ff1448 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Tue, 1 Mar 2022 22:51:04 +0100 Subject: [PATCH 05/64] add test for parameters --- .../defaults/checkParameters.m | 0 tests/config_MT.json | 126 +++++++++++++++++ tests/config_MT_MST.json | 127 ++++++++++++++++++ tests/test_checkParameters.m | 21 +++ 4 files changed, 274 insertions(+) rename checkParameters.m => subfun/defaults/checkParameters.m (100%) create mode 100644 tests/config_MT.json create mode 100644 tests/config_MT_MST.json create mode 100644 tests/test_checkParameters.m diff --git a/checkParameters.m b/subfun/defaults/checkParameters.m similarity index 100% rename from checkParameters.m rename to subfun/defaults/checkParameters.m diff --git a/tests/config_MT.json b/tests/config_MT.json new file mode 100644 index 0000000..12714c8 --- /dev/null +++ b/tests/config_MT.json @@ -0,0 +1,126 @@ +{ + "dir": { + "output": "/home/remi/github/CPP_localizer_visual_motion/subfun/defaults/output" + }, + "debug": { + "do": true, + "smallWin": false, + "transpWin": false + }, + "skipSyncTests": 0, + "verbose": 1, + "testingDevice": "mri", + "eyeTracker": { + "do": false + }, + "audio": { + "do": false + }, + "color": { + "white": [255,255,255], + "black": [0,0,0], + "grey": [127.5,127.5,127.5], + "red": [255,0,0], + "blue": [0,255,0], + "green": [0,0,255], + "background": [0,0,0] + }, + "text": { + "color": [255,255,255] + }, + "screen": { + "monitorWidth": 25, + "monitorDistance": 95 + }, + "keyboard": { + "keyboard": [], + "responseBox": [], + "responseKey": [ + "r", + "g", + "y", + "b", + "d", + "n", + "z", + "e", + "t" + ], + "escapeKey": "ESCAPE" + }, + "mri": { + "triggerKey": "t", + "triggerNb": 5, + "repetitionTime": 1.8 + }, + "bids": { + "MRI": { + "Instructions": "Detect the RED fixation cross", + "TaskDescription": [] + } + }, + "pacedByTriggers": { + "do": false + }, + "design": { + "localizer": "MT", + "motionType": "translation", + "motionDirections": [0,0,180,180], + "names": [ + "static", + "motion" + ], + "nbRepetitions": 12, + "nbEventsPerBlock": 12 + }, + "timing": { + "eventDuration": 0.3, + "IBI": 0, + "ISI": 0, + "onsetDelay": 0, + "endDelay": 3.6 + }, + "dot": { + "speed": 15, + "coherence": 1, + "density": 1, + "lifeTime": 0.4, + "proportionKilledPerFrame": 0, + "size": 0.2, + "color": [255,255,255], + "staticReSeed": true + }, + "aperture": { + "type": "none", + "width": [], + "xPos": 0 + }, + "task": { + "name": "visual localizer", + "instruction": "1-Detect the RED fixation cross\\n \\n\\n" + }, + "fixation": { + "type": "cross", + "color": [255,255,255], + "width": 0.25, + "lineWidthPix": 3, + "xDisplacement": 0, + "yDisplacement": 0, + "colorTarget": [255,0,0] + }, + "target": { + "maxNbPerBlock": 1, + "duration": 0.1, + "type": "fixation_cross" + }, + "extraColumns": [ + "direction", + "speedDegVA", + "target", + "event", + "block", + "keyName", + "fixationPosition", + "aperturePosition" + ] +} diff --git a/tests/config_MT_MST.json b/tests/config_MT_MST.json new file mode 100644 index 0000000..ccca669 --- /dev/null +++ b/tests/config_MT_MST.json @@ -0,0 +1,127 @@ +{ + "dir": { + "output": "/home/remi/github/CPP_localizer_visual_motion/subfun/defaults/output" + }, + "debug": { + "do": true, + "smallWin": false, + "transpWin": false + }, + "skipSyncTests": 0, + "verbose": 1, + "testingDevice": "mri", + "eyeTracker": { + "do": false + }, + "audio": { + "do": false + }, + "color": { + "white": [255,255,255], + "black": [0,0,0], + "grey": [127.5,127.5,127.5], + "red": [255,0,0], + "blue": [0,255,0], + "green": [0,0,255], + "background": [0,0,0] + }, + "text": { + "color": [255,255,255] + }, + "screen": { + "monitorWidth": 25, + "monitorDistance": 95 + }, + "keyboard": { + "keyboard": [], + "responseBox": [], + "responseKey": [ + "r", + "g", + "y", + "b", + "d", + "n", + "z", + "e", + "t" + ], + "escapeKey": "ESCAPE" + }, + "mri": { + "triggerKey": "t", + "triggerNb": 5, + "repetitionTime": 1.8 + }, + "bids": { + "MRI": { + "Instructions": "Detect the RED fixation cross", + "TaskDescription": [] + } + }, + "pacedByTriggers": { + "do": false + }, + "design": { + "localizer": "MT_MST", + "motionType": "radial", + "motionDirections": [666,-666], + "names": ["motion"], + "nbRepetitions": 12, + "nbEventsPerBlock": 24, + "fixationPosition": ["fixation_left"], + "xDisplacementFixation": 7, + "xDisplacementAperture": 3 + }, + "timing": { + "eventDuration": 0.3, + "IBI": 4, + "ISI": 0, + "onsetDelay": 0, + "endDelay": 3.6, + "changeFixationPosition": 10 + }, + "dot": { + "speed": 15, + "coherence": 1, + "density": 1, + "lifeTime": 0.4, + "proportionKilledPerFrame": 0, + "size": 0.2, + "color": [255,255,255], + "staticReSeed": true + }, + "aperture": { + "type": "circle", + "width": 7, + "xPos": 3 + }, + "task": { + "name": "mt mst localizer", + "instruction": "1-Detect the RED fixation cross\\n \\n\\n" + }, + "fixation": { + "type": "cross", + "color": [255,255,255], + "width": 0.25, + "lineWidthPix": 3, + "xDisplacement": 0, + "yDisplacement": 0, + "colorTarget": [255,0,0] + }, + "target": { + "maxNbPerBlock": 1, + "duration": 0.1, + "type": "fixation_cross" + }, + "extraColumns": [ + "direction", + "speedDegVA", + "target", + "event", + "block", + "keyName", + "fixationPosition", + "aperturePosition" + ] +} diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m new file mode 100644 index 0000000..8340e37 --- /dev/null +++ b/tests/test_checkParameters.m @@ -0,0 +1,21 @@ +function test_suite = test_checkParameters %#ok<*STOUT> + % (C) Copyright 2021 CPP visual motion localizer developers + 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_checkParameters_basic() + + cfg = checkParameters(); + + % bids.util.jsonencode(fullfile(pwd, 'config_MT_MST.json'), cfg); + % expected = cfg; + % save(fullfile(pwd, 'config_MT_MST.mat'), 'expected') + + load(fullfile(pwd, 'config_MT_MST.mat')); + assertEqual(cfg, expected); + +end From fddf258e794f5ca8384116fb1acab2a674f30306 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 2 Mar 2022 08:44:54 +0100 Subject: [PATCH 06/64] refactor parameters setting --- subfun/defaults/checkParameters.m | 314 ++++++++++++++++-------------- tests/test_checkParameters.m | 29 ++- 2 files changed, 186 insertions(+), 157 deletions(-) diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index e3b4e55..6ada2ef 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -7,235 +7,249 @@ cfg = struct(); end + % switching this on to MT or MT/MST with use: + % - MT: translational motion on the whole screen + % - alternates static and motion (left or right) blocks + % - MST: radial motion centered in a circle aperture that is on the opposite + % side of the screen relative to the fixation + % - alternates fixaton left and fixation right + % cfg.design.localizer = 'MT'; + % cfg.design.localizer = 'MT_MST'; + % by default the data will be stored in an output folder created where the % setParamters.m file is % change that if you want the data to be saved somewhere else - cfg.dir.output = fullfile(fileparts(mfilename('fullpath')), 'output'); + fieldsToSet.dir.output = fullfile(fileparts(mfilename('fullpath')), 'output'); - %% Debug mode settings + fieldsToSet.skipSyncTests = 0; - cfg.debug.do = true; % To test the script out of the scanner, skip PTB sync - cfg.debug.smallWin = false; % To test on a part of the screen, change to 1 - cfg.debug.transpWin = false; % To test with trasparent full size screen + fieldsToSet.verbose = 1; - cfg.skipSyncTests = 0; - - cfg.verbose = 1; + %% Debug mode settings + fieldsToSet.debug.do = true; + fieldsToSet.debug.smallWin = false; + fieldsToSet.debug.transpWin = false; %% Engine parameters + fieldsToSet.testingDevice = 'mri'; + fieldsToSet.eyeTracker.do = false; - cfg.testingDevice = 'mri'; - cfg.eyeTracker.do = false; - cfg.audio.do = false; - - cfg = setMonitor(cfg); + fieldsToSet = setMonitor(fieldsToSet); % Keyboards - cfg = setKeyboards(cfg); + fieldsToSet = setKeyboards(fieldsToSet); % MRI settings - cfg = setMRI(cfg); + fieldsToSet = setMRI(fieldsToSet); + % cfg.suffix.acquisition = ''; - cfg.pacedByTriggers.do = false; + fieldsToSet.pacedByTriggers.do = false; %% Experiment Design - % switching this on to MT or MT/MST with use: - % - MT: translational motion on the whole screen - % - alternates static and motion (left or right) blocks - % - MST: radial motion centered in a circle aperture that is on the opposite - % side of the screen relative to the fixation - % - alternates fixaton left and fixation right - % cfg.design.localizer = 'MT'; - cfg.design.localizer = 'MT_MST'; - - cfg.design.motionType = 'translation'; - cfg.design.motionDirections = [0 0 180 180]; - cfg.design.names = {'static'; 'motion'}; - % if you have static and motion and `nbRepetions` = 4, this will return 8 blocks (for MT/MST % localizer && 2 hemifield it is 8 blocks per hemifield), i.e. how many times each condition % will be repeated - cfg.design.nbRepetitions = 12; - cfg.design.nbEventsPerBlock = 12; + fieldsToSet.design.nbRepetitions = 12; %% Timing - % FOR 7T: if you want to create localizers on the fly, the following must be - % multiples of the scanner sequence TR - % % IBI % block length = (cfg.eventDuration + cfg.ISI) * cfg.design.nbEventsPerBlock - cfg.timing.eventDuration = 0.30; % second + fieldsToSet.timing.eventDuration = 0.30; % second - % Time between blocs in secs - cfg.timing.IBI = 0; % Time between events in secs - cfg.timing.ISI = 0; + fieldsToSet.timing.ISI = 0; % Number of seconds before the motion stimuli are presented - cfg.timing.onsetDelay = 0; + fieldsToSet.timing.onsetDelay = 0; % Number of seconds after the end all the stimuli before ending the run - cfg.timing.endDelay = 3.6; - - % reexpress those in terms of repetition time - if cfg.pacedByTriggers.do - - cfg.pacedByTriggers.quietMode = true; - cfg.pacedByTriggers.nbTriggers = 1; - - cfg.timing.eventDuration = cfg.mri.repetitionTime / 2 - 0.04; % second - - % Time between blocs in nb of triggers (remember to consider the nb trigger to wait + 1) - cfg.timing.triggerIBI = 4; - % Time between blocks in secs - cfg.timing.IBI = 0; - % Time between events in secs - cfg.timing.ISI = 0; - % Number of seconds before the motion stimuli are presented - cfg.timing.onsetDelay = 0; - % Number of seconds after the end all the stimuli before ending the run - cfg.timing.endDelay = 2; - - end + fieldsToSet.timing.endDelay = 3.6; %% Visual Stimulation - - % Speed in visual angles / second - cfg.dot.speed = 15; - % Coherence Level (0-1) - cfg.dot.coherence = 1; - % Number of dots per visual angle square. - cfg.dot.density = 1; - % Dot life time in seconds - cfg.dot.lifeTime = 0.4; - % proportion of dots killed per frame - cfg.dot.proportionKilledPerFrame = 0; - % Dot Size (dot width) in visual angles. - cfg.dot.size = .2; - cfg.dot.color = cfg.color.white; - % Static dots should change position at each event or not - cfg.dot.staticReSeed = true; - - % Diameter/length of side of aperture in Visual angles - cfg.aperture.type = 'none'; - cfg.aperture.width = []; % if left empty it will take the screen height - cfg.aperture.xPos = 0; + fieldsToSet.dot = cppPtbDefaults('dot'); + fieldsToSet.dot.color = fieldsToSet.color.white; %% Task(s) - cfg.task.name = 'visual localizer'; + % target + % 'fixation_cross' : the fixation cross changes color + % 'static_repeat' : static dots are in the same position as previous trials + fieldsToSet.target.type = 'fixation_cross'; - % Instruction - cfg.task.instruction = '1-Detect the RED fixation cross\n \n\n'; + fieldsToSet.target.maxNbPerBlock = 1; + fieldsToSet.target.duration = 0.1; % In secs % Fixation cross (in pixels) - cfg.fixation.type = 'cross'; - cfg.fixation.color = cfg.color.white; - cfg.fixation.width = .25; - cfg.fixation.lineWidthPix = 3; - cfg.fixation.xDisplacement = 0; - cfg.fixation.yDisplacement = 0; + fieldsToSet.fixation = cppPtbDefaults('fixation'); + fieldsToSet.fixation.color = fieldsToSet.color.white; + fieldsToSet.fixation.width = .25; + fieldsToSet.fixation.lineWidthPix = 3; - % target - cfg.target.maxNbPerBlock = 1; - cfg.target.duration = 0.1; % In secs - cfg.target.type = 'fixation_cross'; - % 'fixation_cross' : the fixation cross changes color - % 'static_repeat' : static dots are in the same position as previous trials + fieldsToSet.extraColumns = {'direction', ... + 'speedDegVA', ... + 'target', ... + 'event', ... + 'block', ... + 'keyName', ... + 'fixationPosition', ... + 'aperturePosition'}; - cfg.fixation.colorTarget = cfg.fixation.color; - if strcmp(cfg.target.type, 'fixation_cross') - cfg.fixation.colorTarget = cfg.color.red; - end + fieldsToSet.audio.do = false; - cfg.extraColumns = {'direction', ... - 'speedDegVA', ... - 'target', ... - 'event', ... - 'block', ... - 'keyName', ... - 'fixationPosition', ... - 'aperturePosition'}; + cfg = setDefaultFields(cfg, fieldsToSet); - %% orverrireds the relevant fields in case we use the MT / MST localizer cfg = setParametersMtMst(cfg); + cfg = setPacedByTrigger(cfg); + + cfg = setTarget(cfg); + end -function cfg = setKeyboards(cfg) +function fieldsToSet = setKeyboards(fieldsToSet) - cfg.keyboard = cppPtbDefaults('keyboard'); + fieldsToSet.keyboard = cppPtbDefaults('keyboard'); - cfg.keyboard.responseKey = {'r', 'g', 'y', 'b', ... - 'd', 'n', 'z', 'e', ... - 't'}; + fieldsToSet.keyboard.responseKey = {'r', 'g', 'y', 'b', ... + 'd', 'n', 'z', 'e', ... + 't'}; end -function cfg = setMRI(cfg) +function fieldsToSet = setMRI(fieldsToSet) % letter sent by the trigger to sync stimulation and volume acquisition - cfg.mri.triggerKey = 't'; + fieldsToSet.mri.triggerKey = 't'; - cfg.mri.triggerNb = 5; + fieldsToSet.mri.triggerNb = 5; - cfg.mri.repetitionTime = 1.8; + fieldsToSet.mri.repetitionTime = 1.8; - cfg.bids.MRI.Instructions = 'Detect the RED fixation cross'; - cfg.bids.MRI.TaskDescription = []; + fieldsToSet.bids.MRI.Instructions = 'Detect the RED fixation cross'; + fieldsToSet.bids.MRI.TaskDescription = []; end -function cfg = setMonitor(cfg) +function fieldsToSet = setMonitor(fieldsToSet) % Monitor parameters for PTB - cfg.color = cppPtbDefaults('color'); - cfg.color.background = cfg.color.black; - cfg.text.color = cfg.color.white; + fieldsToSet.color = cppPtbDefaults('color'); + fieldsToSet.color.background = fieldsToSet.color.black; + fieldsToSet.text.color = fieldsToSet.color.white; % Monitor parameters - cfg.screen.monitorWidth = 50; % in cm - cfg.screen.monitorDistance = 40; % distance from the screen in cm - if strcmpi(cfg.testingDevice, 'mri') - cfg.screen.monitorWidth = 25; - cfg.screen.monitorDistance = 95; + fieldsToSet.screen.monitorWidth = 50; % in cm + fieldsToSet.screen.monitorDistance = 40; % distance from the screen in cm + if strcmpi(fieldsToSet.testingDevice, 'mri') + fieldsToSet.screen.monitorWidth = 25; + fieldsToSet.screen.monitorDistance = 95; end end function cfg = setParametersMtMst(cfg) - if isfield(cfg.design, 'localizer') && strcmpi(cfg.design.localizer, 'MT_MST') + fieldsToSet.design.nbEventsPerBlock = 12; + + switch lower(cfg.design.localizer) + + case 'mt_mst' + + fieldsToSet.task.name = 'mt mst localizer'; + + fieldsToSet.design.motionType = 'radial'; + fieldsToSet.design.motionDirections = [666 -666]; + fieldsToSet.design.names = {'motion'}; + % {'static'; 'motion'} + fieldsToSet.design.fixationPosition = {'fixation_left'}; + % {'fixation_right'; 'fixation_left'}; + fieldsToSet.design.xDisplacementFixation = 7; + fieldsToSet.design.xDisplacementAperture = 3; + + % inward and outward are presented as separated event + fieldsToSet.design.nbEventsPerBlock = fieldsToSet.design.nbEventsPerBlock * 2; + + fieldsToSet.timing.IBI = 4; + + fieldsToSet.timing.changeFixationPosition = 10; + + fieldsToSet.aperture.type = 'circle'; + fieldsToSet.aperture.width = 7; % if left empty it will take the screen height + fieldsToSet.aperture.xPos = fieldsToSet.design.xDisplacementAperture; + + case 'mt' + + fieldsToSet.task.name = 'visual localizer'; + + fieldsToSet.design.motionType = 'translation'; + fieldsToSet.design.motionDirections = [0 0 180 180]; + fieldsToSet.design.names = {'static'; 'motion'}; + + % Time between blocs in secs + fieldsToSet.timing.IBI = 0; + + % Diameter/length of side of aperture in Visual angles + fieldsToSet.aperture.type = 'none'; + fieldsToSet.aperture.width = []; % if left empty it will take the screen height + fieldsToSet.aperture.xPos = 0; + + end - cfg.task.name = 'mt mst localizer'; + cfg = setDefaultFields(cfg, fieldsToSet); - cfg.design.motionType = 'radial'; - cfg.design.motionDirections = [666 -666]; - cfg.design.names = {'motion'}; - % cfg.design.names = {'static'; 'motion'}; - cfg.design.fixationPosition = {'fixation_left'}; - % cfg.design.fixationPosition = {'fixation_right'; 'fixation_left'}; - cfg.design.xDisplacementFixation = 7; - cfg.design.xDisplacementAperture = 3; +end - % inward and outward are presented as separated event - cfg.design.nbEventsPerBlock = cfg.design.nbEventsPerBlock * 2; +function cfg = setPacedByTrigger(cfg) - cfg.timing.IBI = 4; + % reexpress those in terms of repetition time + if cfg.pacedByTriggers.do - cfg.timing.changeFixationPosition = 10; + fieldsToSet.pacedByTriggers.quietMode = true; + fieldsToSet.pacedByTriggers.nbTriggers = 1; - % reexpress those in terms of repetition time - if cfg.pacedByTriggers.do + fieldsToSet.timing.eventDuration = fieldsToSet.mri.repetitionTime / 2 - 0.04; % second - cfg.timing.IBI = 2; + % Time between blocs in nb of triggers (remember to consider the nb trigger to wait + 1) + fieldsToSet.timing.triggerIBI = 4; + % Time between blocks in secs + fieldsToSet.timing.IBI = 0; + if strcmpi(cfg.design.localizer, 'mt_mst') + fieldsToSet.timing.IBI = 2; end - cfg.aperture.type = 'circle'; - cfg.aperture.width = 7; % if left empty it will take the screen height - cfg.aperture.xPos = cfg.design.xDisplacementAperture; + % Time between events in secs + fieldsToSet.timing.ISI = 0; + + % Number of seconds before the motion stimuli are presented + fieldsToSet.timing.onsetDelay = 0; + + % Number of seconds after the end all the stimuli before ending the run + fieldsToSet.timing.endDelay = 2; + + cfg = setDefaultFields(cfg, fieldsToSet); end end + +function cfg = setTarget(cfg) + % 'fixation_cross' : the fixation cross changes color + % 'static_repeat' : static dots are in the same position as previous trials + + if strcmp(cfg.target.type, 'fixation_cross') + cfg.task.instruction = '1-Detect the RED fixation cross\n \n\n'; + cfg.task.taskDescription = ''; + cfg.fixation.colorTarget = cfg.color.red; + elseif strcmp(cfg.target.type, 'static_repeat') + cfg.task.instruction = '1-Detect when the dots are in the same position\n \n\n'; + cfg.task.taskDescription = ''; + cfg.fixation.colorTarget = cfg.fixation.color; + else + error('cfg.target.type must be ''fixation_cross'' or ''static_repeat'''); + end + + cfg.bids.MRI.Instructions = cfg.task.instruction; + cfg.bids.MRI.TaskDescription = cfg.task.taskDescription; + +end diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m index 8340e37..bb83b24 100644 --- a/tests/test_checkParameters.m +++ b/tests/test_checkParameters.m @@ -7,15 +7,30 @@ initTestSuite; end -function test_checkParameters_basic() +function test_checkParameters_MT() - cfg = checkParameters(); - - % bids.util.jsonencode(fullfile(pwd, 'config_MT_MST.json'), cfg); + cfg.design.localizer = 'MT'; + cfg = checkParameters(cfg); % expected = cfg; - % save(fullfile(pwd, 'config_MT_MST.mat'), 'expected') + % save(fullfile(fileparts(mfilename('fullpath')), 'config_MT.mat'), 'expected'); + load(fullfile(fileparts(mfilename('fullpath')), 'config_MT.mat')); + fields = fieldnames(expected); + for i = 1:numel(fields) + assertEqual(cfg.(fields{i}), expected.(fields{i})); + end + +end - load(fullfile(pwd, 'config_MT_MST.mat')); - assertEqual(cfg, expected); +function test_checkParameters_MT_MST() + + cfg.design.localizer = 'MT_MST'; + cfg = checkParameters(cfg); + % expected = cfg; + % save(fullfile(fileparts(mfilename('fullpath')), 'config_MT_MST.mat'), 'expected'); + load(fullfile(fileparts(mfilename('fullpath')), 'config_MT_MST.mat')); + fields = fieldnames(expected); + for i = 1:numel(fields) + assertEqual(cfg.(fields{i}), expected.(fields{i})); + end end From 2ce189352f622d22f504a51636967ad099463a41 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 2 Mar 2022 09:42:10 +0100 Subject: [PATCH 07/64] add way to show config --- defaultParameters.m | 4 - main.m | 18 +++ miss_hit.cfg | 2 + subfun/defaults/checkParameters.m | 42 ++++--- subfun/unfold.m | 178 ++++++++++++++++++++++++++++++ visualMotionLocalizer.m | 11 +- 6 files changed, 227 insertions(+), 28 deletions(-) delete mode 100644 defaultParameters.m create mode 100644 main.m create mode 100644 subfun/unfold.m diff --git a/defaultParameters.m b/defaultParameters.m deleted file mode 100644 index 5bc32d7..0000000 --- a/defaultParameters.m +++ /dev/null @@ -1,4 +0,0 @@ -function defaultParameters() - % - % (C) Copyright 2020 CPP visual motion localizer developers -end diff --git a/main.m b/main.m new file mode 100644 index 0000000..4928f89 --- /dev/null +++ b/main.m @@ -0,0 +1,18 @@ +% set your options here and then call visualMotionLocalizer(cfg) +% +% (C) Copyright 2020 CPP visual motion localizer developers + +cfg.design.localizer = 'MT'; + +initEnv(); + +cfg = checkParameters(cfg); + +%% To view all the options that are set +% +% unfold(cfg); + +%% Run +% + +visualMotionLocalizer(cfg); diff --git a/miss_hit.cfg b/miss_hit.cfg index aa34923..84e5fda 100644 --- a/miss_hit.cfg +++ b/miss_hit.cfg @@ -8,6 +8,8 @@ regex_script_name: "[a-z]+(([A-Z]){1}[A-Za-z]+)*" exclude_dir: "lib" copyright_entity: "Mohamed Rezk" copyright_entity: "Agah Karakuzu" +copyright_entity: "R.F. Tap" +copyright_entity: "Remi Gau" copyright_entity: "CPP visual motion localizer developers" # metrics limit for the code quality (https://florianschanda.github.io/miss_hit/metrics.html) diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 6ada2ef..3d548c9 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -32,20 +32,13 @@ %% Engine parameters fieldsToSet.testingDevice = 'mri'; + fieldsToSet.eyeTracker.do = false; fieldsToSet = setMonitor(fieldsToSet); - % Keyboards fieldsToSet = setKeyboards(fieldsToSet); - % MRI settings - fieldsToSet = setMRI(fieldsToSet); - - % cfg.suffix.acquisition = ''; - - fieldsToSet.pacedByTriggers.do = false; - %% Experiment Design % if you have static and motion and `nbRepetions` = 4, this will return 8 blocks (for MT/MST @@ -57,7 +50,6 @@ % IBI % block length = (cfg.eventDuration + cfg.ISI) * cfg.design.nbEventsPerBlock - fieldsToSet.timing.eventDuration = 0.30; % second % Time between events in secs @@ -78,9 +70,6 @@ % 'static_repeat' : static dots are in the same position as previous trials fieldsToSet.target.type = 'fixation_cross'; - fieldsToSet.target.maxNbPerBlock = 1; - fieldsToSet.target.duration = 0.1; % In secs - % Fixation cross (in pixels) fieldsToSet.fixation = cppPtbDefaults('fixation'); fieldsToSet.fixation.color = fieldsToSet.color.white; @@ -102,10 +91,14 @@ cfg = setParametersMtMst(cfg); - cfg = setPacedByTrigger(cfg); + cfg = setMRI(cfg); cfg = setTarget(cfg); + if cfg.verbose == 2 + unfold(cfg); + end + end function fieldsToSet = setKeyboards(fieldsToSet) @@ -118,7 +111,8 @@ end -function fieldsToSet = setMRI(fieldsToSet) +function cfg = setMRI(cfg) + % letter sent by the trigger to sync stimulation and volume acquisition fieldsToSet.mri.triggerKey = 't'; @@ -126,8 +120,14 @@ fieldsToSet.mri.repetitionTime = 1.8; - fieldsToSet.bids.MRI.Instructions = 'Detect the RED fixation cross'; - fieldsToSet.bids.MRI.TaskDescription = []; + fieldsToSet.suffix.acquisition = ''; + + fieldsToSet.pacedByTriggers.do = false; + + cfg = setDefaultFields(cfg, fieldsToSet); + + cfg = setPacedByTrigger(cfg); + end function fieldsToSet = setMonitor(fieldsToSet) @@ -170,7 +170,6 @@ fieldsToSet.design.nbEventsPerBlock = fieldsToSet.design.nbEventsPerBlock * 2; fieldsToSet.timing.IBI = 4; - fieldsToSet.timing.changeFixationPosition = 10; fieldsToSet.aperture.type = 'circle'; @@ -237,19 +236,28 @@ % 'fixation_cross' : the fixation cross changes color % 'static_repeat' : static dots are in the same position as previous trials + fieldsToSet.target.maxNbPerBlock = 1; + if strcmp(cfg.target.type, 'fixation_cross') cfg.task.instruction = '1-Detect the RED fixation cross\n \n\n'; cfg.task.taskDescription = ''; cfg.fixation.colorTarget = cfg.color.red; + + fieldsToSet.target.duration = 0.1; % In secs + elseif strcmp(cfg.target.type, 'static_repeat') cfg.task.instruction = '1-Detect when the dots are in the same position\n \n\n'; cfg.task.taskDescription = ''; cfg.fixation.colorTarget = cfg.fixation.color; + else error('cfg.target.type must be ''fixation_cross'' or ''static_repeat'''); + end cfg.bids.MRI.Instructions = cfg.task.instruction; cfg.bids.MRI.TaskDescription = cfg.task.taskDescription; + cfg = setDefaultFields(cfg, fieldsToSet); + end diff --git a/subfun/unfold.m b/subfun/unfold.m new file mode 100644 index 0000000..292acd8 --- /dev/null +++ b/subfun/unfold.m @@ -0,0 +1,178 @@ +function unfold(input, varargin) + % + % Unfolds a structure. + % + % USAGE:: + % + % unfold(SC, varargin) + % + % UNFOLD(SC) displays the content of a variable. + % + % If SC is a structure it recursively shows the name of SC and the fieldnames of SC and their + % contents. + % + % If SC is a cell array the contents of each cell are displayed. + % + % It uses the caller's workspace variable name as the name of SC. + % UNFOLD(SC,NAME) uses NAME as the name of SC. + % + % UNFOLD(SC,SHOW) If SHOW is false only the fieldnames and their sizes + % are shown, if SHOW is true the contents are shown also. + % + % (C) Copyright 2022 Remi Gau + % (C) Copyright 2005-2006 R.F. Tap + + % R.F. Tap + % 15-6-2005, 7-12-2005, 5-1-2006, 3-4-2006 + + % taken and adapted from shorturl.at/dqwN7 + + % check input + switch nargin + case 1 + Name = inputname(1); + show = true; + case 2 + if islogical(varargin{1}) + Name = inputname(1); + show = varargin{1}; + elseif ischar(varargin{1}) + Name = varargin{1}; + show = true; + else + error('Second input argument must be a string or a logical'); + end + case 3 + if ischar(varargin{1}) + if islogical(varargin{2}) + Name = varargin{1}; + show = varargin{2}; + else + error('Third input argument must be a logical'); + end + else + error('Second input argument must be a string'); + end + otherwise + error('Invalid number of input arguments'); + end + + fprintf('\n'); + + if isstruct(input) + % number of elements to be displayed + NS = numel(input); + if show + hmax = NS; + else + hmax = min(1, NS); + end + + % recursively display structure including fieldnames + for h = 1:hmax + F = fieldnames(input(h)); + NF = length(F); + for i = 1:NF + if NS > 1 + siz = size(input); + if show + Namei = [Name '(' indToStr(siz, h) ').' F{i}]; + else + Namei = [Name '(' indToStr(siz, NS) ').' F{i}]; + end + else + Namei = [Name '.' F{i}]; + end + if isstruct(input(h).(F{i})) + unfold(input(h).(F{i}), Namei, show); + else + if iscell(input(h).(F{i})) + siz = size(input(h).(F{i})); + NC = numel(input(h).(F{i})); + if show + jmax = NC; + else + jmax = 1; + end + for j = 1:jmax + if show + Namej = [Namei '{' indToStr(siz, j) '}']; + else + Namej = [Namei '{' indToStr(siz, NC) '}']; + end + printKeyToScreen(Namej); + if show + printToScreen(input(h).(F{i}){j}); + end + end + else + printKeyToScreen(Namei); + if show + printToScreen(input(h).(F{i})); + end + end + end + end + end + + elseif iscell(input) + % recursively display cell + siz = size(input); + for i = 1:numel(input) + Namei = [Name '{' indToStr(siz, i) '}']; + unfold(input{i}, Namei, show); + end + + else + disp(Name); + if show + printToScreen(input); + end + end + + fprintf('\n'); + +end + +function printKeyToScreen(input) + fprintf(1, '\n%s', input); +end + +function printToScreen(input) + if ischar(input) + fprintf(1, ':\t%s', input); + elseif isnumeric(input) + pattern = repmat('%f, ', 1, numel(input)); + fprintf(1, [':\t' pattern], input); + end +end + +% local functions +% -------------------------------------------------------------------------- +function str = indToStr(siz, ndx) + + n = length(siz); + % treat vectors and scalars correctly + if n == 2 + if siz(1) == 1 + siz = siz(2); + n = 1; + elseif siz(2) == 1 + siz = siz(1); + n = 1; + end + end + k = [1 cumprod(siz(1:end - 1))]; + ndx = ndx - 1; + str = ''; + for i = n:-1:1 + v = floor(ndx / k(i)) + 1; + if i == n + str = num2str(v); + else + str = [num2str(v) ',' str]; + end + ndx = rem(ndx, k(i)); + end + +end diff --git a/visualMotionLocalizer.m b/visualMotionLocalizer.m index 7cda12e..eee1f35 100755 --- a/visualMotionLocalizer.m +++ b/visualMotionLocalizer.m @@ -4,7 +4,7 @@ function visualMotionLocalizer(cfg) % (C) Copyright 2020 CPP visual motion localizer developers if nargin < 1 - cfg = struct(); + cfg.design.localizer = 'MT'; end getOnlyPress = 1; @@ -82,8 +82,7 @@ function visualMotionLocalizer(cfg) % we wait for a trigger every 2 events if cfg.pacedByTriggers.do && mod(iEvent, 2) == 1 - waitForTrigger( ... - cfg, ... + waitForTrigger(cfg, ... cfg.keyboard.responseBox, ... cfg.pacedByTriggers.quietMode, ... cfg.pacedByTriggers.nbTriggers); @@ -108,8 +107,7 @@ function visualMotionLocalizer(cfg) % play the dots and collect onset and duraton of the event [onset, duration, dots] = doDotMo(cfg, thisEvent, thisFixation, dots, iEvent); - thisEvent = preSaveSetup( ... - thisEvent, ... + thisEvent = preSaveSetup(thisEvent, ... thisFixation, ... iBlock, iEvent, ... duration, onset, ... @@ -153,8 +151,7 @@ function visualMotionLocalizer(cfg) % IBI trigger paced if cfg.pacedByTriggers.do - waitForTrigger( ... - cfg, ... + waitForTrigger(cfg, ... cfg.keyboard.responseBox, ... cfg.pacedByTriggers.quietMode, ... cfg.timing.triggerIBI); From 9e631d6fbfbe2542740de2c4d4beffe749415c7d Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 2 Mar 2022 09:44:29 +0100 Subject: [PATCH 08/64] update CPP PTB --- lib/CPP_PTB | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CPP_PTB b/lib/CPP_PTB index 11a7b10..8b71dfb 160000 --- a/lib/CPP_PTB +++ b/lib/CPP_PTB @@ -1 +1 @@ -Subproject commit 11a7b101fe998367a0b023decc4d250c9a8edb95 +Subproject commit 8b71dfbdfe03f5ed708584105d5586453910bffe From 3109a8f7f46182dac934d7d8d45d3ea41949fcfc Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 2 Mar 2022 09:53:14 +0100 Subject: [PATCH 09/64] add tests for default parameters --- .gitignore | 1 - lib/CPP_PTB | 2 +- tests/config_MT.json | 126 ---------------------------------- tests/config_MT_MST.json | 127 ----------------------------------- tests/data/config_MT.mat | Bin 0 -> 1473 bytes tests/data/config_MT_MST.mat | Bin 0 -> 1533 bytes tests/test_checkParameters.m | 8 +-- 7 files changed, 5 insertions(+), 259 deletions(-) delete mode 100644 tests/config_MT.json delete mode 100644 tests/config_MT_MST.json create mode 100644 tests/data/config_MT.mat create mode 100644 tests/data/config_MT_MST.mat diff --git a/.gitignore b/.gitignore index e9f81a4..037af8d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ */logfiles/* */*/*/logfiles/* *.tsv -*.mat output diff --git a/lib/CPP_PTB b/lib/CPP_PTB index 8b71dfb..cdcd293 160000 --- a/lib/CPP_PTB +++ b/lib/CPP_PTB @@ -1 +1 @@ -Subproject commit 8b71dfbdfe03f5ed708584105d5586453910bffe +Subproject commit cdcd29317b1df31ec196f4575255245e8fcca864 diff --git a/tests/config_MT.json b/tests/config_MT.json deleted file mode 100644 index 12714c8..0000000 --- a/tests/config_MT.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "dir": { - "output": "/home/remi/github/CPP_localizer_visual_motion/subfun/defaults/output" - }, - "debug": { - "do": true, - "smallWin": false, - "transpWin": false - }, - "skipSyncTests": 0, - "verbose": 1, - "testingDevice": "mri", - "eyeTracker": { - "do": false - }, - "audio": { - "do": false - }, - "color": { - "white": [255,255,255], - "black": [0,0,0], - "grey": [127.5,127.5,127.5], - "red": [255,0,0], - "blue": [0,255,0], - "green": [0,0,255], - "background": [0,0,0] - }, - "text": { - "color": [255,255,255] - }, - "screen": { - "monitorWidth": 25, - "monitorDistance": 95 - }, - "keyboard": { - "keyboard": [], - "responseBox": [], - "responseKey": [ - "r", - "g", - "y", - "b", - "d", - "n", - "z", - "e", - "t" - ], - "escapeKey": "ESCAPE" - }, - "mri": { - "triggerKey": "t", - "triggerNb": 5, - "repetitionTime": 1.8 - }, - "bids": { - "MRI": { - "Instructions": "Detect the RED fixation cross", - "TaskDescription": [] - } - }, - "pacedByTriggers": { - "do": false - }, - "design": { - "localizer": "MT", - "motionType": "translation", - "motionDirections": [0,0,180,180], - "names": [ - "static", - "motion" - ], - "nbRepetitions": 12, - "nbEventsPerBlock": 12 - }, - "timing": { - "eventDuration": 0.3, - "IBI": 0, - "ISI": 0, - "onsetDelay": 0, - "endDelay": 3.6 - }, - "dot": { - "speed": 15, - "coherence": 1, - "density": 1, - "lifeTime": 0.4, - "proportionKilledPerFrame": 0, - "size": 0.2, - "color": [255,255,255], - "staticReSeed": true - }, - "aperture": { - "type": "none", - "width": [], - "xPos": 0 - }, - "task": { - "name": "visual localizer", - "instruction": "1-Detect the RED fixation cross\\n \\n\\n" - }, - "fixation": { - "type": "cross", - "color": [255,255,255], - "width": 0.25, - "lineWidthPix": 3, - "xDisplacement": 0, - "yDisplacement": 0, - "colorTarget": [255,0,0] - }, - "target": { - "maxNbPerBlock": 1, - "duration": 0.1, - "type": "fixation_cross" - }, - "extraColumns": [ - "direction", - "speedDegVA", - "target", - "event", - "block", - "keyName", - "fixationPosition", - "aperturePosition" - ] -} diff --git a/tests/config_MT_MST.json b/tests/config_MT_MST.json deleted file mode 100644 index ccca669..0000000 --- a/tests/config_MT_MST.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "dir": { - "output": "/home/remi/github/CPP_localizer_visual_motion/subfun/defaults/output" - }, - "debug": { - "do": true, - "smallWin": false, - "transpWin": false - }, - "skipSyncTests": 0, - "verbose": 1, - "testingDevice": "mri", - "eyeTracker": { - "do": false - }, - "audio": { - "do": false - }, - "color": { - "white": [255,255,255], - "black": [0,0,0], - "grey": [127.5,127.5,127.5], - "red": [255,0,0], - "blue": [0,255,0], - "green": [0,0,255], - "background": [0,0,0] - }, - "text": { - "color": [255,255,255] - }, - "screen": { - "monitorWidth": 25, - "monitorDistance": 95 - }, - "keyboard": { - "keyboard": [], - "responseBox": [], - "responseKey": [ - "r", - "g", - "y", - "b", - "d", - "n", - "z", - "e", - "t" - ], - "escapeKey": "ESCAPE" - }, - "mri": { - "triggerKey": "t", - "triggerNb": 5, - "repetitionTime": 1.8 - }, - "bids": { - "MRI": { - "Instructions": "Detect the RED fixation cross", - "TaskDescription": [] - } - }, - "pacedByTriggers": { - "do": false - }, - "design": { - "localizer": "MT_MST", - "motionType": "radial", - "motionDirections": [666,-666], - "names": ["motion"], - "nbRepetitions": 12, - "nbEventsPerBlock": 24, - "fixationPosition": ["fixation_left"], - "xDisplacementFixation": 7, - "xDisplacementAperture": 3 - }, - "timing": { - "eventDuration": 0.3, - "IBI": 4, - "ISI": 0, - "onsetDelay": 0, - "endDelay": 3.6, - "changeFixationPosition": 10 - }, - "dot": { - "speed": 15, - "coherence": 1, - "density": 1, - "lifeTime": 0.4, - "proportionKilledPerFrame": 0, - "size": 0.2, - "color": [255,255,255], - "staticReSeed": true - }, - "aperture": { - "type": "circle", - "width": 7, - "xPos": 3 - }, - "task": { - "name": "mt mst localizer", - "instruction": "1-Detect the RED fixation cross\\n \\n\\n" - }, - "fixation": { - "type": "cross", - "color": [255,255,255], - "width": 0.25, - "lineWidthPix": 3, - "xDisplacement": 0, - "yDisplacement": 0, - "colorTarget": [255,0,0] - }, - "target": { - "maxNbPerBlock": 1, - "duration": 0.1, - "type": "fixation_cross" - }, - "extraColumns": [ - "direction", - "speedDegVA", - "target", - "event", - "block", - "keyName", - "fixationPosition", - "aperturePosition" - ] -} diff --git a/tests/data/config_MT.mat b/tests/data/config_MT.mat new file mode 100644 index 0000000000000000000000000000000000000000..eb3976acc801dcdfb10188d29478ddfe6d45ff69 GIT binary patch literal 1473 zcmV;y1wQ&sK~zjZLLfCRFd$7qR4ry{Y-KDUP;6mzW^ZzBIv__(PFO)UG%O%Pa%Ew3 zWn>_4ZaN@WWn>^tVR9fKG9WNGIy5voGBY4DFfuYAARr(hARr(hARr(hARr(hARr(h zARr(hARr(hARr(hARr(hARr(B00000000000ZB~{0000v1pokeoXuHJZ`(E$r|l$d z+936IY7ZNH8j1mhH|)||)5Iwf1PP49Sat~D>CcNyL=pvxO6`7=?i2I_^s?KI9k2lf zcG+(G2s`dDAR{GGrW7@nXcQ>{M*7M6y+=~-4@)&;)hu#1#u>&cd7AC-Oz<-|OOQ1H1^W{XFy#I^p zeW&dCO8TzAp9}f3hzom(T{c0}A&GUl-)M4ID&($ca=RRbB!n_=t;ADJ@zi)1@yhdP z%R9lFHk|*e#Nz6bYW?f&`ud-?%=I50@8@#Ob7XU~8LuO46uGKgdkMrnRXTWAGP$km~}dkG4fyk|fROV> zlhZ26QDaum(>$<1?;0xV6*y*Gr(@2~zLHt~+(66menHLb?~cUcN)i?&?0WvLn)jeI zZ-M(05@t42R>~s>hc&PAq?%El)pA?DHh-yKrtLK8yQGd#3+=LqB>X z@jLPTBA6!_y*Xq86ha5eKe!Oan9Z&;e0&Zg99$!yh?0ml@fuDrd@n~5DfFyvLm%OJ9TojhU{@uK26FC|r(#6wkY)#0y}_yU8-Xf^d$@$EDb z*5ltP@df7f=aF#jI_uai@kLkLb6(1&Y1mYbs@rurw_ay8jMJME+ep>9s!aztj(E8M zf%w|90xE{ctTI;3$03}GCqq1y!E{tC@J;O|t)?p0r%8PJSiBF#7n69Hwf9DGxMMnA z$=m8Qv!4x#g+BdUh(a9k4K8exX?}me3r=2cbGJE2OV5vW4ssK(w;}{Htk7^^l%siXMm(_~(sTV>w9^j|0$nqFN#~8 z0`e|ukBmHiVPLC7mS-;zfkX{9w#t|azQO#AgV b_QB?He`Cv(|6SVtSn6EDBwqXv|D5>bVo=u4 literal 0 HcmV?d00001 diff --git a/tests/data/config_MT_MST.mat b/tests/data/config_MT_MST.mat new file mode 100644 index 0000000000000000000000000000000000000000..aea940ad346f27afb30a02f496438f6f59591ce5 GIT binary patch literal 1533 zcmV_4ZaN@WWn>^tVR9fKG9WNGIy5voGBY4DFfuYAARr(hARr(hARr(hARr(hARr(h zARr(hARr(hARr(hARr(hARr(B00000000000ZB~{0001W1pokeoXuHFZ`(!?UQ2$| zuA2xww9ci~sR#-LYS2q=@k2Ij7&Zi3sCzJ=@-dOPQjA5eP$UD;<)Kkc18~nLX*!CT4(nU*wsQQtqFcbxi}Bg z5G)Gz8d^miG5#INo8aezc9vIu}O zpXdgMmowiQLPWVjY7hsMDN!T3QRPwg9`>C+++qt7ep*-n#UA^2&ffwtgD5j6dcgmz z)ca29_-gVl=RfB1XCV{z0^4+grh_0-%X>x$ft;4Mrn7gGFJ3VwaTyjtvO z1L@(~0yjm??64+yez${s-Kzf0)?)pcy&8T8RsY$=Nhas-hU<|2)@9d;A5jupd`l({uAJ{I%VY1D+{BP0y-}MVr{H~mT`lJt(d3cvjpnGxH?@Gt%S|o^~YrlK#U;Fd+ zE6bOp%9rbY+-kP&4+Ve5t``$bg;$s^^Y8T0AutmF0+~;nZY&+h$-UQPD2D{GZ_D{C z+J|kV?t?bEySvlENqxr+aGUJfkqi23v|GMw&0llf9H_VMuO(0+uQKC`=x;;=qa~4lRlMzTM0Yp9uaJl;=Md`f;8I-M}(j{1S?})eHC=eM}&a zFLHF4OLpdbZxVRW zBjDklgXttTdk2HTDD&gdEskQt9i^Y67sci{_Ioyrjo778Pijx~ziF6<9|`_7yP^>C zM5~e&On`uILHQpx_$>6y<`FI)!w`FO02GoS3jEyzlPi}S8R_hUhnl#mywL>rtO0IQjKBJk)1S|E^h*2a>-}|3uWo*AaxOb=-5>AN z@jCfo6BYfC^R~>64diT<)_W)c+LaQ*ERK5;Z2d|>)Ll3eV= z6(1SksR*XSV#7ms-y~IKg?*aDr~eE0w)mnG4^w)h6^HAdSKe0V?KZ3%wgu1iseLj6 zQOHj2updmb=TlaALu4_xIZaCNMe~%D&oiZEaNPy*UX9<2`W9t-bl4No#5tO{Dm&J} znVL9T6IWF~*TKEi#DOMmnfmSU@?dXpnBsRkksJCjE-F&X?~B9 zCQjPnal?Ho&kJ9o@_E5CrsrnX#Ia*i_zgws+eP>9Qz@TQNAOvHMH~R$O2;ZNUDMwsJ{9~A>^j*$K^1gzSvhP?4BvsHa!(d~RtmaCxkr-JX8k$m Date: Wed, 2 Mar 2022 09:54:21 +0100 Subject: [PATCH 10/64] update CPP BIDS --- lib/CPP_BIDS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CPP_BIDS b/lib/CPP_BIDS index 8735318..7b2b45e 160000 --- a/lib/CPP_BIDS +++ b/lib/CPP_BIDS @@ -1 +1 @@ -Subproject commit 87353186f2e5f60561e8c1221cdf68f217a3d25a +Subproject commit 7b2b45ed5fbe4c0e8292a55b0f68dd6a9049ead5 From e3ff0c1f8f5cccdccaee56942c20f1c46ac68695 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 2 Mar 2022 10:01:59 +0100 Subject: [PATCH 11/64] update doc --- subfun/defaults/checkParameters.m | 34 ++++++++++++++++++------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 3d548c9..0d6541b 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -1,25 +1,31 @@ function [cfg] = checkParameters(cfg) + % + % Check that all parameters are sets. If not it uses the defaults. + % + % ``cfg.design.localizer``: switching this to ``MT`` or ``MT_MST`` + % + % - ``MT``: translational motion on the whole screen + % + % - alternates static and motion (left or right) blocks + % + % - ``MT_MST``: radial motion centered in a circle aperture that is on the opposite + % side of the screen relative to the fixation + % + % - alternates fixaton left and fixation right + % + % ``cfg.dir.output``: by default the data will be stored in an output folder created in the root + % dir of this repo. Change that if you want the data to be saved somewhere + % else. % % (C) Copyright 2020 CPP visual motion localizer developers % Initialize the general configuration variables structure if nargin < 1 - cfg = struct(); + cfg.design.localizer = 'MT'; end - % switching this on to MT or MT/MST with use: - % - MT: translational motion on the whole screen - % - alternates static and motion (left or right) blocks - % - MST: radial motion centered in a circle aperture that is on the opposite - % side of the screen relative to the fixation - % - alternates fixaton left and fixation right - % cfg.design.localizer = 'MT'; - % cfg.design.localizer = 'MT_MST'; - - % by default the data will be stored in an output folder created where the - % setParamters.m file is - % change that if you want the data to be saved somewhere else - fieldsToSet.dir.output = fullfile(fileparts(mfilename('fullpath')), 'output'); + root_dir = fileparts(which('visualMotionLocalizer')); + fieldsToSet.dir.output = root_dir; fieldsToSet.skipSyncTests = 0; From 2f43e77479d016126b3632d8982d82abbf3b5dd3 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 2 Mar 2022 10:27:34 +0100 Subject: [PATCH 12/64] update doc --- doc/configurations.md | 110 ++++++++++++++++++++++++++++++ subfun/defaults/checkParameters.m | 3 +- subfun/unfold.m | 10 ++- tests/data/config_MT.mat | Bin 1473 -> 1482 bytes tests/data/config_MT_MST.mat | Bin 1533 -> 1543 bytes tests/test_checkParameters.m | 10 +-- 6 files changed, 126 insertions(+), 7 deletions(-) create mode 100644 doc/configurations.md diff --git a/doc/configurations.md b/doc/configurations.md new file mode 100644 index 0000000..3685a97 --- /dev/null +++ b/doc/configurations.md @@ -0,0 +1,110 @@ +# Configurations + +## MT + +```matlab +cfg.aperture.type = 'none' +cfg.aperture.width +cfg.aperture.xPos = 0.000000 + +cfg.audio.do = 0 + +cfg.bids.MRI.Instructions = '1-Detect the RED fixation cross\n \n\n' +cfg.bids.MRI.TaskDescription = '' + +cfg.color.white = 255.000000, 255.000000, 255.000000 +cfg.color.black = 0.000000, 0.000000, 0.000000 +cfg.color.grey = 127.500000, 127.500000, 127.500000 +cfg.color.red = 255.000000, 0.000000, 0.000000 +cfg.color.blue = 0.000000, 255.000000, 0.000000 +cfg.color.green = 0.000000, 0.000000, 255.000000 +cfg.color.background = 0.000000, 0.000000, 0.000000 + +cfg.debug.do = 1 +cfg.debug.smallWin = 0 +cfg.debug.transpWin = 0 + +cfg.design.localizer = 'MT' +cfg.design.motionDirections = 0.000000, 0.000000, 180.000000, 180.000000 +cfg.design.motionType = 'translation' +cfg.design.names{1} = 'static' +cfg.design.names{2} = 'motion' +cfg.design.nbEventsPerBlock = 12.000000 +cfg.design.nbRepetitions = 12.000000 + +cfg.dir.output = '/home/remi/github/CPP_localizer_visual_motion' + +cfg.dot.speed = 15.000000 +cfg.dot.coherence = 1.000000 +cfg.dot.density = 1.000000 +cfg.dot.lifeTime = 0.400000 +cfg.dot.proportionKilledPerFrame = 0.000000 +cfg.dot.size = 0.200000 +cfg.dot.staticReSeed = 1 +cfg.dot.color = 255.000000, 255.000000, 255.000000 + +cfg.extraColumns{1} = 'direction' +cfg.extraColumns{2} = 'speedDegVA' +cfg.extraColumns{3} = 'target' +cfg.extraColumns{4} = 'event' +cfg.extraColumns{5} = 'block' +cfg.extraColumns{6} = 'keyName' +cfg.extraColumns{7} = 'fixationPosition' +cfg.extraColumns{8} = 'aperturePosition' + +cfg.eyeTracker.do = 0 + +cfg.fixation.type = 'cross' +cfg.fixation.xDisplacement = 0.000000 +cfg.fixation.yDisplacement = 0.000000 +cfg.fixation.color = 255.000000, 255.000000, 255.000000 +cfg.fixation.width = 0.250000 +cfg.fixation.lineWidthPix = 3.000000 +cfg.fixation.colorTarget = 255.000000, 0.000000, 0.000000 + +cfg.keyboard.keyboard +cfg.keyboard.responseBox +cfg.keyboard.responseKey{1} = 'r' +cfg.keyboard.responseKey{2} = 'g' +cfg.keyboard.responseKey{3} = 'y' +cfg.keyboard.responseKey{4} = 'b' +cfg.keyboard.responseKey{5} = 'd' +cfg.keyboard.responseKey{6} = 'n' +cfg.keyboard.responseKey{7} = 'z' +cfg.keyboard.responseKey{8} = 'e' +cfg.keyboard.responseKey{9} = 't' +cfg.keyboard.escapeKey = 'ESCAPE' + +cfg.mri.triggerKey = 't' +cfg.mri.triggerNb = 5.000000 +cfg.mri.repetitionTime = 1.800000 + +cfg.pacedByTriggers.do = 0 + +cfg.screen.monitorWidth = 25.000000 +cfg.screen.monitorDistance = 95.000000 + +cfg.skipSyncTests = 0.000000 + +cfg.suffix.acquisition = '' + +cfg.target.duration = 0.100000 +cfg.target.maxNbPerBlock = 1.000000 +cfg.target.type = 'fixation_cross' + +cfg.task.name = 'visual localizer' +cfg.task.instruction = '1-Detect the RED fixation cross\n \n\n' +cfg.task.taskDescription = '' + +cfg.testingDevice = 'mri' + +cfg.text.color = 255.000000, 255.000000, 255.000000 + +cfg.timing.IBI = 0.000000 +cfg.timing.ISI = 0.000000 +cfg.timing.endDelay = 3.600000 +cfg.timing.eventDuration = 0.300000 +cfg.timing.onsetDelay = 0.000000 + +cfg.verbose = 1.000000 +``` diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 0d6541b..37d7f74 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -24,7 +24,8 @@ cfg.design.localizer = 'MT'; end - root_dir = fileparts(which('visualMotionLocalizer')); + root_dir = bids.internal.file_utils(fullfile(fileparts(mfilename('fullpath')), '..', '..'), ... + 'cpath'); fieldsToSet.dir.output = root_dir; fieldsToSet.skipSyncTests = 0; diff --git a/subfun/unfold.m b/subfun/unfold.m index 292acd8..92ecc62 100644 --- a/subfun/unfold.m +++ b/subfun/unfold.m @@ -140,10 +140,16 @@ function printKeyToScreen(input) function printToScreen(input) if ischar(input) - fprintf(1, ':\t%s', input); + fprintf(1, ' =\t''%s''', input); + elseif isinteger(input) + pattern = repmat('%i, ', 1, numel(input)); + fprintf(1, [' =\t' pattern '\b\b'], input); elseif isnumeric(input) pattern = repmat('%f, ', 1, numel(input)); - fprintf(1, [':\t' pattern], input); + fprintf(1, [' =\t' pattern '\b\b'], input); + elseif islogical(input) + pattern = repmat('%i, ', 1, numel(input)); + fprintf(1, [' =\t' pattern '\b\b'], input); end end diff --git a/tests/data/config_MT.mat b/tests/data/config_MT.mat index eb3976acc801dcdfb10188d29478ddfe6d45ff69..98904e1c21813289c08436155690c37297952fc4 100644 GIT binary patch delta 1390 zcmV-!1(Eu}3(5s6N>QoZ)BeWx3;F|k*+1xj z4JfeFZu<#4?l2%DDN?2swU%fUEdfS;WIylAulI}DL##GsYd~f z@uZhHIi1Dc2vQ~#rr8BoG5?-9GyrDe^wN~iI1k6ce*mtq2NF+96Jj{xU(fLsP?w~| z@}f=N|3%IAEq}ive=G18LjEk_!d_sXP0(~mQd91?hTN4Jxhsa;EskOmLzTBy;pwJ% zdc2Ex)p>N)C&8Pxod2rA;^~um{p;Q4`X6@e^&g!a6mtG)IS*}jeclh^l+nx+M_caU zh@Z0ofAG_a6M5W){AcL>`}q|z_cO=eJs1GvmfmL*=%4Hl`r3f{9wljd9{11V^LX)j z(an^v=lylJ-MsH8e8l^U31-R~+>qOO{xP61Qv?cyZM$Kn4JVjevCCNjC0Xq2@hm!r zJ!GDP9=g81w&H1hPh0TTdB3M8^!IqD`m`Fqf91Rd(Qe+$tru!(Z?_fZ;jOTD?x`au z49_q>1w3NJX(B&b`GJll4=u@?wzQki6~5p-B%TxEmrz90hzP45U<%5KSeY|pC;$;mcrsm zGL~d4m-FL-c|WMkTj1>piC~*Tgtr6CCYigvHyn<^0u*8os$cjJr+1b4Ka2L)qh<0*d%eHi&}$n%+T zoyz+r{&5|Z?M+}`2Zk1MZdc?8EbV9j!4Hq;a%}vbuB)2xS1WvhK}4>G`s?_ve++od z__r#2fqC6|EKIw}I&M|?qU$uAmuxcJ+RD-Ox+&+Q*HbP1^rpft()Fxv(*aHsUKT(k zc6(MrWfz%Oz`BJvhBNVIC~A56%Tc+Iw>>wqYN}bEHvZ{D@!sWMZ2V!~-dg$Lp6z%Q zZ>QJp{A?&J^qKcT6w-tzvan00f5qoRURd(7nw!m`EHOXSeaHKF{RRHs^xsYLZ*x7i z_$O+~3oLnc>)3?nTJn5LUR{0Ig!j^t2bR31ajh<{?w{^G9`5J-d!2T6bQjI@b(UY4 z9;$m71&`hQ*R&`Tbt1gXJlp!0)tdEb>ev4GU9|rmeF|~%O-udeePKjmf6NFy(_v3x z9wC_{iW!@Ay>Gc6V@sZ1ho4%mgZB60>3GjGoTomu`_bwiv!%W0yyY9-{frv_mx!F{ zv0GfLlyjQ7KKnZ5SF5<(LCy01O;lbVfpxw*Rtb=-TUxG{KEGnz;xfuy4?MsBmYCJt ze=iz$U4ES3BlL@lg-`h&P<@gA?3H*u`M)k3Kc?e`cnvJ0C=3uSx;}%6x8+;my0fjg0(p%HSDG~$;jKo-W2;k|@i%dik1&T`Tev|GK^aJ#=+m0Qu z0R?v1ZufV({#QS5m@V-!0S zKpRhdfuoaI=!_s{LLsxL2ilOB6<_G`7=I6k-T*GKe*-C=7AC-Oz<-|OOQ1H1^W{XF zy#I^peW&dCO8TzAp9}f3hzom(T{c0}A&GUl-)M4ID&($ca=RRbB!n_=t;ADJ@zi)1 z@yhdP%R9lFHk|*e#Nz6bYW?f&`ud-?%=I50@8@#UUTbrfM@bU8YCMbVu!D3v z=%A~sDai@1J6B z1w2E9ag^Q~#etR~4=u@?HuRg%BtGZeCywRgSCD7VfC#T1UJAU zfAg(?kn={9(<;ePV^+`8Jg`9T8Y=1)IA&a@W6saMl3D)TK+ExdLCx&%j>O_h5*8)w zdj77O_nl@fuDrd@n~5DfFyvLm%OJ9TojhU{@uK26FC|r(#6wkY)#0y}fA|7} z$Y?e7SMlvM5!U11De(p7_2-dr?KvtakyhTUdh|)G_#)#iG@D>e_V({9Pte*-k97`m6R)=* z-s|zZ&c0kJinwO7iBfQK!o5q*biuI`**M9#^wEv!ce+qf>T|@o) zIbuLU%m_VIX-{IFA(`e|ukBmHiVPLC7mS-;zfk nX{9w#t|azQO#AgV_QB?He`Cv(|6SVtSn6EDBwqXv|D5>bLUPHZ diff --git a/tests/data/config_MT_MST.mat b/tests/data/config_MT_MST.mat index aea940ad346f27afb30a02f496438f6f59591ce5..17e80aff05fd9b8f2d448d361baaadce76dea141 100644 GIT binary patch delta 1452 zcmV;d1ylO{3x^DlKMgT3Ix;mnGczDEFfuZcQ6rIH1(9?Re}4r40C=3uSaqBk%s=M^jPUX-0tkmp7zWeuus4%@B(O& zKw60tH;x>608p^I?QVCcH`DeAv6ejD<>{}=u69+qsy7fqe}0V6GP}ORdI#lgNze;Q z=QK=Wa45J-e`pbHit(8JSTPWq5)g1?r7n(8*=+143W=P^kBCCMV5eS%POuj$G*+Kx zbVMsOOenGTBR>toOb$$8NG#_X1nde=EQ+Io<26j}$Re(!1A;63V#@({Z#pE{^ME8M zaR`7ipX3_H=hM&`LPEK~B)wuH%KxcFJfJF_T&w&kf5YL>>%$FpAfqRh1yLNZzf1ZC zh#e(`deH{|S!nm(^6|y&Sx&#t`A=iU>=}0H7)=IIqVj!=O1_H?e3uozn}T*QaeT<} zpDXy~8T0C}yA@=H>k8Zi>FHrf(ERE~<+@e*tDV{M3w>$62UY&b*-^pgFU@sG`|GiO z6eg6Ue-7W`*}ELF{niJzYjK=yd(QuBbpLz(1XbTFr@wgA2g)qIN5{}RJLvbMA@v** zCCO#jy9_VGyZWp1mrdm_*ZpZnZ{6<-`h@joV@!or*gmuO{MI8d6#xQ-joW@I4ah64 z*=8t@L}}>C`OMmfU8L@VF1o$FHNr`GPc?9>f2?oG1^qGFsb7ueZ@6v_G+Xz4`qK4# zYl8j=mG;g&c3}Db1!lW|MUF6uvs)uSuwaNobK+if_4M$8pnpPTJY=pPmvPaL9LvYg zp&Dz0h(FQC1WNxRM~7J)DO+d-Pzm(;sC{q)Ax#EA_Lz)oIeG>$P^>UzZPLd{%uE>q ze}>qV$BN46VHwQ19%4m*<$9a-z@Ohi_xr*3l;<}EE%i0>;ff;jIC(N0otzKb*-b~m zcbSBjovVLLTVYwF8HUcNib;`$ac!>t?Qx`sG;ZutS}+2M+y`87&uoYI`n zH#7A7sHSI5Z;zt@wh07y+rxC6+S~hsf5E7*403i=i6NepE` zRhtuyfk5a${SOyH=3=II5k9_xAr9^UP)wpYB7DNf*!RI@UgMB3zk(9Bq$b%Yq0Bg) zGdQnLuAXKT&E$PQFvK;*2OZpF4cw|2fB8LczdtdNEA?Y8_vbruP2;G}`Ri%te}2EF zj<<;etEg&koOWdt)ZnvLAuOb#|HiAfB2{W3il@eV&V_;_S(n~w>_7DWe*}4I=TDO& z|CI;fdDf}xUzQs5)7G#3`U`J=KY1JCda>W9-s9Z4L3f3mzqQ(tob@_F-mo2n07eh0{C+VCA<*1Vg}#{umH3GEey zg}3>8!Yu#Ut>C)Zw?7jRbcFnQz0K-%;?YN?01T`d~oOy#YidE?*ujw$}j4y^q)SAE9BZ~Y7Y G79AM`dGDzJ delta 1442 zcmV;T1zq}w4E+m`KMgQAIy5voGBY4DFfuZcQ6rIH1(9?Re{}@_0C=3uSxax*Mi5?0 ze$=j;2tBmUrPZkj3IuA0%cUdb)N}tq^G|x~sYrnq z2+&h+{R#a6E!1*4-i6=&kcgg|IaK){g^+c-cunb?jL7FmHC5QVqFjGY1>VaHc^tiH|o zfEIX|QeqqgZtVGq9+<(97}gC4*ceX@ii1qz4b05IAhzT^f(!CO!vcGMHYC__fJ7*= z2!Jx5=mv+EGv69QM7ct05C@bgQ6suh%X>x$ft;4Mrn7gGFJ3VwaT zyjtvO1L@(~0yjm??64+yez${s-Kzf0)?)pcy&8T8RsY$=Nhas-hU<|2)@9d;A5jup zd`l#eo}e}5O<9|u2D-tP!r+H2&(m?Hf=c{UuKT@LH{O-sSInTA)b z@xQuyiD6^IP4!M1+Dk`Yx;ymp`VP{=ZEND%nmBoG`586y!wtdndl1twrt{~RDm(W} zcIJF<5_r%f;NhNw=_EFL2ZO;V^W)Jie~x0q9i^Y67sci{_Ioyrjo778Pijx~ziF6< z9|`_7yP^>CM5~e&On`uILHQpx_$>6y<`FI)!w`FO02GoS3jEyzlPi}S8R_hUhnl#mywL>rtO0IQjKBJk)1S|E^h*2a>-}|3f3I$S zZE`L?f@uNOC-|XdbbmFh9KkMMvN_fr#&(}5e zSK&>O=Ih`$N_ft*di6`B>e zVu(yT1(ICs!xbMH;He0v!(zije|O&`Rb_>Jn#8C73-`A8q7x5OdZQJG>z-HMR_E2;ZNUDMwsJ{9~A>^j*$K^1gzSvhP?4BvsHa!(d~RtmaCxkr-J wX8k$m Date: Wed, 2 Mar 2022 10:30:09 +0100 Subject: [PATCH 13/64] make test less brittle --- tests/test_checkParameters.m | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m index 8868154..b1d9249 100644 --- a/tests/test_checkParameters.m +++ b/tests/test_checkParameters.m @@ -11,25 +11,27 @@ function test_checkParameters_MT() cfg.design.localizer = 'MT'; cfg = checkParameters(cfg); - expected = cfg; - save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); - load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat')); + % expected = cfg; + % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); + load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); + cfg = rmfield(cfg, 'dir'); + expected = rmfield(expected, 'dir'); %#ok<*NODEF> fields = fieldnames(expected); for i = 1:numel(fields) assertEqual(cfg.(fields{i}), expected.(fields{i})); end - unfold(cfg); - end function test_checkParameters_MT_MST() cfg.design.localizer = 'MT_MST'; cfg = checkParameters(cfg); - expected = cfg; - save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); - load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat')); + % expected = cfg; + % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); + load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); + cfg = rmfield(cfg, 'dir'); + expected = rmfield(expected, 'dir'); fields = fieldnames(expected); for i = 1:numel(fields) assertEqual(cfg.(fields{i}), expected.(fields{i})); From b63a32c0f5450d8624e74270a82c00aa8184865a Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 2 Mar 2022 10:51:34 +0100 Subject: [PATCH 14/64] make test less brittle --- subfun/defaults/checkParameters.m | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 37d7f74..7ad2dcf 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -24,8 +24,10 @@ cfg.design.localizer = 'MT'; end - root_dir = bids.internal.file_utils(fullfile(fileparts(mfilename('fullpath')), '..', '..'), ... - 'cpath'); + root_dir = fullfile(fileparts(mfilename('fullpath')), '..', '..'); + if which('bids.internal.file_utils') + root_dir = bids.internal.file_utils(root_dir, 'cpath'); + end fieldsToSet.dir.output = root_dir; fieldsToSet.skipSyncTests = 0; From 33760301d89bf467c4b3a979805979f29a13d0c3 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Mon, 7 Mar 2022 10:31:55 +0100 Subject: [PATCH 15/64] move unfold to CPP_PTB --- initEnv.m | 1 + lib/CPP_PTB | 2 +- subfun/unfold.m | 184 ------------------------------------------------ 3 files changed, 2 insertions(+), 185 deletions(-) delete mode 100644 subfun/unfold.m diff --git a/initEnv.m b/initEnv.m index 2ef23d0..f3d7e2f 100644 --- a/initEnv.m +++ b/initEnv.m @@ -102,6 +102,7 @@ function addDependencies() pth = fileparts(mfilename('fullpath')); addpath(fullfile(pth, 'lib', 'CPP_BIDS')); addpath(genpath(fullfile(pth, 'lib', 'CPP_PTB', 'src'))); + addpath(genpath(fullfile(pth, 'lib', 'CPP_PTB', 'lib'))); addpath(genpath(fullfile(pth, 'subfun'))); checkCppBidsDependencies(); diff --git a/lib/CPP_PTB b/lib/CPP_PTB index cdcd293..f103e47 160000 --- a/lib/CPP_PTB +++ b/lib/CPP_PTB @@ -1 +1 @@ -Subproject commit cdcd29317b1df31ec196f4575255245e8fcca864 +Subproject commit f103e47f8979c79c39c045ed4058279abc35881a diff --git a/subfun/unfold.m b/subfun/unfold.m deleted file mode 100644 index 92ecc62..0000000 --- a/subfun/unfold.m +++ /dev/null @@ -1,184 +0,0 @@ -function unfold(input, varargin) - % - % Unfolds a structure. - % - % USAGE:: - % - % unfold(SC, varargin) - % - % UNFOLD(SC) displays the content of a variable. - % - % If SC is a structure it recursively shows the name of SC and the fieldnames of SC and their - % contents. - % - % If SC is a cell array the contents of each cell are displayed. - % - % It uses the caller's workspace variable name as the name of SC. - % UNFOLD(SC,NAME) uses NAME as the name of SC. - % - % UNFOLD(SC,SHOW) If SHOW is false only the fieldnames and their sizes - % are shown, if SHOW is true the contents are shown also. - % - % (C) Copyright 2022 Remi Gau - % (C) Copyright 2005-2006 R.F. Tap - - % R.F. Tap - % 15-6-2005, 7-12-2005, 5-1-2006, 3-4-2006 - - % taken and adapted from shorturl.at/dqwN7 - - % check input - switch nargin - case 1 - Name = inputname(1); - show = true; - case 2 - if islogical(varargin{1}) - Name = inputname(1); - show = varargin{1}; - elseif ischar(varargin{1}) - Name = varargin{1}; - show = true; - else - error('Second input argument must be a string or a logical'); - end - case 3 - if ischar(varargin{1}) - if islogical(varargin{2}) - Name = varargin{1}; - show = varargin{2}; - else - error('Third input argument must be a logical'); - end - else - error('Second input argument must be a string'); - end - otherwise - error('Invalid number of input arguments'); - end - - fprintf('\n'); - - if isstruct(input) - % number of elements to be displayed - NS = numel(input); - if show - hmax = NS; - else - hmax = min(1, NS); - end - - % recursively display structure including fieldnames - for h = 1:hmax - F = fieldnames(input(h)); - NF = length(F); - for i = 1:NF - if NS > 1 - siz = size(input); - if show - Namei = [Name '(' indToStr(siz, h) ').' F{i}]; - else - Namei = [Name '(' indToStr(siz, NS) ').' F{i}]; - end - else - Namei = [Name '.' F{i}]; - end - if isstruct(input(h).(F{i})) - unfold(input(h).(F{i}), Namei, show); - else - if iscell(input(h).(F{i})) - siz = size(input(h).(F{i})); - NC = numel(input(h).(F{i})); - if show - jmax = NC; - else - jmax = 1; - end - for j = 1:jmax - if show - Namej = [Namei '{' indToStr(siz, j) '}']; - else - Namej = [Namei '{' indToStr(siz, NC) '}']; - end - printKeyToScreen(Namej); - if show - printToScreen(input(h).(F{i}){j}); - end - end - else - printKeyToScreen(Namei); - if show - printToScreen(input(h).(F{i})); - end - end - end - end - end - - elseif iscell(input) - % recursively display cell - siz = size(input); - for i = 1:numel(input) - Namei = [Name '{' indToStr(siz, i) '}']; - unfold(input{i}, Namei, show); - end - - else - disp(Name); - if show - printToScreen(input); - end - end - - fprintf('\n'); - -end - -function printKeyToScreen(input) - fprintf(1, '\n%s', input); -end - -function printToScreen(input) - if ischar(input) - fprintf(1, ' =\t''%s''', input); - elseif isinteger(input) - pattern = repmat('%i, ', 1, numel(input)); - fprintf(1, [' =\t' pattern '\b\b'], input); - elseif isnumeric(input) - pattern = repmat('%f, ', 1, numel(input)); - fprintf(1, [' =\t' pattern '\b\b'], input); - elseif islogical(input) - pattern = repmat('%i, ', 1, numel(input)); - fprintf(1, [' =\t' pattern '\b\b'], input); - end -end - -% local functions -% -------------------------------------------------------------------------- -function str = indToStr(siz, ndx) - - n = length(siz); - % treat vectors and scalars correctly - if n == 2 - if siz(1) == 1 - siz = siz(2); - n = 1; - elseif siz(2) == 1 - siz = siz(1); - n = 1; - end - end - k = [1 cumprod(siz(1:end - 1))]; - ndx = ndx - 1; - str = ''; - for i = n:-1:1 - v = floor(ndx / k(i)) + 1; - if i == n - str = num2str(v); - else - str = [num2str(v) ',' str]; - end - ndx = rem(ndx, k(i)); - end - -end From eb48cd3e1fd28e7225a1f33c16c78d0aececffda Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Mon, 7 Mar 2022 14:50:15 +0100 Subject: [PATCH 16/64] update CPP_PTB --- lib/CPP_PTB | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CPP_PTB b/lib/CPP_PTB index f103e47..bf19773 160000 --- a/lib/CPP_PTB +++ b/lib/CPP_PTB @@ -1 +1 @@ -Subproject commit f103e47f8979c79c39c045ed4058279abc35881a +Subproject commit bf19773c174d0b60279da0804a8eeb1a40521f96 From f896b1128c6d638ce0867a5074b62e0d494fcc62 Mon Sep 17 00:00:00 2001 From: marcobarilari Date: Tue, 8 Mar 2022 18:37:47 +0100 Subject: [PATCH 17/64] add option for specific use case --- main.m | 39 ++++++++++++++++++++++++++--- subfun/defaults/checkParameters.m | 41 ++++++++++++++----------------- visualMotionLocalizer.m | 6 ++--- 3 files changed, 57 insertions(+), 29 deletions(-) diff --git a/main.m b/main.m index 4928f89..e96c0bf 100644 --- a/main.m +++ b/main.m @@ -2,17 +2,48 @@ % % (C) Copyright 2020 CPP visual motion localizer developers +clear all +clc + +%% Run MT+ localizer + cfg.design.localizer = 'MT'; +cfg.debug.do = true; +cfg.pacedByTriggers.do = true; +cfg.eyeTracker.do = false; + +cfg.design.nbRepetitions = 15; +cfg.timing.eventDuration = 0.43; % second initEnv(); cfg = checkParameters(cfg); -%% To view all the options that are set -% +% to view all the options that are set % unfold(cfg); -%% Run -% +% run +visualMotionLocalizer(cfg); + +clear cfg + +% Run MT/MST localizer + +cfg.design.localizer = 'MT_MST'; +cfg.debug.do = true; +cfg.eyeTracker.do = false; +cfg.design.nbRepetitions = 10; +cfg.design.nbEventsPerBlock = 12; + +initEnv(); + +cfg = checkParameters(cfg); + +% to view all the options that are set +% unfold(cfg); + +% run visualMotionLocalizer(cfg); + +clear cfg \ No newline at end of file diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 7ad2dcf..70634e2 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -2,7 +2,7 @@ % % Check that all parameters are sets. If not it uses the defaults. % - % ``cfg.design.localizer``: switching this to ``MT`` or ``MT_MST`` + % ``cfg.design.localizer``: switching this to ``MT`` (deafult) or ``MT_MST`` % % - ``MT``: translational motion on the whole screen % @@ -11,7 +11,7 @@ % - ``MT_MST``: radial motion centered in a circle aperture that is on the opposite % side of the screen relative to the fixation % - % - alternates fixaton left and fixation right + % - (default) alternates fixaton left and fixation right % % ``cfg.dir.output``: by default the data will be stored in an output folder created in the root % dir of this repo. Change that if you want the data to be saved somewhere @@ -28,14 +28,14 @@ if which('bids.internal.file_utils') root_dir = bids.internal.file_utils(root_dir, 'cpath'); end - fieldsToSet.dir.output = root_dir; + fieldsToSet.dir.output = fullfile(root_dir, 'output'); fieldsToSet.skipSyncTests = 0; fieldsToSet.verbose = 1; %% Debug mode settings - fieldsToSet.debug.do = true; + fieldsToSet.debug.do = false; fieldsToSet.debug.smallWin = false; fieldsToSet.debug.transpWin = false; @@ -54,19 +54,19 @@ % localizer && 2 hemifield it is 8 blocks per hemifield), i.e. how many times each condition % will be repeated fieldsToSet.design.nbRepetitions = 12; + fieldsToSet.design.nbEventsPerBlock = 12; %% Timing - % IBI % block length = (cfg.eventDuration + cfg.ISI) * cfg.design.nbEventsPerBlock fieldsToSet.timing.eventDuration = 0.30; % second % Time between events in secs - fieldsToSet.timing.ISI = 0; + fieldsToSet.timing.ISI = 0.1; % Number of seconds before the motion stimuli are presented - fieldsToSet.timing.onsetDelay = 0; + fieldsToSet.timing.onsetDelay = 5; % Number of seconds after the end all the stimuli before ending the run - fieldsToSet.timing.endDelay = 3.6; + fieldsToSet.timing.endDelay = 5; %% Visual Stimulation fieldsToSet.dot = cppPtbDefaults('dot'); @@ -158,8 +158,6 @@ function cfg = setParametersMtMst(cfg) - fieldsToSet.design.nbEventsPerBlock = 12; - switch lower(cfg.design.localizer) case 'mt_mst' @@ -170,15 +168,17 @@ fieldsToSet.design.motionDirections = [666 -666]; fieldsToSet.design.names = {'motion'}; % {'static'; 'motion'} - fieldsToSet.design.fixationPosition = {'fixation_left'}; - % {'fixation_right'; 'fixation_left'}; + fieldsToSet.design.fixationPosition = {'fixation_right'; 'fixation_left'}; + % {'fixation_right'; 'fixation_left'}; fieldsToSet.design.xDisplacementFixation = 7; fieldsToSet.design.xDisplacementAperture = 3; % inward and outward are presented as separated event - fieldsToSet.design.nbEventsPerBlock = fieldsToSet.design.nbEventsPerBlock * 2; - - fieldsToSet.timing.IBI = 4; + fieldsToSet.design.nbEventsPerBlock = cfg.design.nbEventsPerBlock * 2; + + % time between events in secs + fieldsToSet.timing.ISI = 0; + fieldsToSet.timing.IBI = 10; fieldsToSet.timing.changeFixationPosition = 10; fieldsToSet.aperture.type = 'circle'; @@ -194,7 +194,7 @@ fieldsToSet.design.names = {'static'; 'motion'}; % Time between blocs in secs - fieldsToSet.timing.IBI = 0; + fieldsToSet.timing.IBI = 4; % Diameter/length of side of aperture in Visual angles fieldsToSet.aperture.type = 'none'; @@ -212,19 +212,16 @@ % reexpress those in terms of repetition time if cfg.pacedByTriggers.do - fieldsToSet.pacedByTriggers.quietMode = true; + fieldsToSet.pacedByTriggers.quietMode = false; fieldsToSet.pacedByTriggers.nbTriggers = 1; - fieldsToSet.timing.eventDuration = fieldsToSet.mri.repetitionTime / 2 - 0.04; % second + fieldsToSet.timing.eventDuration = cfg.mri.repetitionTime / 2 - 0.04; % second % Time between blocs in nb of triggers (remember to consider the nb trigger to wait + 1) fieldsToSet.timing.triggerIBI = 4; % Time between blocks in secs fieldsToSet.timing.IBI = 0; - if strcmpi(cfg.design.localizer, 'mt_mst') - fieldsToSet.timing.IBI = 2; - end % Time between events in secs fieldsToSet.timing.ISI = 0; @@ -233,7 +230,7 @@ fieldsToSet.timing.onsetDelay = 0; % Number of seconds after the end all the stimuli before ending the run - fieldsToSet.timing.endDelay = 2; + fieldsToSet.timing.endDelay = 0; cfg = setDefaultFields(cfg, fieldsToSet); diff --git a/visualMotionLocalizer.m b/visualMotionLocalizer.m index eee1f35..3606313 100755 --- a/visualMotionLocalizer.m +++ b/visualMotionLocalizer.m @@ -29,13 +29,13 @@ function visualMotionLocalizer(cfg) % Safety loop: close the screen if code crashes try - [cfg] = initPTB(cfg); + cfg = initPTB(cfg); cfg = postInitializationSetup(cfg); - [el] = eyeTracker('Calibration', cfg); + cfg.el = eyeTracker('Calibration', cfg); - [cfg] = expDesign(cfg); + cfg = expDesign(cfg); % Prepare for the output logfiles with all logFile.extraColumns = cfg.extraColumns; From 697249b076cd89668114e4b4b68e2e3a53248371 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 9 Mar 2022 12:22:31 +0100 Subject: [PATCH 18/64] Apply suggestions from code review --- subfun/defaults/checkParameters.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 70634e2..a780ec8 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -2,7 +2,7 @@ % % Check that all parameters are sets. If not it uses the defaults. % - % ``cfg.design.localizer``: switching this to ``MT`` (deafult) or ``MT_MST`` + % ``cfg.design.localizer``: switching this to ``MT`` (default) or ``MT_MST`` % % - ``MT``: translational motion on the whole screen % From d1189a4d78032af53c1ec6fb7702c0655246ff35 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 9 Mar 2022 11:24:45 +0000 Subject: [PATCH 19/64] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- main.m | 2 +- subfun/defaults/checkParameters.m | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/main.m b/main.m index e96c0bf..f572d5b 100644 --- a/main.m +++ b/main.m @@ -46,4 +46,4 @@ % run visualMotionLocalizer(cfg); -clear cfg \ No newline at end of file +clear cfg diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index a780ec8..ddaa29f 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -169,13 +169,13 @@ fieldsToSet.design.names = {'motion'}; % {'static'; 'motion'} fieldsToSet.design.fixationPosition = {'fixation_right'; 'fixation_left'}; - % {'fixation_right'; 'fixation_left'}; + % {'fixation_right'; 'fixation_left'}; fieldsToSet.design.xDisplacementFixation = 7; fieldsToSet.design.xDisplacementAperture = 3; % inward and outward are presented as separated event fieldsToSet.design.nbEventsPerBlock = cfg.design.nbEventsPerBlock * 2; - + % time between events in secs fieldsToSet.timing.ISI = 0; fieldsToSet.timing.IBI = 10; From 62c4c9baa1c4d4eded45297855a6baee46bd461c Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 9 Mar 2022 12:29:28 +0100 Subject: [PATCH 20/64] conflict resolution --- main.m | 14 +- ...izer_run-666_date-202203091033_events.json | 86 ++++++++ ...izer_run-001_date-202203091034_events.json | 86 ++++++++ subfun/defaults/checkParameters.m | 13 +- subfun/visualMotionLocalizer.m | 207 ++++++++++++++++++ tests/data/config_MT.mat | Bin 1482 -> 1497 bytes tests/data/config_MT_MST.mat | Bin 1543 -> 1591 bytes tests/test_checkParameters.m | 118 +++++++++- 8 files changed, 498 insertions(+), 26 deletions(-) create mode 100644 source/sub-ctrl666/ses-666/func/sub-ctrl666_ses-666_task-visualLocalizer_run-666_date-202203091033_events.json create mode 100644 source/sub-foo001/ses-001/func/sub-foo001_ses-001_task-visualLocalizer_run-001_date-202203091034_events.json create mode 100755 subfun/visualMotionLocalizer.m diff --git a/main.m b/main.m index f572d5b..93bfd5a 100644 --- a/main.m +++ b/main.m @@ -2,8 +2,8 @@ % % (C) Copyright 2020 CPP visual motion localizer developers -clear all -clc +clc; +clear; %% Run MT+ localizer @@ -15,6 +15,12 @@ cfg.design.nbRepetitions = 15; cfg.timing.eventDuration = 0.43; % second +cfg.debug.do = false; +cfg.debug.transpWin = 0; +cfg.debug.smallWin = 0; + +cfg.verbosity = 2; + initEnv(); cfg = checkParameters(cfg); @@ -22,12 +28,12 @@ % to view all the options that are set % unfold(cfg); -% run +% Run visualMotionLocalizer(cfg); clear cfg -% Run MT/MST localizer +%% Run MT/MST localizer cfg.design.localizer = 'MT_MST'; cfg.debug.do = true; diff --git a/source/sub-ctrl666/ses-666/func/sub-ctrl666_ses-666_task-visualLocalizer_run-666_date-202203091033_events.json b/source/sub-ctrl666/ses-666/func/sub-ctrl666_ses-666_task-visualLocalizer_run-666_date-202203091033_events.json new file mode 100644 index 0000000..62cfd4c --- /dev/null +++ b/source/sub-ctrl666/ses-666/func/sub-ctrl666_ses-666_task-visualLocalizer_run-666_date-202203091033_events.json @@ -0,0 +1,86 @@ +{ + "onset": { + "Description": "time elapsed since experiment start", + "Units": "s" + }, + "trial_type": { + "Description": "types of trial", + "Levels": { + } + }, + "duration": { + "Description": "duration of the event or the block", + "Units": "s" + }, + "StimulusPresentation": { + "OperatingSystem": "x86_64-pc-linux-gnu", + "SoftwareRRID": "SCR_002881", + "Code": "", + "SoftwareVersion": "3.0.17", + "SoftwareName": "Psychtoolbox on Octave - 4.2.2" + }, + "direction": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + }, + "speedDegVA": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + }, + "target": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + }, + "event": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + }, + "block": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + }, + "keyName": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + }, + "fixationPosition": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + }, + "aperturePosition": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + } +} diff --git a/source/sub-foo001/ses-001/func/sub-foo001_ses-001_task-visualLocalizer_run-001_date-202203091034_events.json b/source/sub-foo001/ses-001/func/sub-foo001_ses-001_task-visualLocalizer_run-001_date-202203091034_events.json new file mode 100644 index 0000000..62cfd4c --- /dev/null +++ b/source/sub-foo001/ses-001/func/sub-foo001_ses-001_task-visualLocalizer_run-001_date-202203091034_events.json @@ -0,0 +1,86 @@ +{ + "onset": { + "Description": "time elapsed since experiment start", + "Units": "s" + }, + "trial_type": { + "Description": "types of trial", + "Levels": { + } + }, + "duration": { + "Description": "duration of the event or the block", + "Units": "s" + }, + "StimulusPresentation": { + "OperatingSystem": "x86_64-pc-linux-gnu", + "SoftwareRRID": "SCR_002881", + "Code": "", + "SoftwareVersion": "3.0.17", + "SoftwareName": "Psychtoolbox on Octave - 4.2.2" + }, + "direction": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + }, + "speedDegVA": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + }, + "target": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + }, + "event": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + }, + "block": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + }, + "keyName": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + }, + "fixationPosition": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + }, + "aperturePosition": { + "Description": "", + "Levels": { + }, + "LongName": "", + "TermURL": "", + "Units": "" + } +} diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index ddaa29f..2db3764 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -28,20 +28,11 @@ if which('bids.internal.file_utils') root_dir = bids.internal.file_utils(root_dir, 'cpath'); end - fieldsToSet.dir.output = fullfile(root_dir, 'output'); - - fieldsToSet.skipSyncTests = 0; - - fieldsToSet.verbose = 1; - %% Debug mode settings - fieldsToSet.debug.do = false; - fieldsToSet.debug.smallWin = false; - fieldsToSet.debug.transpWin = false; + fieldsToSet.dir.output = fullfile(root_dir, 'output'); %% Engine parameters fieldsToSet.testingDevice = 'mri'; - fieldsToSet.eyeTracker.do = false; fieldsToSet = setMonitor(fieldsToSet); @@ -104,6 +95,8 @@ cfg = setTarget(cfg); + cfg = checkCppPtbCfg(cfg); + if cfg.verbose == 2 unfold(cfg); end diff --git a/subfun/visualMotionLocalizer.m b/subfun/visualMotionLocalizer.m new file mode 100755 index 0000000..dd3e461 --- /dev/null +++ b/subfun/visualMotionLocalizer.m @@ -0,0 +1,207 @@ +function visualMotionLocalizer(cfg) + % + % (C) Copyright 2018 Mohamed Rezk + % (C) Copyright 2020 CPP visual motion localizer developers + + if nargin < 1 + cfg.design.localizer = 'MT'; + end + + getOnlyPress = 1; + + % Clear all the previous stuff + clc; + if ~ismac + close all; + clear Screen; + end + + % make sure we got access to all the required functions and inputs + initEnv(); + + % set and load all the parameters to run the experiment + cfg = checkParameters(cfg); + cfg = userInputs(cfg); + cfg = createFilename(cfg); + + %% Experiment + + % Safety loop: close the screen if code crashes + try + + [cfg] = initPTB(cfg); + + cfg = postInitializationSetup(cfg); + + [el] = eyeTracker('Calibration', cfg); + + [cfg] = expDesign(cfg); + + % Prepare for the output logfiles with all + logFile.extraColumns = cfg.extraColumns; + logFile = saveEventsFile('init', cfg, logFile); + logFile = saveEventsFile('open', cfg, logFile); + + % prepare textures + cfg = apertureTexture('init', cfg); + cfg = dotTexture('init', cfg); + + if cfg.verbose == 2 + unfold(cfg); + end + + % Show experiment instruction + standByScreen(cfg); + + % prepare the KbQueue to collect responses + getResponse('init', cfg.keyboard.responseBox, cfg); + + waitForTrigger(cfg); + + % Start + eyeTracker('StartRecording', cfg); + + cfg = getExperimentStart(cfg); + + getResponse('start', cfg.keyboard.responseBox); + + waitFor(cfg, cfg.timing.onsetDelay); + + for iBlock = 1:cfg.design.nbBlocks + + fprintf('\n - Running Block %.0f \n', iBlock); + + eyeTracker('Message', cfg, ['start_block-', num2str(iBlock)]); + + dots = []; + previousEvent.target = 0; + + for iEvent = 1:cfg.design.nbEventsPerBlock + + checkAbort(cfg, cfg.keyboard.keyboard); + + [thisEvent, thisFixation, cfg] = preTrialSetup(cfg, iBlock, iEvent); + + % we wait for a trigger every 2 events + if cfg.pacedByTriggers.do && mod(iEvent, 2) == 1 + waitForTrigger(cfg, ... + cfg.keyboard.responseBox, ... + cfg.pacedByTriggers.quietMode, ... + cfg.pacedByTriggers.nbTriggers); + end + + eyeTracker('Message', cfg, ... + ['start_trial-', num2str(iEvent), '_', thisEvent.trial_type]); + + % we only reuse the dots position for targets that consists of + % presenting static dots with the same position as those of the + % previous trial + % + % TODO does not take into account what to do if 3 or more targets in a row + if strcmp(cfg.target.type, 'static_repeat') && ... + strcmp(thisEvent.trial_type, 'static') && ... + thisEvent.target == 1 && ... + thisEvent.target == previousEvent.target + else + dots = []; + end + + % play the dots and collect onset and duraton of the event + [onset, duration, dots] = doDotMo(cfg, thisEvent, thisFixation, dots, iEvent); + + thisEvent = preSaveSetup(thisEvent, ... + thisFixation, ... + iBlock, iEvent, ... + duration, onset, ... + cfg, ... + logFile); + + saveEventsFile('save', cfg, thisEvent); + + % collect the responses and appends to the event structure for + % saving in the tsv file + responseEvents = getResponse('check', cfg.keyboard.responseBox, cfg, ... + getOnlyPress); + + triggerString = ['trigger_' cfg.design.blockNames{iBlock}]; + saveResponsesAndTriggers(responseEvents, cfg, logFile, triggerString); + + eyeTracker('Message', cfg, ... + ['end_trial-', num2str(iEvent), '_', thisEvent.trial_type]); + + previousEvent = thisEvent; + + waitFor(cfg, cfg.timing.ISI); + + end + + % "prepare" cross for the baseline block + % if MT / MST this allows us to set the cross at the position of the next block + if iBlock < cfg.design.nbBlocks + nextBlock = iBlock + 1; + else + nextBlock = cfg.design.nbBlocks; + end + + [~, thisFixation] = preTrialSetup(cfg, nextBlock, 1); + drawFixation(thisFixation); + Screen('Flip', cfg.screen.win); + + eyeTracker('Message', cfg, ['end_block-', num2str(iBlock)]); + + waitFor(cfg, cfg.timing.IBI); + + % IBI trigger paced + if cfg.pacedByTriggers.do + waitForTrigger(cfg, ... + cfg.keyboard.responseBox, ... + cfg.pacedByTriggers.quietMode, ... + cfg.timing.triggerIBI); + end + + if isfield(cfg.design, 'localizer') && ... + strcmpi(cfg.design.localizer, 'MT_MST') && ... + iBlock == cfg.design.nbBlocks / 2 + + waitFor(cfg, cfg.timing.changeFixationPosition); + + end + + % trigger monitoring + triggerEvents = getResponse('check', cfg.keyboard.responseBox, cfg, ... + getOnlyPress); + + triggerString = 'trigger_baseline'; + saveResponsesAndTriggers(triggerEvents, cfg, logFile, triggerString); + + end + + % End of the run for the BOLD to go down + waitFor(cfg, cfg.timing.endDelay); + + cfg = getExperimentEnd(cfg); + + eyeTracker('StopRecordings', cfg); + + % Close the logfiles + saveEventsFile('close', cfg, logFile); + + getResponse('stop', cfg.keyboard.responseBox); + getResponse('release', cfg.keyboard.responseBox); + + eyeTracker('Shutdown', cfg); + + createJson(cfg, cfg); + + farewellScreen(cfg); + + cleanUp(); + + catch + + cleanUp(); + psychrethrow(psychlasterror); + + end + +end diff --git a/tests/data/config_MT.mat b/tests/data/config_MT.mat index 98904e1c21813289c08436155690c37297952fc4..c53f206d3748a83df6222437cdd8f0a0a358de97 100644 GIT binary patch delta 1407 zcmV-_1%Ud>3)u^hJr6k`F)=zdH##&mATlsAGLcaukzfUpbP#`01pokeoXuHJZ`(E$ zr|l$L+936MYA>5lLouMhhFx;2n>a;-AVH8A%MJlD{dsW+%c4qBiQUt_#`Xz%+@Y7< zcHDps2(Z&``v^PkFd!o-(xO!@mS`*~0b2S=`n^X{kM9q?ju5)~1fdmi{802J%G$EV z4XaBG;{*Z@;WB?(LT!Eh8}Z{MKzT|*(~*~kn4rA*IAj(?0f`8;a0q@nn86GWVha;) z)5SPA^|nZqj$$PjCeWu|Fa$01439mI$yCA+CO+|KXz+;Q8F`5pK)5;SQ#=>|Wrzh7 zz|zl#I60ccK_3{G3R!w4ROI)$M+d-d%!amnE_gT|^x%I22cYnH=7l&OiQ7580O}Jq zoldka`roM9cgn6Wsb?jADCJKQA?y-|{2YxB2(#sWZpmFLk-KEcZ3`5W7>c}=0?#zV zGvl4dE51ilpGn@h=KC*eERP{6*T34VuK%Y-J^g0hqH8=sPjv zG!3L_t8ahU7k1VIVXZh(<}T%bjc)#)pCbEvX84PzJ>X(xclbGU4!3(9vw%7QC5)ZK zos;+^o^LOv+49Z&eOvRrA80I(hmZirazK4Ng86n-9EWXxPnz|{abM#-(S6}#29%_6 zi2O*LXHWT2YL@CC_Z#ALqOVezdY;R3%xBm2y!C(3nt6}b?enf(^<698%No2@(I1(~ z`SY|}Ji3hI+VQ=wue0%^n(O|a#vh~H?+6b}y_hA(I7V#bMUgxy8CMm5)VL$wxaPX~ zNaHinBNBKKeht%@KO%B5_b>(R%(4r86{l2-y%Egh46(m`0WoI>KsSZFp}3H{1^r}| zc-DWk#@QBVuV2kR>^Rs|=(0@4AKCgctgIo*QxqxZjU}g1kYmPduFK~)=IC8P zvw9_FT<8qk`Po-;i{oo(G2T^8`+KbM&+@$!$X&4A0&)%%;sA;_LWmjWlXn>rK7%X> z6cRs7AW^?Y07&^X!}a_$x6NUYXT4+dX7 z&*ixI5mPT!;V&2X5`&Bc74?_#eHB2e@joc=B^LGMzFgW>=CNJi%Wl$ZQHrVXE+v1Em@&=B)i6hT<;=H+MUVIJ`+7msrA3g$Q$qb)9skqj4apZUXT6glz*7{ z?%psz<{5i_BsO{ZsZO9&eYU_lm77@heBgZlUSVFce?M>BWp%&>W~mo-rrT`q^Zx+z z;zVnP*P8xs(yjR&Ox`B;Hx5JDWQwZ#zdef;j9!OAi4&eY}y0NTNznsom55#`X*P1A5s% z=zt9J@5`_Ei`hg7J^K=&HU9jJ_b$rYs=^(k z3k=f)JO=(MT0wtX>V3lhI0;aeQBZW`WIiTn-dyab21FhS2{o_}ZWfeqii6m|*!(re zgq1K%8FltZm_@PF12Y&=$GZeYyTDV2VNyuEgqcem>T4WPT#}bK9{9Vn5ye3OG)1XL z0gUmampD0{#oh=~CKRUG1y?cuo;frCX5#eHl+QR1$H9L9uCNCZPfHVGIO1Q=@fA>) zq{Z^0P2T@S&Gs#SzaoDt@E1b0&wlY0H@-RAlqcI@>Zog5T${%JW6ZFha%58{;3%o9gj z?%{}^vjKnb(~1*$+=cvS=>7Zo6*BiT$KO2|0OOY4XA|h3><{|dfchRKX?h;_&*SrW z@p;kBl&|Ogb+_HT?LjwKH*$(y#co6i-#;5{Us6XKUpMAL`}s~%tq%8BGJMlwFg z7CRA?Vt4HBUqQ^$A<$he?~=bbfdm*Xyil_^(ly4p#nI8I*|{>~PgkPXuLW;sfxbJ) z)R%u_c?QCHY9QpiGURkBa`c$>dl?57=v_l)y#l9<>-6mT`7YVT&keL3&s?7-=kJ!n z;z=@=WGt8Smn($XEe1Snku7>*S_^y8p zc+L2?Dtv)?-FYlbyU99kRrsRoG@O@gGThqA(e=71=cCtCE&cSS!Y+|{pNjPL}Gu;2tCtb zPhlP*nInoBn{~Z!xgTRoo?eHaTCRik_u}bz&oi8-KDGPN>K?PDz39B<8{Ykl8vmDw zoawP!T&t9Gnz=svI^|cZxZFX_^8QU!ULS#VzB*P3kgQu;u9rT)V%*{~%3KdTzyFq) z)!ctC8h2fOoZln#i;IO%`5sVxk^k(Kcs=>QE*n3l-H+J#jsF3)SNCdh0@OSJ diff --git a/tests/data/config_MT_MST.mat b/tests/data/config_MT_MST.mat index 17e80aff05fd9b8f2d448d361baaadce76dea141..cc2e35cd812dc8491165e0b382a24de3d0821fa6 100644 GIT binary patch delta 1502 zcmV<41tI!}47UuBJr6k`F)=zdH##&mATlsAGLcaukzfUpbP#{91pokeoXlCxZW}ic zrX|~{lhhG%Xq`);UW%YVfcEBF{39DN3>$_m)IAt*_Gcs!-d%1;t}W%1bKW3%ie7u` zsc3-~@U^!-LLZ=oO74dZ@pn#N0(A+S zs1vQqpM}}hDQjO$`%3z;gi!g(emk&eBP$~mBw`W8uwGpby!6C`8hb=OZT4S^H5J-U5eze2@zmGrmII>5yVZ}S1Pk9Rt4eURE7 zC5)X#?X&1Cx~ac1e_c%eT7Pe9&ij#~A{L+G2(i!!0{K!gu37BS!X4q> zH0$Z%Ge!T5a=$EG5YGK`Ks+bFufdE6gpVe&M+Z~L?VN7yrv5B1krP58z{pzNolA%~ zI|6^YC1hOa*4&EZm|+LASR7>t1!7Z&GlkaOJgAU*hzJ9?x7{F zX^GSE({)Y%^+eIXh{|HfU6ENlG5`vZ2jzc1e2B!69o<9(xCfatE|r*)m{7SM`#1=| z7pHKSigSvXIOossIs{Q>tS^ju#BUkIk zUhc0qrG2psrklP*G?=Ud%O1gZ?gRT{A2KwKh#_w?f<2`kVKdhDm)u^K*)dFA>-{yV)0}C9x}~OGz+-qpwAWkR@A+%JycQl zPAZ$dffMy%x10lq$nQYllyht8oxW2rFtW%{omcfo7JB#>00960V`4sFWME-nVBiB{ z10ZGtVh$(`0<2IzBN7GyCMb&>eOyp|79{B7go>X%0|Gn_1F0CM^t EY-#cLa{vGU delta 1454 zcmV;f1yTC942KMmJr6P=|9}=?986_%p0&zz$@?q zXpul#i4!-D9C-jxu)FPUcc(Yg_6V_-Jl*B#ugb1=Rk^A+5JG=`jLzQcM4?R6{oXC%eLc3t6UWHDu7b-MX zpJsGKD>O_fvGyZB4Z=(gOkqeY=Nbg;3QsJGqk`i#Ozp@buA~EkEBs>10e5dYB-rzS zBq(tRfHI%t8pr3;&>2EPxxgg7Vj{}_sYN`XDxF-b{3(CK;n3^D4R#=-CzSm_~jY%>ae>NWQOYs+yv?AVM);Z>PF?dRr#x(+42j0X}$+l{>j-~VEWSs_&^tTm_oN~9 z91s+eku*f zE3MgPD33&G=*s!b+J{}F?t?D6y}dQUNqJ8-aI1f;Z^;GyG1{qLjplE-ZVohC_k8-& z^?PfA{s@)!&OCNt`ThlFyMRTGFp0BUBR{ZUh(mMYUUc>J@PVLzLS;N;t{<0i(T^O< z$Iqb}YlDbC(Z>Wz{~||+SsW=_Xa!IS^!ccLa04Mt20-?hjB7c11~E{qFlBAh$4Sgg z83KQX*pCBG$;C;1Q@-gwVGS6&-U#j6b4LmNll;4E6ML2JR zU#a0a&GPV5ZrW}1xLL#VUO&f}@{#ommCyg4S8Dp{4ME#T=J&EyPETlBp{g!2uL#KI z;}92vL}bt!iMR-$+E`={pf%Ar~eA~CjVmM5A*ig$Pc$Ym%J&T+tJJq)&woM+zV!S!bNd)0r>s!!DQvB~a;AZgB-uLpl3%9P(!Y)T4g{d1~iR zlOq3>2jO|vsq0^s8uZiFul@Q9Z+|~|8{*_EP5ElwG>Ae>BXS|bo}gKTq!v$RO!WHD z@O_L7aZ(R2H1#0;J-=Gcw<%UiL37n}HSI;7TRvmmO^NcICa@-_c2P8*hq_%Y8sbdlt)Y42-};Uz{>u)m{We#9#>8*^ I3;q@z8BpHuwg3PC diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m index b1d9249..71c8929 100644 --- a/tests/test_checkParameters.m +++ b/tests/test_checkParameters.m @@ -7,34 +7,128 @@ initTestSuite; end +function test_checkParameters_no_debug_fullscreen() + + % set up + cfg.design.localizer = 'MT'; + cfg.debug.do = false; + cfg.debug.transpWin = 0; + cfg.debug.smallWin = 0; + + cfg = checkParameters(cfg); + + % prepare expected results + cfg = removeDirFieldForGithubAction(cfg); + + load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); + + expected.debug.do = false; + expected.debug.transpWin = 0; + expected.debug.smallWin = 0; + expected.skipSyncTests = 0; + + % test + assertEqual(cfg.debug, expected.debug); + assertEqual(cfg.skipSyncTests, expected.skipSyncTests); + +end + +function test_checkParameters_no_debug() + + % set up + cfg.design.localizer = 'MT'; + cfg.debug.do = false; + + cfg = checkParameters(cfg); + + % prepare expected results + cfg = removeDirFieldForGithubAction(cfg); + + load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); + + expected.debug.do = false; + expected.debug.transpWin = 1; + expected.debug.smallWin = 1; + expected.skipSyncTests = 0; + + % test + assertEqual(cfg.debug, expected.debug); + assertEqual(cfg.skipSyncTests, expected.skipSyncTests); + +end + +function test_checkParameters_debug() + + cfg.design.localizer = 'MT'; + cfg.debug.do = true; + + cfg = checkParameters(cfg); + + % prepare expected results + cfg = removeDirFieldForGithubAction(cfg); + + load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); + + expected.debug.do = true; + expected.debug.transpWin = 1; + expected.debug.smallWin = 1; + expected.skipSyncTests = 1; + + % test + assertEqual(cfg.debug, expected.debug); + assertEqual(cfg.skipSyncTests, expected.skipSyncTests); + +end + function test_checkParameters_MT() cfg.design.localizer = 'MT'; + cfg = checkParameters(cfg); - % expected = cfg; - % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); + + % prepare expected results + cfg = removeDirFieldForGithubAction(cfg); + + % uncomment for update default config .mat +% expected = cfg; +% save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); - cfg = rmfield(cfg, 'dir'); - expected = rmfield(expected, 'dir'); %#ok<*NODEF> - fields = fieldnames(expected); - for i = 1:numel(fields) - assertEqual(cfg.(fields{i}), expected.(fields{i})); - end + + % test + checkAllFields(cfg, expected); + assertEqual(cfg, expected); + end function test_checkParameters_MT_MST() cfg.design.localizer = 'MT_MST'; + cfg = checkParameters(cfg); - % expected = cfg; - % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); + + % prepare expected results + cfg = removeDirFieldForGithubAction(cfg); + + % uncomment for update default config .mat +% expected = cfg; +% save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); - cfg = rmfield(cfg, 'dir'); - expected = rmfield(expected, 'dir'); + + % test + checkAllFields(cfg, expected); + assertEqual(cfg, expected); + + +end + +function checkAllFields(cfg, expected) fields = fieldnames(expected); for i = 1:numel(fields) assertEqual(cfg.(fields{i}), expected.(fields{i})); end +end +function cfg = removeDirFieldForGithubAction(cfg) + cfg = rmfield(cfg, 'dir'); end From 7bc76ba8b04f78949db49d2492e73b2a0da6ad24 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 9 Mar 2022 12:55:47 +0100 Subject: [PATCH 21/64] update hidCursor default --- lib/CPP_PTB | 2 +- main.m | 26 +++-- subfun/visualMotionLocalizer.m | 6 +- tests/data/config_MT.mat | Bin 1497 -> 1529 bytes tests/data/config_MT_MST.mat | Bin 1591 -> 1636 bytes tests/test_checkParameters.m | 13 +-- visualMotionLocalizer.m | 205 --------------------------------- 7 files changed, 27 insertions(+), 225 deletions(-) delete mode 100755 visualMotionLocalizer.m diff --git a/lib/CPP_PTB b/lib/CPP_PTB index bf19773..de8c5e2 160000 --- a/lib/CPP_PTB +++ b/lib/CPP_PTB @@ -1 +1 @@ -Subproject commit bf19773c174d0b60279da0804a8eeb1a40521f96 +Subproject commit de8c5e27cb3c1bcd2a9947feacc55eedb59a6a1b diff --git a/main.m b/main.m index 93bfd5a..8b6f99d 100644 --- a/main.m +++ b/main.m @@ -8,18 +8,20 @@ %% Run MT+ localizer cfg.design.localizer = 'MT'; -cfg.debug.do = true; -cfg.pacedByTriggers.do = true; -cfg.eyeTracker.do = false; -cfg.design.nbRepetitions = 15; -cfg.timing.eventDuration = 0.43; % second +cfg.verbose = 2; cfg.debug.do = false; cfg.debug.transpWin = 0; cfg.debug.smallWin = 0; -cfg.verbosity = 2; +cfg.pacedByTriggers.do = true; + +cfg.eyeTracker.do = false; + +cfg.design.nbRepetitions = 15; + +cfg.timing.eventDuration = 0.43; % second initEnv(); @@ -31,12 +33,18 @@ % Run visualMotionLocalizer(cfg); -clear cfg +clear cfg; %% Run MT/MST localizer cfg.design.localizer = 'MT_MST'; -cfg.debug.do = true; + +cfg.verbose = 2; + +cfg.debug.do = false; +cfg.debug.transpWin = 0; +cfg.debug.smallWin = 0; + cfg.eyeTracker.do = false; cfg.design.nbRepetitions = 10; @@ -52,4 +60,4 @@ % run visualMotionLocalizer(cfg); -clear cfg +clear cfg; diff --git a/subfun/visualMotionLocalizer.m b/subfun/visualMotionLocalizer.m index dd3e461..b169ffe 100755 --- a/subfun/visualMotionLocalizer.m +++ b/subfun/visualMotionLocalizer.m @@ -29,13 +29,13 @@ function visualMotionLocalizer(cfg) % Safety loop: close the screen if code crashes try - [cfg] = initPTB(cfg); + cfg = initPTB(cfg); cfg = postInitializationSetup(cfg); - [el] = eyeTracker('Calibration', cfg); + cfg.el = eyeTracker('Calibration', cfg); - [cfg] = expDesign(cfg); + cfg = expDesign(cfg); % Prepare for the output logfiles with all logFile.extraColumns = cfg.extraColumns; diff --git a/tests/data/config_MT.mat b/tests/data/config_MT.mat index c53f206d3748a83df6222437cdd8f0a0a358de97..3226ce6681f86608a1ffed81dfe76ae53c2a0cd2 100644 GIT binary patch delta 1436 zcmV;N1!MZz3;7F>KnyZEH8eUgI3O}GGBS}-BavVQk#rD$aRmSXc$~~xy>A;g6sP2m z)=A)~nVhB2R0IVAwCLh3jx7f<3>$_m)Ex{M_wg(fJ{_+l&z3Uv-)R4Wj2*Ic>(~M< zV4zdC{s|pB6mUr%siQ7e>qxb62vB$L?tbs_>J+6F)%)l;;#Q90hrd2`XENV`h;kA_<`u9YdH8rf7x-sYMfR!^Jo_ z4Yo*<4^zb##?YrhbOD;_86E{3lL?1&9K%*lnGt#cZe1KR_cM#{Vh!I#i*H9zDM_J< zTdv?tGdMHeS-9#v+WJo7Mvn7e(zLwBq+b3?ySe-yTW<2ry2&taT+ccW3sdu0c=xy)UwJnQ_tF8k zBKn$HoIg%Cs#l+J+<4CW=B5}way<9@5S6|~ZZqzqXkpVtu`~BHGaiYK6pWl+}Ygb+T%ggq^pZiwjc@ulHVtwDybZiW*1D|^pK9W}F zs0V{DpO<`m?1;&in&6izcu9lw1P$fa;X~y>n&CgF;3X~c$$fdWo2+A}f|uQYgx4Y! zQ|`-`kIBPrK6jlbtvlN3RZWMeYWNh@H>q`kQ#h6x?19X@c^N4nli8X!>S30N@EnFx zOU6@F{rp_c>;DyhR@ZX@`RljJ+G_Ak?P1Zb=d#291?g?cVl((bn^W?fLRoUtD*FpRxT$lQ`O5&yKjGp16T0ZtRH* zJ#n!oF7?E{^2C8B&iK={mS3IbDUx}ODxmJ_%7-TR!{TdNsp8BxPFMS~g#7K{ufNFl z_p|rGzkctyKPGOF@`fbEoKWErc_5P>O&=TgDQp}`@-k5LS?5zv++&S@yGFO$Dcir^ zg&loYb?+APtD73XCa*#Cb&iYBuy!0S_1hM8i$(8c_ z^SB?p;uf>s8@H^F`Nm!!Nt<~7R0m!vubbnX%Ho&39=NRgE1K8T{b!B4E`PYhEDw_I zq&)XN|9>#cPb^H~7AF6Hw`@4>gNfT@9lFRz&WKDLiZTx4;{@i)A7<@SUA=INdNk4RN1iyN^RGS6{|nJ~Hg{0jc8+Wc(zpjnpi6Bkv+o&mA>(asz4aOYBDx!U qGEcnmg=)XeCASXu4*&oF|NmoUU|`??Vn!qk0!%;_hz$T=T>c+Wb=>>_ delta 1404 zcmV-?1%vwe3)u^hKnyWDH8(mmH6SuDGBS}-BavVQk#rD$Q3U`1c%02yPjA~c6sPSZ zTiPJ?dTKA5PeU=Fz=mCNtD87QgCIeW7|RX;GW~gR2+N{MQi4&gF?T0(7o{TuP)B|v#fLDP|!hM1td`8Z@2L;;BiwQvZ2I+(!>4`K@wZqvm$ zIQ6zjl#XI07beiBUN8hL^bC(Zj>%NQ5GFqHXlU?=;u(2~7eKf<=~Fxy0A+{;6u{EY zhB!Hz#6cezmkL>WCRF72xkm@UZOn$Yd@gu69`xXU0tcY*c;*N+!!zTZ z$1A=^Q=duRxaRvWYb=i;Dc8T+tgip3Mm_yz-sJtg!yRRFQqEsB-@~l4j_5lv<1`JV zX{&F4*cW!z17WQ=QRXh?e~oVbo}VK7duI5Hr#;|eWq0^FbPl(B9kYNs0VRx`#GRA) zB%W_CrrGk%{C!*Vy&q^SkB5)|$8tb@Jc9XlR2+wGe@~kA#&KWcJ<)yPV+NF@aftj# zoM%t@QEHazAom;MbfT|Pn0lVebIfPg^}O|e(3*LV*6s7IUG-fn-pd-iRnZ@r$@%lN zTRggqF zw8q&MXs=(*KI}NyROszn$?MM1cOTjMGOVm2%2O06=Zz(&QIKQCY_7}aH|FSFL9==# zW?bkD-1*s8a*N|@XffVZP5XPS@z3(T6Ube#-2!qB6ygAiH$sRR=970B5k7+~2o+jF zNkXWcpIsb95DGheL4^?`CJet!xBeP`hj3IJTroYKHkbK(;K(cU7j<|WHF&G~`uE?- z_Q$hD@s9>Cs`Y$Z;LC2(Yf*}+@Z~Ch$JE`n zoV%`*Hfs9mb&Y*gbbJc+O=%tB7>;EHdmt-so@WZkRJNv#dzd96J%^FBlF1Azf4@5G z_5aF0i}Tq+?)I&!wi13-f0(tah5WE9uiL6;KWiFGeWDZ=OJY|QUiO|31(t{;5jM$q zdM=-G^vcjSeRyx5WV+K~s2 zJQEimHQe@Fo+4SFsEyEFy@R3QzMnl!3%fCkjkB(wSVr!C?YCcL`{&vF5GQ}A`F%|M zm-ZFRXQ4`CqE``>obd K^88=^4*I->@6uEN diff --git a/tests/data/config_MT_MST.mat b/tests/data/config_MT_MST.mat index cc2e35cd812dc8491165e0b382a24de3d0821fa6..be77a422a48239a251349bbbad5ffe9c404019d4 100644 GIT binary patch delta 1544 zcmV+j2KV{54CD-uKnyZEH8eUgI3O}GGBS}-BavVQk#rD$+ywvtc$~~x&2Aev5T+&D zsq^CqIkd^8P%lMLAV7QbE&h>%7={hQ7U~`h82dAl2(Ok~l50yj_1rgTo}$P0)>DxJ zE#PZ!eS|zf3zgg@wcPbq+NGK}1gPDi_|1?*a%MQYju3kL8A7Y#`H`p%l$I4mFBw(R zFp9wA;IE*6Wz@$Nz9tj9FXdm3TpQ9P>hXzf!2^Ztw z)Y&0HJPZ@QForI5ybDlFdwAqr%K@;sCq!odbBFeUn>4$BF!^(V!(qPzm)L`Z9_1#;@lgDo z(U(A7!lvp)>+)x*+PbCf%Sm5JKa%{%kzjU(eLg^=Bf?C+8z|$uT*7zN;M-EPhp87p zivQBUug)1)L%iKVcDSa(jZi&3tSDMOeUi=Fl)u)PFJI$+sksizC_7IF$9u`%lYHLR zoQFPte{E6sLdI$A$t|C(WmoLC4v1ZgqvRM!{@-ss$udAfLde#9hPJEjWpnbgC zY3qa4_9$WOENq{JXW>o#75VF8^4I$NuI9WSDq22|Ap(x&fVy~CVgD7!q2)>3(?-2< z+*9;{sIIU*eM;icM{XeA(_U^6>m%FG?1y-N9jjIfQwwx8z&wAx=beXUZXV6|kDJ)a znwL5Lv>C_5a^924#LE8ORrIGQvpd2PQzvB6DGm`EIzb>`O2$>i z9xdGx?oG3v9zIs|uPF1=!Uf^XUkAi<0{jZh2toL0B71Z&h0M1p^3`2p~(&0_6^+gtBNIm>y=r5aZrWaEWvi~NU zZI9QD{w+moeVvQIWWcNOc~IcLHFZPdW6srJ`D$nxiN8@XCP_Huu_A=lPV)$!La8?)_%*9~--+@1a%jD+RoyLHf&z^2_k9agtq5fI~QynSmpj(crnrD$N+^l8c7WI7gMw zug-aWSMmIR`AeJqo!o*;@Kx=9VOp*ivcvxeuFk&OtQqg$SG1G|%o9gxKe+&#IXDU| z645tolhO2D_Oi8myC*waN4tyV18i~aIey0U8}sreMSZr!8@0ssEpcN@oNI~mEpeeG z?v*7DEOFYOK3=lRdp$!kYmg+S_f;lIk%w;Dn-;QSi;c6ceOW>F_VAB?-(~sx`G??N zf2_GaI&P5ih9tzCP~j1|BQHIQKGp71*f8u zTHl*9^rQQj`pMH}xrQ4*S$d`Fo#?y~#Ckhh17x2K8C5BYn{ zJU`LQ;hNL$SDQ80LC0+}ub2b2Z@Rw$nl34;I= uki`YnXF-BKPN?{-nIN#!o)UXW)yGPKdyT>1GFk40*-NTE5E}sF%_|q^@EYv^ delta 1499 zcmV<11tj|947UuBKnyWDH8(mmH6SuDGBS}-BavVQk#rD$uLS@Ac$~~x&2Aev5T+&D zsgu+Za%i1Pp#1mg z7Vx#VK0+U$g-Y&{TJCylX(^-*0cv+Belz5doEgrpB7|OkiO{lmej;iEWo1dx3r3YR z3}f&(_)BPi5w%qNOY!5xKzTwz!I6{rn4rA4*k=ZbJQ5IU&_1|Hzd$qGj|`e{6E4QV zsk2RjB#ctNFoG_1ybDlFdwA$@OeP#IVB`{q`kD?YF7S&T5B#lBm*RdOC_~Jn0ET>a zf#Z`=t0`W?7`#2%#durMKxL-BV`UjlUro2V15 z%AbYV)+uXWO#4duvE)CB1+y#c^8p$j5oYpTM>*fc3ckw*-ZGDj19wm&O zMeVcbEV`+`GJjo6{#t);YR>zSqUG}#V>~sEflH_Fs7%TAsu`ZPXjb14SQ*>Iz%a zrzDAd*WTCKC=DXeu&qRYNar-Kvx5Q%!}uH+IeUe=F$BBabsI~;}rLz25v>v zHLaXK&o|0Xn{kXS=RF>et?ci8MSp>EyCWv$ToBIvb3i;Nz^}oK2!xL&vPTC~$nBhN?WX=LFOd^MA;8F5-JMH_I6DG= zx+P>>=+@kd}*7`aR zpvRHDzdq=mADnb&+y4y%-xLzwH+uir%B7BvogkAtsHra-dD-r;i!auY9qyqeu4#$W z@zZrp|Mf)Czlh3W$X$_HJTd?Zkq6~}KYWP9ksaMc1h@y8GcJ{wl9*7r9{V^5z!#@* zmx^%FtFoJQaO*X2E2{ndJ6ZmCZX;Lg$6oHQ zH{{y-mpXp-MdNlmVYbg=S67VwEk*mxYWN|I1(6?C}UFKm(F0Y+nYx_^WDd7aqTJo z!nFU>@)l)%w!|B?#Puz4BTJlXiSsRSktOc6B@Qfc+Appx*yWv`A$e<06T|x|lcUH( zH|tGHS*iKPS=UZ1A$z;_`){)R{rqF_lRwm4AMO98ypTkg6Dm9#cjV=NMbW3)4GJ4a zf+P?4Z1j9?iF=}O*XVXTW%|jxu%jOWSEY{yWS0lleoa0d?^S}06w*BT=%+RJosQ4G z7S&Iv@trAjhKKGX*~CjZDlO0cKK7$k{Gs)|af^O*A5%Y)p5&iY0F~a)<~XM^PiN`_ z=if0>npb?sm^SXJdqBv4+acraNn-J1{vI;TPc#d-=H&a)M$L85ahuF@W%r66kr#k0 z9mDu2fVu7g)7I$$D$ZZh+a#eFX!{VZD)lkT{(fwU(|f+|cc9M|{Z`bytvysx_D(9B zy@3<;VYi$Ehsf_h;FNP~>7Bk)Ffg*nP@PxxM;3bc7XSeN|6^i4U}RunU|`?_Vgn#% z17Z#+4FarCJ|hwa0VXJm9DQ6+eHJ9>@L27}A?^z<)?4FGcbA8cNC B_eKB! diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m index 71c8929..5e04c80 100644 --- a/tests/test_checkParameters.m +++ b/tests/test_checkParameters.m @@ -73,6 +73,7 @@ function test_checkParameters_debug() expected.debug.transpWin = 1; expected.debug.smallWin = 1; expected.skipSyncTests = 1; + expected.hideCursor = 1; % test assertEqual(cfg.debug, expected.debug); @@ -90,15 +91,14 @@ function test_checkParameters_MT() cfg = removeDirFieldForGithubAction(cfg); % uncomment for update default config .mat -% expected = cfg; -% save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); + % expected = cfg; + % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); % test checkAllFields(cfg, expected); assertEqual(cfg, expected); - end function test_checkParameters_MT_MST() @@ -111,15 +111,14 @@ function test_checkParameters_MT_MST() cfg = removeDirFieldForGithubAction(cfg); % uncomment for update default config .mat -% expected = cfg; -% save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); + % expected = cfg; + % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); % test checkAllFields(cfg, expected); assertEqual(cfg, expected); - end function checkAllFields(cfg, expected) @@ -130,5 +129,5 @@ function checkAllFields(cfg, expected) end function cfg = removeDirFieldForGithubAction(cfg) - cfg = rmfield(cfg, 'dir'); + cfg = rmfield(cfg, 'dir'); end diff --git a/visualMotionLocalizer.m b/visualMotionLocalizer.m deleted file mode 100755 index 3606313..0000000 --- a/visualMotionLocalizer.m +++ /dev/null @@ -1,205 +0,0 @@ -function visualMotionLocalizer(cfg) - % - % (C) Copyright 2018 Mohamed Rezk - % (C) Copyright 2020 CPP visual motion localizer developers - - if nargin < 1 - cfg.design.localizer = 'MT'; - end - - getOnlyPress = 1; - - % Clear all the previous stuff - clc; - if ~ismac - close all; - clear Screen; - end - - % make sure we got access to all the required functions and inputs - initEnv(); - - % set and load all the parameters to run the experiment - cfg = checkParameters(cfg); - cfg = userInputs(cfg); - cfg = createFilename(cfg); - - %% Experiment - - % Safety loop: close the screen if code crashes - try - - cfg = initPTB(cfg); - - cfg = postInitializationSetup(cfg); - - cfg.el = eyeTracker('Calibration', cfg); - - cfg = expDesign(cfg); - - % Prepare for the output logfiles with all - logFile.extraColumns = cfg.extraColumns; - logFile = saveEventsFile('init', cfg, logFile); - logFile = saveEventsFile('open', cfg, logFile); - - % prepare textures - cfg = apertureTexture('init', cfg); - cfg = dotTexture('init', cfg); - - disp(cfg); - - % Show experiment instruction - standByScreen(cfg); - - % prepare the KbQueue to collect responses - getResponse('init', cfg.keyboard.responseBox, cfg); - - waitForTrigger(cfg); - - % Start - eyeTracker('StartRecording', cfg); - - cfg = getExperimentStart(cfg); - - getResponse('start', cfg.keyboard.responseBox); - - waitFor(cfg, cfg.timing.onsetDelay); - - for iBlock = 1:cfg.design.nbBlocks - - fprintf('\n - Running Block %.0f \n', iBlock); - - eyeTracker('Message', cfg, ['start_block-', num2str(iBlock)]); - - dots = []; - previousEvent.target = 0; - - for iEvent = 1:cfg.design.nbEventsPerBlock - - checkAbort(cfg, cfg.keyboard.keyboard); - - [thisEvent, thisFixation, cfg] = preTrialSetup(cfg, iBlock, iEvent); - - % we wait for a trigger every 2 events - if cfg.pacedByTriggers.do && mod(iEvent, 2) == 1 - waitForTrigger(cfg, ... - cfg.keyboard.responseBox, ... - cfg.pacedByTriggers.quietMode, ... - cfg.pacedByTriggers.nbTriggers); - end - - eyeTracker('Message', cfg, ... - ['start_trial-', num2str(iEvent), '_', thisEvent.trial_type]); - - % we only reuse the dots position for targets that consists of - % presenting static dots with the same position as those of the - % previous trial - % - % TODO does not take into account what to do if 3 or more targets in a row - if strcmp(cfg.target.type, 'static_repeat') && ... - strcmp(thisEvent.trial_type, 'static') && ... - thisEvent.target == 1 && ... - thisEvent.target == previousEvent.target - else - dots = []; - end - - % play the dots and collect onset and duraton of the event - [onset, duration, dots] = doDotMo(cfg, thisEvent, thisFixation, dots, iEvent); - - thisEvent = preSaveSetup(thisEvent, ... - thisFixation, ... - iBlock, iEvent, ... - duration, onset, ... - cfg, ... - logFile); - - saveEventsFile('save', cfg, thisEvent); - - % collect the responses and appends to the event structure for - % saving in the tsv file - responseEvents = getResponse('check', cfg.keyboard.responseBox, cfg, ... - getOnlyPress); - - triggerString = ['trigger_' cfg.design.blockNames{iBlock}]; - saveResponsesAndTriggers(responseEvents, cfg, logFile, triggerString); - - eyeTracker('Message', cfg, ... - ['end_trial-', num2str(iEvent), '_', thisEvent.trial_type]); - - previousEvent = thisEvent; - - waitFor(cfg, cfg.timing.ISI); - - end - - % "prepare" cross for the baseline block - % if MT / MST this allows us to set the cross at the position of the next block - if iBlock < cfg.design.nbBlocks - nextBlock = iBlock + 1; - else - nextBlock = cfg.design.nbBlocks; - end - - [~, thisFixation] = preTrialSetup(cfg, nextBlock, 1); - drawFixation(thisFixation); - Screen('Flip', cfg.screen.win); - - eyeTracker('Message', cfg, ['end_block-', num2str(iBlock)]); - - waitFor(cfg, cfg.timing.IBI); - - % IBI trigger paced - if cfg.pacedByTriggers.do - waitForTrigger(cfg, ... - cfg.keyboard.responseBox, ... - cfg.pacedByTriggers.quietMode, ... - cfg.timing.triggerIBI); - end - - if isfield(cfg.design, 'localizer') && ... - strcmpi(cfg.design.localizer, 'MT_MST') && ... - iBlock == cfg.design.nbBlocks / 2 - - waitFor(cfg, cfg.timing.changeFixationPosition); - - end - - % trigger monitoring - triggerEvents = getResponse('check', cfg.keyboard.responseBox, cfg, ... - getOnlyPress); - - triggerString = 'trigger_baseline'; - saveResponsesAndTriggers(triggerEvents, cfg, logFile, triggerString); - - end - - % End of the run for the BOLD to go down - waitFor(cfg, cfg.timing.endDelay); - - cfg = getExperimentEnd(cfg); - - eyeTracker('StopRecordings', cfg); - - % Close the logfiles - saveEventsFile('close', cfg, logFile); - - getResponse('stop', cfg.keyboard.responseBox); - getResponse('release', cfg.keyboard.responseBox); - - eyeTracker('Shutdown', cfg); - - createJson(cfg, cfg); - - farewellScreen(cfg); - - cleanUp(); - - catch - - cleanUp(); - psychrethrow(psychlasterror); - - end - -end From 93142bee9e53a81ab9c75be9338797490b590d34 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 9 Mar 2022 13:41:55 +0100 Subject: [PATCH 22/64] move doc to relevant help section --- README.md | 178 +++++-------------------- doc/configurations.md | 211 ++++++++++++++++-------------- subfun/defaults/checkParameters.m | 2 +- subfun/design/expDesign.m | 81 ++++++------ subfun/doDotMo.m | 27 ++-- tests/test_checkParameters.m | 20 +++ 6 files changed, 228 insertions(+), 291 deletions(-) diff --git a/README.md b/README.md index 4a2ead7..fbc4ce4 100644 --- a/README.md +++ b/README.md @@ -6,22 +6,19 @@ - [fMRI localizers for visual motion](#fmri-localizers-for-visual-motion) - [Requirements](#requirements) - [Installation](#installation) - - [Structure and function details](#structure-and-function-details) - - [visualMotionLocalizer](#visualmotionlocalizer) - - [setParameters](#setparameters) - - [Let the scanner pace the experiment](#let-the-scanner-pace-the-experiment) - - [subfun/doDotMo](#subfundodotmo) - - [Input](#input) - - [Output](#output) - - [subfun/design/expDesign](#subfundesignexpdesign) - - [Events](#events) - - [Pseudorandomization rules:](#pseudorandomization-rules) - - [Input:](#input-1) - - [Output:](#output-1) + - [Set up and running](#set-up-and-running) - [Contributors ✨](#contributors-) # fMRI localizers for visual motion +Running this script will show blocks of motion dots and static dots. Motion +blocks will show: + +- dots moving in one of four directions (up-, down-, left-, and right-ward) (MT+ + localizer) +- or dots moving inward and outward in the peripheral of the screen (MT/MST + localizer). + ## Requirements Make sure that the following toolboxes are installed and added to the matlab / @@ -39,160 +36,45 @@ For instructions see the following links: ## Installation -The CPP_BIDS and CPP_PTB dependencies are already set up as submodule to this +The CPP_BIDS and CPP_PTB dependencies are already set up as submodules to this repository. You can install it all with git by doing. ```bash git clone --recurse-submodules https://github.com/cpp-lln-lab/localizer_visual_motion.git ``` -## Structure and function details - -### visualMotionLocalizer - -Running this script will show blocks of motion dots and static dots. Motion -blocks will show dots moving in one of four directions (up-, down-, left-, and -right-ward) (MT+ localizer) or dots moving inward and outward in the peripheral -of the screen (MT/MST localizer). - -Run in `Debug mode` (see `setParameters.m`) it does not care about subjID, run -n., Eye Tracker (soon, at the moment it needs to be set off manually), etc.. - -Any details of the experiment can be changed in `setParameters.m` (e.g., -experiment mode, motion stimuli details, exp. design, etc.) +## Set up and running -### setParameters +In the `main.m` script, you are meant -`setParameters.m` is the core engine of the experiment. It contains the -following tweakable sections: +- to set your configuration (`cfg`) +- call `initEnv()` to add the relevant folders to the MATLAB path +- call `cfg = checkParameters(cfg)` to set up any default configuration you did + not set. +- call `visualMotionLocalizer(cfg)` to run the localizer. -- Debug mode setting -- MRI settings -- Engine parameters: - - Monitor parameters - - Monitor parameters for PsychToolBox -- Keyboards -- Experiment Design -- Visual Stimulation -- Task(s) - - Instructions - - Task #1 parameters - -#### Let the scanner pace the experiment - -Set `cfg.pacedByTriggers.do` to `true` and you can then set all the details in -this `if` block +The minimalist script would thus look like: ```matlab -% Time is here in terms of `repetition time (TR)` (i.e. MRI volumes) -if cfg.pacedByTriggers.do +clc; +clear; - cfg.pacedByTriggers.quietMode = true; - cfg.pacedByTriggers.nbTriggers = 1; +%% Run MT+ localizer - cfg.timing.eventDuration = cfg.mri.repetitionTime / 2 - 0.04; % second +cfg.design.localizer = 'MT'; +initEnv(); - % Time between blocs in secs - cfg.timing.IBI = 0; - % Time between events in secs - cfg.timing.ISI = 0; - % Number of seconds before the motion stimuli are presented - cfg.timing.onsetDelay = 0; - % Number of seconds after the end all the stimuli before ending the run - cfg.timing.endDelay = 2; +cfg = checkParameters(cfg); -end +% Run +visualMotionLocalizer(cfg); ``` -### subfun/doDotMo - -Wrapper function that present the dot stimulation (static or motion) per event. - -#### Input - -- `cfg`: PTB/machine and experiment configurations returned by `setParameters` - and `initPTB` -- `logFile`: structure that stores the experiment logfile to be saved -- `thisEvent`: structure that stores information about the event to present - regarding the dots (static or motion, direction, etc.) -- `thisFixation`: structure that stores information about the fixation cross - task to present -- `dots`: [...] -- `iEvent`: index of the event of the block at the moment of the presentation - -#### Output - -- Event `onset` -- Event `duration` -- `dots`: [...] - -> NB: The dots are drawn on a square that contains the round aperture, then any -> dots outside of the aperture is turned into a NaN so effectively the actual -> number of dots on the screen at any given time is not the one that you input -> but a smaller number (nDots / Area of aperture) on average. - -### subfun/design/expDesign - -This function and its companions creates the sequence of blocks (static/motion) -and the events (the single directions) for MT+ and MT/MST localizers. The -conditions are consecutive static and motion blocks (fixed in this order gives -better results than randomised). - -It can be run as a stand alone without inputs and displays a visual example of -the possible design. See `getMockConfig` to set up the mock configuration. - -It computes the directions to display and the task(s), at the moment: - -1. detection of change in the color of the fixation target -2. detection of different speed of the moving dots [ W I P - if selected as a - task it will give the same null output as if not selected ie no difference in - speed] - -#### Events - -The `nbEventsPerBlock` should be a multiple of the number of motion directions -requested in `motionDirections` (which should be more than 1) e.g.: - -- MT localizer: - `cfg.design.motionDirections = [ 0 90 180 270 ]; % right down left up` -- MT_MST localizer: `cfg.design.motionDirections = [666 -666]; % outward inward` - -#### Pseudorandomization rules: - -- Directions: - -1. Directions are all presented in random orders in - `numEventsPerBlock/nDirections` consecutive chunks. This evenly distribute - the directions across the block. -2. No same consecutive direction - -- Color change detection of the fixation cross: - -1. If there are 2 targets per block we make sure that they are at least 2 events - apart. -2. Targets cannot be on the first or last event of a block. -3. No less than 1 target per event position in the whole run - -#### Input: - -- `cfg`: parameters returned by setParameters -- `displayFigs`: a boolean to decide whether to show the basic design matrix of - the design - -#### Output: +Type `help checkParameters` and see the [README in docs](./docs/README.md) to +get more information about the configuration options. -- `cfg.design.blockNames`: cell array (nbBlocks, 1) with the condition name for - each block -- `cfg.design.nbBlocks`: integer for th etotal number of blocks in the run -- `cfg.design.directions`: array (nbBlocks, nbEventsPerBlock) with the direction - to present in a given event of a block. - - 0 90 180 270 indicate the angle for translational motion direction - - 666 -666 indicate in/out-ward direction in radial motion - - -1 indicates static -- `cfg.design.speeds`: array (nbBlocks, nbEventsPerBlock) indicate the dots - speed in each event, the target is represented by a higher/lower value -- `cfg.design.fixationTargets`: array (nbBlocks, numEventsPerBlock) showing for - each event if it should be accompanied by a target +Run in debug mode (set `cfg.debug.do = true`) it does not care about subjID, run +n., Eye Tracker... ## Contributors ✨ diff --git a/doc/configurations.md b/doc/configurations.md index 3685a97..cc91ad1 100644 --- a/doc/configurations.md +++ b/doc/configurations.md @@ -1,110 +1,129 @@ # Configurations -## MT +- [Configurations](#configurations) + - [For MT localiser](#for-mt-localiser) + - [Let the scanner pace the experiment](#let-the-scanner-pace-the-experiment) -```matlab -cfg.aperture.type = 'none' -cfg.aperture.width -cfg.aperture.xPos = 0.000000 - -cfg.audio.do = 0 - -cfg.bids.MRI.Instructions = '1-Detect the RED fixation cross\n \n\n' -cfg.bids.MRI.TaskDescription = '' - -cfg.color.white = 255.000000, 255.000000, 255.000000 -cfg.color.black = 0.000000, 0.000000, 0.000000 -cfg.color.grey = 127.500000, 127.500000, 127.500000 -cfg.color.red = 255.000000, 0.000000, 0.000000 -cfg.color.blue = 0.000000, 255.000000, 0.000000 -cfg.color.green = 0.000000, 0.000000, 255.000000 -cfg.color.background = 0.000000, 0.000000, 0.000000 - -cfg.debug.do = 1 -cfg.debug.smallWin = 0 -cfg.debug.transpWin = 0 - -cfg.design.localizer = 'MT' -cfg.design.motionDirections = 0.000000, 0.000000, 180.000000, 180.000000 -cfg.design.motionType = 'translation' -cfg.design.names{1} = 'static' -cfg.design.names{2} = 'motion' -cfg.design.nbEventsPerBlock = 12.000000 -cfg.design.nbRepetitions = 12.000000 - -cfg.dir.output = '/home/remi/github/CPP_localizer_visual_motion' - -cfg.dot.speed = 15.000000 -cfg.dot.coherence = 1.000000 -cfg.dot.density = 1.000000 -cfg.dot.lifeTime = 0.400000 -cfg.dot.proportionKilledPerFrame = 0.000000 -cfg.dot.size = 0.200000 -cfg.dot.staticReSeed = 1 -cfg.dot.color = 255.000000, 255.000000, 255.000000 +## For MT localiser -cfg.extraColumns{1} = 'direction' -cfg.extraColumns{2} = 'speedDegVA' -cfg.extraColumns{3} = 'target' -cfg.extraColumns{4} = 'event' -cfg.extraColumns{5} = 'block' -cfg.extraColumns{6} = 'keyName' -cfg.extraColumns{7} = 'fixationPosition' -cfg.extraColumns{8} = 'aperturePosition' +These are all the options that can be tweaked. -cfg.eyeTracker.do = 0 - -cfg.fixation.type = 'cross' -cfg.fixation.xDisplacement = 0.000000 -cfg.fixation.yDisplacement = 0.000000 -cfg.fixation.color = 255.000000, 255.000000, 255.000000 -cfg.fixation.width = 0.250000 -cfg.fixation.lineWidthPix = 3.000000 -cfg.fixation.colorTarget = 255.000000, 0.000000, 0.000000 - -cfg.keyboard.keyboard -cfg.keyboard.responseBox -cfg.keyboard.responseKey{1} = 'r' -cfg.keyboard.responseKey{2} = 'g' -cfg.keyboard.responseKey{3} = 'y' -cfg.keyboard.responseKey{4} = 'b' -cfg.keyboard.responseKey{5} = 'd' -cfg.keyboard.responseKey{6} = 'n' -cfg.keyboard.responseKey{7} = 'z' -cfg.keyboard.responseKey{8} = 'e' -cfg.keyboard.responseKey{9} = 't' -cfg.keyboard.escapeKey = 'ESCAPE' - -cfg.mri.triggerKey = 't' -cfg.mri.triggerNb = 5.000000 -cfg.mri.repetitionTime = 1.800000 - -cfg.pacedByTriggers.do = 0 - -cfg.screen.monitorWidth = 25.000000 -cfg.screen.monitorDistance = 95.000000 +```matlab +cfg.aperture.type = 'none'; +cfg.aperture.width = []; +cfg.aperture.xPos = 0.000000; +cfg.audio.do = 0; +cfg.bids.MRI.Instructions = '1-Detect the RED fixation cross'; +cfg.bids.MRI.TaskDescription = ''; +cfg.bids.mri.RepetitionTime = []; +cfg.color.background = 0.000000, 0.000000, 0.000000; +cfg.color.black = 0.000000, 0.000000, 0.000000; +cfg.color.blue = 0.000000, 255.000000, 0.000000; +cfg.color.green = 0.000000, 0.000000, 255.000000; +cfg.color.grey = 127.500000, 127.500000, 127.500000; +cfg.color.red = 255.000000, 0.000000, 0.000000; +cfg.color.white = 255.000000, 255.000000, 255.000000; +cfg.debug.do = 1; +cfg.debug.smallWin = 1; +cfg.debug.transpWin = 1; +cfg.design.localizer = 'MT'; +cfg.design.motionDirections = 0.000000, 0.000000, 180.000000, 180.000000; +cfg.design.motionType = 'translation'; +cfg.design.names{1} = 'static'; +cfg.design.names{2} = 'motion'; +cfg.design.nbEventsPerBlock = 12.000000; +cfg.design.nbRepetitions = 12.000000; +cfg.dot.coherence = 1.000000; +cfg.dot.color = 255.000000, 255.000000, 255.000000; +cfg.dot.density = 1.000000; +cfg.dot.lifeTime = 0.400000; +cfg.dot.proportionKilledPerFrame = 0.000000; +cfg.dot.size = 0.200000; +cfg.dot.speed = 15.000000; +cfg.dot.staticReSeed = 1; +cfg.extraColumns{1} = 'direction'; +cfg.extraColumns{2} = 'speedDegVA'; +cfg.extraColumns{3} = 'target'; +cfg.extraColumns{4} = 'event'; +cfg.extraColumns{5} = 'block'; +cfg.extraColumns{6} = 'keyName'; +cfg.extraColumns{7} = 'fixationPosition'; +cfg.extraColumns{8} = 'aperturePosition'; +cfg.eyeTracker.do = 0; +cfg.fixation.color = 255.000000, 255.000000, 255.000000; +cfg.fixation.colorTarget = 255.000000, 0.000000, 0.000000; +cfg.fixation.lineWidthPix = 3.000000; +cfg.fixation.type = 'cross'; +cfg.fixation.width = 0.250000; +cfg.fixation.xDisplacement = 0.000000; +cfg.fixation.yDisplacement = 0.000000; +cfg.hideCursor = 0; +cfg.keyboard.escapeKey = 'ESCAPE'; +cfg.keyboard.keyboard = []; +cfg.keyboard.responseBox = []; +cfg.keyboard.responseKey{1} = 'r'; +cfg.keyboard.responseKey{2} = 'g'; +cfg.keyboard.responseKey{3} = 'y'; +cfg.keyboard.responseKey{4} = 'b'; +cfg.keyboard.responseKey{5} = 'd'; +cfg.keyboard.responseKey{6} = 'n'; +cfg.keyboard.responseKey{7} = 'z'; +cfg.keyboard.responseKey{8} = 'e'; +cfg.keyboard.responseKey{9} = 't'; +cfg.mri.repetitionTime = 1.800000; +cfg.mri.triggerKey = 't'; +cfg.mri.triggerNb = 5.000000; +cfg.pacedByTriggers.do = 0; +cfg.screen.monitorDistance = 95.000000; +cfg.screen.monitorWidth = 25.000000; +cfg.screen.resolution{1} = []; +cfg.screen.resolution{2} = []; +cfg.screen.resolution{3} = []; +cfg.skipSyncTests = 1.000000; +cfg.suffix.acquisition = ''; +cfg.target.duration = 0.100000; +cfg.target.maxNbPerBlock = 1.000000; +cfg.target.type = 'fixation_cross'; +cfg.task.instruction = '1-Detect the RED fixation cross'; +cfg.task.name = 'visual localizer'; +cfg.task.taskDescription = ''; +cfg.testingDevice = 'mri'; +cfg.text.color = 255.000000, 255.000000, 255.000000; +cfg.text.font = 'Courier New'; +cfg.text.size = 18.000000; +cfg.text.style = 1.000000; +cfg.timing.IBI = 4.000000; +cfg.timing.ISI = 0.100000; +cfg.timing.endDelay = 5.000000; +cfg.timing.eventDuration = 0.300000; +cfg.timing.onsetDelay = 5.000000; +cfg.verbose = 1.000000; +``` -cfg.skipSyncTests = 0.000000 +## Let the scanner pace the experiment -cfg.suffix.acquisition = '' + -cfg.target.duration = 0.100000 -cfg.target.maxNbPerBlock = 1.000000 -cfg.target.type = 'fixation_cross' +Set `cfg.pacedByTriggers.do` to `true` and you can then set all the details in +this `if` block -cfg.task.name = 'visual localizer' -cfg.task.instruction = '1-Detect the RED fixation cross\n \n\n' -cfg.task.taskDescription = '' +```matlab +% Time is here in terms of `repetition time (TR)` (i.e. MRI volumes) +if cfg.pacedByTriggers.do -cfg.testingDevice = 'mri' + cfg.pacedByTriggers.quietMode = true; + cfg.pacedByTriggers.nbTriggers = 1; -cfg.text.color = 255.000000, 255.000000, 255.000000 + cfg.timing.eventDuration = cfg.mri.repetitionTime / 2 - 0.04; % second -cfg.timing.IBI = 0.000000 -cfg.timing.ISI = 0.000000 -cfg.timing.endDelay = 3.600000 -cfg.timing.eventDuration = 0.300000 -cfg.timing.onsetDelay = 0.000000 + % Time between blocs in secs + cfg.timing.IBI = 0; + % Time between events in secs + cfg.timing.ISI = 0; + % Number of seconds before the motion stimuli are presented + cfg.timing.onsetDelay = 0; + % Number of seconds after the end all the stimuli before ending the run + cfg.timing.endDelay = 2; -cfg.verbose = 1.000000 +end ``` diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 2db3764..0c89086 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -29,7 +29,7 @@ root_dir = bids.internal.file_utils(root_dir, 'cpath'); end - fieldsToSet.dir.output = fullfile(root_dir, 'output'); + fieldsToSet.dir.output = fullfile(root_dir, 'output', 'source'); %% Engine parameters fieldsToSet.testingDevice = 'mri'; diff --git a/subfun/design/expDesign.m b/subfun/design/expDesign.m index c7aae94..d26eae9 100644 --- a/subfun/design/expDesign.m +++ b/subfun/design/expDesign.m @@ -1,59 +1,64 @@ function [cfg] = expDesign(cfg) % - % Creates the sequence of blocks and the events in them + % This function and its companions creates the sequence of blocks (static/motion) + % and the events (the single directions) for MT+ and MT/MST localizers. % - % The conditions are consecutive static and motion blocks. - % It gives better results than randomised. + % The conditions are consecutive static and motion blocks (fixed in this order gives + % better results than randomised). + % + % USAGE + % + % [cfg] = expDesign(cfg) + % + % + % Output: + % + % - ``cfg.design.blockNames``: cell array (nbBlocks, 1) with the condition name for each block + % - ``cfg.design.nbBlocks``: integer for the total number of blocks in the run + % - ``cfg.design.directions``: array (nbBlocks, nbEventsPerBlock) with the direction + % to present in a given event of a block. + % - ``cfg.design.blockFixationPosition``: [MT_MST] array (nbBlocks, 1) + % with the position in the hemifiled where to show the fixation cross + % - 0 90 180 270 : indicate the angle for translational motion direction + % - 666 -666 : indicate in/out-ward direction in radial motion + % - -1 : indicates static + % - ``cfg.design.speeds``: array (nbBlocks, nbEventsPerBlock) indicate the dots speed + % in each event, the target is represented by a higher/lower value + % - ``cfg.design.fixationTargets``: array (nbBlocks, numEventsPerBlock) showing + % for each event if it should be accompanied by a target % % It can be run as a stand alone without inputs and display a visual example of the - % possible design. See `getMockConfig` to set up the mock configuration. + % possible design. See ``getMockConfig`` to set up the mock configuration. % % It computes the directions to display and the task(s), at the moment: - % (1) detection of change in the color of the fixation target - % (2) detection of different speed of the moving dots - % [ W I P - if selected as a task it will give the same null output - % as if not selected ie no difference in speed ] + % + % 1. detection of change in the color of the fixation target + % 2. detection of different speed of the moving dots + % [ WIP - if selected as a task it will give the same null output + % as if not selected ie no difference in speed ] % % EVENTS + % % The ``nbEventsPerBlock`` should be a multiple of the number of motion directions requested in - % ``motionDirections`` (which should be more than 1) e.g.: + % ``motionDirections`` (which should be more than 1) for example:: % - % MT localizer: ``cfg.design.motionDirections = [ 0 90 180 270 ]; % right down left up`` - % MT_MST localizer: ``cfg.design.motionDirections = [666 -666]; % outward inward`` + % MT localizer: ``cfg.design.motionDirections = [ 0 90 180 270 ]; % right down left up`` + % MT_MST localizer: ``cfg.design.motionDirections = [666 -666]; % outward inward`` % % Pseudorandomization rules: % % - Directions: - % (1) Directions are all presented in random orders in `numEventsPerBlock/nDirections` - % consecutive chunks. This evenly distribute the directions across the - % block. - % (2) No same consecutive direction % - % - Color change detection of the fixation cross: - % (1) If there are 2 targets per block we make sure that they are at least 2 events apart. - % (2) Targets cannot be on the first or last event of a block. - % (3) No less than 1 target per event position in the whole run + % 1. Directions are all presented in random orders in `numEventsPerBlock/nDirections` + % consecutive chunks. This evenly distribute the directions across the + % block. + % 2. No same consecutive direction % - % Input: - % - cfg: parameters returned by setParameters - % - displayFigs: a boolean to decide whether to show the basic design - % matrix of the design + % - Color change detection of the fixation cross: % - % Output: - % - cfg.design.blockNames: cell array (nbBlocks, 1) with the condition name for each block - % - cfg.design.nbBlocks: integer for th etotal number of blocks in the run - % - cfg.design.directions: array (nbBlocks, nbEventsPerBlock) with the direction - % to present in a given event of a block. - % - cfg.design.blockFixationPosition: [MT_MST] array (nbBlocks, 1) - % with the position in the hemifiled - % where to show the fixation cross - % - 0 90 180 270 indicate the angle for translational motion direction - % - 666 -666 indicate in/out-ward direction in radial motion - % - -1 indicates static - % - cfg.design.speeds: array (nbBlocks, nbEventsPerBlock) indicate the dots speed - % in each event, the target is represented by a higher/lower value - % - cfg.design.fixationTargets: array (nbBlocks, numEventsPerBlock) showing - % for each event if it should be accompanied by a target + % 1. If there are 2 targets per block we make sure that they are at least 2 events apart. + % 2. Targets cannot be on the first or last event of a block. + % 3. No less than 1 target per event position in the whole run % % % (C) Copyright 2020 CPP visual motion localizer developers diff --git a/subfun/doDotMo.m b/subfun/doDotMo.m index feca37f..daa3658 100644 --- a/subfun/doDotMo.m +++ b/subfun/doDotMo.m @@ -1,17 +1,28 @@ function [onset, duration, dots] = doDotMo(cfg, thisEvent, thisFixation, dots, iEvent) % - % [onset, duration, dots] = doDotMo(cfg, thisEvent, thisFixation, dots, iEvent) + % Wrapper function that present the dot stimulation (static or motion) per event. % - % Draws the stimulation of static/moving in 4 directions dots or static + % USAGE:: % - % DIRECTIONS - % 0=Right; 90=Up; 180=Left; 270=down + % [onset, duration, dots] = doDotMo(cfg, thisEvent, thisFixation, dots, iEvent) % - % Input: - % - cfg: PTB/machine configurations returned by setParameters and initPTB + % :param cfg: PTB/machine configurations returned. see ``checkParameters`` + % :type cfg: structure + % + % :param thisEvent: structure that stores information about the event to present + % regarding the dots (static or motion, direction, etc.) + % :type thisEvent: + % + % :param thisFixation: structure that stores information about the fixation cross + % task to present + % :type thisFixation: + % + % :param dots: + % :type dots: + % + % :param iEvent: index of the event of the block at the moment of the presentation + % :type iEvent: % - % Output: - % - % % The dots are drawn on a square with a width equals to the width of the % screen diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m index 5e04c80..96cc1db 100644 --- a/tests/test_checkParameters.m +++ b/tests/test_checkParameters.m @@ -7,6 +7,26 @@ initTestSuite; end +function test_checkParameters_output_dir() + + % set up + cfg.design.localizer = 'MT'; + cfg = checkParameters(cfg); + + % test + if which('bids.internal.file_utils') + cfg.dir.output = bids.internal.file_utils(cfg.dir.output, 'cpath'); + assertEqual(cfg.dir.output, ... + bids.internal.file_utils(fullfile(fileparts(mfilename('fullpath')), ... + '..', ... + 'output', ... + 'source'), ... + 'cpath')); + + end + +end + function test_checkParameters_no_debug_fullscreen() % set up From eea26798969b39e779694df5a0af466e282e9ae1 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 9 Mar 2022 13:47:22 +0100 Subject: [PATCH 23/64] remove old output --- .gitignore | 1 + doc/configurations.md | 4 + main.m | 4 +- ...izer_run-666_date-202203091033_events.json | 86 ------------------- ...izer_run-001_date-202203091034_events.json | 86 ------------------- 5 files changed, 8 insertions(+), 173 deletions(-) delete mode 100644 source/sub-ctrl666/ses-666/func/sub-ctrl666_ses-666_task-visualLocalizer_run-666_date-202203091033_events.json delete mode 100644 source/sub-foo001/ses-001/func/sub-foo001_ses-001_task-visualLocalizer_run-001_date-202203091034_events.json diff --git a/.gitignore b/.gitignore index 037af8d..a7a6c34 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ *.tsv output +source ## virtual env env/ diff --git a/doc/configurations.md b/doc/configurations.md index cc91ad1..18dae77 100644 --- a/doc/configurations.md +++ b/doc/configurations.md @@ -100,6 +100,10 @@ cfg.timing.onsetDelay = 5.000000; cfg.verbose = 1.000000; ``` +## + +Type help `expDesign` to get information on how to tweak your experiment design. + ## Let the scanner pace the experiment diff --git a/main.m b/main.m index 8b6f99d..1c945be 100644 --- a/main.m +++ b/main.m @@ -33,7 +33,9 @@ % Run visualMotionLocalizer(cfg); -clear cfg; +% clear cfg; + +return %% Run MT/MST localizer diff --git a/source/sub-ctrl666/ses-666/func/sub-ctrl666_ses-666_task-visualLocalizer_run-666_date-202203091033_events.json b/source/sub-ctrl666/ses-666/func/sub-ctrl666_ses-666_task-visualLocalizer_run-666_date-202203091033_events.json deleted file mode 100644 index 62cfd4c..0000000 --- a/source/sub-ctrl666/ses-666/func/sub-ctrl666_ses-666_task-visualLocalizer_run-666_date-202203091033_events.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "onset": { - "Description": "time elapsed since experiment start", - "Units": "s" - }, - "trial_type": { - "Description": "types of trial", - "Levels": { - } - }, - "duration": { - "Description": "duration of the event or the block", - "Units": "s" - }, - "StimulusPresentation": { - "OperatingSystem": "x86_64-pc-linux-gnu", - "SoftwareRRID": "SCR_002881", - "Code": "", - "SoftwareVersion": "3.0.17", - "SoftwareName": "Psychtoolbox on Octave - 4.2.2" - }, - "direction": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - }, - "speedDegVA": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - }, - "target": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - }, - "event": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - }, - "block": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - }, - "keyName": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - }, - "fixationPosition": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - }, - "aperturePosition": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - } -} diff --git a/source/sub-foo001/ses-001/func/sub-foo001_ses-001_task-visualLocalizer_run-001_date-202203091034_events.json b/source/sub-foo001/ses-001/func/sub-foo001_ses-001_task-visualLocalizer_run-001_date-202203091034_events.json deleted file mode 100644 index 62cfd4c..0000000 --- a/source/sub-foo001/ses-001/func/sub-foo001_ses-001_task-visualLocalizer_run-001_date-202203091034_events.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "onset": { - "Description": "time elapsed since experiment start", - "Units": "s" - }, - "trial_type": { - "Description": "types of trial", - "Levels": { - } - }, - "duration": { - "Description": "duration of the event or the block", - "Units": "s" - }, - "StimulusPresentation": { - "OperatingSystem": "x86_64-pc-linux-gnu", - "SoftwareRRID": "SCR_002881", - "Code": "", - "SoftwareVersion": "3.0.17", - "SoftwareName": "Psychtoolbox on Octave - 4.2.2" - }, - "direction": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - }, - "speedDegVA": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - }, - "target": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - }, - "event": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - }, - "block": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - }, - "keyName": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - }, - "fixationPosition": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - }, - "aperturePosition": { - "Description": "", - "Levels": { - }, - "LongName": "", - "TermURL": "", - "Units": "" - } -} From 8476c3fc2fb07a7679d574bf767d36de08572f4e Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 9 Mar 2022 14:43:10 +0100 Subject: [PATCH 24/64] refactor base config and update submodules --- cfgMST.m | 22 ++++++++++++++ cfgMT.m | 25 ++++++++++++++++ initEnv.m | 2 ++ lib/CPP_BIDS | 2 +- lib/CPP_PTB | 2 +- main.m | 49 ++----------------------------- subfun/defaults/checkParameters.m | 3 +- tests/test_checkParameters.m | 3 +- 8 files changed, 57 insertions(+), 51 deletions(-) create mode 100644 cfgMST.m create mode 100644 cfgMT.m diff --git a/cfgMST.m b/cfgMST.m new file mode 100644 index 0000000..1bd47a3 --- /dev/null +++ b/cfgMST.m @@ -0,0 +1,22 @@ +function cfg = cfgMST() + % + % (C) Copyright 2020 CPP visual motion localizer developers + + cfg.design.localizer = 'MT_MST'; + + cfg.subject.subjectGrp = 'pilot'; + cfg.subject.sessionNb = 1; + cfg.subject.askGrpSess = [false false]; + + cfg.verbose = 1; + + cfg.debug.do = false; + cfg.debug.transpWin = false; + cfg.debug.smallWin = false; + + cfg.eyeTracker.do = false; + + cfg.design.nbRepetitions = 10; + cfg.design.nbEventsPerBlock = 12; + +end diff --git a/cfgMT.m b/cfgMT.m new file mode 100644 index 0000000..7c413cd --- /dev/null +++ b/cfgMT.m @@ -0,0 +1,25 @@ +function cfg = cfgMT() + % + % (C) Copyright 2020 CPP visual motion localizer developers + + cfg.design.localizer = 'MT'; + + cfg.subject.subjectGrp = 'pilot'; + cfg.subject.sessionNb = 1; + cfg.subject.askGrpSess = [false false]; + + cfg.verbose = 1; + + cfg.debug.do = false; + cfg.debug.transpWin = false; + cfg.debug.smallWin = false; + + cfg.pacedByTriggers.do = false; + + cfg.eyeTracker.do = false; + + cfg.design.nbRepetitions = 15; + + cfg.timing.eventDuration = 0.43; % second + +end diff --git a/initEnv.m b/initEnv.m index f3d7e2f..a6c42bc 100644 --- a/initEnv.m +++ b/initEnv.m @@ -15,6 +15,8 @@ % % 2 - Add project to the O/M path + more off; + octaveVersion = '4.0.3'; matlabVersion = '8.6.0'; diff --git a/lib/CPP_BIDS b/lib/CPP_BIDS index 7b2b45e..3a67904 160000 --- a/lib/CPP_BIDS +++ b/lib/CPP_BIDS @@ -1 +1 @@ -Subproject commit 7b2b45ed5fbe4c0e8292a55b0f68dd6a9049ead5 +Subproject commit 3a67904c66439e90c8fc528ac8729254b91d56d6 diff --git a/lib/CPP_PTB b/lib/CPP_PTB index de8c5e2..7fa6cae 160000 --- a/lib/CPP_PTB +++ b/lib/CPP_PTB @@ -1 +1 @@ -Subproject commit de8c5e27cb3c1bcd2a9947feacc55eedb59a6a1b +Subproject commit 7fa6cae221972f74d895145c5cae5ed37e376753 diff --git a/main.m b/main.m index 1c945be..49318c4 100644 --- a/main.m +++ b/main.m @@ -5,54 +5,13 @@ clc; clear; -%% Run MT+ localizer - -cfg.design.localizer = 'MT'; - -cfg.verbose = 2; - -cfg.debug.do = false; -cfg.debug.transpWin = 0; -cfg.debug.smallWin = 0; - -cfg.pacedByTriggers.do = true; - -cfg.eyeTracker.do = false; - -cfg.design.nbRepetitions = 15; - -cfg.timing.eventDuration = 0.43; % second - initEnv(); -cfg = checkParameters(cfg); - -% to view all the options that are set -% unfold(cfg); - -% Run -visualMotionLocalizer(cfg); - -% clear cfg; - -return +%% Run MT+ localizer +cfg = cfgMT(); %% Run MT/MST localizer - -cfg.design.localizer = 'MT_MST'; - -cfg.verbose = 2; - -cfg.debug.do = false; -cfg.debug.transpWin = 0; -cfg.debug.smallWin = 0; - -cfg.eyeTracker.do = false; - -cfg.design.nbRepetitions = 10; -cfg.design.nbEventsPerBlock = 12; - -initEnv(); +% cfg = cfgMST(); cfg = checkParameters(cfg); @@ -61,5 +20,3 @@ % run visualMotionLocalizer(cfg); - -clear cfg; diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 0c89086..ebac28e 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -29,7 +29,8 @@ root_dir = bids.internal.file_utils(root_dir, 'cpath'); end - fieldsToSet.dir.output = fullfile(root_dir, 'output', 'source'); + % the "source" subfolder will be added by createFilename of CPP_BIDS + fieldsToSet.dir.output = fullfile(root_dir, 'output'); %% Engine parameters fieldsToSet.testingDevice = 'mri'; diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m index 96cc1db..646639b 100644 --- a/tests/test_checkParameters.m +++ b/tests/test_checkParameters.m @@ -19,8 +19,7 @@ function test_checkParameters_output_dir() assertEqual(cfg.dir.output, ... bids.internal.file_utils(fullfile(fileparts(mfilename('fullpath')), ... '..', ... - 'output', ... - 'source'), ... + 'output'), ... 'cpath')); end From 1c49d60c306a993d8e0c765d05d348644e20d41c Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 9 Mar 2022 14:57:12 +0100 Subject: [PATCH 25/64] fix paced by trigger message and refactor config --- cfgMST.m | 14 +------------- cfgMT.m | 16 ++-------------- lib/CPP_PTB | 2 +- main.m | 12 ++++++++++++ subfun/defaults/checkParameters.m | 2 +- 5 files changed, 17 insertions(+), 29 deletions(-) diff --git a/cfgMST.m b/cfgMST.m index 1bd47a3..cc584fa 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -1,21 +1,9 @@ -function cfg = cfgMST() +function cfg = cfgMST(cfg) % % (C) Copyright 2020 CPP visual motion localizer developers cfg.design.localizer = 'MT_MST'; - cfg.subject.subjectGrp = 'pilot'; - cfg.subject.sessionNb = 1; - cfg.subject.askGrpSess = [false false]; - - cfg.verbose = 1; - - cfg.debug.do = false; - cfg.debug.transpWin = false; - cfg.debug.smallWin = false; - - cfg.eyeTracker.do = false; - cfg.design.nbRepetitions = 10; cfg.design.nbEventsPerBlock = 12; diff --git a/cfgMT.m b/cfgMT.m index 7c413cd..092f407 100644 --- a/cfgMT.m +++ b/cfgMT.m @@ -1,22 +1,10 @@ -function cfg = cfgMT() +function cfg = cfgMT(cfg) % % (C) Copyright 2020 CPP visual motion localizer developers cfg.design.localizer = 'MT'; - cfg.subject.subjectGrp = 'pilot'; - cfg.subject.sessionNb = 1; - cfg.subject.askGrpSess = [false false]; - - cfg.verbose = 1; - - cfg.debug.do = false; - cfg.debug.transpWin = false; - cfg.debug.smallWin = false; - - cfg.pacedByTriggers.do = false; - - cfg.eyeTracker.do = false; + cfg.pacedByTriggers.do = true; cfg.design.nbRepetitions = 15; diff --git a/lib/CPP_PTB b/lib/CPP_PTB index 7fa6cae..cbe438c 160000 --- a/lib/CPP_PTB +++ b/lib/CPP_PTB @@ -1 +1 @@ -Subproject commit 7fa6cae221972f74d895145c5cae5ed37e376753 +Subproject commit cbe438c17baa2ba0f74b7f5578c061744fa41d42 diff --git a/main.m b/main.m index 49318c4..650215d 100644 --- a/main.m +++ b/main.m @@ -7,6 +7,18 @@ initEnv(); +cfg.subject.subjectGrp = 'pilot'; +cfg.subject.sessionNb = 1; +cfg.subject.askGrpSess = [false false]; + +cfg.verbose = 1; + +cfg.debug.do = false; +cfg.debug.transpWin = false; +cfg.debug.smallWin = false; + +cfg.eyeTracker.do = false; + %% Run MT+ localizer cfg = cfgMT(); diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index ebac28e..2a72d50 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -206,7 +206,7 @@ % reexpress those in terms of repetition time if cfg.pacedByTriggers.do - fieldsToSet.pacedByTriggers.quietMode = false; + fieldsToSet.pacedByTriggers.quietMode = true; fieldsToSet.pacedByTriggers.nbTriggers = 1; fieldsToSet.timing.eventDuration = cfg.mri.repetitionTime / 2 - 0.04; % second From ad62f35bf386d2bac49cb316c497def4b761ec94 Mon Sep 17 00:00:00 2001 From: marcobarilari Date: Wed, 9 Mar 2022 17:16:06 +0100 Subject: [PATCH 26/64] add various comments and inputs --- cfgMST.m | 5 ++++- cfgMT.m | 4 +++- {doc => docs}/configurations.md | 0 subfun/doDotMo.m | 6 +++++- 4 files changed, 12 insertions(+), 3 deletions(-) rename {doc => docs}/configurations.md (100%) diff --git a/cfgMST.m b/cfgMST.m index cc584fa..87faaab 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -5,6 +5,9 @@ cfg.design.localizer = 'MT_MST'; cfg.design.nbRepetitions = 10; - cfg.design.nbEventsPerBlock = 12; + + cfg.design.nbEventsPerBlock = 10; + + cfg.timing.eventDuration = 0.3; % 0.6 seconds end diff --git a/cfgMT.m b/cfgMT.m index 092f407..3b680ef 100644 --- a/cfgMT.m +++ b/cfgMT.m @@ -6,8 +6,10 @@ cfg.pacedByTriggers.do = true; + cfg.mri.triggerNb = 0; + cfg.design.nbRepetitions = 15; - cfg.timing.eventDuration = 0.43; % second + cfg.timing.eventDuration = 0.43; % .86 second end diff --git a/doc/configurations.md b/docs/configurations.md similarity index 100% rename from doc/configurations.md rename to docs/configurations.md diff --git a/subfun/doDotMo.m b/subfun/doDotMo.m index daa3658..7d53701 100644 --- a/subfun/doDotMo.m +++ b/subfun/doDotMo.m @@ -57,6 +57,8 @@ %% make textures + % If staticReSeed is true, then change the seed of the static dots only + % for the first event if cfg.dot.staticReSeed && ... strcmpi(thisEvent.trial_type, 'static') && ... iEvent ~= 1 @@ -96,7 +98,9 @@ drawFixation(thisFixation); - if cfg.dot.staticReSeed && strcmpi(thisEvent.trial_type, 'static') + if cfg.dot.staticReSeed && ... + strcmpi(thisEvent.trial_type, 'static') && ... + iEvent ~= cfg.design.nbEventsPerBlock dotTexture('draw', cfg, thisEvent); From 4abee05d8e33b75339c32f19bc545fef71b421d1 Mon Sep 17 00:00:00 2001 From: marcobarilari Date: Wed, 9 Mar 2022 17:16:17 +0100 Subject: [PATCH 27/64] fix bugs --- lib/CPP_PTB | 2 +- main.m | 6 +++--- subfun/defaults/checkParameters.m | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/CPP_PTB b/lib/CPP_PTB index cbe438c..88af543 160000 --- a/lib/CPP_PTB +++ b/lib/CPP_PTB @@ -1 +1 @@ -Subproject commit cbe438c17baa2ba0f74b7f5578c061744fa41d42 +Subproject commit 88af543514b3c29ef5c95f64ec12c1c202e33763 diff --git a/main.m b/main.m index 650215d..4fafa59 100644 --- a/main.m +++ b/main.m @@ -13,17 +13,17 @@ cfg.verbose = 1; -cfg.debug.do = false; +cfg.debug.do = true; cfg.debug.transpWin = false; cfg.debug.smallWin = false; cfg.eyeTracker.do = false; %% Run MT+ localizer -cfg = cfgMT(); +% cfg = cfgMT(cfg); %% Run MT/MST localizer -% cfg = cfgMST(); +cfg = cfgMST(cfg); cfg = checkParameters(cfg); diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 2a72d50..248f2ea 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -211,20 +211,20 @@ fieldsToSet.timing.eventDuration = cfg.mri.repetitionTime / 2 - 0.04; % second - % Time between blocs in nb of triggers (remember to consider the nb trigger to wait + 1) + % Time in nb of volumes between blocs in nb of triggers (remember to consider the nb trigger to wait + 1) fieldsToSet.timing.triggerIBI = 4; % Time between blocks in secs - fieldsToSet.timing.IBI = 0; + cfg.timing.IBI = 0; % Time between events in secs - fieldsToSet.timing.ISI = 0; + cfg.timing.ISI = 0; % Number of seconds before the motion stimuli are presented - fieldsToSet.timing.onsetDelay = 0; + cfg.timing.onsetDelay = 0; % Number of seconds after the end all the stimuli before ending the run - fieldsToSet.timing.endDelay = 0; + cfg.timing.endDelay = 0; cfg = setDefaultFields(cfg, fieldsToSet); From 8bcda0e3a0ba8a3787dbb481128686772694089b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 9 Mar 2022 16:16:37 +0000 Subject: [PATCH 28/64] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- cfgMST.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cfgMST.m b/cfgMST.m index 87faaab..e4f30a5 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -5,9 +5,9 @@ cfg.design.localizer = 'MT_MST'; cfg.design.nbRepetitions = 10; - + cfg.design.nbEventsPerBlock = 10; - + cfg.timing.eventDuration = 0.3; % 0.6 seconds end From 22daf9bc7e6daeaeb65e772e6cf4604ffe92bb52 Mon Sep 17 00:00:00 2001 From: marcobarilari Date: Wed, 9 Mar 2022 17:31:55 +0100 Subject: [PATCH 29/64] add ask for subject group --- main.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.m b/main.m index 4fafa59..ee0e290 100644 --- a/main.m +++ b/main.m @@ -9,11 +9,11 @@ cfg.subject.subjectGrp = 'pilot'; cfg.subject.sessionNb = 1; -cfg.subject.askGrpSess = [false false]; +cfg.subject.askGrpSess = [true false]; cfg.verbose = 1; -cfg.debug.do = true; +cfg.debug.do = false; cfg.debug.transpWin = false; cfg.debug.smallWin = false; From 9cefffc531710d331f519fc5271edce29ac73f97 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 9 Mar 2022 20:06:43 +0100 Subject: [PATCH 30/64] fix one of the defaults for file naming --- subfun/defaults/checkParameters.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 248f2ea..5123c74 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -123,7 +123,7 @@ fieldsToSet.mri.repetitionTime = 1.8; - fieldsToSet.suffix.acquisition = ''; + fieldsToSet.suffix.acq = ''; fieldsToSet.pacedByTriggers.do = false; From 6357c0018f418f963f0a676e7a6447a96025c6ad Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 9 Mar 2022 20:11:17 +0100 Subject: [PATCH 31/64] fix tests --- subfun/defaults/checkParameters.m | 3 ++- tests/data/config_MT.mat | Bin 1529 -> 1519 bytes tests/data/config_MT_MST.mat | Bin 1636 -> 1631 bytes tests/test_checkParameters.m | 10 +++++----- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 5123c74..5c7f47c 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -211,7 +211,8 @@ fieldsToSet.timing.eventDuration = cfg.mri.repetitionTime / 2 - 0.04; % second - % Time in nb of volumes between blocs in nb of triggers (remember to consider the nb trigger to wait + 1) + % Time in nb of volumes between blocs in nb of triggers + % (remember to consider the nb trigger to wait + 1) fieldsToSet.timing.triggerIBI = 4; % Time between blocks in secs diff --git a/tests/data/config_MT.mat b/tests/data/config_MT.mat index 3226ce6681f86608a1ffed81dfe76ae53c2a0cd2..847eb47f89e574acc202d90e01bc38320bff3369 100644 GIT binary patch delta 1427 zcmV;E1#J5H3-1e%KMgW4IxsjoG&UeIFfuZcQ6rIH1(9?Re`f^%0C=3tSwC+ZHx#EN zJFSzzQ8Oh=p{WQ81ZdI4TO3;sVi-0ITc|r2Fz(N@O!!1zNuDib>epyLLB-`)M*{O~O-iv?@LAaQof4lO9*}~a^!X;B9uUx zcc;X&#qw->=kdz@Xq!958#nC#vcc*a(`x-I?fUwEY&Fww$4$N8J=oSZr{w(Eupf5a z^<>>9e_XIEQl_rwa3Jlh57Jt3s?A@?{|enapPwLiK6Cu}(>@5f(tF|zdIwwmo?TGA zh*8duN$;2(llk^yi!0xb-!~2W{lH*#J%AJhRt*~95zM!vaywl6d(v*!j(Z00${I?a zGh{R)F$xoTpMMo5nO&;G!f(jiiFwLk>Ul2Df3TQc*YnmxXQm&Wch9@_)pxCVFB|Yy zWPM}@=Z};1^3|su*Pi{pzRuf^8m{}h27inSzau>`3kXk-FhP72B#FAIXjdJ7)Vd|! zxZ%3_$lz016B-2xeg)GQU_{ko?qdeVndJ`#dY{sT1S6Pj22xqMK# ze+Bbpo&Busw6iPG?x3E1xcgvRqc?99Z+(uwd&t$7V{Hvd5wa*buN^t9k{sJ+`&@m$ zHb?IrG^&ag~A29C8B4*fJ9J!5d+~^Ox|WB z_!RO@s8mu$Q_9r%?BFDUSla0eCXEAvIuj6l4obS5^$JWs{kaM>rM`68= z`Y`&&e_f_UCibw(3%+{81AM;d(=P*)M zGMPcu{cEyb|F8J7Jf0ooZ{Ip=tKir5hk3bL$PfP)ye4+H-f3oc_YGG1WC|^p(vD8p z+_NGEJe9#EY|!!aUVY{3_qGllM6olX7AGV=F_zy6}i z-_PEM{q_5X^JC)%rEf$D7L>^yQ3NXKG5E-CpVG(CBr5_%pK(6%fF197C-k6qOU9UH#xU`($L;)Jol-ramJkgWk$hxFPt9V%tmm9KL7mf2d{X= zj`R8r<72;Z$46ls$Df#hOXqV7tWS05<&Fm~&igeM73cl)+Fg}5TwtCBNpE^A_dfq` zFmHe8%&V!BDb=3KDo`;-Ll`!PTH(X2-SSW9pH&0dPgqt*D7+7x)E-S~Q zj(tD$KMgT5IyE#pF*qPHFfuZcQ6rIH1(9?Re{lr>0C=3tS-o!?Hx#Gj zkJd@xsF|Fl&{PBk0<`GjEsiY*F$^1qEz}(h829lk6FwcUB+r&I_1|d!f{Y!qbnDmx zEnuKixBdwoI}~t99;u@)SL;Z%aR^X%@9uu@@#FD*X%!)~)6X7oP$@~F zid(MWOfxt$-dVWnJlgtB;zo}1U(&R^#-v{UO1ruIA6stn&AQ3=dxtwp=Omv$9p_=r zU03v-f0S{WM^e?*9`=Qv^+0GV&XoE~{$HWn_wy5E?`J`O{%r}`drUC4+~TCSa|oi8((=h3ir|h zw<7wQS)4ykH>y{kaol*$`{t$?KXN?x_cZ-6D(#N2z%)o%c8pWRhC!0Zo0@Sou}7^t z!i^ly%}1I(6FnhOkl;UMd;CCS& zf0SlHf7!&JwXJb>1hv<1rXRK+Y%A)`8;RSPA@4r2khaT{rtOcW&8cvJaMAG+@If)>uXnC{L9Pszn}Y7<#`i(vtoVU(R6GKtplHX6+V(y z=cosRFQ1oueC&wHmzv<0DtJkQ^aKs%*Wp9uK$_t{sNf|n^2vR9w41DBr-GN=e}vZ} z6;tlZmygNAZ9aFMC#^f$=~YdKsA~8W)iSt_8SH_~ym=WZAd}geHtJ!PiSQhT zQcK2DRQ>#1&g=gbe^%FX0r~5<%Gzr1P3>XPuIIAD{{_xP?=}|P^zMPCr96>Bi=(uw z5;nV5M1f@@xP(nIn%v8;eC^)$f6>dJ>E_rv0ATB+j9H%?dkvV{EY;jh2Q z_V=^*!M}d*xIZRtkn)Bk#hgqTh!9!(z`_bF@~N%AsK^jYUqPuydTf4fGv+bP?> z-h~}~S9R|e@~fK~zb3Ci^mUGl(6DwKF7?|dj(TU}x=%%qb87uRGYm%i;iQZ+9m$pQ z{PVaUyy6zK-W#{9kNL)4A4!{d{!|BEDzBU4oXX;ty&kx%`zxB))ct3TyDopY#4Hbz z?xZ~TKL39(%TFv!;T9(Uf46Kn?t_WjWF5N5N6v^$9Evgy?RqrP??;|Eqw}vl&;JY2cQ$uW*>;X>3eva-NuWz@Dzonyb0OnxZoTyx|022@ rdooYF@r7!?%_X-E_YVL70RR7EWnf_70AfZY3<69*7KjZ1UtInl;C$Uf diff --git a/tests/data/config_MT_MST.mat b/tests/data/config_MT_MST.mat index be77a422a48239a251349bbbad5ffe9c404019d4..60a11e83d56d4f960d057318e526fc6bd925cb7a 100644 GIT binary patch delta 1367 zcmV-d1*rPu4BrfpKMgW4IxsjoG&UeIFfuZcQ6rIH1(9?Rf7b;70C=3tSxavlHxQ;J z+o|(#gdE!BQmB_AC=j5%`4&IqAckSXu!Xt@1I9i^65-WyOLA=~r=I%{nqSdld+Vu4 zffn$!w;p@!4``v1yQG%8-b%Yv6Ndn$9WK8aa!Ae$XV(!ze}00{s`&pv)CNk+ilUc{ zDrp!+;BoL*f6y{&srE?xI1x}DQ&4c^#6Bh{D=zk#K_ZU?gc`IDZrsn&4EIBWCftOJ zad7JFkRTq0311jPmpa}BD5gC;ayTYa4g>7NPE45=dI4jXIMmnghZN`dM~(;n_P9%N zzYmll=1~A+JnRBTC*#oT0^@Q3Eba-B*?aELK5&y}e-|cyE^s*Pci<9xkkF&t1UVjx z*BN~Y)Fo`HUbHTMma45=+P<9hmGmRYe;f&BSJ>wRG&&;8EL)T*?W@D zUp42Uf6rfA)V+{#8hdifCu`Xi`>g|F*WxHS29p0*X!g2(it_6!=`WsjfQu8~<^yOS z?{?byV6{C;7&{BwXW?0RQ-4MNx|sa6{=TU>?}v((|Hlvk$8tbjJgl()isR7oB<^XW z-Z<_l`ao1y*q%Nmap)sA5YK5ZH;DC-?PvBwT0D+bD}|{Ax*A}fKi~7tLo+vz=DWvD zY~@W7+{+rcHBldH<@|BJS^T#d$Ha2plgY%&{@zve$0)Nq!V*&_WYH-O5gR%|ARkJ` zRmC1H-4gCivz{J4RP@i2*#b=gV3Q{UQUSMQlJ?_~M? zxs6<{AA7mK+>mSQr|S6YmyOwW!fdZ%SJ#aGEk*m}@)(jfh1MfqiTSGn0L_&Wu>q{Th`P#*0ndTbT&vKHeDTRu9!Ve+}{d*?%FMu#%xLgjWR+$Nbjd|SXq=$+2Q{KS7+aC){OV>D_Y6}=82w_aMW1T-DQp}G;w(_K(et?_?uo)(quF-K^sl#JN8bjnOdm^V@$U$Z_jRfKI(hJ? zHTRp2=ROnFkE!v!Yv_y)-D#4G7jk1-p8fspN2_>6>v?mAesmvGKe@b@3b>N{+yduQ z<_ArE;OzTJLi3XEC-cT#c5fK+_K@*^_B5gSK7WUq=O3CmTyy%}YP04#=y*-$^V54s zkH`x{n!aIt9Kb^NhI#9B59Q}C=^YYN477a+SEc%>vcDf$;`E-c`~B%7MSm;m-u50U zDSIcS&ECKX`ykWT{{jF2|Nkq=%+CwRFU~9h(hRA2DK4owiIohfAhj$tuf(NJv?vj* z2oCb|ic?FlsRsc*AT|JEHX!DJ(jdSJf<}k_fMsTas%_IrZE(Xr7|S_SRF8 z0xjTcZ+(P3Kns=JCAHl3R@$YSI0UHOq4>>^Lvm&~yN(cg`x!#3;`x!N4V0D@MK2ju z(lCm^>tUHE18)xSyjL?uQ0VxCs~I z;MCb6K|Bl-zA%O^b-W8uOnZ3ba7?Bg2H1z4m@+N&0>&%-IUe}i<1WSh zK2V03M*)oSunQcWj6<&rjLQMAxF>L?8z;ktYug1w+@J1i=*TiNdDiT+3Wf_%CD=Wzk1dIE>3)#51@U# z+iB~A)%GZ1>?~}bg=gVS{T2D^V)EDe`>y7^A1Yctk0An%<$$_)SYiJa$D!p(+|x$A zaokh%fvB#qJ$*{z&_`|{-qT)g5bGn`&+LbISsklZ3R4SoHNZT7zUQ5XW^NwM_m7*{ z%9|v(mo;!}qCVEj`RjbM__P_v#B$z~$;8V3-c|IcD6>1l5>qE+(J2lQ8#+NCUrNSR z#U3r)67Eg2o*q6{^skfJ0!;yAlPCjH0l$-b0~>#T_z;StKfZ|wa1TLHFZPdW6srJ`D$nxiN z8@XCP_Huu_A=lPV)$!La8?)_%*gtq5fI~QynSmpj(crnrD$N+^l8c7WI7gMwug-aWSMmIR`AeJqo!o*; z@Kx<$TCNwe!~X}a&c55M8Smd$w3G+T6Gwk(Ke+&#IXDU|645tolhO2D_Oi8myC*wa zN4tyV18i~aIey0U8}sreMSZr!8@0ssEpcN@oNI~mEpeeG?v*7DEOFYOK3=lRdp$!k zYmg+S_f;lIk%w;Dn-;QSi;c6ceOW>F_VAD2W%>L0hu~j-thqiqZjkbZB*dIh;Sqni zBQHIQKGp71*f8uTHl*9^rQQj`pMlQetGEZpg183h+5}KEMN0~S7vipC-khh17x2K8C5BYn{JU`LQ;hNL$SDQ80LC0+} zub2b2Z@Rw$nl34;I=ki`YnXF-BKPN?{-nIN#! eo)UXW)yGPKdyT>1GFk40*-NTE5E}sF%_|qW&%(a| diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m index 646639b..cc53f96 100644 --- a/tests/test_checkParameters.m +++ b/tests/test_checkParameters.m @@ -14,7 +14,7 @@ function test_checkParameters_output_dir() cfg = checkParameters(cfg); % test - if which('bids.internal.file_utils') + if ~bids.internal.is_github_ci cfg.dir.output = bids.internal.file_utils(cfg.dir.output, 'cpath'); assertEqual(cfg.dir.output, ... bids.internal.file_utils(fullfile(fileparts(mfilename('fullpath')), ... @@ -110,8 +110,8 @@ function test_checkParameters_MT() cfg = removeDirFieldForGithubAction(cfg); % uncomment for update default config .mat - % expected = cfg; - % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); + % expected = cfg; + % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); % test @@ -130,8 +130,8 @@ function test_checkParameters_MT_MST() cfg = removeDirFieldForGithubAction(cfg); % uncomment for update default config .mat - % expected = cfg; - % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); + % expected = cfg; + % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); % test From 9ef171f7a993d18e76fb11fc9b271449821d6e04 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 9 Mar 2022 20:12:18 +0100 Subject: [PATCH 32/64] add comment --- tests/test_checkParameters.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m index cc53f96..3b11ab1 100644 --- a/tests/test_checkParameters.m +++ b/tests/test_checkParameters.m @@ -9,6 +9,8 @@ function test_checkParameters_output_dir() + % failure expected when run with runTests + % set up cfg.design.localizer = 'MT'; cfg = checkParameters(cfg); From 121212cba524b3bfe1693f306693aceb754c071a Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 9 Mar 2022 20:23:02 +0100 Subject: [PATCH 33/64] skip test in CI --- tests/test_checkParameters.m | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m index 3b11ab1..e237c7c 100644 --- a/tests/test_checkParameters.m +++ b/tests/test_checkParameters.m @@ -16,7 +16,7 @@ function test_checkParameters_output_dir() cfg = checkParameters(cfg); % test - if ~bids.internal.is_github_ci + if ~isGithubCi cfg.dir.output = bids.internal.file_utils(cfg.dir.output, 'cpath'); assertEqual(cfg.dir.output, ... bids.internal.file_utils(fullfile(fileparts(mfilename('fullpath')), ... @@ -152,3 +152,18 @@ function checkAllFields(cfg, expected) function cfg = removeDirFieldForGithubAction(cfg) cfg = rmfield(cfg, 'dir'); end + +function [is_github, pth] = isGithubCi() + % (C) Copyright 2021 Remi Gau + is_github = false; + + GITHUB_WORKSPACE = getenv('HOME'); + + if strcmp(GITHUB_WORKSPACE, '/home/runner') + + is_github = true; + pth = GITHUB_WORKSPACE; + + end + +end From b96ff44b1800590966ee8931528ee6cf455e15f3 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 9 Mar 2022 20:31:00 +0100 Subject: [PATCH 34/64] F CI --- tests/test_checkParameters.m | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m index e237c7c..e64cf75 100644 --- a/tests/test_checkParameters.m +++ b/tests/test_checkParameters.m @@ -16,7 +16,7 @@ function test_checkParameters_output_dir() cfg = checkParameters(cfg); % test - if ~isGithubCi + if ~isGithubMoxunitAction cfg.dir.output = bids.internal.file_utils(cfg.dir.output, 'cpath'); assertEqual(cfg.dir.output, ... bids.internal.file_utils(fullfile(fileparts(mfilename('fullpath')), ... @@ -153,17 +153,17 @@ function checkAllFields(cfg, expected) cfg = rmfield(cfg, 'dir'); end -function [is_github, pth] = isGithubCi() - % (C) Copyright 2021 Remi Gau - is_github = false; +function [isGithub, pth] = isGithubMoxunitAction() + % (C) Copyright 2021 Remi Gau + isGithub = false; - GITHUB_WORKSPACE = getenv('HOME'); + GITHUB_WORKSPACE = getenv('HOME'); - if strcmp(GITHUB_WORKSPACE, '/home/runner') + if strcmp(GITHUB_WORKSPACE, '/github/workspace') - is_github = true; - pth = GITHUB_WORKSPACE; + isGithub = true; + pth = GITHUB_WORKSPACE; - end + end end From ce78e6c74aff38769c6058646fa86eda5189ec6b Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 9 Mar 2022 20:34:59 +0100 Subject: [PATCH 35/64] CI CI tell me where you live, so I can come break your legs... --- tests/test_checkParameters.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m index e64cf75..a3d9de5 100644 --- a/tests/test_checkParameters.m +++ b/tests/test_checkParameters.m @@ -9,6 +9,8 @@ function test_checkParameters_output_dir() + fprintf(getenv('HOME')); + % failure expected when run with runTests % set up From 7fcb87fab9b85875e4085eedd89c9bafc50d0156 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 9 Mar 2022 20:38:59 +0100 Subject: [PATCH 36/64] now I know wher eyou live --- tests/test_checkParameters.m | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m index a3d9de5..9eefe82 100644 --- a/tests/test_checkParameters.m +++ b/tests/test_checkParameters.m @@ -9,8 +9,6 @@ function test_checkParameters_output_dir() - fprintf(getenv('HOME')); - % failure expected when run with runTests % set up @@ -161,7 +159,7 @@ function checkAllFields(cfg, expected) GITHUB_WORKSPACE = getenv('HOME'); - if strcmp(GITHUB_WORKSPACE, '/github/workspace') + if strcmp(GITHUB_WORKSPACE, '/github/home') isGithub = true; pth = GITHUB_WORKSPACE; From 25f9cbc86f76bb19052e0b8c1b09f64e7a2bc7b1 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 13:38:19 +0100 Subject: [PATCH 37/64] add details for FOV tweaking in MT localiser config --- cfgMT.m | 19 ++++++++++++++++++- main.m | 8 ++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/cfgMT.m b/cfgMT.m index 3b680ef..1a8dddf 100644 --- a/cfgMT.m +++ b/cfgMT.m @@ -4,7 +4,7 @@ cfg.design.localizer = 'MT'; - cfg.pacedByTriggers.do = true; + cfg.pacedByTriggers.do = false; cfg.mri.triggerNb = 0; @@ -12,4 +12,21 @@ cfg.timing.eventDuration = 0.43; % .86 second + %% variable FOV info + % in case the field of view is not properly centered or obstructed + % + % see https://github.com/cpp-lln-lab/estimate_visual_FOV.git + % + % set up configuration: ensure that the following fields are the same + % as when you ran the estimate_visual_FOV script + % + % cfg.testingDevice + % cfg.screen.monitorDistance + % cfg.screen.monitorWidth + + % fixation cross displacement in degrees of visual angles + % + % cfg.fixation.xDisplacement = FIXME; + % cfg.fixation.yDisplacement = FIXME; + end diff --git a/main.m b/main.m index ee0e290..712d67c 100644 --- a/main.m +++ b/main.m @@ -13,17 +13,17 @@ cfg.verbose = 1; -cfg.debug.do = false; -cfg.debug.transpWin = false; +cfg.debug.do = true; +cfg.debug.transpWin = true; cfg.debug.smallWin = false; cfg.eyeTracker.do = false; %% Run MT+ localizer -% cfg = cfgMT(cfg); +cfg = cfgMT(cfg); %% Run MT/MST localizer -cfg = cfgMST(cfg); +% cfg = cfgMST(cfg); cfg = checkParameters(cfg); From 7062908d0c5476662153e3212604c0d091bc59f5 Mon Sep 17 00:00:00 2001 From: marcobarilari Date: Thu, 17 Mar 2022 17:07:17 +0100 Subject: [PATCH 38/64] adjust parameters according to Liege testing --- cfgMST.m | 4 +++- cfgMT.m | 8 +++++++- main.m | 10 +++++++--- subfun/defaults/checkParameters.m | 2 +- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/cfgMST.m b/cfgMST.m index e4f30a5..3c7d9ae 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -8,6 +8,8 @@ cfg.design.nbEventsPerBlock = 10; - cfg.timing.eventDuration = 0.3; % 0.6 seconds + % in Liege is 0.6 + % on macs is 0.3 + cfg.timing.eventDuration = 0.6; % 0.6 seconds end diff --git a/cfgMT.m b/cfgMT.m index 3b680ef..7712b09 100644 --- a/cfgMT.m +++ b/cfgMT.m @@ -5,11 +5,17 @@ cfg.design.localizer = 'MT'; cfg.pacedByTriggers.do = true; + + cfg.timing.triggerIBI = 4; cfg.mri.triggerNb = 0; cfg.design.nbRepetitions = 15; - cfg.timing.eventDuration = 0.43; % .86 second + cfg.design.nbEventsPerBlock = 12; + + % in Liege is 0.79 (tsry less) + % in mcas is 0.43 + cfg.timing.eventDuration = 0.79; % .86 second end diff --git a/main.m b/main.m index ee0e290..0b5cac7 100644 --- a/main.m +++ b/main.m @@ -17,13 +17,17 @@ cfg.debug.transpWin = false; cfg.debug.smallWin = false; -cfg.eyeTracker.do = false; +cfg.audio.devIdx = 5; + +cfg.eyeTracker.do = true; +% in liege +cfg.dot.speed = 7.5; %% Run MT+ localizer -% cfg = cfgMT(cfg); +cfg = cfgMT(cfg); %% Run MT/MST localizer -cfg = cfgMST(cfg); +% cfg = cfgMST(cfg); cfg = checkParameters(cfg); diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 5c7f47c..4dfb647 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -51,7 +51,7 @@ %% Timing % block length = (cfg.eventDuration + cfg.ISI) * cfg.design.nbEventsPerBlock - fieldsToSet.timing.eventDuration = 0.30; % second + fieldsToSet.timing.eventDuration = 0.6; % second % Time between events in secs fieldsToSet.timing.ISI = 0.1; From 19aad07074cbf6f34543a7c842d6f493e7516ab7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 17 Mar 2022 16:07:50 +0000 Subject: [PATCH 39/64] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- cfgMT.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cfgMT.m b/cfgMT.m index 7712b09..a79363a 100644 --- a/cfgMT.m +++ b/cfgMT.m @@ -5,7 +5,7 @@ cfg.design.localizer = 'MT'; cfg.pacedByTriggers.do = true; - + cfg.timing.triggerIBI = 4; cfg.mri.triggerNb = 0; @@ -13,7 +13,7 @@ cfg.design.nbRepetitions = 15; cfg.design.nbEventsPerBlock = 12; - + % in Liege is 0.79 (tsry less) % in mcas is 0.43 cfg.timing.eventDuration = 0.79; % .86 second From 9de888615e2806159d060b3166439409fd2786f6 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 17:36:27 +0100 Subject: [PATCH 40/64] fix tests --- tests/data/config_MT.mat | Bin 1519 -> 1519 bytes tests/data/config_MT_MST.mat | Bin 1631 -> 1631 bytes tests/test_checkParameters.m | 8 ++++---- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/data/config_MT.mat b/tests/data/config_MT.mat index 847eb47f89e574acc202d90e01bc38320bff3369..9a3f2d81911d5e948ad2f10732c2bfe7b09808ab 100644 GIT binary patch delta 95 zcmV-l0HFWx3-1e%G#FH9bs$Y)av(7`ATc*OGc-CiFd#B8GBS}-BavVQk#tlB@Y=0F zzd*6h&H(}Uvz-D20ReBbq607j9kGz!n|S{K00960V`N}pV1!~2U;?s0Yyj}L`kgfj BBt`%L delta 95 zcmV-l0HFWx3-1e%G#FQ9WFSppav&f%ATlsIFgQ9iHXt%EGBS}-BavVQk#tlBFwm)6 zKSHt2&H(|Bvz-D20Riu`q607j9k!6(n|S{K00960V`N}pV1!~2U;?s0Yyjz(`i<;h BBHI7} diff --git a/tests/data/config_MT_MST.mat b/tests/data/config_MT_MST.mat index 60a11e83d56d4f960d057318e526fc6bd925cb7a..0ebb9648e082c1941b1d58a9914a07626f51f1c8 100644 GIT binary patch delta 58 zcmcc5bDw8|i9|?7se*4}k%FN)5Lp?USeY6q7#SEDO$=0?n83QRNlH05TF>0sx8dQ5; NWlv&esCuQ|3IGcZ5}5!1 diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m index 9eefe82..4e96d9a 100644 --- a/tests/test_checkParameters.m +++ b/tests/test_checkParameters.m @@ -112,8 +112,8 @@ function test_checkParameters_MT() cfg = removeDirFieldForGithubAction(cfg); % uncomment for update default config .mat - % expected = cfg; - % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); + % expected = cfg; + % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); % test @@ -132,8 +132,8 @@ function test_checkParameters_MT_MST() cfg = removeDirFieldForGithubAction(cfg); % uncomment for update default config .mat - % expected = cfg; - % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); + % expected = cfg; + % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); % test From 425c9a2f43fb2e83dcec21a150e4b8fc402ea9d3 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 18:51:44 +0100 Subject: [PATCH 41/64] switch to MST for testing --- cfgMST.m | 29 +++++++++++++++++++++++++++++ main.m | 4 ++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/cfgMST.m b/cfgMST.m index 3c7d9ae..2a8411d 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -12,4 +12,33 @@ % on macs is 0.3 cfg.timing.eventDuration = 0.6; % 0.6 seconds + %% variable FOV info + % in case the field of view is not properly centered or obstructed + % + % see https://github.com/cpp-lln-lab/estimate_visual_FOV.git + % + % set up configuration: ensure that the following fields are the same + % as when you ran the estimate_visual_FOV script + % + % cfg.testingDevice + % cfg.screen.monitorDistance + % cfg.screen.monitorWidth + % + % + % Field of view in DEGREES OF VISUAL ANGLES: + % top left: 8.32304 1.60312 + % bottom right: 11.6757 3.49172 + % + % Field of view in DEGREES OF VISUAL ANGLES: + % width: 1.8886 + % height: 3.35264 + % + % fixation cross displacement in degrees of visual angles + % cfg.fixation.xDisplacement = 0; + % cfg.fixation.yDisplacement = 0; + + % cfg.design.xDisplacementFixation = 3; + % cfg.design.xDisplacementAperture = 7; + % cfg.aperture.width = 7; + end diff --git a/main.m b/main.m index 60fc70e..5a9830b 100644 --- a/main.m +++ b/main.m @@ -24,10 +24,10 @@ cfg.dot.speed = 7.5; %% Run MT+ localizer -cfg = cfgMT(cfg); +% cfg = cfgMT(cfg); %% Run MT/MST localizer -% cfg = cfgMST(cfg); +cfg = cfgMST(cfg); cfg = checkParameters(cfg); From bedfed8b8fcfc52d2906d3caa12cdfa0bde6d6f8 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 19:26:35 +0100 Subject: [PATCH 42/64] MST: add fixation and dor position to MST config --- cfgMST.m | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cfgMST.m b/cfgMST.m index 2a8411d..a6dfcd2 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -37,8 +37,9 @@ % cfg.fixation.xDisplacement = 0; % cfg.fixation.yDisplacement = 0; - % cfg.design.xDisplacementFixation = 3; - % cfg.design.xDisplacementAperture = 7; - % cfg.aperture.width = 7; + cfg.design.xDisplacementFixation = 3; + + cfg.aperture.width = 6; + cfg.design.xDisplacementAperture = 6; end From 5158b97d704511b2183a98183899aac97e069a20 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 19:28:18 +0100 Subject: [PATCH 43/64] add some post init --- subfun/postInitializationSetup.m | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/subfun/postInitializationSetup.m b/subfun/postInitializationSetup.m index 0a2d63b..07fbf17 100644 --- a/subfun/postInitializationSetup.m +++ b/subfun/postInitializationSetup.m @@ -10,4 +10,17 @@ cfg = postInitDots(cfg); + % TODO transfer those if blocks into 'degToPix' (and similarly into pixToDeg) + % TODO this kind of generic post initialization can be done systematically at end of initPTB + if isfield(cfg.fixation, 'xDisplacement') + cfg.fixation = degToPix('xDisplacement', cfg.fixation, cfg); + end + if isfield(cfg.fixation, 'yDisplacement') + cfg.fixation = degToPix('yDisplacement', cfg.fixation, cfg); + end + + if isfield(cfg.design, 'xDisplacementAperture') + cfg.design = degToPix('xDisplacementAperture', cfg.design, cfg); + end + end From 56cf2bf011aab191c964fe2a95f64d76411c5079 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 19:40:32 +0100 Subject: [PATCH 44/64] refactor preTrialSetup and prepare for adapting FOV --- subfun/preTrialSetup.m | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/subfun/preTrialSetup.m b/subfun/preTrialSetup.m index 76a27aa..85d6965 100644 --- a/subfun/preTrialSetup.m +++ b/subfun/preTrialSetup.m @@ -34,26 +34,36 @@ thisEvent.fixationPosition = cfg.design.blockFixationPosition{iBlock}; + % cfg.aperture.xPosPix = cfg.design.xDisplacementAperturePix; + switch thisEvent.fixationPosition case 'fixation_right' cfg.aperture.xPosPix = -abs(cfg.aperture.xPosPix); - - thisEvent.dotCenterXPosPix = cfg.aperture.xPosPix; - thisFixation.fixation.xDisplacement = cfg.design.xDisplacementFixation; - thisFixation = initFixation(thisFixation); case 'fixation_left' cfg.aperture.xPosPix = +abs(cfg.aperture.xPosPix); + thisFixation.fixation.xDisplacement = -cfg.design.xDisplacementFixation; - thisEvent.dotCenterXPosPix = cfg.aperture.xPosPix; + otherwise - thisFixation.fixation.xDisplacement = -cfg.design.xDisplacementFixation; - thisFixation = initFixation(thisFixation); + error('WTF'); end + thisEvent.dotCenterXPosPix = cfg.aperture.xPosPix; + + if isfield(cfg.fixation, 'xDisplacementPix') + thisEvent.dotCenterXPosPix = thisEvent.dotCenterXPosPix + cfg.fixation.xDisplacementPix; + thisFixation.fixation.xDisplacement = thisFixation.fixation.xDisplacement + ... + cfg.fixation.xDisplacementPix; + end + if isfield(cfg.fixation, 'yDisplacementPix') + end + + thisFixation = initFixation(thisFixation); + end varargout = {thisEvent, thisFixation, cfg}; From f92ed0ac8477de664e30347e6762456ca063c492 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 21:17:05 +0100 Subject: [PATCH 45/64] start implementing FOV change on MST --- cfgMST.m | 5 +++-- subfun/defaults/checkParameters.m | 2 +- subfun/preTrialSetup.m | 9 ++++++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/cfgMST.m b/cfgMST.m index a6dfcd2..7e9e4a4 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -34,12 +34,13 @@ % height: 3.35264 % % fixation cross displacement in degrees of visual angles - % cfg.fixation.xDisplacement = 0; + % this will also shift the whole FOV + cfg.fixation.xDisplacement = 0; % cfg.fixation.yDisplacement = 0; cfg.design.xDisplacementFixation = 3; cfg.aperture.width = 6; - cfg.design.xDisplacementAperture = 6; + cfg.design.xDisplacementAperture = 3; end diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 4dfb647..4ef85ce 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -177,7 +177,7 @@ fieldsToSet.aperture.type = 'circle'; fieldsToSet.aperture.width = 7; % if left empty it will take the screen height - fieldsToSet.aperture.xPos = fieldsToSet.design.xDisplacementAperture; + fieldsToSet.aperture.xPos = 0; case 'mt' diff --git a/subfun/preTrialSetup.m b/subfun/preTrialSetup.m index 85d6965..279190d 100644 --- a/subfun/preTrialSetup.m +++ b/subfun/preTrialSetup.m @@ -34,7 +34,8 @@ thisEvent.fixationPosition = cfg.design.blockFixationPosition{iBlock}; - % cfg.aperture.xPosPix = cfg.design.xDisplacementAperturePix; + cfg.aperture.xPos = cfg.design.xDisplacementAperture; + cfg.aperture = degToPix('xPos', cfg.aperture, cfg); switch thisEvent.fixationPosition @@ -56,12 +57,14 @@ if isfield(cfg.fixation, 'xDisplacementPix') thisEvent.dotCenterXPosPix = thisEvent.dotCenterXPosPix + cfg.fixation.xDisplacementPix; - thisFixation.fixation.xDisplacement = thisFixation.fixation.xDisplacement + ... - cfg.fixation.xDisplacementPix; + % thisFixation.fixation.xDisplacement = thisFixation.fixation.xDisplacement + ... + % cfg.fixation.xDisplacementPix; end if isfield(cfg.fixation, 'yDisplacementPix') end + thisFixation.fixation.allCoords; + thisFixation = initFixation(thisFixation); end From cdb8808360d3b5eab4fb6dfbc0ce510575a494b5 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 21:20:15 +0100 Subject: [PATCH 46/64] start implementing FOV change on MST --- subfun/preTrialSetup.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/subfun/preTrialSetup.m b/subfun/preTrialSetup.m index 279190d..0420338 100644 --- a/subfun/preTrialSetup.m +++ b/subfun/preTrialSetup.m @@ -34,8 +34,13 @@ thisEvent.fixationPosition = cfg.design.blockFixationPosition{iBlock}; + % This is necessary because where the dot aperture is drawn is set in cfg + % So we "reset" that pixel value from the value in degrees cfg.aperture.xPos = cfg.design.xDisplacementAperture; cfg.aperture = degToPix('xPos', cfg.aperture, cfg); + if isfield(cfg.fixation, 'xDisplacementPix') + cfg.aperture.xPosPix = cfg.aperture.xPosPix + cfg.fixation.xDisplacementPix; + end switch thisEvent.fixationPosition From cf4f396505f5caef08cc30b5760519aac57819b1 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 21:33:24 +0100 Subject: [PATCH 47/64] move dots and aperture according to FOV --- cfgMST.m | 2 +- subfun/preTrialSetup.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cfgMST.m b/cfgMST.m index 7e9e4a4..55d7944 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -35,7 +35,7 @@ % % fixation cross displacement in degrees of visual angles % this will also shift the whole FOV - cfg.fixation.xDisplacement = 0; + cfg.fixation.xDisplacement = 3; % cfg.fixation.yDisplacement = 0; cfg.design.xDisplacementFixation = 3; diff --git a/subfun/preTrialSetup.m b/subfun/preTrialSetup.m index 0420338..a5b4ca2 100644 --- a/subfun/preTrialSetup.m +++ b/subfun/preTrialSetup.m @@ -61,10 +61,10 @@ thisEvent.dotCenterXPosPix = cfg.aperture.xPosPix; if isfield(cfg.fixation, 'xDisplacementPix') - thisEvent.dotCenterXPosPix = thisEvent.dotCenterXPosPix + cfg.fixation.xDisplacementPix; % thisFixation.fixation.xDisplacement = thisFixation.fixation.xDisplacement + ... % cfg.fixation.xDisplacementPix; end + if isfield(cfg.fixation, 'yDisplacementPix') end From 09cd09da8fafc71b98efedce45fe0d711dcc90d0 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 21:36:12 +0100 Subject: [PATCH 48/64] fix direction of FOV correction --- subfun/preTrialSetup.m | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/subfun/preTrialSetup.m b/subfun/preTrialSetup.m index a5b4ca2..077104e 100644 --- a/subfun/preTrialSetup.m +++ b/subfun/preTrialSetup.m @@ -38,9 +38,6 @@ % So we "reset" that pixel value from the value in degrees cfg.aperture.xPos = cfg.design.xDisplacementAperture; cfg.aperture = degToPix('xPos', cfg.aperture, cfg); - if isfield(cfg.fixation, 'xDisplacementPix') - cfg.aperture.xPosPix = cfg.aperture.xPosPix + cfg.fixation.xDisplacementPix; - end switch thisEvent.fixationPosition @@ -58,13 +55,17 @@ end - thisEvent.dotCenterXPosPix = cfg.aperture.xPosPix; - if isfield(cfg.fixation, 'xDisplacementPix') - % thisFixation.fixation.xDisplacement = thisFixation.fixation.xDisplacement + ... - % cfg.fixation.xDisplacementPix; + cfg.aperture.xPosPix = cfg.aperture.xPosPix + cfg.fixation.xDisplacementPix; end + thisEvent.dotCenterXPosPix = cfg.aperture.xPosPix; + + % if isfield(cfg.fixation, 'xDisplacementPix') + % thisFixation.fixation.xDisplacement = thisFixation.fixation.xDisplacement + ... + % cfg.fixation.xDisplacementPix; + % end + if isfield(cfg.fixation, 'yDisplacementPix') end From fd30f2583290516036833e93c953166dc221156b Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 21:46:37 +0100 Subject: [PATCH 49/64] move cross with FOV --- cfgMST.m | 8 ++++---- subfun/preTrialSetup.m | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cfgMST.m b/cfgMST.m index 55d7944..6e96405 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -35,12 +35,12 @@ % % fixation cross displacement in degrees of visual angles % this will also shift the whole FOV - cfg.fixation.xDisplacement = 3; + cfg.fixation.xDisplacement = -2; % cfg.fixation.yDisplacement = 0; - cfg.design.xDisplacementFixation = 3; + cfg.design.xDisplacementFixation = 2; - cfg.aperture.width = 6; - cfg.design.xDisplacementAperture = 3; + cfg.aperture.width = 4; + cfg.design.xDisplacementAperture = 4; end diff --git a/subfun/preTrialSetup.m b/subfun/preTrialSetup.m index 077104e..9df1cae 100644 --- a/subfun/preTrialSetup.m +++ b/subfun/preTrialSetup.m @@ -61,10 +61,10 @@ thisEvent.dotCenterXPosPix = cfg.aperture.xPosPix; - % if isfield(cfg.fixation, 'xDisplacementPix') - % thisFixation.fixation.xDisplacement = thisFixation.fixation.xDisplacement + ... - % cfg.fixation.xDisplacementPix; - % end + if isfield(cfg.fixation, 'xDisplacementPix') + thisFixation.fixation.xDisplacement = thisFixation.fixation.xDisplacement + ... + cfg.fixation.xDisplacement; + end if isfield(cfg.fixation, 'yDisplacementPix') end From 370754bb379089d5a313b406d3cd1955298bd55a Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 21:48:10 +0100 Subject: [PATCH 50/64] refactor --- subfun/preTrialSetup.m | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/subfun/preTrialSetup.m b/subfun/preTrialSetup.m index 9df1cae..b87ca30 100644 --- a/subfun/preTrialSetup.m +++ b/subfun/preTrialSetup.m @@ -57,15 +57,12 @@ if isfield(cfg.fixation, 'xDisplacementPix') cfg.aperture.xPosPix = cfg.aperture.xPosPix + cfg.fixation.xDisplacementPix; + thisFixation.fixation.xDisplacement = thisFixation.fixation.xDisplacement + ... + cfg.fixation.xDisplacement; end thisEvent.dotCenterXPosPix = cfg.aperture.xPosPix; - if isfield(cfg.fixation, 'xDisplacementPix') - thisFixation.fixation.xDisplacement = thisFixation.fixation.xDisplacement + ... - cfg.fixation.xDisplacement; - end - if isfield(cfg.fixation, 'yDisplacementPix') end From b6098c7ff293d60409029b1f3363e6854b787523 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 21:49:11 +0100 Subject: [PATCH 51/64] update test data --- tests/data/config_MT.mat | Bin 1519 -> 1519 bytes tests/data/config_MT_MST.mat | Bin 1631 -> 1628 bytes tests/test_checkParameters.m | 8 ++++---- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/data/config_MT.mat b/tests/data/config_MT.mat index 9a3f2d81911d5e948ad2f10732c2bfe7b09808ab..781780280ccdfa79c53a0d20d7417f5591f7e744 100644 GIT binary patch delta 30 lcmaFQ{hoV*J+G0Wm5GIwiK&8-fsxU~K;?-EtQ$+JSpkp12?GEC delta 30 lcmaFQ{hoV*J+Gm;m9dGHseyu#fsxU~K;?-EtQ$+JSpkoa2>$>8 diff --git a/tests/data/config_MT_MST.mat b/tests/data/config_MT_MST.mat index 0ebb9648e082c1941b1d58a9914a07626f51f1c8..dbeb17e942eebe9b112ed017aec2be2ffc2a857d 100644 GIT binary patch delta 570 zcmV-A0>%B`4BQNmKMgW5Iy5*sG&LYHFfuZcQ6rIH1(9?R0o1XDQvrX|;~k-TdRS4k z{P#&VZ&UtSqq_W`YOcdF%Fffl@m{j`B%i-(&O@KSwy1j{<23fi`!gzRd^FKHlxL^}%X;lrVM{w$H+|@TUHX{B<$;YyEvw zbKVaXE&q=p0*>W?x_EzBVgD7!q2)>3(?-2<+*9;{sIIU*eM;icM{XdV(_U^6>m%FG z?1y+9t5ynA3v@NWJb%9Dorh*_9?f@;o7l>mB)FF~aBHGI*2?+ge6#p(GmeSnyeE^1 zmHoY|=#NomcZ4OTPROED93nP!f()k!6%A-BPxp^b7^Mr$N(sW9u!~r5Q?KezKIBM4^pRIC=n$Qp>jR;aS(tnPV);Y z&O2hlWR%H9jEl|g9m7d+aK&rLwAkqHp(U=&{?@^5)W8g_srJ|3$@2U2MdEI=;{$jC I1SD=Jl52J&-T(jq delta 573 zcmV-D0>b^=4BrfpKMgTAIx{pnH83DDFfuZcQ6rIH1(9?R0oSpGQvrW#D%=Rw)5D6Q z<-bp|d7JXr8uR6A+)p*vVHsuT>EL)T*?W@DUp42U&tF^Ay^wJldvePsYuOe1tpj4$ z;wU)=lK)p|_PTzG^6M(;FP?RPixc1G185)bcG~)2wLMB0I}6)q;aPZ7e?|VfnEbW= zzNtCyhl-Z}#}EO>azKAwJgl()isR7oB<^XW-Z<_l`ao1y*q%Nmap)sA5YK5ZH;DC- z?PvBwJdRZ>g{cL)8epD3-}BBxGdGXsyT?szfQ6FpN{Bgcn{I?m$#B$z~ z$;8V3-c|I+D6>1l5>qE+(J2lQ8#+NCA49BHe&dkGR=X$ zqYOiV*wW!muJuJ0WJo>yVCXNKZ>ASh53>Iznr)BQjs7h~Yki%Iz+}Ly@p(|-^T6a2 zK#wDPzkkp@KRAEsRy#)x1K$)9UN?IG*vh4jkDVZuJD8#O;{LOhm+msVIORTix45Py zPRC)_HT~cdMZXc1MUc5Pvv_0x6haS*FMJ5a(I4ML1h@yOQ!kW=l88{b9{V^5z!#_a z1r_HVF<~;wWFyAKX7`Taq&T?ZHDp?B^!LybS7v|f;5H9x;MP?8>+fXw{ke@?tsk@C L19$=if(j> Date: Thu, 17 Mar 2022 22:06:21 +0100 Subject: [PATCH 52/64] make it possible to move dot texture vertically --- cfgMST.m | 12 ++++++------ lib/CPP_PTB | 2 +- subfun/preTrialSetup.m | 5 +++++ tests/test_checkParameters.m | 8 ++++---- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/cfgMST.m b/cfgMST.m index 6e96405..80d027b 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -26,17 +26,17 @@ % % % Field of view in DEGREES OF VISUAL ANGLES: - % top left: 8.32304 1.60312 - % bottom right: 11.6757 3.49172 + % top left: 8.0 1.0 + % bottom right: 11.0 3.0 % % Field of view in DEGREES OF VISUAL ANGLES: - % width: 1.8886 - % height: 3.35264 + % width: 1.8 + % height: 3.3 % % fixation cross displacement in degrees of visual angles % this will also shift the whole FOV - cfg.fixation.xDisplacement = -2; - % cfg.fixation.yDisplacement = 0; + % cfg.fixation.xDisplacement = 0; + cfg.fixation.yDisplacement = 1; cfg.design.xDisplacementFixation = 2; diff --git a/lib/CPP_PTB b/lib/CPP_PTB index 88af543..d4da2b6 160000 --- a/lib/CPP_PTB +++ b/lib/CPP_PTB @@ -1 +1 @@ -Subproject commit 88af543514b3c29ef5c95f64ec12c1c202e33763 +Subproject commit d4da2b6c28638107ebe06552427582d242d6a018 diff --git a/subfun/preTrialSetup.m b/subfun/preTrialSetup.m index b87ca30..4eb02c4 100644 --- a/subfun/preTrialSetup.m +++ b/subfun/preTrialSetup.m @@ -61,6 +61,11 @@ cfg.fixation.xDisplacement; end + if isfield(cfg.fixation, 'yDisplacementPix') + cfg.aperture.yPosPix = cfg.fixation.yDisplacementPix; + thisEvent.dotCenterYPosPix = cfg.aperture.yPosPix; + end + thisEvent.dotCenterXPosPix = cfg.aperture.xPosPix; if isfield(cfg.fixation, 'yDisplacementPix') diff --git a/tests/test_checkParameters.m b/tests/test_checkParameters.m index 5990007..b13c997 100644 --- a/tests/test_checkParameters.m +++ b/tests/test_checkParameters.m @@ -112,8 +112,8 @@ function test_checkParameters_MT() cfg = removeDirFieldForGithubAction(cfg); % uncomment for update default config .mat -% expected = cfg; -% save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); + % expected = cfg; + % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT.mat'), 'expected'); % test @@ -132,8 +132,8 @@ function test_checkParameters_MT_MST() cfg = removeDirFieldForGithubAction(cfg); % uncomment for update default config .mat -% expected = cfg; -% save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); + % expected = cfg; + % save(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); load(fullfile(fileparts(mfilename('fullpath')), 'data', 'config_MT_MST.mat'), 'expected'); % test From 099170070d431ddf076f9035e538d7f27e69252e Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 22:14:08 +0100 Subject: [PATCH 53/64] add comments --- cfgMST.m | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/cfgMST.m b/cfgMST.m index 80d027b..6883382 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -23,24 +23,24 @@ % cfg.testingDevice % cfg.screen.monitorDistance % cfg.screen.monitorWidth - % - % - % Field of view in DEGREES OF VISUAL ANGLES: - % top left: 8.0 1.0 - % bottom right: 11.0 3.0 - % - % Field of view in DEGREES OF VISUAL ANGLES: - % width: 1.8 - % height: 3.3 - % + + + % Field of view in DEGREES OF VISUAL ANGLES + % fixation cross displacement in degrees of visual angles % this will also shift the whole FOV - % cfg.fixation.xDisplacement = 0; - cfg.fixation.yDisplacement = 1; + cfg.fixation.xDisplacement = 0; + cfg.fixation.yDisplacement = 0; + + % determines position of the fixation cross on the right / left + % should be a bit less than the: ( width of FOV ) / 2 + cfg.design.xDisplacementFixation = 5; - cfg.design.xDisplacementFixation = 2; + % determines position of the dots on the left / + % should be a bit less than the: ( width of FOV ) / 2 + cfg.design.xDisplacementAperture = 5; - cfg.aperture.width = 4; - cfg.design.xDisplacementAperture = 4; + % determines the width of the dot circle + cfg.aperture.width = 1; end From 23fda424b624896db4bc5277fa2e897ec4a0afee Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Thu, 17 Mar 2022 22:21:50 +0100 Subject: [PATCH 54/64] lint --- cfgMST.m | 1 - 1 file changed, 1 deletion(-) diff --git a/cfgMST.m b/cfgMST.m index 6883382..2e77150 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -24,7 +24,6 @@ % cfg.screen.monitorDistance % cfg.screen.monitorWidth - % Field of view in DEGREES OF VISUAL ANGLES % fixation cross displacement in degrees of visual angles From 4989054155edc9740951e06f51c7d1e07c4cd540 Mon Sep 17 00:00:00 2001 From: marcobarilari Date: Thu, 17 Mar 2022 22:40:15 +0100 Subject: [PATCH 55/64] Auto stash before merge of "update_config_FOV" and "Remi-Gau/update_config_FOV" --- cfgMST.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cfgMST.m b/cfgMST.m index 2e77150..6fde696 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -28,8 +28,8 @@ % fixation cross displacement in degrees of visual angles % this will also shift the whole FOV - cfg.fixation.xDisplacement = 0; - cfg.fixation.yDisplacement = 0; + cfg.fixation.xDisplacement = -3.676540; + cfg.fixation.yDisplacement = -0.499724; % determines position of the fixation cross on the right / left % should be a bit less than the: ( width of FOV ) / 2 From 84c6845f561c00e11cee86b75fa82b524c5a7327 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Fri, 18 Mar 2022 10:24:25 +0100 Subject: [PATCH 56/64] update doc --- cfgMST.m | 11 +++++------ cfgMT.m | 8 +++++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/cfgMST.m b/cfgMST.m index 2e77150..2896541 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -24,22 +24,21 @@ % cfg.screen.monitorDistance % cfg.screen.monitorWidth - % Field of view in DEGREES OF VISUAL ANGLES - % fixation cross displacement in degrees of visual angles - % this will also shift the whole FOV + % this will also shift the whole FOV relative to the center of the screen + % Note: negative values will move things to the left and up. cfg.fixation.xDisplacement = 0; cfg.fixation.yDisplacement = 0; % determines position of the fixation cross on the right / left % should be a bit less than the: ( width of FOV ) / 2 - cfg.design.xDisplacementFixation = 5; + cfg.design.xDisplacementFixation = 3; % determines position of the dots on the left / % should be a bit less than the: ( width of FOV ) / 2 - cfg.design.xDisplacementAperture = 5; + cfg.design.xDisplacementAperture = 7; % determines the width of the dot circle - cfg.aperture.width = 1; + cfg.aperture.width = 7; end diff --git a/cfgMT.m b/cfgMT.m index 3a59044..0172a64 100644 --- a/cfgMT.m +++ b/cfgMT.m @@ -31,8 +31,10 @@ % cfg.screen.monitorWidth % fixation cross displacement in degrees of visual angles - % - % cfg.fixation.xDisplacement = FIXME; - % cfg.fixation.yDisplacement = FIXME; + % this will also shift the whole FOV relative to the center of the screen + % Note: negative values will move things to the left and up. + + cfg.fixation.xDisplacement = 0; + cfg.fixation.yDisplacement = 0; end From 0f78a539b42ce8d97505f886dee5121f7dc08de8 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Fri, 18 Mar 2022 11:11:56 +0100 Subject: [PATCH 57/64] move static reseed config back to visual localizer --- lib/CPP_PTB | 2 +- subfun/defaults/checkParameters.m | 2 ++ tests/data/config_MT.mat | Bin 1519 -> 1520 bytes tests/data/config_MT_MST.mat | Bin 1628 -> 1624 bytes tests/test_checkParameters.m | 12 +++++++----- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/CPP_PTB b/lib/CPP_PTB index d4da2b6..ac16cd4 160000 --- a/lib/CPP_PTB +++ b/lib/CPP_PTB @@ -1 +1 @@ -Subproject commit d4da2b6c28638107ebe06552427582d242d6a018 +Subproject commit ac16cd4eb2498e1c920052628537e693593a7099 diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 4ef85ce..03367dd 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -63,6 +63,8 @@ %% Visual Stimulation fieldsToSet.dot = cppPtbDefaults('dot'); fieldsToSet.dot.color = fieldsToSet.color.white; + % Static dots should change position at each event or not + fieldsToSet.staticReSeed = true; %% Task(s) diff --git a/tests/data/config_MT.mat b/tests/data/config_MT.mat index 781780280ccdfa79c53a0d20d7417f5591f7e744..c370cdfe6b72fca0241601420b6f0876f12b77bd 100644 GIT binary patch delta 1439 zcmV;Q1z`H`3-Ak&G#Ey5X&_Buav(7{ATcpIFf=+bG$1lCGBS}-BavVQk#rD$XaxWO zc$~~xy>1*g5aykJ64{1)ab-8bRe=$}K!P;tEK4WDf*?VV4p9mL!v2g-g!ae{$(8P0 z={1rkaF-Nr(xnZM0B+L-$P1)Q5kMii5upUiyyX(lHp{c~oy9A^N84N}-l*aGFBzZ`hZ1)&pt1IMv%h$^Qo3{5?NI z?)S{`mrr^i{^}2S0bt6VOKPKH{a!h91i*2rayM9*<-}}D7>h}Or5Liv9 zkB2bZj>_|J?eB5B**xwVyeoSseb9i>jKnBR(<4j}9|lRHE-L0##~-zBi8pGvZ$2^jRQ7~ML4sexBqkVAwV8XEfpKQ}jlMpo zbR)qKreX>bZe0L>5quxmhLm?MZxn99jI48>wVio(B--uQvk&(iY-{xTwc@SM(03QP z`f{wTAt^!_CFhkRr&W?;=WOq*@oO{mE~9C^3g>Z*KR^FUe&_f-G#~G(q5VBF_y_gg zDHJZ)Z4o^K1|)*=gBS?MV*EBE!KaWPLZy~6no_3LX9p*L3B=M)pEGI1h)ct-(*0JH zTr{6`y6?%W@(WFPYYliS=KlBJsrLKRdE!BTy}#7b`>ylgMf=_Rv{kxa$3Lt%<2we& z)-g7abEhOnVQu$47<~P#kmIxOZGKaSzf|HY49auY)L+F9wZpH+|ER=QSmuL!YAe=R z$4-f_x($baW$L7l8(%p#k9OtUc3!jA(66o<9HO!Z)2MG#;RF*nQW@vI%9KTMvLl;` z+BWK8p2~0gm=n(WvAD_$(G=K}J#Z=GdT@ay`uyuF#rpZ*uTCU&>J(9G`c z8Lafllvi%09i3pgwH^jMmBAov(9z^tjq>$-TZfx}&-Sv4?KDHJbl>mtE)UgDi6^G&>d5$FmNx-N3&AZWxjbf z^)E}v-yi<=t7`u|{SeOA9~*uj8#gF@LrSoqOrD4$P)UlxNA~!XK8_|?5h(hs^NA<# zk>S06K{xv;_k6t#Kl;Av)U66$qxuT+x6>f{wsPK0>a&j<+Nq5LKbJkunDhUbVKCYY zCuN%H$gj}npTGU&73bJ>UcX^|>=<`_6t?mIi3!wn9yrIoR>duMJ#bOi*H~24^=Hky zD&M%kJPVTUr2O_F|9@cCxw0_DTbTSmWxe5ccd&7usx#;L%PCcfMqZ}jVw}KS`Npj8 zR8wIj toTonXUqrX#Pv(hFzS8Z_x%AfI{R;p9|NmoTfB+^2Mj&Kh002k#`aG9%--`eM delta 1438 zcmV;P1!4N|3-1e%G#FH9bs$Y)av(7`ATlvJG&njmH6SuDGBS}-BavVQk#rD$X9WNN zc$~~xKW`g16sIIRt&_k}GbKx*sR#-LXwk)699s@z7&Z)Bs5=-i?$5JK_(Wbwo-JkS z*JwXM#tvD!b!>qa@Y=0Fzd*+h1zeIx>Zr@rx}(}S1gN{;-TmI^hoj43Kgh-2xy?0XXg9=Qur_kZ1s0s0Q%tRH`iAi+~M5xR{@RyYhwPVKVH) z1&%=D@k|E=9?91Qz5o_dJ{?}PD(hdU-n`|{m-M#^KUDH3sT6jJV{wMY`;@zKKXc?R zRmfd()oDH|+ni!Ri{*YW*wi`ucxtHPdg$O}*be z*w!|u ziMpw1R~>)Ux+UJY;kx8U+b{1=AQ{MAc&MV+O{V zL{NSa1L0Uq-ex5D6!J}|R8mG$%GCJm;3R=q+UW}>jTmu%Y4}yT&1@XNVYzYTaCusM z#_xeAugYIE;jJ~`t(fQEeXGiE&lZUj{q_F*mR?`K+GKxu+5Y!+-zq(?<8M}+@4E)a z*3mYQbGIZ%VZDy}F#Pg)A;-s$*nFuDf4Rh07}QQsQ-2jd)Eh`W{s$$#!ZM%SQ%k$f zICe{XRc&~GEmJYQefi3pX=Zo# z4OaSO3N4q?j!xLzvmypOmBA%!(DC$MedX)-whlLcpYLximcRP)dUN&}ci*TJN4w+M zm3PdOH}vF9Jb9rfFZSdSPu?p}9(eNXe)_28cTV#Zsk}xXpzfHH4+HnY{A*S^#aXPK zP5sL<^7n_o{-Vm?&)$dq_4|hNW8(&;Z$t?el*t`Y1S;t<_{eUb(#O#xD*{EIaX#_n zJvO|5D|EA;a`)HU@T2eQ+`EMqKlcuzuPgO8Ik$b%(B5o3_o=LL#+?6UM!|S5oF3oI zMsS5b|NQL-uXx3d^ZE_rW5037M`0VspO}D4=W`3JPj%?!jt4Hz`!yC7=l%2AU6nUn zV4ej@Z+a~EKL2kpZ-3~_@H*4~S=JlQgN@g9)cJFshn!NCFyzNKTuc&JC~ufIPgUoH zn>1q>SZ@z5E61abeLwW%S(|_Dx&B|sy1lWDin4v^A|P=elE56X>5RT_-Gz#?h4a>@ s{Y&U}{K+D5#uvK$v5?-Ic>e$Z0RR7EWME)mgklh20 diff --git a/tests/data/config_MT_MST.mat b/tests/data/config_MT_MST.mat index dbeb17e942eebe9b112ed017aec2be2ffc2a857d..a3c4e61979d4297b43803442cbd15bb24c718c7f 100644 GIT binary patch delta 1544 zcmV+j2KV{g4A=~iG#Ey5X&_Buav(7{ATcpIFf=+bG$1lCGBS}-BavVQk#rD$&;z}YcV1q|Wq(v#JEzxUJ0<`pK{@x=W`94UkB81+2hS0Kj zek5uGrDaLc3r3YR3?uM3_)BPi5w%qNwfJ!&pgg9a;K+%6Oi)%_>@$Nz9tj9FXdm3T zm!lc(g$7Ny2^Ztw)Y&3IJO~rMFoG_1ybDlF&+*XVm`phIu@74@Wm@P3j9lVSU;jU# zILAM7Jn%P1U5a}>pbRmO0vO|A7dSc|g%b-UAfbo333EIUe`oY1P?xZYy3wlqS*W&-Y5QW*SJICp|4}5EU16X1 z(eRKklkXbJ_%4?4T{if(6zyT^1(4#uH1Nwa#?=sScaR-Uk9Uab>0wFH^68Uo-lqJO zMs@kW)Le%}l-bw*(QdMT7bTy+YtBR4V_VeSkZ~G&(gc#V?27%?0kMm5l$eF&{|%bH zuAig)x=Q-1XC2_e1GIS`+DF@+wl=i3M+sx6Vf!>Z4R7kN$X^$ezt-P%&3Qjmw0s^x z1RTo&b@8CW{wt0{%agdLje6s_r|5lAUEzy*l*FNr+(5jiz1$#w)+XD_{E2uSsa6UT zk95_?Ja6B#?4g;PNAvyT#TX{`$k`##O(Ek#w`N`>!wfr^MZ%O}AP^fm-O07? zWJ!nA!%v3(viW9uG4&w(ucPVyc-83NQnc3BnMhRnyc(Ye1wIcvt(gW?}Pgu?VkHxU6ohcu`cN<>LSs9cXd90cGCYu=&4-VqZnqfGXV z(??cp^z_gYSLSEy;MQv3R#f||?`8Sx`8@fxz1-g`$$eXVebJb1*JgVaKe%G_Zz z(WC~Sy9GXfl1}!02YO#`WPEJ=j6OG3!7ml?k_H*yD#|azyDBVJ!QUz1B`wa`2htR) z=&@D6%Ua9_Z29Q>36sxlpA*+=`c)nOT~zd73DwnC3;_<|M4sdi`#U+cmf)-UwY0pR%b)&#AGkXEZoOuHeqYg29xzXs(q3|4 zHSf?Uut;Rfut|oKciGFjwv zoNtK>Epaa`abStl@$~V6-96PaBv1Lt#qyrI`BCJ7oA#!KTdeuUS=YZTA$x!L=O42C z^ZY}9h_64^Tpyh`NO=PiVos=th}@Bf6h)ut@F{#83F0hKw9)gKCGLsBy++ghlo?-d z!;iiTT$w%=N^o`VtLE9Kj`wZpxa-_^Kdre>bsqSIsD4b1?_2|Cc;HShvv}bSOv|%B zzx`~L=V(2zPtlL=W9lb&zoinjd`98H?a~*V^C-3dk^UFDr2aWWahVfAVbDcM4tZ8j3eq@Q$d%o^>rcV_8ov6E;yQrk>9+x(IeJAX}j&Y{`4*&rF|0~JN&tphm z%}a4f%}K0eKn1B~sd*(XrA3J)AVqMHpI4k(f=xXL@By&_5VHX>2b2Z@Rw$nl34;I= uki`YnXF-BKPN?{-nIN#!o)UXW)yGPKdyT>1F#0bA7Vx#V9((K$XrYq3q?WthO1o4OhXAD=F25OaNX`sr*AYU0euB`d z`2RrE21?6{qL+*+X&6P|aqw4v&@yVN_DK9V5l|jeP;lhLJ|-wDF7}y0B98=w8nh2? z+|SVr_d|mw+=Pp9aO&)kARdMZUl>D|I^G2+rae4zI3`mL1MI_2OqmvX0b`dq)YtEa z6zBLyjtBnsxJz-r50oM1Q2=8+>;gw8HN?{$WQWt^9ie)9SW&e6_enNyQ~p|`y8NGNuER3Q z&eOs1Ub6QjpTBC(L!ZBYwy1j{<23fi`!gzRd^FKHlxL^}%X;lrVM{w$H+|@TUHX{B<$;YyEvwbKVaXE&q=p0*>W?x_DS& z{}sofmB)FF~aBHGI*2?+ge6#p(GmeSnyeE^1mHoY|=#NomcZ4OTPROED z93nP!f=nVr+E z-Nc_|C3J?63pmn$R(JOjLe7qWZVMR~x;3*R8D`YMED}c!>()k!6%A-BPxp^b7^Mr z$N(sW9u!~r5Q?KezKIBM4^pRIC=n$Qp>jR;aS(tnPV);Y&O2hlWR%H9jEl|g9m7d+ zaK&rLwAkqHp(U=&{?@^5)WEH&_SfIZ^852e;%!<4Y>z9q$cEW70VprFU z{w+oO+B?;M;B&XYN7BhT>OlX?t&ES2-O~5aD)^NGUeX}_WkvaAcvrdED)>7EyrjiF z{ZJn5Dtc@c@Uj-;3tK)qzhUyZ?R)1&O*^gQ2^SR&UqW?t$|AraoXX6=k<4iDTx6AI z40OpwLuj0%%I8<-yuPh?{=fXC&Hheq!6o>r_Ao7f*9+O<{{vTN-)+{6_wOrO$^+(! zqqLt~fXy5n1r~|u8@9=4`Ye0d+P&SAovowY#qt5Rxb_@BWBQGGd6S|(TjGgY;`)}j zu_ey6#QB!E&=U8`5(kzz?N1*s+2y^SA(=Hu64U!ClcdN)H|=h}@Bv9z~yO_bF@~3F0hJw9)gqCGLsBU8C7{ z%Ji?dVMpHvu1p_GXz}j|j`ww`{5pB?r#1JRj^{oT)sLz1y=&-<4&7;zix+ZZTAuy= z?MJJ4MeBKUhJJJ(Q$M-9mkPL&``iNOQ|1SMO?}|(`$p_+_l9}vbPwg{FX0sItEwS>p7bulxP!BSn8J>fZJqDk*y>rOn>J3Hu<^*Z%?l0RR6h$;{6S$S=-g zECJFCsd*_bsX2+245%QrEH$shrL-s!tOySB^NLeTu&D Date: Tue, 22 Mar 2022 11:25:44 +0100 Subject: [PATCH 58/64] add changes from testing session 18-03-2022 --- cfgMST.m | 2 +- cfgMT.m | 19 ++++++++++++++----- main.m | 8 +++++--- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/cfgMST.m b/cfgMST.m index 6fde696..5052843 100644 --- a/cfgMST.m +++ b/cfgMST.m @@ -40,6 +40,6 @@ cfg.design.xDisplacementAperture = 5; % determines the width of the dot circle - cfg.aperture.width = 1; + cfg.aperture.width = 7; end diff --git a/cfgMT.m b/cfgMT.m index 3a59044..748f517 100644 --- a/cfgMT.m +++ b/cfgMT.m @@ -8,15 +8,24 @@ cfg.timing.triggerIBI = 4; - cfg.mri.triggerNb = 0; - + cfg.mri.triggerNb = 5; + + % Time between events in secs + cfg.timing.ISI = 0; + % Time between blocs in secs + cfg.timing.IBI = 5.4; + % Number of seconds before the motion stimuli are presented + cfg.timing.onsetDelay = 0; + % Number of seconds after the end all the stimuli before ending the run + cfg.timing.endDelay = 0; + cfg.design.nbRepetitions = 15; cfg.design.nbEventsPerBlock = 12; % in Liege is 0.79 (tsry less) % in mcas is 0.43 - cfg.timing.eventDuration = 0.79; % .86 second + cfg.timing.eventDuration = 0.75; % .86 second %% variable FOV info % in case the field of view is not properly centered or obstructed @@ -32,7 +41,7 @@ % fixation cross displacement in degrees of visual angles % - % cfg.fixation.xDisplacement = FIXME; - % cfg.fixation.yDisplacement = FIXME; + cfg.fixation.xDisplacement = -3.676540; + cfg.fixation.yDisplacement = -0.499724; end diff --git a/main.m b/main.m index 5a9830b..8bce08c 100644 --- a/main.m +++ b/main.m @@ -13,14 +13,16 @@ cfg.verbose = 1; -cfg.debug.do = true; -cfg.debug.transpWin = true; +cfg.debug.do = false; +cfg.debug.transpWin = false; cfg.debug.smallWin = false; cfg.audio.devIdx = 5; cfg.eyeTracker.do = true; -% in liege + +% in liege 7.5 +% on Marco's mac 15 cfg.dot.speed = 7.5; %% Run MT+ localizer From 39f16f10ccf1804e3407fc6518c71bf6f3c57a01 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Tue, 22 Mar 2022 11:37:55 +0100 Subject: [PATCH 59/64] update CPP_PTB --- lib/CPP_PTB | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CPP_PTB b/lib/CPP_PTB index ac16cd4..1d93745 160000 --- a/lib/CPP_PTB +++ b/lib/CPP_PTB @@ -1 +1 @@ -Subproject commit ac16cd4eb2498e1c920052628537e693593a7099 +Subproject commit 1d937450088cd670a7d0308847aa540b455a2967 From 26cb046529d655e201338326ec6ef0a8405d9c2b Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Wed, 23 Mar 2022 16:45:24 +0100 Subject: [PATCH 60/64] fix staticReseed bug --- subfun/defaults/checkParameters.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subfun/defaults/checkParameters.m b/subfun/defaults/checkParameters.m index 03367dd..9bffb73 100755 --- a/subfun/defaults/checkParameters.m +++ b/subfun/defaults/checkParameters.m @@ -64,7 +64,7 @@ fieldsToSet.dot = cppPtbDefaults('dot'); fieldsToSet.dot.color = fieldsToSet.color.white; % Static dots should change position at each event or not - fieldsToSet.staticReSeed = true; + fieldsToSet.dot.staticReSeed = true; %% Task(s) From 22fb51fda90965fb6d6fd78f8618976cfc54da0a Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Sat, 7 May 2022 16:08:24 +0200 Subject: [PATCH 61/64] lintt --- cfgMT.m | 4 ++-- main.m | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cfgMT.m b/cfgMT.m index fd24cf7..7702270 100644 --- a/cfgMT.m +++ b/cfgMT.m @@ -9,7 +9,7 @@ cfg.timing.triggerIBI = 4; cfg.mri.triggerNb = 5; - + % Time between events in secs cfg.timing.ISI = 0; % Time between blocs in secs @@ -18,7 +18,7 @@ cfg.timing.onsetDelay = 0; % Number of seconds after the end all the stimuli before ending the run cfg.timing.endDelay = 0; - + cfg.design.nbRepetitions = 15; cfg.design.nbEventsPerBlock = 12; diff --git a/main.m b/main.m index 8bce08c..c402f87 100644 --- a/main.m +++ b/main.m @@ -13,7 +13,7 @@ cfg.verbose = 1; -cfg.debug.do = false; +cfg.debug.do = false; cfg.debug.transpWin = false; cfg.debug.smallWin = false; From ad92cedbc7d609664558310f8db5b7b90c1f28bd Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Mon, 9 May 2022 18:18:38 +0200 Subject: [PATCH 62/64] update parameters --- tests/data/config_MT.mat | Bin 1520 -> 1519 bytes tests/data/config_MT_MST.mat | Bin 1624 -> 1626 bytes tests/test_checkParameters.m | 8 ++++---- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/data/config_MT.mat b/tests/data/config_MT.mat index c370cdfe6b72fca0241601420b6f0876f12b77bd..aa67118e596dfb504bebfe84fa161bc01198f0cd 100644 GIT binary patch delta 1438 zcmV;P1!4N|3-1e%G#E{9ZXiuzc_1J;ATc;PF*Q0hHXt%EGBS}-BavVQk#rD$X9WNN zc$~~xy>A;g6sP2m)=A)~nUbZ@R0IVAwCLh3jx7f<3>$_m)Ex{M_wg(fK9LuaXG@v- zZ?u0w#tvD!b!>qa@Y=0F|ACGj3b-VX)KQmqp2vB#wyZgPzkH^RNs8xher;E_C zynZTc8|7um;FePrhEWQUfOrXiEuxNjp30vf1tu~EhK_to5)k)sKY_ z&%5^3cddCZ8t_(ReP{>guaoui)u$cTp8dYQ&fAX~uKPO%e~t>jBRwz+2v3hNL3|h_ ziMpw1R~>)Ux+UJI;kx8U+b{1(O(HNY!HQVFt#T)0)~hfVQfK7P&u7VRAHRp@<6SkhzefiDs`{Nm;ey=~(KBE` zA}GIzfp9FwZ!;2n3i&2fDk-BWWomqOaFReQ?esa5MvS(1C`+URLUFa&G&$p}pC7?n_zYj5+_y41>{LI61zV zj^GM?{`uR_Uh#?@=k*)L$A06EkHR*NKQRH9&gbS>pX$)d9S>Zb_iHRF&iiMzyDD$E zz&s0*?&MhRWB%V@*8Z?C#ao#C&$8Zd9&EgIrp}-9Jmi$Bgdsn^;bNS?TzSK+d8#@m z+@u-9z`A>ISvekc?E8Ty&)WQJ&-MRY*6odLRFv&Q7XgWTkObz4O=t8y>n>EBEu6PL s?O#N<<4@*^GrrN~@458e#QPrr0RR7EWME)mgklh201*g5aykJ64{1)ab-8bRe=$}K!P;tEK4WDf*?VV4p9mL!v2g-g!ae{$(8P0 z={1rkaF-Nr(xnZM0B+L-$P1)Q5kMii5upUiyyX(lHp{c~oy9A^N84N}-l*aGFBzZ`hZ1)&pt1IMv%h$^Qo3{5?NI z?)S{`mrr^i{^}2S0bt6VOKPKH{a!h91i*2rayM9*<-}}D7>h}Or5Liv9 zkB2bZj>_|J?eB5B**xwVyeoSseb9i>jKnBR(<4j}9|lRHE-L0##~-zBi8pGvZ$2^jRQ7~ML4sexBqkVAwV8XEfpKQ}jlMpo zbR)qKreX>bZe0L>5quxmhLm?MZxn99jI48>wVio(B--uQvk&(iY-{xTwc@SM(03QP z`f{wTAt^!_CFhkRr&W?;=WOq*@oO{mE~9C^3g>Z*KR^FUe&_f-G#~G(q5VBF_y_gg zDHJZ)Z4o^K1|)*=gBS?MV*EBE!KaWPLZy~6no_3LX9p*L3B=M)pEGI1h)ct-(*0JH zTr{6`y6?%W@(WFPYYliS=KlBJsrLKRdE!BTy}#7b`>ylgMf=_Rv{kxa$3Lt%<2we& z)-g7abEhOnVQu$47<~P#kmIxOZGKaSzf|HY49auY)L+F9wZpH+|ER=QSmuL!YAe=R z$4-f_x($baW$L7l8(%p#k9OtUc3!jA(66o<9HO!Z)2MG#;RF*nQW@vI%9KTMvLl;` z+BWK8p2~0gm=n(WvAD_$(G=K}J#Z=GdT@ay`uyuF#rpZ*uTCU&>J(9G`c z8Lafllvi%09i3pgwH^jMmBAov(9z^tjq>$-TZfx}&-Sv4?KDHJbl>mtE)UgDi6^G&>d5$FmNx-N3&AZWxjbf z^)E}v-yi<=t7`u|{SeOA9~*uj8#gF@LrSoqOrD4$P)UlxNA~!XK8_|?5h(hs^NA<# zk>S06K{xv;_k6t#Kl;Av)U66$qxuT+x6>f{wsPK0>a&j<+Nq5LKbJkunDhUbVKCYY zCuN%H$gj}npTGU&73bJ>UcX^|>=<`_6t?mIi3!wn9yrIoR>duMJ#bOi*H~24^=Hky zD&M%kJPVTUr2O_F|9@cCxw0_DTbTSmWxe5ccd&7usx#;L%PCcfMqZ}jVw}KS`Npj8 zR8wIj toTonXUqrX#Pv(hFzS8Z_x%AfI{R;p9|NmoTfB+^2Mj&Kh002k#`aG9%--`eM diff --git a/tests/data/config_MT_MST.mat b/tests/data/config_MT_MST.mat index a3c4e61979d4297b43803442cbd15bb24c718c7f..af1b90d73f9d3a716523e0844336030dda47b143 100644 GIT binary patch delta 1546 zcmV+l2KD*a4B8BkG#E{9ZXiuzc_1J;ATc;PF*Q0hHXt%EGBS}-BavVQk#rD$(ggqj zc$~~x&2QT_6ld%tUHWPCu(g-Ly9~vE0^2RO=EEr(1POw~Sat{y=;PTYB8w_XC3a6c z?>|`oiXFGxPD2N5K(4#(xa0nS4IU|x7Nw}RM0ZUI$kwCydyjnL`{2`kgwS7~A+##~ zKN431rENvgOU5N>7)9W5@K?}(GHR**Nc=bvP##lIaOA{3CMatz_L)HTHuB9)<~D7(XY z4sc=dZ9ahZ(N3qW4Xf=@!q{opJ`GR9>-sD5*UjXw_4jSfbw5zF{6B&SIF=LY;$emT zSDc5ICvi_2_2zL$(fi_Zh41N85{Eu=196{@a)Vf#Y(MiK;&!ZmdMQjj(B%O0ynWBJ zhh}aa&G(O+*vgwExED2WYvOvOmGkG>M)BWf9uv!TPbL#9|9e}}pQ6m~2v1C%kVPjr zL~Q5;fxIc1R~3J>bVIl|&3bzHSkb?rEKZ9MgtK@Z5YGwlD=;$z5u=G5(ZLilKc{=U zNj%G1=nNs3aHPF|?#=~-oE-w)5;D$pZ{|fZ%&3D|Bup8G0TTg{Fd2EHjI zyl(XVwUtX9A3H%RcQ8Zm#r#AOK%j^K&Zf9WmiD%4AY6dW zrD$JAry6{JZWs7SIkAUQPCqNR9BZQ0vy7LtPC8=iU!YRR%yjR zw_G-a#yP5deYSS~F7x@f#Y>z0ot%P8@Kya`+O8IV^26@}S7+aC)XewqDq6||<_S~U zOAf$h4UPhfMD`6^WHh~(qip@&&hhr<;m%_909#ypPMk60#=N>oQJ*bwM=f!EOWfEJ z=UU=?OI&D)du53OOPr3UkCyD}UQdy%8YG43Jyl6kjelEK#)4^O+^?vBF)U*?!85 zuQ%aG{|{W5K90=L(;^oy)W)7FRA)iDR8eb7(6D+y)b)8)dyk&0EwL^l5K(raR2}S delta 1544 zcmV+j2KV{e4A=~iG#Ey5X&_Buav(7{ATcpIFf=+bG$1lCGBS}-BavVQk#rD$&;z}YcV1q|Wq(v#JEzxUJ0<`pK{@x=W`94UkB81+2hS0Kj zek5uGrDaLc3r3YR3?uM3_)BPi5w%qNwfJ!&pgg9a;K+%6Oi)%_>@$Nz9tj9FXdm3T zm!lc(g$7Ny2^Ztw)Y&3IJO~rMFoG_1ybDlF&+*XVm`phIu@74@Wm@P3j9lVSU;jU# zILAM7Jn%P1U5a}>pbRmO0vO|A7dSc|g%b-UAfbo333EIUe`oY1P?xZYy3wlqS*W&-Y5QW*SJICp|4}5EU16X1 z(eRKklkXbJ_%4?4T{if(6zyT^1(4#uH1Nwa#?=sScaR-Uk9Uab>0wFH^68Uo-lqJO zMs@kW)Le%}l-bw*(QdMT7bTy+YtBR4V_VeSkZ~G&(gc#V?27%?0kMm5l$eF&{|%bH zuAig)x=Q-1XC2_e1GIS`+DF@+wl=i3M+sx6Vf!>Z4R7kN$X^$ezt-P%&3Qjmw0s^x z1RTo&b@8CW{wt0{%agdLje6s_r|5lAUEzy*l*FNr+(5jiz1$#w)+XD_{E2uSsa6UT zk95_?Ja6B#?4g;PNAvyT#TX{`$k`##O(Ek#w`N`>!wfr^MZ%O}AP^fm-O07? zWJ!nA!%v3(viW9uG4&w(ucPVyc-83NQnc3BnMhRnyc(Ye1wIcvt(gW?}Pgu?VkHxU6ohcu`cN<>LSs9cXd90cGCYu=&4-VqZnqfGXV z(??cp^z_gYSLSEy;MQv3R#f||?`8Sx`8@fxz1-g`$$eXVebJb1*JgVaKe%G_Zz z(WC~Sy9GXfl1}!02YO#`WPEJ=j6OG3!7ml?k_H*yD#|azyDBVJ!QUz1B`wa`2htR) z=&@D6%Ua9_Z29Q>36sxlpA*+=`c)nOT~zd73DwnC3;_<|M4sdi`#U+cmf)-UwY0pR%b)&#AGkXEZoOuHeqYg29xzXs(q3|4 zHSf?Uut;Rfut|oKciGFjwv zoNtK>Epaa`abStl@$~V6-96PaBv1Lt#qyrI`BCJ7oA#!KTdeuUS=YZTA$x!L=O42C z^ZY}9h_64^Tpyh`NO=PiVos=th}@Bf6h)ut@F{#83F0hKw9)gKCGLsBy++ghlo?-d z!;iiTT$w%=N^o`VtLE9Kj`wZpxa-_^Kdre>bsqSIsD4b1?_2|Cc;HShvv}bSOv|%B zzx`~L=V(2zPtlL=W9lb&zoinjd`98H?a~*V^C-3dk^UFDr2aWWahVfAVbDcM4tZ8j3eq@Q$d%o^>rcV_8ov6E;yQrk>9+x(IeJAX}j&Y{`4*&rF|0~JN&tphm z%}a4f%}K0eKn1B~sd*(XrA3J)AVqMHpI4k(f=xXL@By&_5VHX>2b2Z@Rw$nl34;I= uki`YnXF-BKPN?{-nIN#!o)UXW)yGPKdyT>1F Date: Mon, 9 May 2022 18:21:42 +0200 Subject: [PATCH 63/64] bump version --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index c8d7ef2..b043aa6 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -v0.4.0dev +v0.5.0 From 9ef55c2aefd25a9abeeb7edaf050e128a597b1f1 Mon Sep 17 00:00:00 2001 From: Remi Gau Date: Mon, 9 May 2022 18:24:18 +0200 Subject: [PATCH 64/64] only update submod on dev branch --- .github/workflows/update_submodules.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/update_submodules.yml b/.github/workflows/update_submodules.yml index 3505a04..ee2be70 100644 --- a/.github/workflows/update_submodules.yml +++ b/.github/workflows/update_submodules.yml @@ -30,8 +30,6 @@ name: update submodules on: push: branches: - - main - - master - dev schedule: - cron: "0 0 1 * *"