diff --git a/code/InSegtFibre_2D.m b/code/InSegtFibre_2D.m
new file mode 100755
index 0000000000000000000000000000000000000000..bf5ee958f04809ae6f9060c1573004c6c7088ac5
--- /dev/null
+++ b/code/InSegtFibre_2D.m
@@ -0,0 +1,221 @@
+% InSegtFibre_2D
+% Written by Monica Jane Emerson, April 2018.
+% MIT license
+
+%% Step 0: Add paths of GUI and other functions and scripts used in Insegt Fibre
+close all,
+clear all,
+addpath(genpath('./texture_gui'))
+addpath('./scripts')
+addpath('./functions')
+
+disp('Step 0 completed')
+
+%% Step 1: Load and visualise the four 2D images
+%the path of the 2Ddata folder in your computer
+str_datafolder = '../data/2Ddata/'; %default value
+
+%Visualise all four datasets
+contents_datafolder = dir(str_datafolder);
+num_datasets = length(contents_datafolder)-2; 
+
+figure
+ for k= 1:num_datasets
+    %read image
+    im = imread([str_datafolder,contents_datafolder(k+2).name]); 
+    %create subtitle for image
+    subtitle = [num2str(k),'. ',contents_datafolder(k+2).name(1:end-4)];
+    ind = find(subtitle=='_');
+    subtitle(ind) = ' ';
+    %plot image
+    subplot(2,2,k), imagesc(im), axis image, colormap gray, title(subtitle)
+ end
+ 
+h = msgbox('Inspect the quality of the four different scans');
+waitfor(h)
+
+disp('Step 1 completed')
+
+%% Step 2: Select data-set and region of interest (RoI)
+close all
+%USER INPUT: select dataset
+x = inputdlg('Choose a data-set (1, 2, 3 or 4?): ','User input',[1,20],{num2str(4)});
+
+%read the 2D image chosen by the user 
+dataset = str2double(x{1}); 
+im = imread([str_datafolder,contents_datafolder(dataset+2).name]);
+
+%print the name of the selected data-set
+disp(['Selected data-set: ', contents_datafolder(dataset+2).name(1:end-4)]);
+
+%USER INPUT: select RoI
+h = msgbox('Crop a region of interest containing 100-1000 fibres.'); 
+waitfor(h)
+im_crop = imcrop(im);
+
+%visualise the selected RoI
+if isempty(im_crop)
+   h = msgbox('There was an error in the cropping. Run the section again.'); 
+   waitfor(h)
+else
+    figure, imagesc(im_crop), axis image, colormap gray, 
+    title('Region of Interest for training the dictionary')
+end
+
+disp('Step 2 completed')
+
+%% Step 3: Set default parameters and the patch size at the scale of the fibres
+close all
+%USER INPUT: Parameters that give the scale of the fibres in pixels
+prompt_px = ['Pixel size [', char(181),'m]: '];
+prompt_diam = ['Diameter size [', char(181),'m]: '];
+x = str2double(inputdlg({prompt_px, prompt_diam},'User input',[1,30],{num2str(0.96),num2str(7)}));
+
+%compute patch size as the closest odd integer to the fibre diameter
+%measured in pixels diam/pixel_size
+patch_size = calcu_psize(x(2)/x(1));
+
+%check that the patch size is in the optimal range to ensure precision and
+%speed
+if ((x(2)/x(1)) < 7)
+    factor = 9/(x(2)/x(1));
+    patch_size = calcu_psize(factor*x(2)/x(1));
+    msg = ['We will upscale your images with a factor ',...
+        num2str(factor,'%0.2f'),' to obtain better precision. The patch size is now ',...
+        num2str(patch_size),'.'];
+    h = msgbox(msg);
+    waitfor(h)
+elseif ((x(2)/x(1)) >= 17)
+     factor = 11/(x(2)/x(1));
+    patch_size = calcu_psize(factor*x(2)/x(1));
+    msg = ['We will downscale your images with a factor ',...
+        num2str(factor),' to obtain reduce the computational time. The patch size is now ',...
+        num2str(patch_size),'.'];
+    h = msgbox(msg);
+    waitfor(h)
+else
+    factor = 1;
+end
+
+%set patch size
+dictopt.patch_size = patch_size; 
+%set the default ditionary parameters
+dictopt.method = 'euclidean';
+dictopt.branching_factor = 3; %it should at least be 3
+dictopt.number_layers = 5; %at least 5. The higher the more accurate, but also slower and more computationally heavy
+num_dict_elts = calc_eltsdict(dictopt.branching_factor,dictopt.number_layers);
+dictopt.number_training_patches = 5000; %at least an order of magnitude more than the number of dictionary elements
+dictopt.normalization = false; %set to true if the global intensity of the slices varies along the depth of the volume
+
+disp('Step 3 completed')
+
+%% Step 4: Run InSegt
+%display the important dictionary parameters
+fprintf('\nImportant Dictionary Parameters:\n');
+disp(['patch size: ', num2str(dictopt.patch_size)]);
+disp(['number dictionary elements: ', num2str(calc_eltsdict(dictopt.branching_factor,dictopt.number_layers))]);
+
+%resize cropped region of interest with factor
+im_train = imresize(im_crop, factor);
+%open the GUI with 2 labels for pixel annotation (fibre centre region or not)
+image_texture_gui(im_train,dictopt,2)
+
+disp('Step 4 completed')
+
+%% Step 5: Obtain the centre coordinates from the hard segmentation
+close all
+%USER INPUT: label used for the centre regions
+label = 2; %1 (blue) or 2 (pink)
+
+%calculate the centroids of the connected centre regions
+c = regionprops(gui_S==label,'centroid');
+centrePoints = cat(1,c.Centroid);
+
+%show fibre centre coordinates over slice
+figure(1), subplot(1,2,1), imagesc(im_crop), axis image, colormap gray, 
+hold on, h = imagesc(ind2rgb(imresize(gui_S==label,1/factor), cool(2))); set(h, 'AlphaData',0.5);
+
+figure(1), subplot(1,2,2), imagesc(im_crop), axis image, colormap gray
+hold on, plot(centrePoints(:,1)*1/factor,centrePoints(:,2)*1/factor,'r*');
+
+disp('Step 5 completed')
+
+%% Step 6: Save the dictionary to process other regions of the scan
+close all
+%train the dictionary with the small RoI
+dictionary = build_dictionary(im_train,dictopt); %create the dictionary of intensities
+image_texture_gui(im_train,dictionary,2) %learn the dictionary of probabilities by annotating in the GUI 
+dictionary = update_dictionary(dictionary,gui_dictprob); %update dictionary to include the learnt probalilities
+
+%USER INPUT: select a RoI to process with the learnt dictionary
+h = msgbox('Crop a region of interest, it can be as big as you like.'); 
+waitfor(h)
+im_p = imcrop(im);
+if isempty(im_crop)
+   h = msgbox('There was an error in the cropping. Run the section again from the cropping.'); 
+   waitfor(h)
+else
+    figure, imagesc(im_p), axis image, colormap gray, 
+    title('Region of Interest for finding fibre centres')
+end
+
+%apply the dictionary to process the larger RoI
+im_process = imresize(im_p,factor);
+[S,allP] = process_image(im_process,dictionary);
+    
+%calculate the centroids of the connected centre regions
+label = 2; %1 (blue) or 2 (pink)
+c = regionprops(S==label,'centroid');
+centrePoints = cat(1,c.Centroid);
+
+%Centre regions and coordinates over the image to evaluate the accuracy of the segmentation
+figure, imagesc(im_process), axis image, colormap gray, 
+hold on, h = imagesc(ind2rgb(S, cool(2))); set(h, 'AlphaData',0.5);
+hold on, plot(centrePoints(:,1),centrePoints(:,2),'y.');
+title('Segmented centre regions and fibre detections over the processed image');
+    
+if factor ~=1
+    figure, imagesc(im_p), axis image, colormap gray, 
+    hold on, plot(centrePoints(:,1)*1/factor,centrePoints(:,2)*1/factor,'y.');
+    title('Centre detections over the original resolution')
+end
+    
+disp('Step 6 completed')
+
+%% Step 7: Tune the threshold applied to the probability map
+close all
+%visualise the propabilistic segmentation of fibre centre regions
+figure(1), imagesc(allP(:,:,2)), axis image off, colormap gray, title('Centre class probability map'), colorbar
+
+y = 'yes';
+while strcmp(y,'yes') 
+    %USER INPUT: threshold value for the probability map 
+    x = inputdlg('Choose threshold: ','User input',[1,20],{num2str(0.5)});
+
+    %Centre regions over the image to evaluate the accuracy of the segmentation
+    figure, imagesc(im_process), axis image, colormap gray, 
+    hold on, h = imagesc(ind2rgb(allP(:,:,2)>str2double(x{1}), cool(2))); set(h, 'AlphaData',0.5);
+    
+    %USER INPUT: do you want to try another threshold?? 
+    y = questdlg('Do you want to try another thresold?: ','User input','yes','no','yes');
+end
+
+disp('Step 7 completed')
+
+%% Step 8: Save your manual input to add additional markings later on
+close all
+%annotate a little in the GUI and save your manual input
+h = msgbox(['Annotate a little in the GUI and press [S] before closing the GUI (then close by pressing export [E]). Choose to save',...
+    ' your annotations in the folder "InsegtFibre_workshopDTU/data/saved_data/trainingData".']); 
+waitfor(h)
+image_texture_gui(im_train,dictopt,2)  
+%save the training region, over which you placed the markings
+save('../data/saved_data/trainingData/training_image.mat','im_train');
+
+%Call the GUI with a saved labelling
+load('../data/saved_data/trainingData/training_image.mat');
+[filename,pathname] = uigetfile('*_labels_indexed.png', 'Choose label image', '../data/saved_data/trainingData/');  
+labelling = imread([pathname,filename]); %read labelling
+image_texture_gui(im_train,dictopt,2,labelling) %call the GUI with the saved labelling
+
+disp('Step 8 completed')
diff --git a/code/InsegtFibre_3D.m b/code/InsegtFibre_3D.m
new file mode 100755
index 0000000000000000000000000000000000000000..33dc83721940e987d868bbceb14785f6dc4ebf7a
--- /dev/null
+++ b/code/InsegtFibre_3D.m
@@ -0,0 +1,254 @@
+% InSegtFibre_3D
+% Written by Monica Jane Emerson, May 2018.
+% MIT license
+
+%% Step 0: Add paths of Insegt GUI, other functions and scripts, and prepare workspace
+close all,
+clear all,
+addpath(genpath('./texture_gui'))
+addpath('./scripts')
+addpath('./functions')
+
+disp('Step 0 completed')
+
+%% Step 1: Locate folder with the CT data
+close all
+indicate_dataFolder
+
+disp('Step 1 completed')
+
+%% Step 2: Load and visualise the data
+close all
+[V,depth] = loadVolumeRoI(path_volumeFolder);
+figure, imshow3D(V) %visualise the loaded RoI
+
+disp('Step 2 completed')
+
+%% Step 3: Compute a dictionary model from the CT scan 
+close all
+setup_dict %set the parameters of the dictionary model
+create_dict %learn the dictionary model from training data
+
+disp('Step 3 completed')
+
+%% Step 4: Obtain the centre-class probabilistic segmentation for a slice
+close all
+% USER INPUT: Load a saved dictionary
+[filename,pathname] = uigetfile('*.mat','Choose dictionary','../data/saved_data/dictionaries/dictionary');
+load([pathname,filename]);
+
+% USER INPUT: Choose slice
+prompt = ['Choose a slice to segment: [1,', num2str(size(V,3)),']:'];
+x = inputdlg(prompt,'User input',[1,30],{num2str(round(size(V,3)/4))}); 
+sliceAnalys = str2double(x{1});
+h = msgbox('Segmenting image...');
+[~,allP] = process_image(V(:,:,sliceAnalys),dictionary);
+delete(h)
+Pcentre = allP(:,:,2);
+
+%Visualise for each pixel its probabily of belonging to a fibre centre region
+h = figure(1), %h.Units = 'normalized'; h.Position = [0 0 1 1]; 
+subplot(1,2,1), imagesc(Pcentre), axis image, colormap gray,  colorbar, 
+title('Probability of belonging to the central region of a fibre') 
+figure(1), subplot(1,3,3), histogram(Pcentre(:)), 
+ylabel('Count of probabilities'), xlabel('Range of probabilities') 
+
+disp('Step 4 completed')
+
+%% Step 5: Obtain the fibre centres by thresholding the probabilistic segmentation
+% USER INPUT: threshold value for the probability map 
+thresh = inputdlg('Choose threshold: ','User input',[1,20],{num2str(0.50)});
+
+%Threshold probability map
+areas_th = Pcentre > str2double(thresh{1}); 
+
+%Calculate centroids
+concomp = logical(areas_th);
+c = regionprops(concomp,'centroid');
+centrePoints_2D = cat(1,c.Centroid);
+    
+%Visualisations to evaluate the chosen threshold
+figure(2), subplot(1,2,1), imagesc(V(:,:,sliceAnalys)), axis image, colormap gray, 
+hold on, h = imagesc(ind2rgb(areas_th, cool(2))), set(h, 'AlphaData',0.5);
+figure(2), subplot(1,2,2), imagesc(V(:,:,sliceAnalys)), axis image, colormap gray
+hold on, plot(centrePoints_2D(:,1),centrePoints_2D(:,2),'r*');
+
+disp('Step 5 completed')
+
+%% Step 6: Detect fibre centres in the batch of slices forming the volume
+close all
+clear centrePoints, clear allP, clear c
+% USER INPUT: Load a saved dictionary
+[filename,pathname] = uigetfile('*.mat','Choose dictionary','../data/saved_data/dictionaries/dictionary_');
+load([pathname,filename]);
+
+% USER INPUT: threshold value for the probability map 
+thresh = inputdlg('Choose threshold: ','User input',[1,20],{num2str(0.5)});
+ 
+%Initialise variables
+step = 1; 
+slices = 1:step:size(V,3);
+
+%Start timer
+tstart = tic; 
+h = waitbar(0,'Processing volume...');
+
+for l = 1:numel(slices)
+    %Compute the probabilistic segmentation
+    [~,allP] = process_image(V(:,:,slices(l)),dictionary);
+    %Save probability map
+    P(:,:,l) = allP(:,:,2);
+    %Compute the connected components of the thresholded probabilities
+    c = regionprops(bwlabel(allP(:,:,2) > str2num(thresh{1})),'centroid');
+    %Store the coordinates of the centre points
+    centrePoints{l} = cat(1,c.Centroid);
+    %Update the data processing wait bar
+    waitbar(l/numel(slices),h)
+end
+
+%disp processing time
+t_load = toc(tstart);
+f = msgbox(['time to process volume: ' , num2str(t_load), 's']);
+close(h)
+waitfor(f)
+
+%Compute the number of detected fibres per slice
+clear len
+close all
+for l = 1:length(centrePoints)
+    len(l) = size(centrePoints{l},1);
+end
+aux = str2double(depth);
+figure(1), plot([aux(1):aux(3):aux(2)],len,'.'), axis tight, title('Nr. fibres per slice'), 
+xlabel('slice number (1 is the top of the sample)')
+ylabel('number of detected fibres')
+
+%Visualise the detections in 3D
+if ~exist('vx_size')
+    vx_size = str2double(inputdlg(['Pixel size [', char(181),'m]: '],'User input',[1,30],{num2str(1.1)}));
+end
+
+for l = 1:step:length(centrePoints)
+    figure(2), hold on, plot3(centrePoints{l}(:,1)*vx_size,centrePoints{l}(:,2)*vx_size,l*ones(size(centrePoints{l}(:,1)))*vx_size,'r.','MarkerSize',1)
+end
+h = figure(2), axis tight, view(3), axis equal
+xlabel('x axis [\mum]'),ylabel('y axis [\mum]'), zlabel('z axis [\mum]')
+aux = cellstr(num2str(vx_size*linspace(str2double(depth{1}),str2double(depth{2}),length(h.Children.ZTickLabel)+1)','%.f'));
+h.Children.ZTickLabel = aux(2:end);
+
+% USER INPUT: Save 3D detections
+uisave('centrePoints','../data/saved_data/centreCoordinates/centreCoords_?.mat')
+
+disp('Step 6 completed')
+
+%% Step 7: Compute the 3D fibre trajectories via tracking
+% USER INPUT: Load the saved 3D detections
+[filename,pathname] = uigetfile('*.mat','Choose the set of 3D coordinates to track','../data/saved_data/centreCoordinates');
+load([pathname,filename]);
+
+% USER INPUT: How many pixels is a fibre allowed to move from one slice to the
+% next? (function of the step, the diameter and the pixel size).
+x = inputdlg('How many pixels is a fibre allowed to move from one slice to the next? (a function of the step, the diameter and the pixel size): ','User input',[1,65],{num2str(5)}); 
+dist = str2num(x{1});
+
+% USER INPUT: Should the tracking start with the detections of the bottom 
+% or the top slice?
+if ~exist('depth')
+    depth = input_depthRoI(num_slices);
+end
+top = 'Top of the volume (slice 1)';
+bottom = ['Bottom of the volume (slice ', depth{2},')'];
+direct = questdlg('Where shall we start the fibres?','Tracking direction',top, bottom,bottom);
+
+if strcmp(direct,bottom)
+    m = length(centrePoints);
+else 
+    m = 1;
+end
+
+%Initialise variables
+thisCt = centrePoints{m}; %we start tracking from the bottom of the volume (end slice)
+f_x = nan(size(thisCt,1),length(centrePoints));
+f_y = nan(size(thisCt,1),length(centrePoints));
+f_x(:,1) = centrePoints{m}(:,1);
+f_y(:,1) = centrePoints{m}(:,2);
+
+%Starting time
+tstart = tic;
+
+%Track the coordinates in the z direction
+for l = 2:length(centrePoints)
+    % coordinates of next slice
+    if strcmp(direct,bottom)
+        ctNext = centrePoints{end-l+1};
+    else
+        ctNext = centrePoints{l};
+    end
+    
+    % build kd-tree
+    tree_down = KDTreeSearcher(ctNext);
+    % search the kd-tree
+    [id_down, d_down] = knnsearch(tree_down,thisCt,'K',1);
+    % build kd-tree
+    tree_up = KDTreeSearcher(thisCt);
+    % search the kd-tree
+    [id_up, d_up] = knnsearch(tree_up,ctNext,'K',1);
+    
+    % keep matches that are bidirectional
+    id_top = unique(id_up(id_down));
+    id_bottom = id_down(unique(id_up(id_down)));
+    
+    % keep matches that are closer than a distance
+    idMatch = find(d_down(id_top) < dist);
+    id_top_th = id_top(idMatch);
+    id_bottom_th = id_bottom(idMatch);
+    
+    if strcmp(direct,bottom)
+        f_x(id_top_th,l) = centrePoints{end-l+1}(id_bottom_th,1);
+        f_y(id_top_th,l) = centrePoints{end-l+1}(id_bottom_th,2);
+    else
+        f_x(id_top_th,l) = centrePoints{l}(id_bottom_th,1);
+        f_y(id_top_th,l) = centrePoints{l}(id_bottom_th,2);
+    end
+    
+    %points to be matched with the next slice
+    thisCt(id_top_th,:) = ctNext(id_bottom_th,:);
+end
+t_load = toc(tstart);
+disp(['time to track coordinates along the volume: ' , num2str(t_load), 's']);
+
+%Save track coordinates in the structure 'fibres'
+fibres.x = f_x;
+fibres.y = f_y;
+
+%Visualise fibre tracks
+% USER INPUT: How many fibres would you like to visualise (in percentage)?
+questions = {'What percentage of the tracked fibres would you like to visualise (%)?: '};
+x = inputdlg(questions,'User input',[1,40],{num2str(10)}); %ask for patch size
+
+perc = str2double(x{1})/100;
+fib_ind = randperm(size(fibres.x,1),round(perc*size(fibres.x,1))); %indices of fibre to plot
+z = [1:size(fibres.x,2)]; %z-values
+
+if ~exist('vx_size')
+    vx_size = str2double(inputdlg(['Pixel size [', char(181),'m]: '],'User input',[1,30],{num2str(1.1)}));
+end
+figure(3),clf
+for l= 1:numel(fib_ind)
+	h = figure(3);
+    hold on, plot3(fibres.x(fib_ind(l),:)*vx_size,fibres.y(fib_ind(l),:)*vx_size,z*vx_size,'LineWidth',1), 
+end
+axis tight, axis equal, view(3), 
+xlabel('x axis [\mum]'),ylabel('y axis [\mum]'), zlabel('z axis [\mum]')
+aux = cellstr(num2str(vx_size*linspace(str2double(depth{1}),str2double(depth{2}),length(h.Children.ZTickLabel)+1)','%.f'));
+h.Children.ZTickLabel = aux(2:end);
+
+% USER INPUT: Save fibre tracks
+if strcmp(direct,bottom)
+    direction = [depth{2},'to',depth{1}];
+else
+    direction = [depth{1},'to',depth{2}];
+end
+uisave('fibres',['../data/saved_data/fibreTracks/fibreTracks_dataSetX_',direction,'step',depth{3},'.mat'])
+
+    
\ No newline at end of file
diff --git a/code/InsegtFibre_orientations.m b/code/InsegtFibre_orientations.m
new file mode 100755
index 0000000000000000000000000000000000000000..86cbcc38e3bff275064376c3bd25ff779e37d166
--- /dev/null
+++ b/code/InsegtFibre_orientations.m
@@ -0,0 +1,138 @@
+% InSegtFibre_orientations
+% Written by Monica Jane Emerson, May 2019.
+% MIT license
+
+%% Prepare workspace
+close all
+clear all
+addpath('./scripts')
+addpath('./functions')
+
+%% Read tracks, z-values (analysed slices) and voxel size 
+[filename_tracks,pathname_tracks] = uigetfile('*.mat','Choose tracks','../data/saved_data/fibreTracks');
+fibres = getfield(load([pathname_tracks,filename_tracks]),'fibres');
+
+depth = input_depthRoI; %get z coordinates (start, end and step)
+z_axis = [str2double(depth{1}):str2double(depth{3}):str2double(depth{2})];
+
+vx_size = str2double(inputdlg(['What is the pixel size of your scan [', char(181),'m]: '],'Pixel/voxel size',[1,45],{num2str(1.1)}));
+
+%% Display tracks
+h1 = figure(1);
+for l= 1:size(fibres.x,1)
+    figure(1), hold on, 
+    plot3(fibres.x(l,:)*vx_size,fibres.y(l,:)*vx_size,z_axis*vx_size,'k','LineWidth',1), 
+end
+figure(1), axis tight, axis equal, view(2), view(3) 
+xlabel('x axis [\mum]'),ylabel('y axis [\mum]'), zlabel('z axis [\mum]')
+
+%% Display locations of missed detections
+missed_det = isnan(fibres.x');
+figure(2), imagesc(missed_det), axis image, axis xy
+title('Missed fibre centres')
+ylabel('z axis [slices]'),xlabel('fibre ID'),
+
+%% Select fibres for the orientation plot
+%Indices of fibres that miss start and/or end detection
+%(will be excluded from the orientation plot)
+exc_fibres = find((missed_det(1,:)|missed_det(end,:))==1);
+
+%Indices of the fibre kept for the orientation plot
+keep_fibres = 1:size(fibres.x,1);
+keep_fibres(exc_fibres) = []; 
+
+display(['The orientation can been computed for ',num2str(length(keep_fibres)/size(fibres.x,1)*100,'%.2f') ,'% of the tracked fibres']);
+
+%% Compute orientation (inclination and it's direction, azimuth)
+%displacement between end and start points
+disp_x = fibres.x(keep_fibres,end)-fibres.x(keep_fibres,1);
+disp_y = fibres.y(keep_fibres,end)-fibres.y(keep_fibres,1);
+disp_r = sqrt(disp_x.^2 + disp_y.^2);
+
+%inclination and azimuth angles
+inclination = atan2(disp_r,(size(fibres.x,2)-1)*ones(length(keep_fibres),1));
+azimuth = atan2(disp_y,disp_x);
+
+display('The orientations (inclination and azimuth angles) have been computed');
+
+%% Histograms of orientation angles
+close all
+%Inclination
+max_inc = str2double(inputdlg('What is the maximum misalignment angle you expect [0°, 90°]?','Max. Inclination',[1,35],{num2str(15)}));
+bins_inc = [0:max_inc];
+int_inc = [0:0.1:max_inc];
+
+h_inc = hist(inclination*180/pi,bins_inc)/length(inclination);
+h_inc_int = interp1(bins_inc,h_inc,int_inc);
+h1 = figure(1),hold on, plot(int_inc,smooth(h_inc_int))
+ylim([0,max(smooth(h_inc_int))]), xlim([0,max_inc]),h1.Children.XTick = linspace(0,max_inc,10);
+xlabel('Inclination \phi [\circ] of the fibres'), ylabel('Relative frequency')
+title('Amount of fibre misalignment with respect to the scanning z-axis'),
+
+%Azimuth
+max_az = 360;
+bins_az = [-max_az/2:24:max_az/2];
+int_az = [-max_az/2:2.4:max_az/2];
+
+h_az = hist(azimuth*180/pi,bins_az)/length(azimuth);
+h_az_int = interp1(bins_az,h_az,int_az);
+h2 = figure(2),hold on, plot(int_az,smooth(h_az_int))
+xlim([-max_az/2,max_az/2]), h2.Children.XTick = [-180,-90,0,90,180];
+ylim([0,max(smooth(h_az_int))])
+xlabel('Azimuth \theta [\circ] of the fibres'), ylabel('Relative frequency')
+title('Direction of misalignment with respect to scanning x-axis'),
+
+%% Colour-code fibre tracks according to orientation angles
+%Azimuth (direction of misalingment)
+cmap_az = circshift(colormap(hsv),32);
+h3 = figure(3);
+for l= 1:length(keep_fibres)
+    colouring = cmap_az(round(azimuth(l)/(2*pi)*63+1+63/2),:);
+    figure(3), hold on, plot3(fibres.x(keep_fibres(l),:)*vx_size,fibres.y(keep_fibres(l),:)*vx_size,z_axis*vx_size,'LineWidth',1,'Color',colouring), 
+end
+figure(3), axis tight, axis equal, view(2), 
+xlabel('x axis [\mum]'),ylabel('y axis [\mum]'), zlabel('z axis [\mum]')
+colormap(cmap_az), colorbar, caxis([-180,180]), h3.Children(1).Ticks = -180:30:180;
+for k = 1:length(h3.Children(1).Ticks)
+    h3.Children(1).TickLabels(k) = {[h3.Children(1).TickLabels{k},'°']};
+end
+
+%Inclination (amount of misalignment)
+cmap_inc = linspace(0,1,32)'*[1,1,1];
+sat_angle = max_inc/3;
+sat = sat_angle*pi/180;
+h4 = figure(4);
+for l= 1:length(keep_fibres)
+    if inclination(l) < sat
+            colouring = [1,1,1]*inclination(l)/sat;
+        else
+            colouring = [1,1,1];
+        end
+    figure(4), hold on, plot3(fibres.x(keep_fibres(l),:)*vx_size,fibres.y(keep_fibres(l),:)*vx_size,z_axis*vx_size,'LineWidth',1,'Color',colouring), 
+end
+figure(4), axis tight, axis equal, view(2), 
+xlabel('x axis [\mum]'),ylabel('y axis [\mum]'), zlabel('z axis [\mum]')
+colormap(cmap_inc), 
+colorbar, caxis([0,sat_angle]), h.Children(1).Ticks = linspace(0,sat_angle,5); 
+h4.Children(1).TickLabels(end) = {['>',num2str(sat_angle)]};
+for k = 1:length(h.Children(1).Ticks)
+    h4.Children(1).TickLabels(k) = {[h4.Children(1).TickLabels{k},'°']};
+end
+
+%Azimuth weighed by inclination (amount of misalignment)
+h5 = figure(5);
+for l= 1:length(keep_fibres)
+    if inclination(l) < sat
+            colouring = cmap_az(round(azimuth(l)/(2*pi)*63+1+63/2),:)*inclination(l)/sat;
+        else
+            colouring = cmap_az(round(azimuth(l)/(2*pi)*63+1+63/2),:);
+        end
+    figure(5), hold on, plot3(fibres.x(keep_fibres(l),:)*vx_size,fibres.y(keep_fibres(l),:)*vx_size,z_axis*vx_size,'LineWidth',1,'Color',colouring), 
+end
+figure(5), axis tight, axis equal, view(2), 
+xlabel('x axis [\mum]'),ylabel('y axis [\mum]'), zlabel('z axis [\mum]')
+colormap(cmap_az), colorbar, caxis([-180,180]), h5.Children(1).Ticks = -180:30:180;
+for k = 1:length(h.Children(1).Ticks)
+    h5.Children(1).TickLabels(k) = {[h5.Children(1).TickLabels{k},'°']};
+end
+
diff --git a/code/InsegtFibre_validate3DTracks.m b/code/InsegtFibre_validate3DTracks.m
new file mode 100755
index 0000000000000000000000000000000000000000..29ae8d1a6fc20c3296fe748d3a632463903c58b0
--- /dev/null
+++ b/code/InsegtFibre_validate3DTracks.m
@@ -0,0 +1,68 @@
+% VALIDATION_3DFIBREDETECTION
+% Written by Monica Jane Emerson, April 2019.
+% MIT license
+
+%% Add paths of Insegt, functions and scripts, and prepare workspace
+close all, clear all,
+addpath('./scripts')
+addpath('./functions')
+
+%% Get the measured fibre tracks in the format required by the validation GUI
+% USER INPUT: Load the fibre tracks to validate
+[filename_tracks,pathname_tracks] = uigetfile('*.mat','Choose the fibre tracks to validate','saved_data/fibreTracks');
+load([pathname_tracks,filename_tracks]);
+
+%USER INPUT: Deregister the tracks if necessary
+x = questdlg('Have the tracks undergone a transformation (rotation and/or translation) since they were measured from the CT scan?','2D de-registration','Yes','No','No');
+if strcmp(x,'Yes')
+    [filename,pathname] = uigetfile('*.mat','Load the transformation matrix','saved_data/2Dregistration/');
+    t = load([pathname,filename],'tform');  
+    %USER INPUT: Offset between registration FoV and analysis FoV
+    offset = str2double(inputdlg('Offset between the FoV used for the analysis and the FoV used for the 2D registration','Offset registration-analysis',[1,50],{num2str(100)}));
+    aux = [fibres.x(:) + offset*ones(size(fibres.x(:))),fibres.y(:) + offset*ones(size(fibres.x(:))),ones(size(fibres.y(:)))]*t.tform.tdata.Tinv;
+    fibres.x = reshape(aux(:,1), size(fibres.x)) - offset*ones(size(fibres.x));
+    fibres.y = reshape(aux(:,2), size(fibres.x)) - offset*ones(size(fibres.x));
+end
+
+for l = 1:size(fibres.x,2) 
+    centers{l} = [fibres.x(:,l),fibres.y(:,l),[1:size(fibres.x,1)]']; 
+end;
+
+%% Get the analysed volume of interest (VoI) in the format read by the validaiton GUI
+close all
+% USER INPUT: Option to open a volume of interest saved as a tif file
+x = questdlg('Is the analysed volume of interest saved as one .tif file, with the slices ordered in the direction of tracking?','Load analysed volume','Yes','No','Yes');
+
+if strcmp(x,'No')
+    indicate_dataFolder;
+    [V,depth] = loadVolumeRoI(path_volumeFolder);
+    % USER INPUT: Tracking direction
+    top = ['Top to bottom (from slice ',depth{1},')'];
+    bottom = ['Bottom to top (from slice ',depth{2},')'];
+    direct = questdlg('In which direction did you track the coordinates?','Tracking direction',top, bottom, bottom);
+    % USER INPUT: Give a name to the .tif Volume of Interest
+    if strcmp(direct,bottom)
+        direction = [depth{2},'to',depth{1},'step',depth{3}];
+    else
+        direction = [depth{1},'to',depth{2},'step',depth{3}];
+    end
+    name_tif = inputdlg('Name for the .tif file of your volume of interest (VoI): ','Name your VOI',[1,55],{['V_?_',direction,'.tif']});
+    filename_voi= name_tif{1};
+    pathname_voi = 'saved_data/volumeOfInterest/';
+    if strcmp(direct,bottom) 
+        imwrite(V(:,:,end),[pathname_voi,filename_voi]);
+        for l= 2:size(V,3)
+            imwrite(V(:,:,end-l+1),[pathname_voi,filename_voi], 'WriteMode','append');
+        end 
+    else
+        imwrite(V(:,:,1),[pathname_voi,filename_voi]);
+        for l= 2:size(V,3)
+            imwrite(V(:,:,l),[pathname_voi,filename_voi], 'WriteMode','append');
+        end 
+    end
+else
+    [filename_voi,pathname_voi] = uigetfile('*.tif','Choose volume of interest','saved_data/volumeOfInterest/VOI_v');
+end
+
+%% Validate all fibres
+track_slicer([pathname_voi,filename_voi],centers)
diff --git a/code/functions/calc_eltsdict.m b/code/functions/calc_eltsdict.m
new file mode 100755
index 0000000000000000000000000000000000000000..6edad49199094c0b1ae84ce3bc2d86506867368d
--- /dev/null
+++ b/code/functions/calc_eltsdict.m
@@ -0,0 +1,8 @@
+function [num] = calc_eltsdict(k,n)
+%CALC_ELTSDICT Summary of this function goes here
+% Written by Monica Jane Emerson, April 2018, MIT License
+vect = [1:n];
+series = k.^(vect-1);
+num = k*sum(series);
+end
+
diff --git a/code/functions/calcu_psize.m b/code/functions/calcu_psize.m
new file mode 100755
index 0000000000000000000000000000000000000000..76ee312d02214630eb8e97e8273ffb72aa251b07
--- /dev/null
+++ b/code/functions/calcu_psize.m
@@ -0,0 +1,15 @@
+function [patch_size] = calcu_psize(pixPerDiam)
+%CALCU_PSIZE Loads a selected region of interest from a volume.
+%   Details...
+%by Monica Jane Emerson, April 2019, MIT License
+if mod(round(pixPerDiam),2)==0
+    if (round(pixPerDiam)-pixPerDiam)<0
+        patch_size = round(pixPerDiam)+1;
+    else
+        patch_size = round(pixPerDiam)-1;
+    end   
+else
+    patch_size = round(pixPerDiam);
+end
+end
+
diff --git a/code/functions/imshow3D.m b/code/functions/imshow3D.m
new file mode 100755
index 0000000000000000000000000000000000000000..15f49c4f93cf5a8c5857581b427ffff6297fa39d
--- /dev/null
+++ b/code/functions/imshow3D.m
@@ -0,0 +1,291 @@
+function  imshow3D( Img, disprange )
+%IMSHOW3D displays 3D grayscale images in slice by slice fashion with mouse
+%based slice browsing and window and level adjustment control.
+%
+% Usage:
+% imshow3D ( Image )
+% imshow3D ( Image , [] )
+% imshow3D ( Image , [LOW HIGH] )
+%   
+%    Image:      3D image MxNxK (K slices of MxN images) 
+%    [LOW HIGH]: display range that controls the display intensity range of
+%                a grayscale image (default: the widest available range)
+%
+% Use the scroll bar or mouse scroll wheel to switch between slices. To
+% adjust window and level values keep the mouse right button pressed and
+% drag the mouse up and down (for level adjustment) or right and left (for
+% window adjustment). 
+% 
+% "Auto W/L" button adjust the window and level automatically 
+%
+% While "Fine Tune" check box is checked the window/level adjustment gets
+% 16 times less sensitive to mouse movement, to make it easier to control
+% display intensity rang.
+%
+% Note: The sensitivity of mouse based window and level adjustment is set
+% based on the user defined display intensity range; the wider the range
+% the more sensitivity to mouse drag.
+% 
+% 
+%   Example
+%   --------
+%       % Display an image (MRI example)
+%       load mri 
+%       Image = squeeze(D); 
+%       figure, 
+%       imshow3D(Image) 
+%
+%       % Display the image, adjust the display range
+%       figure,
+%       imshow3D(Image,[20 100]);
+%
+%   See also IMSHOW.
+
+%
+% - Maysam Shahedi (mshahedi@gmail.com)
+% - Released: 1.0.0   Date: 2013/04/15
+% - Revision: 1.1.0   Date: 2013/04/19
+% 
+
+sno = size(Img,3);  % number of slices
+S = round(sno/2);
+
+global InitialCoord;
+
+MinV = 0;
+MaxV = max(Img(:));
+LevV = (double( MaxV) + double(MinV)) / 2;
+Win = double(MaxV) - double(MinV);
+WLAdjCoe = (Win + 1)/1024;
+FineTuneC = [1 1/16];    % Regular/Fine-tune mode coefficients
+
+if isa(Img,'uint8')
+    MaxV = uint8(Inf);
+    MinV = uint8(-Inf);
+    LevV = (double( MaxV) + double(MinV)) / 2;
+    Win = double(MaxV) - double(MinV);
+    WLAdjCoe = (Win + 1)/1024;
+elseif isa(Img,'uint16')
+    MaxV = uint16(Inf);
+    MinV = uint16(-Inf);
+    LevV = (double( MaxV) + double(MinV)) / 2;
+    Win = double(MaxV) - double(MinV);
+    WLAdjCoe = (Win + 1)/1024;
+elseif isa(Img,'uint32')
+    MaxV = uint32(Inf);
+    MinV = uint32(-Inf);
+    LevV = (double( MaxV) + double(MinV)) / 2;
+    Win = double(MaxV) - double(MinV);
+    WLAdjCoe = (Win + 1)/1024;
+elseif isa(Img,'uint64')
+    MaxV = uint64(Inf);
+    MinV = uint64(-Inf);
+    LevV = (double( MaxV) + double(MinV)) / 2;
+    Win = double(MaxV) - double(MinV);
+    WLAdjCoe = (Win + 1)/1024;
+elseif isa(Img,'int8')
+    MaxV = int8(Inf);
+    MinV = int8(-Inf);
+    LevV = (double( MaxV) + double(MinV)) / 2;
+    Win = double(MaxV) - double(MinV);
+    WLAdjCoe = (Win + 1)/1024;
+elseif isa(Img,'int16')
+    MaxV = int16(Inf);
+    MinV = int16(-Inf);
+    LevV = (double( MaxV) + double(MinV)) / 2;
+    Win = double(MaxV) - double(MinV);
+    WLAdjCoe = (Win + 1)/1024;
+elseif isa(Img,'int32')
+    MaxV = int32(Inf);
+    MinV = int32(-Inf);
+    LevV = (double( MaxV) + double(MinV)) / 2;
+    Win = double(MaxV) - double(MinV);
+    WLAdjCoe = (Win + 1)/1024;
+elseif isa(Img,'int64')
+    MaxV = int64(Inf);
+    MinV = int64(-Inf);
+    LevV = (double( MaxV) + double(MinV)) / 2;
+    Win = double(MaxV) - double(MinV);
+    WLAdjCoe = (Win + 1)/1024;
+elseif isa(Img,'logical')
+    MaxV = 0;
+    MinV = 1;
+    LevV =0.5;
+    Win = 1;
+    WLAdjCoe = 0.1;
+end    
+
+SFntSz = 9;
+LFntSz = 10;
+WFntSz = 10;
+LVFntSz = 9;
+WVFntSz = 9;
+BtnSz = 10;
+ChBxSz = 10;
+
+if (nargin < 2)
+    [Rmin Rmax] = WL2R(Win, LevV);
+elseif numel(disprange) == 0
+    [Rmin Rmax] = WL2R(Win, LevV);
+else
+    LevV = (double(disprange(2)) + double(disprange(1))) / 2;
+    Win = double(disprange(2)) - double(disprange(1));
+    WLAdjCoe = (Win + 1)/1024;
+    [Rmin Rmax] = WL2R(Win, LevV);
+end
+
+axes('position',[0,0.2,1,0.8]), imshow(Img(:,:,S), [Rmin Rmax])
+
+FigPos = get(gcf,'Position');
+S_Pos = [50 45 uint16(FigPos(3)-100)+1 20];
+Stxt_Pos = [50 65 uint16(FigPos(3)-100)+1 15];
+Wtxt_Pos = [50 20 60 20];
+Wval_Pos = [110 20 60 20];
+Ltxt_Pos = [175 20 45 20];
+Lval_Pos = [220 20 60 20];
+BtnStPnt = uint16(FigPos(3)-250)+1;
+if BtnStPnt < 300
+    BtnStPnt = 300;
+end
+Btn_Pos = [BtnStPnt 20 100 20];
+ChBx_Pos = [BtnStPnt+110 20 100 20];
+
+if sno > 1
+    shand = uicontrol('Style', 'slider','Min',1,'Max',sno,'Value',S,'SliderStep',[1/(sno-1) 10/(sno-1)],'Position', S_Pos,'Callback', {@SliceSlider, Img});
+    stxthand = uicontrol('Style', 'text','Position', Stxt_Pos,'String',sprintf('Slice# %d / %d',S, sno), 'BackgroundColor', [0.8 0.8 0.8], 'FontSize', SFntSz);
+else
+    stxthand = uicontrol('Style', 'text','Position', Stxt_Pos,'String','2D image', 'BackgroundColor', [0.8 0.8 0.8], 'FontSize', SFntSz);
+end    
+ltxthand = uicontrol('Style', 'text','Position', Ltxt_Pos,'String','Level: ', 'BackgroundColor', [0.8 0.8 0.8], 'FontSize', LFntSz);
+wtxthand = uicontrol('Style', 'text','Position', Wtxt_Pos,'String','Window: ', 'BackgroundColor', [0.8 0.8 0.8], 'FontSize', WFntSz);
+lvalhand = uicontrol('Style', 'edit','Position', Lval_Pos,'String',sprintf('%6.0f',LevV), 'BackgroundColor', [1 1 1], 'FontSize', LVFntSz,'Callback', @WinLevChanged);
+wvalhand = uicontrol('Style', 'edit','Position', Wval_Pos,'String',sprintf('%6.0f',Win), 'BackgroundColor', [1 1 1], 'FontSize', WVFntSz,'Callback', @WinLevChanged);
+Btnhand = uicontrol('Style', 'pushbutton','Position', Btn_Pos,'String','Auto W/L', 'FontSize', BtnSz, 'Callback' , @AutoAdjust);
+ChBxhand = uicontrol('Style', 'checkbox','Position', ChBx_Pos,'String','Fine Tune', 'BackgroundColor', [0.8 0.8 0.8], 'FontSize', ChBxSz);
+
+set (gcf, 'WindowScrollWheelFcn', @mouseScroll);
+set (gcf, 'ButtonDownFcn', @mouseClick);
+set(get(gca,'Children'),'ButtonDownFcn', @mouseClick);
+set(gcf,'WindowButtonUpFcn', @mouseRelease)
+set(gcf,'ResizeFcn', @figureResized)
+
+
+% -=< Figure resize callback function >=-
+    function figureResized(object, eventdata)
+        FigPos = get(gcf,'Position');
+        S_Pos = [50 45 uint16(FigPos(3)-100)+1 20];
+        Stxt_Pos = [50 65 uint16(FigPos(3)-100)+1 15];
+        BtnStPnt = uint16(FigPos(3)-250)+1;
+        if BtnStPnt < 300
+            BtnStPnt = 300;
+        end
+        Btn_Pos = [BtnStPnt 20 100 20];
+        ChBx_Pos = [BtnStPnt+110 20 100 20];
+        if sno > 1
+            set(shand,'Position', S_Pos);
+        end
+        set(stxthand,'Position', Stxt_Pos);
+        set(ltxthand,'Position', Ltxt_Pos);
+        set(wtxthand,'Position', Wtxt_Pos);
+        set(lvalhand,'Position', Lval_Pos);
+        set(wvalhand,'Position', Wval_Pos);
+        set(Btnhand,'Position', Btn_Pos);
+        set(ChBxhand,'Position', ChBx_Pos);
+    end
+
+% -=< Slice slider callback function >=-
+    function SliceSlider (hObj,event, Img)
+        S = round(get(hObj,'Value'));
+        set(get(gca,'children'),'cdata',Img(:,:,S))
+        caxis([Rmin Rmax])
+        if sno > 1
+            set(stxthand, 'String', sprintf('Slice# %d / %d',S, sno));
+        else
+            set(stxthand, 'String', '2D image');
+        end
+    end
+
+% -=< Mouse scroll wheel callback function >=-
+    function mouseScroll (object, eventdata)
+        UPDN = eventdata.VerticalScrollCount;
+        S = S - UPDN;
+        if (S < 1)
+            S = 1;
+        elseif (S > sno)
+            S = sno;
+        end
+        if sno > 1
+            set(shand,'Value',S);
+            set(stxthand, 'String', sprintf('Slice# %d / %d',S, sno));
+        else
+            set(stxthand, 'String', '2D image');
+        end
+        set(get(gca,'children'),'cdata',Img(:,:,S))
+    end
+
+% -=< Mouse button released callback function >=-
+    function mouseRelease (object,eventdata)
+        set(gcf, 'WindowButtonMotionFcn', '')
+    end
+
+% -=< Mouse click callback function >=-
+    function mouseClick (object, eventdata)
+        MouseStat = get(gcbf, 'SelectionType');
+        if (MouseStat(1) == 'a')        %   RIGHT CLICK
+            InitialCoord = get(0,'PointerLocation');
+            set(gcf, 'WindowButtonMotionFcn', @WinLevAdj);
+        end
+    end
+
+% -=< Window and level mouse adjustment >=-
+    function WinLevAdj(varargin)
+        PosDiff = get(0,'PointerLocation') - InitialCoord;
+
+        Win = Win + PosDiff(1) * WLAdjCoe * FineTuneC(get(ChBxhand,'Value')+1);
+        LevV = LevV - PosDiff(2) * WLAdjCoe * FineTuneC(get(ChBxhand,'Value')+1);
+        if (Win < 1)
+            Win = 1;
+        end
+
+        [Rmin, Rmax] = WL2R(Win,LevV);
+        caxis([Rmin, Rmax])
+        set(lvalhand, 'String', sprintf('%6.0f',LevV));
+        set(wvalhand, 'String', sprintf('%6.0f',Win));
+        InitialCoord = get(0,'PointerLocation');
+    end
+
+% -=< Window and level text adjustment >=-
+    function WinLevChanged(varargin)
+
+        LevV = str2double(get(lvalhand, 'string'));
+        Win = str2double(get(wvalhand, 'string'));
+        if (Win < 1)
+            Win = 1;
+        end
+
+        [Rmin, Rmax] = WL2R(Win,LevV);
+        caxis([Rmin, Rmax])
+    end
+
+% -=< Window and level to range conversion >=-
+    function [Rmn Rmx] = WL2R(W,L)
+        Rmn = L - (W/2);
+        Rmx = L + (W/2);
+        if (Rmn >= Rmx)
+            Rmx = Rmn + 1;
+        end
+    end
+
+% -=< Window and level auto adjustment callback function >=-
+    function AutoAdjust(object,eventdata)
+        Win = double(max(Img(:))-min(Img(:)));
+        Win (Win < 1) = 1;
+        LevV = double(min(Img(:)) + (Win/2));
+        [Rmin, Rmax] = WL2R(Win,LevV);
+        caxis([Rmin, Rmax])
+        set(lvalhand, 'String', sprintf('%6.0f',LevV));
+        set(wvalhand, 'String', sprintf('%6.0f',Win));
+    end
+
+end
+% -=< Maysam Shahedi (mshahedi@gmail.com), April 19, 2013>=-
\ No newline at end of file
diff --git a/code/functions/loadVolumeRoI.m b/code/functions/loadVolumeRoI.m
new file mode 100755
index 0000000000000000000000000000000000000000..42631336b15b4ad85b71c9a6d82c583cd093227b
--- /dev/null
+++ b/code/functions/loadVolumeRoI.m
@@ -0,0 +1,42 @@
+function [V,depth] = loadVolumeRoI(path)
+%LOADVOLUMEROI Loads a selected region of interest from a volume.
+%   Details...
+%by Monica Jane Emerson, March 2019, MIT License
+
+contents_datafolder = dir(path);
+path_firstSlice = [path,contents_datafolder(3).name];
+
+%select FoV in the cross-sectional direction
+[rect,~] = selectFoV(path_firstSlice);
+
+%select slices
+num_slices = length(contents_datafolder)-2; %depth of the volume
+zmin = ['Lower limit in the depth direction [1, ',num2str(num_slices),']:'];
+zmax = ['Upper limit in the depth direction [1, ',num2str(num_slices),']:'];
+zstep = ['Step (1 to take every slice):'];
+prompt = {zmin,zmax,zstep};
+depth = inputdlg(prompt,'RoI in the depth direction', [1,50], {'1',num2str(num_slices),'1'});
+slices = [str2double(depth{1}):str2double(depth{3}):str2double(depth{2})];
+
+V = zeros([rect(4)-rect(2)+1,rect(3)-rect(1)+1,numel(slices)]); %volume preallocation (for speed)
+
+tstart = tic;
+h = waitbar(0,'Loading volume...', 'CreateCancelBtn','setappdata(gcbf,''canceling'',1)');
+ for k= 1:numel(slices)
+    im = imread([path,contents_datafolder(slices(k)+2).name]);
+    V(:,:,k) = double(im(rect(2):rect(4),rect(1):rect(3)))/2^16;
+    
+    %Processing data wait bar
+    waitbar(k/numel(slices),h)
+    if getappdata(h,'canceling')
+        break
+    end
+    if k == numel(slices) 
+        delete(h)
+        t_load = toc(tstart);
+        f = msgbox(['time to load volume: ' , num2str(t_load), 's']);
+    end
+ end
+
+end
+
diff --git a/code/functions/num_dictAtoms.m b/code/functions/num_dictAtoms.m
new file mode 100755
index 0000000000000000000000000000000000000000..968a080312d92111256017531e6462ebbadb0d48
--- /dev/null
+++ b/code/functions/num_dictAtoms.m
@@ -0,0 +1,8 @@
+function [num] = num_dictAtoms(k,n)
+%NUM_DICTATOMS Summary of this function goes here
+%by Monica Jane Emerson, April 2018, MIT License
+vect = [1:n];
+series = k.^(vect-1);
+num = k*sum(series);
+end
+
diff --git a/code/functions/selectFoV.m b/code/functions/selectFoV.m
new file mode 100755
index 0000000000000000000000000000000000000000..8b3af9a06b1e4c2079cb104bf76b09d029f0622f
--- /dev/null
+++ b/code/functions/selectFoV.m
@@ -0,0 +1,29 @@
+function [rect,im_rect] = selectFoV(slice_path)
+%SELECTFOV is a user-friendly function to select a region of interest from a 2D image.
+%   The user can choose to select interactively the region of interest (RoI) 
+%   interactively with imcrop, or specify the coordinates of the RoI.
+% by Monica Jane Emerson, March 2019, MIT License
+
+%USER INPUT: SLICE_PATH, The location of the slice to crop the RoI from.
+% Other user input given through interaction with windows.
+
+autoManual = questdlg('How would you like to select the region of interest (RoI)?','Select analysis region','Interactively','I know the coordinates','Interactively');
+im = imread(slice_path);
+
+if strcmp(autoManual,'Interactively')
+    [~,rect] = imcrop(im);
+    rect = round(rect);
+    rect(3:4) = rect(1:2) + rect(3:4) - [1,1];
+else
+    xmin = ['Lower limit for the x value [1, ',num2str(size(im,2)),']:'];
+    xmax = ['Upper limit for the x value [1, ',num2str(size(im,2)),']:'];
+    ymin = ['Lower limit for the y value [1, ',num2str(size(im,1)),']:'];
+    ymax = ['Upper limit for the y value [1, ',num2str(size(im,1)),']:'];
+    prompt = {xmin,ymin,xmax,ymax};
+    dimRoI = inputdlg(prompt,'RoI in the cross-sectional direction', [1,60], {'200','200','1799','1799'});
+    rect = str2double(dimRoI);
+end
+    im_rect = double(im(rect(2):rect(4),rect(1):rect(3)))/2^16;
+
+end
+
diff --git a/code/functions/track_slicer.m b/code/functions/track_slicer.m
new file mode 100755
index 0000000000000000000000000000000000000000..7500058f54d9c5e3093fd574641ab6c4fdeab5f5
--- /dev/null
+++ b/code/functions/track_slicer.m
@@ -0,0 +1,109 @@
+function track_slicer(filename,centers,clim)
+%TRACK_SLICER   Slice trough data, centers and tracks.
+%   TRACK_SLICER(FILENAME,CENTERS,CLIM)
+%       FILENAME, name of the tiff stack with image data.
+%       CENTERS, detected fibre centers. If CENTERS contains track ids (as
+%           returned by fibre_tracking function) those will be shown as 
+%           numbers.
+%       CLIM, optional color limits.
+%   Author: vand@dtu.dk 2018
+
+if ~iscell(centers) % then tracks are given, and need to be converted
+    tracks = centers;
+    tracks = permute(tracks,[2,3,1]);
+    tracks(:,3,:) = repmat((1:size(tracks,1))',[1 1 size(tracks,3)]); % using slice number not z coordinate
+    centers = permute(mat2cell(tracks,size(tracks,1),size(tracks,2),ones(size(tracks,3),1)),[3 2 1]);
+end
+
+Z = length(imfinfo(filename));
+z = round(0.5*(Z+1));
+%update_drawing
+I = imread(filename,'Index',z);
+dim = [size(I),Z];
+if nargin<3 || isempty(clim)
+    clim = [min(I(:)),max(I(:))];
+end
+
+show_numbers = true;
+
+fig = figure('Units','Normalized','Position',[0.1 0.3 0.5 0.6],...
+    'KeyPressFcn',@key_press);
+imagesc(I,clim)
+hold on, colormap gray, axis image ij
+plot(centers{z}(:,1),centers{z}(:,2),'r.')
+title(['slice ',num2str(z),'/',num2str(Z)])
+drawnow
+
+% to capture zoom
+LIMITS = [0.5,dim(2)+0.5,0.5,dim(1)+0.5];
+zoom_handle = zoom(fig);
+pan_handle = pan(fig);
+set(zoom_handle,'ActionPostCallback',@adjust_limits,...
+    'ActionPreCallback',@force_keep_key_press);
+set(pan_handle,'ActionPostCallback',@adjust_limits,...
+    'ActionPreCallback',@force_keep_key_press);
+
+% if nargout>1
+%     uiwait(fig) % waits with assigning output until a figure is closed
+% end
+
+%%%%%%%%%% CALLBACK FUNCTIONS %%%%%%%%%%
+
+    function key_press(~,object)
+        % keyboard commands
+        key = object.Key;
+        switch key
+            case 'uparrow'
+                z = min(z+1,dim(3));
+            case 'downarrow'
+                z = max(z-1,1);
+            case 'rightarrow'
+                z = min(z+10,dim(3));
+            case 'leftarrow'
+                z = max(z-10,1);
+            case 'pageup'
+                z = min(z+50,dim(3));
+            case 'pagedown'
+                z = max(z-50,1);
+            case 'n'
+                show_numbers = ~show_numbers;
+        end
+        update_drawing
+    end
+
+%%%%%%%%%% HELPING FUNCTIONS %%%%%%%%%%
+
+    function update_drawing
+        I = imread(filename,'Index',z);
+        cla, imagesc(I,clim), hold on
+        if ~show_numbers || size(centers{z},2)<3 || (LIMITS(2)-LIMITS(1))*(LIMITS(4)-LIMITS(3))>300^2
+            plot(centers{z}(:,1),centers{z}(:,2),'r.')
+        else
+            present = (centers{z}(:,1)<LIMITS(2))&(centers{z}(:,1)>LIMITS(1))&...
+                (centers{z}(:,2)<LIMITS(4))&(centers{z}(:,2)>LIMITS(3));
+            text(centers{z}(present,1),centers{z}(present,2),num2cell(centers{z}(present,3)'),...
+                'HorizontalAlignment','center','VerticalAlignment','middle',...
+                'Color','r')
+        end
+        title(['slice ',num2str(z),'/',num2str(Z)])
+        drawnow
+    end
+
+    function adjust_limits(~,~)
+        % response to zooming and panning
+        LIMITS([1,2]) = get(gca,'XLim');
+        LIMITS([3,4]) = get(gca,'YLim');
+        if show_numbers
+            update_drawing
+        end
+    end
+
+    function force_keep_key_press(~,~)
+        % a hack to maintain my key_press while in zoom and pan mode
+        % http://undocumentedmatlab.com/blog/enabling-user-callbacks-during-zoom-pan
+        hManager = uigetmodemanager(fig);
+        [hManager.WindowListenerHandles.Enabled] = deal(false);
+        set(fig, 'KeyPressFcn', @key_press);
+    end
+
+end
diff --git a/code/scripts/addpaths_inSegtFibre.m b/code/scripts/addpaths_inSegtFibre.m
new file mode 100755
index 0000000000000000000000000000000000000000..9e96bfd90a2a552977cb960a5d67971f5d83316f
--- /dev/null
+++ b/code/scripts/addpaths_inSegtFibre.m
@@ -0,0 +1,12 @@
+%ADDPATHS_INSEGTFIBRE Makes all the code of Insegt Fibre accesible
+%   Written by Monica Jane Emerson, March 2019, MIT License
+
+%USER INPUT: The path of the textureGUI folder in your computer
+x = inputdlg('Confirm the default path of the texture_GUI folder: ',...
+    'User input',[1,30],{'./texture_gui'});
+path_textureGUI = x{1}; 
+
+%Add the functions and Insegt software path 
+addpath(genpath(path_textureGUI))
+addpath('./scripts')
+addpath('./functions')
\ No newline at end of file
diff --git a/code/scripts/create_dict.m b/code/scripts/create_dict.m
new file mode 100755
index 0000000000000000000000000000000000000000..5ef7e62937405a54169181e9d0f3675242a4daf7
--- /dev/null
+++ b/code/scripts/create_dict.m
@@ -0,0 +1,31 @@
+%CREATE_DICT Updates the dictionary of intensities built by SETUP_DICT with
+%a training data-set that can be loaded or created from scratch.
+%   Written by Monica Jane Emerson, March 2019, MIT License
+
+%USER INPUT: Option to load a labelling that was saved
+x = questdlg('Would you like to load a labelling or create a new one?','Annotation of training data','New one','Load','New one');
+
+if strcmp(x,'Load') 
+    [filename,pathname] = uigetfile('*.mat','Choose training image','../data/saved_data/trainingData/imtrain.mat');
+    load([pathname,filename]);
+    [filename,pathname] = uigetfile('*labels_indexed.png','Choose label image','../data/saved_data/trainingData/');
+    labelling = imread([pathname,filename]);
+    
+    dictionary = build_dictionary(im_train,dictopt); %create the dictionary of intensities
+    image_texture_gui(im_train,dictionary,2,labelling)
+else
+    %select a small RoI for training, containing 100 fibres approx
+    prompt = ['Choose a slice for training: [1,', num2str(size(V,3)),']:'];
+    x = inputdlg(prompt,...
+    'User input',[1,30],{num2str(round(size(V,3)/2))});  %select slice
+    path_trainSlice = [path_volumeFolder,contents_datafolder(str2double(x{1})+2).name];
+    [~,im_train] = selectFoV(path_trainSlice);
+    uisave('im_train','../data/saved_data/trainingData/imtrain.mat')
+    
+    dictionary = build_dictionary(im_train,dictopt); %create the dictionary of intensities
+    image_texture_gui(im_train,dictionary,2) %learn the dictionary of probabilities by annotating in the GUI 
+end
+dictionary = update_dictionary(dictionary,gui_dictprob); %update dictionary to include the learnt probalilities
+
+%USER INPUT: Save dictionary to process the complete scan
+uisave('dictionary','../data/saved_data/dictionaries/dictionary_v.mat')
diff --git a/code/scripts/indicate_dataFolder.m b/code/scripts/indicate_dataFolder.m
new file mode 100755
index 0000000000000000000000000000000000000000..1899d0f51838d081c8b284dfcf92bcb903228c93
--- /dev/null
+++ b/code/scripts/indicate_dataFolder.m
@@ -0,0 +1,19 @@
+%INDICATE_DATAFOLDER Allows the user to specify the location of their data,
+%and displays a slice to ensure that the right data is contained at the 
+%specified location.
+%   Written by Monica Jane Emerson, March 2019, MIT License
+
+%USER INPUT: Path to CT volume? 
+path_volumeFolder = uigetdir('../data/','Open the folder with your CT data');
+if ~strcmp(path_volumeFolder(end),'/')
+    path_volumeFolder = [path_volumeFolder,'/'];
+end
+
+%add the path and check the contents of the data folder
+addpath(genpath(path_volumeFolder))
+contents_datafolder = dir(path_volumeFolder);
+
+%display cross-section, first slice
+path_firstSlice = [path_volumeFolder,contents_datafolder(3).name];
+im = imread(path_firstSlice);
+figure, imagesc(im), axis image, colormap gray, title('First slice of the loaded data-set')
\ No newline at end of file
diff --git a/code/scripts/input_depthRoI.m b/code/scripts/input_depthRoI.m
new file mode 100644
index 0000000000000000000000000000000000000000..a6c8c5d5ac6f521f4b301372569c7c756ba58732
--- /dev/null
+++ b/code/scripts/input_depthRoI.m
@@ -0,0 +1,19 @@
+function [ depth ] = input_depthRoI(varargin)
+%INPUT_DEPTHROI asks the user to specify the depth range to analyse
+%   Details...
+%by Monica Jane Emerson, May 2019, MIT License
+
+if nargin == 1
+    num_slices = varargin{1};
+else
+    num_slices = [];
+end
+
+zmin = ['Lower limit in the depth direction [1, ',num2str(num_slices),']:'];
+zmax = ['Upper limit in the depth direction [1, ',num2str(num_slices),']:'];
+zstep = ['Step (1 to take every slice):'];
+prompt = {zmin,zmax,zstep};
+depth = inputdlg(prompt,'RoI in the depth direction', [1,50], {'1',num2str(num_slices),'10'});
+
+end
+
diff --git a/code/scripts/load_multiple_trackSets.m b/code/scripts/load_multiple_trackSets.m
new file mode 100755
index 0000000000000000000000000000000000000000..0a25847e5002a7d7752b130fd765720e28b411fb
--- /dev/null
+++ b/code/scripts/load_multiple_trackSets.m
@@ -0,0 +1,15 @@
+%LOAD_MULTIPLE_TRACKSETS is a user-friendly script to load tracks measured 
+%from multiple data-sets, e.g. acquired at progressive load steps.
+% by Monica Jane Emerson, March 2019, MIT License
+
+%% USER INPUT: Load several sets of tracks corresponding to different steps of a time-lapse data-set
+x = inputdlg('How many sets of tracks would you like to load [>=2]?','Nr. analysed matching volumes',[1,60],{num2str(2)});
+
+for l = 1:str2double(x{1})
+    [filename_tracks,pathname_tracks] = uigetfile('*.mat',['Choose tracks for data-set ',num2str(l)],'saved_data/fibreTracks');
+    aux = load([pathname_tracks,filename_tracks]);
+    tracks{l} = aux.fibres;
+end
+num_datasets = length(tracks);
+num_slices = size(tracks{1}.x,2);
+
diff --git a/code/scripts/setup_dict.m b/code/scripts/setup_dict.m
new file mode 100755
index 0000000000000000000000000000000000000000..b6e8f81b6736bb5b963faa5330c3ae395f500c28
--- /dev/null
+++ b/code/scripts/setup_dict.m
@@ -0,0 +1,15 @@
+%SETUP_DICT Set-ups the default parameters for the dictionary, andasks for the
+%data-dependent parameter (patch size)
+%   Written by Monica Jane Emerson, March 2019, MIT License
+
+%USER INPUT: select patch size, the closest odd integer to factor*diam/pixel_size 
+x = inputdlg('Choose patch size: ','User input',[1,20],{num2str(11)}); %ask for patch size
+dictopt.patch_size = str2double(x{1}); %save patch size
+
+%Set the default parameters and initialise dictionary
+dictopt.method = 'euclidean';
+dictopt.branching_factor = 3; %>=3
+dictopt.number_layers = 5; %>=5. The higher the more accurate, but also slower and more computationally heavy
+dictopt.number_training_patches = 15000; %at least 10*num_dictAtoms(branching_factor,number_layers)
+dictopt.normalization = false; %set to true if the global intensity of the slices varies along the depth of the volume
+
diff --git a/code/texture_gui/code/batch_processing_script.m b/code/texture_gui/code/batch_processing_script.m
new file mode 100755
index 0000000000000000000000000000000000000000..9d87ea3884a90d90352f9ae69dd3b186bd652b83
--- /dev/null
+++ b/code/texture_gui/code/batch_processing_script.m
@@ -0,0 +1,39 @@
+clear
+close all
+addpath functions
+
+% VERSION 1: WITHOUT CORRECTION
+% for batch processing dictionary is reused, and manual labeling might need
+% correction, so easiest is to build dictionary outside the gui to be able
+% to use it later
+im = double(imread('../data/slice1.png'))/255;
+
+dictopt.method = 'euclidean';
+dictopt.patch_size = 9;
+dictopt.branching_factor = 5;
+dictopt.number_layers = 4;
+dictopt.number_training_patches = 30000;
+dictopt.normalization = false;
+
+dictionary = build_dictionary(im,dictopt);
+
+% IMPORTANT:
+% once inside gui export dict_labels to workspace (E)
+image_texture_gui(im,dictionary,2)
+%%
+dictionary = update_dictionary(dictionary,gui_dictprob);
+%%
+figure, imagesc(gui_S), axis image, title('results from gui')
+
+figure
+for i=1:5
+    I = imread(['../data/slice',num2str(i),'.png']);
+    S = process_image(I,dictionary);
+    subplot(1,5,i)
+    imagesc(S), axis image, title(i), drawnow
+end
+
+%%
+
+% VERSION 2: WITH (OR WITHOUT) CORRECTION
+% TODO: freezeing (F) and correcting
diff --git a/code/texture_gui/code/functions/biadjacency_matrix.cpp b/code/texture_gui/code/functions/biadjacency_matrix.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..efb16ea08cc771d7e59ff26f4b2c0434d870ab15
--- /dev/null
+++ b/code/texture_gui/code/functions/biadjacency_matrix.cpp
@@ -0,0 +1,103 @@
+/*=================================================================
+* syntax: B = biadjacency_matrix(A,M,K) OR B = biadjacency_matrix(A,M)
+*
+* BIADJACENCY_MATRIX  - build biadjacancy matrix from assignment image
+* 			
+* 			Input: 	- A: X-by-Y assignment image
+* 					- M: patch size (length of edge)
+*                   - K: number of dictionary patches, defaults to max(A(:))
+*
+* 			Output: - B: XY-by-MMK sparse biadjacency matrix 
+*
+* 			Author: Vedrana Andersen Dahl, vand@dtu.dk, december 2015.
+*=================================================================*/
+
+#include <math.h>
+#include <stdio.h>
+#include <vector>
+#include <algorithm>
+#include "mex.h"
+
+// struct containing i and j indices of a sparse matrix element
+struct ij
+{
+    int i,j;
+    ij(int i_, int j_) : i(i_), j(j_){}; // constructor
+    bool operator<(const ij second) const{ // leq operator needed for sorting
+        return (j<second.j) || ((j==second.j) && (i<second.i));
+    }    
+};
+
+// The gateway mex routine
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+    /* Check for proper number of input and output arguments */    
+    if ((nlhs != 1) || (nrhs != 2))
+        mexErrMsgTxt("Usage: B = BIADJANCENCY_MATRIX(A,M) OR "
+                "B = BIADJANCENCY_MATRIX(A,M,K).\n");
+        
+    /* Read input */
+    double *A = mxGetPr(prhs[0]); // assignment image
+    int X = mxGetM(prhs[0]); // image size X
+	int Y = mxGetN(prhs[0]); // image size Y
+    int M = (int)mxGetPr(prhs[1])[0]; // patch size
+    int K; // number dict patches
+    if (nrhs==3)
+        K = (int)mxGetPr(prhs[2])[0]; 
+    else{ // assumes number of dict patches is max(A)
+        K = 0;
+        for (int a=0; a<X*Y; a++)
+            if (A[a]>K)
+                K = A[a];
+    }
+    
+    /* Compute some useful sizes */
+    int c = (M-1)/2; // width of boundary having no assignment 
+    int n = X*Y; // number of image pixels
+    int m = M*M*K; // number of dict pixels
+    int s = (X-M+1)*(Y-M+1)*M*M; // number image-dict links (elements in B)
+    
+    /* Finding elements of B as row-column indices */
+    std::vector<ij> bij;
+    bij.reserve(s); 
+    int ic,i,j;   
+    for (int y=0+c; y<Y-c; y++){ // visiting patches centered around pixels
+        for (int x=0+c; x<X-c; x++){
+            ic = x+y*X; // central patch pixel
+            for (int dy=-c; dy<=c; dy++){ // visiting pixels around central
+                for (int dx=-c; dx<=c; dx++){
+                    i = (x+dx)+(y+dy)*X;
+                    j = (c+dx)+(c+dy)*M+(A[ic]-1)*M*M;
+                    bij.push_back(ij(i,j));
+                }
+            }
+        }
+    }
+    
+    /* Sorting elements in bij columnwise */
+    std::sort (bij.begin(), bij.end());    
+    
+    /* Placeholder for output */
+    plhs[0] = mxCreateSparseLogicalMatrix(n,m,s); // output mxArray, sparse logical matrix B
+    if (plhs[0]==NULL)
+        mexErrMsgTxt("Could not allocate enough memory!\n");
+    
+    /* Access fields of output mxArray via pointers  */
+    mwIndex *ir = mxGetIr(plhs[0]); // row index (0 indexed) 
+    mwIndex *jc = mxGetJc(plhs[0]); // cumulative number of elements per column 
+    mxLogical *pr = mxGetLogicals(plhs[0]); // element values (will be all true)
+        
+    /* Converting row-column indices into row-cumulative column  */
+    int k = 0; // for visiting elements of bij
+    jc[0] = 0; // first element of cumulative sum is 0
+    for (int bc=0; bc<m; bc++){ // all columns of B        
+        jc[bc+1] = jc[bc]; 
+        while (k<bij.size() && bij[k].j==bc){
+            jc[bc+1]++;
+            ir[k] = bij[k].i;
+            pr[k] = true;
+            k++;
+        }
+    }
+}
+ 
diff --git a/code/texture_gui/code/functions/biadjacency_matrix.mexa64 b/code/texture_gui/code/functions/biadjacency_matrix.mexa64
new file mode 100755
index 0000000000000000000000000000000000000000..703f486d9d5d8524e9e27c48c259071a086f90a1
Binary files /dev/null and b/code/texture_gui/code/functions/biadjacency_matrix.mexa64 differ
diff --git a/code/texture_gui/code/functions/biadjacency_matrix.mexmaci64 b/code/texture_gui/code/functions/biadjacency_matrix.mexmaci64
new file mode 100755
index 0000000000000000000000000000000000000000..f40f6e00dc3e5bf9fbbabf158abccc084bfc6a93
Binary files /dev/null and b/code/texture_gui/code/functions/biadjacency_matrix.mexmaci64 differ
diff --git a/code/texture_gui/code/functions/biadjacency_matrix.mexw64 b/code/texture_gui/code/functions/biadjacency_matrix.mexw64
new file mode 100755
index 0000000000000000000000000000000000000000..6985266719edbacda108ffd1a788c7c78c26a019
Binary files /dev/null and b/code/texture_gui/code/functions/biadjacency_matrix.mexw64 differ
diff --git a/code/texture_gui/code/functions/build_dictionary.m b/code/texture_gui/code/functions/build_dictionary.m
new file mode 100755
index 0000000000000000000000000000000000000000..6750331e3cb3640e4c36a65d336d4b938b765326
--- /dev/null
+++ b/code/texture_gui/code/functions/build_dictionary.m
@@ -0,0 +1,23 @@
+function dictionary = build_dictionary(image,dictionary_options)
+
+image = normalize_image(image);
+dictionary.options = dictionary_options;
+
+switch dictionary.options.method%dictionary_options.method
+    case 'euclidean'
+        dictionary.tree = build_km_tree(image,...
+            dictionary_options.patch_size,...
+            dictionary_options.branching_factor,...
+            dictionary_options.number_training_patches,...
+            dictionary_options.number_layers,...
+            dictionary_options.normalization);
+    case 'nxcorr'
+        dictionary.tree = build_km_tree_xcorr(image,...
+            dictionary_options.patch_size,...
+            dictionary_options.branching_factor,...
+            dictionary_options.number_training_patches,...
+            dictionary_options.number_layers);
+    otherwise
+        error('Unknown dictionary method.')
+        
+end
diff --git a/code/texture_gui/code/functions/build_km_tree.cpp b/code/texture_gui/code/functions/build_km_tree.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..a1e1116738f18af5569fc9b55bc14ee31b694ebb
--- /dev/null
+++ b/code/texture_gui/code/functions/build_km_tree.cpp
@@ -0,0 +1,421 @@
+/*=================================================================
+* syntax: T = build_km_tree(I, M, b, t, L, n); OR T = build_km_tree(I, M, b, t, L);
+*
+* build_km_tree  - build km-tree matrix from image
+* 			
+* 			Input: 	- I: X-by-Y intensity image
+* 					- M: patch size (length of edge)
+*                   - L: number of dictionary layers. This parameter is limited 
+*                        such that the average number of patches in a leafnode is 
+*                        greater than five
+*                   - b: branching factor
+*                   - t: number of training patches
+*                   - n: normalization (true or false), defaults to false
+*
+* 			Output: - T: MMl-by-K matrix where l is the number of layers 
+*                        in the image (1 for grayscale and 3 for RGB)
+*                        and K is the number of nodes in the tree.
+*
+* 			Author: Anders Dahl, abda@dtu.dk, december 2015.
+*=================================================================*/
+
+#include "mex.h"
+#include <stdio.h>
+#include <math.h>
+#include "matrix.h"
+#include <vector>
+#include <algorithm>
+
+#include <iostream>
+using namespace std;
+
+// struct for image
+struct im_st
+{
+    double *im_data; // pointer to image data
+    int rows, cols, layers, n_pix; // rows, cols and layers are the image dimensions and n_pix = rows*cols
+};
+
+// struct for the tree
+struct tree_st
+{
+    double *tree_data;
+    int n_dim, n_nodes, branch_fac, M, Mh;
+};
+
+// struct for image patches
+struct im_patch
+{
+    double *patch_data; // pointer to the data
+    int idx; // id used for sorting the patches according to the tree
+    bool operator<(const im_patch& rhs) const {return idx < rhs.idx;} // operator needed for sorting
+};
+
+
+// Function for sampling patches from the image into the patch arrays
+// inputs reference to the image struct, tree struct, patch struct and position of the sampling coordinate.
+// There is no check if the sampling is outside the image
+void sample_patch(im_st& im, tree_st& tree, im_patch& patch, int r_im, int c_im, bool normalize)
+{
+    int id_l, id_r, id_i; // iterators for looking up image data
+    int id_p = 0; // iterator for looking up patch data
+    double sum_sq = 0, pix_val; // variables for normalization
+    
+    for ( int l = 0; l < im.layers; l++ ){ // image is sampled by three nested loops
+        id_l = im.n_pix*l;
+        for ( int i = c_im-tree.Mh; i <= c_im+tree.Mh; i++ ){
+            id_r = id_l + i*im.rows;
+            for ( int j = r_im-tree.Mh; j <= r_im+tree.Mh; j++ ){
+                id_i = id_r + j;
+                pix_val = *(im.im_data + id_i);
+                *(patch.patch_data + id_p) = pix_val;
+                sum_sq += pix_val*pix_val;
+                id_p++;
+            }
+        }
+    }
+    
+    if ( normalize ){ // normalization to unit length
+        double inv_sq = 1;
+        if ( sum_sq > 0 ){
+            inv_sq = 1/sqrt(sum_sq); // divide by sum of squares
+        }
+        for ( int i = 0; i < tree.n_dim; i++ ){
+            *(patch.patch_data + i) = (*(patch.patch_data + i))*inv_sq;
+        }
+    }
+
+    
+}
+
+
+// function for randomly permuted set of indices
+// n is the numbers to choose from, n_set is the number of random indices
+// that is returned. Returns a vector of indices
+vector<int> randperm( int n, int n_set ) {
+    if ( n_set > n ){ // check if n_set exceeds n
+        n_set = n;
+    }
+    
+    vector<int> rid;
+    rid.reserve(n); // vector of indices
+    for ( int i = 0; i < n; i++ ){ // set all indices in order
+        rid.push_back(i);
+    }
+    
+    int t, id; // place holders for id and temporary number
+    int r_max = RAND_MAX; // maximum random number
+    for ( int i = 0; i < n_set; i++ ){
+        // choose a random number between i and n-1 and swap place between i and id
+        if ( LONG_MAX > RAND_MAX && n-i-1>RAND_MAX ){ // not enough with a random integer up til RAND_MAX
+            id = ((rand()*(r_max+1)+rand()) % (n-i)) + i; 
+        }
+        else{
+            id = (rand() % (n-i)) + i; 
+        }
+        t = rid[id];
+        rid[id] = rid[i];
+        rid[i] = t;
+    }
+    rid.resize(n_set); // set size to n_set
+    return rid;
+}
+
+
+// copy values from a patch array into the tree array at node
+void set_values(tree_st& tree, im_patch& patch, int node){
+    int idx = tree.n_dim*node;
+    for ( int i = 0; i < tree.n_dim; i++ ){
+        *(tree.tree_data + idx) = *(patch.patch_data + i);
+        idx++;
+    }
+}
+
+// add values to vector of cluster center points
+void add_values(vector<double>& center_sum, im_patch& patch, int id, int n_dim){
+    int idx = n_dim*id;
+    for ( int i = 0; i < n_dim; i++ ){
+        center_sum[idx] += *(patch.patch_data + i);
+        idx++;
+    }
+}
+
+// estimates the squared Euclidian distance between an image patch and a tree node
+double get_dist(tree_st& tree, im_patch& patch, int node)
+{
+    double d = 0, tmp;
+    int id = tree.n_dim*node;
+    
+    for ( int i = 0; i < tree.n_dim; i++ ){
+        tmp = *(tree.tree_data + id) - *(patch.patch_data + i);
+        d += tmp*tmp;
+        id++;
+        
+    }
+    
+    return d;
+}
+
+// k-means-function taking a reference to the vector of image patches and a
+// tree struct as input f and t gives the image patches that should be clustered.
+// node is the first node in the tree included in the clustering
+void k_means( vector<im_patch>& patches, tree_st& tree, int f, int t, int node )
+{
+    // vectors holding the sum of values in the cluster and a vector containing the change
+    vector<double> centSum(tree.branch_fac*tree.n_dim), centChange(tree.branch_fac);
+    vector<int> centCount(tree.branch_fac); // vector for counting the number of points in a cluster
+    double min_d, d, tmp;//, diff; // variables for clustering
+    // variables for cluster id and index of previous cluseter, which will be overwritten by new cluster id
+    int id = 0, id_in = patches[f].idx;
+    
+    if ( t-f > tree.branch_fac ){ // check if there are enough point to carry out the clustering
+        // initialize the center positions
+        for (  int i = 0; i < tree.branch_fac; i++ ){
+            set_values(tree, patches[f+i], node+i);
+        }
+        
+        // run clutering for 20 iterations - only little change happens after 10 iterations
+        for ( int n_run = 0; n_run < 30; n_run++){
+            
+            for ( int i = f; i < t; i++ ){ // go through the patches from f to t
+                min_d = get_dist(tree, patches[i], node); // initially set min distance and id to the first
+                id = 0;
+                for ( int j = 1; j < tree.branch_fac; j++ ){ // run throgh the other points
+                    d = get_dist(tree, patches[i], node + j); // get the distance
+                    if ( d < min_d ){ // if the this cluster is closer set this as min distance
+                        min_d = d;
+                        id = j;
+                    }
+                }
+                add_values(centSum, patches[i], id, tree.n_dim); // add the patch to the closest cluster
+                centCount[id]++; // count the extra patch
+                // update the idx to the child idx - note that all layers start with idx = 0
+                patches[i].idx = (id + id_in*tree.branch_fac);
+            }
+            
+            // update the clusters in the tree and calculate the center change (not used for anything)
+            id = node*tree.n_dim;
+            int id_c = 0;
+            
+            for ( int i = 0; i < tree.branch_fac; i++ ){ // go through all new clusters
+                if ( centCount[i] == 0 ){
+                    centCount[i] = 1;
+                }
+                for ( int j = 0; j < tree.n_dim; j++ ){ // go through cluster pixels
+                    tmp = centSum[id_c]/centCount[i];
+                    //diff = (tmp - *(tree.tree_data + id)); // for calculating center change
+                    //centChange[i] += diff*diff;
+                    *(tree.tree_data + id) = tmp;
+                    id_c++;
+                    id++;
+                }
+            }
+            
+            // set counter and sum to zero
+            fill(centSum.begin(), centSum.end(), 0);
+            fill(centCount.begin(), centCount.end(),0);
+            fill(centChange.begin(), centChange.end(), 0);
+        }
+    }
+}
+
+// runs through the patches vector to find the last element with id
+int get_to( vector<im_patch>& patches, int id )
+{
+    int to = 0;
+    for ( int i = 0; i < patches.size(); i++ ){
+        if ( patches[i].idx == id ){
+            to = i;
+        }
+    }
+    return to+1;
+}
+
+// Main function for building the km-tree. Takes the image and tree struct
+// and the number of training patches as argument
+void build_km_tree ( im_st& im, tree_st& tree, int n_train, bool normalize ) {
+    // allocate memory for the image patches
+    double* im_patch_data = new double[n_train*tree.M*tree.M*im.layers];
+    
+    int rows_c = im.rows-tree.M+1, cols_c = im.cols-tree.M+1; // number of rows and cols within sampling area
+    int n_im_patches = rows_c*cols_c; // number of pixels in the image for sampling - inside boundary
+    
+    // checks that the number of training patches is not exceeding the number of pixels in the sample area
+    if ( n_im_patches < n_train ){
+        n_train = n_im_patches;
+    }
+    
+    vector<int> r_id = randperm(n_im_patches, n_train); // indices of random patches
+    
+    vector<im_patch> patches; // vector of image patches
+    patches.resize(n_train); // allocate memory
+    
+    int r, c, idx = 0; // variables used for sampling the image
+    // sample image patches
+    for (int i = 0; i < n_train; i++ )
+    {
+        c = r_id[i]/rows_c; // column is floored because of int
+        r = r_id[i]-c*rows_c; // row is rest after column
+        patches[i].idx = 0; // inital id is 0
+        patches[i].patch_data = im_patch_data + idx; // pointer to patch memory
+        sample_patch(im, tree, patches[i], r + tree.Mh, c + tree.Mh, normalize); // sampel in image with added boundary
+        idx += tree.n_dim; // step number of patch pixels forward
+    }
+    
+    // k-means tree
+    int n_layer = (int)ceil(log((double)tree.n_nodes)/log((double)tree.branch_fac)); // number of layers in the tree
+    int n_in_layer; // number of nodes in layer
+    int t, f; // keeps track of patches that belong to a certain cluster
+    int node = 0; // node number that will be updated
+    
+    // go through the layers in the tree
+    for (int i = 0; i < n_layer; i++ )
+    {
+        t = 0; // start at 0
+        n_in_layer = pow((double)tree.branch_fac,i); // number of nodes in current layer of the tree
+        sort(patches.begin(), patches.end()); // sort the patches according to their current id
+        for ( int j = 0; j < n_in_layer; j++ ) // go through the nodes in the layer and cluster that node
+        {
+            f = t; // patch j from
+            t = get_to(patches,j); // patch j to
+            // check that the node does not exceed the size of the tree
+            if ( node + tree.branch_fac <= tree.n_nodes ){
+                k_means( patches, tree, f, t, node );
+            }
+            else {
+                break;
+            }
+            node += tree.branch_fac; // next node
+        }
+    }
+    
+    delete[] im_patch_data; // free up patch memory
+}
+
+
+// The gateway routine
+void mexFunction( int nlhs, mxArray *plhs[],
+        int nrhs, const mxArray *prhs[])
+{
+    // input image (I), patch size (M*M), number of nodes in the tree (n), branching
+    // factor (b), and number of training patches (n_train). Outputs the km-tree (tree)
+    double *I, *tree; // pointers to image and tree
+    int b, M, L, n, ndim, n_train; // variables
+    const int *dim; // image dimensinos
+    int dtree[2]; // tree dimensions
+    bool normalize = false; // decide if vectors of image patches should be normalized to unit length
+    
+    /*  Check for proper number of arguments. */
+    /* NOTE: You do not need an else statement when using
+     mexErrMsgTxt within an if statement. It will never
+     get to the else statement if mexErrMsgTxt is executed.
+     (mexErrMsgTxt breaks you out of the MEX-file.)
+     */
+    if(nrhs < 5 || nrhs > 6)
+        mexErrMsgTxt("Five or six inputs required.");
+    if(nlhs != 1)
+        mexErrMsgTxt("One output required.");
+    
+    if ( !mxIsDouble(prhs[0]) )
+        mexErrMsgTxt("Image should be double!");
+    
+    // Create a pointer to the input matrix.
+    I = mxGetPr(prhs[0]);
+    
+    // input passing
+    double *Md, *bd, *Ld, *n_train_d;
+    Md = mxGetPr(prhs[1]);
+    M = (int)Md[0];
+    
+    bd = mxGetPr(prhs[2]);
+    b = (int)bd[0];
+    
+    // check if number of clusters is smaller than branching factor
+    if ( n < b ){
+        n = b;
+    }
+    
+    n_train_d = mxGetPr(prhs[3]);
+    n_train = (int)n_train_d[0];
+    
+    // determine number of tree nodes
+    Ld = mxGetPr(prhs[4]);
+    L = (int)Ld[0]; // layers in tree
+    n = 0;
+    int n_tmp = 0;
+    int max_n = (double)n_train/1.0;
+//     int max_n = (double)n_train/5.0;
+    for ( int i = 0; i < L; i++ ){
+        n_tmp += pow((double)b,(i+1));
+        if ( n_tmp > max_n ){
+            L = i+1;
+            break;
+        }
+        n = n_tmp;
+    }
+    printf("Number of nodes in resulting tree: %d in %d layers.\n", n, L);
+    
+    if ( nrhs == 6 ){
+        bool *normalize_d;
+        normalize_d = (bool *)mxGetData(prhs[5]);
+        normalize = normalize_d[0];
+    }
+    
+    // check input properties
+    if ( 1 - (M % 2)  || M < 1)
+        mexErrMsgTxt("M must be odd and positive.");
+    
+    if ( n < 1 )
+        mexErrMsgTxt("n must be positive.");
+    
+    if ( b < 1 )
+        mexErrMsgTxt("b must be positive.");
+    
+    // Get the dimensions of the matrix input.
+    ndim = mxGetNumberOfDimensions(prhs[0]);
+    if (ndim != 2 && ndim != 3)
+        mexErrMsgTxt("search_km_tree only works for 2-dimensional or 3-dimensional images.");
+    
+    // image dimensions
+    dim = mxGetDimensions(prhs[0]);
+    
+    
+    // image struct
+    im_st Im;
+    Im.im_data = I;
+    Im.rows = dim[0];
+    Im.cols = dim[1];
+    if ( ndim == 3 )
+    {
+        Im.layers = dim[2];
+    }
+    else
+    {
+        Im.layers = 1;
+    }
+    Im.n_pix = Im.rows*Im.cols;
+    
+    dtree[0] = Im.layers*M*M;
+    dtree[1] = n;
+    
+    // Set the output pointer to the output matrix. Array initialized to zero.
+    plhs[0] = mxCreateNumericArray(2, dtree, mxDOUBLE_CLASS, mxREAL);
+    
+    // Create a C pointer to a copy of the output matrix.
+    tree = mxGetPr(plhs[0]);
+    for (int i = 0; i < dtree[0]*dtree[1]; i++ )
+        *(tree + i) = -1;
+    
+    // tree struct
+    tree_st Tree;
+    Tree.tree_data = tree;
+    Tree.n_dim = dtree[0];
+    Tree.n_nodes = dtree[1];
+    Tree.branch_fac = b;
+    Tree.M = M;
+    Tree.Mh = (int)(0.5*((double)M-1.0));
+    
+    // build the km-tree using C++ subroutine
+    build_km_tree ( Im, Tree, n_train, normalize );
+    
+}
diff --git a/code/texture_gui/code/functions/build_km_tree.mexa64 b/code/texture_gui/code/functions/build_km_tree.mexa64
new file mode 100755
index 0000000000000000000000000000000000000000..64f090ccc0f775fd55f0c576b8e29df61ad8ff29
Binary files /dev/null and b/code/texture_gui/code/functions/build_km_tree.mexa64 differ
diff --git a/code/texture_gui/code/functions/build_km_tree.mexmaci64 b/code/texture_gui/code/functions/build_km_tree.mexmaci64
new file mode 100755
index 0000000000000000000000000000000000000000..af834dcdddc581cf19474646a2383c938c2441ca
Binary files /dev/null and b/code/texture_gui/code/functions/build_km_tree.mexmaci64 differ
diff --git a/code/texture_gui/code/functions/build_km_tree.mexw64 b/code/texture_gui/code/functions/build_km_tree.mexw64
new file mode 100755
index 0000000000000000000000000000000000000000..fc2e3cefa7e292a1cc3fd9baf7d06414b15fa888
Binary files /dev/null and b/code/texture_gui/code/functions/build_km_tree.mexw64 differ
diff --git a/code/texture_gui/code/functions/build_km_tree_xcorr.cpp b/code/texture_gui/code/functions/build_km_tree_xcorr.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..0e15bbf7e5a66e4f0102ecc7e8c4692a933097f5
--- /dev/null
+++ b/code/texture_gui/code/functions/build_km_tree_xcorr.cpp
@@ -0,0 +1,427 @@
+/*=================================================================
+* syntax: T = build_km_tree_xcorr(I, M, L, b, t);
+*
+* build_km_tre:xcorr  - build km-tree matrix from image based on cross correlation
+* 			
+* 			Input: 	- I: X-by-Y intensity image
+* 					- M: patch size (length of edge)
+*                   - L: number of dictionary layers. This parameter is limited 
+*                        such that the average number of patches in a leafnode is 
+*                        greater than five
+*                   - b: brancing factor
+*                   - t: number of training patches
+*
+* 			Output: - T: MMl-by-K matrix where l is the number of layers 
+*                        in the image (1 for grayscale and 3 for RGB)
+*                        and K is the number of nodes in the tree. 
+*
+* 			Author: Anders Dahl, abda@dtu.dk, december 2015.
+*=================================================================*/
+
+#include "mex.h"
+#include <stdio.h>
+#include <math.h>
+#include "matrix.h"
+#include <vector>
+#include <algorithm>
+
+#include <iostream>
+using namespace std;
+
+// struct for image
+struct im_st
+{
+    double *im_data; // pointer to image data
+    int rows, cols, layers, n_pix; // rows, cols and layers are the image dimensions and n_pix = rows*cols
+};
+
+// struct for the tree
+struct tree_st
+{
+    double *tree_data;
+    int n_dim, n_nodes, branch_fac, M, Mh;
+    double inv_ndim;
+};
+
+// struct for image patches
+struct im_patch
+{
+    double *patch_data; // pointer to the data
+    int idx; // id used for sorting the patches according to the tree
+    bool operator<(const im_patch& rhs) const {return idx < rhs.idx;} // operator needed for sorting
+};
+
+// nomalize patch vectors to zero mean and unit Euclidean length
+void norm_patch(double* patch_data, double& mu, int n_dim){
+    
+    double sum_sq = 0;
+    
+    for ( int i = 0; i < n_dim; i++ ){
+        *(patch_data + i) = *(patch_data + i) - mu;
+        sum_sq += (*(patch_data + i))*(*(patch_data + i));
+    }
+    
+    double inv_sq = 1;
+    if ( sum_sq > 0 ){
+        inv_sq = 1.0/sqrt(sum_sq); // divide by sum of squares
+    }
+
+    for ( int i = 0; i < n_dim; i++ ){
+        *(patch_data + i) = (*(patch_data + i))*inv_sq;
+    }
+}
+
+
+// Function for sampling patches from the image into the patch arrays
+// inputs reference to the image struct, tree struct, patch struct and position of the sampling coordinate.
+// There is no check if the sampling is outside the image
+void sample_patch(im_st& im, tree_st& tree, im_patch& patch, int r_im, int c_im)
+{
+    int id_l, id_r, id_i; // iterators for looking up image data
+    int id_p = 0; // iterator for looking up patch data
+    double sum_sq = 0, sum = 0, pix_val, mu, tmp; // variables for normalization
+    
+    for ( int l = 0; l < im.layers; l++ ){ // image is sampled by three nested loops
+        id_l = im.n_pix*l;
+        for ( int i = c_im-tree.Mh; i <= c_im+tree.Mh; i++ ){
+            id_r = id_l + i*im.rows;
+            for ( int j = r_im-tree.Mh; j <= r_im+tree.Mh; j++ ){
+                id_i = id_r + j;
+                pix_val = *(im.im_data + id_i);
+                *(patch.patch_data + id_p) = pix_val;
+                sum += pix_val;
+                id_p++;
+            }
+        }
+    }
+    
+    mu = sum*tree.inv_ndim;
+    
+    norm_patch(patch.patch_data, mu, tree.n_dim);
+}
+
+
+// function for randomly permuted set of indices
+// n is the numbers to choose from, n_set is the number of random indices
+// that is returned. Returns a vector of indices
+vector<int> randperm( int n, int n_set ) {
+    if ( n_set > n ){ // check if n_set exceeds n
+        n_set = n;
+    }
+    
+    vector<int> rid;
+    rid.reserve(n); // vector of indices
+    for ( int i = 0; i < n; i++ ){ // set all indices in order
+        rid.push_back(i);
+    }
+    
+    int t, id; // place holders for id and temporary number
+    int r_max = RAND_MAX; // maximum random number
+    for ( int i = 0; i < n_set; i++ ){
+        // choose a random number between i and n-1 and swap place between i and id
+        if ( LONG_MAX > RAND_MAX && n-i-1>RAND_MAX ){ // not enough with a random integer up til RAND_MAX
+            id = ((rand()*(r_max+1)+rand()) % (n-i)) + i; 
+        }
+        else{
+            id = (rand() % (n-i)) + i; 
+        }
+        t = rid[id];
+        rid[id] = rid[i];
+        rid[i] = t;
+    }
+    rid.resize(n_set); // set size to n_set
+    return rid;
+}
+
+
+// copy values from a patch array into the tree array at node
+void set_values(tree_st& tree, im_patch& patch, int node){
+    int idx = tree.n_dim*node;
+    for ( int i = 0; i < tree.n_dim; i++ ){
+        *(tree.tree_data + idx) = *(patch.patch_data + i);
+        idx++;
+    }
+}
+
+// add values to vector of cluster center points
+void add_values(vector<double>& center_sum, im_patch& patch, int id, int n_dim){
+    int idx = n_dim*id;
+    for ( int i = 0; i < n_dim; i++ ){
+        center_sum[idx] += *(patch.patch_data + i);
+        idx++;
+    }
+}
+
+// estimates the normalized cross correlation between an image patch and a tree node
+double get_corr(tree_st& tree, im_patch& patch, int node)
+{
+    double corr = 0, tmp_t, tmp_p;
+    int id = tree.n_dim*node;
+    
+    for ( int i = 0; i < tree.n_dim; i++ ){
+        tmp_t = *(tree.tree_data + id);
+        tmp_p = *(patch.patch_data + i);
+        corr += tmp_t*tmp_p;
+        id++;   
+    }
+    
+    return corr;
+}
+
+// k-means-function taking a reference to the vector of image patches and a
+// tree struct as input f and t gives the image patches that should be clustered.
+// node is the first node in the tree included in the clustering
+void k_means( vector<im_patch>& patches, tree_st& tree, int f, int t, int node )
+{
+    // vectors holding the sum of values in the cluster and a vector containing the change
+    vector<double> centSum(tree.branch_fac*tree.n_dim), centChange(tree.branch_fac);
+    vector<int> centCount(tree.branch_fac); // vector for counting the number of points in a cluster
+    double max_corr, corr, tmp, mu, sum;//, diff; // variables for clustering
+    // variables for cluster id and index of previous cluseter, which will be overwritten by new cluster id
+    int id = 0, id_in = patches[f].idx;
+    
+    if ( t-f > tree.branch_fac ){ // check if there are enough point to carry out the clustering
+        // initialize the center positions
+        for (  int i = 0; i < tree.branch_fac; i++ ){
+            set_values(tree, patches[f+i], node+i);
+        }
+        
+        // run clutering for 10 iterations - only little change happens after 10 iterations
+        for ( int n_run = 0; n_run < 10; n_run++){
+            
+            for ( int i = f; i < t; i++ ){ // go through the patches from f to t
+                max_corr = get_corr(tree, patches[i], node); // initially set min distance and id to the first
+                id = 0;
+                for ( int j = 1; j < tree.branch_fac; j++ ){ // run throgh the other points
+                    corr = get_corr(tree, patches[i], node + j); // get the cross correlation
+                    if ( corr > max_corr ){ // if the this cluster is closer set this as max correlation
+                        max_corr = corr;
+                        id = j;
+                    }
+                }
+                add_values(centSum, patches[i], id, tree.n_dim); // add the patch to the closest cluster
+                centCount[id]++; // count the extra patch
+                // update the idx to the child idx - note that all layers start with idx = 0
+                patches[i].idx = (id + id_in*tree.branch_fac);
+            }
+            
+            // update the clusters in the tree and calculate the center change (not used for anything)
+            id = node*tree.n_dim;
+            int id_c = 0;
+            
+            
+            for ( int i = 0; i < tree.branch_fac; i++ ){ // go through all new clusters
+                sum = 0;
+                if ( centCount[i] == 0 ){
+                    centCount[i] = 1;
+                }
+                for ( int j = 0; j < tree.n_dim; j++ ){ // go through cluster pixels
+                    tmp = centSum[id_c]/centCount[i];
+                    //diff = (tmp - *(tree.tree_data + id)); // for calculating center change
+                    //centChange[i] += diff*diff;
+                    *(tree.tree_data + id) = tmp;
+                    sum += tmp;
+                    id_c++;
+                    id++;
+                }
+                mu = sum*tree.inv_ndim;
+                norm_patch(tree.tree_data+id-tree.n_dim, mu, tree.n_dim);
+            }
+            
+            // set counter and sum to zero
+            fill(centSum.begin(), centSum.end(), 0);
+            fill(centCount.begin(), centCount.end(),0);
+            fill(centChange.begin(), centChange.end(), 0);
+        }
+    }
+}
+
+// runs through the patches vector to find the last element with id
+int get_to( vector<im_patch>& patches, int id )
+{
+    int to = 0;
+    for ( int i = 0; i < patches.size(); i++ ){
+        if ( patches[i].idx == id ){
+            to = i;
+        }
+    }
+    return to+1;
+}
+
+// Main function for building the km-tree. Takes the image and tree struct
+// and the number of training patches as argument
+void build_km_tree ( im_st& im, tree_st& tree, int n_train ) {
+    // allocate memory for the image patches
+    double* im_patch_data = new double[n_train*tree.M*tree.M*im.layers];
+    
+    int rows_c = im.rows-tree.M+1, cols_c = im.cols-tree.M+1; // number of rows and cols within sampling area
+    int n_im_patches = rows_c*cols_c; // number of pixels in the image for sampling - inside boundary
+    
+    // checks that the number of training patches is not exceeding the number of pixels in the sample area
+    if ( n_im_patches < n_train ){
+        n_train = n_im_patches;
+    }
+    
+    vector<int> r_id = randperm(n_im_patches, n_train); // indices of random patches
+    
+    vector<im_patch> patches; // vector of image patches
+    patches.resize(n_train); // allocate memory
+    
+    int r, c, idx = 0; // variables used for sampling the image
+    // sample image patches
+    for (int i = 0; i < n_train; i++ )
+    {
+        c = r_id[i]/rows_c; // column is floored because of int
+        r = r_id[i]-c*rows_c; // row is rest after column
+        patches[i].idx = 0; // inital id is 0
+        patches[i].patch_data = im_patch_data + idx; // pointer to patch memory
+        sample_patch(im, tree, patches[i], r + tree.Mh, c + tree.Mh); // sampel in image with added boundary
+        idx += tree.n_dim; // step number of patch pixels forward
+    }
+    
+    // k-means tree
+    int n_layer = (int)ceil(log((double)tree.n_nodes)/log((double)tree.branch_fac)); // number of layers in the tree
+    int n_in_layer; // number of nodes in layer
+    int t, f; // keeps track of patches that belong to a certain cluster
+    int node = 0; // node number that will be updated
+    
+    // go through the layers in the tree
+    for (int i = 0; i < n_layer; i++ )
+    {
+        t = 0; // start at 0
+        n_in_layer = pow((double)tree.branch_fac,i); // number of nodes in current layer of the tree
+        sort(patches.begin(), patches.end()); // sort the patches according to their current id
+        for ( int j = 0; j < n_in_layer; j++ ) // go through the nodes in the layer and cluster that node
+        {
+            f = t; // patch j from
+            t = get_to(patches,j); // patch j to
+            // check that the node does not exceed the size of the tree
+            if ( node + tree.branch_fac <= tree.n_nodes ){
+                k_means( patches, tree, f, t, node );
+            }
+            else {
+                break;
+            }
+            node += tree.branch_fac; // next node
+        }
+    }
+    
+    delete[] im_patch_data; // free up patch memory
+}
+
+
+// The gateway routine
+void mexFunction( int nlhs, mxArray *plhs[],
+        int nrhs, const mxArray *prhs[])
+{
+    // input image (I), patch size (M*M), number of nodes in the tree (n), branching
+    // factor (b), and number of training patches (n_train). Outputs the km-tree (tree)
+    double *I, *tree; // pointers to image and tree
+    int b, M, L, n, ndim, n_train; // variables
+    const int *dim; // image dimensinos
+    int dtree[2]; // tree dimensions
+    
+    /*  Check for proper number of arguments. */
+    /* NOTE: You do not need an else statement when using
+     mexErrMsgTxt within an if statement. It will never
+     get to the else statement if mexErrMsgTxt is executed.
+     (mexErrMsgTxt breaks you out of the MEX-file.)
+     */
+    if(nrhs != 5)
+        mexErrMsgTxt("Five inputs required.");
+    if(nlhs != 1)
+        mexErrMsgTxt("One output required.");
+    
+    // Create a pointer to the input matrix.
+    I = mxGetPr(prhs[0]);
+    
+    // input passing
+    double *Md, *bd, *Ld, *n_train_d;
+    Md = mxGetPr(prhs[1]);
+    M = (int)Md[0];
+    
+    bd = mxGetPr(prhs[2]);
+    b = (int)bd[0];
+    
+    // check if number of clusters is smaller than branching factor
+    if ( n < b ){
+        n = b;
+    }
+    
+    n_train_d = mxGetPr(prhs[3]);
+    n_train = (int)n_train_d[0];
+    
+    // determine number of tree nodes
+    Ld = mxGetPr(prhs[4]);
+    L = (int)Ld[0]; // layers in tree
+    n = 0;
+    int n_tmp = 0;
+    int max_n = (double)n_train/5.0;
+    for ( int i = 0; i < L; i++ ){
+        n_tmp += pow((double)b,(i+1));
+        if ( n_tmp > max_n ){
+            L = i+1;
+            break;
+        }
+        n = n_tmp;
+    }
+    printf("Number of nodes in resulting tree: %d in %d layers.\n", n, L);
+        
+    // check input properties
+    if ( 1 - (M % 2)  || M < 1)
+        mexErrMsgTxt("M must be odd and positive.");
+    
+    if ( n < 1 )
+        mexErrMsgTxt("n must be positive.");
+    
+    if ( b < 1 )
+        mexErrMsgTxt("b must be positive.");
+    
+    // Get the dimensions of the matrix input.
+    ndim = mxGetNumberOfDimensions(prhs[0]);
+    if (ndim != 2 && ndim != 3)
+        mexErrMsgTxt("search_km_tree only works for 2-dimensional or 3-dimensional images.");
+    
+    // image dimensions
+    dim = mxGetDimensions(prhs[0]);
+    
+    
+    // image struct
+    im_st Im;
+    Im.im_data = I;
+    Im.rows = dim[0];
+    Im.cols = dim[1];
+    if ( ndim == 3 )
+    {
+        Im.layers = dim[2];
+    }
+    else
+    {
+        Im.layers = 1;
+    }
+    Im.n_pix = Im.rows*Im.cols;
+    
+    dtree[0] = Im.layers*M*M;
+    dtree[1] = n;
+    
+    // Set the output pointer to the output matrix. Array initialized to zero.
+    plhs[0] = mxCreateNumericArray(2, dtree, mxDOUBLE_CLASS, mxREAL);
+    
+    // Create a C pointer to a copy of the output matrix.
+    tree = mxGetPr(plhs[0]);
+    for (int i = 0; i < dtree[0]*dtree[1]; i++ )
+        *(tree + i) = -1;
+    
+    // tree struct
+    tree_st Tree;
+    Tree.tree_data = tree;
+    Tree.n_dim = dtree[0];
+    Tree.inv_ndim = 1/(double)Tree.n_dim;
+    Tree.n_nodes = dtree[1];
+    Tree.branch_fac = b;
+    Tree.M = M;
+    Tree.Mh = (int)(0.5*((double)M-1.0));
+    // build the km-tree using C++ subroutine
+    build_km_tree ( Im, Tree, n_train );
+    
+}
diff --git a/code/texture_gui/code/functions/build_km_tree_xcorr.mexa64 b/code/texture_gui/code/functions/build_km_tree_xcorr.mexa64
new file mode 100755
index 0000000000000000000000000000000000000000..4f23c01adc36f93d1ea6e2b3a2df0915bac3247f
Binary files /dev/null and b/code/texture_gui/code/functions/build_km_tree_xcorr.mexa64 differ
diff --git a/code/texture_gui/code/functions/build_km_tree_xcorr.mexmaci64 b/code/texture_gui/code/functions/build_km_tree_xcorr.mexmaci64
new file mode 100755
index 0000000000000000000000000000000000000000..592f56e947462978fc07a59c067768e67277fcc6
Binary files /dev/null and b/code/texture_gui/code/functions/build_km_tree_xcorr.mexmaci64 differ
diff --git a/code/texture_gui/code/functions/build_km_tree_xcorr.mexw64 b/code/texture_gui/code/functions/build_km_tree_xcorr.mexw64
new file mode 100755
index 0000000000000000000000000000000000000000..a0b030b73702276a175b4c59a684ad0e0d2e5ff6
Binary files /dev/null and b/code/texture_gui/code/functions/build_km_tree_xcorr.mexw64 differ
diff --git a/code/texture_gui/code/functions/compile_mex_functions.m b/code/texture_gui/code/functions/compile_mex_functions.m
new file mode 100755
index 0000000000000000000000000000000000000000..bab817b10e16d154f102e50dbd6c3311f70f473c
--- /dev/null
+++ b/code/texture_gui/code/functions/compile_mex_functions.m
@@ -0,0 +1,8 @@
+% compile mex files
+mex -largeArrayDims biadjacency_matrix.cpp
+mex build_km_tree.cpp % based on Euclidean distance
+mex search_km_tree.cpp % based on Euclidean distance
+mex build_km_tree_xcorr.cpp % based on normalized cross correlation
+mex search_km_tree_xcorr.cpp % based on normalized cross correlation
+mex probability_search_km_tree.cpp % based on normalized cross correlation
+
diff --git a/code/texture_gui/code/functions/compute_mappings.m b/code/texture_gui/code/functions/compute_mappings.m
new file mode 100755
index 0000000000000000000000000000000000000000..9abe4f73c4c25df190e78ea63377b3ffd8cf7335
--- /dev/null
+++ b/code/texture_gui/code/functions/compute_mappings.m
@@ -0,0 +1,21 @@
+function [mappings,A] = compute_mappings(image,dictionary)
+
+switch dictionary.options.method
+    case 'euclidean'
+        A = search_km_tree(image,...
+            dictionary.tree,...
+            dictionary.options.branching_factor,...
+            dictionary.options.normalization);
+    case 'nxcorr'
+        A = search_km_tree_xcorr(image,...
+            dictionary.tree,...
+            dictionary.options.branching_factor);
+    otherwise
+        error('Unknown dictionary method.')
+end
+B = biadjacency_matrix(A,dictionary.options.patch_size);
+
+[rc,nm] = size(B);
+mappings.T1 = sparse(1:nm,1:nm,1./(sum(B,1)+eps),nm,nm)*B';
+mappings.T2 = sparse(1:rc,1:rc,1./(sum(B,2)+eps),rc,rc)*B;
+
diff --git a/code/texture_gui/code/functions/image_texture_gui.m b/code/texture_gui/code/functions/image_texture_gui.m
new file mode 100755
index 0000000000000000000000000000000000000000..a3145772eb60534de8814ff7da8dc12b3465869c
--- /dev/null
+++ b/code/texture_gui/code/functions/image_texture_gui.m
@@ -0,0 +1,805 @@
+function image_texture_gui(image,dict,nr_labels,labeling)
+%IMAGE_TEXTURE_GUI   Interactive texture segmentation of the image
+% IMAGE_TEXTURE_GUI(IMAGE,DICTOP,NR_LABELS,LABELING)
+% Called without imput arguments starts in a demo mode. Input:
+%   IMAGE, may be rgb or grayscale, 0-to-1 or uint8
+%   DICT, may be either:
+%       - dictopt struct containing dictinary parameters,
+%       - dictionary struct containing the dictionary,
+%       - mappings struct containing the transformation matrices,
+%       - not given or empty, so default options are loaded
+%   NR_LABELS, number of labels, defaults to 2.
+%   LABELING, optional initial labeling, given as either
+%       - binary matrix of the size nr_pixels-by-nr_labels,
+%       - labeling image of the same dimensions as IMAGE
+%
+% Keyboard controls (TODO update this for newest version):
+%   L, shift+L and numerical values change label
+%   T, shift+T, uparrow and downarros change pen thickness
+%   W and shift+W change show option
+%   M and shift+M change method
+%   O and shift+O change overwrite option
+%   R and shift+R change regularize option
+%   U and shift+U change live update option
+%   C and shift+C change colormap
+%   A and shift+A change opacity (alpha)
+%   S saves a project
+%   E export
+%   F freeze
+%
+% Author: vand@dtu.dk, 2015
+% char(100+[18 -3 10 0 -36 0 16 17 -54 0 7])
+%
+% TODO:
+%   - when LABELING given, update segmentation upon startup - DONE, TESTING
+%   - when zooming, make sure mouse overlay circle not displayed (frozen)
+%   - option for changing opacity - DONE, TESTING
+
+%%%%%%%%%% DEFAULTS %%%%%%%%%%
+if nargin<1 % default example image
+    image = imread('bag.png');
+    dict.method = 'euclidean';
+    dict.patch_size = 15;
+    dict.branching_factor = 2;
+    dict.number_layers = 5;
+    dict.number_training_patches = 1000;
+    dict.normalization = false;
+    nr_labels = 2;
+else
+    if nargin<2 || isempty(dict)% default dictionary
+        dict.method = 'euclidean';
+        dict.patch_size = 3;
+        dict.branching_factor = 2;
+        dict.number_layers = 5;
+        dict.number_training_patches = 1000;
+        dict.normalization = false;
+    end
+    if nargin<3 || isempty(nr_labels) % defalult number of labels
+        nr_labels = 2;
+    else
+        nr_labels = double(nr_labels); % for colormaps to work properly
+    end
+end
+
+[r,c,~] = size(image);
+if nargin<4 || isempty(labeling) % default, unlabeled initial labeling
+    LABELING = zeros(r*c,nr_labels);
+else
+    parse_labeling_input(labeling)
+end
+
+%%%%%%%%%% PROBABILITY COMPUTING METHODS %%%%%%%%%%
+% to add a new method, add a function to the method_options list
+method_options = {...
+    @(labeling)distributed(labeling),...
+    @(labeling)two_max(labeling),...
+    @(labeling)two_max_over(labeling),...
+    @(labeling)two_cont(labeling),...
+    @(labeling)two_cont_over(labeling),...
+    };
+
+%%%%%%%%%% SETTINGS %%%%%%%%%%
+
+% method options
+METHOD_INDEX = 1; % initial method is the first on the list
+METHOD = method_options{METHOD_INDEX};
+METHOD_NAME = method_name_str;
+
+% brush label options
+LABEL = 1; % initial label is 1
+
+% brush thickness options
+thickness_options = [1 2 3 4 5 10 20 30 40 50 100 -1]; % last option (value -1) is 'fill'
+thickness_options_string = num2cell(thickness_options);
+thickness_options_string{end} = 'fill';
+THICKNESS_INDEX = 5; % initial pencil thickness is the fifth option
+RADIUS = thickness2radius(thickness_options(THICKNESS_INDEX)); % pencil radius
+
+% results visualization options
+show_options(1:2) = {'segmentation','overlay'};
+show_options((1:nr_labels)+2) = num2cell([repmat('probability ',[nr_labels,1]),num2str((1:nr_labels)')],2);
+SHOW_INDEX = 1;
+
+% overwrite option
+overwrite_options = {'no','yes'};
+OVERWRITE = false; % initialy no overwrite
+
+% regularization (smoothness) options
+regularize_options = [0 1 2 3 4 5 10 15 20 25 30 50];
+REGULARIZE_INDEX = 1; % initialy no regularization
+
+% visualization colormap options (for labelings and results)
+colormap_options = {@(x)[0.5,0.5,0.5;cool(x)], @(x)[0.5,0.5,0.5;spring(x)],...
+    @(x)[0.5,0.5,0.5;parula(x)]}; % gray color for unlabeled
+COLORMAP_INDEX = 1; % current colormap
+COLORS = colormap_options{COLORMAP_INDEX}(nr_labels); % visualization colors for label overlay
+
+% visualization opacity options (for labelings and results)
+color_weight_options = 0.1:0.1:0.9;
+COLOR_WEIGHT_INDEX = 2;
+COLOR_WEIGHT = color_weight_options(COLOR_WEIGHT_INDEX);
+
+% live update option
+live_update_options = {'off','on'};
+LIVE_UPDATE = true; % initially on
+
+% other settings
+nr_circle_pts = 16; % number of points defining a circular pencil
+
+%%%%%%%%%% INITIALIZATION AND LAYOUT %%%%%%%%%%
+
+[image,image_rgb,image_gray] = normalize_image(image); % impose 0-to-1 rgb
+LABELING_OVERLAY = image_rgb; % image overlaid labeling
+SEGMENTATION_OVERLAY = 0.5+zeros(r,c,3); % segmentation, optionally overlay
+
+fmar = [0.2 0.2]; % discance from screen edge to figure (x and y)
+amar = [0.02 0.02]; % margin around axes, relative to figure
+my = 0.85:0.04:0.95; % menu items y position
+mw = 0.15; % menu items width
+mx = 0.05:0.15:0.8;
+mh = 0.03; % menu items height
+cw = (0.25-0.15)/(nr_labels+1); % colorcube width
+cx = 0.15:cw:0.25; % colorcubes x position
+pointer_char = 'X';
+
+fig = figure('Units','Normalized','Position',[fmar,1-2*fmar],...
+    'Pointer','watch','KeyPressFcn',@key_press,'InvertHardCopy', 'off',...
+    'Name','Texture segmentation GUI');
+
+labeling_axes = axes('Units','Normalized','Position',[0,0,0.5,0.85]+[amar,-2*amar]);
+imagesc(LABELING_OVERLAY), axis image off, hold on
+segmentation_axes = axes('Units','Normalized','Position',[0.5,0,0.5,0.85]+[amar,-2*amar]);
+imagesc(SEGMENTATION_OVERLAY,[0,nr_labels]), axis image off, hold on
+
+clean_toolbar % also defines linkaxes tool
+
+uicontrol('String','Label [L] : ','Style','text','HorizontalAlignment','right',...
+    'Units','Normalized','Position',[mx(1),my(3),mw,mh]);
+labels_text = uicontrol('String',num2str(LABEL),...
+    'BackgroundColor',COLORS(LABEL+1,:),...
+    'Style','text','HorizontalAlignment','left',...
+    'Units','Normalized','Position',[mx(2),my(3),0.03,mh]);
+label_pointer = cell(nr_labels+1,1);
+for k = 1:nr_labels+1
+    label_pointer{k} = uicontrol('String',' ','Style','text',...
+        'HorizontalAlignment','center','BackgroundColor',COLORS(k,:),...
+        'Units','Normalized','Position',[cx(k),my(2),cw,mh],...
+        'Enable','Inactive','ButtonDownFcn',@label_click,'UserData',k-1);
+end
+set(label_pointer{LABEL+1},'String',pointer_char);
+
+uicontrol('String','Thickness [T] : ','Style','text','HorizontalAlignment','right',...
+    'Units','Normalized','Position',[mx(1),my(1),mw,mh]);
+thickness_text = uicontrol('String',thickness_options_string(THICKNESS_INDEX),...
+    'Style','text','HorizontalAlignment','left',...
+    'Units','Normalized','Position',[mx(2),my(1),mw,mh]);
+
+uicontrol('String','Show [W] : ','Style','text','HorizontalAlignment','right',...
+    'Units','Normalized','Position',[mx(5),my(2),mw,mh]);
+show_text = uicontrol('String',show_options{SHOW_INDEX},...
+    'Style','text','HorizontalAlignment','left',...
+    'Units','Normalized','Position',[mx(6),my(2),mw,mh]);
+
+uicontrol('String','Live update [U] : ','Style','text','HorizontalAlignment','right',...
+    'Units','Normalized','Position',[mx(5),my(3),mw,mh]);
+update_text = uicontrol('String',live_update_options(LIVE_UPDATE+1),...
+    'Style','text','HorizontalAlignment','left',...
+    'Units','Normalized','Position',[mx(6),my(3),mw,mh]);
+
+uicontrol('String','Method [M] : ','Style','text','HorizontalAlignment','right',...
+    'Units','Normalized','Position',[mx(3),my(3),mw,mh]);
+method_text = uicontrol('String',METHOD_NAME,...
+    'Style','text','HorizontalAlignment','left',...
+    'Units','Normalized','Position',[mx(4),my(3),mw,mh]);
+
+uicontrol('String','Overwrite [O] : ','Style','text','HorizontalAlignment','right',...
+    'Units','Normalized','Position',[mx(3),my(2),mw,mh]);
+overlay_text = uicontrol('String',overwrite_options(OVERWRITE+1),...
+    'Style','text','HorizontalAlignment','left',...
+    'Units','Normalized','Position',[mx(4),my(2),mw,mh]);
+
+uicontrol('String','Regularize [R] : ','Style','text','HorizontalAlignment','right',...
+    'Units','Normalized','Position',[mx(3),my(1),mw,mh]);
+regularize_text = uicontrol('String',regularize_options(REGULARIZE_INDEX),...
+    'Style','text','HorizontalAlignment','left',...
+    'Units','Normalized','Position',[mx(4),my(1),mw,mh]);
+
+drawnow % pointer shows busy system
+
+LIMITS = [1,c-0.5,1,r+0.5]; % to capture zoom
+zoom_handle = zoom(fig);
+pan_handle = pan(fig);
+set(zoom_handle,'ActionPostCallback',@adjust_limits,...
+    'ActionPreCallback',@force_keep_key_press);
+set(pan_handle,'ActionPostCallback',@adjust_limits,...
+    'ActionPreCallback',@force_keep_key_press);
+
+%%%%%%%%%% TEXTURE REPRESENTATION %%%%%%%%%%
+% initiolization: building a texture representation of the image
+T1 = 0;
+T2 = 0;
+parsing_dictionary_input; % T1 and T2 are assigned here
+
+if nargin>3
+    PROBABILITY = METHOD(LABELING);
+else
+    PROBABILITY = 1/nr_labels*ones(size(LABELING));
+    %labeling_overwrite % relevant only if we allow loading all settings
+    %regularize % relevant only if we allow loading all settings
+end
+compute_overlays
+
+% ready to draw
+set(fig,'Pointer','arrow','WindowButtonDownFcn',@start_draw,...
+    'WindowButtonMotionFcn',@pointer_motion);
+XO = []; % current drawing point
+
+show_overlays(get_pixel);
+uiwait % waits with assigning output until a figure is closed
+
+%%%%%%%%%% CALLBACK FUNCTIONS %%%%%%%%%%
+    function key_press(~,object)
+        % keyboard commands
+        key = object.Key;
+        numkey = str2double(key);
+        if ~isempty(numkey) && numkey<=nr_labels;
+            change_label(numkey)
+        else
+            switch key
+                case 'l'
+                    change_label(move_once(LABEL+1,nr_labels+1,...
+                        any(strcmp(object.Modifier,'shift')))-1)
+                case 'uparrow'
+                    THICKNESS_INDEX = move_once(THICKNESS_INDEX,...
+                        numel(thickness_options),false);
+                    RADIUS = thickness2radius(thickness_options(THICKNESS_INDEX));
+                    set(thickness_text,'String',...
+                        thickness_options_string(THICKNESS_INDEX));
+                    show_overlays(get_pixel);
+                case 'downarrow'
+                    THICKNESS_INDEX = move_once(THICKNESS_INDEX,...
+                        numel(thickness_options),true);
+                    RADIUS = thickness2radius(thickness_options(THICKNESS_INDEX));
+                    set(thickness_text,'String',...
+                        thickness_options_string(THICKNESS_INDEX));
+                    show_overlays(get_pixel);
+                case 't'
+                    THICKNESS_INDEX = move_once(THICKNESS_INDEX,...
+                        numel(thickness_options),any(strcmp(object.Modifier,'shift')));
+                    RADIUS = thickness2radius(thickness_options(THICKNESS_INDEX));
+                    set(thickness_text,'String',...
+                        thickness_options_string(THICKNESS_INDEX));
+                    show_overlays(get_pixel);
+                case 'w'
+                    SHOW_INDEX = move_once(SHOW_INDEX,numel(show_options),...
+                        any(strcmp(object.Modifier,'shift')));
+                    set(show_text,'String',show_options{SHOW_INDEX})
+                    compute_overlays
+                    show_overlays(get_pixel);
+                case 'c'
+                    COLORMAP_INDEX = move_once(COLORMAP_INDEX,...
+                        length(colormap_options),...
+                        any(strcmp(object.Modifier,'shift')));
+                    COLORS = colormap_options{COLORMAP_INDEX}(nr_labels);
+                    set(labels_text,'BackgroundColor',COLORS(LABEL+1,:));
+                    for kk = 1:nr_labels+1
+                        set(label_pointer{kk},'BackgroundColor',COLORS(kk,:))
+                    end
+                    compute_overlays
+                    show_overlays(get_pixel);
+                case 'a'
+                    COLOR_WEIGHT_INDEX = move_once(COLOR_WEIGHT_INDEX,...
+                        length(color_weight_options),...
+                        any(strcmp(object.Modifier,'shift')));
+                    COLOR_WEIGHT = color_weight_options(COLOR_WEIGHT_INDEX);
+                    compute_overlays
+                    show_overlays(get_pixel);
+                case 'm'
+                    METHOD_INDEX = move_once(METHOD_INDEX,...
+                        length(method_options),...
+                        any(strcmp(object.Modifier,'shift')));
+                    METHOD = method_options{METHOD_INDEX};
+                    METHOD_NAME = method_name_str;
+                    set(method_text,'String',METHOD_NAME)
+                    PROBABILITY = METHOD(LABELING);
+                    labeling_overwrite
+                    regularize
+                    compute_overlays
+                    show_overlays(get_pixel);
+                case 'o'
+                    OVERWRITE = ~OVERWRITE;
+                    set(overlay_text,'String',overwrite_options{OVERWRITE+1})
+                    PROBABILITY = METHOD(LABELING);
+                    labeling_overwrite
+                    regularize
+                    compute_overlays
+                    show_overlays(get_pixel);
+                case 'u'
+                    LIVE_UPDATE = ~LIVE_UPDATE;
+                    set(update_text,'String',live_update_options{LIVE_UPDATE+1})
+                    if LIVE_UPDATE
+                        PROBABILITY = METHOD(LABELING);
+                        labeling_overwrite
+                        regularize
+                        compute_overlays
+                        show_overlays(get_pixel);
+                    end
+                case 'r'
+                    REGULARIZE_INDEX = move_once(REGULARIZE_INDEX,...
+                        numel(regularize_options),...
+                        any(strcmp(object.Modifier,'shift')));
+                    set(regularize_text,'String',...
+                        regularize_options(REGULARIZE_INDEX))
+                    PROBABILITY = METHOD(LABELING);
+                    labeling_overwrite
+                    regularize
+                    compute_overlays
+                    show_overlays(get_pixel);
+                case 's'
+                    save_displayed
+                case 'e'
+                    export_LS
+                case 'f'
+                    freeze_LS
+                case 'q'
+                    close(fig)
+            end
+        end
+    end
+
+    function label_click(source,~)
+        change_label(source.UserData)
+    end
+
+    function change_label(new_label)
+        set(label_pointer{LABEL+1},'String',' ');
+        LABEL = new_label;
+        set(label_pointer{LABEL+1},'String',pointer_char);
+        set(labels_text,'String',num2str(LABEL),...
+            'BackgroundColor',COLORS(LABEL+1,:));
+    end
+
+    function adjust_limits(~,~)
+        % response to zooming and panning
+        LIMITS([1,2]) = get(labeling_axes,'XLim');
+        LIMITS([3,4]) = get(labeling_axes,'YLim');
+    end
+
+    function force_keep_key_press(~,~)
+        % a hack to maintain my key_press while in zoom and pan mode
+        % http://undocumentedmatlab.com/blog/enabling-user-callbacks-during-zoom-pan
+        hManager = uigetmodemanager(fig);
+        [hManager.WindowListenerHandles.Enabled] = deal(false);
+        set(fig, 'KeyPressFcn', @key_press);
+    end
+
+    function start_draw(~,~)
+        % click in the image
+        x = get_pixel;
+        if is_inside(x)
+            if RADIUS>0 % thickness>0
+                XO = x;
+                M = disc(XO,RADIUS,nr_circle_pts,[r,c]);
+                set(fig,'WindowButtonMotionFcn',@drag_and_draw,...
+                    'WindowButtonUpFcn',@end_draw)
+            else % fill
+                M = fill(x);
+            end
+            update(M);
+        end
+    end
+
+    function drag_and_draw(~,~)
+        % drag after clicking in the image
+        x = get_pixel;
+        M = stadium(XO,x,RADIUS,nr_circle_pts,[r,c]);
+        update(M);
+        XO = x;
+    end
+
+    function end_draw(~,~)
+        % release click after clicking in the image
+        M = stadium(XO,get_pixel,RADIUS,nr_circle_pts,[r,c]);
+        update(M);
+        XO = [];
+        set(fig,'WindowButtonMotionFcn',@pointer_motion,...
+            'WindowButtonUpFcn','')
+    end
+
+    function pointer_motion(~,~)
+        % move around without clicking
+        if strcmp(zoom_handle.Enable,'off') && ...
+                strcmp(pan_handle.Enable,'off') % not zooming or panning
+            x = get_pixel;
+            if is_inside(x)
+                set(fig,'Pointer','crosshair')
+            else
+                set(fig,'Pointer','arrow')
+            end
+            show_overlays(x);
+        end
+    end
+
+%%%%%%%%%% HELPING FUNCTIONS %%%%%%%%%%
+
+    function [L,S] = membership2indexed
+        % computes labeling and segmentation as indexed r-by-c images
+        % from membership r*c-by-nr_labels representation
+        [maxlab,L] = max(LABELING,[],2);
+        L(maxlab==0) = 0;
+        L = uint8(reshape(L,[r,c]));
+        [maxprob,S] = max(PROBABILITY,[],2);
+        S(sum(PROBABILITY==maxprob(:,ones(nr_labels,1)),2)>1) = 0;
+        S = uint8(reshape(S,[r,c]));
+    end
+
+    function save_displayed
+        % saves mat file with user settings and images as separate files
+        [file,path] = uiputfile('settings.mat','Save settings as');
+        if ~isequal(file,0) && ~isequal(path,0)
+            matfile = fullfile(path,file);
+            roothname = matfile(1:find(matfile=='.',1,'last')-1);
+            current_settings.method = METHOD_NAME;
+            current_settings.show = show_options{SHOW_INDEX};
+            current_settings.overwrite = OVERWRITE;
+            current_settings.regularize = regularize_options(REGULARIZE_INDEX);
+            save(matfile,'current_settings')
+            % saving displayed images
+            imwrite(LABELING_OVERLAY,[roothname,'_labels_displayed.png'])
+            imwrite(SEGMENTATION_OVERLAY,[roothname,'_results_displayed.png'])
+            [L,S] = membership2indexed;
+            imwrite(L,COLORS,[roothname,'_labels_indexed.png'])
+            imwrite(S,COLORS,[roothname,'_segmentation_indexed.png'])
+        end
+    end
+
+    function export_LS
+        % saves variables to workspace
+        % TODO, consider using:
+        % export2wsdlg({'Labeling','Segmentation'},{'gui_L','gui_S'},{L,S})
+        button = questdlg({'Exporting variables to the base workspace',...
+            'will close texture segmentation gui and',...
+            'might overwrite existing variables'},...
+            'Exporting variables','OK','Cancel','OK');
+        if strcmp(button,'OK')
+            [L,S] = membership2indexed;
+            [~,dictprob] = METHOD(LABELING);
+            assignin('base','gui_L',L)
+            assignin('base','gui_S',S)
+            assignin('base','gui_dictprob',dictprob)
+            %             assignin('base','gui_dictprob',T1*LABELING)
+        end
+        close(fig)
+    end
+
+    function freeze_LS
+        % feezes, closes and opens segmentation_correction_gui
+        button = questdlg({'Freezing segmentation will close texture segmentation gui',...
+            'and open segmentation correction gui.'},...
+            'Freezing segmentation','OK','Cancel','OK');
+        if strcmp(button,'OK')
+            [L,S] = membership2indexed;
+            close(fig)
+            segmentation_correction_gui(image_rgb,S,nr_labels,L);
+        end
+    end
+
+    function a = is_inside(x)
+        % check if x is inside image limits
+        a = inpolygon(x(1),x(2),LIMITS([1,2,2,1]),LIMITS([3,3,4,4]));
+    end
+
+    function p = get_pixel
+        % get cursor position
+        p = get(labeling_axes,'CurrentPoint');
+        p = round(p(1,[1,2]));
+    end
+
+    function show_overlays(x)
+        % overlay a circular region where the pointer is and show
+        shown_left = LABELING_OVERLAY;
+        shown_right = SEGMENTATION_OVERLAY;
+        if RADIUS>0 % thickness>0
+            P = repmat(disc(x,RADIUS,nr_circle_pts,[r,c]),[1,1,3]);
+            shown_left(P(:)) = 0.5+0.5*LABELING_OVERLAY(P(:));
+            shown_right(P(:)) = 0.5+0.5*SEGMENTATION_OVERLAY(P(:));
+        end
+        % we have to imagesc(shown) to remove overlay if needed
+        axes(labeling_axes), cla, imagesc(shown_left)
+        axes(segmentation_axes), cla, imagesc(shown_right)
+    end
+
+    function update(M)
+        % change the state of the segmentation by updating LABELING with a
+        % mask M, and updating PROBABILITY
+        labcol = zeros(1,nr_labels);
+        if LABEL>0 % not unlabeling
+            labcol(LABEL) = 1;
+        end
+        LABELING(M(:),:) = repmat(labcol,[sum(M(:)),1]);
+        if LIVE_UPDATE
+            PROBABILITY = METHOD(LABELING); % PROBABILITY computed
+            labeling_overwrite
+            regularize
+            compute_overlays(true) % compute both overlays
+        else
+            compute_overlays(false) % comput only left overlay
+        end
+        % computing overlay images
+        show_overlays(get_pixel); % showing overlay and pointer
+    end
+
+    function compute_overlays(compute_both)
+        if nargin<1
+            compute_both = true; % default computes overlay for both images
+        end
+        % computes overlays but not pointer overalay
+        % TODO: a lot of this does not need to be recalculated
+        LABELING_OVERLAY = reshape(LABELING*COLORS(2:end,:),size(image_rgb)).*...
+            (COLOR_WEIGHT+(1-COLOR_WEIGHT)*image_gray);
+        unlabeled = repmat(~any(LABELING,2),[3,1]); % pixels not labeled
+        LABELING_OVERLAY(unlabeled) = image_rgb(unlabeled);
+        if compute_both
+            if SHOW_INDEX<3 % showing segmentation or overlay
+                maxprob = max(PROBABILITY,[],2);
+                maxprobloc = PROBABILITY == maxprob(:,ones(nr_labels,1));
+                uncertain = sum(maxprobloc,2)>1; % pixels with max probability at two or more classes
+                maxprobloc(uncertain,:) = 0;
+                if SHOW_INDEX==1 % segmentation
+                    SEGMENTATION_OVERLAY = reshape([uncertain,maxprobloc]*COLORS,size(image_rgb));
+                else % SHOW_INDEX==2 overlay
+                    SEGMENTATION_OVERLAY = reshape([uncertain,maxprobloc]*COLORS,...
+                        size(image_rgb)).*(COLOR_WEIGHT+(1-COLOR_WEIGHT)*image_gray);
+                end
+            else % 'probability x'
+                pw = SHOW_INDEX-2; % probability to show
+                minpw = min(PROBABILITY(:,pw));
+                maxpw = max(PROBABILITY(:,pw));
+                % TODO scaling should be better, relative to 1/nr_labels
+                SEGMENTATION_OVERLAY = reshape((PROBABILITY(:,pw)-minpw)/(maxpw-minpw)*[1,1,1],size(image_rgb));
+            end
+        end
+    end
+
+% TODO disc shold be saved as a list of index shifts with respect to
+% the central pixel, and change only when thickness changes
+    function M = disc(x,r,N,dim)
+        % disc shaped mask in the image
+        angles = (0:2*pi/N:2*pi*(1-1/N));
+        X = x(1)+r*cos(angles);
+        Y = x(2)+r*sin(angles);
+        M = poly2mask(X,Y,dim(1),dim(2));
+    end
+
+    function M = stadium(x1,x2,r,N,dim)
+        % stadium shaped mask in the image
+        angles = (0:2*pi/N:pi)-atan2(x1(1)-x2(1),x1(2)-x2(2));
+        X = [x1(1)+r*cos(angles), x2(1)+r*cos(angles+pi)];
+        Y = [x1(2)+r*sin(angles), x2(2)+r*sin(angles+pi)];
+        M = poly2mask(X,Y,dim(1),dim(2));
+    end
+
+    function M = fill(x)
+        [maxL,labL] = max(LABELING,[],2);
+        label_image = reshape(maxL.*labL,[r,c]);
+        M = bwselect(label_image==label_image(x(2),x(1)),x(1),x(2),4);
+    end
+
+    function [I,I_rgb,I_gray] = normalize_image(I)
+        % initialization: normalize image
+        if isa(I,'uint8')
+            I = double(I)/255;
+        end
+        if isa(I,'uint16')
+            I = double(I)/65535;
+        end
+        if size(I,3)==3 % rgb image
+            I_gray = repmat(rgb2gray(I),[1 1 3]);
+            I_rgb = I;
+        else % assuming grayscale image
+            I_gray = repmat(I,[1,1,3]);
+            I_rgb = I_gray;
+        end
+    end
+
+    function name = method_name_str
+        method_str = func2str(METHOD);
+        s1 = find(method_str==')',1,'first')+1;
+        s2 = find(method_str=='(',1,'last')-1;
+        name = method_str(s1:s2);
+    end
+
+    function n = move_once(n,total,reverse)
+        % moves option index once, respecting total number of options
+        if ~reverse
+            n = mod(n,total)+1;
+        else
+            n = mod(n+total-2,total)+1;
+        end
+    end
+
+    function labeling_overwrite
+        % labeled areas get assigned probability 1
+        if OVERWRITE
+            labeled = any(LABELING,2);
+            PROBABILITY(labeled,:) = LABELING(labeled,:); % overwritting labeled
+        end
+    end
+
+    function regularize
+        sigma = regularize_options(REGULARIZE_INDEX);
+        if sigma>0
+            filter = fspecial('gaussian',[2*ceil(sigma)+1,1],sigma);
+            PROBABILITY = reshape(PROBABILITY,[r,c,nr_labels]);
+            PROBABILITY = imfilter(PROBABILITY,filter,'replicate');
+            PROBABILITY = imfilter(PROBABILITY,filter','replicate');
+            PROBABILITY = reshape(PROBABILITY,[r*c,nr_labels]);
+        end
+    end
+
+    function r = thickness2radius(t)
+        r = t/2+0.4;
+    end
+
+    function clean_toolbar
+        set(fig,'MenuBar','none','Toolbar','figure');
+        toolbar = findall(fig,'Type','uitoolbar');
+        all_tools = allchild(toolbar);
+        % removing tools
+        for i=1:numel(all_tools)
+            if isempty(strfind(all_tools(i).Tag,'Pan'))&&...
+                    isempty(strfind(all_tools(i).Tag,'Zoom'))&&...
+                    isempty(strfind(all_tools(i).Tag,'SaveFigure'))&&...
+                    isempty(strfind(all_tools(i).Tag,'PrintFigure'))&&...
+                    isempty(strfind(all_tools(i).Tag,'DataCursor'))
+                delete(all_tools(i)) % keeping only Pan, Zoom, Save and Print
+            end
+        end
+        % adding a tool
+        [icon,~,alpha] = imread('linkaxesicon.png');
+        icon = double(icon)/255;
+        icon(alpha==0)=NaN;
+        uitoggletool(toolbar,'CData',icon,...
+            'TooltipString','Link Axes','Tag','LinkAxes',...
+            'OnCallback',{@link_axes,'xy'},...
+            'OffCallback',{@link_axes,'off'});
+        % changing the order of tools
+        all_tools = allchild(toolbar);
+        set(toolbar,'children',all_tools([2,1,3:end]));
+    end
+
+    function link_axes(~,~,flag)
+        linkaxes([labeling_axes,segmentation_axes],flag)
+    end
+
+    function parsing_dictionary_input
+        % either dictionary_options, dictionary or mappings should be given
+        if isfield(dict,'patch_size') % dictionary options given
+            dictionary = build_dictionary(image,dict);
+            mappings = compute_mappings(image,dictionary);
+            T1 = mappings.T1;
+            T2 = mappings.T2;
+        elseif isfield(dict,'tree')% dictinary given
+            mappings = compute_mappings(image,dict);
+            T1 = mappings.T1;
+            T2 = mappings.T2;
+        elseif isfield(dict,'T1')% mapping given
+            T1 = dict.T1;
+            T2 = dict.T2;
+        else
+            error('Could not parse dictionary input.')
+        end
+    end
+
+    function parse_labeling_input(labeling)
+        % parsing labeling input, either labeling or labeling image
+        dim_l = size(labeling);
+        labeling = double(labeling);
+        if numel(dim_l)==3 %% rgb labeling image, to be turned to 2D image
+            max_l = max(labeling(:))+1;
+            labeling = labeling(:,:,1)+max_l*labeling(:,:,2)+max_l^2*labeling(:,:,3);
+            dim_l = size(labeling);
+        end
+        if numel(dim_l)==2 % either LABELING or 2D labeling image
+            if all(dim_l==[r*c,nr_labels]) % LABELING
+                LABELING = labeling;
+            elseif all(dim_l==[r,c]) % labeling image
+                l = unique(labeling(:)); % present labels
+                if numel(union(l,0:nr_labels))~=nr_labels+1
+                    labeling_old = labeling;
+                    for li = 1:numel(l)
+                        labeling(labeling_old==l(li)) = li-1;
+                    end
+                end
+                % now we have labels from 0 to nr_labels
+                i = (labeling(:)-1)*r*c + (1:r*c)'; % indices in LABELINGS
+                i = i(labeling(:)>0); % only labeled parts
+                LABELING = zeros(r*c,nr_labels);
+                LABELING(i) = 1;
+            else
+                error('Could not parse labeling input.')
+            end
+        else
+            error('Could not parse labeling input.')
+        end
+    end
+
+%%%%%%%%%% LABELINGS TO PROBABILITIES METHODS %%%%%%%%%%
+
+    function [probabilities,dictprob] = distributed(labelings)
+        % unlabeled pixels have label weights DISTRIBUTED equally
+        labelings(~any(labelings,2),:) = 1/nr_labels; % distributing
+        dictprob = T1*labelings;
+        probabilities = T2*dictprob; % computing probabilities
+    end
+
+    function [probabilities,dictprob] = two_max(labelings)
+        % DISTRIBUTED tresholded and repeated
+        labelings(~any(labelings,2),:) = 1/nr_labels; % distributing
+        probabilities = T2*(T1*labelings); % probabilities
+        maxprob = max(probabilities,[],2); % finding max probabilities
+        labelings_new = probabilities == maxprob(:,ones(nr_labels,1)); % new labeling is where max prob was
+        uncertain = sum(labelings_new,2)>1; % pixels with max probability at two or more classes
+        labelings_new(uncertain,:) = 1/nr_labels; % distributing at uncertain
+        dictprob = T1*labelings_new;
+        probabilities = T2*dictprob;
+    end
+
+    function [probabilities,dictprob] = two_max_over(labelings)
+        % DISTRIBUTED tresholded, overwriten and repeated
+        known_labels = any(labelings,2);
+        labelings(~known_labels,:) = 1/nr_labels; % distributing
+        probabilities = T2*(T1*labelings); % probabilities
+        maxprob = max(probabilities,[],2); % finding max probabilities
+        labelings_new = probabilities == maxprob(:,ones(nr_labels,1)); % new labeling is where max prob was
+        uncertain = sum(labelings_new,2)>1; % pixels with max probability at two or more classes
+        labelings_new(uncertain,:) = 1/nr_labels; % distributing at uncertain
+        labelings_new(known_labels,:) = labelings(known_labels,:); % OVERWRITING
+        dictprob = T1*labelings_new;
+        probabilities = T2*dictprob;
+    end
+
+    function [probabilities,dictprob] = two_cont(labelings)
+        % DISTRIBUTED repeated
+        labelings(~any(labelings,2),:) = 1/nr_labels; % distributing
+        labelings_new = T2*(T1*labelings); % probabilities
+        dictprob = T1*labelings_new;
+        probabilities = T2*dictprob;
+    end
+
+    function [probabilities,dictprob] = two_cont_over(labelings)
+        % DISTRIBUTED overwriten and repeated
+        known_labels = any(labelings,2);
+        labelings(~known_labels,:) = 1/nr_labels; % distributing
+        labelings_new = T2*(T1*labelings); % probabilities
+        labelings_new(known_labels,:) = labelings(known_labels,:); % OVERWRITING
+        dictprob = T1*labelings_new;
+        probabilities = T2*dictprob;
+    end
+
+%     function probabilities = normalized(labelings)
+%         probabilities = T2*(T1*labelings); % computing probabilities
+%         % normalizing probabilities so that they sum to 1
+%         probabilities = probabilities./repmat(sum(probabilities,2),[1,size(probabilities,2)]);
+%         probabilities(isnan(probabilities)) = 0;
+%     end
+%
+%     function probabilities = normalized_2_max(labelings)
+%         probabilities = T2*(T1*labelings); % probabilities
+%         maxprob = max(probabilities,[],2); % finding max probabilities
+%         labelings_new = probabilities == maxprob(:,ones(nr_labels,1)); % new labeling is where max prob was
+%         uncertain = sum(labelings_new,2)>1; % pixels with max probability at two or more classes
+%         labelings_new(uncertain,:) = 0; % zero at uncertain
+%         probabilities = T2*(T1*labelings_new);
+%         probabilities = probabilities./repmat(sum(probabilities,2),[1,size(probabilities,2)]);
+%         probabilities(isnan(probabilities)) = 0;
+%     end
+%
+%     function probabilities = normalized_2_cont(labelings)
+%         labelings_new = T2*(T1*labelings); % probabilities
+%         probabilities = T2*(T1*labelings_new);
+%         probabilities = probabilities./repmat(sum(probabilities,2),[1,size(probabilities,2)]);
+%         probabilities(isnan(probabilities)) = 0;
+%     end
+
+end
diff --git a/code/texture_gui/code/functions/linkaxesicon.png b/code/texture_gui/code/functions/linkaxesicon.png
new file mode 100755
index 0000000000000000000000000000000000000000..f1c1759a401c8c3cc0dbbb158860bcb9e18ab4ae
Binary files /dev/null and b/code/texture_gui/code/functions/linkaxesicon.png differ
diff --git a/code/texture_gui/code/functions/normalize_image.m b/code/texture_gui/code/functions/normalize_image.m
new file mode 100755
index 0000000000000000000000000000000000000000..8dd729f89488dfc3714d2fb55c1fc88dcdde0360
--- /dev/null
+++ b/code/texture_gui/code/functions/normalize_image.m
@@ -0,0 +1,9 @@
+function I = normalize_image(I)
+% we work with [0 1] images
+if isa(I,'uint8')
+    I = double(I)/255;
+end
+if isa(I,'uint16')
+    I = double(I)/65535;
+end
+end
\ No newline at end of file
diff --git a/code/texture_gui/code/functions/probability_search_km_tree.cpp b/code/texture_gui/code/functions/probability_search_km_tree.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..489281bd1148ea5b59977876e996ea9e822744a9
--- /dev/null
+++ b/code/texture_gui/code/functions/probability_search_km_tree.cpp
@@ -0,0 +1,305 @@
+/*=================================================================
+* syntax: Q = probability_search_km_tree(I, T, P, b, n); OR Q = search_km_tree(I, T, P, b);
+*
+* serach_km_tree  - build probability image from dictionary and intensity image
+* 			
+* 			Input: 	- I: X-by-Y image
+* 					- T: MMl-by-K tree matrix where l is the number of layers 
+*                        in the image (1 for grayscale and 3 for RGB)
+                    - P: MMc-by-K probability matrix where c is the number of 
+                         classes
+*                   - b: branching factor
+*                   - n: normalization (true or false), defaults to false
+*
+* 			Output: - Q: X-by-Y-by-c probability image
+*
+* 			Author: Anders Dahl, abda@dtu.dk, February 2016.
+*=================================================================*/
+
+#include "mex.h"
+#include <stdio.h>
+#include <math.h>
+#include "matrix.h"
+#include <vector>
+
+#include <iostream>
+using namespace std;
+
+// struct for the tree
+struct tree_st
+{
+    double *tree_data;
+    double *probability_data;
+    int n_dim, n_dprob, n_nodes, branch_fac, M, Mh, n_cls;
+    vector<int> idx_disp;
+};
+
+// struct for image
+struct im_st
+{
+    double *im_data;
+    int rows, cols, layers, n_pix;
+};
+
+// estimate the distance between a vector in tree given by the node and a 
+// patch in the image given by the row and column
+double get_dist(vector<double>& patch, tree_st& tree, int& node)
+{
+    double d = 0, tmp;
+    int id_t = tree.n_dim*node;
+    
+    for ( int i = 0; i < tree.n_dim; i++ ){
+        tmp = patch[i] - *(tree.tree_data + id_t);
+        id_t++;
+        d += tmp*tmp;
+    }
+    
+    return d;
+}
+
+
+// Function for sampling patches from the image into the patch arrays
+// inputs reference to the image struct, tree struct, patch struct and position of the sampling coordinate.
+// There is no check if the sampling is outside the image
+// vector<double> sample_patch(im_st& im, int& M, int r_im, int c_im, bool& normalize)
+vector<double> sample_patch(im_st& im, int& M, int r_im, int c_im, bool& normalize)
+{
+    int id_l, id_r, id_i; // iterators for looking up image data
+    int id_p = 0; // iterator for looking up patch data
+    double sum_sq = 0, pix_val; // variables for normalization
+    int n_dim = M*M*im.layers; // number of dimensions computed here, becasue tree is not included
+    vector<double> patch(n_dim);
+    int Mh = (M-1)/2;
+    
+    for ( int l = 0; l < im.layers; l++ ){ // image is sampled by three nested loops (layers, columns, rows)
+        id_l = im.n_pix*l;
+        for ( int i = c_im-Mh; i <= c_im+Mh; i++ ){
+            id_r = id_l + i*im.rows;
+            for ( int j = r_im-Mh; j <= r_im+Mh; j++ ){
+                id_i = id_r + j;
+                pix_val = *(im.im_data + id_i);
+                patch[id_p] = pix_val;
+                sum_sq += pix_val*pix_val; // sum of squares for normalization
+                id_p++;
+            }
+        }
+    }
+    if ( normalize ){ // if the patch should be normalized to unit length
+        double inv_sq = 1;
+        if ( sum_sq > 0 ){
+            inv_sq = 1/sqrt(sum_sq); // inverse sum of squares
+        }
+        for ( int i = 0; i < n_dim; i++ ){
+            patch[i] = patch[i]*inv_sq;
+        }
+    }
+    return patch;
+}
+
+
+// The tree search function
+int search_tree(im_st& im, tree_st& tree, int& r, int& c, bool& normalize)
+{
+    int node = 0, node_min = -1, node_min_level, next_node; // variables for searching the tree
+    double d_min = 10e100, d, d_min_level; 
+    
+    vector<double> patch = sample_patch(im, tree.M, c, r, normalize); // get the pixel values in a patch
+    while ( node < tree.n_nodes ){ // go through the tree
+        if ( *(tree.tree_data + node*tree.n_dim) == -1 ){ // check if node is a leaf-node
+            return node_min;
+        }
+        
+        d_min_level = 10e100; // set minimum distance to high value
+        for ( int i = 0; i < tree.branch_fac; i++ ){ // go through nodes at level 
+            next_node = node + i;
+            d = get_dist(patch, tree, next_node);
+            
+            if ( d < d_min_level ){ // set current node to the minimum distance
+                d_min_level = d;
+                node_min_level = next_node;
+            }
+        }
+        if ( d_min_level < d_min ){ // set overall minimum distance and minimum node
+            d_min = d_min_level;
+            node_min = node_min_level;
+        }
+        node = (node_min_level+1)*tree.branch_fac; // go to the child node
+    }
+    return node_min;
+}
+
+void add_probability(tree_st& tree, double *Q, int& idx, int& node){
+    int id_node = node*tree.n_dprob;
+    for ( int i = 0; i < tree.idx_disp.size(); i++ ){
+        *(Q + idx + tree.idx_disp[i]) += *(tree.probability_data + id_node + i);
+    }
+}
+
+
+void add_count(vector<int>& ct_im, int& col, int& row, int& rows, tree_st& tree){
+    for ( int i = col-tree.Mh; i <= col+tree.Mh; i++ ){
+        for ( int j = row-tree.Mh; j <= row+tree.Mh; j++ ){
+            ct_im[i*rows+j]++;
+        }
+    }
+}
+
+// The tree search function applied to the entire image - border is zero and interior is in 1,...,n
+void probability_search_image(im_st& im, tree_st& tree, double *Q, bool& normalize)
+{
+    vector<int> ct_im;
+    ct_im.resize(im.rows*im.cols);
+    int node;
+    int idx = tree.Mh*im.rows; // increase with empty rows at border
+    for ( int i = tree.Mh; i < im.cols-tree.Mh; i++ ){
+        idx += tree.Mh; // first Mh pixels are border
+        for ( int j = tree.Mh; j < im.rows-tree.Mh; j++ ){           
+            node = search_tree(im, tree, i, j, normalize); // find assignment
+            add_probability(tree, Q, idx, node);
+            idx++;
+            add_count(ct_im, i, j, im.rows, tree);
+        }
+        idx += tree.Mh; // last Mh pixels are border
+    }
+    
+    int l_id;
+    for ( int j = 0; j < tree.n_cls; j++) {
+        l_id = j*im.rows*im.cols;
+        for ( int i = 0; i < ct_im.size(); i++ ){
+            *(Q+i+l_id) = *(Q+i+l_id)/(double)ct_im[i];
+        }
+    }
+}
+
+
+// The gateway routine 
+void mexFunction( int nlhs, mxArray *plhs[],
+                  int nrhs, const mxArray *prhs[])
+{
+  // input image (I), tree (tree), probabilities (P) and output probabilities (Q)
+  double *I, *tree, *P, *Q;
+  int b, M, ndim, ndtree, ndprob;
+  const int *dim, *dtree, *dprob;
+  bool normalize = false;
+  /*  Check for proper number of arguments. */
+  /* NOTE: You do not need an else statement when using
+     mexErrMsgTxt within an if statement. It will never
+     get to the else statement if mexErrMsgTxt is executed.
+     (mexErrMsgTxt breaks you out of the MEX-file.) 
+  */
+  if(nrhs < 4 || nrhs > 5) 
+    mexErrMsgTxt("Four or five inputs required.");
+  if(nlhs != 1) 
+    mexErrMsgTxt("One output required.");
+    
+  // Create a pointer to the input matrix.
+  I = mxGetPr(prhs[0]);
+  tree = mxGetPr(prhs[1]);
+  P = mxGetPr(prhs[2]);
+  
+  double *bd;
+  bd = mxGetPr(prhs[3]);
+  b = (int)bd[0];
+  
+  if ( nrhs == 5 ){
+      bool *normalize_d;
+      normalize_d = (bool *)mxGetData(prhs[4]);
+      normalize = normalize_d[0];
+  }
+  
+  if ( b < 1 )
+    mexErrMsgTxt("b must be positive.");
+  
+  // Get the dimensions of the matrix input.
+  ndim = mxGetNumberOfDimensions(prhs[0]);
+  if (ndim != 2 && ndim != 3)
+    mexErrMsgTxt("probability_search_km_tree only works for 2-dimensional or 3-dimensional images.");
+
+  ndtree = mxGetNumberOfDimensions(prhs[1]);
+  if (ndtree != 2)
+    mexErrMsgTxt("probability_search_km_tree requires tree to be a matrix (2-dimensional).");
+
+  ndprob = mxGetNumberOfDimensions(prhs[2]);
+  if (ndprob != 2)
+    mexErrMsgTxt("probability_search_km_tree requires probability matrix to be a matrix (2-dimensional).");
+
+  dim = mxGetDimensions(prhs[0]);
+  dtree = mxGetDimensions(prhs[1]);
+  dprob = mxGetDimensions(prhs[2]);
+  
+  if ( dtree[1] != dprob[1] )
+    mexErrMsgTxt("Tree matrix and probability matrix must have the same number of columns.");
+  
+  if ( ndim == 3 )
+  {
+      M = (int)sqrt((double)dtree[0]/(double)dim[2]);
+  }
+  else
+  {
+      M = (int)sqrt((double)dtree[0]);
+  }
+  
+  if ( 1 - (M % 2)  || M < 1)
+    mexErrMsgTxt("M must be odd and positive.");
+  
+  
+  // image struct
+  im_st Im;
+  Im.im_data = I;
+  Im.rows = dim[0];
+  Im.cols = dim[1];
+  if ( ndim == 3 )
+  {
+      Im.layers = dim[2];
+  }
+  else
+  {
+      Im.layers = 1;
+  }
+  Im.n_pix = Im.rows*Im.cols;
+
+  // tree struct
+  tree_st Tree;
+  Tree.tree_data = tree;
+  Tree.probability_data = P;
+  Tree.n_dim = dtree[0];
+  Tree.n_nodes = dtree[1];
+  Tree.n_dprob = dprob[0];
+  Tree.branch_fac = b;
+  Tree.M = M;
+  Tree.Mh = (int)(0.5*(double)(M-1.0));
+  // Number of classes
+  Tree.n_cls = dprob[0]/(M*M);
+  // Compute relative displacement vector
+  Tree.idx_disp.reserve(dprob[0]);
+  int id;
+  for ( int k = 0; k < Tree.n_cls; k++ ){
+      id = -Tree.Mh*Im.rows - Tree.Mh + k*Im.rows*Im.cols;
+      for ( int i = 0; i < M; i++ ){
+          for ( int j = 0; j < M; j++ ){
+              Tree.idx_disp.push_back(id);
+              id++;
+          }
+      id+=Im.rows-M;
+      }
+  }
+//   for ( int i = 0; i < Tree.idx_disp.size(); i++ ){
+//       cout << Tree.idx_disp[i] << " ";
+//   }
+//   cout << endl;
+
+  
+  if ( M*M*Im.layers != Tree.n_dim )
+    mexErrMsgTxt("Dimensions of the tree and the image does not fit.");
+  
+  int ndpout[3] = {Im.rows, Im.cols, Tree.n_cls};
+  
+  // Set the output pointer to the output matrix. Array initialized to zero. 
+  plhs[0] = mxCreateNumericArray(3, ndpout, mxDOUBLE_CLASS, mxREAL);
+  
+  // Create a C pointer to a copy of the output matrix.
+  Q = mxGetPr(plhs[0]);
+  // Search the tree using the C++ subroutine
+  probability_search_image(Im, Tree, Q, normalize);
+}
+
diff --git a/code/texture_gui/code/functions/probability_search_km_tree.mexa64 b/code/texture_gui/code/functions/probability_search_km_tree.mexa64
new file mode 100755
index 0000000000000000000000000000000000000000..80a9ec4cb9d02af3b31b2d1b6f0df54720cd8d27
Binary files /dev/null and b/code/texture_gui/code/functions/probability_search_km_tree.mexa64 differ
diff --git a/code/texture_gui/code/functions/probability_search_km_tree.mexmaci64 b/code/texture_gui/code/functions/probability_search_km_tree.mexmaci64
new file mode 100755
index 0000000000000000000000000000000000000000..86ce9e57e1823c0b786e2bedbfb5a8fbdd0aada4
Binary files /dev/null and b/code/texture_gui/code/functions/probability_search_km_tree.mexmaci64 differ
diff --git a/code/texture_gui/code/functions/probability_search_km_tree.mexw64 b/code/texture_gui/code/functions/probability_search_km_tree.mexw64
new file mode 100755
index 0000000000000000000000000000000000000000..14ed3e6c6fea7689c9c02ffc4a86221931b35546
Binary files /dev/null and b/code/texture_gui/code/functions/probability_search_km_tree.mexw64 differ
diff --git a/code/texture_gui/code/functions/process_image.m b/code/texture_gui/code/functions/process_image.m
new file mode 100755
index 0000000000000000000000000000000000000000..6dce460669eb429803cf9132fe20e5957ae30045
--- /dev/null
+++ b/code/texture_gui/code/functions/process_image.m
@@ -0,0 +1,16 @@
+function [S,P] = process_image(im,dictionary)
+% segmentation and probabilities from and image and a dictionary
+
+im = normalize_image(im);
+P = probability_search_km_tree(im, ...
+    dictionary.tree, ...
+    dictionary.dictprob, ...
+    dictionary.options.branching_factor, ...
+    dictionary.options.normalization);
+
+[maxprob,S] = max(P,[],3);
+uncertain = sum(P == maxprob(:,:,ones(size(P,3),1)),3)>1; 
+S(uncertain) = 0;
+
+end
+
diff --git a/code/texture_gui/code/functions/search_km_tree.cpp b/code/texture_gui/code/functions/search_km_tree.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..3b9fcbcb4adc6a2c885724f29f1dcdc24fcbd425
--- /dev/null
+++ b/code/texture_gui/code/functions/search_km_tree.cpp
@@ -0,0 +1,239 @@
+/*=================================================================
+* syntax: A = search_km_tree(I, T, b, n); OR A = search_km_tree(I, T, b);
+*
+* serach_km_tree  - build assignment image from intensity image
+* 			
+* 			Input: 	- I: X-by-Y image
+* 					- T: MMl-by-K tree matrix  where l is the number of layers 
+*                        in the image (1 for grayscale and 3 for RGB)
+*                   - b: brancing factor
+*                   - n: normalization (true or false), defaults to false
+*
+* 			Output: - A: X-by-Y assignment matrix
+*
+* 			Author: Anders Dahl, abda@dtu.dk, december 2015.
+*=================================================================*/
+
+#include "mex.h"
+#include <stdio.h>
+#include <math.h>
+#include "matrix.h"
+#include <vector>
+
+#include <iostream>
+using namespace std;
+
+// struct for the tree
+struct tree_st
+{
+    double *tree_data;
+    int n_dim, n_nodes, branch_fac, M, Mh;
+};
+
+// struct for image
+struct im_st
+{
+    double *im_data;
+    int rows, cols, layers, n_pix;
+};
+
+// estimate the distance between a vector in tree given by the node and a 
+// patch in the image given by the row and column
+double get_dist(vector<double>& patch, tree_st& tree, int& node)
+{
+    double d = 0, tmp;
+    int id_t = tree.n_dim*node;
+    
+    for ( int i = 0; i < tree.n_dim; i++ ){
+        tmp = patch[i] - *(tree.tree_data + id_t);
+        id_t++;
+        d += tmp*tmp;
+    }
+    
+    return d;
+}
+
+
+// Function for sampling patches from the image into the patch arrays
+// inputs reference to the image struct, tree struct, patch struct and position of the sampling coordinate.
+// There is no check if the sampling is outside the image
+// vector<double> sample_patch(im_st& im, int& M, int r_im, int c_im, bool& normalize)
+vector<double> sample_patch(im_st& im, int& M, int r_im, int c_im, bool& normalize)
+{
+    int id_l, id_r, id_i; // iterators for looking up image data
+    int id_p = 0; // iterator for looking up patch data
+    double sum_sq = 0, pix_val; // variables for normalization
+    int n_dim = M*M*im.layers; // number of dimensions computed here, becasue tree is not included
+    vector<double> patch(n_dim);
+    int Mh = (M-1)/2;
+    
+    for ( int l = 0; l < im.layers; l++ ){ // image is sampled by three nested loops (layers, columns, rows)
+        id_l = im.n_pix*l;
+        for ( int i = c_im-Mh; i <= c_im+Mh; i++ ){
+            id_r = id_l + i*im.rows;
+            for ( int j = r_im-Mh; j <= r_im+Mh; j++ ){
+                id_i = id_r + j;
+                pix_val = *(im.im_data + id_i);
+                patch[id_p] = pix_val;
+                sum_sq += pix_val*pix_val; // sum of squares for normalization
+                id_p++;
+            }
+        }
+    }
+    if ( normalize ){ // if the patch should be normalized to unit length
+        double inv_sq = 1;
+        if ( sum_sq > 0 ){
+            inv_sq = 1/sqrt(sum_sq); // inverse sum of squares
+        }
+        for ( int i = 0; i < n_dim; i++ ){
+            patch[i] = patch[i]*inv_sq;
+        }
+    }
+    return patch;
+}
+
+
+// The tree search function
+int search_tree(im_st& im, tree_st& tree, int& r, int& c, bool& normalize)
+{
+    int node = 0, node_min = -1, node_min_level, next_node; // variables for searching the tree
+    double d_min = 10e100, d, d_min_level; 
+    
+    vector<double> patch = sample_patch(im, tree.M, c, r, normalize); // get the pixel values in a patch
+    while ( node < tree.n_nodes ){ // go through the tree
+        if ( *(tree.tree_data + node*tree.n_dim) == -1 ){ // check if node is a leaf-node
+            return node_min;
+        }
+        
+        d_min_level = 10e100; // set minimum distance to high value
+        for ( int i = 0; i < tree.branch_fac; i++ ){ // go through nodes at level 
+            next_node = node + i;
+            d = get_dist(patch, tree, next_node);
+            
+            if ( d < d_min_level ){ // set current node to the minimum distance
+                d_min_level = d;
+                node_min_level = next_node;
+            }
+        }
+        if ( d_min_level < d_min ){ // set overall minimum distance and minimum node
+            d_min = d_min_level;
+            node_min = node_min_level;
+        }
+        node = (node_min_level+1)*tree.branch_fac; // go to the child node
+    }
+    return node_min;
+}
+
+// The tree search function applied to the entire image - border is zero and interior is in 1,...,n
+void search_image(im_st& im, tree_st& tree, double *A, bool& normalize)
+{
+    int idx = tree.Mh*im.rows; // increase with empty rows at border
+    for ( int i = tree.Mh; i < im.cols-tree.Mh; i++ ){
+        idx += tree.Mh; // first Mh pixels are border
+        for ( int j = tree.Mh; j < im.rows-tree.Mh; j++ ){           
+            *(A + idx) = search_tree(im, tree, i, j, normalize) + 1; // find assignment
+            idx++;
+        }
+        idx += tree.Mh; // last Mh pixels are border
+    }
+}
+
+
+// The gateway routine 
+void mexFunction( int nlhs, mxArray *plhs[],
+                  int nrhs, const mxArray *prhs[])
+{
+  // input image (I), tree (tree) and output assignment (A)
+  double *I, *A, *tree;
+  int b, M, ndim, ndtree;
+  const int *dim, *dtree;
+  bool normalize = false;
+  /*  Check for proper number of arguments. */
+  /* NOTE: You do not need an else statement when using
+     mexErrMsgTxt within an if statement. It will never
+     get to the else statement if mexErrMsgTxt is executed.
+     (mexErrMsgTxt breaks you out of the MEX-file.) 
+  */
+  if(nrhs < 3 || nrhs > 4) 
+    mexErrMsgTxt("Three or four inputs required.");
+  if(nlhs != 1) 
+    mexErrMsgTxt("One output required.");
+    
+  // Create a pointer to the input matrix.
+  I = mxGetPr(prhs[0]);
+  tree = mxGetPr(prhs[1]);
+  
+  double *bd;
+  bd = mxGetPr(prhs[2]);
+  b = (int)bd[0];
+  
+  if ( nrhs == 4 ){
+      bool *normalize_d;
+      normalize_d = (bool *)mxGetData(prhs[3]);
+      normalize = normalize_d[0];
+  }
+  
+  if ( b < 1 )
+    mexErrMsgTxt("b must be positive.");
+  
+  // Get the dimensions of the matrix input.
+  ndim = mxGetNumberOfDimensions(prhs[0]);
+  if (ndim != 2 && ndim != 3)
+    mexErrMsgTxt("search_km_tree only works for 2-dimensional or 3-dimensional images.");
+
+  ndtree = mxGetNumberOfDimensions(prhs[1]);
+  if (ndtree != 2)
+    mexErrMsgTxt("search_km_tree only works for 2-dimensional tree.");
+
+  dim = mxGetDimensions(prhs[0]);
+  dtree = mxGetDimensions(prhs[1]);
+  
+  if ( ndim == 3 )
+  {
+      M = (int)sqrt((double)dtree[0]/(double)dim[2]);
+  }
+  else
+  {
+      M = (int)sqrt((double)dtree[0]);
+  }
+  
+  if ( 1 - (M % 2)  || M < 1)
+    mexErrMsgTxt("M must be odd and positive.");
+  
+  
+  // tree struct
+  tree_st Tree;
+  Tree.tree_data = tree;
+  Tree.n_dim = dtree[0];
+  Tree.n_nodes = dtree[1];
+  Tree.branch_fac = b;
+  Tree.M = M;
+  Tree.Mh = (int)(0.5*(double)(M-1.0));
+  
+  // image struct
+  im_st Im;
+  Im.im_data = I;
+  Im.rows = dim[0];
+  Im.cols = dim[1];
+  if ( ndim == 3 )
+  {
+      Im.layers = dim[2];
+  }
+  else
+  {
+      Im.layers = 1;
+  }
+  Im.n_pix = Im.rows*Im.cols;
+  
+  if ( M*M*Im.layers != Tree.n_dim )
+    mexErrMsgTxt("Dimensions of the tree and the image does not fit.");
+  
+  // Set the output pointer to the output matrix. Array initialized to zero. 
+  plhs[0] = mxCreateNumericArray(ndtree, dim, mxDOUBLE_CLASS, mxREAL);
+  
+  // Create a C pointer to a copy of the output matrix.
+  A = mxGetPr(plhs[0]);
+  // Search the tree using the C++ subroutine
+  search_image(Im, Tree, A, normalize);
+}
+
diff --git a/code/texture_gui/code/functions/search_km_tree.mexa64 b/code/texture_gui/code/functions/search_km_tree.mexa64
new file mode 100755
index 0000000000000000000000000000000000000000..1c413daea71625531c3473517f3c177df8cadac0
Binary files /dev/null and b/code/texture_gui/code/functions/search_km_tree.mexa64 differ
diff --git a/code/texture_gui/code/functions/search_km_tree.mexmaci64 b/code/texture_gui/code/functions/search_km_tree.mexmaci64
new file mode 100755
index 0000000000000000000000000000000000000000..f6786b110627679ad91fbfd91cb9022bdf2b1a71
Binary files /dev/null and b/code/texture_gui/code/functions/search_km_tree.mexmaci64 differ
diff --git a/code/texture_gui/code/functions/search_km_tree.mexw64 b/code/texture_gui/code/functions/search_km_tree.mexw64
new file mode 100755
index 0000000000000000000000000000000000000000..cbe6d41e8ffdb3c5057845234410e9daeeebe734
Binary files /dev/null and b/code/texture_gui/code/functions/search_km_tree.mexw64 differ
diff --git a/code/texture_gui/code/functions/search_km_tree_xcorr.cpp b/code/texture_gui/code/functions/search_km_tree_xcorr.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..20c722b6018fe6907bb0ed9d4c0dbe87a133bc0e
--- /dev/null
+++ b/code/texture_gui/code/functions/search_km_tree_xcorr.cpp
@@ -0,0 +1,239 @@
+#include "mex.h"
+#include <stdio.h>
+#include <math.h>
+#include "matrix.h"
+#include <vector>
+
+#include <iostream>
+using namespace std;
+
+/*
+ * This is a MEX-file for MATLAB.
+ * 
+ * Anders Bjorholm Dahl, 8/12-2015
+ *
+ *
+ */
+
+// struct for the tree
+struct tree_st
+{
+    double *tree_data;
+    int n_dim, inv_ndim, n_nodes, branch_fac, M, Mh;
+};
+
+// struct for image
+struct im_st
+{
+    double *im_data;
+    int rows, cols, layers, n_pix;
+};
+
+// estimate the distance between a vector in tree given by the node and a 
+// patch in the image given by the row and column
+double get_corr(vector<double>& patch, tree_st& tree, int& node)
+{
+    double corr = 0, tmp;
+    int id_t = tree.n_dim*node;
+    
+    for ( int i = 0; i < tree.n_dim; i++ ){
+        corr += patch[i]*(*(tree.tree_data + id_t));
+        id_t++;
+    }
+    
+    return corr;
+}
+
+// nomalize patch vectors to zero mean and unit Euclidean length
+void norm_patch(vector<double>& patch, double& mu, int n_dim){
+    
+    double sum_sq = 0;
+    
+    for ( int i = 0; i < n_dim; i++ ){
+        patch[i] = patch[i] - mu;
+        sum_sq += patch[i]*patch[i];
+    }
+    
+    double inv_sq = 1;
+    if ( sum_sq > 0 ){
+        inv_sq = 1.0/sqrt(sum_sq); // divide by sum of squares
+    }
+
+    for ( int i = 0; i < n_dim; i++ ){
+        patch[i] = patch[i]*inv_sq;
+    }
+}
+
+
+// Function for sampling patches from the image into the patch arrays
+// inputs reference to the image struct, tree struct, patch struct and position of the sampling coordinate.
+// There is no check if the sampling is outside the image
+// vector<double> sample_patch(im_st& im, int& M, int r_im, int c_im, bool& normalize)
+vector<double> sample_patch(im_st& im, int& M, int r_im, int c_im)
+{
+    int id_l, id_r, id_i; // iterators for looking up image data
+    int id_p = 0; // iterator for looking up patch data
+    double sum = 0, pix_val, mu; // variables for normalization
+    int n_dim = M*M*im.layers; // number of dimensions computed here, becasue tree is not included
+    vector<double> patch(n_dim);
+    int Mh = (M-1)/2;
+    
+    for ( int l = 0; l < im.layers; l++ ){ // image is sampled by three nested loops (layers, columns, rows)
+        id_l = im.n_pix*l;
+        for ( int i = c_im-Mh; i <= c_im+Mh; i++ ){
+            id_r = id_l + i*im.rows;
+            for ( int j = r_im-Mh; j <= r_im+Mh; j++ ){
+                id_i = id_r + j;
+                pix_val = *(im.im_data + id_i);
+                patch[id_p] = pix_val;
+                sum += pix_val; // sum for estimating the mean
+                id_p++;
+            }
+        }
+    }
+    
+    mu = sum/((double)n_dim); // mean value
+    norm_patch(patch, mu, n_dim); // nomalization
+
+    return patch;
+}
+
+
+// The tree search function
+int search_tree(im_st& im, tree_st& tree, int& r, int& c)
+{
+    int node = 0, node_max = -1, node_max_level, next_node; // variables for searching the tree
+    double corr_max = -1, corr, corr_max_level; 
+    
+    vector<double> patch = sample_patch(im, tree.M, c, r); // get the pixel values in a patch
+    while ( node < tree.n_nodes ){ // go through the tree
+        if ( *(tree.tree_data + node*tree.n_dim) == -1 ){ // check if node is a leaf-node
+            return node_max;
+        }
+        
+        corr_max_level = -1; // set correlation to low value
+        for ( int i = 0; i < tree.branch_fac; i++ ){ // go through nodes at level 
+            next_node = node + i;
+            corr = get_corr(patch, tree, next_node);
+            
+            if ( corr > corr_max_level ){ // set current node to the maximum correlation
+                corr_max_level = corr;
+                node_max_level = next_node;
+            }
+        }
+        if ( corr_max_level > corr_max ){ // set overall maximum correlation and corresponding node
+            corr_max = corr_max_level;
+            node_max = node_max_level;
+        }
+        node = (node_max_level+1)*tree.branch_fac; // go to the child node
+    }
+    return node_max;
+}
+
+// The tree search function applied to the entire image - border is zero and interior is in 1,...,n
+void search_image(im_st& im, tree_st& tree, double *A)
+{
+    int idx = tree.Mh*im.rows; // increase with empty rows at border
+    for ( int i = tree.Mh; i < im.cols-tree.Mh; i++ ){
+        idx += tree.Mh; // first Mh pixels are border
+        for ( int j = tree.Mh; j < im.rows-tree.Mh; j++ ){           
+            *(A + idx) = search_tree(im, tree, i, j) + 1; // find assignment
+            idx++;
+        }
+        idx += tree.Mh; // last Mh pixels are border
+    }
+}
+
+
+// The gateway routine 
+void mexFunction( int nlhs, mxArray *plhs[],
+                  int nrhs, const mxArray *prhs[])
+{
+  // input image (I), tree (tree) and output assignment (A)
+  double *I, *A, *tree;
+  int b, M, ndim, ndtree;
+  const int *dim, *dtree;
+  /*  Check for proper number of arguments. */
+  /* NOTE: You do not need an else statement when using
+     mexErrMsgTxt within an if statement. It will never
+     get to the else statement if mexErrMsgTxt is executed.
+     (mexErrMsgTxt breaks you out of the MEX-file.) 
+  */
+  if(nrhs != 3 ) 
+    mexErrMsgTxt("Three inputs required.");
+  if(nlhs != 1) 
+    mexErrMsgTxt("One output required.");
+    
+  // Create a pointer to the input matrix.
+  I = mxGetPr(prhs[0]);
+  tree = mxGetPr(prhs[1]);
+  
+  double *bd;
+  bd = mxGetPr(prhs[2]);
+  b = (int)bd[0];
+    
+  if ( b < 1 )
+    mexErrMsgTxt("b must be positive.");
+  
+  // Get the dimensions of the matrix input.
+  ndim = mxGetNumberOfDimensions(prhs[0]);
+  if (ndim != 2 && ndim != 3)
+    mexErrMsgTxt("search_km_tree only works for 2-dimensional or 3-dimensional images.");
+
+  ndtree = mxGetNumberOfDimensions(prhs[1]);
+  if (ndtree != 2)
+    mexErrMsgTxt("search_km_tree only works for 2-dimensional tree.");
+
+  dim = mxGetDimensions(prhs[0]);
+  dtree = mxGetDimensions(prhs[1]);
+  
+  if ( ndim == 3 )
+  {
+      M = (int)sqrt((double)dtree[0]/(double)dim[2]);
+  }
+  else
+  {
+      M = (int)sqrt((double)dtree[0]);
+  }
+  
+  if ( 1 - (M % 2)  || M < 1)
+    mexErrMsgTxt("M must be odd and positive.");
+  
+  
+  // tree struct
+  tree_st Tree;
+  Tree.tree_data = tree;
+  Tree.n_dim = dtree[0];
+  Tree.inv_ndim = 1/((double)Tree.n_dim);
+  Tree.n_nodes = dtree[1];
+  Tree.branch_fac = b;
+  Tree.M = M;
+  Tree.Mh = (int)(0.5*(double)(M-1.0));
+  
+  // image struct
+  im_st Im;
+  Im.im_data = I;
+  Im.rows = dim[0];
+  Im.cols = dim[1];
+  if ( ndim == 3 )
+  {
+      Im.layers = dim[2];
+  }
+  else
+  {
+      Im.layers = 1;
+  }
+  Im.n_pix = Im.rows*Im.cols;
+  
+  if ( M*M*Im.layers != Tree.n_dim )
+    mexErrMsgTxt("Dimensions of the tree and the image does not fit.");
+  
+  // Set the output pointer to the output matrix. Array initialized to zero. 
+  plhs[0] = mxCreateNumericArray(ndtree, dim, mxDOUBLE_CLASS, mxREAL);
+  
+  // Create a C pointer to a copy of the output matrix.
+  A = mxGetPr(plhs[0]);
+  // Search the tree using the C++ subroutine
+  search_image(Im, Tree, A);
+}
+
diff --git a/code/texture_gui/code/functions/search_km_tree_xcorr.mexa64 b/code/texture_gui/code/functions/search_km_tree_xcorr.mexa64
new file mode 100755
index 0000000000000000000000000000000000000000..0ac82cdef7ccd8a4ca18fcd4b65ed8df7fd7ec13
Binary files /dev/null and b/code/texture_gui/code/functions/search_km_tree_xcorr.mexa64 differ
diff --git a/code/texture_gui/code/functions/search_km_tree_xcorr.mexmaci64 b/code/texture_gui/code/functions/search_km_tree_xcorr.mexmaci64
new file mode 100755
index 0000000000000000000000000000000000000000..5f224caefe0987623c73d07353e150a8b390ada6
Binary files /dev/null and b/code/texture_gui/code/functions/search_km_tree_xcorr.mexmaci64 differ
diff --git a/code/texture_gui/code/functions/search_km_tree_xcorr.mexw64 b/code/texture_gui/code/functions/search_km_tree_xcorr.mexw64
new file mode 100755
index 0000000000000000000000000000000000000000..8d771be06e99b9fa7ee3d64aa69f4f7669f16de2
Binary files /dev/null and b/code/texture_gui/code/functions/search_km_tree_xcorr.mexw64 differ
diff --git a/code/texture_gui/code/functions/segmentation_correction_gui.m b/code/texture_gui/code/functions/segmentation_correction_gui.m
new file mode 100755
index 0000000000000000000000000000000000000000..6df8c878f3ef343279513f8cf5f7cd0009c45ea1
--- /dev/null
+++ b/code/texture_gui/code/functions/segmentation_correction_gui.m
@@ -0,0 +1,406 @@
+function segmentation_correction_gui(image,segmentation,nr_labels,labeling)
+%IMAGE_TEXTURE_GUI   Interactive segmentation correction
+
+%%%%%%%%%% DEFAULTS %%%%%%%%%%
+
+if nargin<1 % default example image
+    %image = imread('bag.png');
+    image = imread('football.jpg');
+end
+[r,c,~] = size(image);
+if nargin<2 || isempty(segmentation)% default segmentation
+    segmentation = zeros(r,c,'uint8');
+else
+    segmentation = uint8(segmentation);
+end
+if nargin<3 || isempty(nr_labels) % defalult number of labels
+    nr_labels = double(max(2,max(segmentation(:))));
+end
+if nargin<4 || isempty(labeling) % default, unlabeled initial correction
+    % TODO allow corrections to be inferred from labelings
+    DRAWING = zeros(r,c,'uint8');
+else
+    DRAWING = uint8(labeling);
+end
+
+%%%%%%%%%% SETTINGS %%%%%%%%%%
+
+% labels
+LABEL = 1; % initial label is 1
+
+% thickness
+thickness_options = [1 2 3 4 5 10 20 30 40 50 100 -1]; % last option (value -1) is 'fill'
+thickness_options_string = num2cell(thickness_options);
+thickness_options_string{end} = 'fill';
+THICKNESS_INDEX = 5; % initial pencil thickness is the fifth option
+RADIUS = thickness2radius(thickness_options(THICKNESS_INDEX)); % pencil radius
+
+% show
+show_options(1:2) = {'segmentation','overlay'};
+SHOW_INDEX = 1;
+
+% colormap
+colormap_options = {@(x)[0.5,0.5,0.5;cool(x)], @(x)[0.5,0.5,0.5;spring(x)],...
+    @(x)[0.5,0.5,0.5;parula(x)]}; % gray color for unlabeled
+COLORMAP_INDEX = 1; % current colormap
+COLORS = colormap_options{COLORMAP_INDEX}(nr_labels); % visualization colors for label overlay
+% other settings
+color_weight = 0.4; % color weight for label overlay
+nr_circle_pts = 16; % number of points defining a circular pencil
+
+%%%%%%%%%% INITIALIZATION AND LAYOUT %%%%%%%%%%
+[image,gray] = normalize_image(image); % impose 0-to-1 rgb
+CORRECTED = uint8(segmentation);
+CORRECTED(DRAWING~=0) = DRAWING(DRAWING~=0); % if initial corrections given
+DRAWING_OVERLAY = image; % image overlaid labeling
+CORRECTED_OVERLAY = ind2rgb(CORRECTED,COLORS);
+
+fmar = [0.2 0.2]; % discance from screen edge to figure (x and y)
+amar = [0.05 0.05]; % margin around axes, relative to figure
+my = 0.8:0.05:0.9; % menu items y position
+mh = 0.03; % menu items height
+cw = (0.4-0.3)/(nr_labels+1); % colorcube width
+cx = 0.3:cw:0.4; % colorcubes x position
+
+fig = figure('Units','Normalized','Position',[fmar,1-2*fmar],...
+    'Pointer','watch','KeyPressFcn',@key_press,'InvertHardCopy', 'off',...
+    'Name','Segmentation correction GUI');
+clean_toolbar
+
+labeling_axes = axes('Units','Normalized','Position',[0,0,0.5,0.8]+[amar,-2*amar]);
+imagesc(DRAWING_OVERLAY), axis image off, hold on
+segmentation_axes = axes('Units','Normalized','Position',[0.5,0,0.5,0.8]+[amar,-2*amar]);
+imagesc(CORRECTED_OVERLAY,[0,nr_labels]), axis image off, hold on
+
+uicontrol('String','Label [L] : ','Style','text','HorizontalAlignment','right',...
+    'Units','Normalized','Position',[0,my(3),0.25,mh]);
+labels_text = uicontrol('String',num2str(LABEL),...
+    'BackgroundColor',COLORS(LABEL+1,:),...
+    'Style','text','HorizontalAlignment','left',...
+    'Units','Normalized','Position',[0.25,my(3),0.03,mh]);
+label_pointer = cell(nr_labels+1,1);
+label_colorcubes = cell(nr_labels+1,1);
+label_char = repmat(' ',[1,nr_labels+1]);
+label_char(LABEL+1)='|';
+for k = 1:nr_labels+1
+    label_colorcubes{k} = uicontrol('String',' ','Style','text',...
+        'BackgroundColor',COLORS(k,:),...
+        'Units','Normalized','Position',[cx(k),my(3),cw,mh/2]);
+    label_pointer{k} = uicontrol('String',label_char(k),'Style','text',...
+        'HorizontalAlignment','center',...
+        'Units','Normalized','Position',[cx(k),my(3)+mh/2,cw,mh/2]);
+end
+
+uicontrol('String','Thickness [T] : ','Style','text','HorizontalAlignment','right',...
+    'Units','Normalized','Position',[0,my(2),0.25,mh]);
+thickness_text = uicontrol('String',thickness_options_string(THICKNESS_INDEX),...
+    'Style','text','HorizontalAlignment','left',...
+    'Units','Normalized','Position',[0.25,my(2),0.25,mh]);
+
+uicontrol('String','Show [W] :','Style','text','HorizontalAlignment','right',...
+    'Units','Normalized','Position',[0,my(1),0.25,mh]);
+show_text = uicontrol('String',show_options{SHOW_INDEX},...
+    'Style','text','HorizontalAlignment','left',...
+    'Units','Normalized','Position',[0.25,my(1),0.25,mh]);
+
+drawnow % pointer shows busy system
+
+LIMITS = [1,c-0.5,1,r+0.5]; % to capture zoom
+zoom_handle = zoom(fig);
+pan_handle = pan(fig);
+set(zoom_handle,'ActionPostCallback',@adjust_limits,...
+    'ActionPreCallback',@force_keep_key_press);
+set(pan_handle,'ActionPostCallback',@adjust_limits,...
+    'ActionPreCallback',@force_keep_key_press);
+
+compute_overlays
+
+% ready to draw
+set(fig,'Pointer','arrow','WindowButtonDownFcn',@start_draw,...
+    'WindowButtonMotionFcn',@pointer_motion);
+XO = []; % current drawing point
+uiwait % waits with assigning output until a figure is closed
+
+%%%%%%%%%% CALLBACK FUNCTIONS %%%%%%%%%%
+    function key_press(~,object)
+        % keyboard commands
+        key = object.Key;
+        numkey = str2double(key);
+        if ~isempty(numkey) && numkey<=nr_labels;
+            label_char(LABEL+1)=' ';
+            LABEL = numkey;
+            set(labels_text,'String',num2str(LABEL),...
+                'BackgroundColor',COLORS(LABEL+1,:));
+            label_char(LABEL+1)='|';
+            for kk = 1:nr_labels+1
+                set(label_pointer{kk},'String',label_char(kk));
+            end
+        else
+            switch key
+                case 'l'
+                    label_char(LABEL+1)=' ';
+                    LABEL = move_once(LABEL+1,nr_labels+1,...
+                        any(strcmp(object.Modifier,'shift')))-1;
+                    set(labels_text,'String',num2str(LABEL),...
+                        'BackgroundColor',COLORS(LABEL+1,:));
+                    label_char(LABEL+1)='|';
+                    for kk = 1:nr_labels+1
+                        set(label_pointer{kk},'String',label_char(kk));
+                    end
+                case 'uparrow'
+                    THICKNESS_INDEX = move_once(THICKNESS_INDEX,...
+                        numel(thickness_options),false);
+                    RADIUS = thickness2radius(thickness_options(THICKNESS_INDEX));
+                    set(thickness_text,'String',...
+                        thickness_options_string(THICKNESS_INDEX));
+                    show_overlays(get_pixel);
+                case 'downarrow'
+                    THICKNESS_INDEX = move_once(THICKNESS_INDEX,...
+                        numel(thickness_options),true);
+                    RADIUS = thickness2radius(thickness_options(THICKNESS_INDEX));
+                    set(thickness_text,'String',...
+                        thickness_options_string(THICKNESS_INDEX));
+                    show_overlays(get_pixel);
+                case 't'
+                    THICKNESS_INDEX = move_once(THICKNESS_INDEX,...
+                        numel(thickness_options),any(strcmp(object.Modifier,'shift')));
+                    RADIUS = thickness2radius(thickness_options(THICKNESS_INDEX));
+                    set(thickness_text,'String',...
+                        thickness_options_string(THICKNESS_INDEX));
+                    show_overlays(get_pixel);
+                case 'w'
+                    SHOW_INDEX = move_once(SHOW_INDEX,numel(show_options),...
+                        any(strcmp(object.Modifier,'shift')));
+                    set(show_text,'String',show_options{SHOW_INDEX})
+                    compute_overlays
+                    show_overlays(get_pixel);
+                case 'c'
+                    COLORMAP_INDEX = move_once(COLORMAP_INDEX,...
+                        length(colormap_options),...
+                        any(strcmp(object.Modifier,'shift')));
+                    COLORS = colormap_options{COLORMAP_INDEX}(nr_labels);
+                    set(labels_text,'BackgroundColor',COLORS(LABEL+1,:));
+                    for kk = 1:nr_labels+1
+                        set(label_colorcubes{kk},'BackgroundColor',COLORS(kk,:))
+                    end
+                    compute_overlays
+                    show_overlays(get_pixel);
+                case 's'
+                    save_project
+                case 'e'
+                    export_DC
+                case 'q'
+                    close(fig)
+            end
+        end
+    end
+
+    function adjust_limits(~,~)
+        % response to zooming and panning
+        LIMITS([1,2]) = get(labeling_axes,'XLim');
+        LIMITS([3,4]) = get(labeling_axes,'YLim');
+    end
+
+    function force_keep_key_press(~,~)
+        % a hack to maintain my key_press while in zoom and pan mode
+        % http://undocumentedmatlab.com/blog/enabling-user-callbacks-during-zoom-pan
+        hManager = uigetmodemanager(fig);
+        [hManager.WindowListenerHandles.Enabled] = deal(false);
+        set(fig, 'KeyPressFcn', @key_press);
+    end
+
+    function start_draw(~,~)
+        % click in the image
+        x = get_pixel;
+        if is_inside(x)
+            if RADIUS>0 % thickness>0
+                XO = x;
+                M = disc(XO,RADIUS,nr_circle_pts,[r,c]);
+                set(fig,'WindowButtonMotionFcn',@drag_and_draw,...
+                    'WindowButtonUpFcn',@end_draw)
+            else % fill
+                M = fill(x);
+            end
+            update(M);
+        end
+    end
+
+    function drag_and_draw(~,~)
+        % drag after clicking in the image
+        x = get_pixel;
+        M = stadium(XO,x,RADIUS,nr_circle_pts,[r,c]);
+        update(M);
+        XO = x;
+    end
+
+    function end_draw(~,~)
+        % release click after clicking in the image
+        M = stadium(XO,get_pixel,RADIUS,nr_circle_pts,[r,c]);
+        update(M);
+        XO = [];
+        set(fig,'WindowButtonMotionFcn',@pointer_motion,...
+            'WindowButtonUpFcn','')
+    end
+
+    function pointer_motion(~,~)
+        % move around without clicking
+        if strcmp(zoom_handle.Enable,'off') && ...
+                strcmp(pan_handle.Enable,'off') % not zooming or panning
+            x = get_pixel;
+            if is_inside(x)
+                set(fig,'Pointer','crosshair')
+            else
+                set(fig,'Pointer','arrow')
+            end
+            show_overlays(x);
+        end
+    end
+
+%%%%%%%%%% HELPING FUNCTIONS %%%%%%%%%%
+
+    function save_project
+        % save mat file with user input and setting
+        % save images as separate files
+        [file,path] = uiputfile('correction.mat','Save project as');
+        if ~isequal(file,0) && ~isequal(path,0)
+            matfile = fullfile(path,file);
+            roothname = matfile(1:find(matfile=='.',1,'last')-1);
+            current_settings.show = show_options{SHOW_INDEX};
+            save(matfile,'DRAWINGS','CORRECTED',...
+                'dictopt','nr_labels','current_settings')
+            imwrite(DRAWING_OVERLAY,[roothname,'_drawing.png'])
+            imwrite(CORRECTED_OVERLAY,[roothname,'_corrected.png'])
+        end
+    end
+
+    function export_DC
+        button = questdlg({'Exporting variables to the base workspace',...
+            'might overwrite existing variables'},...
+            'Exporting variables','OK','Cancel','OK');
+        if strcmp(button,'OK')
+            assignin('base','gui_D',DRAWING)
+            assignin('base','gui_C',CORRECTED)
+        end
+        
+    end
+
+    function a = is_inside(x)
+        % check if x is inside image limits
+        a = inpolygon(x(1),x(2),LIMITS([1,2,2,1]),LIMITS([3,3,4,4]));
+    end
+
+    function p = get_pixel
+        % get cursor position
+        p = get(labeling_axes,'CurrentPoint');
+        p = round(p(1,[1,2]));
+    end
+
+    function show_overlays(x)
+        % overlay a circular region where the pointer and show
+        shown_left = DRAWING_OVERLAY;
+        shown_right = CORRECTED_OVERLAY;
+        if RADIUS>0 % thickness>0
+            P = repmat(disc(x,RADIUS,nr_circle_pts,[r,c]),[1,1,3]);
+            shown_left(P(:)) = 0.5+0.5*DRAWING_OVERLAY(P(:));
+            shown_right(P(:)) = 0.5+0.5*CORRECTED_OVERLAY(P(:));
+        end
+        % we have to imagesc(shown) to remove overlay if needed
+        axes(labeling_axes), cla, imagesc(shown_left)
+        axes(segmentation_axes), cla, imagesc(shown_right)
+    end
+
+    function update(M)
+        % change the state of the segmentation by updating LABELINGS with a
+        % mask M, and updating PROBABILITIES
+        DRAWING(M(:)) = LABEL;
+        if LABEL>0
+            CORRECTED(M(:)) = LABEL;
+        else
+            CORRECTED(M(:)) = segmentation(M(:));
+        end
+        compute_overlays % computing overlay images
+        show_overlays(get_pixel); % showing overlay and pointer
+    end
+
+    function compute_overlays
+        % computes overlays but not pointer overalay
+        uncorrected = repmat(DRAWING==0,[1 1 3]);
+        DRAWING_OVERLAY = uncorrected.*image + ~uncorrected.*...
+            (color_weight.*ind2rgb(DRAWING,COLORS) + (1-color_weight).*gray);
+        switch show_options{SHOW_INDEX}
+            case 'segmentation'
+                CORRECTED_OVERLAY = ind2rgb(CORRECTED,COLORS);
+            case 'overlay'
+                CORRECTED_OVERLAY = color_weight*...
+                    ind2rgb(CORRECTED,COLORS) + (1-color_weight)*gray;
+        end
+    end
+
+% TODO disc shold be saved as a list of index shifts with respect to
+% the central pixel, and change only when thickness changes
+    function M = disc(x,r,N,dim)
+        % disc shaped mask in the image
+        angles = (0:2*pi/N:2*pi*(1-1/N));
+        X = x(1)+r*cos(angles);
+        Y = x(2)+r*sin(angles);
+        M = poly2mask(X,Y,dim(1),dim(2));
+    end
+
+    function M = stadium(x1,x2,r,N,dim)
+        % stadium shaped mask in the image
+        angles = (0:2*pi/N:pi)-atan2(x1(1)-x2(1),x1(2)-x2(2));
+        X = [x1(1)+r*cos(angles), x2(1)+r*cos(angles+pi)];
+        Y = [x1(2)+r*sin(angles), x2(2)+r*sin(angles+pi)];
+        M = poly2mask(X,Y,dim(1),dim(2));
+    end
+
+    function M = fill(x)
+        M = bwselect(DRAWING==DRAWING(x(2),x(1)),x(1),x(2),4);
+    end
+
+    function [I,G] = normalize_image(I)
+        % initialization: normalize image
+        if isa(I,'uint8')
+            I = double(I)/255;
+        end
+        if isa(I,'uint16')
+            I = double(I)/65535;
+        end
+        if size(I,3)==3 % rgb image
+            G = repmat(rgb2gray(I),[1 1 3]);
+        else % assuming grayscale image
+            I = repmat(I,[1,1,3]);
+            G = I;
+        end
+    end
+
+    function n = move_once(n,total,reverse)
+        % moves option index once, respecting total number of options
+        if ~reverse
+            n = mod(n,total)+1;
+        else
+            n = mod(n+total-2,total)+1;
+        end
+    end
+
+    function r = thickness2radius(t)
+        r = t/2+0.4;
+    end
+
+    function clean_toolbar
+        set(fig,'MenuBar','none','Toolbar','figure');
+        all_tools = allchild(findall(fig,'Type','uitoolbar'));
+        %my_tool = uipushtool(toolbar,'CData',rand(16,16,3),'Separator','on',...
+        %            'TooltipString','my tool','Tag','my tool');
+        for i=1:numel(all_tools)
+            if isempty(strfind(all_tools(i).Tag,'Pan'))&&...
+                    isempty(strfind(all_tools(i).Tag,'Zoom'))&&...
+                    isempty(strfind(all_tools(i).Tag,'SaveFigure'))&&...
+                    isempty(strfind(all_tools(i).Tag,'PrintFigure'))&&...
+                    isempty(strfind(all_tools(i).Tag,'DataCursor'))
+                delete(all_tools(i)) % keeping only Pan, Zoom, Save and Print
+            end
+        end
+    end
+
+end
diff --git a/code/texture_gui/code/functions/update_dictionary.m b/code/texture_gui/code/functions/update_dictionary.m
new file mode 100755
index 0000000000000000000000000000000000000000..11627b2d4d2026bcde2b7f23fb82a432405c7c48
--- /dev/null
+++ b/code/texture_gui/code/functions/update_dictionary.m
@@ -0,0 +1,9 @@
+function dictionary = update_dictionary(dictionary,gui_dictprob)
+
+M = dictionary.options.patch_size;
+nr_dict_patches = size(dictionary.tree,2);
+L = size(gui_dictprob,2); % nr labels
+gui_dictprob = reshape(gui_dictprob,[M^2,nr_dict_patches,L]);
+gui_dictprob = permute(gui_dictprob,[1,3,2]);
+gui_dictprob = reshape(gui_dictprob,[M^2*L,nr_dict_patches]);
+dictionary.dictprob = gui_dictprob;
\ No newline at end of file
diff --git a/code/texture_gui/code/reusing_labels_script.m b/code/texture_gui/code/reusing_labels_script.m
new file mode 100755
index 0000000000000000000000000000000000000000..f25eb922bd6ce18a3b51f9658c4596ed6e318df2
--- /dev/null
+++ b/code/texture_gui/code/reusing_labels_script.m
@@ -0,0 +1,23 @@
+clear 
+close all
+addpath functions
+
+% example of re-using externaly made labeling image
+im = imread('../data/randen15B.png'); % randen 5 textures
+labeling = double(imread('../data/randen_labels_rgb.png'));
+dictopt.patch_size = 15;
+dictopt.branching_factor = 4;
+dictopt.number_layers = 4;
+dictopt.number_training_patches = 2000;
+dictopt.normalization = false;
+dictopt.method = 'euclidean';
+image_texture_gui(im,dictopt,5,labeling)
+
+%% an image exported from gui can be re-used 
+image_texture_gui(im,dictopt,5) %% <- EXPORT (E) labeling here
+image_texture_gui(im,dictopt,5,gui_L) %% <- use labeling here
+
+%% an image saved from gui can be re-used 
+image_texture_gui(im,dictopt,5) %% <- SAVE (S) labeling here using some filename
+image_texture_gui(im,dictopt,5,imread('filename_labels_indexed.png')) %% <- use labeling here
+
diff --git a/code/texture_gui/code/test.m b/code/texture_gui/code/test.m
new file mode 100755
index 0000000000000000000000000000000000000000..b05b7fdaef8a69b9cb8668204e2d70dbbfe29803
--- /dev/null
+++ b/code/texture_gui/code/test.m
@@ -0,0 +1,31 @@
+addpath('functions')
+%%
+fig = figure;
+imagesc(rand(200,200));
+set(fig,'MenuBar','none','Toolbar','figure');
+
+%%
+toolbar = findall(fig,'Type','uitoolbar');
+all_tools = allchild(toolbar);
+% removing tools
+for i=1:numel(all_tools)
+    t = get(all_tools(i),'Tag');
+    if isempty(strfind(t,'Pan'))&&...
+            isempty(strfind(t,'Zoom'))&&...
+            isempty(strfind(t,'SaveFigure'))&&...
+            isempty(strfind(t,'PrintFigure'))&&...
+            isempty(strfind(t,'DataCursor'))
+        delete(all_tools(i)) % keeping only Pan, Zoom, Save and Print
+    end
+end
+%% adding a tool
+[icon,~,alpha] = imread('linkaxesicon.png');
+icon = double(icon)/255;
+icon(alpha==0)=NaN;
+uitoggletool(toolbar,'CData',icon,...
+    'TooltipString','Link Axes','Tag','LinkAxes',...
+    'OnCallback',{@link_axes,'xy'},...
+    'OffCallback',{@link_axes,'off'});
+%% changing the order of tools
+all_tools = allchild(toolbar);
+set(toolbar,'children',all_tools([2,1,3:end]));
\ No newline at end of file
diff --git a/code/texture_gui/code/texture_gui_uses_script.m b/code/texture_gui/code/texture_gui_uses_script.m
new file mode 100755
index 0000000000000000000000000000000000000000..aa2c156a988022be9cfc72a49b46b3728a8d7483
--- /dev/null
+++ b/code/texture_gui/code/texture_gui_uses_script.m
@@ -0,0 +1,29 @@
+clear 
+close all
+
+addpath functions
+
+%% demo: no input
+image_texture_gui
+
+%% usage 1: only image (default dictionary options )
+im = double(imread('bag.png'))/255; 
+image_texture_gui(im)
+
+%% usage 2: image and dictionary options
+dictopt.method = 'euclidean';
+dictopt.patch_size = 11;
+dictopt.branching_factor = 2;
+dictopt.number_layers = 5;
+dictopt.number_training_patches = 30000;
+dictopt.normalization = false;
+image_texture_gui(im,dictopt,5)
+
+%% usage 3: image and dictionary
+dictionary = build_dictionary(im,dictopt);
+image_texture_gui(im,dictionary,2)
+
+%% usage 4: image and mappings
+mappings = compute_mappings(im,dictionary);
+image_texture_gui(im,mappings,2)
+