Commit 1dcd0f7d authored by Vaanathi Sundaresan's avatar Vaanathi Sundaresan
Browse files

Merge branch 'vaanu' into 'master'

LOCATE initial commit

See merge request !1
parents 1d8b4e8a 7b4a6f25
File added
function LUT = FillEulerLUT
LUT(1) = 1;
LUT(3) = -1;
LUT(5) = -1;
LUT(7) = 1;
LUT(9) = -3;
LUT(11) = -1;
LUT(13) = -1;
LUT(15) = 1;
LUT(17) = -1;
LUT(19) = 1;
LUT(21) = 1;
LUT(23) = -1;
LUT(25) = 3;
LUT(27) = 1;
LUT(29) = 1;
LUT(31) = -1;
LUT(33) = -3;
LUT(35) = -1;
LUT(37) = 3;
LUT(39) = 1;
LUT(41) = 1;
LUT(43) = -1;
LUT(45) = 3;
LUT(47) = 1;
LUT(49) = -1;
LUT(51) = 1;
LUT(53) = 1;
LUT(55) = -1;
LUT(57) = 3;
LUT(59) = 1;
LUT(61) = 1;
LUT(63) = -1;
LUT(65) = -3;
LUT(67) = 3;
LUT(69) = -1;
LUT(71) = 1;
LUT(73) = 1;
LUT(75) = 3;
LUT(77) = -1;
LUT(79) = 1;
LUT(81) = -1;
LUT(83) = 1;
LUT(85) = 1;
LUT(87) = -1;
LUT(89) = 3;
LUT(91) = 1;
LUT(93) = 1;
LUT(95) = -1;
LUT(97) = 1;
LUT(99) = 3;
LUT(101) = 3;
LUT(103) = 1;
LUT(105) = 5;
LUT(107) = 3;
LUT(109) = 3;
LUT(111) = 1;
LUT(113) = -1;
LUT(115) = 1;
LUT(117) = 1;
LUT(119) = -1;
LUT(121) = 3;
LUT(123) = 1;
LUT(125) = 1;
LUT(127) = -1;
LUT(129) = -7;
LUT(131) = -1;
LUT(133) = -1;
LUT(135) = 1;
LUT(137) = -3;
LUT(139) = -1;
LUT(141) = -1;
LUT(143) = 1;
LUT(145) = -1;
LUT(147) = 1;
LUT(149) = 1;
LUT(151) = -1;
LUT(153) = 3;
LUT(155) = 1;
LUT(157) = 1;
LUT(159) = -1;
LUT(161) = -3;
LUT(163) = -1;
LUT(165) = 3;
LUT(167) = 1;
LUT(169) = 1;
LUT(171) = -1;
LUT(173) = 3;
LUT(175) = 1;
LUT(177) = -1;
LUT(179) = 1;
LUT(181) = 1;
LUT(183) = -1;
LUT(185) = 3;
LUT(187) = 1;
LUT(189) = 1;
LUT(191) = -1;
LUT(193) = -3;
LUT(195) = 3;
LUT(197) = -1;
LUT(199) = 1;
LUT(201) = 1;
LUT(203) = 3;
LUT(205) = -1;
LUT(207) = 1;
LUT(209) = -1;
LUT(211) = 1;
LUT(213) = 1;
LUT(215) = -1;
LUT(217) = 3;
LUT(219) = 1;
LUT(221) = 1;
LUT(223) = -1;
LUT(225) = 1;
LUT(227) = 3;
LUT(229) = 3;
LUT(231) = 1;
LUT(233) = 5;
LUT(235) = 3;
LUT(237) = 3;
LUT(239) = 1;
LUT(241) = -1;
LUT(243) = 1;
LUT(245) = 1;
LUT(247) = -1;
LUT(249) = 3;
LUT(251) = 1;
LUT(253) = 1;
LUT(255) = -1;
function LOCATE_LOSO_testing(varargin)
% Function for extracting features from the images in a directory
% and performing Leave-one-subject-out testing for LOCATE
% Copyright - FMRIB, WIN, University of Oxford
% Vaanathi Sundaresan - 25/05/2018
%
% Example funtional calls:
% 1. LOCATE_LOSO_testing();
% - If you have the training images (all the modalities) in the same folder
% 2. LOCATE_LOSO_testing(train_image_directory_name);
% - If you have the training images are in the seperate directory
% 3. LOCATE_LOSO_testing(train_image_directory_name, feat_select);
% - If you want to select specific features for training and testing
% 4. LOCATE_LOSO_testing(train_image_directory_name, feat_select, verbose);
%
% Optional inputs (in the order):
% - train_image_directory_name - Name of the directory where the training images for feature extraction are located (if not in the same folder)
% - feat_select - vector with elements indicating if the feature has to be included or not. Current order is distance from ventricles, lesion volume and other modalities in alphabetical naming order
% (e.g. If FLAIR is the only modality provided and distance from ventricles is not needed then feat_Select = [0, 1, 1])
% - verbose (0 or 1)
addpath('MATLAB');
training_image_directory_name = pwd;
if nargin > 0
training_image_directory_name = varargin{1};
end
% Assigning the Root directories
root_data_directory = training_image_directory_name;
results_directory = sprintf('%s/LOCATE_LOSO_results_directory',training_image_directory_name);
xdir = dir(sprintf('%s/*_BIANCA_LPM.nii.gz',root_data_directory));
if numel(xdir) == 0
error('Cannot find any input image. Please check your training_image_directoy_name');
else
xsplit = regexp(xdir(1).name,'_BIANCA_LPM','split');
xfeats = dir(sprintf('%s/%s_feature_*',root_data_directory,xsplit{1}));
if numel(xfeats) == 0
fprintf('Warning: No feature modality found. Can extract only volume and ventricle distance \n');
end
end
numfeats = numel(xfeats);
feature_selection_cols = ones(numfeats+2,1);
if nargin > 1
if numel(varargin{2}) == 1
error('Second input (feat_select) must be a vector with number of elements equal to the number of features specified.');
elseif numel(varargin{2}) < numfeats + 2
error('Number of columns in feat_select does not match the number of features specified.');
else
feature_selection_cols = varargin{2};
end
end
verbose = 0;
if nargin > 2
verbose = varargin{3};
end
if verbose
feature_selection_cols
training_image_directory_name
end
% Creating the results directory
if ~exist(results_directory)
mkdir(results_directory)
end
imgfeatmats = cell(numel(xdir),1);
ventdistfeatmats = cell(numel(xdir),1);
lesvolfeatmats = cell(numel(xdir),1);
minbestthrs = cell(numel(xdir),1);
maxbestthrs = cell(numel(xdir),1);
meanbestthrs = cell(numel(xdir),1);
index_indices_list = cell(numel(xdir),1);
index_maps = cell(numel(xdir),1);
for subj = 1:numel(xdir)
if verbose
subj
end
xsplit = regexp(xdir(subj).name,'_BIANCA_LPM','split');
xfeats = dir(sprintf('Test/%s_feature_*',xsplit{1}));
flairimage = cell(numel(xfeats),1);
% Loading the image files
lesionmaskfile = sprintf('%s/%s_BIANCA_LPM.nii.gz',root_data_directory,xsplit{1});
manualmaskfile = sprintf('%s/%s_manualmask.nii.gz',root_data_directory,xsplit{1});
biancamaskfile = sprintf('%s/%s_biancamask.nii.gz',root_data_directory,xsplit{1});
brainmaskfile = sprintf('%s/%s_brainmask.nii.gz',root_data_directory,xsplit{1});
lesionmask = read_avw(lesionmaskfile);
manualmask = read_avw(manualmaskfile);
biancamask = read_avw(biancamaskfile);
brainmask = read_avw(brainmaskfile);
if feature_selection_cols(1) == 0
try
ventdistmapfile = sprintf('%s/%s_ventdistmap.nii.gz',root_data_directory,xsplit{1});
ventdistmap = read_avw(ventdistmapfile);
catch
ventdistmap = zeros(size(lesionmask));
end
else
ventdistmapfile = sprintf('%s/%s_ventdistmap.nii.gz',root_data_directory,xsplit{1});
ventdistmap = read_avw(ventdistmapfile);
end
for subj_feat_no = 1:numel(xfeats)
flairimagefile = sprintf('%s/%s',root_data_directory,xfeats(subj_feat_no).name);
flairimage{subj_feat_no} = read_avw(flairimagefile);
end
if verbose
fprintf('All specified feature image modalities loaded \n');
end
% Getting image dimensions and determining up/downsampling factor
dim = size(lesionmask);
factor = floor(max(dim)./dim);
inv_factor = 1./factor;
% Up/downsampling the images
lesionmask = imresizen(lesionmask,factor);
biancamask = imresizen(single(biancamask),factor);
brainmask = imresizen(single(brainmask),factor);
biancamask = (biancamask>0) & (brainmask>0);
% Performing Voronoi tessellation on resampled images
[lesionmask, index_mask, index_numbers] = LOCATE_Voronoi_tessellation(lesionmask, biancamask, inv_factor);
if verbose
fprintf('Voronoi Tessellation done! \n')
end
numel(index_numbers)
% Extractng features from Voronoi regions individually
[flairintfeats, ventdistfeats, lesvolfeats, minbestthr_values, maxbestthr_values, meanbestthr_values, index_numbers, index_mask] ...
= LOCATE_feature_extraction(lesionmask, ventdistmap, flairimage, manualmask, index_mask, index_numbers);
if verbose
fprintf('LOCATE features extracted! \n')
end
% Storing the features in a cell array
imgfeatmats{subj} = flairintfeats;
ventdistfeatmats{subj} = ventdistfeats;
lesvolfeatmats{subj} = lesvolfeats;
minbestthrs{subj} = minbestthr_values;
maxbestthrs{subj} = maxbestthr_values;
meanbestthrs{subj} = meanbestthr_values;
index_indices_list{subj} = index_numbers;
index_maps{subj} = index_mask;
% Saving the features as an intermediate results .mat file
save(sprintf('%s/LOCATE_features_%s.mat',...
root_data_directory,xsplit{1}),'flairintfeats',...
'ventdistfeats','lesvolfeats','minbestthr_values','maxbestthr_values','meanbestthr_values','index_numbers','index_mask');
end
% Saving the array as an intermediate results .mat file
save(sprintf('%s/LOCATE_features.mat',root_data_directory),'imgfeatmats',...
'ventdistfeatmats','lesvolfeatmats','minbestthrs','maxbestthrs','meanbestthrs','index_indices_list','index_maps');
if verbose
fprintf('LOCATE features saved! \n')
end
% Loading the features (not needed) if run on a local system (can aslo
% resumed from this step onwards if you already have features saved in above format
% as 'LOCATE_features.mat'
load(sprintf('%s/LOCATE_features.mat',root_data_directory))
% Modifying features to correct it to remove -1's (internal processing)
[flairfeatmats_modified,ventdistfeatmats_modified,lesvolfeatmats_modified] = LOCATE_modify_voronoi_features(imgfeatmats,ventdistfeatmats,lesvolfeatmats);
imgfeatmats = flairfeatmats_modified;
ventdistfeatmats = ventdistfeatmats_modified;
lesvolfeatmats = lesvolfeatmats_modified;
if verbose
fprintf('Voronoi features has been corrected! \n');
end
% Initializing cell array to store images
lesion_masks = cell(1,numel(xdir));
thresholds = cell(1,numel(xdir));
thresholdmap = cell(1,numel(xdir));
indexmaps = cell(1,numel(xdir));
for testsubj = 1:numel(xdir)
% Load the test image
xsplit = regexp(xdir(testsubj).name,'_BIANCA_LPM','split');
lesionmaskfile = sprintf('%s/%s_BIANCA_LPM.nii.gz',root_data_directory,xsplit{1});
lesionmask = read_avw(lesionmaskfile);
% Defining the indicies of trainign subjects as everything except the
% current test subject
trainsubjects = setdiff(1:numel(xdir),testsubj);
fprintf('trainsubjects identified! \n');
% Concatenating the training features
trainflairfeatmat = [];
trainventdistfeatmat = [];
trainlesvolfeatmat = [];
trainminbestthrs = [];
trainmaxbestthrs = [];
trainmeanbestthrs = [];
for trainsubj = 1:numel(trainsubjects)
trainflairfeatmat = [trainflairfeatmat;imgfeatmats{trainsubjects(trainsubj)}];
trainventdistfeatmat = [trainventdistfeatmat;ventdistfeatmats{trainsubjects(trainsubj)}];
trainlesvolfeatmat = [trainlesvolfeatmat;lesvolfeatmats{trainsubjects(trainsubj)}];
trainminbestthrs = [trainminbestthrs;minbestthrs{trainsubjects(trainsubj)}];
trainmaxbestthrs = [trainmaxbestthrs;maxbestthrs{trainsubjects(trainsubj)}];
trainmeanbestthrs = [trainmeanbestthrs;meanbestthrs{trainsubjects(trainsubj)}];
end
voronoi_train_features_all = [trainventdistfeatmat,trainlesvolfeatmat,trainflairfeatmat];
if verbose
fprintf('Voronoi training features has been collected! \n');
end
threshold_array = 0:0.05:0.95;
feature_selection_cols_exp = repmat(feature_selection_cols, [numel(threshold_array),1]);
feature_selection_cols_exp = feature_selection_cols_exp(:)';
voronoi_train_features = voronoi_train_features_all(:,feature_selection_cols_exp);
% Training RF regression model using all the feataures except the test
% subject
RFmodel_LOSO = TreeBagger(1000,voronoi_train_features,trainmaxbestthrs,'Method','Regression',...
'numPredictorsToSample','all');
if verbose
fprintf('Training done! \n');
end
% Extract the corresponding test features and index masks from cell
% arrays
testflairfeatmat = imgfeatmats{testsubj};
testventdistfeatmat = ventdistfeatmats{testsubj};
testlesvolfeatmat = lesvolfeatmats{testsubj};
index_mask = index_maps{testsubj};
index_numbers = index_indices_list{testsubj};
voronoi_test_features_all = [testventdistfeatmat,testlesvolfeatmat,testflairfeatmat];
if verbose
fprintf('Voronoi test features has been collected! \n');
end
feature_selection_cols_exp = repmat(feature_selection_cols, [numel(threshold_array),1]);
feature_selection_cols_exp = feature_selection_cols_exp(:)';
voronoi_test_features = voronoi_test_features_all(:,feature_selection_cols_exp);
testmeanbestthrs = predict(RFmodel_LOSO,voronoi_test_features);
%Assigning the values to the final image
final_binary_lesionmask = zeros(size(lesionmask));
threshold_mask = zeros(size(lesionmask));
for ind = 1:numel(index_numbers)
voronoi_region_mask = index_mask == index_numbers(ind);
lesionmask_voronoi = lesionmask.*double(voronoi_region_mask);
binary_voronoi_lesionmask = lesionmask_voronoi > testmeanbestthrs(ind);
thresh = single(voronoi_region_mask).*testmeanbestthrs(ind);
threshold_mask = threshold_mask + thresh;
final_binary_lesionmask = final_binary_lesionmask | binary_voronoi_lesionmask;
end
lesion_masks{testsubj} = final_binary_lesionmask;
thresholds{testsubj} = testmeanbestthrs;
thresholdmap{testsubj} = threshold_mask;
indexmaps{testsubj} = index_mask;
% Saving the images
save_avw(index_mask,sprintf('%s/%s_indexmap.nii.gz',results_directory,xsplit{1}),'f',[1 1 1]);
save_avw(threshold_mask,sprintf('%s/%s_thresholdsmap.nii.gz',results_directory,xsplit{1}),'f',[1 1 1]);
save_avw(final_binary_lesionmask,sprintf('%s/%s_BIANCA_LOCATE_binarylesionmap.nii.gz',results_directory,xsplit{1}),'f',[1 1 1]);
save(sprintf('%s/%s_LOCATE_thresholds.mat',results_directory,xsplit{1}),'testmeanbestthrs');
end
% Save all the results as a consolidated single folder
save(sprintf('%s/Consolidated_LOCATE_output.mat',results_directory),'lesion_masks','thresholds','indexmaps','thresholdmap');
function [lesionmask, index_mask, index_numbers] = LOCATE_Voronoi_tessellation(lesionmask, biancamask,inv_factor)
% Function for extracting test features for LOCATE
% Copyright - FMRIB, WIN, University of Oxford
% Vaanathi Sundaresan - 25/05/2018
%
% lesionmask - BIANCA lesion probability maps
% biancamask - WM matter with SC structures used in BIANCA
% Inv_factor - inverse of up/downsampling factor to resample images to
% original dimensions
% Smoothing the images with Gaussian kernel to remove spurious lesion
% voxels
lesionmask_smooth = imgaussfilt3(lesionmask,1.8,'FilterSize',7);
% Determine local maxima of the lesion mask
regmax = imregionalmax(lesionmask_smooth);
regmax = regmax.*(biancamask>0);
regmax_props = regionprops(bwlabeln(regmax),'Centroid');
temp = struct2cell(regmax_props);
regmax_centroid = cell2mat(temp(1,:)');
% Create dummy points to restrict the voronoi points from extending to
% infinity
regmax_centroid_dummy = [1,1,1;size(lesionmask,1),1,1;1,size(lesionmask,2),1;size(lesionmask,1),size(lesionmask,2),1;...
1,1,size(lesionmask,3);size(lesionmask,1),1,size(lesionmask,3);1,size(lesionmask,2),size(lesionmask,3);...
size(lesionmask,1),size(lesionmask,2),size(lesionmask,3)];
regmax_centroid= [regmax_centroid_dummy;regmax_centroid];
% Voronoi Tessellation
[vertices,indices] = voronoin(regmax_centroid);
index_mask = zeros(size(lesionmask));
voronoi_area = zeros(1,size(indices,1)-size(regmax_centroid_dummy,1));
% Iterating over voronoi regions
for ind = size(regmax_centroid_dummy,1)+1:size(indices,1) %
temp = zeros(size(lesionmask));
reqd_indices = indices{ind};
reqd_indices(reqd_indices == 1) = [];
reqd_vertices = floor(vertices(reqd_indices,:));
reqd_vertices1 = reqd_vertices(:,1);
reqd_vertices2 = reqd_vertices(:,2);
reqd_vertices3 = reqd_vertices(:,3);
reqd_vertices1 = max(reqd_vertices1,ones(numel(reqd_vertices1),1));
reqd_vertices1 = min(reqd_vertices1,size(lesionmask,2).*ones(numel(reqd_vertices1),1));
reqd_vertices2 = max(reqd_vertices2,ones(numel(reqd_vertices1),1));
reqd_vertices2 = min(reqd_vertices2,size(lesionmask,1).*ones(numel(reqd_vertices1),1));
reqd_vertices3 = max(reqd_vertices3,ones(numel(reqd_vertices1),1));
reqd_vertices3 = min(reqd_vertices3,size(lesionmask,3).*ones(numel(reqd_vertices1),1));
reqd_vertices = [reqd_vertices1,reqd_vertices2,reqd_vertices3];
% Getting voronoi vertices
for num = 1:numel(reqd_indices)
temp(reqd_vertices(num,2),reqd_vertices(num,1), reqd_vertices(num,3)) = 1;
end
% And forming voronoi regions (as convex hulls)
voronoi_region_mask = bwconvhull3d(temp);
voronoi_region_mask = voronoi_region_mask & biancamask;
voronoi_region_mask(index_mask>0) = 0;
index = voronoi_region_mask.*(ind-size(regmax_centroid_dummy,1));
% Forming Voronoi index maps
index_mask = index_mask + index;
voronoi_area(ind-size(regmax_centroid_dummy,1)) = sum(voronoi_region_mask(:));
end
% Resizing the images back to the original dimensions
lesionmask = imresizen(lesionmask,inv_factor);
biancamask = imresizen(single(biancamask),inv_factor);
index_mask = imresizen(index_mask,inv_factor);
index_mask = round(index_mask);
index_mask = index_mask.*(biancamask);
index_numbers = setdiff(union(index_mask(:),[]),0);
end
\ No newline at end of file
function [flairintfeats, ventdistfeats, lesvolfeats, minbestthr_values, maxbestthr_values, meanbestthr_values, index_numbers, index_mask] ...
= LOCATE_feature_extraction(lesionmask, ventdistmap, flairimage, manualmask, index_mask, index_numbers)
% Function for extracting test features for LOCATE
% Copyright - FMRIB, WIN, University of Oxford
% Vaanathi Sundaresan - 25/05/2018
%
% lesionmask - BIANCA lesion probability maps
% ventdistmap - distance from the ventricles
% flairimage - FLAIR image
% index_mask - Voronoi tessellation index mask
% manualmask - sumal segmentation
% index_numbers - Voronoi tessellation region indices
thresholds = 0:0.05:0.95;
flairintfeats = zeros(numel(index_numbers),numel(thresholds)*numel(flairimage));
ventdistfeats = zeros(numel(index_numbers),numel(thresholds));
lesvolfeats = zeros(numel(index_numbers),numel(thresholds));
dice_values = zeros(numel(index_numbers),1);
maxbestthr_values = zeros(numel(index_numbers),1);
minbestthr_values = zeros(numel(index_numbers),1);
meanbestthr_values = zeros(numel(index_numbers),1);
fprintf('Initiating LOCATE feature extraction...')
% Iterating over Voronoi regions
for ind = 1:numel(index_numbers)
voronoi_region_mask = index_mask == index_numbers(ind);
lesionmask_voronoi = lesionmask.*double(voronoi_region_mask);
manualmask_voronoi = single(manualmask).*double(voronoi_region_mask);
flairint_values = zeros(numel(flairimage),numel(thresholds));
ventdist_values = zeros(1,numel(thresholds));
lesvol_values = zeros(1,numel(thresholds));
size(lesvol_values)
diceindex_values = zeros(1,numel(thresholds));
size(flairint_values)
% Applying thresholds and calculating features and dice indices for each thresholds
for thr = 1:numel(thresholds)
binary_lesion_mask = lesionmask_voronoi > thresholds(thr);
size(binary_lesion_mask)
size(flairimage)
for img_no = 1:numel(flairimage)
flair_image = flairimage{img_no};
flairint_values(img_no,thr) = mean(flair_image(binary_lesion_mask));
end
ventdist_values(thr) = mean(ventdistmap(binary_lesion_mask));
lesvol_values(thr) = sum(binary_lesion_mask(:));
intersect_img = binary_lesion_mask & manualmask_voronoi;
no_intersect = sum(intersect_img(:));
diceindex_values(thr) = 2*(no_intersect/(sum(manualmask_voronoi(:))+sum(binary_lesion_mask(:))));
if sum(manualmask_voronoi(:)) == 0 && sum(binary_lesion_mask(:))== 0
diceindex_values(thr) = 1;
end
end
flairint_values = flairint_values';
flairint_values = flairint_values(:)';
% Replacing NANs with -1
diceindex_values(isnan(diceindex_values)) = 0;
flairint_values(isnan(flairint_values)) = -1;
ventdist_values(isnan(ventdist_values)) = -1;
lesvol_values(isnan(lesvol_values)) = -1;
[maxdice] = max(diceindex_values);
maxdicepos = diceindex_values == max(diceindex_values);
dice_values(ind) = maxdice;
% Aggregating features and (mean, min and max) thresholds that give maximum dices
maxbestthr_values(ind) = max(thresholds(maxdicepos));
minbestthr_values(ind) = min(thresholds(maxdicepos));
meanbestthr_values(ind) = mean(thresholds(maxdicepos));
flairintfeats(ind,:) = flairint_values;
ventdistfeats(ind,:) = ventdist_values;
lesvolfeats(ind,:) = lesvol_values;
end
function [flairfeatmats_modified,ventdistfeatmats_modified,lesvolfeatmats_modified] = LOCATE_modify_voronoi_features(flairfeatmats,ventdistfeatmats,lesvolfeatmats)
flairfeatmats_modified = cell(1,size(flairfeatmats,1));
for nums = 1:size(flairfeatmats,1)
feats = flairfeatmats{nums};
feats_modified = [];
for length = 1:size(feats,1)
no_of_feats = size(feats,2)/20;
feature1 = zeros(1,size(feats,2));
for no_feats = 1:no_of_feats
feature11 = feats(length,20*(no_feats-1)+1:20*no_feats);
pos1 = find(feature11 == -1, 1, 'first');
if isempty(pos1)
feature1(20*(no_feats-1)+1:20*no_feats) = feature11;
continue;
elseif pos1 == 1
feature11 = zeros(1,size(feats,2));
else
value = feature11(pos1-1);
feature11(pos1:end) = value;
end
feature1(20*(no_feats-1)+1:20*no_feats) = feature11;
end
feats_modified = [feats_modified;feature1];
end
flairfeatmats_modified{nums} = feats_modified;
end
ventdistfeatmats_modified = cell(1,size(flairfeatmats,1));
for nums = 1:size(flairfeatmats,1)
feats = ventdistfeatmats{nums};
feats_modified = [];
for length = 1:size(feats,1)
feature1 = feats(length,1:size(feats,2));
pos1 = find(feature1 == -1, 1, 'first');
if isempty(pos1)
feats_modified = [feats_modified;feature1];
continue;
elseif pos1 == 1
feature1 = zeros(1,size(feats,2));
else
value = feature1(pos1-1);
feature1(pos1:end) = value;
end
feats_modified = [feats_modified;feature1];
end
ventdistfeatmats_modified{nums} = feats_modified;
end
lesvolfeatmats_modified = cell(1,size(flairfeatmats,1));
for num