From 37d1b81dee22dc558e003c6d5339caf78ab6cd05 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 4 Mar 2019 10:10:21 +0100 Subject: [PATCH 001/132] Adding documentation to the function determineElectrodeType. --- src/Functions/determineElectrodeType.m | 27 +++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/Functions/determineElectrodeType.m b/src/Functions/determineElectrodeType.m index 6aff7be..7c71018 100644 --- a/src/Functions/determineElectrodeType.m +++ b/src/Functions/determineElectrodeType.m @@ -1,12 +1,25 @@ -%% determineElectrodeType - get most likly electrode type be eucleadian distance between detected ans specified peaks +function [elecStruct, rms, d] = determineElectrodeType(peakDistances) +% gets the most suitable electrode type based on the euclidean distance between +% detected and specified peaks in the collected data. Data should should be provided +% in the form of the file 'electrodeGeometries.mat'. +% +% USAGE: +% +% [electStruct, rms, d] = determineElectrodeType(peakDistances) % -% Andreas Husch -% Centre Hospitalier de Luxembourg / Luxembourg Centre for Systems -% Biomedicine, University of Luxembourg -% 2016 - 2017 -% mail@andreashusch.de +% INPUT: +% peakDistances: The peak distances between the signals, provided by the inserted +% data sheet. +% +% OUTPUTS: +% electStruct: Electrode Type. +% rms: Root-mean-square of the distance between the electrode signals. +% d: ? +% +% .. AUTHOR: +% - Andreas Husch, Original file +% - Daniel Duarte, Documentation -function [elecStruct, rms, d] = determineElectrodeType(peakDistances) electrodeGeometries = load('electrodeGeometries.mat'); electrodeGeometries = electrodeGeometries.electrodeGeometries; From e54acbaec0b67c8ee0107ce15a7e5ed003ca0945 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 4 Mar 2019 18:22:06 +0100 Subject: [PATCH 002/132] Adding documentation template to the function createSimpleMPRWorldCoordinates --- .../createSimpleMPRWorldCoordinates.m | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/Functions/createSimpleMPRWorldCoordinates.m b/src/Functions/createSimpleMPRWorldCoordinates.m index 0fc6104..9a1979f 100644 --- a/src/Functions/createSimpleMPRWorldCoordinates.m +++ b/src/Functions/createSimpleMPRWorldCoordinates.m @@ -1,13 +1,21 @@ -%% Convenience Wrapper for the MPRWorldCoordinate Class by Florian Bernard -% -% Andreas Husch -% Centre Hospitalier de Luxembourg, Dept. of Neurosurgery / -% University of Luxembourg - Luxembourg Centre for Systems Biomedicne -% 2017 -% mail@andreashusch.de, husch.andreas@chl.lu function [mpr, oc] = createSimpleMPRWorldCoordinates(nii) -%mprPanel = uipanel('Parent', gcf); -axesObj = gca;%axesObj = axes('Parent', mprPanel); +% Convenience Wrapper for the MPRWorldCoordinate Class by Florian Bernard +% +% USAGE: +% +% [mpr, oc] = createSimpleMPRWorldCoordinates(nii) +% +% INPUT: +% nii: +% +% OUTPUTS: +% mpr: +% oc: +% +% .. AUTHOR: +% - Andreas Husch, Centre Hospitalier de Luxembourg, Dept. of Neurosurgery / Luxembourg Centre for Systems, Biomedicine, University of Luxembourg, 2017, mail@andreashusch.de, husch.andreas@chl.lu + +axesObj = gca;%axesObj = axes('Parent', mprPanel); %mprPanel = uipanel('Parent', gcf); mpr = MPRWorldCoordinates(axesObj, nii.img, [0 0 0], nii); view(160,10); %oc = OrientationCube(mprPanel, axesObj); From 4fab39e22d4eb7e40de80835fd3e6ac999666787 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 4 Mar 2019 18:37:15 +0100 Subject: [PATCH 003/132] Adding doc template to the function createSimpleMPRWorldCoordinates --- src/Functions/createSimpleMPRWorldCoordinates.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Functions/createSimpleMPRWorldCoordinates.m b/src/Functions/createSimpleMPRWorldCoordinates.m index 9a1979f..71413ad 100644 --- a/src/Functions/createSimpleMPRWorldCoordinates.m +++ b/src/Functions/createSimpleMPRWorldCoordinates.m @@ -13,9 +13,10 @@ % oc: % % .. AUTHOR: -% - Andreas Husch, Centre Hospitalier de Luxembourg, Dept. of Neurosurgery / Luxembourg Centre for Systems, Biomedicine, University of Luxembourg, 2017, mail@andreashusch.de, husch.andreas@chl.lu +% - Andreas Husch, Original file +% - Daniel Duarte, Documentation -axesObj = gca;%axesObj = axes('Parent', mprPanel); %mprPanel = uipanel('Parent', gcf); +axesObj = gca; %axesObj = axes('Parent', mprPanel); %mprPanel = uipanel('Parent', gcf); mpr = MPRWorldCoordinates(axesObj, nii.img, [0 0 0], nii); view(160,10); %oc = OrientationCube(mprPanel, axesObj); From b00d0f3690abf40f606fe4670cbefef807989a36 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 4 Mar 2019 19:19:29 +0100 Subject: [PATCH 004/132] Adding documentation template to function extractBrainConvHull --- src/Functions/extractBrainConvHull.m | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/Functions/extractBrainConvHull.m b/src/Functions/extractBrainConvHull.m index a0162df..2f807c3 100644 --- a/src/Functions/extractBrainConvHull.m +++ b/src/Functions/extractBrainConvHull.m @@ -1,13 +1,22 @@ -%% Extracts the convex hull of the brain out of a CT image -% -% Andreas Husch -% Centre Hospitalier de Luxembourg, Dept. of Neurosurgery / -% University of Luxembourg - Luxembourg Centre for Systems Biomedicne -% 2015 - 2017 -% mail@andreashusch.de, husch.andreas@chl.lu function [convHullBrainMask, roughBrainMask] = extractBrainConvHull(niiCT) -%% force caching -niiCT.isToBeCached = 1; +% Extracts the convex hull of the brain out of a CT image +% +% USAGE: +% +% [convHullBrainMask, roughBrainMask] = extractBrainConvHull(niiCT) +% +% INPUT: +% niiCT: +% +% OUTPUTS: +% convHullBrainMask: +% roughBrainMask: +% +% .. AUTHOR: +% - Andreas Husch, Original File +% - Daniel Duarte Tojal, Documentation + +niiCT.isToBeCached = 1; % force caching if(~niiCT.isLoaded) niiCT.load(); end From 1ea0c54a63963003b5dad93ec24414ad9657cc7e Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Tue, 5 Mar 2019 08:27:58 +0100 Subject: [PATCH 005/132] Adding doc template to function extractElectrodePointcloud --- src/Functions/extractElectrodePointclouds.m | 26 ++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/Functions/extractElectrodePointclouds.m b/src/Functions/extractElectrodePointclouds.m index 03fa82b..aba1896 100644 --- a/src/Functions/extractElectrodePointclouds.m +++ b/src/Functions/extractElectrodePointclouds.m @@ -1,10 +1,22 @@ -%% extractElectrodePointclouds - Preprocess CT Data for Electrode Artifacts +function +% extractElectrodePointclouds - Preprocess CT Data for Electrode Artifacts % -% Andreas Husch -% Centre Hospitalier de Luxembourg, Dep. of Neurosurgery / -% University of Luxembourg - Luxembourg Centre for Systems Biomedicne -% 2014 - 2017 -% mail@andreashusch.de, husch.andreas@chl.lu +% USAGE: +% +% [elecsPointcloudStruct, brainMask] = extractElectrodePointclouds(niiCT, varargin) +% +% INPUTS: +% niiCT: +% varargin: +% +% OUTPUTS: +% elecsPointcloudStruct: create output struct and try to associate electrodes +% from xml defition if given +% brainMask: +% +% .. AUTHOR: +% - Andreas Husch, Original file +% - Daniel Duarte Tojal, Documentation function [elecsPointcloudStruct, brainMask] = extractElectrodePointclouds(niiCT, varargin) disp(['Voxel size in elecsPointcloudStruct: ' num2str(niiCT.voxsize')]); @@ -113,8 +125,6 @@ disp(['No xmlElectrodeDefition given. Guessing that there are ' num2str(nElecs) ' electrodes in the image']); end - %% create output struct and try to associate electrodes from xml defitions - % if given elecsPointcloudStruct = struct(); for i=1:nElecs From d9c36b4171b40529f51d8d13e07d053ba3c37293 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Thu, 7 Mar 2019 18:45:30 +0100 Subject: [PATCH 006/132] Adding documentation template to function fitParamPolyToSkeleton --- src/Functions/fitParamPolyToSkeleton.m | 27 ++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/Functions/fitParamPolyToSkeleton.m b/src/Functions/fitParamPolyToSkeleton.m index 780e9c0..53c866b 100644 --- a/src/Functions/fitParamPolyToSkeleton.m +++ b/src/Functions/fitParamPolyToSkeleton.m @@ -1,15 +1,22 @@ -%% Fits a parameterized polynomial [0,1] -> R^3 to a skeleton point cloud -% Params: -% skeleton - 3 x N skeleton pointcloud -% OPTIONAL degree - degree of fitted polynomial (DEFAULT: 3) +function [r3polynomial, avgTperMm] = fitParamPolyToSkeleton(skeleton, degree) +% Fits a parameterized polynomial [0,1] -> R^3 to a skeleton point cloud +% +% USAGE: +% +% [r3polynomial, avgTperMm] = fitParamPolyToSkeleton(skeleton, degree) % -% Andreas Husch -% Centre Hospitalier de Luxembourg / Luxembourg Centre for Systems -% Biomedicine, University of Luxembourg -% 2014 - 2017 -% mail@andreashusch.de, husch.andreas@chl.lu +% INPUTS: +% skeleton: 3 x N skeleton pointcloud +% degree: degree of fitted polynomial (DEFAULT: 3) +% +% OUTPUTS: +% r3polynomial: +% avgTperMm: +% +% .. AUTHOR: +% - Andreas Husch, Original file +% - DanielDuarte Tojal, Documentation -function [r3polynomial, avgTperMm] = fitParamPolyToSkeleton(skeleton, degree) if(nargin < 2) disp('No degree given, using default degree=3'); degree=3; From c140019b1550e830ebc37697746a30721f0c7d73 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Thu, 7 Mar 2019 19:09:16 +0100 Subject: [PATCH 007/132] Adding doc template to function getIntensityPeaks --- src/Functions/getIntensityPeaks.m | 52 ++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/src/Functions/getIntensityPeaks.m b/src/Functions/getIntensityPeaks.m index 56b4be1..9ccb6e3 100644 --- a/src/Functions/getIntensityPeaks.m +++ b/src/Functions/getIntensityPeaks.m @@ -1,12 +1,38 @@ -%% Get peaks respectivly center points at threshold below the peaks from 1D -% intensity profile. Expected peakWaveCenter number == 4 for now (needs update to support electrodes with more ring contacts)! -% -% Andreas Husch -% Centre Hospitalier de Luxembourg, Dep. of Neurosurgery / -% University of Luxembourg - Luxembourg Centre for Systems Biomedicne -% 2014 - 2017 -% mail@andreashusch.de, husch.andreas@chl.lu function [peakLocs, peakWaveCenters, peakValues, threshIntensityProfile, threshold, contactAreaCenter, contactAreaWidth, xrayMarkerAreaCenter, xrayMarkerAreaWidth] = getIntensityPeaks(intensityProfile, skelScaleMm, filterIdxs) +% Get peaks, respectively center points, at threshold below the peaks from 1D +% intensity profile. Expected peakWaveCenter number is 4 for now (needs +% update to support electrodes with more ring contacts)! +% +% USAGE: +% +% [peakLocs, peakWaveCenters, peakValues, threshIntensityProfile, +% threshold, contactAreaCenter, contactAreaWidth, xrayMarkerAreaCenter, +% xrayMarkerAreaWidth] = getIntensityPeaks(intensityProfile, skelScaleMm, filterIdxs) +% +% INPUTS: +% intensityProfile: +% skelScaleMm: +% filterIdxs: +% +% OUTPUTS: +% peaklocs: +% peakWaveCenters: +% peakValues: +% threshIntensityProfile: +% threshold: +% contactAreaCenter: +% contactAreaWidth: +% xrayMarkerAreaCenter: +% xrayMarkerAreaWidth: +% +% EXAMPLE: +% +% NOTE: +% +% .. AUTHOR: +% - Andreas Husch, Original File +% - Daniel Duarte Tojal, Documentation + [peakValues, peakLocs, ~, pkPromineces] = findpeaks(intensityProfile(filterIdxs),skelScaleMm(filterIdxs), 'MinPeakDistance', 1.4, 'MinPeakHeight', 1.1 * nanmean(intensityProfile), 'MinPeakProminence', 0.01 * nanmean(intensityProfile)); % find elec contacts, TODO 1.5 is for 3389/3387 xrayMarkerAreaWidth = []; xrayMarkerAreaCenter = []; @@ -31,18 +57,22 @@ contactSampleLabels = bwlabel(~(threshIntensityProfileArea(filterIdxs) < thresholdArea)); values = accumarray((contactSampleLabels+1)', skelScaleMm(filterIdxs)); % in x ([mm]) counts = accumarray((contactSampleLabels+1)', 1); -contactAreaCenter = values(2)./counts(2); % index 1 is the "zero label", index 2 (value 1) is the contact region, index 3 (value 2) might be an X-Ray obaque arker +contactAreaCenter = values(2)./counts(2); % index 1 is the "zero label", index 2 (value 1) is the contact region, + % index 3 (value 2) might be an X-Ray obaque arker idxs = find(contactSampleLabels+1==2); contactAreaWidth = abs(skelScaleMm(idxs(1))-skelScaleMm(idxs(end))); if(max(contactSampleLabels) > 1) disp('Multiple metal areas found along electrode. Is this an electrode type with an addtional X-Ray marker?'); - xrayMarkerAreaCenter = values(3)./counts(3); % index 1 is the "zero label", index 2 (value 1) is the contact region, index 3 (value 2) might be an X-Ray obaque arker + xrayMarkerAreaCenter = values(3)./counts(3); % index 1 is the "zero label", index 2 (value 1) + % is the contact region, index 3 (value 2) might be an X-Ray obaque arker idxs = find(contactSampleLabels+1==3); xrayMarkerAreaWidth = abs(skelScaleMm(idxs(1))-skelScaleMm(idxs(end))); end %% Plot % figure -% findpeaks(intensityProfile(filterIdxs),skelScaleMm(filterIdxs), 'MinPeakDistance', 3, 'MinPeakHeight', 1.1 * nanmean(intensityProfile), 'MinPeakProminence', 0.1 * nanmean(intensityProfile)); % find elec contacts, TODO 1.5 is for 3389/3387 +% findpeaks(intensityProfile(filterIdxs),skelScaleMm(filterIdxs), 'MinPeakDistance', 3, +% 'MinPeakHeight', 1.1 * nanmean(intensityProfile), 'MinPeakProminence', +% 0.1 * nanmean(intensityProfile)); % find elec contacts, TODO 1.5 is for 3389/3387 % hold on; % plot(skelScaleMm(filterIdxs), threshIntensityProfileArea(filterIdxs)); % scatter(peakWaveCenters, repmat(threshold,1,4), 'filled'); From ed23ab312fc63aed11ed5a2beac40f81c9ed17f4 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 08:34:18 +0100 Subject: [PATCH 008/132] Updating the documentation of the function extractBrainConvHull --- src/Functions/extractBrainConvHull.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Functions/extractBrainConvHull.m b/src/Functions/extractBrainConvHull.m index 2f807c3..70ae0b8 100644 --- a/src/Functions/extractBrainConvHull.m +++ b/src/Functions/extractBrainConvHull.m @@ -6,11 +6,11 @@ % [convHullBrainMask, roughBrainMask] = extractBrainConvHull(niiCT) % % INPUT: -% niiCT: +% niiCT: NiftiMod object of a post-operative CT image % % OUTPUTS: -% convHullBrainMask: -% roughBrainMask: +% convHullBrainMask: Estimated mask of the convex hull of the brain +% roughBrainMask: Estimated rough brain mask wich may contain inaccuracies % % .. AUTHOR: % - Andreas Husch, Original File From cc17bd57be96128039d56d66fa34fc49b37274f1 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 08:45:31 +0100 Subject: [PATCH 009/132] Updating documentation of the function createSimpleMPRWorldCoordinates --- src/Functions/createSimpleMPRWorldCoordinates.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Functions/createSimpleMPRWorldCoordinates.m b/src/Functions/createSimpleMPRWorldCoordinates.m index 71413ad..60b76cf 100644 --- a/src/Functions/createSimpleMPRWorldCoordinates.m +++ b/src/Functions/createSimpleMPRWorldCoordinates.m @@ -6,11 +6,11 @@ % [mpr, oc] = createSimpleMPRWorldCoordinates(nii) % % INPUT: -% nii: +% nii: NiftiModality object to visualize as multi-planar-reformatting (MPR) % % OUTPUTS: -% mpr: -% oc: +% mpr: Handle to MPR +% oc: optional orientation cube (deprecated) % % .. AUTHOR: % - Andreas Husch, Original file From f011ccc29539a698cf88b38cc386567ccc1979fe Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 08:50:01 +0100 Subject: [PATCH 010/132] Updating the documentation of the function determineElectrodeType --- src/Functions/determineElectrodeType.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Functions/determineElectrodeType.m b/src/Functions/determineElectrodeType.m index 7c71018..aa0bbfe 100644 --- a/src/Functions/determineElectrodeType.m +++ b/src/Functions/determineElectrodeType.m @@ -14,7 +14,7 @@ % OUTPUTS: % electStruct: Electrode Type. % rms: Root-mean-square of the distance between the electrode signals. -% d: ? +% d: Euclidian distance to the closest electrode prototype % % .. AUTHOR: % - Andreas Husch, Original file From 2c0908acc8fafa82070ef560e8be369b8fea226d Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 09:01:18 +0100 Subject: [PATCH 011/132] Adding doc template to function invPolyArcLength3 --- src/Functions/invPolyArcLength3.m | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/Functions/invPolyArcLength3.m b/src/Functions/invPolyArcLength3.m index 1d290c0..cfe25dc 100644 --- a/src/Functions/invPolyArcLength3.m +++ b/src/Functions/invPolyArcLength3.m @@ -1,17 +1,27 @@ -%% invPolyArcLength3 - Numerically calculate the parameter (t) of parameterized [0,1] -> R^3 polynomial +function t = invPolyArcLength3(polyCoeff, arcLength) +% Numerically calculate the parameter (t) of parameterized [0,1] -> R^3 polynomial % *given* an arc length (measured from 0) i.e. find the corresponding t to an arc length -% (e.g. given in [mm] from the origin) or in other words numerically invert polyArcLength3 +% (e.g. given in [mm] from the origin), or in other words numerically invert polyArcLength3 % -% Andreas Husch -% Centre Hospitalier de Luxembourg, Dep. of Neurosurgery / -% University of Luxembourg - Luxembourg Centre for Systems Biomedicine -% 2016 - 2017 -% mail@andreashusch.de, husch.andreas@chl.lu -function t = invPolyArcLength3(polyCoeff, arcLength) -t = zeros(size(arcLength)); % default t=0 (i.e. in caes arcLength is 0) +% USAGE: +% +% t = invPolyArcLength3(polyCoeff, arcLength) +% +% INPUTS: +% polyCoeff: Coefficient matrix +% arcLength: +% +% OUTPUT: +% t: +% +% .. AUTHOR: +% - Andreas Husch, Original File +% - Daniel Duarte Tojal, Documentation + +t = zeros(size(arcLength)); % default t=0 (i.e. in case arcLength is 0) for i = 1:length(arcLength) if(arcLength(i)<0) - warning('invPolyArcLength3: given arcLength is negatie! Forcing t=0. This is wrong but might be approximatly okay for the use case! Check carefully!'); + warning('invPolyArcLength3: given arcLength is negative! Forcing t=0. This is wrong but might be approximatly okay for the use case! Check carefully!'); else t(i) = fminsearch( @(b)(abs(arcLength(i) - polyArcLength3(polyCoeff,0,b))), 0); end From ebd496319fb4342ad872678208ffc25f180925cc Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 09:03:25 +0100 Subject: [PATCH 012/132] Adding doc template to function largestConnCompSliceWise --- src/Functions/largestConnCompSliceWise.m | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Functions/largestConnCompSliceWise.m b/src/Functions/largestConnCompSliceWise.m index 7c48b2e..062cff9 100644 --- a/src/Functions/largestConnCompSliceWise.m +++ b/src/Functions/largestConnCompSliceWise.m @@ -1,6 +1,20 @@ -% Andreas Husch -% 2018 function binaryMask = largestConnCompSliceWise(img3d) +% +% USAGE: +% +% binaryMask = largestConnCompSliceWise(img3d) +% +% INPUT: +% img3d: +% +% OUTPUT: +% binaryMask: +% +% .. AUTHOR: +% - Andreas Husch, Original File +% - Daniel Duarte Tojal, Documentation + + binaryMask = false(size(img3d)); for i = 1:size(img3d,3) % z From ad7d9313eda8713dd859decbf1450826bef64a4e Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 09:10:13 +0100 Subject: [PATCH 013/132] Adding doc template to function plotIntensityProfileAndPeaks.m git add plotIntensityProfileAndPeaks.m --- src/Functions/plotIntensityProfileAndPeaks.m | 35 +++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/Functions/plotIntensityProfileAndPeaks.m b/src/Functions/plotIntensityProfileAndPeaks.m index 0f0c0d3..31197a2 100644 --- a/src/Functions/plotIntensityProfileAndPeaks.m +++ b/src/Functions/plotIntensityProfileAndPeaks.m @@ -1,13 +1,27 @@ -%% plotIntensityProfileAndPeaks +function [peakLocs, peakWaveCenters, peakValues, threshIntensityProfile, threshold] = getIntensityPeaks(intensityProfile, skelScaleMm, filterIdxs); % -% Andreas Husch -% Centre Hospitalier de Luxembourg, Dep. of Neurosurgery / -% University of Luxembourg - Luxembourg Centre for Systems Biomedicne -% 2017 -% mail@andreashusch.de, husch.andreas@chl.lu -function plotIntensityProfileAndPeaks(intensityProfile, skelScaleMm) +% USAGE: +% +% [peakLocs, peakWaveCenters, peakValues, threshIntensityProfile, threshold] +% = getIntensityPeaks(intensityProfile, skelScaleMm, filterIdxs); +% +% INPUTS: +% intensityProfile: +% skelScaleMm: +% filterIdxs: +% +% OUTPUTS: +% peakLocs +% peakWaveCenters: +% peakValues: +% threshIntensityProfile: +% threshold: +% +% .. AUTHOR: +% - Andreas Husch, Original File +% - Daniel Duarte Tojal, Documentation + filterIdxs = find(skelScaleMm <= 20); % restrict to first 20mm -[peakLocs, peakWaveCenters, peakValues, threshIntensityProfile, threshold] = getIntensityPeaks(intensityProfile, skelScaleMm, filterIdxs); figure('Name', 'Intensity Profile'); ax = gca; @@ -22,4 +36,7 @@ function plotIntensityProfileAndPeaks(intensityProfile, skelScaleMm) plot(skelScaleMm(filterIdxs), threshIntensityProfile(filterIdxs)); scatter(peakWaveCenters, repmat(threshold,1,length(peakWaveCenters)), 'filled'); grid on; -end \ No newline at end of file +end + + +% function plotIntensityProfileAndPeaks(intensityProfile, skelScaleMm) From a5de487078a7cbf1f9a9798af30d08a057542ba1 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 09:14:28 +0100 Subject: [PATCH 014/132] Adding doc template to function polyArcLength3 --- src/Functions/polyArcLength3.m | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/Functions/polyArcLength3.m b/src/Functions/polyArcLength3.m index 4b45f62..a8716cb 100644 --- a/src/Functions/polyArcLength3.m +++ b/src/Functions/polyArcLength3.m @@ -1,21 +1,25 @@ -%% Calculate the arc length of an interval on a parameterized polynomial in R3 -% Params: -% polyCoeff - coefficient matrix -% lowerLimit -% upperLimit +function arcLength = polyArcLength3(polyCoeff, lowerLimit, upperLimit) % -% lowerLimit / upperLimit parameters can take scalar as well as vector inputs, -% in the vector case arc lengths are returend for all pairs of intervals -% between lowerLimit and upperLimit +% USAGE: % -% Andreas Husch -% Centre Hospitalier de Luxembourg / Luxembourg Centre for Systems -% Biomedicine, University of Luxembourg -% 2016 - 2017 -% mail@andreashusch.de, husch.andreas@chl.lu - +% arcLength = polyArcLength3(polyCoeff, lowerLimit, upperLimit) +% +% INPUTS: +% polyCoeff: Coefficient matrix +% lowerLimit: Lower limit, taken as scalar or vector input. If put in as a vector, +% arc lengths are returned for all pairs of intervals between the lower +% and upper limit. +% upperLimit: Upper limit, taken as scalar or vector input. If put in as a vector, +% arc lengths are returned for all pairs of intervals between the upper +% and lower limit. +% +% OUTPUT: +% arcLength: Length of the arc. +% +% .. AUTHOR: +% - Andreas Husch, Original File +% - Daniel Duarte Tojal, Documentation -function arcLength = polyArcLength3(polyCoeff, lowerLimit, upperLimit) epsilon = 0.001; % avoid numerical accuracy problems in assertion assert(all(lowerLimit(:) <= upperLimit(:) + epsilon)); From 7856adb0574658ffd6a3faf5cbecfdc57c276cd3 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 09:15:57 +0100 Subject: [PATCH 015/132] Adding doc template to funtion polyval3 --- src/Functions/polyval3.m | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/Functions/polyval3.m b/src/Functions/polyval3.m index 95e7031..0e21a29 100644 --- a/src/Functions/polyval3.m +++ b/src/Functions/polyval3.m @@ -1,11 +1,21 @@ -%% polyval3 - evaluate an (independent component) polynomial in R3 -% -% Andreas Husch -% Centre Hospitalier de Luxembourg, Dep. of Neurosurgery / -% University of Luxembourg - Luxembourg Centre for Systems Biomedicne -% 2014 - 2017 -% mail@andreashusch.de, husch.andreas@chl.lu function val = polyval3(polyCoeffs, evalAt) +% evaluate an (independent component) polynomial in R3 +% +% USAGE: +% +% val = polyval3(polyCoeffs, evalAt) +% +% INPUTS: +% polyCoeffs: Coefficient matrix +% evalAt: +% +% OUTPUT: +% val: +% +% .. AUTHOR: +% - Andreas Husch, Original File +% - Daniel Duarte Tojal, Documentation + x = polyval(((polyCoeffs(:,1))), evalAt); y = polyval(((polyCoeffs(:,2))), evalAt); z = polyval(((polyCoeffs(:,3))), evalAt); From 5515a9bebfae7f58de2adc2c3ca785ad86472e70 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 09:17:19 +0100 Subject: [PATCH 016/132] Adding doc template to function refitElec --- src/Functions/refitElec.m | 48 +++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/Functions/refitElec.m b/src/Functions/refitElec.m index 8fd644f..2a635ac 100644 --- a/src/Functions/refitElec.m +++ b/src/Functions/refitElec.m @@ -1,27 +1,35 @@ -%% refitElec - refits a previously extracted corse electrode model using -% ptimal oblique samplingto increase accuracy and enable -% automatic contact localisation. Intital refitting -% ("2nd pass" is followed by a final "3rd pass" to -% calibrate the point of origin / zero according to the detected contacts) +function [refitReZeroedElecMod, filteredIntensity, skelScaleMm] = refitElec(initialPoly, pointCloudWorld, voxelValues, varargin) +% refits a previously extracted corse electrode model using +% optimal oblique sampling to increase accuracy and enable +% automatic contact localisation. Intital refitting +% ("2nd pass" is followed by a final "3rd pass" to +% calibrate the point of origin / zero according to the detected contacts) + +% USAGE: +% +% [refitReZeroedElecMod, filteredIntensity, skelScaleMm] +% = refitElec(initialPoly, pointCloudWorld, voxelValues, varargin) % -% Params: initialPoly - Dx3 double, R3 ploynomial coeffecients, -% pointCloudWorld - Nx3 double, point cloud of sourounding voxels in respective coordinate system -% voxelValues - Nx1 double, voxels intensitiy values (1:1 to pointCloudWorld) -% varargin - options cell +% INPUTS: +% initialPoly: Dx3 double, R3 ploynomial coeffecients +% pointCloudWorld: Nx3 double, point cloud of sourounding voxels in +% respective coordinate system +% voxelValues: Nx1 double, voxels intensitiy values (1:1 to pointCloudWorld) +% varargin: options cell % -% Returns: refitReZeroedElecMod - polynomialElectrodeModel Object with the -% refitted and rezeored elec model, -% including reference to elecInfo etc. +% OUTPUTS: +% refitReZeroedElecMod: polynomialElectrodeModel Object with the +% refitted and rezeored elec model, +% including reference to elecInfo etc. +% filteredIntensity: +% skelScaleMm: % -% Andreas Husch -% Centre Hospitalier de Luxembourg / Luxembourg Centre for Systems -% Biomedicine, University of Luxembourg -% 2016 - 2017 -% mail@andreashusch.de +% .. AUTHOR: +% - Andreas Husch, Original File +% - Daniel Duarte Tojal, Documentation -function [refitReZeroedElecMod, filteredIntensity, skelScaleMm] = refitElec(initialPoly, pointCloudWorld, voxelValues, varargin) -%% CONSTANTS FOR OOR / CONTACT DETECTION -XY_RESOLUTION = 0.1; + +XY_RESOLUTION = 0.1; %% CONSTANTS FOR OOR / CONTACT DETECTION Z_RESOLUTION = 0.025; LIMIT_CONTACT_SEARCH_MM = 20; % limit contact search to first 20 mm From f007575feb0c65abc77cef1e9d91eeed7c2fe9e1 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 14:24:52 +0100 Subject: [PATCH 017/132] Update in the fucntion --- src/Functions/extractElectrodePointclouds.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Functions/extractElectrodePointclouds.m b/src/Functions/extractElectrodePointclouds.m index aba1896..411879c 100644 --- a/src/Functions/extractElectrodePointclouds.m +++ b/src/Functions/extractElectrodePointclouds.m @@ -6,12 +6,12 @@ % [elecsPointcloudStruct, brainMask] = extractElectrodePointclouds(niiCT, varargin) % % INPUTS: -% niiCT: +% niiCT: NiftiMod object of a post-operative CT image % varargin: % % OUTPUTS: -% elecsPointcloudStruct: create output struct and try to associate electrodes -% from xml defition if given +% elecsPointcloudStruct: Create output struct and try to associate electrodes +% from xml definition if given % brainMask: % % .. AUTHOR: From 59fac882ad54d384017e1c6a3d69b16c8dcbd089 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 15:14:34 +0100 Subject: [PATCH 018/132] Update the function description for brainMask --- src/Functions/extractElectrodePointclouds.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Functions/extractElectrodePointclouds.m b/src/Functions/extractElectrodePointclouds.m index 411879c..b520d51 100644 --- a/src/Functions/extractElectrodePointclouds.m +++ b/src/Functions/extractElectrodePointclouds.m @@ -12,7 +12,7 @@ % OUTPUTS: % elecsPointcloudStruct: Create output struct and try to associate electrodes % from xml definition if given -% brainMask: +% brainMask: Define the brain area % % .. AUTHOR: % - Andreas Husch, Original file From dc123ad7da854b1000c9f6a6371ca88f0bffa768 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 16:16:02 +0100 Subject: [PATCH 019/132] Updated the documentation --- src/Functions/extractElectrodePointclouds.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Functions/extractElectrodePointclouds.m b/src/Functions/extractElectrodePointclouds.m index b520d51..353e84b 100644 --- a/src/Functions/extractElectrodePointclouds.m +++ b/src/Functions/extractElectrodePointclouds.m @@ -1,4 +1,4 @@ -function +function [elecsPointcloudStruct, brainMask] = extractElectrodePointclouds(niiCT, varargin) % extractElectrodePointclouds - Preprocess CT Data for Electrode Artifacts % % USAGE: @@ -18,7 +18,6 @@ % - Andreas Husch, Original file % - Daniel Duarte Tojal, Documentation -function [elecsPointcloudStruct, brainMask] = extractElectrodePointclouds(niiCT, varargin) disp(['Voxel size in elecsPointcloudStruct: ' num2str(niiCT.voxsize')]); % CONSTANTS From 351157c961dfda46247f5e4134427ee3adefca58 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 16:31:57 +0100 Subject: [PATCH 020/132] change of name of function orr to oor --- src/Functions/oor.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Functions/oor.m b/src/Functions/oor.m index 053e8e7..9c2ce4a 100644 --- a/src/Functions/oor.m +++ b/src/Functions/oor.m @@ -11,7 +11,7 @@ % mail@andreashusch.de % % That code needs some cleanup :-) But it works ;-) -function [improvedSkeleton, medIntensity,orthIntensVol, orthSamplePointsVol, skelScaleMm] = orr(r3polyToUse, STEP_SIZE, XGrid, YGrid, interpolationF) +function [improvedSkeleton, medIntensity,orthIntensVol, orthSamplePointsVol, skelScaleMm] = oor(r3polyToUse, STEP_SIZE, XGrid, YGrid, interpolationF) SND_THRESH=1500; arcLength = polyArcLength3(r3polyToUse, 0, 1); From 40f232485490c4531a3d0ee59ea1f5d5a9d8096a Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 16:44:29 +0100 Subject: [PATCH 021/132] Adding doc template to function oor --- src/Functions/oor.m | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/Functions/oor.m b/src/Functions/oor.m index 9c2ce4a..45a99b1 100644 --- a/src/Functions/oor.m +++ b/src/Functions/oor.m @@ -1,17 +1,28 @@ -%% oor - optimal opliptimal oblique sampling along a given polynonimal +function [improvedSkeleton, medIntensity,orthIntensVol, orthSamplePointsVol, skelScaleMm] = oor(r3polyToUse, STEP_SIZE, XGrid, YGrid, interpolationF) % -% Returns: improvedSkeleton - skeleton gained along the polynomial by -% resampling and intensity weithed centroid calculation -% medIntensity - median intensity profile along the polynoial +% USAGE: % -% Andreas Husch -% Centre Hospitalier de Luxembourg / Luxembourg Centre for Systems -% Biomedicine, University of Luxembourg -% 2016 - 2017 -% mail@andreashusch.de +% [improvedSkeleton, medIntensity, orthIntensVol, orthSamplePointsVol, skelScaleMm] +% = oor(r3polyToUse, STEP_SIZE, XGrid, YGrid, interpolationF) % -% That code needs some cleanup :-) But it works ;-) -function [improvedSkeleton, medIntensity,orthIntensVol, orthSamplePointsVol, skelScaleMm] = oor(r3polyToUse, STEP_SIZE, XGrid, YGrid, interpolationF) +% INPUTS: +% r3polyToUse: +% STEP_SIZE: +% XGrid: +% YGrid: +% interpolationF: +% +% OUTPUTS: +% improvedSkeleton: +% medIntensity: +% orthIntensVol: +% orthSamplePointsVol: +% skelScaleMm: +% +% .. AUTHOR: +% - Andreas Husch, Original File +% - Daniel Duarte Tojal, Documentation + SND_THRESH=1500; arcLength = polyArcLength3(r3polyToUse, 0, 1); From 1e5010cff400ebe8a4dcb0580eaefae81eb0aa64 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 11 Mar 2019 16:55:20 +0100 Subject: [PATCH 022/132] Correcting mistakes in the documentation --- src/Functions/oor.m | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Functions/oor.m b/src/Functions/oor.m index 45a99b1..0a7b014 100644 --- a/src/Functions/oor.m +++ b/src/Functions/oor.m @@ -1,4 +1,5 @@ function [improvedSkeleton, medIntensity,orthIntensVol, orthSamplePointsVol, skelScaleMm] = oor(r3polyToUse, STEP_SIZE, XGrid, YGrid, interpolationF) +% oor - optimal oblique resampling along a given polynonimal % % USAGE: % @@ -13,8 +14,9 @@ % interpolationF: % % OUTPUTS: -% improvedSkeleton: -% medIntensity: +% improvedSkeleton: skeleton gained along the polynomial by +% resampling and intensity weithed centroid calculation +% medIntensity: median intensity profile along the polynoial % orthIntensVol: % orthSamplePointsVol: % skelScaleMm: From c48b86e9333e6493967544345444cc13eafec6f1 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Tue, 5 Mar 2019 18:52:09 +0100 Subject: [PATCH 023/132] Editing the extrensions list for Sphinx --- docs/source/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index 5501225..3634aa0 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -34,6 +34,7 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ + 'sphinx.ext.autodoc', 'sphinxcontrib.fulltoc'] # remove path in function names From 07263da8684d307c5cf1f65ed73b830fc3d29fc6 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Tue, 5 Mar 2019 18:54:08 +0100 Subject: [PATCH 024/132] Adding modules/index to the contents.rst file --- docs/source/contents.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/contents.rst b/docs/source/contents.rst index 18461b7..840228e 100644 --- a/docs/source/contents.rst +++ b/docs/source/contents.rst @@ -6,6 +6,7 @@ PaCER Home gettingStarted + modules/index literature help acknowledgments From f159e1cc707c69eb572016936b5ef5c211ab7ea3 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Tue, 5 Mar 2019 18:56:21 +0100 Subject: [PATCH 025/132] Adding the modules folder to the existing source folder --- docs/source/modules/functions/index.rst | 8 ++++++++ docs/source/modules/index.rst | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 docs/source/modules/functions/index.rst create mode 100644 docs/source/modules/index.rst diff --git a/docs/source/modules/functions/index.rst b/docs/source/modules/functions/index.rst new file mode 100644 index 0000000..06c3928 --- /dev/null +++ b/docs/source/modules/functions/index.rst @@ -0,0 +1,8 @@ +.. _functions: + + +Functions +------------ + +.. automodule:: src.Functions + :members: \ No newline at end of file diff --git a/docs/source/modules/index.rst b/docs/source/modules/index.rst new file mode 100644 index 0000000..ca417a1 --- /dev/null +++ b/docs/source/modules/index.rst @@ -0,0 +1,8 @@ +.. _modules_functions: + +Source Code +========= + +.. toctree:: + + functions/index \ No newline at end of file From 47f93f262f80834db98687e68b960461765cd205 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 5 Mar 2019 19:24:22 +0100 Subject: [PATCH 026/132] adding napoleon and matlab eggs --- docs/requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/requirements.txt b/docs/requirements.txt index fd6f9c7..5f93b57 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -2,3 +2,5 @@ git+https://github.com/uni-lu/sphinx.git@develop#egg=sphinx sphinx_rtd_theme git+https://github.com/uni-lu/sphinx_julia_theme.git@develop#egg=sphinx_julia_theme git+https://github.com/syarra/Documenter.py@develop#egg=documenter +git+https://github.com/uni-lu/sphinxcontrib-napoleon.git@develop#egg=sphinxcontrib_napoleon +git+https://github.com/syarra/sphinxcontrib-matlabdomain#egg=sphinxcontrib-matlabdomain From 08f9bc4bbb163a116b0741b2bb5c9dd267bda3f9 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 5 Mar 2019 19:24:42 +0100 Subject: [PATCH 027/132] registering extension in conf.py --- docs/source/conf.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index 3634aa0..5aa718e 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -24,6 +24,8 @@ sys.path.insert(0, os.path.abspath(os.path.join('..', '..', '..'))) # sys.path.insert(0, os.path.abspath('.')) +matlab_src_dir = os.path.abspath(os.path.join('..', '..')) + # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. @@ -35,6 +37,8 @@ # ones. extensions = [ 'sphinx.ext.autodoc', + 'sphinxcontrib.napoleon', + 'sphinxcontrib.matlab', 'sphinxcontrib.fulltoc'] # remove path in function names From b3ae9236c3477cecfaa09786f9e6fa5074e91253 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 5 Mar 2019 19:24:55 +0100 Subject: [PATCH 028/132] minor header changes --- docs/source/modules/functions/index.rst | 6 +++--- docs/source/modules/index.rst | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/source/modules/functions/index.rst b/docs/source/modules/functions/index.rst index 06c3928..451273b 100644 --- a/docs/source/modules/functions/index.rst +++ b/docs/source/modules/functions/index.rst @@ -2,7 +2,7 @@ Functions ------------- +--------- -.. automodule:: src.Functions - :members: \ No newline at end of file +.. automodule:: src.Functions + :members: diff --git a/docs/source/modules/index.rst b/docs/source/modules/index.rst index ca417a1..dacb20b 100644 --- a/docs/source/modules/index.rst +++ b/docs/source/modules/index.rst @@ -1,8 +1,8 @@ .. _modules_functions: -Source Code -========= +Source code +=========== .. toctree:: - functions/index \ No newline at end of file + functions/index From 453aa6131b08c86f7815a6e8d69e368f79c59960 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 12 Mar 2019 17:03:14 +0100 Subject: [PATCH 029/132] update URLs of documentation depenendencies --- docs/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 5f93b57..bfd97af 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,6 @@ -git+https://github.com/uni-lu/sphinx.git@develop#egg=sphinx +git+https://github.com/LCSB-BioCore/sphinx.git@develop#egg=sphinx sphinx_rtd_theme -git+https://github.com/uni-lu/sphinx_julia_theme.git@develop#egg=sphinx_julia_theme +git+https://github.com/LCSB-BioCore/sphinx_julia_theme.git@develop#egg=sphinx_julia_theme git+https://github.com/syarra/Documenter.py@develop#egg=documenter -git+https://github.com/uni-lu/sphinxcontrib-napoleon.git@develop#egg=sphinxcontrib_napoleon +git+https://github.com/LCSB-BioCore/sphinxcontrib-napoleon.git@develop#egg=sphinxcontrib_napoleon git+https://github.com/syarra/sphinxcontrib-matlabdomain#egg=sphinxcontrib-matlabdomain From 07e27a32b1514cd0fe62639f0659f4cc8c3a32c8 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Wed, 13 Mar 2019 15:46:32 +0100 Subject: [PATCH 030/132] Adding the missing variable descriptions --- src/Functions/oor.m | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/Functions/oor.m b/src/Functions/oor.m index 0a7b014..f66a1dc 100644 --- a/src/Functions/oor.m +++ b/src/Functions/oor.m @@ -1,5 +1,5 @@ function [improvedSkeleton, medIntensity,orthIntensVol, orthSamplePointsVol, skelScaleMm] = oor(r3polyToUse, STEP_SIZE, XGrid, YGrid, interpolationF) -% oor - optimal oblique resampling along a given polynonimal +% OOR - Optimal Oblique Resampling along a given polynonimal % % USAGE: % @@ -7,19 +7,18 @@ % = oor(r3polyToUse, STEP_SIZE, XGrid, YGrid, interpolationF) % % INPUTS: -% r3polyToUse: -% STEP_SIZE: -% XGrid: -% YGrid: -% interpolationF: +% r3polyToUse: Polynomial coefficient matrix +% STEP_SIZE: Step size along polynomial +% XGrid: Grid to sample perpentidular to polyonial (x) +% YGrid: Grid to sample perpentidular to polyonial (y) +% interpolationF: An interpolater fitted to point cloud (see scatteredInterpolant) % % OUTPUTS: -% improvedSkeleton: skeleton gained along the polynomial by -% resampling and intensity weithed centroid calculation -% medIntensity: median intensity profile along the polynoial -% orthIntensVol: -% orthSamplePointsVol: -% skelScaleMm: +% improvedSkeleton: Newly determined skeleton point cloud after re-sampling +% medIntensity: Median intensity along the polynomial +% orthIntensVol: Intensity volume stacked as orthogonal matrix +% orthSamplePointsVol: Sampling points stacked as orthogonal matrix +% skelScaleMm: Estimated millimetric scale % % .. AUTHOR: % - Andreas Husch, Original File From e304d5ca6758f2624797e4956a67d7ecd823952c Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Wed, 13 Mar 2019 16:17:57 +0100 Subject: [PATCH 031/132] Expanding the varargin input into its possible argumentsin the doc --- src/Functions/extractElectrodePointclouds.m | 24 +++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Functions/extractElectrodePointclouds.m b/src/Functions/extractElectrodePointclouds.m index 353e84b..ac6ba06 100644 --- a/src/Functions/extractElectrodePointclouds.m +++ b/src/Functions/extractElectrodePointclouds.m @@ -7,7 +7,13 @@ % % INPUTS: % niiCT: NiftiMod object of a post-operative CT image -% varargin: +% varargin: Variable Argument: +% +% noMask: For phantom studies where no brain is present in data +% brainMask: For manually providing brain mask +% (binary segmentation image file path) +% medtronicXMLPlan: +% metalThreshold: % % OUTPUTS: % elecsPointcloudStruct: Create output struct and try to associate electrodes @@ -27,8 +33,8 @@ argParser = inputParser(); argParser.KeepUnmatched = true; - argParser.addParameter('noMask', false); % for phantom studies where no brain is present in data - argParser.addParameter('brainMask', ''); % for manually providing brain mask (binary segmentation image file path) + argParser.addParameter('noMask', false); + argParser.addParameter('brainMask', ''); argParser.addParameter('medtronicXMLPlan', '', @(x)(ischar(x))); argParser.addParameter('metalThreshold', 800, @(x)(isnumeric(x))); @@ -66,7 +72,7 @@ maskedImg(~(brainMask)) = NaN; threImg = (maskedImg > METAL_THRESHOLD); - %% largest connectet components of metal inside the brain represent electrodes + %% largest connected components of metal inside the brain represent electrodes cc = bwconncomp(threImg,26); disp([num2str(cc.NumObjects) ' potential metal components detected within brain.']); @@ -75,9 +81,9 @@ %% try to guess the number and idxs of electrodes in the image elecIdxs = []; - minVoxelNumber = (1.2 * (1.27/2))^2 * pi * 40 / prod(niiCT.voxsize); % assumin at least 40mm in brain and 20% partial voluming - maxVoxelNumber = (3 * (1.27/2))^2 * pi * 80 / prod(niiCT.voxsize); % assumin 80mm in brain and 300% partial voluming - % maxVoxelNumber = Inf; % FIXME + minVoxelNumber = (1.2 * (1.27/2))^2 * pi * 40 / prod(niiCT.voxsize); % assuming at least 40mm in brain and 20% partial voluming + maxVoxelNumber = (3 * (1.27/2))^2 * pi * 80 / prod(niiCT.voxsize); % assuming 80mm in brain and 300% partial voluming + % maxVoxelNumber = Inf; % FIXME % DEBUG: figure, scatterMatrix3(ccProps(1).PixelList) largeComponents = areas(areas >= minVoxelNumber & areas <= maxVoxelNumber); % Voxels componentIdxs = idxs(areas >= minVoxelNumber & areas <= maxVoxelNumber); @@ -90,7 +96,7 @@ latent = sqrt(latent) * 2; % axes length == variance, * 2 for full (instead half) axes, note that the variance is not the extrem value! % an electrode has large variance in one direction and about the same in the % two others FIXME magic constants! - % pointCloudExtend = norm(max(ccProps(componentIdxs(i)).PixelList) - min(ccProps(componentIdxs(i)).PixelList)) + % pointCloudExtend = norm(max(ccProps(componentIdxs(i)).PixelList) - min(ccProps(componentIdxs(i)).PixelList)) lowerAxesLength = sort(latent(2:3)); if(latent(1) > LAMBDA_1 && latent(1) / mean(latent(2:3)) > 10 && lowerAxesLength(2) / (lowerAxesLength(1)+0.001) < 8) % elecIdxs(end+1) = componentIdxs(i); %#ok @@ -135,7 +141,7 @@ elecsPointcloudStruct(i).pointCloudMm =(pixelList-1) * abs(niiCT.transformationMatrix(1:3,1:3)); % minus 1 is done in the get funtions but manually here elecsPointcloudStruct(i).pointCloudWorld = niiCT.getNiftiWorldCoordinatesFromMatlabIdx(pixelList')';%bsxfun(@plus,(pixelList-1) * niiCT.transformationMatrix(1:3,1:3), niiCT.transformationMatrix(1:3,4)'); - % elecsPointcloudStruct(i).surroundingPoints = setdiff(bbPointCloud, pixelList, 'rows')* abs(niiCT.transformationMatrix(1:3,1:3)); + % elecsPointcloudStruct(i).surroundingPoints = setdiff(bbPointCloud, pixelList, 'rows')* abs(niiCT.transformationMatrix(1:3,1:3)); elecMask = false(size(maskedImg)); % FIXME check this swaps!! elecMask(elecsPointcloudStruct(i).pixelIdxs ) = true; % TODO: make sure we don't have to Swap i,j to X,Y here! From 87f3892c7cc9311d9abf15144f0612b4bedfc480 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Wed, 13 Mar 2019 16:50:19 +0100 Subject: [PATCH 032/132] removed the EXAMPLE and NOTE block --- src/Functions/getIntensityPeaks.m | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Functions/getIntensityPeaks.m b/src/Functions/getIntensityPeaks.m index 9ccb6e3..88ec104 100644 --- a/src/Functions/getIntensityPeaks.m +++ b/src/Functions/getIntensityPeaks.m @@ -6,8 +6,8 @@ % USAGE: % % [peakLocs, peakWaveCenters, peakValues, threshIntensityProfile, -% threshold, contactAreaCenter, contactAreaWidth, xrayMarkerAreaCenter, -% xrayMarkerAreaWidth] = getIntensityPeaks(intensityProfile, skelScaleMm, filterIdxs) +% threshold, contactAreaCenter, contactAreaWidth, xrayMarkerAreaCenter, xrayMarkerAreaWidth] +% = getIntensityPeaks(intensityProfile, skelScaleMm, filterIdxs) % % INPUTS: % intensityProfile: @@ -25,10 +25,6 @@ % xrayMarkerAreaCenter: % xrayMarkerAreaWidth: % -% EXAMPLE: -% -% NOTE: -% % .. AUTHOR: % - Andreas Husch, Original File % - Daniel Duarte Tojal, Documentation From f3db3566d5dcb88388552f2246a87f2b5de06c8c Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 18 Mar 2019 09:38:53 +0100 Subject: [PATCH 033/132] Alligning input/output descriptions and updating authors header --- src/Functions/oor.m | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Functions/oor.m b/src/Functions/oor.m index f66a1dc..2e47131 100644 --- a/src/Functions/oor.m +++ b/src/Functions/oor.m @@ -7,11 +7,11 @@ % = oor(r3polyToUse, STEP_SIZE, XGrid, YGrid, interpolationF) % % INPUTS: -% r3polyToUse: Polynomial coefficient matrix -% STEP_SIZE: Step size along polynomial -% XGrid: Grid to sample perpentidular to polyonial (x) -% YGrid: Grid to sample perpentidular to polyonial (y) -% interpolationF: An interpolater fitted to point cloud (see scatteredInterpolant) +% r3polyToUse: Polynomial coefficient matrix +% STEP_SIZE: Step size along polynomial +% XGrid: Grid to sample perpentidular to polyonial (x) +% YGrid: Grid to sample perpentidular to polyonial (y) +% interpolationF: An interpolater fitted to point cloud (see scatteredInterpolant) % % OUTPUTS: % improvedSkeleton: Newly determined skeleton point cloud after re-sampling @@ -20,7 +20,7 @@ % orthSamplePointsVol: Sampling points stacked as orthogonal matrix % skelScaleMm: Estimated millimetric scale % -% .. AUTHOR: +% .. AUTHORS: % - Andreas Husch, Original File % - Daniel Duarte Tojal, Documentation From 703cc8d57aed1428f5ecc2452469e7aeff7f93c0 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 18 Mar 2019 09:46:59 +0100 Subject: [PATCH 034/132] Authors --- src/Functions/invPolyArcLength3.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Functions/invPolyArcLength3.m b/src/Functions/invPolyArcLength3.m index cfe25dc..d44e55e 100644 --- a/src/Functions/invPolyArcLength3.m +++ b/src/Functions/invPolyArcLength3.m @@ -14,7 +14,7 @@ % OUTPUT: % t: % -% .. AUTHOR: +% .. AUTHORS: % - Andreas Husch, Original File % - Daniel Duarte Tojal, Documentation From 21d132215418a694a5a1e857769f7be4e9567283 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 18 Mar 2019 09:52:22 +0100 Subject: [PATCH 035/132] Authors --- src/Functions/largestConnCompSliceWise.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Functions/largestConnCompSliceWise.m b/src/Functions/largestConnCompSliceWise.m index 062cff9..538231d 100644 --- a/src/Functions/largestConnCompSliceWise.m +++ b/src/Functions/largestConnCompSliceWise.m @@ -10,7 +10,7 @@ % OUTPUT: % binaryMask: % -% .. AUTHOR: +% .. AUTHORS: % - Andreas Husch, Original File % - Daniel Duarte Tojal, Documentation From fdae116f06cc846a40ebd2159ee99230328f2b31 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 18 Mar 2019 09:56:31 +0100 Subject: [PATCH 036/132] Authors --- src/Functions/plotIntensityProfileAndPeaks.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Functions/plotIntensityProfileAndPeaks.m b/src/Functions/plotIntensityProfileAndPeaks.m index 31197a2..66e91bd 100644 --- a/src/Functions/plotIntensityProfileAndPeaks.m +++ b/src/Functions/plotIntensityProfileAndPeaks.m @@ -17,7 +17,7 @@ % threshIntensityProfile: % threshold: % -% .. AUTHOR: +% .. AUTHORS: % - Andreas Husch, Original File % - Daniel Duarte Tojal, Documentation From 052e9dd58e5179e8b3ffcb0ba4bc1e27113aa89e Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 18 Mar 2019 10:03:01 +0100 Subject: [PATCH 037/132] Updating descriptions --- src/Functions/polyArcLength3.m | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Functions/polyArcLength3.m b/src/Functions/polyArcLength3.m index a8716cb..0278aae 100644 --- a/src/Functions/polyArcLength3.m +++ b/src/Functions/polyArcLength3.m @@ -14,9 +14,10 @@ % and lower limit. % % OUTPUT: -% arcLength: Length of the arc. +% arcLength: The arc length is defined as the integral of the norm of the +% derivatives of the parameterized equations. % -% .. AUTHOR: +% .. AUTHORS: % - Andreas Husch, Original File % - Daniel Duarte Tojal, Documentation @@ -34,7 +35,7 @@ arcLength = nan(size(lowerLimit)); for i = 1:length(lowerLimit) - f = @(t) sqrt(polyval(x_d, t).^2 + polyval(y_d, t).^2 + polyval(z_d, t).^2); % The arc length is defined as the integral of the norm of the derivatives of the parameterized equations. + f = @(t) sqrt(polyval(x_d, t).^2 + polyval(y_d, t).^2 + polyval(z_d, t).^2); arcLength(i) = integral(f,lowerLimit(i),upperLimit(i)); end From a617f1a8a36b5028fe94a3f2eaf0b14d74bd5185 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 18 Mar 2019 10:05:47 +0100 Subject: [PATCH 038/132] Adding desc of arclenght --- src/Functions/invPolyArcLength3.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Functions/invPolyArcLength3.m b/src/Functions/invPolyArcLength3.m index d44e55e..6a107ba 100644 --- a/src/Functions/invPolyArcLength3.m +++ b/src/Functions/invPolyArcLength3.m @@ -9,7 +9,8 @@ % % INPUTS: % polyCoeff: Coefficient matrix -% arcLength: +% arcLength: The arc length is defined as the integral of the norm of the +% derivatives of the parameterized equations. % % OUTPUT: % t: From 7d6c96510a7fa603aad3e39b32732c3614b2ac9d Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 18 Mar 2019 10:09:08 +0100 Subject: [PATCH 039/132] Authors --- src/Functions/polyval3.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Functions/polyval3.m b/src/Functions/polyval3.m index 0e21a29..2f0b1e2 100644 --- a/src/Functions/polyval3.m +++ b/src/Functions/polyval3.m @@ -12,7 +12,7 @@ % OUTPUT: % val: % -% .. AUTHOR: +% .. AUTHORS: % - Andreas Husch, Original File % - Daniel Duarte Tojal, Documentation From d624377e783fe399c4ed48bdce21984fb23f99c4 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 18 Mar 2019 10:12:05 +0100 Subject: [PATCH 040/132] Authors --- src/Functions/refitElec.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Functions/refitElec.m b/src/Functions/refitElec.m index 2a635ac..92c1fa5 100644 --- a/src/Functions/refitElec.m +++ b/src/Functions/refitElec.m @@ -24,7 +24,7 @@ % filteredIntensity: % skelScaleMm: % -% .. AUTHOR: +% .. AUTHORS: % - Andreas Husch, Original File % - Daniel Duarte Tojal, Documentation From 08ce2913a606d1afd47143f64b7c405b36e233cc Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 18 Mar 2019 10:18:32 +0100 Subject: [PATCH 041/132] Redo of the doc description --- src/Functions/plotIntensityProfileAndPeaks.m | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/Functions/plotIntensityProfileAndPeaks.m b/src/Functions/plotIntensityProfileAndPeaks.m index 66e91bd..9cf48e6 100644 --- a/src/Functions/plotIntensityProfileAndPeaks.m +++ b/src/Functions/plotIntensityProfileAndPeaks.m @@ -1,27 +1,19 @@ -function [peakLocs, peakWaveCenters, peakValues, threshIntensityProfile, threshold] = getIntensityPeaks(intensityProfile, skelScaleMm, filterIdxs); +function plotIntensityProfileAndPeaks(intensityProfile, skelScaleMm) % % USAGE: % -% [peakLocs, peakWaveCenters, peakValues, threshIntensityProfile, threshold] -% = getIntensityPeaks(intensityProfile, skelScaleMm, filterIdxs); +% plotIntensityProfileAndPeaks(intensityProfile, skelScaleMm) % % INPUTS: % intensityProfile: % skelScaleMm: -% filterIdxs: -% -% OUTPUTS: -% peakLocs -% peakWaveCenters: -% peakValues: -% threshIntensityProfile: -% threshold: % % .. AUTHORS: % - Andreas Husch, Original File % - Daniel Duarte Tojal, Documentation filterIdxs = find(skelScaleMm <= 20); % restrict to first 20mm +[peakLocs, peakWaveCenters, peakValues, threshIntensityProfile, threshold] = getIntensityPeaks(intensityProfile, skelScaleMm, filterIdxs); figure('Name', 'Intensity Profile'); ax = gca; @@ -39,4 +31,3 @@ end -% function plotIntensityProfileAndPeaks(intensityProfile, skelScaleMm) From 72d90b1fe47317a982b7b46fa2d97df0525086b4 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 19 Mar 2019 08:05:24 +0100 Subject: [PATCH 042/132] update of badge url to unprotected --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 295099c..9dc8724 100644 --- a/README.rst +++ b/README.rst @@ -12,7 +12,7 @@ PaCER |br| Precise and Convenient Electrode Reconstruction for DBS
-     +    

