Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[FIX] fix octave create roi #130

Merged
merged 10 commits into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions .github/workflows/run_tests_octave.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
name: tests and coverage with octave

env:
OCTFLAGS: --no-gui --no-window-system --silent

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

on:
push:
branches:
- main
pull_request:
branches: ['*']
schedule:
- cron: 0 0 1 * *

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

jobs:
tests_octave:
runs-on: ubuntu-latest

steps:
- name: Install CPP_ROI
uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0

- name: Install SPM
run: |
git clone https://github.com/spm/spm12.git --depth 1

- name: Install Moxunit and MOcov
run: |
git clone https://github.com/MOxUnit/MOxUnit.git --depth 1
git clone https://github.com/MOcov/MOcov.git --depth 1

- name: Install octave
run: |
sudo apt-get -y -qq update
sudo apt-get -y install \
octave \
liboctave-dev\
octave-common \
octave-io \
octave-image \
octave-signal \
octave-statistics
make -C MOxUnit install
make -C MOcov install

- name: Compile SPM
run: |
make -C spm12/src PLATFORM=octave distclean
make -C spm12/src PLATFORM=octave
make -C spm12/src PLATFORM=octave install
octave $OCTFLAGS --eval "addpath(fullfile(pwd, 'spm12')); savepath();"

- name: Add bids-matlab
run: make install_dev

- name: Run tests
run: |
octave $OCTFLAGS --eval "addpath(fullfile(pwd, 'tests', 'utils')); savepath();"
octave $OCTFLAGS --eval "cd(fullfile(getenv('GITHUB_WORKSPACE'), '.github', 'workflows')); run tests_octave;"

- name: Code coverage
uses: codecov/codecov-action@v4
with:
file: coverage.xml
flags: octave
name: codecov-umbrella
fail_ci_if_error: false
22 changes: 22 additions & 0 deletions .github/workflows/tests_octave.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
function tests_octave()

%
% (C) Copyright 2024 CPP ROI developers

root_dir = getenv('GITHUB_WORKSPACE');

addpath(fullfile(root_dir, 'spm12'));
addpath(fullfile(root_dir, 'lib', 'bids-matlab'));
addpath(fullfile(root_dir, 'MOcov', 'MOcov'));

cd(fullfile(root_dir, 'MOxUnit', 'MOxUnit'));

moxunit_set_path();

cd(fullfile(root_dir));

initCppRoi();

run_tests();

end
5 changes: 0 additions & 5 deletions src/atlas/copyAtlasToSpmDir.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@ function copyAtlasToSpmDir(varargin)

% (C) Copyright 2022 CPP ROI developers

if bids.internal.is_octave
% the atlas in the spm dir are only useful in matlab with the GUI
return
end

args = inputParser;

addOptional(args, 'atlas', 'AAL', @ischar);
Expand Down
13 changes: 11 additions & 2 deletions src/atlas/extractRoiFromAtlas.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@
args = inputParser;

addRequired(args, 'outputDir', isChar);
addRequired(args, 'atlasName', @(x) isAKnownAtlas(x));
addRequired(args, 'atlasName');
addRequired(args, 'roiName', isChar);
addRequired(args, 'hemisphere', @(x) ismember(x, {'L', 'R'}));
addRequired(args, 'hemisphere');

parse(args, varargin{:});

Expand All @@ -50,6 +50,15 @@
roiName = args.Results.roiName;
hemisphere = args.Results.hemisphere;

if ~ismember(hemisphere, {'L', 'R'})
msg = sprintf('"hemisphere must be "L" or "R"": %s\nGot: "%s"', ...
hemisphere);
bids.internal.error_handling(mfilename(), ...
'invalidHemisphere', msg, false);
end

isAKnownAtlas(atlasName);

[atlasFile, lut] = getAtlasAndLut(atlasName);

switch lower(atlasName)
Expand Down
12 changes: 9 additions & 3 deletions src/atlas/unzipAtlas.m
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,13 @@ function gunzipAtlasIfNecessary(file)
end