.. @@ -207,4 +207,4 @@ for providing the `ARTENOLIS infrastructure `__ an .. |br| raw:: html -
\ No newline at end of file +
From c711ce45ca27641e7c2224f0c49a777c7f7ebfb7 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 19 Mar 2019 14:52:35 +0100 Subject: [PATCH 043/132] instructions to pull data path --- .artenolis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.artenolis.yml b/.artenolis.yml index e6502d1..e464f94 100644 --- a/.artenolis.yml +++ b/.artenolis.yml @@ -7,6 +7,10 @@ script: # set the environment variable CURRENT_DIR - CURRENT_DIR=`pwd` + # update the data repository + - cd $DATA_PACER_PATH + - git pull origin master + # change to the current directory - cd $CURRENT_DIR From 96c70927bf5bbb74fae26d7dcb0806413930a7a0 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 19 Mar 2019 16:13:26 +0100 Subject: [PATCH 044/132] rename env var --- .artenolis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.artenolis.yml b/.artenolis.yml index e464f94..f51d011 100644 --- a/.artenolis.yml +++ b/.artenolis.yml @@ -8,7 +8,7 @@ script: - CURRENT_DIR=`pwd` # update the data repository - - cd $DATA_PACER_PATH + - cd $PACER_DATA_PATH - git pull origin master # change to the current directory From 8223f368b0d3ee98bb2f988d1982f674e78e3ace Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 20 Mar 2019 10:32:36 +0100 Subject: [PATCH 045/132] WIP --- test/testextractElectrodePointclouds.m | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 test/testextractElectrodePointclouds.m diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m new file mode 100644 index 0000000..cec42e1 --- /dev/null +++ b/test/testextractElectrodePointclouds.m @@ -0,0 +1,28 @@ +% The PaCER Toolbox: testExtractElectrodePointclouds.m +% +% Purpose: +% - test the extractElectrodePointclouds function +% +% Author: +% - Loic Marx, March 2019 + +% save the current path +currentDir = pwd; + +% initialize the test +fileDir = fileparts(which(mfilename)); +cd(fileDir); + +% load reference data +refData = load ([getenv('PACER_DATA_PATH') filesep 'ref' filesep 'refData_extractElectrodePC.mat']) + +% generate new data +niiCT_new = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']) +[elecsPointcloudStruct_new, brainMask_new] = extractElectrodePointclouds(niiCT_new); + +% compare the new data against the reference data +assert(isequal(elecsPointcloudStruct_new, refData.elecsPointcloudStruct_ref)) +assert(isequal(brainMask_new, refData.brainMask_ref)) + + + From 2217d7983717e026e16d8e4c646f036c5d977ae5 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 13 Mar 2019 11:06:51 +0100 Subject: [PATCH 046/132] wip --- test/testextractElectrodePointclouds.m | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 test/testextractElectrodePointclouds.m diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m new file mode 100644 index 0000000..b0fdbaf --- /dev/null +++ b/test/testextractElectrodePointclouds.m @@ -0,0 +1,25 @@ +% The PaCER Toolbox: testextractElectrodePointclouds.m +% +% Purpose: +% - test the extractElectrodePointclouds function +% +% Author: +% - Loic Marx, March 2019 + +% save the current path +currentDir = pwd; + +% initialize the test +fileDir = fileparts(which(mfilename)); +cd(fileDir); + +% load reference data +refData = load ('refData_extractElectrodePC.m') + +% generate data +niiCT_new = NiftiMod('ct_post.nii.gz') +[elecsPointcloudStruct_new, brainMask_new] = extractElectrodePointclouds(niiCT) + +% compare the reference data + + From 2de43b129a161c2dc7bb9eaaafd352796bbd25e8 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 13 Mar 2019 11:06:51 +0100 Subject: [PATCH 047/132] wip From 7c717886e27be146b9f183d53460cab318a1ce81 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Thu, 14 Mar 2019 17:12:32 +0100 Subject: [PATCH 048/132] WIP Change path --- test/testextractElectrodePointclouds.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m index b0fdbaf..c77cf95 100644 --- a/test/testextractElectrodePointclouds.m +++ b/test/testextractElectrodePointclouds.m @@ -14,10 +14,10 @@ cd(fileDir); % load reference data -refData = load ('refData_extractElectrodePC.m') +refData = load ([getenv('PACER_DATA_PATH') filesep 'refData_extractElectrodePC.m']) % generate data -niiCT_new = NiftiMod('ct_post.nii.gz') +niiCT_new = NiftiMod([getenv('PACER_DATA_PATH') filesep 'ct_post.nii.gz']) [elecsPointcloudStruct_new, brainMask_new] = extractElectrodePointclouds(niiCT) % compare the reference data From 8860aeba819766491e0c4be703452ff3e256cf8b Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Mon, 18 Mar 2019 11:36:28 +0100 Subject: [PATCH 049/132] WIP test with no brainMask --- test/testextractElectrodePointclouds.m | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m index c77cf95..3da001f 100644 --- a/test/testextractElectrodePointclouds.m +++ b/test/testextractElectrodePointclouds.m @@ -1,4 +1,4 @@ -% The PaCER Toolbox: testextractElectrodePointclouds.m +% The PaCER Toolbox: testExtractElectrodePointclouds.m % % Purpose: % - test the extractElectrodePointclouds function @@ -14,12 +14,13 @@ cd(fileDir); % load reference data -refData = load ([getenv('PACER_DATA_PATH') filesep 'refData_extractElectrodePC.m']) +refData = load ([getenv('PACER_DATA_PATH') filesep 'ref' filesep 'refData_extractElectrodePC.mat']) -% generate data -niiCT_new = NiftiMod([getenv('PACER_DATA_PATH') filesep 'ct_post.nii.gz']) -[elecsPointcloudStruct_new, brainMask_new] = extractElectrodePointclouds(niiCT) - -% compare the reference data +% generate new data +niiCT_new = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']) +[elecsPointcloudStruct_new, brainMask_new] = extractElectrodePointclouds(niiCT_new); +% compare the new data against the reference data +assert(isequal(elecsPointcloudStruct_new, refData.elecsPointcloudStruct_ref)) +assert(isequal(brainMask_new, refData.brainMask_ref)) From 811f23b880f4289df7d855e86659b60adba2352f Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 20 Mar 2019 17:23:32 +0100 Subject: [PATCH 050/132] adding the different environmental variables to testAll --- test/testAll.m | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/testAll.m b/test/testAll.m index 4192337..f133c5b 100644 --- a/test/testAll.m +++ b/test/testAll.m @@ -55,4 +55,11 @@ cd(origDir); rethrow(ME); end -end \ No newline at end of file +end + +% load the different environment variables +global refDataPath +global inputDataPath + +refDataPath = [getenv('PACER_DATA_PATH') filesep 'ref'] +inputDataPath = [getenv('PACER_DATA_PATH') filesep 'input'] \ No newline at end of file From 089c55631c1b3264a723aca2d9f0599f13b63a09 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 20 Mar 2019 17:28:37 +0100 Subject: [PATCH 051/132] WIP apply post CT Mask --- test/testextractElectrodePointclouds.m | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m index cec42e1..f5c0ef9 100644 --- a/test/testextractElectrodePointclouds.m +++ b/test/testextractElectrodePointclouds.m @@ -14,6 +14,8 @@ cd(fileDir); % load reference data +global refDataPath +global inputDataPath refData = load ([getenv('PACER_DATA_PATH') filesep 'ref' filesep 'refData_extractElectrodePC.mat']) % generate new data @@ -24,5 +26,11 @@ assert(isequal(elecsPointcloudStruct_new, refData.elecsPointcloudStruct_ref)) assert(isequal(brainMask_new, refData.brainMask_ref)) +% apply post CT brain mask +niiCT_brainMask_ref = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']) +brainMask_ref = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post_mask.nii']) + +brainMask_ref= [getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post_mask.nii'] +[elecsPointcloudStruct_brainMask_ref, brainMask_brainMask_ref] = extractElectrodePointclouds(niiCT_brainMask_ref,'brainMask',brainMask_ref); From 368a1283469b46a477979edc6733276c913e3ba9 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 20 Mar 2019 17:35:57 +0100 Subject: [PATCH 052/132] WIP reorganizing test file --- test/testextractElectrodePointclouds.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m index f5c0ef9..9d2d706 100644 --- a/test/testextractElectrodePointclouds.m +++ b/test/testextractElectrodePointclouds.m @@ -6,6 +6,9 @@ % Author: % - Loic Marx, March 2019 +global refDataPath +global inputDataPath + % save the current path currentDir = pwd; @@ -14,12 +17,10 @@ cd(fileDir); % load reference data -global refDataPath -global inputDataPath -refData = load ([getenv('PACER_DATA_PATH') filesep 'ref' filesep 'refData_extractElectrodePC.mat']) +refData = load([refDataPath filesep 'refData_extractElectrodePC.mat']); +niiCT_new = load ([inputDataPath filesep 'ct_post.nii.gz']); % generate new data -niiCT_new = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']) [elecsPointcloudStruct_new, brainMask_new] = extractElectrodePointclouds(niiCT_new); % compare the new data against the reference data @@ -30,7 +31,6 @@ niiCT_brainMask_ref = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']) brainMask_ref = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post_mask.nii']) -brainMask_ref= [getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post_mask.nii'] [elecsPointcloudStruct_brainMask_ref, brainMask_brainMask_ref] = extractElectrodePointclouds(niiCT_brainMask_ref,'brainMask',brainMask_ref); From 493c13cc1aad5e541f9835ba5b37861a556e60d1 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 20 Mar 2019 18:08:31 +0100 Subject: [PATCH 053/132] WIP --- test/testextractElectrodePointclouds.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m index 9d2d706..361427f 100644 --- a/test/testextractElectrodePointclouds.m +++ b/test/testextractElectrodePointclouds.m @@ -17,8 +17,8 @@ cd(fileDir); % load reference data -refData = load([refDataPath filesep 'refData_extractElectrodePC.mat']); -niiCT_new = load ([inputDataPath filesep 'ct_post.nii.gz']); +refData = [refDataPath filesep 'refData_extractElectrodePC.mat']; +niiCT_new = [inputDataPath filesep 'ct_post.nii.gz']; % generate new data [elecsPointcloudStruct_new, brainMask_new] = extractElectrodePointclouds(niiCT_new); @@ -28,9 +28,9 @@ assert(isequal(brainMask_new, refData.brainMask_ref)) % apply post CT brain mask -niiCT_brainMask_ref = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']) -brainMask_ref = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post_mask.nii']) +niiCT_brainMask_ref = [inputDataPath filesep 'ct_post.nii.gz']; +brainMask_ref = [inputDataPath filesep 'ct_post_mask.nii']; -[elecsPointcloudStruct_brainMask_ref, brainMask_brainMask_ref] = extractElectrodePointclouds(niiCT_brainMask_ref,'brainMask',brainMask_ref); +[elecsPointcloudStruct_brainMask_ref, brainMask_brainMask_ref] = extractElectrodePointclouds(niiCT_brainMask_ref, 'brainMask', brainMask_ref); From cc8fc8dafd94662293703b1ab2cdc0ed01620c77 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Thu, 21 Mar 2019 11:42:21 +0100 Subject: [PATCH 054/132] WIP fixing path issue --- test/testextractElectrodePointclouds.m | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m index 361427f..156478a 100644 --- a/test/testextractElectrodePointclouds.m +++ b/test/testextractElectrodePointclouds.m @@ -17,10 +17,10 @@ cd(fileDir); % load reference data -refData = [refDataPath filesep 'refData_extractElectrodePC.mat']; -niiCT_new = [inputDataPath filesep 'ct_post.nii.gz']; +refData = load ([getenv('PACER_DATA_PATH') filesep 'ref' filesep 'refData_extractElectrodePC.mat']) % generate new data +niiCT_new = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']) [elecsPointcloudStruct_new, brainMask_new] = extractElectrodePointclouds(niiCT_new); % compare the new data against the reference data @@ -28,9 +28,8 @@ assert(isequal(brainMask_new, refData.brainMask_ref)) % apply post CT brain mask -niiCT_brainMask_ref = [inputDataPath filesep 'ct_post.nii.gz']; -brainMask_ref = [inputDataPath filesep 'ct_post_mask.nii']; - -[elecsPointcloudStruct_brainMask_ref, brainMask_brainMask_ref] = extractElectrodePointclouds(niiCT_brainMask_ref, 'brainMask', brainMask_ref); +niiCT_brainMask_ref = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']) +brainMaskPath = [inputDataPath filesep 'ct_post_mask.nii'] +[elecsPointcloudStruct_brainMask_ref, brainMask_brainMask_ref] = extractElectrodePointclouds(niiCT_brainMask_ref, 'brainMask', brainMaskPath); From 111027664f698d7f6d17f3d5b9a8a57eb19c2c83 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Thu, 21 Mar 2019 15:01:28 +0100 Subject: [PATCH 055/132] Updating variable descriptions --- src/Functions/refitElec.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Functions/refitElec.m b/src/Functions/refitElec.m index 92c1fa5..32e4e43 100644 --- a/src/Functions/refitElec.m +++ b/src/Functions/refitElec.m @@ -21,8 +21,8 @@ % refitReZeroedElecMod: polynomialElectrodeModel Object with the % refitted and rezeored elec model, % including reference to elecInfo etc. -% filteredIntensity: -% skelScaleMm: +% filteredIntensity: 1D intensity profile +% skelScaleMm: estimated mm per skeleton step % % .. AUTHORS: % - Andreas Husch, Original File From 61271336be880536fa2737ed0ebe7f582a4fd0d1 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Thu, 21 Mar 2019 15:01:34 +0100 Subject: [PATCH 056/132] WIP --- test/testextractElectrodePointclouds.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m index 156478a..a48adbd 100644 --- a/test/testextractElectrodePointclouds.m +++ b/test/testextractElectrodePointclouds.m @@ -29,7 +29,7 @@ % apply post CT brain mask niiCT_brainMask_ref = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']) -brainMaskPath = [inputDataPath filesep 'ct_post_mask.nii'] +brainMaskPath = [getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post_mask.nii'] [elecsPointcloudStruct_brainMask_ref, brainMask_brainMask_ref] = extractElectrodePointclouds(niiCT_brainMask_ref, 'brainMask', brainMaskPath); From 2141569c31b0e7ef17737d1c1b050627b77ae1fa Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Thu, 21 Mar 2019 15:49:41 +0100 Subject: [PATCH 057/132] compare the new data against the reference data using a BrainMask --- test/testextractElectrodePointclouds.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m index a48adbd..8f4ee83 100644 --- a/test/testextractElectrodePointclouds.m +++ b/test/testextractElectrodePointclouds.m @@ -28,8 +28,12 @@ assert(isequal(brainMask_new, refData.brainMask_ref)) % apply post CT brain mask -niiCT_brainMask_ref = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']) +refData_brainMask = load ([getenv('PACER_DATA_PATH') filesep 'ref' filesep 'refData_extractElectrodePC_withBrainMask.mat']) +niiCT_brainMask_new = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']) brainMaskPath = [getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post_mask.nii'] -[elecsPointcloudStruct_brainMask_ref, brainMask_brainMask_ref] = extractElectrodePointclouds(niiCT_brainMask_ref, 'brainMask', brainMaskPath); +[elecsPointcloudStruct_brainMask_new, brainMask_brainMask_new] = extractElectrodePointclouds(niiCT_brainMask_new, 'brainMask', brainMaskPath); +% compare the new data against the reference data using a BrainMask +assert(isequal(elecsPointcloudStruct_brainMask_new, refData_brainMask.elecsPointcloudStruct_brainMask_ref)) +assert(isequal(brainMask_brainMask_new, refData_brainMask.brainMask_brainMask_ref)) From d57ce3767b790a96e0f67853210824b8ad2c1e7a Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Fri, 22 Mar 2019 11:06:52 +0100 Subject: [PATCH 058/132] load environmental variable --- SETUP_PACER.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/SETUP_PACER.m b/SETUP_PACER.m index 8243e77..2e8a957 100644 --- a/SETUP_PACER.m +++ b/SETUP_PACER.m @@ -6,7 +6,12 @@ % 2017 % mail@andreashusch.de, husch.andreas@chl.lu +global refDataPath +global inputDataPath + %% RUN this file once (F5) to automatically make sure all PaCER files (including subdirectories) are in your MATLAB path! pacerDir = fileparts(mfilename('fullpath')); addpath(genpath(pacerDir)); -savepath(); \ No newline at end of file +savepath(); +refDataPath = [getenv('PACER_DATA_PATH') filesep 'ref' filesep]; +inputDataPath = [getenv('PACER_DATA_PATH') filesep 'input' filesep]; \ No newline at end of file From 969dc0f15cb13b243a66c841a2594abd94b90ef1 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Fri, 22 Mar 2019 11:40:50 +0100 Subject: [PATCH 059/132] WIP clean up of the code --- test/testextractElectrodePointclouds.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m index 8f4ee83..c316a69 100644 --- a/test/testextractElectrodePointclouds.m +++ b/test/testextractElectrodePointclouds.m @@ -17,10 +17,10 @@ cd(fileDir); % load reference data -refData = load ([getenv('PACER_DATA_PATH') filesep 'ref' filesep 'refData_extractElectrodePC.mat']) +refData = load([refDataPath 'refData_extractElectrodePC.mat']); % generate new data -niiCT_new = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']) +niiCT_new = NiftiMod([inputDataPath 'ct_post.nii.gz']) [elecsPointcloudStruct_new, brainMask_new] = extractElectrodePointclouds(niiCT_new); % compare the new data against the reference data @@ -28,9 +28,9 @@ assert(isequal(brainMask_new, refData.brainMask_ref)) % apply post CT brain mask -refData_brainMask = load ([getenv('PACER_DATA_PATH') filesep 'ref' filesep 'refData_extractElectrodePC_withBrainMask.mat']) -niiCT_brainMask_new = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']) -brainMaskPath = [getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post_mask.nii'] +refData_brainMask = load ([refDataPath 'refData_extractElectrodePC_withBrainMask.mat']) +niiCT_brainMask_new = NiftiMod([inputDataPath 'ct_post.nii.gz']) +brainMaskPath = [inputDataPath 'ct_post_mask.nii'] [elecsPointcloudStruct_brainMask_new, brainMask_brainMask_new] = extractElectrodePointclouds(niiCT_brainMask_new, 'brainMask', brainMaskPath); % compare the new data against the reference data using a BrainMask From 38791c40aa84bbaa5d6d513adf821532cb9364a1 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Fri, 22 Mar 2019 14:32:18 +0100 Subject: [PATCH 060/132] create verify error function --- test/verifyFunctionError.m | 58 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 test/verifyFunctionError.m diff --git a/test/verifyFunctionError.m b/test/verifyFunctionError.m new file mode 100644 index 0000000..61b2f1e --- /dev/null +++ b/test/verifyFunctionError.m @@ -0,0 +1,58 @@ +function success = verifyFunctionError(functionCall, varargin) +% Tests whether the provided call throws an error and if the error message +% fits to the message provided +% +% USAGE: +% +% success = verifyFunctionError(functionCall, message) +% +% INPUTS: +% functionCall: The name of a function. +% +% OPTIONAL INPUTS: +% +% varargin: Parameter Value pairs for specific options. +% * outputArgCount - The number of output arguments requested, as this can influence the functionality (Default: 0). +% * testMessage - The message that should be thrown in this error. If no message is supplied, any thrown error will be accepted +% * inputs - If the function requires Any inputs, provide them in a cell array. +% +% OUTPUTS: +% success: Whether an error was thrown, and the type and +% message match (if provided) +% AUTHOR: +% - Loic Marx, March 2019 + +testMessage = false; +parser = inputParser(); +parser.addRequired('functionCall',@ischar) +parser.addParamValue('inputs',{},@iscell) +parser.addParamValue('testMessage','',@ischar) +parser.addParamValue('outputArgCount',0,@(x) isnumeric(x) && mod(x,1) == 0); + +parser.parse(functionCall,varargin{:}); + +outputArgcount = parser.Results.outputArgCount; +testMessage = ~any(ismember('testMessage',parser.UsingDefaults)); +message = parser.Results.testMessage; +inputs = parser.Results.inputs; + +functionCall = str2func(functionCall); +success = true; +try + if outputArgcount > 0 + outArgs = cell(outputArgcount,1); + [outArgs{:}] = functionCall(inputs{:}); + else + functionCall(inputs{:}); + end +catch ME + if testMessage + success = strcmp(ME.message,message); + end + %Now, we checked the message if necessary, and we are obvously in the + %catch block, so an error was thrown, i.e. this is successful. + return +end +%If we reach this point, the function did not throw an error. i.e. the +%verification is unsuccessful. +success = false; \ No newline at end of file From 2d868feaa1c3ec291e3791169bdb167902a8831c Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Fri, 22 Mar 2019 15:03:59 +0100 Subject: [PATCH 061/132] formate the header --- test/verifyFunctionError.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/verifyFunctionError.m b/test/verifyFunctionError.m index 61b2f1e..ffc64b1 100644 --- a/test/verifyFunctionError.m +++ b/test/verifyFunctionError.m @@ -20,7 +20,9 @@ % success: Whether an error was thrown, and the type and % message match (if provided) % AUTHOR: -% - Loic Marx, March 2019 +% - Loic Marx, March 2019 (adapted from +% https://github.com/opencobra/cobratoolbox/blob/master/test/verifyCobraFunctionError.m) +% 5aa9ccd testMessage = false; parser = inputParser(); From bb91c32c7cfc1d1a56ec8011370347bce96e776d Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Fri, 22 Mar 2019 15:42:07 +0100 Subject: [PATCH 062/132] deleted env variable --- SETUP_PACER.m | 5 ----- 1 file changed, 5 deletions(-) diff --git a/SETUP_PACER.m b/SETUP_PACER.m index 2e8a957..b1b461c 100644 --- a/SETUP_PACER.m +++ b/SETUP_PACER.m @@ -6,12 +6,7 @@ % 2017 % mail@andreashusch.de, husch.andreas@chl.lu -global refDataPath -global inputDataPath - %% RUN this file once (F5) to automatically make sure all PaCER files (including subdirectories) are in your MATLAB path! pacerDir = fileparts(mfilename('fullpath')); addpath(genpath(pacerDir)); savepath(); -refDataPath = [getenv('PACER_DATA_PATH') filesep 'ref' filesep]; -inputDataPath = [getenv('PACER_DATA_PATH') filesep 'input' filesep]; \ No newline at end of file From 5ebf9bb4647920541b3dc2a7c26397f44785e618 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Fri, 22 Mar 2019 15:44:01 +0100 Subject: [PATCH 063/132] formating the code --- test/testAll.m | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/testAll.m b/test/testAll.m index f133c5b..913826b 100644 --- a/test/testAll.m +++ b/test/testAll.m @@ -1,3 +1,10 @@ +% load the different environment variables +global refDataPath +global inputDataPath + +refDataPath = [getenv('PACER_DATA_PATH') filesep 'ref'] +inputDataPath = [getenv('PACER_DATA_PATH') filesep 'input'] + % request explicitly from the user to launch test suite locally if isempty(strfind(getenv('HOME'), 'jenkins')) reply = ''; @@ -56,10 +63,3 @@ rethrow(ME); end end - -% load the different environment variables -global refDataPath -global inputDataPath - -refDataPath = [getenv('PACER_DATA_PATH') filesep 'ref'] -inputDataPath = [getenv('PACER_DATA_PATH') filesep 'input'] \ No newline at end of file From aa8802abcb7e9dbc459ba84b5d80973e32c4c8ca Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Mon, 25 Mar 2019 15:51:34 +0100 Subject: [PATCH 064/132] cleaning the code --- src/Functions/createSimpleMPRWorldCoordinates.m | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Functions/createSimpleMPRWorldCoordinates.m b/src/Functions/createSimpleMPRWorldCoordinates.m index 60b76cf..75d48ed 100644 --- a/src/Functions/createSimpleMPRWorldCoordinates.m +++ b/src/Functions/createSimpleMPRWorldCoordinates.m @@ -1,16 +1,15 @@ -function [mpr, oc] = createSimpleMPRWorldCoordinates(nii) +function [mpr] = createSimpleMPRWorldCoordinates(nii) % Convenience Wrapper for the MPRWorldCoordinate Class by Florian Bernard % % USAGE: % -% [mpr, oc] = createSimpleMPRWorldCoordinates(nii) +% [mpr] = createSimpleMPRWorldCoordinates(nii) % % INPUT: % nii: NiftiModality object to visualize as multi-planar-reformatting (MPR) % % OUTPUTS: % mpr: Handle to MPR -% oc: optional orientation cube (deprecated) % % .. AUTHOR: % - Andreas Husch, Original file @@ -19,6 +18,4 @@ axesObj = gca; %axesObj = axes('Parent', mprPanel); %mprPanel = uipanel('Parent', gcf); mpr = MPRWorldCoordinates(axesObj, nii.img, [0 0 0], nii); view(160,10); -%oc = OrientationCube(mprPanel, axesObj); -%axes(axesObj); end \ No newline at end of file From 21f644e8d33aba42b2473aa640db1f314e3fd329 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Thu, 28 Mar 2019 13:41:52 +0100 Subject: [PATCH 065/132] update function descriptions --- src/Functions/extractElectrodePointclouds.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Functions/extractElectrodePointclouds.m b/src/Functions/extractElectrodePointclouds.m index ac6ba06..8420202 100644 --- a/src/Functions/extractElectrodePointclouds.m +++ b/src/Functions/extractElectrodePointclouds.m @@ -12,8 +12,9 @@ % noMask: For phantom studies where no brain is present in data % brainMask: For manually providing brain mask % (binary segmentation image file path) -% medtronicXMLPlan: -% metalThreshold: +% medtronicXMLPlan: Path to XML file defining a Medtronic Stealth Station +% S7 trajectory plan +% metalThreshold: CT metal threshold value. % % OUTPUTS: % elecsPointcloudStruct: Create output struct and try to associate electrodes From 0b6dac9cd13451ef3a220a1f5214d07c9b2d0c41 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Thu, 28 Mar 2019 14:43:56 +0100 Subject: [PATCH 066/132] Complete documentation of the function --- src/Functions/fitParamPolyToSkeleton.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Functions/fitParamPolyToSkeleton.m b/src/Functions/fitParamPolyToSkeleton.m index 53c866b..086d0ef 100644 --- a/src/Functions/fitParamPolyToSkeleton.m +++ b/src/Functions/fitParamPolyToSkeleton.m @@ -7,13 +7,13 @@ % % INPUTS: % skeleton: 3 x N skeleton pointcloud -% degree: degree of fitted polynomial (DEFAULT: 3) +% degree: Degree of fitted polynomial (DEFAULT: 3) % % OUTPUTS: -% r3polynomial: -% avgTperMm: +% r3polynomial: Coefficient matrix of fitted polynomial +% avgTperMm: Average "t" per millimeter along the arc length of the polynomial % -% .. AUTHOR: +% .. AUTHORS: % - Andreas Husch, Original file % - DanielDuarte Tojal, Documentation From ed8f64edd135801a7de993efe6ae33ddf96c808e Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Thu, 28 Mar 2019 15:05:42 +0100 Subject: [PATCH 067/132] Complete the function description --- src/Functions/invPolyArcLength3.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Functions/invPolyArcLength3.m b/src/Functions/invPolyArcLength3.m index 6a107ba..dcb1d96 100644 --- a/src/Functions/invPolyArcLength3.m +++ b/src/Functions/invPolyArcLength3.m @@ -10,10 +10,10 @@ % INPUTS: % polyCoeff: Coefficient matrix % arcLength: The arc length is defined as the integral of the norm of the -% derivatives of the parameterized equations. +% derivatives of the parameterized equations, given in mm. % % OUTPUT: -% t: +% t: Parameter of the polynomial % % .. AUTHORS: % - Andreas Husch, Original File From 2c568afc4326827f3c3f5d5cf94154a86806ffe2 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Thu, 28 Mar 2019 15:23:09 +0100 Subject: [PATCH 068/132] Complete the function documentation --- src/Functions/largestConnCompSliceWise.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Functions/largestConnCompSliceWise.m b/src/Functions/largestConnCompSliceWise.m index 538231d..cac5d6e 100644 --- a/src/Functions/largestConnCompSliceWise.m +++ b/src/Functions/largestConnCompSliceWise.m @@ -5,10 +5,11 @@ % binaryMask = largestConnCompSliceWise(img3d) % % INPUT: -% img3d: +% img3d: An image volume % % OUTPUT: -% binaryMask: +% binaryMask: Binary mask of the largest connected +% component within that volume, computed slice wise 2d and stacked % % .. AUTHORS: % - Andreas Husch, Original File From 5333878a919a28519ff69d7e7b40f7b8dbc33a81 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Thu, 28 Mar 2019 15:44:24 +0100 Subject: [PATCH 069/132] Update the function header --- src/Functions/largestConnCompSliceWise.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Functions/largestConnCompSliceWise.m b/src/Functions/largestConnCompSliceWise.m index cac5d6e..edc37db 100644 --- a/src/Functions/largestConnCompSliceWise.m +++ b/src/Functions/largestConnCompSliceWise.m @@ -1,4 +1,6 @@ function binaryMask = largestConnCompSliceWise(img3d) +% Outputs a Binary mask of the largest connected component within that volume, +% computed slice wise 2d and stacked % % USAGE: % From df7502bb22c7a79d08fa3a85988ce798cd489354 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Fri, 29 Mar 2019 11:59:59 +0100 Subject: [PATCH 070/132] testing with XML plan --- test/testextractElectrodePointclouds.m | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m index c316a69..9019374 100644 --- a/test/testextractElectrodePointclouds.m +++ b/test/testextractElectrodePointclouds.m @@ -37,3 +37,11 @@ assert(isequal(elecsPointcloudStruct_brainMask_new, refData_brainMask.elecsPointcloudStruct_brainMask_ref)) assert(isequal(brainMask_brainMask_new, refData_brainMask.brainMask_brainMask_ref)) +% load reference data for CT post OP with XML file +refData_Xml = load([refDataPath 'refData_extractElectrodePC_xmlPlan']); +niiCT_Xml_new = NiftiMod([inputDataPath 'CT_POSTOP_with_XML.nii.gz']) +xml_Plan_new = [inputDataPath 'CT_POSTOP_with_XML.xml']; + +[elecModels_xml_new, elecPointCloudsStruct_xml_new] = PaCER(niiCT_Xml_new, 'medtronicXMLPlan', xml_Plan_new, 'electrodeType', 'Medtronic 3389'); + +% compare the new data against the reference data using a XML plan From 909c5ed8c001d4b03dd754a7193a06ffc80b04cb Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Fri, 29 Mar 2019 14:20:43 +0100 Subject: [PATCH 071/132] assertion with xml file --- test/testextractElectrodePointclouds.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m index 9019374..d3c46b9 100644 --- a/test/testextractElectrodePointclouds.m +++ b/test/testextractElectrodePointclouds.m @@ -37,11 +37,12 @@ assert(isequal(elecsPointcloudStruct_brainMask_new, refData_brainMask.elecsPointcloudStruct_brainMask_ref)) assert(isequal(brainMask_brainMask_new, refData_brainMask.brainMask_brainMask_ref)) -% load reference data for CT post OP with XML file -refData_Xml = load([refDataPath 'refData_extractElectrodePC_xmlPlan']); +% load reference data for CT post OP with the corresponding XML file +refData_Xml = load([refDataPath 'refData_extractElectrodePC_xmlPlan.mat']); niiCT_Xml_new = NiftiMod([inputDataPath 'CT_POSTOP_with_XML.nii.gz']) xml_Plan_new = [inputDataPath 'CT_POSTOP_with_XML.xml']; - -[elecModels_xml_new, elecPointCloudsStruct_xml_new] = PaCER(niiCT_Xml_new, 'medtronicXMLPlan', xml_Plan_new, 'electrodeType', 'Medtronic 3389'); +[elecsPointcloudStruct_Xml_new, brainMask_Xml_new] = extractElectrodePointclouds(niiCT_Xml_new, 'medtronicXMLPlan', xml_Plan_new); % compare the new data against the reference data using a XML plan +assert(isequal(elecsPointcloudStruct_Xml_new, refData_Xml.elecsPointcloudStruct_Xml_ref)) +assert(isequal(brainMask_Xml_new, refData_Xml.brainMask_Xml_ref)) \ No newline at end of file From 6d923c6848a9b74509994d8654922b6db6f0fbae Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Fri, 29 Mar 2019 14:40:46 +0100 Subject: [PATCH 072/132] cleaning code --- test/testextractElectrodePointclouds.m | 35 ++++++++++++++++++-------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m index d3c46b9..e905707 100644 --- a/test/testextractElectrodePointclouds.m +++ b/test/testextractElectrodePointclouds.m @@ -9,40 +9,53 @@ global refDataPath global inputDataPath -% save the current path +%% save the current path currentDir = pwd; % initialize the test fileDir = fileparts(which(mfilename)); cd(fileDir); -% load reference data +%% load reference data (function implemented only with niiCT model) refData = load([refDataPath 'refData_extractElectrodePC.mat']); -% generate new data -niiCT_new = NiftiMod([inputDataPath 'ct_post.nii.gz']) +% define input argument (testing only niiCT input argument) +niiCT_new = NiftiMod([inputDataPath 'ct_post.nii.gz']); + +% generate the new output (testing only niiCT input argument) [elecsPointcloudStruct_new, brainMask_new] = extractElectrodePointclouds(niiCT_new); % compare the new data against the reference data assert(isequal(elecsPointcloudStruct_new, refData.elecsPointcloudStruct_ref)) assert(isequal(brainMask_new, refData.brainMask_ref)) -% apply post CT brain mask -refData_brainMask = load ([refDataPath 'refData_extractElectrodePC_withBrainMask.mat']) -niiCT_brainMask_new = NiftiMod([inputDataPath 'ct_post.nii.gz']) -brainMaskPath = [inputDataPath 'ct_post_mask.nii'] +%% load reference data (provide brain mask to the CT post OP) +refData_brainMask = load([refDataPath 'refData_extractElectrodePC_withBrainMask.mat']); + +% define input arguments (testing niiCT and brainMask) +niiCT_brainMask_new = NiftiMod([inputDataPath 'ct_post.nii.gz']); +brainMaskPath = [inputDataPath 'ct_post_mask.nii']; + +% generate the new output (testing niiCT and brainMask) [elecsPointcloudStruct_brainMask_new, brainMask_brainMask_new] = extractElectrodePointclouds(niiCT_brainMask_new, 'brainMask', brainMaskPath); % compare the new data against the reference data using a BrainMask assert(isequal(elecsPointcloudStruct_brainMask_new, refData_brainMask.elecsPointcloudStruct_brainMask_ref)) assert(isequal(brainMask_brainMask_new, refData_brainMask.brainMask_brainMask_ref)) -% load reference data for CT post OP with the corresponding XML file +%% load reference data for CT post OP with the corresponding XML file refData_Xml = load([refDataPath 'refData_extractElectrodePC_xmlPlan.mat']); -niiCT_Xml_new = NiftiMod([inputDataPath 'CT_POSTOP_with_XML.nii.gz']) + +% define input arguments (testing niiCT and Xml Plan) +niiCT_Xml_new = NiftiMod([inputDataPath 'CT_POSTOP_with_XML.nii.gz']); xml_Plan_new = [inputDataPath 'CT_POSTOP_with_XML.xml']; + +% generate the new output (function implemented with XML plan) [elecsPointcloudStruct_Xml_new, brainMask_Xml_new] = extractElectrodePointclouds(niiCT_Xml_new, 'medtronicXMLPlan', xml_Plan_new); % compare the new data against the reference data using a XML plan assert(isequal(elecsPointcloudStruct_Xml_new, refData_Xml.elecsPointcloudStruct_Xml_ref)) -assert(isequal(brainMask_Xml_new, refData_Xml.brainMask_Xml_ref)) \ No newline at end of file +assert(isequal(brainMask_Xml_new, refData_Xml.brainMask_Xml_ref)) + +%% change back to the current directory +cd(currentDir); \ No newline at end of file From 031da34130022e2806761f57307f4b1eed08fd3a Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Fri, 29 Mar 2019 15:05:55 +0100 Subject: [PATCH 073/132] test if the function throws an error --- test/testextractElectrodePointclouds.m | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m index e905707..ded423e 100644 --- a/test/testextractElectrodePointclouds.m +++ b/test/testextractElectrodePointclouds.m @@ -57,5 +57,12 @@ assert(isequal(elecsPointcloudStruct_Xml_new, refData_Xml.elecsPointcloudStruct_Xml_ref)) assert(isequal(brainMask_Xml_new, refData_Xml.brainMask_Xml_ref)) +%% test the error message in the test +% define metal threshold +METAL_THRESHOLD = 3200; + +% test if extractElectrodePointclouds throws an error when METAL_THRESHOLD value is too high +assert(verifyFunctionError('extractElectrodePointclouds', 'inputs', {niiCT_brainMask_new, 'brainMask', brainMaskPath, 'metalThreshold', METAL_THRESHOLD}, 'testMessage','NO electrode artifact found within brain mask. Did you supply a post-op brain CT image? \n Try the ''no mask'' parameter in case of phantom scans without brain. \n Try providing an externally created brain mask using the "brainMask" parameter in other cases.')); + %% change back to the current directory cd(currentDir); \ No newline at end of file From 8fa8340f5311dd16c15fdea4a5157e59667598e6 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Fri, 29 Mar 2019 15:10:45 +0100 Subject: [PATCH 074/132] formating --- test/testextractElectrodePointclouds.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testextractElectrodePointclouds.m b/test/testextractElectrodePointclouds.m index ded423e..3faf29f 100644 --- a/test/testextractElectrodePointclouds.m +++ b/test/testextractElectrodePointclouds.m @@ -58,7 +58,7 @@ assert(isequal(brainMask_Xml_new, refData_Xml.brainMask_Xml_ref)) %% test the error message in the test -% define metal threshold +% define high metal threshold METAL_THRESHOLD = 3200; % test if extractElectrodePointclouds throws an error when METAL_THRESHOLD value is too high From 5547c3d2995113f46dcce9bf9a4776310769f867 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Mon, 1 Apr 2019 15:10:44 +0200 Subject: [PATCH 075/132] Update function description --- src/Functions/polyval3.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Functions/polyval3.m b/src/Functions/polyval3.m index 2f0b1e2..b8b59ec 100644 --- a/src/Functions/polyval3.m +++ b/src/Functions/polyval3.m @@ -7,10 +7,10 @@ % % INPUTS: % polyCoeffs: Coefficient matrix -% evalAt: +% evalAt: a polynomial in R^3 % % OUTPUT: -% val: +% val: a polynomial in R % % .. AUTHORS: % - Andreas Husch, Original File From cb6e2904801739cd883e338481728aeda2a9e05f Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 2 Apr 2019 10:54:54 +0200 Subject: [PATCH 076/132] update the url of the main image --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 9dc8724..3b6045e 100644 --- a/README.rst +++ b/README.rst @@ -31,7 +31,7 @@ PaCER |br| Precise and Convenient Electrode Reconstruction for DBS .. raw:: html

- Image of a PaCER electrode reconstruction at two different time points of resolving brain shift. + Image of a PaCER electrode reconstruction at two different time points of resolving brain shift.

From 13fe51114cf5e8eb2e30be8c3bf21108c72601ba Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 2 Apr 2019 15:49:33 +0200 Subject: [PATCH 077/132] add code grade computation --- test/testAll.m | 94 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/test/testAll.m b/test/testAll.m index 913826b..94dc3aa 100644 --- a/test/testAll.m +++ b/test/testAll.m @@ -42,12 +42,100 @@ % include the root folder and all subfolders. addpath(genpath([pwd filesep 'test'])); +if launchTestSuite + if ~isempty(getenv('MOCOV_PATH')) && ~isempty(getenv('JSONLAB_PATH')) + addpath(genpath(getenv('MOCOV_PATH'))) + addpath(genpath(getenv('JSONLAB_PATH'))) + COVERAGE = true; + fprintf('MoCov and JsonLab are on path, coverage will be computed.\n') + else + COVERAGE = false; + end + + % change to the test folder + currentDir = cd('test'); + testDirContent = getFilesInDir('type', 'all'); % Get all currently present files in the folder. + testDirPath = pwd; + cd(currentDir); + + % define a success exit code + exit_code = 0; + + % enable profiler + profile on; + + if COVERAGE + % Get the ignored Files from gitIgnore + % only retain the lines that end with .txt and .m and + % are not comments and point to files in the /src folder + ignoredPatterns = {'^.{0,3}$', ... % Is smaller than four. + ['^[^s][^r][^c][^' regexptranslate('escape', filesep) ']']}; % does not start with src/ + filterPatterns = {'\.txt$', '\.m$'}; % Is either a .m file or a .txt file. + ignoreFiles = getIgnoredFiles(ignoredPatterns, filterPatterns); + + % check the code quality + listFiles = getFilesInDir('type', 'tracked', 'restrictToPattern', '^.*\.m$', 'checkSubFolders', true); + + % count the number of failed code quality checks per file + nMsgs = 0; + nCodeLines = 0; + nEmptyLines = 0; + nCommentLines = 0; + + for i = 1:length(listFiles) + nMsgs = nMsgs + length(checkcode(listFiles{i})); + fid = fopen(listFiles{i}); + + while ~feof(fid) + lineOfFile = strtrim(char(fgetl(fid))); + if length(lineOfFile) > 0 && length(strfind(lineOfFile(1), '%')) ~= 1 ... + && length(strfind(lineOfFile, 'end')) ~= 1 && length(strfind(lineOfFile, 'otherwise')) ~= 1 ... + && length(strfind(lineOfFile, 'switch')) ~= 1 && length(strfind(lineOfFile, 'else')) ~= 1 ... + && length(strfind(lineOfFile, 'case')) ~= 1 && length(strfind(lineOfFile, 'function')) ~= 1 + nCodeLines = nCodeLines + 1; + + elseif length(lineOfFile) == 0 + nEmptyLines = nEmptyLines + 1; + + elseif length(strfind(lineOfFile(1), '%')) == 1 + nCommentLines = nCommentLines + 1; + end + end + fclose(fid); + end + + % average number of messages per codeLines + avMsgsPerc = floor(nMsgs / nCodeLines * 100); + + grades = {'A', 'B', 'C', 'D', 'E', 'F'}; + intervals = [0, 3; + 3, 6; + 6, 9; + 9, 12; + 12, 15; + 15, 100]; + + grade = 'F'; + for i = 1:length(intervals) + if avMsgsPerc >= intervals(i, 1) && avMsgsPerc < intervals(i, 2) + grade = grades{i}; + end + end + + fprintf('\n\n -> The code grade is %s (%1.2f%%).\n\n', grade, avMsgsPerc); + + % set the new badge + if ~isempty(strfind(getenv('HOME'), 'jenkins')) + coverageBadgePath = [getenv('ARTENOLIS_DATA_PATH') filesep 'PaCER' filesep 'codegrade' filesep]; + system(['cp ' coverageBadgePath 'codegrade-', grade, '.svg ' coverageBadgePath 'codegrade.svg']); + end + end + +end + try if launchTestSuite - % define a success exit code - exit_code = 0; - % ensure that we ALWAYS call exit if ~isempty(strfind(getenv('HOME'), 'jenkins')) || ~isempty(strfind(getenv('USERPROFILE'), 'jenkins')) exit(exit_code); From 7fe1f8b46a753223b12ea198ef3e17a4b0962ab6 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 2 Apr 2019 16:41:32 +0200 Subject: [PATCH 078/132] move test file to suite dir --- test/{ => suite}/testextractElectrodePointclouds.m | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{ => suite}/testextractElectrodePointclouds.m (100%) diff --git a/test/testextractElectrodePointclouds.m b/test/suite/testextractElectrodePointclouds.m similarity index 100% rename from test/testextractElectrodePointclouds.m rename to test/suite/testextractElectrodePointclouds.m From f519c9be9db078c1ee9d5b8b347cae9496ba380e Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 2 Apr 2019 16:45:17 +0200 Subject: [PATCH 079/132] adding rdir from https://github.com/LCSB-BioCore/rdir.git --- external/rdir/LICENSE.md | 25 ++ external/rdir/README.md | 8 + external/rdir/enhanced_rdir.m | 65 +++++ external/rdir/rdir.m | 438 ++++++++++++++++++++++++++++++++++ 4 files changed, 536 insertions(+) create mode 100644 external/rdir/LICENSE.md create mode 100644 external/rdir/README.md create mode 100755 external/rdir/enhanced_rdir.m create mode 100755 external/rdir/rdir.m diff --git a/external/rdir/LICENSE.md b/external/rdir/LICENSE.md new file mode 100644 index 0000000..1753a7d --- /dev/null +++ b/external/rdir/LICENSE.md @@ -0,0 +1,25 @@ +Copyright (c) 2014, Thomas Vanaret +Copyright (c) 2009, Gus Brown +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/external/rdir/README.md b/external/rdir/README.md new file mode 100644 index 0000000..8a85840 --- /dev/null +++ b/external/rdir/README.md @@ -0,0 +1,8 @@ +# Recursive directory listing + +Original version is +[here](https://nl.mathworks.com/matlabcentral/fileexchange/19550-recursive-directory-listing?requestedDomain=true). + +The script has been adapted for `opencobra` repositories, such as [the COBRA +Toolbox](https://github.com/opencobra/cobratoolbox) and [the +MATLAB.devTools](https://github.com/opencobra/MATLAB.devTools). diff --git a/external/rdir/enhanced_rdir.m b/external/rdir/enhanced_rdir.m new file mode 100755 index 0000000..9ee8257 --- /dev/null +++ b/external/rdir/enhanced_rdir.m @@ -0,0 +1,65 @@ +%% RDIR Enhanced - Examples of use +% +% This script demonstrates how to use the different abilities of the +% enhanced |rdir| function. +% +% Examples are based on |matlabroot| directory content. Results may vary +% depending on your version of Matlab. +% + +%% Standard use +rdir([matlabroot, '\*.txt']) + +%% Using double wildcard ** +% List |".m"| files whose name contains |"tmpl"| in all subdirectories of +% |matlabroot| +rdir([matlabroot, '\**\*tmpl*.m']) + +%% RDIR output +d = rdir([matlabroot, '\**\*tmpl*.m']) + +%% +disp(d(1)) + + +%% Using 3rd argument to shorten output names +% Remove |"C:\Program Files\"| in returned names +rdir([matlabroot, '\*.txt'], '', 'C:\Program Files\') + +%% +% Remove |matlabroot| in returned names +rdir([matlabroot, '\*.txt'], '', true) + +%% +% Optional 2nd |rdir| output indicates common path removed from each output +% name +[d, p] = rdir([matlabroot, '\*.txt'], '', true); + +fprintf('Common path : \n%s\n\n', p) + +disp( d(1) ) + +%% Using a filter with "regexp" +% List |".mat"| files, then select those whose name match regular expression +% |'data\d'| (ie |"data"| followed by a numeric digit) +rdir([matlabroot '\toolbox\**\*.mat'], 'regexp(name, ''data\d'')', true) + +%% Using a function handle as filter + +fun = @(d) ~isempty(regexp(d.name, 'data\d')) && (d.bytes < 10*1024) + +rdir([matlabroot '\toolbox\**\*.mat'], fun, true) + +%% Specific display - No item matching filter +% When some items match input path, but none match filter, a specific +% message is displayed. +rdir(matlabroot, 'strcmp(name, ''unknowtoolbox'')', 1) + + +%% Specific display - Wrong filter +% A warning is displayed after the non-filtered result list if entered +% filter is wrong. +rdir(matlabroot, 'wrong filter', 1) + + +% EOF diff --git a/external/rdir/rdir.m b/external/rdir/rdir.m new file mode 100755 index 0000000..44058c9 --- /dev/null +++ b/external/rdir/rdir.m @@ -0,0 +1,438 @@ +function [varargout] = rdir(rootdir,varargin) +% RDIR - Recursive directory listing +% +% D = rdir(ROOT) +% D = rdir(ROOT, TEST) +% D = rdir(ROOT, TEST, RMPATH) +% D = rdir(ROOT, TEST, 1) +% D = rdir(ROOT, '', ...) +% [D, P] = rdir(...) +% rdir(...) +% +% +% *Inputs* +% +% * ROOT +% +% rdir(ROOT) lists the specified files. +% ROOT can be a pathname, filename, or can include both. One can use +% absolute and relative pathnames and wildcards (*). Wildcard can be placed +% anywhere and used many times like 'path*\*.m' +% +% One can also use a double wildcard (**) to match multiple directory +% levels. For example ROOT = 'path\**\*.m' will match all ".m" files in +% "path" and all subdirectories of "path". +% +% NOTE : ".svn" directories created by SubVersion (SVN) or ".git" +% repositories created by git are excluded from the recursive listing. +% +% * TEST +% +% Optional test that can be performed on the returned files. +% +% TEST is a string indicating expression to be evaluated on selected field +% of rdir output. +% All fields (ie name, date, bytes, isdir and datenum) can be used. +% +% Tests are strings similar to what one would use in a "if" statement e.g. +% 'bytes>1024 & datenum>now-7' +% +% One can also use function like "regexp" or "strfind" with string fields +% like "name" and "date" e.g 'regexp(name, 'expr')'. In that case, tests +% that return a non empty value are considered as true. +% +% regexp(name, '(\.m$)|(\.mdl$)') +% +% Test can also be a function handle as used in arrayfun/cellfun, e.g. +% @(f)f.bytes>1024 +% +% * RMPATH +% +% Optional path to remove from beginning of "name" field in returned +% output. Specified path must be common to all items found. +% +% If RMPATH = 1 or true, path to remove is part of ROOT before the first +% wildcard. +% +% +% *Outputs* +% +% * D +% +% D is a structure with the same fields as Matlab DIR output. +% +% The "name" field includes the relative path as well as the name to the +% file that was found. Path can be shorten or ommited when using 3rd +% argument RMPATH. +% +% * P +% +% Common path or RMPATH (if specified) for the file list returned in D. +% +% * Screen output +% +% If not output variable is specified then the output is sent to the +% screen. +% +% +% *Versions* +% +% * 1.0 - 2009, Gus Brown +% * 2.0 - 26/05/2011 Thomas Vanaret +% No longer exclude all directories from a simple search (no *); +% Fixing bug on returned path; +% Exclude ".svn" directories; +% Extended test possibilies; +% Subfunctions created; +% * 2.1 - 14/07/2011 Thomas Vanaret +% New argument allowing to remove common path from name; +% Comments review; +% * 2.2 - 20/12/2011 Thomas Vanaret +% Fixing bug on display with 0b files; +% Specific display when no file match filter; +% * 2.3 - 19/01/2014 Thomas Vanaret +% Adding improvements suggested by X. Mo : +% - function handle as TEST input +% - code optimisation (avoiding loop) +% Fixing possible bug when using a wildcard at the beginning; +% Common path as 2nd optionnal output; +% +% +% *Examples* +% +% D = rdir('*.m'); +% for ii=1:length(D), disp(D(ii).name); end; +% +% % to find all files in the current directory and sub directories +% D = rdir('**\*') +% +% % If no output is specified then the files are sent to +% % the screen. +% rdir('c:\program files\windows *\*.exe'); +% rdir('c:\program files\windows *\**\*.dll'); +% +% % Using the test function to find files modified today +% rdir('c:\win*\*','datenum>floor(now)'); +% % Using the test function to find files of a certain size +% rdir('c:\program files\win*\*.exe','bytes>1024 & bytes<1048576'); +% % Using the test function to find files modified in 2011 +% rdir('c:\win*\*','strfind(date, ''2011'')'); +% +% % Using the 3rd input to shorten output name +% rdir([matlabroot, '\*.txt'], '', 'C:\Program Files\') +% % Using the 3rd input to shorten output name +% rdir([matlabroot, '\*.txt'], '', 1) +% +% +% See also DIR +% + + +%-------------------------------------------------------------------------- +%% Input validation + +% use the current directory if nothing is specified +if ~exist('rootdir','var'), + rootdir = '*'; +end + +prepath = ''; % the path before the wild card +wildpath = ''; % the path wild card +postpath = rootdir; % the path after the wild card +I = find(rootdir==filesep,1,'last'); + +% Directory separator for current platform +if filesep == '\' + % On PC, filesep is '\' + anti_filesep = '/'; +else + % On UNIX system, filesep is '/' + anti_filesep = '\'; +end + +if isempty(I) && ~isempty(strfind(rootdir, anti_filesep)) + error([mfilename, ':FileSep'],... + 'Use correct directory separator "%s".', filesep) +end + + +%-------------------------------------------------------------------------- +%% Split rootdir +% split the file path around the wild card specifiers + +if ~isempty(I), + prepath = rootdir(1:I); + postpath = rootdir(I+1:end); + I = find(prepath=='*',1,'first'); + if ~isempty(I), + postpath = [prepath(I:end) postpath]; + prepath = prepath(1:I-1); + I = find(prepath==filesep,1,'last'); + if ~isempty(I), + wildpath = prepath(I+1:end); + prepath = prepath(1:I); + end; + I = find(postpath==filesep,1,'first'); + if ~isempty(I), + wildpath = [wildpath postpath(1:I-1)]; + postpath = postpath(I:end); + end; + end; +end; + +% disp([' "' prepath '" ~ "' wildpath '" ~ "' postpath '" ']); + +%-------------------------------------------------------------------------- +%% Recursive listing +% Search for matching files until all wildcards have been considered. + +if isempty(wildpath) + % If no directory wildcards then just get files and directories list + + D = dir([prepath postpath]); + + % Exclude ".", ".." and ".svn" directories from the list + excl = isdotdir(D) | isRepoDir(D); + D(excl) = []; + + if isdir([prepath postpath]); + fullpath = [prepath postpath]; + else + fullpath = prepath; + end + + % Place directories on the top of the list + is_dir = [D.isdir]'; + D = [D(is_dir); D(~is_dir)]; + + % Add path before name + for ii = 1:length(D) + D(ii).name = fullfile(fullpath, D(ii).name); + end + + % disp(sprintf('Scanning "%s" %g files found',[prepath postpath],length(D))); + +elseif strcmp(wildpath,'**') + % A double wildcards directory means recurs down into sub directories + + % first look for files in the current directory (remove extra filesep) + D = rdir([prepath postpath(2:end)]); + + % then look for sub directories + D_sd = dir([prepath '*']); + + % Exclude ".", "..", ".svn" directories and files from the list + excl = isdotdir(D_sd) | isRepoDir(D_sd) | ~([D_sd.isdir]'); + D_sd(excl) = []; + + % Process each sub directory found + % Performance tweak: avoid growing array within loop (X. Mo) + c_D = arrayfun(@(x) rdir([prepath x.name filesep wildpath postpath]),... + D_sd, 'UniformOutput', false); + + D = [D; cell2mat( c_D ) ]; + +else + % Process directory wild card looking for sub directories that match + + D_sd = dir([prepath wildpath]); + + % Exclude ".", "..", ".svn" directories and files from the list + excl = isdotdir(D_sd) | isRepoDir(D_sd) | ~([D_sd.isdir]'); + D_sd(excl) = []; + + if ~isdir(prepath) || ( numel(D_sd)==1 && strcmp(D_sd.name, prepath)) + % Fix case like rdir('path*\...') where prepath is not a full directoty + % name OR case were prepath match a unique directory. + % Previous "dir" return then the matching directory name(s). + % prepath is cleaned to use them. + % + % In else case, prepath is a valid path which must be kept. + prepath = ''; + end + + % Process each directory found + Dt = dir(''); + + c_D = arrayfun(@(x) rdir([prepath x.name postpath]),... + D_sd, 'UniformOutput', false); + + D = [Dt; cell2mat( c_D ) ]; + +end + + +%-------------------------------------------------------------------------- +%% Apply filter +% If specified, apply the filter to refine the search. + +nb_before_filt = length(D); +warning_msg = ''; + +if (nargin>=2 && ~isempty(varargin{1})), + try + if isa(varargin{1}, 'function_handle') + test_tf = arrayfun(varargin{1}, D); + else + test_tf = evaluate(D, varargin{1}); + end + + D = D(test_tf); + + catch + if isa(varargin{1}, 'function_handle') + test_expr = func2str(varargin{1}); + else + test_expr = varargin{1}; + end + + warning_msg = sprintf('Invalid TEST "%s" : %s', test_expr, lasterr); + end +end + + +%-------------------------------------------------------------------------- +%% Remove path +% If specified, remove given or common path from each returned path. + +common_path = ''; +if (nargin>=3 && ~isempty(varargin{2})), + + arg2 = varargin{2}; + if ischar(arg2) + common_path = arg2; + elseif (isnumeric(arg2) || islogical(arg2)) && arg2 + common_path = prepath; + end + + rm_path = regexptranslate('escape', common_path); + + % Check that path is common to all + start = regexp({D.name}', ['^', rm_path]); + + % Convert to a logical. + is_common = not( cellfun(@isempty, start) ); + + if all(is_common) + for k = 1:length(D) + D(k).name = regexprep(D(k).name, ['^', rm_path], ''); + end + + else + common_path = ''; + end + + % 19/07/2012 : ajouter common_path en sortie optionnelle + +end + + +%-------------------------------------------------------------------------- +%% Display listing if no output variables are specified +% Screen display. + +nout = nargout; + +if nout == 0 + if isempty(D) + if nb_before_filt == 0 + fprintf('%s not found.\n', rootdir) + else + fprintf('No item matching filter.\n') + end + else + + if ~isempty(common_path) + fprintf('All in : %s\n', common_path) + end + + pp = {'' 'k' 'M' 'G' 'T'}; + for ii = 1:length(D) + if D(ii).isdir + % Directory item : display name + disp(sprintf(' %29s %-64s','',D(ii).name)); + else + % File item : display size, modification date and name + sz = D(ii).bytes; + if sz > 0 + ss = min(4,floor(log2(sz)/10)); + else + ss = 0; + end + disp(sprintf('%4.0f %1sb %20s %-64s ',... + sz/1024^ss, pp{ss+1}, datestr(D(ii).datenum, 0), D(ii).name)); + end + end + end +elseif nout == 1 + % send list out + varargout{1} = D; +else + % send list and common path out + varargout{1} = D; + varargout{2} = common_path; +end; + +if ~isempty(warning_msg) + warning([mfilename, ':InvalidTest'],... + warning_msg); % ap aff +end + +%---------------------------- end of main function ------------------------ + + +%% ------------------------------------------------------------------------ +function tf = isRepoDir(d) +% True for ".svn" or ".git" directories. +% d is a structure returned by "dir" +% + +is_dir = [d.isdir]'; + +is_svn = strcmp({d.name}, '.svn')' | strcmp({d.name}, '.git')'; +%is_svn = false; % uncomment to disable ".svn" filtering + +tf = (is_dir & is_svn); + +%---------------------------- end of subfunction -------------------------- + +%% ------------------------------------------------------------------------ +function tf = isdotdir(d) +% True for "." and ".." directories. +% d is a structure returned by "dir" +% + +is_dir = [d.isdir]'; + +is_dot = strcmp({d.name}, '.')'; +is_dotdot = strcmp({d.name}, '..')'; + +tf = (is_dir & (is_dot | is_dotdot) ); + +%---------------------------- end of subfunction -------------------------- + +%% ------------------------------------------------------------------------ +function tf = evaluate(d, expr) +% True for item where evaluated expression is correct or return a non empty +% cell. +% d is a structure returned by "dir" +% + +% Get fields that can be used +name = {d.name}'; %#ok +date = {d.date}'; %#ok +datenum = [d.datenum]'; %#ok +bytes = [d.bytes]'; %#ok +isdir = [d.isdir]'; %#ok + +tf = eval(expr); % low risk since done in a dedicated subfunction. + +% Convert cell outputs returned by "strfind" or "regexp" filters to a +% logical. +if iscell(tf) + tf = not( cellfun(@isempty, tf) ); +end + +%---------------------------- end of subfunction -------------------------- + +%---------------------------- END OF FUNCTION ----------------------------- From 1bf58f580fad2215c7cc2a7cb3b0c2730eddc4e0 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 2 Apr 2019 16:46:46 +0200 Subject: [PATCH 080/132] change of mode in rdir --- external/rdir/enhanced_rdir.m | 0 external/rdir/rdir.m | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 external/rdir/enhanced_rdir.m mode change 100755 => 100644 external/rdir/rdir.m diff --git a/external/rdir/enhanced_rdir.m b/external/rdir/enhanced_rdir.m old mode 100755 new mode 100644 diff --git a/external/rdir/rdir.m b/external/rdir/rdir.m old mode 100755 new mode 100644 From 743c84e6246d714d37470a219bf1f39e0d2d1b0f Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 2 Apr 2019 17:12:09 +0200 Subject: [PATCH 081/132] adding the coverage generation code --- test/testAll.m | 95 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 3 deletions(-) diff --git a/test/testAll.m b/test/testAll.m index 94dc3aa..b049a7d 100644 --- a/test/testAll.m +++ b/test/testAll.m @@ -1,9 +1,10 @@ % load the different environment variables global refDataPath global inputDataPath +global PACERDIR -refDataPath = [getenv('PACER_DATA_PATH') filesep 'ref'] -inputDataPath = [getenv('PACER_DATA_PATH') filesep 'input'] +refDataPath = [getenv('PACER_DATA_PATH') filesep 'ref']; +inputDataPath = [getenv('PACER_DATA_PATH') filesep 'input']; % request explicitly from the user to launch test suite locally if isempty(strfind(getenv('HOME'), 'jenkins')) @@ -52,8 +53,10 @@ COVERAGE = false; end + SETUP_PACER + % change to the test folder - currentDir = cd('test'); + currentDir = cd([PACERDIR filesep 'test']); testDirContent = getFilesInDir('type', 'all'); % Get all currently present files in the folder. testDirPath = pwd; cd(currentDir); @@ -136,6 +139,92 @@ try if launchTestSuite + % save the userpath + originalUserPath = path; + + % run the tests in the subfolder verifiedTests/ recursively + [result, resultTable] = runTestSuite(); + + sumSkipped = sum(resultTable.Skipped); + sumFailed = sum(resultTable.Failed); + + fprintf(['\n > ', num2str(sumFailed), ' tests failed. ', num2str(sumSkipped), ' tests were skipped due to missing requirements.\n\n']); + + % count the number of covered lines of code + if COVERAGE + % write coverage based on profile('info') + fprintf('Running MoCov ... \n') + mocov('-cover', 'src', ... + '-profile_info', ... + '-cover_json_file', 'coverage.json', ... + '-cover_html_dir', 'coverage_html', ... + '-cover_method', 'profile', ... + '-verbose'); + + % load the coverage file + data = loadjson('coverage.json', 'SimplifyCell', 1); + + sf = data.source_files; + clFiles = zeros(length(sf), 1); + tlFiles = zeros(length(sf), 1); + + for i = 1:length(sf) + clFiles(i) = nnz(sf(i).coverage); + tlFiles(i) = length(sf(i).coverage); + end + + % average the values for each file + cl = sum(clFiles); + tl = sum(tlFiles); + + % print out the coverage + fprintf('Covered Lines: %i, Total Lines: %i, Coverage: %f%%.\n', cl, tl, cl / tl * 100); + end + + % print out a summary table + resultTable + + % Print some information on failed and skipped tests. + skippedTests = find(resultTable.Skipped); + if sum(skippedTests > 0) + fprintf('The following tests were skipped:\n%s\n\n', strjoin(resultTable.TestName(skippedTests), '\n')); + fprintf('The reasons were as follows:\n') + for i = 1:numel(skippedTests) + fprintf('------------------------------------------------\n') + fprintf('%s:\n', resultTable.TestName{skippedTests(i)}); + fprintf('%s\n', resultTable.Details{skippedTests(i)}); + fprintf('------------------------------------------------\n') + end + fprintf('\n\n') + end + + failedTests = find(resultTable.Failed & ~resultTable.Skipped); + if sum(failedTests > 0) + fprintf('The following tests failed:\n%s\n\n', strjoin(resultTable.TestName(failedTests), '\n')); + fprintf('The reasons were as follows:\n') + for i = 1:numel(failedTests) + fprintf('------------------------------------------------\n') + fprintf('%s:\n', resultTable.TestName{failedTests(i)}); + trace = result(failedTests(i)).Error.getReport(); + tracePerLine = strsplit(trace, '\n'); + testSuitePosition = find(cellfun(@(x) ~isempty(strfind(x, 'runTestSuite')), tracePerLine)); + trace = sprintf(strjoin(tracePerLine(1:(testSuitePosition - 7)), '\n')); % Remove the testSuiteTrace. + fprintf('%s\n', trace); + fprintf('------------------------------------------------\n') + end + fprintf('\n\n') + end + + % restore the original path + restoredefaultpath; + addpath(originalUserPath); + + if sumFailed > 0 + exit_code = 1; + end + + fprintf(['\n > The exit code is ', num2str(exit_code), '.\n\n']); + % ensure that we ALWAYS call exit if ~isempty(strfind(getenv('HOME'), 'jenkins')) || ~isempty(strfind(getenv('USERPROFILE'), 'jenkins')) exit(exit_code); From b28da28346dac0b1c04c6ffdc4c6aea3031da932 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 2 Apr 2019 17:12:40 +0200 Subject: [PATCH 082/132] adding filesep to load paths --- test/suite/testextractElectrodePointclouds.m | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/suite/testextractElectrodePointclouds.m b/test/suite/testextractElectrodePointclouds.m index 3faf29f..e64d788 100644 --- a/test/suite/testextractElectrodePointclouds.m +++ b/test/suite/testextractElectrodePointclouds.m @@ -17,24 +17,24 @@ cd(fileDir); %% load reference data (function implemented only with niiCT model) -refData = load([refDataPath 'refData_extractElectrodePC.mat']); +refData = load([refDataPath filesep 'refData_extractElectrodePC.mat']); % define input argument (testing only niiCT input argument) -niiCT_new = NiftiMod([inputDataPath 'ct_post.nii.gz']); +niiCT_new = NiftiMod([inputDataPath filesep 'ct_post.nii.gz']); % generate the new output (testing only niiCT input argument) [elecsPointcloudStruct_new, brainMask_new] = extractElectrodePointclouds(niiCT_new); -% compare the new data against the reference data +% compare the new data against the reference data assert(isequal(elecsPointcloudStruct_new, refData.elecsPointcloudStruct_ref)) assert(isequal(brainMask_new, refData.brainMask_ref)) %% load reference data (provide brain mask to the CT post OP) -refData_brainMask = load([refDataPath 'refData_extractElectrodePC_withBrainMask.mat']); +refData_brainMask = load([refDataPath filesep 'refData_extractElectrodePC_withBrainMask.mat']); % define input arguments (testing niiCT and brainMask) -niiCT_brainMask_new = NiftiMod([inputDataPath 'ct_post.nii.gz']); -brainMaskPath = [inputDataPath 'ct_post_mask.nii']; +niiCT_brainMask_new = niiCT_new; +brainMaskPath = [inputDataPath filesep 'ct_post_mask.nii']; % generate the new output (testing niiCT and brainMask) [elecsPointcloudStruct_brainMask_new, brainMask_brainMask_new] = extractElectrodePointclouds(niiCT_brainMask_new, 'brainMask', brainMaskPath); @@ -44,11 +44,11 @@ assert(isequal(brainMask_brainMask_new, refData_brainMask.brainMask_brainMask_ref)) %% load reference data for CT post OP with the corresponding XML file -refData_Xml = load([refDataPath 'refData_extractElectrodePC_xmlPlan.mat']); +refData_Xml = load([refDataPath filesep 'refData_extractElectrodePC_xmlPlan.mat']); % define input arguments (testing niiCT and Xml Plan) -niiCT_Xml_new = NiftiMod([inputDataPath 'CT_POSTOP_with_XML.nii.gz']); -xml_Plan_new = [inputDataPath 'CT_POSTOP_with_XML.xml']; +niiCT_Xml_new = NiftiMod([inputDataPath filesep 'CT_POSTOP_with_XML.nii.gz']); +xml_Plan_new = [inputDataPath filesep 'CT_POSTOP_with_XML.xml']; % generate the new output (function implemented with XML plan) [elecsPointcloudStruct_Xml_new, brainMask_Xml_new] = extractElectrodePointclouds(niiCT_Xml_new, 'medtronicXMLPlan', xml_Plan_new); @@ -65,4 +65,4 @@ assert(verifyFunctionError('extractElectrodePointclouds', 'inputs', {niiCT_brainMask_new, 'brainMask', brainMaskPath, 'metalThreshold', METAL_THRESHOLD}, 'testMessage','NO electrode artifact found within brain mask. Did you supply a post-op brain CT image? \n Try the ''no mask'' parameter in case of phantom scans without brain. \n Try providing an externally created brain mask using the "brainMask" parameter in other cases.')); %% change back to the current directory -cd(currentDir); \ No newline at end of file +cd(currentDir); From f502d544f70d4e197b4aa4a64fe2fff742c1573c Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 2 Apr 2019 17:14:41 +0200 Subject: [PATCH 083/132] add json and cov folder to gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 5c5a6eb..07f71e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +coverage.json +coverage_html/ *.asv *.m~ *.mex* From 3b4983a2c186326357a823574b05df4de14a7774 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 2 Apr 2019 17:19:25 +0200 Subject: [PATCH 084/132] move verifyFunctionError to base --- test/{ => base}/verifyFunctionError.m | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{ => base}/verifyFunctionError.m (100%) diff --git a/test/verifyFunctionError.m b/test/base/verifyFunctionError.m similarity index 100% rename from test/verifyFunctionError.m rename to test/base/verifyFunctionError.m From 1f1162a99f6405741267b2bcd03a908470bc4210 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 2 Apr 2019 17:19:36 +0200 Subject: [PATCH 085/132] adding base test functions --- test/base/clearGlobal.m | 11 ++ test/base/getEnvironment.m | 19 ++++ test/base/getFilesInDir.m | 154 ++++++++++++++++++++++++++++ test/base/getGlobalValue.m | 15 +++ test/base/getIgnoredFiles.m | 54 ++++++++++ test/base/restoreEnvironment.m | 48 +++++++++ test/base/runScriptFile.m | 63 ++++++++++++ test/base/runTestSuite.m | 178 +++++++++++++++++++++++++++++++++ test/base/setGlobal.m | 14 +++ 9 files changed, 556 insertions(+) create mode 100644 test/base/clearGlobal.m create mode 100644 test/base/getEnvironment.m create mode 100644 test/base/getFilesInDir.m create mode 100644 test/base/getGlobalValue.m create mode 100644 test/base/getIgnoredFiles.m create mode 100644 test/base/restoreEnvironment.m create mode 100644 test/base/runScriptFile.m create mode 100644 test/base/runTestSuite.m create mode 100644 test/base/setGlobal.m diff --git a/test/base/clearGlobal.m b/test/base/clearGlobal.m new file mode 100644 index 0000000..5240fce --- /dev/null +++ b/test/base/clearGlobal.m @@ -0,0 +1,11 @@ +function clearGlobal(globalName) +% Safely clear a global variable. +% +% USAGE: +% clearGlobal(globalName) +% +% INPUTS: +% globalName: The name of the global variable to clear. + + clearvars('-global',globalName); +end \ No newline at end of file diff --git a/test/base/getEnvironment.m b/test/base/getEnvironment.m new file mode 100644 index 0000000..1ee5fe0 --- /dev/null +++ b/test/base/getEnvironment.m @@ -0,0 +1,19 @@ +function environment = getEnvironment() +% Get all values of current globals in a struct. +% USAGE: +% environment = getEnvironment() +% +% OUTPUT: +% environment: a struct with two fields +% * .globals - contains all global values +% * .path - contains the current path +environment = struct(); +globals = struct(); +globalvars = who('global'); +for i = 1:numel(globalvars) + globals.(globalvars{i}) = getGlobalValue(globalvars{i}); +end +environment.globals = globals; +environment.path = path; +end + diff --git a/test/base/getFilesInDir.m b/test/base/getFilesInDir.m new file mode 100644 index 0000000..220940e --- /dev/null +++ b/test/base/getFilesInDir.m @@ -0,0 +1,154 @@ +function files = getFilesInDir(varargin) +% List all files in the supplied (git tracked) Directory with their absolute path name +% based on the git ls-file command. If the directory is not git controlled, the +% type is assumed to be 'all' and all files (except for .git files +% will be returned). +% +% USAGE: +% files = getFilesInDir(varargin) +% +% OPTIONAL INPUTS: +% varargin: Options as 'ParameterName' value pairs with the following options: +% +% - `dirToList`: the directory to list the files for (default: the current working directory) +% - `type`: Git type of files to return +% +% - `tracked`: Only tracked files +% - `ignored`: Only `git` ignored files excluding files that are tracked but ignored (specified in .gitignore). If the folder is not controlled by git, `all` will be used. +% - `untracked`: anything that is not ignored and not tracked (new files) +% - `all`: all files except for the git specific files (e.g. .git, .gitignore etc). +% - `ignoredByCOBRA`: use the COBRA Toolbox .gitignore file. Only return those files that match patterns specified there. Slower than `ignored` since all files have to be manually checked against the expressions specified in the .gitignore file, but available on all folders (default: `all`) +% - `restrictToPattern` - give a regexp pattern to filter the files, this option is ignored if empty (default: '', i.e. ignored) +% - `checkSubFolders - check the subfolders of the current directory (default: `true`) +% - `printLevel` +% +% - `0`: No print out (default) +% - `1`: print Information +% +% +% OUTPUTS: +% files: A Cell Array of files with absolute file pathes. +% present in this folder matching the options choosen. +% +% EXAMPLES: +% +% % get all m files in the source folder: +% files = getFilesInDir('dirToList', [CBTDIR filesep 'src'], 'restrictToPattern', '\.m$'); +% +% % Get the git tracked files in the test Directory. +% files = getFilesInDir('dirToList', [CBTDIR filesep 'test'], 'type', 'tracked'); +% +% % get all git tracked files which start with "MyFile" in the current directory +% files = getFilesInDir('type', 'tracked', 'restrictToPattern', '^MyFile'); +% +% % get only the gitIgnored files in the current folder +% files = getFilesInDir('type', 'ignored'); + +persistent COBRAIgnored + +if isempty(COBRAIgnored) + COBRAIgnored = regexptranslate('wildcard',getIgnoredFiles()); +end + +gitFileTypes = {'tracked','all','untracked','ignored','ignoredByCOBRA'}; +parser = inputParser(); +parser.addParamValue('dirToList',pwd,@(x) exist(x,'file') == 7); +parser.addParamValue('type','all',@(x) ischar(x) && any(strcmpi(x,gitFileTypes))); +parser.addParamValue('restrictToPattern','',@(x) ischar(x)); +parser.addParamValue('checkSubFolders','',@(x) islogical(x) || (isnumeric(x) && x == 0 || x == 1)); +parser.addParamValue('printLevel',0,@(x) isnumeric(x)); + +parser.parse(varargin{:}); + +printLevel = parser.Results.printLevel; + +%get the absolute path of the files that are listed +currentDir = cd(parser.Results.dirToList); + +%get the absolute path to the folder to be listed. +absPath = pwd; + +%get the type of files to obtain. +selectedType = lower(parser.Results.type); + +%test, whether the folder is git controlled +[gitStatus,~] = system('git status'); +if gitStatus ~= 0 && ~strcmpi(selectedType,'ignoredbycobra') + selectedType = 'all'; +end +if gitStatus == 0 && strcmpi(selectedType,'ignoredbycobra') + [~,repos] = system('git remote -v'); + if any(cellfun(@(x) ~isempty(strfind(x,'cobratoolbox.git')),strsplit(repos,'\n'))) + %So, we are on a COBRA repo. lets just use the ignored option + selectedType = 'ignored'; + end +end + +if gitStatus == 0 && printLevel > 0 && strcmp(selectedType,'ignored') + [~,folder] = system('git rev-parse --show-toplevel'); + fprintf('Using the .gitignore files as specified in the repository under:\n%s\n',folder); +end + + +switch selectedType + case 'all' + if gitStatus == 0 + [status, trackedfiles] = system('git ls-files'); + [status, untrackedfiles] = system('git ls-files -o'); + trackedfiles = strsplit(strtrim(trackedfiles), '\n'); + untrackedfiles = strsplit(strtrim(untrackedfiles), '\n'); + files = [trackedfiles,untrackedfiles]; + else + if parser.Results.checkSubFolders + rdircall = ['**' filesep '*']; + else + rdircall = ['*']; + end + files = rdir(rdircall); + files = {files.name}'; %Need to transpose to give consistent results. + end + + case 'tracked' + [status, files] = system('git ls-files'); + files = strsplit(strtrim(files), '\n'); + case 'untracked' + %Files, which are not tracked but are not ignored. + [status, files] = system('git ls-files -o --exclude-standard'); + files = strsplit(strtrim(files), '\n'); + case 'ignored' + [~, files] = system('git ls-files -o -i --exclude-standard'); + files = strsplit(strtrim(files), '\n'); + case 'ignoredbycobra' + if gitStatus == 0 + [status, trackedfiles] = system('git ls-files'); + [status, untrackedfiles] = system('git ls-files -o'); + trackedfiles = strsplit(strtrim(trackedfiles), '\n'); + untrackedfiles = strsplit(strtrim(untrackedfiles), '\n'); + files = [trackedfiles,untrackedfiles]; + else + files = rdir(['**' filesep '*']); + files = {files.name}'; %Need to transpose to give consistent results. + end + matching = false(size(files)); + for i = 1:numel(COBRAIgnored) + matching = matching | ~cellfun(@(x) isempty(regexp(x,COBRAIgnored{i},'ONCE')),files); + end + files = files(matching); + +end +if ~parser.Results.checkSubFolders + files = files(cellfun(@(x) isempty(regexp(x,regexptranslate('escape',filesep))),files)); +end + +files = strcat(absPath, filesep, files); + +%Filter according to the restriction pattern. +if ~isempty(parser.Results.restrictToPattern) + files = files(cellfun(@(x) ~isempty(regexp(x,parser.Results.restrictToPattern)), files)); +end + +cd(currentDir); +end + + + diff --git a/test/base/getGlobalValue.m b/test/base/getGlobalValue.m new file mode 100644 index 0000000..9c8c879 --- /dev/null +++ b/test/base/getGlobalValue.m @@ -0,0 +1,15 @@ +function value = getGlobalValue(globalName) +% Safely get the Value of a global variable. +% +% USAGE: +% value = getGlobalValue(globalName) +% +% INPUTS: +% globalName: The name of the global variable to get the value for +% +% OUTPUT: +% value: The value of the requested global variable + + eval(['global ' globalName]); + eval(['value = ' globalName ';']); +end \ No newline at end of file diff --git a/test/base/getIgnoredFiles.m b/test/base/getIgnoredFiles.m new file mode 100644 index 0000000..2130e2e --- /dev/null +++ b/test/base/getIgnoredFiles.m @@ -0,0 +1,54 @@ +function ignoredFiles = getIgnoredFiles(ignorepatterns, filterpatterns) +% Get all files/patterns which are ignored by git in the COBRA Toolbox directory.. +% USAGE: +% +% ignoreFiles = getIgnoredFiles() +% +% OPTIONAL INPUTS: +% ignorePatterns: A cell array of regexp patterns indicating files +% which are not to be listed +% filterpatterns: A cell array of regexp patterns identifying those +% files which should be returned after ignoring. +% +% OUTPUTS: +% ignoredFiles: All files (and patterns) indicated as ignored in +% the gitignore file. +% +% .. Authors: - Original Code: Laurent Heirandt +% - Move to function: Thomas Pfau, Jan 2018 + + +global PACERDIR + +fid = fopen([PACERDIR filesep '.gitignore']); +emptyAndCommentLines = {'^#','^$'}; +if ~exist('ignorepatterns','var') + ignorepatterns = emptyAndCommentLines; +else + ignorepatterns = union(ignorepatterns,emptyAndCommentLines); +end + +if ~exist('filterpatterns','var') + filterpatterns = {'.*'}; +end + +% initialise +counter = 1; +ignoredFiles = {}; + + +% loop through the file names of the .gitignore file +while ~feof(fid) + lineOfFile = strtrim(char(fgetl(fid))); + %remove lines that match any ignore pattern and do not match any + %filterpattern + if ~any(~cellfun(@(x) isempty(regexp(lineOfFile,x,'ONCE')),ignorepatterns)) + if any(~cellfun(@(x) isempty(regexp(lineOfFile,x,'ONCE')),filterpatterns)) + ignoredFiles{counter} = lineOfFile; + counter = counter + 1; + end + end +end + +% close the .gitignore file +fclose(fid); diff --git a/test/base/restoreEnvironment.m b/test/base/restoreEnvironment.m new file mode 100644 index 0000000..95db5e4 --- /dev/null +++ b/test/base/restoreEnvironment.m @@ -0,0 +1,48 @@ +function restoreEnvironment(environment, restorePath, printLevel) +% Reset all global variables to a value stored in the input struct (all +% variables not present will be deleted. +% USAGE: +% restoreEnvironment(globals) +% +% INPUTS: +% environment: A struct with the following fields: +% * .globals: a struct with the fields being global variables and the value the respective values. +% * .path: the path to restore (it will override the current path) +% restorePath: Also restore the path (default: true) +% printLevel: Set the verbosity of this method: +% * 0: No outputs (Default) +% * 1: Info what each value is set to +% + if ~exist('restorePath','var') + restorePath = true; + end + if ~exist('printLevel','var') + printLevel = 0; + end + + globalvars = who('global'); + globalsToDelete = setdiff(globalvars,fieldnames(environment.globals)); + + for i = 1:numel(globalsToDelete) + clearGlobal(globalsToDelete{i}); + end + + % for everything else, check, if it changed + globalNames = fieldnames(environment.globals); + for i = 1:numel(globalNames) + % set the global to the old value. + setGlobal(globalNames{i},environment.globals.(globalNames{i})); + if printLevel >= 1 + fprintf('%s set to:\n', globalNames{i}); + disp(environment.globals.(globalNames{i})); + end + end + %Restore the path + if restorePath + path(environment.path); + if printLevel >= 1 + fprintf('Path set to:\n%s\n', sprintf(strrep(environment.path,':','\n'))); + end + end +end + diff --git a/test/base/runScriptFile.m b/test/base/runScriptFile.m new file mode 100644 index 0000000..31201f2 --- /dev/null +++ b/test/base/runScriptFile.m @@ -0,0 +1,63 @@ +function result = runScriptFile(fileName) +% This function runs the test in fileName +% It can distinguish between skipped and Failed tests. A test is considered +% to be skipped if it throws a COBRA:RequirementsNotMet error. +% +% OUTPUTS: +% +% result: A structure array with the following fields: +% +% - `.passed`: true if the test passed otherwise false +% - `.skipped`: true if the test was skipped otherwise false +% - `.failed`: true if the test failed, or was skipped, otherwise false +% - `.status`: a string representing the status of the test ('failed','skipped' or'passed') +% - `.fileName`: the fileName of the test +% - `.time`: the duration of the test (if passed otherwise NaN) +% - `.statusMessage`: Informative string about potential problems. +% - `.Error`: Error message received from a failed or skipped test +% +% .. Author: - Thomas Pfau Jan 2018. + +global CBT_MISSING_REQUIREMENTS_ERROR_ID + +COBRA_TESTSUITE_TESTFILE = fileName; + +% get the timinig (and hope these values are not overwritten. +COBRA_TESTSUITE_STARTTIME = clock(); + +try + % run the file + executefile(fileName); +catch ME + % vatch errors and interpret them + clearvars -except ME COBRA_TESTSUITE_STARTTIME COBRA_TESTSUITE_TESTFILE CBT_MISSING_REQUIREMENTS_ERROR_ID + scriptTime = etime(clock(), COBRA_TESTSUITE_STARTTIME); + result = struct('status', 'failed', 'failed', true, 'passed', false, 'skipped', false, 'fileName', ... + COBRA_TESTSUITE_TESTFILE, 'time', scriptTime, 'statusMessage', 'fail', 'Error', ME); + if strcmp(ME.identifier, CBT_MISSING_REQUIREMENTS_ERROR_ID) + % requirement missing, so the test was skipped. + result.status = 'skipped'; + result.skipped = true; + result.failed = false; + result.statusMessage = ME.message; + else + % actual error in the test. + result.skipped = false; + result.status = 'failed'; + result.statusMessage = ME.message; + end + return +end + +% get the timinig. +scriptTime = etime(clock(), COBRA_TESTSUITE_STARTTIME); + +result = struct('status', 'passed', 'failed', false, 'passed', true, 'skipped', false, 'fileName', ... + COBRA_TESTSUITE_TESTFILE, 'time', scriptTime, 'statusMessage', 'success', 'Error', MException('', '')); + +end + +function executefile(fileName) +% runs a script file (used to separate workspaces) + run(fileName) +end diff --git a/test/base/runTestSuite.m b/test/base/runTestSuite.m new file mode 100644 index 0000000..c7fff7f --- /dev/null +++ b/test/base/runTestSuite.m @@ -0,0 +1,178 @@ +function [results, resultTable] = runTestSuite(testNames) +% This function runs all tests (i.e. files starting with 'test' in the +% CBTDIR/test/ folder and returns the status. +% It can distinguish between skipped and Failed tests. A test is considered +% to be skipped if it throws a COBRA:RequirementsNotMet error. +% +% INPUTS: +% +% testNames: only run tests matching the regexp given in testNames. +% +% OUTPUTS: +% +% results: A structure array with one entry per test and the following fields: +% +% - `.passed`: true if the test passed otherwise false +% - `.skipped`: true if the test was skipped otherwise false +% - `.failed`: true if the test failed, or was skipped, otherwise false +% - `.status`: a string representing the status of the test ('failed','skipped' or'passed') +% - `.fileName`: the fileName of the test +% - `.time`: the duration of the test (if passed otherwise NaN) +% - `.statusMessage`: Informative string about potential problems +% - `.Error`: Error message received from a failed or skipped test +% resultTable: A Table with details of the results. +% +% Author: +% - Thomas Pfau Jan 2018. + +global PACERDIR + +if ~exist('testNames','var') + testNames = '.*'; +end + +% go to the test directory. +testDir = [PACERDIR filesep 'test']; +currentDir = cd(testDir); + +% get all names of test files +testFiles = rdir(['suite' filesep '**' filesep 'test*.m']); +testFileNames = {testFiles.name}; +testFileNames = testFileNames(~cellfun(@(x) isempty(regexp(x,testNames,'ONCE')),testFileNames)); + +% save the current globals (all tests should have the same environment when +% starting) and path +environment = getEnvironment(); + +% save the current warning state +warnstate = warning(); + +% run the tests and show outputs. +for i = 1:numel(testFileNames) + % shut down any existing parpool. + try + % test if there is a parpool that we should shut down before the next test. + p = gcp('nocreate'); + delete(p); + catch + % do nothing + end + + % reset the globals + restoreEnvironment(environment) + + % reset the warning state + warning(warnstate); + + [~,file,ext] = fileparts(testFileNames{i}); + testName = file; + fprintf('****************************************************\n\n'); + fprintf('Running %s\n\n',testName); + results(i) = runScriptFile([file ext]); + fprintf('\n\n%s %s!\n',testName,results(i).status); + if ~results(i).passed + if results(i).skipped + fprintf('Reason:\n%s\n',results(i).statusMessage); + else + trace = results(i).Error.getReport(); + tracePerLine = strsplit(trace,'\n'); + testSuitePosition = find(cellfun(@(x) ~isempty(strfind(x, 'runTestSuite')),tracePerLine)); + trace = sprintf(strjoin(tracePerLine(1:(testSuitePosition-7)),'\n')); % Remove the testSuiteTrace. + fprintf('Reason:\n%s\n',trace); + end + end + fprintf('\n\n****************************************************\n'); +end + +% create a table from the fields +resultTable= table({results.fileName}',{results.status}',[results.passed]',[results.skipped]',... + [results.failed]',[results.time]',{results.statusMessage}',... + 'VariableNames',{'TestName','Status','Passed','Skipped','Failed','Time','Details'}); + +% change back to the original directory. +cd(currentDir) +end + + +function globals = getGlobals() +% Get all values of current globals in a struct. +% USAGE: +% globals = getGlobals() +% +% OUTPUT: +% +% globals: a struct of all global variables + + globals = struct(); + globalvars = who('global'); + for i = 1:numel(globalvars) + globals.(globalvars{i}) = getGlobalValue(globalvars{i}); + end +end + +function resetGlobals(globals) +% Reset all global variables to a value stored in the input struct (all +% variables not present will be deleted. +% USAGE: +% resetGlobals(globals) +% +% INPUT: +% globals: A struct with 1 field per global variable. + + globalvars = who('global'); + globalsToDelete = setdiff(globalvars,fieldnames(globals)); + + for i = 1:numel(globalsToDelete) + clearGlobal(globalsToDelete{i}); + end + + % Note: we cannot clean functions as this would remove profiling information + + % for everything else, check, if it changed + globalNames = fieldnames(globals); + for i = 1:numel(globalNames) + % set the global to the old value. + setGlobal(globalNames{i},globals.(globalNames{i})); + end +end + + +function setGlobal(globalName,globalValue) +% Safely set a global Variable to a specific value. +% +% USAGE: +% setGlobal(globalName,globalValue) +% +% INPUTS: +% globalName: A string representing the name of the global variable +% globalValue: The value to set the global variable to + + eval([ globalName '_val = globalValue;']); + eval(['global ' globalName]); + eval([globalName ' = ' globalName '_val;']); +end + +function clearGlobal(globalName) +% Safely clear a global variable. +% +% USAGE: +% clearGlobal(globalName) +% +% INPUTS: +% globalName: The name of the global variable to clear. + + clearvars('-global',globalName); +end + +function value = getGlobalValue(globalName) +% Safely get the Value of a global variable. +% +% USAGE: +% getGlobalValue(globalName) +% +% INPUTS: +% globalName: The name of the global variable to get the value for + + eval(['global ' globalName]); + eval(['value = ' globalName ';']); +end diff --git a/test/base/setGlobal.m b/test/base/setGlobal.m new file mode 100644 index 0000000..d2d1493 --- /dev/null +++ b/test/base/setGlobal.m @@ -0,0 +1,14 @@ +function setGlobal(globalName,globalValue) +% Safely set a global Variable to a specific value. +% +% USAGE: +% setGlobal(globalName,globalValue) +% +% INPUTS: +% globalName: A string representing the name of the global variable +% globalValue: The value to set the global variable to + + eval([ globalName '_val = globalValue;']); + eval(['global ' globalName]); + eval([globalName ' = ' globalName '_val;']); +end \ No newline at end of file From 21757fcdc78ab62250cf5f85058f4cd66c54c8ee Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 2 Apr 2019 17:23:15 +0200 Subject: [PATCH 086/132] change of note --- test/base/verifyFunctionError.m | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/test/base/verifyFunctionError.m b/test/base/verifyFunctionError.m index ffc64b1..364517b 100644 --- a/test/base/verifyFunctionError.m +++ b/test/base/verifyFunctionError.m @@ -10,7 +10,7 @@ % functionCall: The name of a function. % % OPTIONAL INPUTS: -% +% % varargin: Parameter Value pairs for specific options. % * outputArgCount - The number of output arguments requested, as this can influence the functionality (Default: 0). % * testMessage - The message that should be thrown in this error. If no message is supplied, any thrown error will be accepted @@ -19,10 +19,13 @@ % OUTPUTS: % success: Whether an error was thrown, and the type and % message match (if provided) -% AUTHOR: -% - Loic Marx, March 2019 (adapted from -% https://github.com/opencobra/cobratoolbox/blob/master/test/verifyCobraFunctionError.m) -% 5aa9ccd +% +% .. AUTHOR: +% - Thomas Pfau, 2018 +% - Loic Marx, March 2019 +% +% .. NOTE: +% This function has been adapted from https://github.com/opencobra/cobratoolbox/blob/master/test/verifyCobraFunctionError.m [5aa9ccd] testMessage = false; parser = inputParser(); @@ -40,7 +43,7 @@ functionCall = str2func(functionCall); success = true; -try +try if outputArgcount > 0 outArgs = cell(outputArgcount,1); [outArgs{:}] = functionCall(inputs{:}); @@ -57,4 +60,4 @@ end %If we reach this point, the function did not throw an error. i.e. the %verification is unsuccessful. -success = false; \ No newline at end of file +success = false; From ba602a373448d9291ba2f6406fb996241a879afd Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 2 Apr 2019 17:48:17 +0200 Subject: [PATCH 087/132] change of branch --- .artenolis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.artenolis.yml b/.artenolis.yml index f51d011..31c5672 100644 --- a/.artenolis.yml +++ b/.artenolis.yml @@ -9,7 +9,8 @@ script: # update the data repository - cd $PACER_DATA_PATH - - git pull origin master + - git checkout develop + - git pull origin develop # change to the current directory - cd $CURRENT_DIR From 484cf1836c16baf985eb932785ba629a599abb74 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 2 Apr 2019 20:30:57 +0200 Subject: [PATCH 088/132] uncomment coverage submission commands --- .artenolis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.artenolis.yml b/.artenolis.yml index 31c5672..5df5fc7 100644 --- a/.artenolis.yml +++ b/.artenolis.yml @@ -21,6 +21,6 @@ script: after_success: # submit coverage report - #- if [[ "$MATLAB_VER" == "R2018b" && "$ARCH" == "Linux" ]]; then - # bash <(curl -s https://codecov.io/bash) -f "!*.lst"; - # fi + - if [[ "$MATLAB_VER" == "R2018b" && "$ARCH" == "Linux" ]]; then + bash <(curl -s https://codecov.io/bash) -f "!*.lst"; + fi From 11a47c0c1c4d226242519d2fcee1036a137d4c80 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Tue, 2 Apr 2019 20:34:03 +0200 Subject: [PATCH 089/132] adding codecov yml --- codecov.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..cbfea86 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,6 @@ +coverage: + status: + project: + default: + threshold: 15 + patch: off From 3efc03b5890c2568b2cc7cc629a1550a19f03c3e Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 26 Mar 2019 16:14:51 +0100 Subject: [PATCH 090/132] adding header to the function --- test/testDetermineElectrodeType.m | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 test/testDetermineElectrodeType.m diff --git a/test/testDetermineElectrodeType.m b/test/testDetermineElectrodeType.m new file mode 100644 index 0000000..f6fce94 --- /dev/null +++ b/test/testDetermineElectrodeType.m @@ -0,0 +1,9 @@ +% The PaCER Toolbox: testDetermineElectrodeType.m +% +% Purpose: +% - test the determineElectrodeType function +% +% Author: +% - Loic Marx, March 2019 + + From b494da7ee2a04bedb329fbd5729051f23efffa46 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Mon, 1 Apr 2019 09:32:40 +0200 Subject: [PATCH 091/132] test for determineElectrodeType function --- test/testDetermineElectrodeType.m | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/testDetermineElectrodeType.m b/test/testDetermineElectrodeType.m index f6fce94..19ee329 100644 --- a/test/testDetermineElectrodeType.m +++ b/test/testDetermineElectrodeType.m @@ -6,4 +6,28 @@ % Author: % - Loic Marx, March 2019 +% save the current path +currentDir = pwd; + +% initialize the test +fileDir = fileparts(which(mfilename)); +cd(fileDir); + +% load reference data +load('RefData_determineElectrodeType.mat'); + +% define input argument +peakDistances_new = [0.7500 1.75]; + +% generate new output +[elecStruct_new, rms_new, d_new] = determineElectrodeType(peakDistances_new); + +% comparison between refData and new generated output +assert(isequal(elecStruct_ref, elecStruct_new)) +assert(isequal(rms_ref, rms_new)) +assert(isequal(d_ref, d_new)) + +% change back to the current directory +cd(currentDir); + From 66f3803d94fb49ad5c1f5730c8a29cb97578eaa9 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Mon, 1 Apr 2019 09:33:26 +0200 Subject: [PATCH 092/132] reference data for determine electrode type --- test/RefData_determineElectrodeType.mat | Bin 0 -> 568 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/RefData_determineElectrodeType.mat diff --git a/test/RefData_determineElectrodeType.mat b/test/RefData_determineElectrodeType.mat new file mode 100644 index 0000000000000000000000000000000000000000..ffb231710b22af36e9dbe0017ce232787eb639c7 GIT binary patch literal 568 zcmeZu4DoSvQZUssQ1EpO(M`+DN!3vZ$Vn_o%P-2c0*X0%nwjV*I2WZRmZYXA6G4t&9wCttduw*!mB1QOKQTimQ(9Lbyfs!eY@S3Auf?4s#~WoEG+G_UQ(uF7Ga*&zAy^ zN__gn93;HC`y%Vy&!4@7CVO`UvNSi`x~LLlBwQTq9n>B0W|f!jDgKk?r**XS7$x~8 zYM<0OAdsx#G~>nOS<~YtF$%d0mH3@ymg@V!dEz}APe(zLGq-x$l7b|Lc4cE`VPWBj z`OK5-#B?5>ZeQZhaO%6Sucqdy^QV2n49vD|P|2|`vT=Nq&T`vS;Fpfah2xx}{I?XZ z|FZhfZM*ZA;se&!Uo&MiF8^oFsb^sPtCR6dbiy6}g*RmswiryAR>r`PcF1QkC^)R( zfyjXzh)jmUQ=YLtYPxbHXZo2(laB0pawSP&zHkStM8bns+m?UH{0wgeIJ`k7Xu?g{ dfNX+NVwr;8DcwGOFW=+@rmlt~40f{2DFFCy%kcmJ literal 0 HcmV?d00001 From 0762acacf159f7a49f19c9577e550bcc74660949 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Mon, 1 Apr 2019 10:04:26 +0200 Subject: [PATCH 093/132] test if the function throws a warning --- test/testDetermineElectrodeType.m | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/test/testDetermineElectrodeType.m b/test/testDetermineElectrodeType.m index 19ee329..112d106 100644 --- a/test/testDetermineElectrodeType.m +++ b/test/testDetermineElectrodeType.m @@ -17,7 +17,7 @@ load('RefData_determineElectrodeType.mat'); % define input argument -peakDistances_new = [0.7500 1.75]; +peakDistances_new = [0.7500 1.75]; % electrod contact is normally 1.5mm long % generate new output [elecStruct_new, rms_new, d_new] = determineElectrodeType(peakDistances_new); @@ -27,7 +27,15 @@ assert(isequal(rms_ref, rms_new)) assert(isequal(d_ref, d_new)) -% change back to the current directory -cd(currentDir); - +% test if there is no objective - will throw a warning message +w = warning ('off','all'); +peakDistances_warning = Inf; +try + [elecStruct_warning, rms_warning, d_warning] = determineElectrodeType(peakDistances_warning); +catch ME + assert(length(ME.message) > 0) +end +w = warning ('on','all'); +% change back to the current directory +cd(currentDir); \ No newline at end of file From 33beaa51fd72307d4aa15aedf2f50f3033700728 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Mon, 1 Apr 2019 10:14:15 +0200 Subject: [PATCH 094/132] fixing header --- test/testDetermineElectrodeType.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testDetermineElectrodeType.m b/test/testDetermineElectrodeType.m index 112d106..da137ed 100644 --- a/test/testDetermineElectrodeType.m +++ b/test/testDetermineElectrodeType.m @@ -27,7 +27,7 @@ assert(isequal(rms_ref, rms_new)) assert(isequal(d_ref, d_new)) -% test if there is no objective - will throw a warning message +% test if there is infinite value assigned to PeakDistances - will throw a warning message w = warning ('off','all'); peakDistances_warning = Inf; try From 2cd97cf26f11e2a85b27a0c1e6ac3a172a45dd33 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 3 Apr 2019 11:03:10 +0200 Subject: [PATCH 095/132] rename refdata --- ...eType.mat => refData_determineElectrodeType.mat} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{RefData_determineElectrodeType.mat => refData_determineElectrodeType.mat} (100%) diff --git a/test/RefData_determineElectrodeType.mat b/test/refData_determineElectrodeType.mat similarity index 100% rename from test/RefData_determineElectrodeType.mat rename to test/refData_determineElectrodeType.mat From 440821eef44f1fbb2886afb35a02b37c0bdc0d6f Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 3 Apr 2019 11:11:14 +0200 Subject: [PATCH 096/132] move refdata into suite --- test/suite/refData_determineElectrodeType.mat | Bin 0 -> 568 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/suite/refData_determineElectrodeType.mat diff --git a/test/suite/refData_determineElectrodeType.mat b/test/suite/refData_determineElectrodeType.mat new file mode 100644 index 0000000000000000000000000000000000000000..ffb231710b22af36e9dbe0017ce232787eb639c7 GIT binary patch literal 568 zcmeZu4DoSvQZUssQ1EpO(M`+DN!3vZ$Vn_o%P-2c0*X0%nwjV*I2WZRmZYXA6G4t&9wCttduw*!mB1QOKQTimQ(9Lbyfs!eY@S3Auf?4s#~WoEG+G_UQ(uF7Ga*&zAy^ zN__gn93;HC`y%Vy&!4@7CVO`UvNSi`x~LLlBwQTq9n>B0W|f!jDgKk?r**XS7$x~8 zYM<0OAdsx#G~>nOS<~YtF$%d0mH3@ymg@V!dEz}APe(zLGq-x$l7b|Lc4cE`VPWBj z`OK5-#B?5>ZeQZhaO%6Sucqdy^QV2n49vD|P|2|`vT=Nq&T`vS;Fpfah2xx}{I?XZ z|FZhfZM*ZA;se&!Uo&MiF8^oFsb^sPtCR6dbiy6}g*RmswiryAR>r`PcF1QkC^)R( zfyjXzh)jmUQ=YLtYPxbHXZo2(laB0pawSP&zHkStM8bns+m?UH{0wgeIJ`k7Xu?g{ dfNX+NVwr;8DcwGOFW=+@rmlt~40f{2DFFCy%kcmJ literal 0 HcmV?d00001 From 32b74a4128674eda8f0fbfd184fd91551989a617 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 3 Apr 2019 11:11:57 +0200 Subject: [PATCH 097/132] move testDetermineElectrode into suite --- test/suite/testDetermineElectrodeType.m | 41 +++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/suite/testDetermineElectrodeType.m diff --git a/test/suite/testDetermineElectrodeType.m b/test/suite/testDetermineElectrodeType.m new file mode 100644 index 0000000..da137ed --- /dev/null +++ b/test/suite/testDetermineElectrodeType.m @@ -0,0 +1,41 @@ +% The PaCER Toolbox: testDetermineElectrodeType.m +% +% Purpose: +% - test the determineElectrodeType function +% +% Author: +% - Loic Marx, March 2019 + +% save the current path +currentDir = pwd; + +% initialize the test +fileDir = fileparts(which(mfilename)); +cd(fileDir); + +% load reference data +load('RefData_determineElectrodeType.mat'); + +% define input argument +peakDistances_new = [0.7500 1.75]; % electrod contact is normally 1.5mm long + +% generate new output +[elecStruct_new, rms_new, d_new] = determineElectrodeType(peakDistances_new); + +% comparison between refData and new generated output +assert(isequal(elecStruct_ref, elecStruct_new)) +assert(isequal(rms_ref, rms_new)) +assert(isequal(d_ref, d_new)) + +% test if there is infinite value assigned to PeakDistances - will throw a warning message +w = warning ('off','all'); +peakDistances_warning = Inf; +try + [elecStruct_warning, rms_warning, d_warning] = determineElectrodeType(peakDistances_warning); +catch ME + assert(length(ME.message) > 0) +end +w = warning ('on','all'); + +% change back to the current directory +cd(currentDir); \ No newline at end of file From 4e16ef192f3c8b46358ef401424978dc8f0b2efd Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 3 Apr 2019 11:53:19 +0200 Subject: [PATCH 098/132] change the name of refdata in the test file --- test/suite/testDetermineElectrodeType.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite/testDetermineElectrodeType.m b/test/suite/testDetermineElectrodeType.m index da137ed..4735bc1 100644 --- a/test/suite/testDetermineElectrodeType.m +++ b/test/suite/testDetermineElectrodeType.m @@ -14,7 +14,7 @@ cd(fileDir); % load reference data -load('RefData_determineElectrodeType.mat'); +load('refData_determineElectrodeType.mat'); % define input argument peakDistances_new = [0.7500 1.75]; % electrod contact is normally 1.5mm long From 2d814e1b8a872dc560efcfff7a6f0b4b33fd9f8b Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 3 Apr 2019 11:55:51 +0200 Subject: [PATCH 099/132] formating --- test/suite/testDetermineElectrodeType.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite/testDetermineElectrodeType.m b/test/suite/testDetermineElectrodeType.m index 4735bc1..9046680 100644 --- a/test/suite/testDetermineElectrodeType.m +++ b/test/suite/testDetermineElectrodeType.m @@ -17,7 +17,7 @@ load('refData_determineElectrodeType.mat'); % define input argument -peakDistances_new = [0.7500 1.75]; % electrod contact is normally 1.5mm long +peakDistances_new = [0.7500 1.75]; % electrode contact is normally 1.5mm long % generate new output [elecStruct_new, rms_new, d_new] = determineElectrodeType(peakDistances_new); From 3e41ab0401e0f2e2a413c1bf32ea442f42296fb1 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 3 Apr 2019 14:19:44 +0200 Subject: [PATCH 100/132] deleted refData in test --- test/refData_determineElectrodeType.mat | Bin 568 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 test/refData_determineElectrodeType.mat diff --git a/test/refData_determineElectrodeType.mat b/test/refData_determineElectrodeType.mat deleted file mode 100644 index ffb231710b22af36e9dbe0017ce232787eb639c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 568 zcmeZu4DoSvQZUssQ1EpO(M`+DN!3vZ$Vn_o%P-2c0*X0%nwjV*I2WZRmZYXA6G4t&9wCttduw*!mB1QOKQTimQ(9Lbyfs!eY@S3Auf?4s#~WoEG+G_UQ(uF7Ga*&zAy^ zN__gn93;HC`y%Vy&!4@7CVO`UvNSi`x~LLlBwQTq9n>B0W|f!jDgKk?r**XS7$x~8 zYM<0OAdsx#G~>nOS<~YtF$%d0mH3@ymg@V!dEz}APe(zLGq-x$l7b|Lc4cE`VPWBj z`OK5-#B?5>ZeQZhaO%6Sucqdy^QV2n49vD|P|2|`vT=Nq&T`vS;Fpfah2xx}{I?XZ z|FZhfZM*ZA;se&!Uo&MiF8^oFsb^sPtCR6dbiy6}g*RmswiryAR>r`PcF1QkC^)R( zfyjXzh)jmUQ=YLtYPxbHXZo2(laB0pawSP&zHkStM8bns+m?UH{0wgeIJ`k7Xu?g{ dfNX+NVwr;8DcwGOFW=+@rmlt~40f{2DFFCy%kcmJ From e8815aaebf1c0fa512b0a43e9046d9fb475ae983 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 3 Apr 2019 14:20:25 +0200 Subject: [PATCH 101/132] delete test file in test folder --- test/testDetermineElectrodeType.m | 41 ------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 test/testDetermineElectrodeType.m diff --git a/test/testDetermineElectrodeType.m b/test/testDetermineElectrodeType.m deleted file mode 100644 index da137ed..0000000 --- a/test/testDetermineElectrodeType.m +++ /dev/null @@ -1,41 +0,0 @@ -% The PaCER Toolbox: testDetermineElectrodeType.m -% -% Purpose: -% - test the determineElectrodeType function -% -% Author: -% - Loic Marx, March 2019 - -% save the current path -currentDir = pwd; - -% initialize the test -fileDir = fileparts(which(mfilename)); -cd(fileDir); - -% load reference data -load('RefData_determineElectrodeType.mat'); - -% define input argument -peakDistances_new = [0.7500 1.75]; % electrod contact is normally 1.5mm long - -% generate new output -[elecStruct_new, rms_new, d_new] = determineElectrodeType(peakDistances_new); - -% comparison between refData and new generated output -assert(isequal(elecStruct_ref, elecStruct_new)) -assert(isequal(rms_ref, rms_new)) -assert(isequal(d_ref, d_new)) - -% test if there is infinite value assigned to PeakDistances - will throw a warning message -w = warning ('off','all'); -peakDistances_warning = Inf; -try - [elecStruct_warning, rms_warning, d_warning] = determineElectrodeType(peakDistances_warning); -catch ME - assert(length(ME.message) > 0) -end -w = warning ('on','all'); - -% change back to the current directory -cd(currentDir); \ No newline at end of file From 320f00d488626a1118ec0a2792d653591878d639 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Wed, 3 Apr 2019 14:57:03 +0200 Subject: [PATCH 102/132] add documenter enc --- docs/.documenter.enc | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/.documenter.enc diff --git a/docs/.documenter.enc b/docs/.documenter.enc new file mode 100644 index 0000000..750b26a --- /dev/null +++ b/docs/.documenter.enc @@ -0,0 +1 @@ +LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKS0FJQkFBS0NBZ0VBbHNzWkQ4NFNXVUJKd09SS0xjN1Z6R0NWTThBSk1XcFk3N055MzR1QVJTTStTMi9PCldVbm0xNjY3dldnSndmMkdPblBqdGFnTVJBZUxwdk8zcklZQ2J5YUNPQ1dmUzNzNmtXeEg3U2U1UW0vSVp2NzQKakpXNDFyazdhcnUwUzFVUHNLclNUUXpOM252N0FvUjlDbXdndmM0cGVEZTJSSDdKRVljb2JrbDJvRGltYzNObApLUmtHaHN1VG1yTTlyM2oxVXMwbFRkK2E0VEVDdTR4NzVvdzhmZ1U2NHN3YWk2WnZESHhJRXgrQ3QxVjhYV2ZnCk1ia0NaS29PWmU1MjlZVzB3S2hXTVFWcDhPSkkxWXZRcHcxd0cwcmtvZXdHbXd1eVFjamZ3NWVKcHFTeXBRMEoKeG1Zbk1KZnFnZEVaaDUzaWVGNndZcWJrUjNDUXNyVEw5K3lscW90dXdPQjFuYTB1WkRkbjVnWEZ3VHBSd09xMApBd1FnYWtndUFKeUlOR3EwUVpFU1FWL1MvN3h3WDJaL3BmMTJvbjBRbmkrVjdnSEgrUXE4dzY3TnRjY0d4dTl0CmtwbGhQRStIZHZmRTlycVdVSFFtSHgzY1dTdHFmK0pYZ1ozVExCbUdwYVRUVzF0UDlUS3cxOU9YTGU2aERlQzgKRGgybXJWc2lJcEFGVzZsQkJoVVoyVE1WdytpZ3RjMjZZNHFRcm54eFNPbTdHbWcwbFlVaW13cXZQOU5SZEFncQpBcmtxemtsbE5pWjFCcnpNVWY0dGMvUzNjSWtlQkhNeDI4T3NJWDh5YXhJTlBleksrU3NvS1VSVE5ucE81SVEvCkU2T1h4NlhwQWRQa25nYUhNTEsyTmNYZU5USFhWL216bFZNeWUzSkVEK25OSnlIOGJiaW5WZ013dzRVQ0F3RUEKQVFLQ0FnQngvR3loYWVDczNzL2hvNi8vR0k2OHczV0ZmUEIyRGpIVVlBM0J0YTNzbFV1TnNxS0ZGRHdQWmVJOAp0dHhKYTk5L2FBTUZXbGFMUmpqbXB1eDgyWUFWalVKNk50WkhOSXQ5U2lERXdIWm1KaUdTMmNJQVkxMHAwek42CjV4RE9zU24vSGVHQ3BOOHFBd1luVFFkSVRad2lYaWt5MnNwSTFKNGhSYzNtTUZvZm16TVhxbThadGZVZEI5NDMKM3E0T2Fwem5Ubk9ZZmlLUmYzN1ZUc2lKNmhBQUl1djBiTnpVRzZkdUJMUm00RGJyWnc5dmZBb1pEQVVuR3ZWdgpUK2RVaVJHdFlKSm0wL1RWUmZoUWxEUFJVM01lN21vTmpHRWg2cUdBNE50aytyUHU2Q2l5WXp5MFlKdlhPNzdsCkNxOEZ1TzlzbGdjM1MzamNGOWNKZjJsL3E3OCtGcVp0RHM4M29GR0ZDZmZOVURPTFhkczYwTWVvU2h2MU5Ud0YKenlOZXFoRUVGS0pGa2xQQ0pjS1ZIZnVEbnJ2WWRlV2FjMlRlSU44QnorUk5wNXlwRHgvREFpTXJMN3FhV3RFeQpHcE1QTEpnbitJMVZrcFo2a2ZZR2lsUC9IeEd1UXpBTmpldUNZVXVoRXJnQU1nMjFFR3hUZlpMc1R0WW5MZ0Z0Cjlwam5aVVFNQ0oydXliLys1dzduUkQrL21FWkJzZzRjckM2ejM4dS9FQzNpWCtwSUU3ZE9vb0R1N1dycysvSDkKa2t2M0dlYVRJVHNXbzVTQ1kyVVhjcTBMWS9zV3dVT3BocngzNjlPY0w2TnVuUmU4dlJvdEE4Nkg0QnNBZGlkcQpscURvcFZkdEJwY2dXamNjbnYyVlVOVkVzMUFOYVVLYXVXdkw4djJIUnRIU2g3bnZNUUtDQVFFQXZ1eUs4cDQ2ClFobW14TUNVTHVMMEI1R1VpMytoL05sVWQzM1lqcy9SeTlYdWd6cldsVjQ2MlhKVy9jMVBwVksrbGRVd01lczEKZ1JIOVU3QkdPbmNjbExJSnhFM0habWRqNTFHaHY0QVJGcnFNRDVEbnhxM25FSHJJdGxWK2t1QjZEWlFsb0VYNQpuRWhPSERyeDNZR00xNDdCV3dMUG1icFhDWnJOdmdHSHVoTWQxOHBzN1B6Wk5GdWtITTVNb3oxa0w5WE1vTE1pCnVMblY4MjNCY1dHUm9NMFNQbGJtWlVjT1F3MFJFMnJ1TnBCYmpwQU5aT01wZ3QyeW05cWZRT0dwT29mZytKUkkKa1dKYllYK0Q2b3Z6VWtWeWhuak9rWHdEekY0eEg2dEw0amV1ZnpHcjRlTXZLaEFCRlE1d1B3VXkxYkVxK0llWQpVejhnV1N4NHVjS0Rhd0tDQVFFQXlqRGdCSGxKQVJRWG5TQmVMZkc2Ung0NEY0SDRJNDJkaDRKbHpMb25UM25iCk9Iak1aR3ZibUdrY0wvbDBmWTVUT1VnenQyN2t0UkFDTmc1WHBpN0l3b0JNOWdMajEvb0ZSbEJENk9QQ1JuUVYKS3hKYzhLTHYwYU1NR3BIZVpqNTNKeU1pRlJVNWYwc2JuUzdobHRqaVd3SFRRdWU0ditVeUQrc2JPNi9MR00vWgo2V0ZvdUxMeWtGQ25McDlpSDBwa1VrV2cwWHBsc3lrbC9YOFlLSHQzQkxITmlGZ0RMajFkRDlaVURtRjJHL1hTCnpUZnp2dllxbFRBcFhzVG16cDN1bjY5aDdNdEExODNiMSt4VVBQNU1LZ3dwclVROFJiVDljNWo5dTlWSDhKZnMKdEVWNnUzMlB5VUs5SFlRYklpcXM2c29sVHluS2JUWEJtWG1JMTFtQXp3S0NBUUExZHFleUtQekhaY2Q5Y1RBTgpzU0FFdm8rS1FNTnJ1ckFjaGZFT2pNT0RBUFU1YWxDTW8wWjNmYjArZFMvSWE5TlN3ZEF0S21CaE5GaHNCd0NqCmZwZFNURWpQMzdmbXhTMEVxYWRScU5zZ01qem1YdjJJZFVvdkl6THhYQitGb2JhTDl1QlNjVVhrclpxeDdRK3QKcDRsNUUxQ3gyNmVtdExlS3lQNjBKbG1Ma2E3WnJxV3g5MXdiZlU0SGd2MlMrSzRGZHlsR0Z1T3lOdGZpd3VsWQpocW54RFh2K1dQZExoUXBKWEc5YnNLWGtRYWhoMDVUc20zQVVaV0NPcERuVVFWelNOeHFZZ1cyUXlLb3VNemNOCmh3TXNGcVpyWVlqMjFITjcxeVNLYWIxbUs1R0JyTGNsR2lrcTdqQmZaUnVwaWhzaUcrcWNqZHZwODlOckpUanAKUzc3aEFvSUJBUUNGcDQxT0o4YUVlZjJxRmsxclhaRmZsYkJLaWRXMzJ0TTVVbzlzcDlsNGhmck45N3hVM1orSgp2bUd0ck42K2FLakhBdDE4OGtjcEVXNEV3YkphM2k1RHRJQXJWM201dVVKbldvT3BuWFU5RVZzMDM2eWtQWEQrClNTT2xKS3U1TnEyWkozWk9MWHVXazlXckwrUmJ6UDdFWGc2QytaNTg2MHNPanNHdjBPTVdnYjl3c0wyQzZuZkIKd2k3aGVPWnAvTWtZUVlLdk5wT252Um1wMnF2amhzb0VSbXl4Smt6ajhoaGtjYSthMmY0ek9XcWgwY3pFZlFGbApJVE1YdkYwK1U5UDdwdm02aUJsVERuZTI0amhGSVd6RGxzcXVDSjgzRFE5RnJPcDlrZDArUTQ5ckUwcXdTYTRVCndwTTB3YkVXQXRQUFdOVVU0WEU0aEFKNEs0aXpvaXl0QW9JQkFFbGs4TjR3eStPMWNBalVmVzRYZnRHTUc5OE8KL3BLZS9JNFpEM2p1SmhxNXhLaWdkRmVDL0UzODhsbkhxVDJ4OFhBZndMZFBTUVllNFdzcndUM0IzeU1kbEpyWApHTFQ3RnNzd01CMGtwRWZmTFU5VWFCbmxnS3I0OXQwYWJIL1NXdksyVnhXVnVHZDlVSVpWaGR5QlE3aUpHMFBxCjdlYkJEVVJ4cEZjTHNpNi9yZDgrOUZWOHJDUmh4cVZhSlp4Umt6N0UyT3pnbk1FSUJTMEQrVEdtOWwxWkhPN00KWHp2WXVBRHppVmNTdmtSeTlvdzJSeUp5MHEzVUhKUkhlb2NNM3FBQi92T2VxelVxMzFOV0FwYUFEazVmbUs4cwpuUTJCNXVUS01laVVNVUFDNHVZOUg0eVA5NGE5dE53NmlOWWFEMlZHM3EvOHlwYU4wcE5Kd1gvK2p5dz0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0= \ No newline at end of file From 9d09634a3545c31e19aa2b26f7696094d2502c6f Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Wed, 3 Apr 2019 14:57:35 +0200 Subject: [PATCH 103/132] add commands to deploy doc --- .artenolis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.artenolis.yml b/.artenolis.yml index 5df5fc7..4d840ab 100644 --- a/.artenolis.yml +++ b/.artenolis.yml @@ -24,3 +24,12 @@ after_success: - if [[ "$MATLAB_VER" == "R2018b" && "$ARCH" == "Linux" ]]; then bash <(curl -s https://codecov.io/bash) -f "!*.lst"; fi + + # deploy documentation + - if [[ "$MATLAB_VER" == "R2018b" && "$ARCH" == "Linux" && "$JENKINS_PULL_REQUEST" != "True" ]]; then + export PATH="/home/jenkins/.local/bin":$PATH; + pip install --upgrade --user -r docs/requirements.txt; + export GIT_LOCAL_BRANCH=${GIT_BRANCH##origin/}; + echo $GIT_LOCAL_BRANCH; + python -c "from documenter.deploy import Documentation; doc = Documentation('github.com/adhusch/PaCER', local_upstream='$(pwd)', ci='jenkins'); doc.deploy()"; + fi From 3f5f170cdc6cb58956b4a5e409036f1db1c402b3 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Wed, 3 Apr 2019 15:44:32 +0200 Subject: [PATCH 104/132] add fulltoc to reqs --- docs/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/requirements.txt b/docs/requirements.txt index bfd97af..57c2bc4 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -4,3 +4,4 @@ git+https://github.com/LCSB-BioCore/sphinx_julia_theme.git@develop#egg=sphinx_ju git+https://github.com/syarra/Documenter.py@develop#egg=documenter git+https://github.com/LCSB-BioCore/sphinxcontrib-napoleon.git@develop#egg=sphinxcontrib_napoleon git+https://github.com/syarra/sphinxcontrib-matlabdomain#egg=sphinxcontrib-matlabdomain +sphinxcontrib-fulltoc From ee5b03247c7a1dc5e03257941c7f93ed4e71780e Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Wed, 3 Apr 2019 17:20:45 +0200 Subject: [PATCH 105/132] Adding function description --- src/Functions/getIntensityPeaks.m | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Functions/getIntensityPeaks.m b/src/Functions/getIntensityPeaks.m index 88ec104..135f08d 100644 --- a/src/Functions/getIntensityPeaks.m +++ b/src/Functions/getIntensityPeaks.m @@ -10,20 +10,20 @@ % = getIntensityPeaks(intensityProfile, skelScaleMm, filterIdxs) % % INPUTS: -% intensityProfile: -% skelScaleMm: -% filterIdxs: +% intensityProfile: Profile intensity +% skelScaleMm: Estimated millimetric scale +% filterIdxs: Finds the linear index of the millimetric scale % % OUTPUTS: -% peaklocs: -% peakWaveCenters: -% peakValues: -% threshIntensityProfile: -% threshold: -% contactAreaCenter: -% contactAreaWidth: -% xrayMarkerAreaCenter: -% xrayMarkerAreaWidth: +% peaklocs: 1D peak locations +% peakWaveCenters: 1D peak wave center locations +% peakValues: Peak values +% threshIntensityProfile: Thresholded intensity profile +% threshold: Threshold +% contactAreaCenter: Center of the assumed contact area +% contactAreaWidth: Width of the assumed contact area +% xrayMarkerAreaCenter: Center of the xray marker (if any) +% xrayMarkerAreaWidth: Width of the xray maker (if any) % % .. AUTHOR: % - Andreas Husch, Original File From 0cde7dddf2c75ddb4aa6a91cbe89d11d39d000c9 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Wed, 3 Apr 2019 17:24:13 +0200 Subject: [PATCH 106/132] Adding function description --- src/Functions/plotIntensityProfileAndPeaks.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Functions/plotIntensityProfileAndPeaks.m b/src/Functions/plotIntensityProfileAndPeaks.m index 9cf48e6..4649745 100644 --- a/src/Functions/plotIntensityProfileAndPeaks.m +++ b/src/Functions/plotIntensityProfileAndPeaks.m @@ -5,8 +5,8 @@ function plotIntensityProfileAndPeaks(intensityProfile, skelScaleMm) % plotIntensityProfileAndPeaks(intensityProfile, skelScaleMm) % % INPUTS: -% intensityProfile: -% skelScaleMm: +% intensityProfile: a 1D Intensity profile +% skelScaleMm: Estimated scale (mm per intensity sample) % % .. AUTHORS: % - Andreas Husch, Original File From afb401ace214558d61d68c1a89a2ac86c1d7ef25 Mon Sep 17 00:00:00 2001 From: Daniel Duarte Tojal Date: Wed, 3 Apr 2019 17:29:21 +0200 Subject: [PATCH 107/132] small change to intesity profile description --- src/Functions/getIntensityPeaks.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Functions/getIntensityPeaks.m b/src/Functions/getIntensityPeaks.m index 135f08d..007dda7 100644 --- a/src/Functions/getIntensityPeaks.m +++ b/src/Functions/getIntensityPeaks.m @@ -10,7 +10,7 @@ % = getIntensityPeaks(intensityProfile, skelScaleMm, filterIdxs) % % INPUTS: -% intensityProfile: Profile intensity +% intensityProfile: 1D Intensity Profile % skelScaleMm: Estimated millimetric scale % filterIdxs: Finds the linear index of the millimetric scale % From a91cc9bcd87328f3ded5f1e6b2b842f92d82dbed Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Wed, 17 Apr 2019 19:21:15 +0200 Subject: [PATCH 108/132] catchWarning function --- catchWarning.m | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 catchWarning.m diff --git a/catchWarning.m b/catchWarning.m new file mode 100644 index 0000000..cf400c0 --- /dev/null +++ b/catchWarning.m @@ -0,0 +1,25 @@ +function foundWarning = catchWarning(functionName, warningMsg) + foundWarning = false; + logFile = '.testCatch.log'; + + % run the function in diary mode + diary(logFile); + eval(functionName); + diary off + + % loop through the temporary diary file + fid = fopen(logFile); + tline = fgetl(fid); + while ischar(tline) + tline = fgetl(fid); + disp(tline); + if ~isempty(tline) && contains(tline, warningMsg) + foundWarning = true; + break; + end + end + fclose(fid); + + % remove the temporary diary file + delete(logFile); +end \ No newline at end of file From a638200a8e2f70185d97f4c6de4a664cbd1ee0f5 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Wed, 17 Apr 2019 19:21:30 +0200 Subject: [PATCH 109/132] WIP test A warning message --- .testCatch.log | 10 +++++ test/suite/.testCatch.log | 84 +++++++++++++++++++++++++++++++++++++++ testA.m | 4 ++ 3 files changed, 98 insertions(+) create mode 100644 .testCatch.log create mode 100644 test/suite/.testCatch.log create mode 100644 testA.m diff --git a/.testCatch.log b/.testCatch.log new file mode 100644 index 0000000..afb962c --- /dev/null +++ b/.testCatch.log @@ -0,0 +1,10 @@ +{Error: File: testA.m Line: 2 Column: 1 +Invalid use of operator. + +Error in catchWarning (line 7) + eval(functionName); +} +niiCT_brainMask_new = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']); +clear +niiCT_brainMask_new = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']); +foundWarning = catchWarning('PaCER', 'Slice thickness is greater than 0.7 mm! Independet contact detection might not work reliable in this case. However, for certain electrode types with large contacts spacings you might be lucky.'); diff --git a/test/suite/.testCatch.log b/test/suite/.testCatch.log new file mode 100644 index 0000000..5e5b434 --- /dev/null +++ b/test/suite/.testCatch.log @@ -0,0 +1,84 @@ +{Not enough input arguments. + +Error in PaCER (line 35) +if(~isa(niiCT, 'NiftiMod') && ~isa(niiCT, 'NiftiModSPM') ) + +Error in catchWarning (line 7) + eval(functionName); +} +[elecModels_warning, elecPointCloudsStruct_warning, intensityProfiles_warning, skelSkelmms_warning] = PaCER(niiCT_brainMask_new); +[Warning: Slice thickness is greater than 0.7 mm! Independet contact detection might not work reliable in this case. However, +for certain electrode types with large contacts spacings you might be lucky. +(Type "warning off " to suppress this warning.) +] +[> In PaCER (line 44)] +===================== Processing /Users/loicmarx/pacer.data/input/ct_post.nii.gz ===================== +Voxel size: 0.48828 0.48828 1 +Voxel size in elecsPointcloudStruct: 0.48828 0.48828 1 +Loading /Users/loicmarx/pacer.data/input/ct_post.nii.gz from disk... +Caching is enabeld. +Extracting convex hull brain mask... +MorphFraction:0.14229 +[Warning: Uncommon fraction of CT data in threshold range (15-60 HU). Trying to compensate. Make sure to use "soft tissue" +reconstruction filters for the CT (e.g. J30 kernel) if this fails. +(Type "warning off " to suppress this warning.) +] +[> In extractBrainConvHull (line 64) + In extractElectrodePointclouds (line 64) + In PaCER (line 51)] +Thresholding /Users/loicmarx/pacer.data/input/ct_post.nii.gz for metal with METAL_THRESHOLD = 800... +19 potential metal components detected within brain. +Guessing that 2 of them are Electrodes... +No xmlElectrodeDefition given. Guessing that there are 2 electrodes in the image +------------- Processing Electrode ------------- +Applied axial skeleton filter because of low intensity planes +Max off-model: 0.078328 Mean off-model: 0.034988 +Max off-model: 0.53878 Mean off-model: 0.021295 +Check for outliers / make sure that the polynomial degree choosen is appropriate. + In most cases this should be fine. +1st Pass Electrode Length within Brain Convex Hull: 73.9421mm +2nd Pass Electrode Length within Brain Convex Hull: 74.6762mm +refitElec: selected contactDetectionMethod is contactAreaCenter +determineElectrodeType: data to model peak/contact spacing RMS distance is 0.36034 [mm] +Trying to estimate electrode type by simple contactAreaCenter. +[Warning: No electrode specification given! Set electrodeType option! Trying to estimate type by contactAreaWidth only which +might be wrong! +(Type "warning off " to suppress this warning.) +] +[> In refitElec (line 125) + In PaCER (line 60)] +Assuming Medtronic 3389 or Boston Scientific Vercise Directional. Setting 3389. +Max off-model: 0.43564 Mean off-model: 0.10219 +Check for outliers / make sure that the polynomial degree choosen is appropriate. + In most cases this should be fine. +Electrode Length within Brain Convex Hull after contact detection and Zero-Point calibration: 73.8118mm +------------- Processing Electrode ------------- +Applied axial skeleton filter because of low intensity planes +Max off-model: 0.13706 Mean off-model: 0.039501 +Max off-model: 0.24463 Mean off-model: 0.021733 +1st Pass Electrode Length within Brain Convex Hull: 68.8864mm +2nd Pass Electrode Length within Brain Convex Hull: 69.7922mm +refitElec: selected contactDetectionMethod is contactAreaCenter +determineElectrodeType: data to model peak/contact spacing RMS distance is 0.11336 [mm] +Trying to estimate electrode type by simple contactAreaCenter. +[Warning: No electrode specification given! Set electrodeType option! Trying to estimate type by contactAreaWidth only which +might be wrong! +(Type "warning off " to suppress this warning.) +] +[> In refitElec (line 125) + In PaCER (line 60)] +Assuming Medtronic 3389 or Boston Scientific Vercise Directional. Setting 3389. +Max off-model: 0.32285 Mean off-model: 0.06274 +Check for outliers / make sure that the polynomial degree choosen is appropriate. + In most cases this should be fine. +Electrode Length within Brain Convex Hull after contact detection and Zero-Point calibration: 68.971mm +foundWarning = catchWarning('PaCER', 'Slice thickness is greater than 0.7 mm! Independet contact detection might not work reliable in this case. However, for certain electrode types with large contacts spacings you might be lucky.'); +{Not enough input arguments. + +Error in PaCER (line 35) +if(~isa(niiCT, 'NiftiMod') && ~isa(niiCT, 'NiftiModSPM') ) + +Error in catchWarning (line 7) + eval(functionName); +} +foundWarning = catchWarning('PaCER', 'Slice thickness is greater than 0.7 mm! Independet contact detection might not work reliable in this case. However, for certain electrode types with large contacts spacings you might be lucky.'); diff --git a/testA.m b/testA.m new file mode 100644 index 0000000..59334b2 --- /dev/null +++ b/testA.m @@ -0,0 +1,4 @@ +function testA() + warning('This is a warning in the testA function.'); + testB(); +end From d389d350d456a8843a6eeeaf27315da35791f6a4 Mon Sep 17 00:00:00 2001 From: laurentheirendt Date: Wed, 17 Apr 2019 19:21:37 +0200 Subject: [PATCH 110/132] deleted testB --- testB.m | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 testB.m diff --git a/testB.m b/testB.m new file mode 100644 index 0000000..5f94ccc --- /dev/null +++ b/testB.m @@ -0,0 +1,3 @@ +function testB() + warning('This is a warning in the testB function'); +end From 6fedbbaf58d61d4cc23edc1d5629d6e2b3493953 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Fri, 19 Apr 2019 14:12:58 +0200 Subject: [PATCH 111/132] ignore .log file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 07f71e7..d0f6f1a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ pacer_sample_dataset/ exampledata/ .DS_Store docs/build +*.log \ No newline at end of file From 608ae774d216b5df96a75b61561f553b47c8aa3e Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 10:08:20 +0200 Subject: [PATCH 112/132] note to clearGlobal function --- test/base/clearGlobal.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/base/clearGlobal.m b/test/base/clearGlobal.m index 5240fce..75a273d 100644 --- a/test/base/clearGlobal.m +++ b/test/base/clearGlobal.m @@ -6,6 +6,11 @@ function clearGlobal(globalName) % % INPUTS: % globalName: The name of the global variable to clear. +% +% NOTE: +% this function has been uploaded from +% https://github.com/opencobra/cobratoolbox/blob/master/src/base/utilities/clearGlobal.m +% [e6b4efd] clearvars('-global',globalName); end \ No newline at end of file From 441a28d2dc63a29b1ad31940c768fbea11aca182 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 10:10:13 +0200 Subject: [PATCH 113/132] note to getEnvironment function --- test/base/getEnvironment.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/base/getEnvironment.m b/test/base/getEnvironment.m index 1ee5fe0..dc93815 100644 --- a/test/base/getEnvironment.m +++ b/test/base/getEnvironment.m @@ -7,6 +7,11 @@ % environment: a struct with two fields % * .globals - contains all global values % * .path - contains the current path +% NOTE: +% this function has been uploaded from +% https://github.com/opencobra/cobratoolbox/blob/master/src/base/utilities/getEnvironment.m +% [cadfa58] + environment = struct(); globals = struct(); globalvars = who('global'); From 3927d52bc42475f6cfd54d3ed0cb2877af5c28ad Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 10:14:39 +0200 Subject: [PATCH 114/132] note to getFilesInDir function --- test/base/getFilesInDir.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/base/getFilesInDir.m b/test/base/getFilesInDir.m index 220940e..788e462 100644 --- a/test/base/getFilesInDir.m +++ b/test/base/getFilesInDir.m @@ -43,6 +43,11 @@ % % % get only the gitIgnored files in the current folder % files = getFilesInDir('type', 'ignored'); +% +% NOTE: +% this function has been uploaded from +% https://github.com/opencobra/cobratoolbox/blob/master/src/base/install/getFilesInDir.m +% [cdb2478] persistent COBRAIgnored From 63c5c7faddf335aae4f3188344056f862c72e126 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 10:18:19 +0200 Subject: [PATCH 115/132] note to getGlobalValue function --- test/base/getGlobalValue.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/base/getGlobalValue.m b/test/base/getGlobalValue.m index 9c8c879..053ad06 100644 --- a/test/base/getGlobalValue.m +++ b/test/base/getGlobalValue.m @@ -9,6 +9,11 @@ % % OUTPUT: % value: The value of the requested global variable +% +% NOTE: +% this function has been uploaded from +% https://github.com/opencobra/cobratoolbox/blob/master/src/base/utilities/getGlobalValue.m +% [e6b4efd] eval(['global ' globalName]); eval(['value = ' globalName ';']); From a1fbef812f592ec8cb3d41fe80b148aeabcefd38 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 10:21:01 +0200 Subject: [PATCH 116/132] note to getIgnoreFiles function --- test/base/getIgnoredFiles.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/base/getIgnoredFiles.m b/test/base/getIgnoredFiles.m index 2130e2e..42d0708 100644 --- a/test/base/getIgnoredFiles.m +++ b/test/base/getIgnoredFiles.m @@ -16,6 +16,10 @@ % % .. Authors: - Original Code: Laurent Heirandt % - Move to function: Thomas Pfau, Jan 2018 +% NOTE: +% this function has been adapted from +% https://github.com/opencobra/cobratoolbox/blob/master/src/base/install/getIgnoredFiles.m +% [f9a9213] global PACERDIR From af133a464eeb4952fa8e1cbf6141785f1eab1a7e Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 10:27:55 +0200 Subject: [PATCH 117/132] note to restoreEnvironment function --- test/base/restoreEnvironment.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/base/restoreEnvironment.m b/test/base/restoreEnvironment.m index 95db5e4..f8f9e20 100644 --- a/test/base/restoreEnvironment.m +++ b/test/base/restoreEnvironment.m @@ -12,7 +12,8 @@ function restoreEnvironment(environment, restorePath, printLevel) % printLevel: Set the verbosity of this method: % * 0: No outputs (Default) % * 1: Info what each value is set to -% +% + if ~exist('restorePath','var') restorePath = true; end From ff7b17060ed9e436f8ef8728e15347cffa8eda6d Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 10:30:33 +0200 Subject: [PATCH 118/132] note to restoreEnvironment function --- test/base/restoreEnvironment.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/base/restoreEnvironment.m b/test/base/restoreEnvironment.m index f8f9e20..0b61953 100644 --- a/test/base/restoreEnvironment.m +++ b/test/base/restoreEnvironment.m @@ -12,7 +12,11 @@ function restoreEnvironment(environment, restorePath, printLevel) % printLevel: Set the verbosity of this method: % * 0: No outputs (Default) % * 1: Info what each value is set to -% +% NOTE: +% this function has been adapted from +% https://github.com/opencobra/cobratoolbox/blob/master/src/base/utilities/restoreEnvironment.m +% [005f7d1] + if ~exist('restorePath','var') restorePath = true; From 09eaea8440deebfb5069a4b09f9843423af61fed Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 10:31:11 +0200 Subject: [PATCH 119/132] note to restoreEnvironment function --- test/base/restoreEnvironment.m | 1 - 1 file changed, 1 deletion(-) diff --git a/test/base/restoreEnvironment.m b/test/base/restoreEnvironment.m index 0b61953..4d01569 100644 --- a/test/base/restoreEnvironment.m +++ b/test/base/restoreEnvironment.m @@ -17,7 +17,6 @@ function restoreEnvironment(environment, restorePath, printLevel) % https://github.com/opencobra/cobratoolbox/blob/master/src/base/utilities/restoreEnvironment.m % [005f7d1] - if ~exist('restorePath','var') restorePath = true; end From 9de753c597d71fcf4a8597dceff36495c5f292db Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 10:33:27 +0200 Subject: [PATCH 120/132] note to runScriptFile function --- test/base/runScriptFile.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/base/runScriptFile.m b/test/base/runScriptFile.m index 31201f2..5c56f84 100644 --- a/test/base/runScriptFile.m +++ b/test/base/runScriptFile.m @@ -17,6 +17,11 @@ % - `.Error`: Error message received from a failed or skipped test % % .. Author: - Thomas Pfau Jan 2018. +% +% NOTE: +% this function has been adapted from +% https://github.com/opencobra/cobratoolbox/blob/master/test/runScriptFile.m +% [b58da0c] global CBT_MISSING_REQUIREMENTS_ERROR_ID From 0224ce2004804b6b6d5f9a1606d33690c945d75f Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 10:35:33 +0200 Subject: [PATCH 121/132] note to runTestSuite function --- test/base/runTestSuite.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/base/runTestSuite.m b/test/base/runTestSuite.m index c7fff7f..28c5f99 100644 --- a/test/base/runTestSuite.m +++ b/test/base/runTestSuite.m @@ -24,6 +24,11 @@ % % Author: % - Thomas Pfau Jan 2018. +% +% NOTE: +% this function has been adapted from +% https://github.com/opencobra/cobratoolbox/blob/master/test/runTestSuite.m +% [5395578] global PACERDIR From 1839a1d0cee3cf3397d3cb989668b20cf5e95bca Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 10:38:01 +0200 Subject: [PATCH 122/132] note to setGloabal function --- test/base/setGlobal.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/base/setGlobal.m b/test/base/setGlobal.m index d2d1493..fc08c6f 100644 --- a/test/base/setGlobal.m +++ b/test/base/setGlobal.m @@ -7,6 +7,11 @@ function setGlobal(globalName,globalValue) % INPUTS: % globalName: A string representing the name of the global variable % globalValue: The value to set the global variable to +% +% NOTE: +% this function has been adapted from +% https://github.com/opencobra/cobratoolbox/blob/master/src/base/utilities/setGlobal.m +% [e6b4efd] eval([ globalName '_val = globalValue;']); eval(['global ' globalName]); From 71125244ce457b6e7db2989e22c0b7f2b0bdb78c Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 11:00:26 +0200 Subject: [PATCH 123/132] add header to verifyFunctionWarning --- verifyFunctionWarning.m | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 verifyFunctionWarning.m diff --git a/verifyFunctionWarning.m b/verifyFunctionWarning.m new file mode 100644 index 0000000..ea14ed6 --- /dev/null +++ b/verifyFunctionWarning.m @@ -0,0 +1,18 @@ +function success = verifyFunctionWarning(functionCall, warningMessage, varargin) +% Tests if the warning message fits to the warning provided +% +% USAGE: +% +% success = verifyFunctionWarning(functionCall, warningMessage, varargin) +% +% INPUTS: +% functionCall: The name of a function. +% warningMessage: The warning message that we want to capture +% +% OUPUTS: +% success: Catch the provided warning message +% +% AUTORS: +% Laurent Heirendt, April 2019 +% Loic Marx, April 2019 + From ca1c51fb4e26f9e15e6592d61250fc058ff7cd6f Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 11:19:38 +0200 Subject: [PATCH 124/132] WIP implementation of diary --- verifyFunctionWarning.m | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/verifyFunctionWarning.m b/verifyFunctionWarning.m index ea14ed6..bdef8b3 100644 --- a/verifyFunctionWarning.m +++ b/verifyFunctionWarning.m @@ -15,4 +15,56 @@ % AUTORS: % Laurent Heirendt, April 2019 % Loic Marx, April 2019 +% +% NOTE: +% This function has been adapted from +% https://github.com/opencobra/cobratoolbox/blob/master/test/verifyCobraFunctionError.m +% [5aa9ccd] + +testMessage = false; +parser = inputParser(); +parser.addRequired('functionCall',@ischar) +parser.addRequired('warningMessage','',@ischar) +parser.addParamValue('inputs',{},@iscell) +parser.addParamValue('outputArgCount',0,@(x) isnumeric(x) && mod(x,1) == 0); + +parser.parse(functionCall,varargin{:}); + +outputArgcount = parser.Results.outputArgCount; +warningMessage = ~any(ismember('warningMessage',parser.UsingDefaults)); +message = parser.Results.testMessage; +inputs = parser.Results.inputs; + +functionCall = str2func(functionCall); +success = true; + +verifyFunctionWarning = false; +logFile = '.testCatch.log'; +diary(logFile); % run the function in diary mode +try + if outputArgcount > 0 + outArgs = cell(outputArgcount,1); + [outArgs{:}] = functionCall(inputs{:}); + else + functionCall(inputs{:}); + end +end + + diary off + +% loop through the temporary diary file + fid = fopen(logFile); + tline = fgetl(fid); + while ischar(tline) + tline = fgetl(fid); + disp(tline); + if ~isempty(tline) && contains(tline, warningMessage) + verifyFunctionWarning = true; + break; + end + end + fclose(fid); + % remove the temporary diary file + delete(logFile); +end From 8f779281eeea1c21fd51b8d5d374a132933953d2 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 14:34:27 +0200 Subject: [PATCH 125/132] WIP --- verifyFunctionWarning.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/verifyFunctionWarning.m b/verifyFunctionWarning.m index bdef8b3..b24ba4d 100644 --- a/verifyFunctionWarning.m +++ b/verifyFunctionWarning.m @@ -21,24 +21,24 @@ % https://github.com/opencobra/cobratoolbox/blob/master/test/verifyCobraFunctionError.m % [5aa9ccd] -testMessage = false; +warningMessage = false; parser = inputParser(); parser.addRequired('functionCall',@ischar) parser.addRequired('warningMessage','',@ischar) parser.addParamValue('inputs',{},@iscell) parser.addParamValue('outputArgCount',0,@(x) isnumeric(x) && mod(x,1) == 0); -parser.parse(functionCall,varargin{:}); +parser.parse(functionCall, warningMessage, varargin{:}); outputArgcount = parser.Results.outputArgCount; warningMessage = ~any(ismember('warningMessage',parser.UsingDefaults)); -message = parser.Results.testMessage; +message = parser.Results.warningMessage; inputs = parser.Results.inputs; functionCall = str2func(functionCall); success = true; -verifyFunctionWarning = false; +%success = false; logFile = '.testCatch.log'; diary(logFile); % run the function in diary mode try From 93b74ae5c1231f069390f78b93a09fed21806ba3 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Tue, 23 Apr 2019 16:14:21 +0200 Subject: [PATCH 126/132] WIP diary mode --- verifyFunctionWarning.m | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/verifyFunctionWarning.m b/verifyFunctionWarning.m index b24ba4d..6258d6d 100644 --- a/verifyFunctionWarning.m +++ b/verifyFunctionWarning.m @@ -21,24 +21,23 @@ % https://github.com/opencobra/cobratoolbox/blob/master/test/verifyCobraFunctionError.m % [5aa9ccd] -warningMessage = false; + parser = inputParser(); -parser.addRequired('functionCall',@ischar) -parser.addRequired('warningMessage','',@ischar) +parser.addRequired('functionCall', @ischar) +parser.addRequired('warningMessage', @ischar) parser.addParamValue('inputs',{},@iscell) parser.addParamValue('outputArgCount',0,@(x) isnumeric(x) && mod(x,1) == 0); parser.parse(functionCall, warningMessage, varargin{:}); outputArgcount = parser.Results.outputArgCount; -warningMessage = ~any(ismember('warningMessage',parser.UsingDefaults)); -message = parser.Results.warningMessage; +%warningMessage = ~any(ismember('warningMessage',parser.UsingDefaults)); +%message = parser.Results.warningMessage; inputs = parser.Results.inputs; functionCall = str2func(functionCall); -success = true; +success = false; -%success = false; logFile = '.testCatch.log'; diary(logFile); % run the function in diary mode try @@ -55,14 +54,21 @@ % loop through the temporary diary file fid = fopen(logFile); tline = fgetl(fid); - while ischar(tline) - tline = fgetl(fid); - disp(tline); + counter = 0; + while ~feof(fid) + tline = [tline ' ' fgetl(fid)]; + %disp(tline); if ~isempty(tline) && contains(tline, warningMessage) - verifyFunctionWarning = true; + success = true; break; end + if counter > 3 + tline = ''; + counter = 0; + end + counter = counter + 1; end + fclose(fid); % remove the temporary diary file From c7dbc45c5c0d7e5d9a75246572afe8027332dbd0 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 24 Apr 2019 10:42:28 +0200 Subject: [PATCH 127/132] clean up the code --- verifyFunctionWarning.m | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/verifyFunctionWarning.m b/verifyFunctionWarning.m index 6258d6d..3e7fecf 100644 --- a/verifyFunctionWarning.m +++ b/verifyFunctionWarning.m @@ -1,16 +1,20 @@ function success = verifyFunctionWarning(functionCall, warningMessage, varargin) -% Tests if the warning message fits to the warning provided +% Tests if the warning message fits to the provided warning % % USAGE: % -% success = verifyFunctionWarning(functionCall, warningMessage, varargin) +% success = verifyFunctionWarning('functionCall', warningMessage, varargin) % % INPUTS: % functionCall: The name of a function. % warningMessage: The warning message that we want to capture % % OUPUTS: -% success: Catch the provided warning message +% success: Catch the provided warning message in tline +% +% EXAMPLE: +% % Test whether PaCER function throws the provided warning message: +% verifyFunctionWarning('PaCER', warningMessage, 'inputs', {niiCT}) % % AUTORS: % Laurent Heirendt, April 2019 @@ -21,43 +25,41 @@ % https://github.com/opencobra/cobratoolbox/blob/master/test/verifyCobraFunctionError.m % [5aa9ccd] - parser = inputParser(); parser.addRequired('functionCall', @ischar) parser.addRequired('warningMessage', @ischar) -parser.addParamValue('inputs',{},@iscell) -parser.addParamValue('outputArgCount',0,@(x) isnumeric(x) && mod(x,1) == 0); - +parser.addParamValue('inputs', {}, @iscell) +parser.addParamValue('outputArgCount', 0, @(x) isnumeric(x) && mod(x,1) == 0); parser.parse(functionCall, warningMessage, varargin{:}); outputArgcount = parser.Results.outputArgCount; -%warningMessage = ~any(ismember('warningMessage',parser.UsingDefaults)); -%message = parser.Results.warningMessage; inputs = parser.Results.inputs; - functionCall = str2func(functionCall); -success = false; -logFile = '.testCatch.log'; -diary(logFile); % run the function in diary mode +% initialize the test +success = false; +% create an hidden file +logFile = '.testCatch.log'; +% run the function in diary mode +diary(logFile); try if outputArgcount > 0 - outArgs = cell(outputArgcount,1); + outArgs = cell(outputArgcount, 1); [outArgs{:}] = functionCall(inputs{:}); else functionCall(inputs{:}); end end - diary off % loop through the temporary diary file fid = fopen(logFile); tline = fgetl(fid); counter = 0; - while ~feof(fid) + % Read one line at a time until you reach the end of the file + while ~feof(fid) + % Concatenate the text if the provided warning message is found in the 3 next line, otherwise tline is empty tline = [tline ' ' fgetl(fid)]; - %disp(tline); if ~isempty(tline) && contains(tline, warningMessage) success = true; break; @@ -70,7 +72,6 @@ end fclose(fid); - % remove the temporary diary file delete(logFile); end From aa9d08d351083eebe86f62e55478bc6adefceba2 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 24 Apr 2019 10:42:28 +0200 Subject: [PATCH 128/132] clean up the code From c7d62692e7643aa06cc58c8a0b2284b662b92b72 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 24 Apr 2019 10:42:28 +0200 Subject: [PATCH 129/132] clean up the code From 21234e490085bdd67f04435be159c8f21aec2cba Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 24 Apr 2019 11:20:22 +0200 Subject: [PATCH 130/132] deleted unrelevant files --- .testCatch.log | 10 ----- catchWarning.m | 25 ------------ test/suite/.testCatch.log | 84 --------------------------------------- testA.m | 4 -- testB.m | 3 -- 5 files changed, 126 deletions(-) delete mode 100644 .testCatch.log delete mode 100644 catchWarning.m delete mode 100644 test/suite/.testCatch.log delete mode 100644 testA.m delete mode 100644 testB.m diff --git a/.testCatch.log b/.testCatch.log deleted file mode 100644 index afb962c..0000000 --- a/.testCatch.log +++ /dev/null @@ -1,10 +0,0 @@ -{Error: File: testA.m Line: 2 Column: 1 -Invalid use of operator. - -Error in catchWarning (line 7) - eval(functionName); -} -niiCT_brainMask_new = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']); -clear -niiCT_brainMask_new = NiftiMod([getenv('PACER_DATA_PATH') filesep 'input' filesep 'ct_post.nii.gz']); -foundWarning = catchWarning('PaCER', 'Slice thickness is greater than 0.7 mm! Independet contact detection might not work reliable in this case. However, for certain electrode types with large contacts spacings you might be lucky.'); diff --git a/catchWarning.m b/catchWarning.m deleted file mode 100644 index cf400c0..0000000 --- a/catchWarning.m +++ /dev/null @@ -1,25 +0,0 @@ -function foundWarning = catchWarning(functionName, warningMsg) - foundWarning = false; - logFile = '.testCatch.log'; - - % run the function in diary mode - diary(logFile); - eval(functionName); - diary off - - % loop through the temporary diary file - fid = fopen(logFile); - tline = fgetl(fid); - while ischar(tline) - tline = fgetl(fid); - disp(tline); - if ~isempty(tline) && contains(tline, warningMsg) - foundWarning = true; - break; - end - end - fclose(fid); - - % remove the temporary diary file - delete(logFile); -end \ No newline at end of file diff --git a/test/suite/.testCatch.log b/test/suite/.testCatch.log deleted file mode 100644 index 5e5b434..0000000 --- a/test/suite/.testCatch.log +++ /dev/null @@ -1,84 +0,0 @@ -{Not enough input arguments. - -Error in PaCER (line 35) -if(~isa(niiCT, 'NiftiMod') && ~isa(niiCT, 'NiftiModSPM') ) - -Error in catchWarning (line 7) - eval(functionName); -} -[elecModels_warning, elecPointCloudsStruct_warning, intensityProfiles_warning, skelSkelmms_warning] = PaCER(niiCT_brainMask_new); -[Warning: Slice thickness is greater than 0.7 mm! Independet contact detection might not work reliable in this case. However, -for certain electrode types with large contacts spacings you might be lucky. -(Type "warning off " to suppress this warning.) -] -[> In PaCER (line 44)] -===================== Processing /Users/loicmarx/pacer.data/input/ct_post.nii.gz ===================== -Voxel size: 0.48828 0.48828 1 -Voxel size in elecsPointcloudStruct: 0.48828 0.48828 1 -Loading /Users/loicmarx/pacer.data/input/ct_post.nii.gz from disk... -Caching is enabeld. -Extracting convex hull brain mask... -MorphFraction:0.14229 -[Warning: Uncommon fraction of CT data in threshold range (15-60 HU). Trying to compensate. Make sure to use "soft tissue" -reconstruction filters for the CT (e.g. J30 kernel) if this fails. -(Type "warning off " to suppress this warning.) -] -[> In extractBrainConvHull (line 64) - In extractElectrodePointclouds (line 64) - In PaCER (line 51)] -Thresholding /Users/loicmarx/pacer.data/input/ct_post.nii.gz for metal with METAL_THRESHOLD = 800... -19 potential metal components detected within brain. -Guessing that 2 of them are Electrodes... -No xmlElectrodeDefition given. Guessing that there are 2 electrodes in the image -------------- Processing Electrode ------------- -Applied axial skeleton filter because of low intensity planes -Max off-model: 0.078328 Mean off-model: 0.034988 -Max off-model: 0.53878 Mean off-model: 0.021295 -Check for outliers / make sure that the polynomial degree choosen is appropriate. - In most cases this should be fine. -1st Pass Electrode Length within Brain Convex Hull: 73.9421mm -2nd Pass Electrode Length within Brain Convex Hull: 74.6762mm -refitElec: selected contactDetectionMethod is contactAreaCenter -determineElectrodeType: data to model peak/contact spacing RMS distance is 0.36034 [mm] -Trying to estimate electrode type by simple contactAreaCenter. -[Warning: No electrode specification given! Set electrodeType option! Trying to estimate type by contactAreaWidth only which -might be wrong! -(Type "warning off " to suppress this warning.) -] -[> In refitElec (line 125) - In PaCER (line 60)] -Assuming Medtronic 3389 or Boston Scientific Vercise Directional. Setting 3389. -Max off-model: 0.43564 Mean off-model: 0.10219 -Check for outliers / make sure that the polynomial degree choosen is appropriate. - In most cases this should be fine. -Electrode Length within Brain Convex Hull after contact detection and Zero-Point calibration: 73.8118mm -------------- Processing Electrode ------------- -Applied axial skeleton filter because of low intensity planes -Max off-model: 0.13706 Mean off-model: 0.039501 -Max off-model: 0.24463 Mean off-model: 0.021733 -1st Pass Electrode Length within Brain Convex Hull: 68.8864mm -2nd Pass Electrode Length within Brain Convex Hull: 69.7922mm -refitElec: selected contactDetectionMethod is contactAreaCenter -determineElectrodeType: data to model peak/contact spacing RMS distance is 0.11336 [mm] -Trying to estimate electrode type by simple contactAreaCenter. -[Warning: No electrode specification given! Set electrodeType option! Trying to estimate type by contactAreaWidth only which -might be wrong! -(Type "warning off " to suppress this warning.) -] -[> In refitElec (line 125) - In PaCER (line 60)] -Assuming Medtronic 3389 or Boston Scientific Vercise Directional. Setting 3389. -Max off-model: 0.32285 Mean off-model: 0.06274 -Check for outliers / make sure that the polynomial degree choosen is appropriate. - In most cases this should be fine. -Electrode Length within Brain Convex Hull after contact detection and Zero-Point calibration: 68.971mm -foundWarning = catchWarning('PaCER', 'Slice thickness is greater than 0.7 mm! Independet contact detection might not work reliable in this case. However, for certain electrode types with large contacts spacings you might be lucky.'); -{Not enough input arguments. - -Error in PaCER (line 35) -if(~isa(niiCT, 'NiftiMod') && ~isa(niiCT, 'NiftiModSPM') ) - -Error in catchWarning (line 7) - eval(functionName); -} -foundWarning = catchWarning('PaCER', 'Slice thickness is greater than 0.7 mm! Independet contact detection might not work reliable in this case. However, for certain electrode types with large contacts spacings you might be lucky.'); diff --git a/testA.m b/testA.m deleted file mode 100644 index 59334b2..0000000 --- a/testA.m +++ /dev/null @@ -1,4 +0,0 @@ -function testA() - warning('This is a warning in the testA function.'); - testB(); -end diff --git a/testB.m b/testB.m deleted file mode 100644 index 5f94ccc..0000000 --- a/testB.m +++ /dev/null @@ -1,3 +0,0 @@ -function testB() - warning('This is a warning in the testB function'); -end From e9a3bbe853805cef5c11cc891614ad9e23436b82 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 24 Apr 2019 13:05:41 +0200 Subject: [PATCH 131/132] formating code --- verifyFunctionWarning.m | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/verifyFunctionWarning.m b/verifyFunctionWarning.m index 3e7fecf..a9b1b75 100644 --- a/verifyFunctionWarning.m +++ b/verifyFunctionWarning.m @@ -6,15 +6,15 @@ % success = verifyFunctionWarning('functionCall', warningMessage, varargin) % % INPUTS: -% functionCall: The name of a function. -% warningMessage: The warning message that we want to capture +% functionCall: The name of a function +% warningMessage: The specific warning message that need to be tested % % OUPUTS: -% success: Catch the provided warning message in tline +% success: Verify if the function throws the provided warning message and catch it in tline % % EXAMPLE: % % Test whether PaCER function throws the provided warning message: -% verifyFunctionWarning('PaCER', warningMessage, 'inputs', {niiCT}) +% assert(verifyFunctionWarning('PaCER', warningMessage, 'inputs', {niiCT})); % % AUTORS: % Laurent Heirendt, April 2019 @@ -31,11 +31,9 @@ parser.addParamValue('inputs', {}, @iscell) parser.addParamValue('outputArgCount', 0, @(x) isnumeric(x) && mod(x,1) == 0); parser.parse(functionCall, warningMessage, varargin{:}); - outputArgcount = parser.Results.outputArgCount; inputs = parser.Results.inputs; functionCall = str2func(functionCall); - % initialize the test success = false; % create an hidden file @@ -50,15 +48,16 @@ functionCall(inputs{:}); end end - diary off - + diary off % loop through the temporary diary file fid = fopen(logFile); tline = fgetl(fid); counter = 0; - % Read one line at a time until you reach the end of the file + % Read the code until it reaches the end of the script while ~feof(fid) - % Concatenate the text if the provided warning message is found in the 3 next line, otherwise tline is empty + % Setup the function to read the script three lines by three lines. If a + % warning message is found in these three lines, this message will be + % concatenated in tline. If not, tline will be empty. tline = [tline ' ' fgetl(fid)]; if ~isempty(tline) && contains(tline, warningMessage) success = true; @@ -70,7 +69,6 @@ end counter = counter + 1; end - fclose(fid); % remove the temporary diary file delete(logFile); From 6c9a626c37dfc353fdc31c04f6705947f343eab6 Mon Sep 17 00:00:00 2001 From: Loic Marx Date: Wed, 24 Apr 2019 15:16:28 +0200 Subject: [PATCH 132/132] Formating --- verifyFunctionWarning.m | 66 +++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/verifyFunctionWarning.m b/verifyFunctionWarning.m index a9b1b75..8bc5f27 100644 --- a/verifyFunctionWarning.m +++ b/verifyFunctionWarning.m @@ -10,11 +10,11 @@ % warningMessage: The specific warning message that need to be tested % % OUPUTS: -% success: Verify if the function throws the provided warning message and catch it in tline +% success: Boolean indicating whether the warning message is thrown % % EXAMPLE: % % Test whether PaCER function throws the provided warning message: -% assert(verifyFunctionWarning('PaCER', warningMessage, 'inputs', {niiCT})); +% verifyFunctionWarning('PaCER', warningMessage, 'inputs', {niiCT}); % % AUTORS: % Laurent Heirendt, April 2019 @@ -25,44 +25,51 @@ % https://github.com/opencobra/cobratoolbox/blob/master/test/verifyCobraFunctionError.m % [5aa9ccd] -parser = inputParser(); -parser.addRequired('functionCall', @ischar) -parser.addRequired('warningMessage', @ischar) -parser.addParamValue('inputs', {}, @iscell) -parser.addParamValue('outputArgCount', 0, @(x) isnumeric(x) && mod(x,1) == 0); -parser.parse(functionCall, warningMessage, varargin{:}); -outputArgcount = parser.Results.outputArgCount; -inputs = parser.Results.inputs; -functionCall = str2func(functionCall); -% initialize the test -success = false; -% create an hidden file -logFile = '.testCatch.log'; -% run the function in diary mode -diary(logFile); -try - if outputArgcount > 0 - outArgs = cell(outputArgcount, 1); - [outArgs{:}] = functionCall(inputs{:}); - else - functionCall(inputs{:}); + parser = inputParser(); + parser.addRequired('functionCall', @ischar) + parser.addRequired('warningMessage', @ischar) + parser.addParamValue('inputs', {}, @iscell) + parser.addParamValue('outputArgCount', 0, @(x) isnumeric(x) && mod(x,1) == 0); + parser.parse(functionCall, warningMessage, varargin{:}); + outputArgcount = parser.Results.outputArgCount; + + inputs = parser.Results.inputs; + functionCall = str2func(functionCall); + + % initialize the test + success = false; + + % create an hidden file + logFile = '.testCatch.log'; + + % run the function in diary mode + diary(logFile); + try + if outputArgcount > 0 + outArgs = cell(outputArgcount, 1); + [outArgs{:}] = functionCall(inputs{:}); + else + functionCall(inputs{:}); + end end -end diary off -% loop through the temporary diary file + + % loop through the temporary diary file fid = fopen(logFile); tline = fgetl(fid); counter = 0; - % Read the code until it reaches the end of the script + + % read the code until it reaches the end of the script while ~feof(fid) - % Setup the function to read the script three lines by three lines. If a - % warning message is found in these three lines, this message will be - % concatenated in tline. If not, tline will be empty. + % setup the function to read the script three lines by three lines. tline = [tline ' ' fgetl(fid)]; if ~isempty(tline) && contains(tline, warningMessage) success = true; break; end + + % if a warning message is found in consecutive three lines, this message will be + % concatenated in tline. If not, tline will be reset. if counter > 3 tline = ''; counter = 0; @@ -70,6 +77,7 @@ counter = counter + 1; end fclose(fid); + % remove the temporary diary file delete(logFile); end