function gunzipWithOctave(file)
copyfile(file, [file '.bak']);
gunzip(file);
copyfile([file '.bak'], file);
if iscellstr(file)
for i = 1:numel(file)
gunzipWithOctave(file{i});
end
else
copyfile(file, [file '.bak']);
gunzip(file);
copyfile([file '.bak'], file);
end
end
6 changes: 5 additions & 1 deletion src/roi/thresholdToMask.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@

% add peakThreshold and clusterSizeInfo to desc
if ~isfield(bf.entities, 'desc')
bf.entities.desc = '';
bf.entities(1).desc = '';
end
descSuffix = sprintf('p%05.2f', peakThreshold);
if clusterSize > 0
Expand All @@ -57,6 +57,10 @@
descSuffix = strrep(descSuffix, '.', 'pt');
bf.entities.desc = [bf.entities.desc descSuffix];

if isempty(bf.extension)
bf.extension = '.nii';
end

bf = bf.update();

hdr = spm_vol(inputImage);
Expand Down
37 changes: 10 additions & 27 deletions tests/test_createRoi.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

function test_createRoi_sphere()

volumeDefiningImage = fullfile(demoDir(), 'TStatistic.nii');
inputDir = setUpDemoData();
volumeDefiningImage = fullfile(inputDir, 'inputs', 'TStatistic.nii');

sphere.location = [44 -67 0];
sphere.radius = 5;
Expand Down Expand Up @@ -91,38 +92,20 @@ function test_createRoi_intersection_mask_sphere()
value = fileparts(mfilename('fullpath'));
end

function value = demoDir()

value = fullfile(thisDir(), '..', 'demos', 'roi', 'inputs');

if exist(fullfile(value, 'TStatistic.nii'), 'file') == 0 || ...
exist(fullfile(value, 'visual motion_association-test_z_FDR_0.01.nii'), 'file') == 0
gunzip(fullfile(value, '*.gz'));
end

end

function [roiFilename, volumeDefiningImage] = prepareRoiAndVolumeDefiningImage()

volumeDefiningImage = fullfile(demoDir(), 'TStatistic.nii');

roiFilename = fullfile(demoDir(), ...
'space-MNI_atlas-neurosynth_label-visualMotion_desc-p10pt00_mask.nii');

if exist(roiFilename, 'file') == 2
inputDir = setUpDemoData();

else
volumeDefiningImage = fullfile(inputDir, 'inputs', 'TStatistic.nii');

zMap = fullfile(demoDir(), 'visual motion_association-test_z_FDR_0.01.nii');
zMap = fullfile(inputDir, 'inputs', 'visual motion_association-test_z_FDR_0.01.nii');

zMap = renameNeuroSynth(zMap);
zMap = resliceRoiImages(volumeDefiningImage, zMap);
zMap = renameNeuroSynth(zMap);
zMap = resliceRoiImages(volumeDefiningImage, zMap);

zMap = removePrefix(zMap, 'r');
zMap = removePrefix(zMap, 'r');

threshold = 10;
roiFilename = thresholdToMask(zMap, threshold);

end
threshold = 10;
roiFilename = thresholdToMask(zMap, threshold);

end
21 changes: 3 additions & 18 deletions tests/test_getPeakCoordinates.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@

function test_getPeakCoordinates_basic()

roiImage = extractRoiFromAtlas(pwd, 'wang', 'V1v', 'L');
inputDir = setUpDemoData();
dataImage = fullfile(inputDir, 'inputs', 'TStatistic.nii');

dataImage = fullfile(demoDir(), 'TStatistic.nii');
roiImage = extractRoiFromAtlas(pwd, 'wang', 'V1v', 'L');

reslicedImages = resliceRoiImages(dataImage, roiImage);

Expand All @@ -22,20 +23,4 @@ function test_getPeakCoordinates_basic()
assertEqual(voxelCoord, [28 8 24]);
assertElementsAlmostEqual(maxVal, 1.6212, 'absolute', 1e-3);

delete('*hemi-L_space-MNI_atlas-wang_label-V1v_mask.*');

end

function value = thisDir()
value = fileparts(mfilename('fullpath'));
end

function value = demoDir()

value = fullfile(thisDir(), '..', 'demos', 'roi', 'inputs');

if exist(fullfile(value, 'TStatistic.nii'), 'file') == 0
gunzip(fullfile(value, '*.gz'));
end

end
42 changes: 6 additions & 36 deletions tests/test_isBinaryMask.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,50 +9,20 @@

function test_isBinaryMask_true()

roiFilename = prepareRoiAndVolumeDefiningImage();
[roiFilename, zMap] = prepareRoiAndVolumeDefiningImage();
isBinaryMask(roiFilename);

end

function test_isBinaryMask_false()

[~, zMap] = prepareRoiAndVolumeDefiningImage();
assertExceptionThrown(@()isBinaryMask(zMap), 'isBinaryMask:notBinaryImage');

end

function value = thisDir()
value = fileparts(mfilename('fullpath'));
end

function value = demoDir()

value = fullfile(thisDir(), '..', 'demos', 'roi', 'inputs');

if exist(fullfile(value, 'visual motion_association-test_z_FDR_0.01.nii'), 'file') == 0
gunzip(fullfile(value, '*.gz'));
end

end

function [roiFilename, zMap] = prepareRoiAndVolumeDefiningImage()

zMap = fullfile(demoDir(), 'space-MNI_atlas-neurosynth_label-visualMotion_probseg.nii');

roiFilename = fullfile(demoDir(), ...
'space-MNI_atlas-neurosynth_label-visualMotion_desc-p10pt00_mask.nii');

if exist(roiFilename, 'file') == 2
inputDir = setUpDemoData();

else
zMap = fullfile(inputDir, 'inputs', 'visual motion_association-test_z_FDR_0.01.nii');

zMap = fullfile(demoDir(), 'visual motion_association-test_z_FDR_0.01.nii');

zMap = renameNeuroSynth(zMap);

threshold = 10;
roiFilename = thresholdToMask(zMap, threshold);

end
zMap = renameNeuroSynth(zMap);
threshold = 10;
roiFilename = thresholdToMask(zMap, threshold);

end
8 changes: 1 addition & 7 deletions tests/test_keepHemisphere.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@

function test_keepHemisphere_basic()

inputDir = fullfile(fileparts(mfilename('fullpath')), '..', 'demos', 'roi');

gunzip(fullfile(inputDir, 'inputs', '*.gz'));
inputDir = setUpDemoData();
zMap = fullfile(inputDir, 'inputs', 'visual motion_association-test_z_FDR_0.01.nii');

zMap = renameNeuroSynth(zMap);
Expand All @@ -32,8 +30,4 @@ function test_keepHemisphere_basic()
'file'), ...
2);

% TODO check the data content

delete(fullfile(inputDir, 'inputs', '*.nii'));

end
21 changes: 4 additions & 17 deletions tests/test_labelClusters.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

function test_labelClusters_basic

zMap = fullfile(demoDir(), 'visual motion_association-test_z_FDR_0.01.nii');
inputDir = setUpDemoData();
zMap = fullfile(inputDir, 'inputs', 'visual motion_association-test_z_FDR_0.01.nii');

zMap = renameNeuroSynth(zMap);

Expand All @@ -19,28 +20,14 @@
labeledClusters = labelClusters(zMap, peakThreshold, extendThreshold);

expected = 'space-MNI_seg-neurosynth_label-visualMotion_dseg.nii';
assertEqual(exist(fullfile(demoDir(), expected), 'file'), 2);
assertEqual(exist(fullfile(inputDir, 'inputs', expected), 'file'), 2);

labelStruct = struct('ROI', 'ns left MT', ...
'label', 1);

roiName = extractRoiByLabel(labeledClusters, labelStruct);

expected = 'space-MNI_seg-neurosynth_label-nsLeftMT_mask.nii';
assertEqual(exist(fullfile(demoDir(), expected), 'file'), 2);

end

function value = thisDir()
value = fileparts(mfilename('fullpath'));
end

function value = demoDir()

value = fullfile(thisDir(), '..', 'demos', 'roi', 'inputs');

if exist(fullfile(value, 'visual motion_association-test_z_FDR_0.01.nii'), 'file') == 0
gunzip(fullfile(value, '*.gz'));
end
assertEqual(exist(fullfile(inputDir, 'inputs', expected), 'file'), 2);

end
Loading
Loading