image thumbnail

overlayVolume

by

 

14 Dec 2012 (Updated )

Displays 3 orthogonal slices from a 3D volume with optional overlay.

overlayVolume
classdef overlayVolume < handle
    %OVERLAYVOLUME displays a 3D volume in slices with optional overlay.
    %
    % Usage: 
    % - OVERLAYVOLUME(VOL1, VOL2); displays a 3D datasets VOL1, and an
    %   overlay dataset VOL2, with default display settings.
    % - OVERLAYVOLUME(VOL1); displays one 3D dataset VOL1
    % - OVERLAYVOLUME(VOL1,VOL2,optionalparameters); displays 3D datasets
    %   VOL1 and VOL2 with addional user specified display settings.
    %   Settings should be provided as parameter name - value pairs.
    % - After initialization, many settings can be changed using the
    %   setPROPERTY functions, see below.
    % - showColorBar shows the colorbars, see example below.
    %
    % Optional parameters:
    % - backRange:   display range of background data as [lower, upper]
    %                default: [lowest value in data, highest value]
    % - backMap:     colormap of the background as Nx3 matrix
    %                default: gray(256)
    % - overRange:   display range of overlay data as [lower, upper]
    %                default: [lowest value in data, highest value]
    % - overMap:     colormap of the overlay as Nx3 matrix
    %                default: hot(256)
    % - alpha:       transparency of the overlay as scalar between 0 and 1
    %                default: 0.4
    % - maskRange:   range of values in the overlay that will not be
    %                displayed as [lower, upper]
    %                default: []
    % - aspectRatio: aspect ratio of the three dimensions as [x,y,z]
    %                default: [1 1 1]
    %
    % Available setPROPERTY functions:
    % - setBackVolume:  set the background volume, should be the same size.
    % - setBackRange:   set the background display range.
    % - setBackMap:     set the background colormap
    % - setOverVolume:  set the overlay volume
    % - setOverRange:   set the overlay display range
    % - setOverMap:     set the overlay colormap
    % - setAlpha:       set the overlay transparency
    % - setMaskRange:   set the overlay mask range
    % - setAspectRatio: set the aspect ratio of the volumes
    % 
    % Examples:
    % load('mri'); VOL1 = double(squeeze(D)); % load matlab sample data
    % VOL2 = (VOL1>20).*rand(size(VOL1));     % create a random overlay
    % OVERLAYVOLUME(VOL1,VOL2,'alpha',0.2);   % show volumes, alpha=0.2
    % OVERLAYVOLUME(VOL1,VOL2,'backMap',bone(256),'overMap',hot(64));
    % OVERLAYVOLUME(VOL1,[],'aspectRatio',[1 1 5]);
    % OV = OVERLAYVOLUME(VOL1,VOL2);          % start with default settings
    % OV.showColorBar;                        % show the colorbars.
    % OV.setOverMap(jet(256));                % set the overlay color map
    % OV.setAspectRatio([1 1 5]);             % set the aspect ratio
    % OV.setOverVolume([]);                   % remove the overlay volume
    % 
    % Acknowledgement:
    % - "ct3"        by "tripp",      FileExchange ID: #32173
    % - "OverlayImg" by "Jochen Rau", FileExchange ID: #26790
    %
    % J.A. Disselhorst, December 2012
    % Werner Siemens Imaging Center, http://www.preclinicalimaging.org/
    % University of Tuebingen, Germany.
    
    properties                                                  % These properties are public.
        aspectRatio = [];                                       % data aspect ratio.
        backVol     = [];                                       % Background volume
        backMap     = [];                                       % Color map for the background 
        backRange   = [];                                       % background image range [min, max]
        overVol     = [];                                       % Overlay volume
        overMap     = [];                                       % Color map for the overlay
        overRange   = [];                                       % Overlay image range [min, max]
        maskRange   = [];                                       % Overlay will not be shown for values in the maskRange [lower, upper]
        alpha       = [];                                       % Transparency value [0<=alpha<=1]
    end 
    properties (SetAccess = private, Hidden = true)             % These properties are private.
        volumeSize   = [];                                      % size of the volume
        currentPoint = [];                                      % current point shown
        figsHandles  = [];                                      % handles to the figures.
        imgsHandles  = [];                                      % handles to the images
        lineHandles  = [];                                      % handles to the lines
        cursHandles  = [];                                      % handles to the cursor tool tips.
        colorBarFig  = [];                                      % handle to the optional colorbar figure.
    end
    methods(Static)
        function range = getRange(volume)                       % Provides display range for a volume
            volume(isnan(volume) | isinf(volume)) = [];         % Remove the Inf's and NaN's
            range = [min(volume(:)), max(volume(:))];           % Set the range to minimum to maximum value.
            if diff(range)==0                                   % When the numbers are equal
                range(2) = range(2)*1.01;                       % Add one percent to the upper limit.
            end
        end
        function figureScroll(fig,evnt,obj)                     % When the mousewheel is scrolled with one of the figures selected.
            CP = obj.currentPoint;                              % The current point
            VS = obj.volumeSize;                                % The size of the volume.
            if fig==obj.figsHandles(1)                          % For figure 1.
                temp = CP(1);                                   % The x coordinate of the current position.
                CP(1) = CP(1)+evnt.VerticalScrollCount;         % Add the scroll count (this number can also be negative)
                CP(1) = min([VS(1), max([1, CP(1)])]);          % The new position should be in correct range (>0 and <image size).
                obj.currentPoint = CP;                          % Set the new position.
                if temp~=CP(1)                                  % When the position has changed
                    updateImages(obj,fig);                      % Update the images.
                end
            elseif fig==obj.figsHandles(2)                      % For figure 2.
                temp = CP(2);                                   % y coordinate.
                CP(2) = CP(2)+evnt.VerticalScrollCount;         % Add the scroll count (this number can also be negative)
                CP(2) = min([VS(2), max([1, CP(2)])]);          % The new position should be in correct range (>0 and <image size).
                obj.currentPoint = CP;                          % Set the new position.
                if temp~=CP(2)                                  % When the position has changed
                    updateImages(obj,fig);                      % Update the images.
                end
            else                                                % For figure 3.
                temp = CP(3);                                   % z coordinate.
                CP(3) = CP(3)+evnt.VerticalScrollCount;         % Add the scroll count (this number can also be negative)
                CP(3) = min([VS(3), max([1, CP(3)])]);          % The new position should be in correct range (>0 and <image size).
                obj.currentPoint = CP;                          % Set the new position.
                if temp~=CP(3)                                  % When the position has changed
                    updateImages(obj,fig);                      % Update the images.
                end
            end
        end
        function figureClick(fig,~,obj)                         % When the mouse is clicked in one of the figures.
            CP = obj.currentPoint;                              % The current coordinates.
            VS = obj.volumeSize;                                % The size of the volume.
            p = get(findall(fig,'tag','IMG'),'CurrentPoint');   % Get the currentpoint in the correct image. 
            if fig==obj.figsHandles(1)                          % In figure 1.
                CP(3) = max([1 min([VS(3), round(p(1,2))])]);   % calculate the new positions
                CP(2) = max([1 min([VS(2), round(p(1,1))])]);   % calculate the new positions
            elseif fig==obj.figsHandles(2)                      % In figure 2
                CP(3) = max([1 min([VS(3), round(p(1,2))])]);   % calculate the new positions
                CP(1) = max([1 min([VS(1), round(p(1,1))])]);   % calculate the new positions
            else                                                % In figure 3
                CP(1) = max([1 min([VS(1), round(p(1,2))])]);   % calculate the new positions
                CP(2) = max([1 min([VS(2), round(p(1,1))])]);   % calculate the new positions
            end
            obj.currentPoint = CP;                              % update the position in the class.
            updateImages(obj,setdiff(obj.figsHandles,fig));     % Update the images of the other figures.
        end
        function IMG = provideImage(fig,obj)                    % Create an image from the volumes, using current display settings.
            CP = obj.currentPoint;                              % The current coordinates.
            if fig==obj.figsHandles(1)                          % Figure 1.
                IMG1 = permute(obj.backVol(CP(1),:,:),[3 2 1]); % Get the image of the background.
            elseif fig==obj.figsHandles(2)                      % Figure 2.
                IMG1 = permute(obj.backVol(:,CP(2),:),[3 1 2]); % Get the image of the background.
            else                                                % Figure 3.
                IMG1 = obj.backVol(:,:,CP(3));                  % Get the image of the background.
            end
            
            IMG1 = IMG1-obj.backRange(1);                       % Subtract the lower display limit.
            IMG1 = IMG1./(obj.backRange(2)-obj.backRange(1));   % Calculate image including the upper display limit.
            IMG1(IMG1<0) = 0;                                   % Everything below the lower limit is set to the lower limit.
            IMG1(IMG1>1) = 1;                                   % Everything above the upper limit is set to the upper limit.
            IMG1 = round(IMG1*(size(obj.backMap,1)-1))+1;       % Multiply by the size of the colormap, and make it integers to get a color index.
            IMG1(isnan(IMG1)) = 1;                              % remove NaNs -> these will be shown as the lower limit.
            IMG1 = reshape(obj.backMap(IMG1,:),...              % Get the correct color from the colormap using the index calculated above.
                [size(IMG1,1),size(IMG1,2),3]);                 % ...
            
            if ~isempty(obj.overVol);                           % Do this only when there is actually an overlay image.
                if fig==obj.figsHandles(1)                      % If figure 1.
                    IMG2 = permute(obj.overVol(CP(1),:,:),...   % Get the image from the overlay volume
                        [3 2 1]);                               % ...
                elseif fig==obj.figsHandles(2)                  % If figure 2.
                    IMG2 = permute(obj.overVol(:,CP(2),:),...   % Get the image from the overlay volume
                        [3 1 2]);                               % ...
                else                                            % If figure 3.
                    IMG2 = obj.overVol(:,:,CP(3));              % Get the image from the overlay volume
                end
                if ~isempty(obj.maskRange)                      % Do this only when a mask range is available.
                    mask = ones(size(IMG2));                    % Set mask to one (everything is shown).
                    mask(IMG2>=obj.maskRange(1) & ...           % Set the mask to zero (not shown) for values within the mask range.
                         IMG2<=obj.maskRange(2)) = 0;           % ...
                    mask = repmat(mask,[1 1 3]);                % Repeat for Red, Green and Blue.
                else                                            % Otherwise, if no mask range is available
                    mask = repmat(ones(size(IMG2)),[1 1 3]);    % Set mask to one (everything is shown) for R,G, and B.
                end
                IMG2=IMG2-obj.overRange(1);                     % Subtract the lower display limit.
                IMG2=IMG2./(obj.overRange(2)-obj.overRange(1)); % Use the upper display limit.
                IMG2(IMG2<0) = 0;                               % Everything below the lower limit is set to the lower limit.
                IMG2(IMG2>1) = 1;                               % Everything above the upper limit is set to the upper limit.
                IMG2 = round(IMG2*(size(obj.overMap,1)-1))+1;   % Multiply by the size of the colormap, and make it integers to get a color index.
                mask(isnan(IMG2)) = 0;                          % NaNs in the overlay will not be shown.
                IMG2(isnan(IMG2)) = 1;                          % remove NaNs
                IMG2 = reshape(obj.overMap(IMG2,:),...          % Get the correct color from the colormap using the index calculated above.
                    [size(IMG2,1),size(IMG2,2),3]);             % ...
                
                IMG = IMG1*(1-obj.alpha)+mask.*IMG2*obj.alpha;  % Combine background and overlay, using alpha and mask.
            else
                IMG = IMG1;                                     % Simple case, only a background is available.
            end
            
            
        end
        function parseInputs(input,obj)                         % Parse the inputs given by the user.
            p = inputParser;                                    % Matlabs input parser, see "help inputparser"
            p.addParamValue('backRange',overlayVolume.getRange(obj.backVol),@(x)length(x)==2&x(1)<x(2));
            p.addParamValue('overRange',overlayVolume.getRange(obj.overVol),@(x)length(x)==2&x(1)<x(2));
            p.addParamValue('backMap',gray(256),@(x)ismatrix(x)&size(x,2)==3)
            p.addParamValue('overMap',hot(256),@(x)ismatrix(x)&size(x,2)==3)
            p.addParamValue('maskRange',[],@(x)length(x)==2&x(1)<x(2));
            p.addParamValue('alpha',0.4,@(x)x>=0&x<=1);
            p.addParamValue('aspectRatio',[1 1 1],@(x)length(x)==3);
            p.addParamValue('colorBar',0,@isscalar)
            p.parse(input{:});                                  % Parse the input, given parameters set above. If a parameter is not provided, use the default.
            obj.backRange   = p.Results.backRange;              % Set all the parameters.
            obj.overRange   = p.Results.overRange;              % ...
            obj.maskRange   = p.Results.maskRange;              % ...
            obj.alpha       = p.Results.alpha;                  % ...
            obj.backMap     = p.Results.backMap;                % ...
            obj.overMap     = p.Results.overMap;                % ...
            obj.aspectRatio = p.Results.aspectRatio;            % ...
            if p.Results.colorBar, showColorBar(obj); end       % When the user wants a colorbar, show it.
        end
    end
    methods
    	function obj = overlayVolume(backVol,overVol,varargin)  % Initial start of this function, show the images, provide the class handle.
            if nargin==1, overVol = []; end                     % Only one input variable? -> overVol is empty.
            if isscalar(backVol)                                % If the provided input is not an image, but a scalar.
                error('Images should be 2- or 3-Dimensional');  % Error.
            end
            if ismatrix(backVol)                                % If an image (2D) is provided, 
                backVol = permute(backVol,[3,1,2]);             % make it a volume (3D)
            end
            if ismatrix(overVol)==2                             % If an image (2D) is provided, 
                overVol = permute(overVol,[3,1,2]);             % make it a volume (3D)
            end
            vS = size(backVol);                                 % The size of the volume. 
            obj.currentPoint = round(vS/2);                     % Current point is in the center of the volume.
            if ~isempty(overVol)                                % The overlay volume may be empty,
                if ~all(vS == size(overVol))                    % Otherwise it should be the same size as the background.
                    error('Overlay must be the same size');     % Throw error if not.
                end
            end
            obj.volumeSize = vS;                                % Set the the volume size, this is from now on read only.
            obj.backVol = backVol;                              % Set the background volume
            obj.overVol = overVol;                              % Set the overlay volume.
            
            if nargin <= 2                                      % If only the volume(s) are given, 
                overlayVolume.parseInputs({},obj);              % Set default parameters for the display settings
            else                                                % Otherwise...
                overlayVolume.parseInputs(varargin,obj);        % parse the additional input.
            end
            
            obj.figsHandles(1) = figure;                        % Make a figure, and save its handle.
            obj.imgsHandles(1) = imshow(zeros(vS(3),vS(2)));    % Initialize the image.
            set(gca,'position',[0 0 1 1],'DataAspectRatio',...  % Image should be full size, The correct
                [obj.aspectRatio(3) obj.aspectRatio(2) 1],...   % ... data aspect ratio, and 
                'Tag', 'IMG');                                  % ... can be identified by a the tag 'IMG'
            hold on                                             % Hold, to initialize lines
            obj.lineHandles(1) = ...                            % The handle for the line
                plot(0,1,'Color',[0.8,0.8,0.8]);                % The correct coordinates are not necessary at this stage.
            hold off
            obj.cursHandles=datacursormode(obj.figsHandles(1)); % Get the data cursor mode handle
            
            obj.figsHandles(2) = figure;
            obj.imgsHandles(2) = imshow(zeros(vS(3),vS(1)));    % Initialize image
            set(gca,'position',[0 0 1 1],'DataAspectRatio',...  % Image should be full size, The correct
                [obj.aspectRatio(3) obj.aspectRatio(1) 1],...   % ... data aspect ratio, and 
                'Tag', 'IMG');                                  % ... can be identified by a the tag 'IMG'
            hold on                                             % Hold, to initialize lines
            obj.lineHandles(2) = ...                            % The handle for the line
                plot(0,1,'Color',[0.8,0.8,0.8]);                % The correct coordinates are not necessary at this stage.
            hold off
            obj.cursHandles(2)=datacursormode(obj.figsHandles(2));% Get the data cursor mode handle
            
            obj.figsHandles(3) = figure;
            obj.imgsHandles(3) = imshow(zeros(vS(1),vS(2)));    % Initialize image
            set(gca,'position',[0 0 1 1],'DataAspectRatio',...  % Image should be full size, The correct ...
                [obj.aspectRatio(1) obj.aspectRatio(2) 1],...   % ... data aspect ratio, and 
                'Tag', 'IMG');                                  % ... can be identified by a the tag 'IMG'
            hold on                                             % Hold, to initialize lines
            obj.lineHandles(3) = ...                            % The handle for the line
                plot(0,1,'Color',[0.8,0.8,0.8]);                % The correct coordinates are not necessary at this stage.
            hold off
            obj.cursHandles(3)=datacursormode(obj.figsHandles(3));% Get the data cursor mode handle
           
            set(obj.figsHandles, 'WindowScrollWheelFcn',...     % For each figure, ....
                {@overlayVolume.figureScroll,obj},...           % set the scroll wheel 
                'WindowButtonDownFcn',...                       % and mouse click functions
                {@overlayVolume.figureClick,obj});              % ...
            set(obj.cursHandles, 'UpdateFcn', @obj.dataTip);    % Set the data cursor mode to a custom function.
            updateImages(obj);                                  % Update the images. 
        end
        function tiptext = dataTip(obj, ~, event)               % Function to show something meaningful when the data cursor is used.
            CP = obj.currentPoint;                              % Get the current coordinates.
            Pos = event.Position;                               % Get the position of the click.
            fig = get(event.Target,'Parent');                   % Get where the click occured.
            while ~strcmp('figure', get(fig,'type'))            % Get its parent until the we have the handle to the figure in which was clicked.
                fig = get(fig,'Parent');                        % ...
            end  
            if fig==obj.figsHandles(1)                          % It was in figure 1.
                X=CP(1); Y=Pos(1); Z=Pos(2);                    % Get the 'real' position.
            elseif fig==obj.figsHandles(2)                      % Figure 2.
                X=Pos(1); Y=CP(2); Z=Pos(2);                    % Get the 'real' position.
            else                                                % Figure 3.
                X=Pos(2); Y=Pos(1); Z=CP(3);                    % Get the 'real' position.
            end
            back = obj.backVol(X,Y,Z);                          % The value of the background volume at this position.
            tiptext = sprintf('X: %1.0f, Y: %1.0f, Z: = %1.0f\nBackground: %2.2f',X,Y,Z,back); % Show some text.
            if ~isempty(obj.overVol)                            % If the overlay exists, 
                over = obj.overVol(X,Y,Z);                      % get the value of the overlay at this position. 
                tiptext = sprintf('%s\nOverlay: %2.2f',tiptext,over); % and add it to the tiptext.
            end  
        end
        function updateImages(obj,figs)                         % Function to update the images
            if nargin==1                                        % If no specific figure is requested, 
                figs = obj.figsHandles;                         % update them all.
            end
            for loop = 1:length(figs)                           % Loop through the figure handles that should be updated.
                IMG=overlayVolume.provideImage(figs(loop),obj); % Get the right image,
                try set(obj.imgsHandles(figs(loop) == ...       % And try to show it
                        obj.figsHandles),'CData',IMG); end      % ... (The 'try' is there in case a window was closed by the user)
            end
            updateMarkers(obj);                                 % Set the line markers correctly.
        end
        function updateMarkers(obj)                             % Function to set the line markers.
            CP = obj.currentPoint;                              % The current coordinates
            vS = obj.volumeSize;                                % The size of the volume
            LL = vS/15; LL2 = LL-0.5;                           % Length of the helper lines depends on the size of the volume.
            try                                                 % Set the lines in figure 1.
                set(obj.lineHandles(1),'XData',[0.5 0.5+LL(2) NaN vS(2)-LL2(2) vS(2)+0.5 NaN CP(2) CP(2) NaN CP(2) CP(2)]);
                set(obj.lineHandles(1),'YData',[CP(3) CP(3) NaN CP(3) CP(3) NaN 0.5 0.5+LL(3) NaN vS(3)-LL2(3) vS(3)+0.5]);
            end
            try                                                 % Set the lines in figure 2.
                set(obj.lineHandles(2),'XData',[0.5 0.5+LL(1) NaN vS(1)-LL2(1) vS(1)+0.5 NaN CP(1) CP(1) NaN CP(1) CP(1)]);
                set(obj.lineHandles(2),'YData',[CP(3) CP(3) NaN CP(3) CP(3) NaN 0.5 0.5+LL(3) NaN vS(3)-LL2(3) vS(3)+0.5]); 
            end
            try                                                 % Set the lines if figure 3.
                set(obj.lineHandles(3),'XData',[0.5 0.5+LL(2) NaN vS(2)-LL2(2) vS(2)+0.5 NaN CP(2) CP(2) NaN CP(2) CP(2)]);
                set(obj.lineHandles(3),'YData',[CP(1) CP(1) NaN CP(1) CP(1) NaN 0.5 0.5+LL(1) NaN vS(1)-LL2(1) vS(1)+0.5]); 
            end
        end
                
        function setBackVolume(obj, Value)                      % Change the background volume
            if ~isequal(size(Value), size(obj.backVol))         % Size of the background data should match the old size.
                warning('Background image should have the same dimensions!');
            end;
            obj.backVol = Value;                                % Set the volume.
            updateImages(obj);                                  % Update the images.
        end
        function setOverVolume(obj, Value)                      % Change the overlay volume.
            if ~isempty(Value)                                  % Overlay may be empty.
                if ~isequal(size(Value), size(obj.backVol))     % If not, it should match the size of the background.
                    warning('Overlay image should have the same dimensions as the background!');
                end
            end
            obj.overVol = Value;                                % Set the overlay
            if isempty(obj.overRange)                           % If the overlay range was previously empty, ...
                obj.overRange = overlayVolume.getRange(Value);  % Get the defaults.
                showColorBar(obj,'UpdateIfExist');              % If there is a colorbar, update it.
            end
            updateImages(obj);                                  % Update the images.
        end
        function setBackMap(obj, Value)                         % Change the colormap of the background
            try iptcheckmap(Value)                              % Check the validity of the provided colormap
                obj.backMap = Value;                            % Set the colormap
                updateImages(obj);                              % Update the images.
                showColorBar(obj,'UpdateIfExist');              % If it exists, update the colorbar.
            catch                                     %#ok<CTCH>  We do not need the error message.
                warning('Colormap should be X*3');              % It did not work, throw error.
            end
        end
        function setOverMap(obj, Value)                         % Change the colormap of the overlay
            try iptcheckmap(Value)                              % Check the validity of the provided colormap
                obj.overMap = Value;                            % Set the colormap
                updateImages(obj);                              % Update the images.
                showColorBar(obj,'UpdateIfExist');              % If it exists, update the colorbar.
            catch                                     %#ok<CTCH>  We do not need the error message.
                warning('Colormap should be X*3');              % It did not work, trow error.
            end
        end
        function setBackRange(obj, Value)                       % Set the background color range
            if length(Value) == 2                               % It should be two numbers.
                if Value(1)<Value(2)                            % The first should be smaller than the second
                    obj.backRange = Value;                      % Set the values.
                    updateImages(obj);                          % Update the images.
                    showColorBar(obj,'UpdateIfExist');          % Update the colorbar if it exists.
                end
            end
        end
        function setOverRange(obj, Value)                       % Set the overlay color range
            if length(Value) == 2                               % It should be two numbers.
                if Value(1)<Value(2)                            % The first should be smaller than the second
                    obj.overRange = Value;                      % Set the values.
                    updateImages(obj);                          % Update the images.
                    showColorBar(obj,'UpdateIfExist');          % Update the colorbar if it exists.
                end
            end
        end
        function setMaskRange(obj, Value)                       % Set range that is invisible in the overlay
            if length(Value) == 2                               % It should be two numbers.
                if Value(1)<Value(2)                            % The first should be smaller than the second
                    obj.maskRange = Value;                      % Set the values.
                    updateImages(obj);                          % Update the images.
                end
            end
        end
        function setAlpha(obj, Value)                           % Set the transparency of the overlay
            if length(Value)==1                                 % It should be one value
                if Value>=0 && Value<=1                         % It should be between zero and one
                    obj.alpha = Value;                          % Set the value.
                    updateImages(obj);                          % Update the images.
                end
            end
        end
        function setAspectRatio(obj, Value)                     % Set the aspect ratio
            if length(Value)==2,Value = [1 Values]; end         % In this case it is probably a 2D image, make it three values.
            if length(Value)==3                                 % It should be three values.
                obj.aspectRatio = Value;                        % Set the aspect ratio in the object.
                set(findall(obj.figsHandles(1),...              % Find all objects in figure 1 ...
                    'type','axes'),'position',[0 0 1 1],...     % that are axes, ...
                    'DataAspectRatio',[Value(3) Value(2) 1]);   % and set the aspect ratio.
                set(findall(obj.figsHandles(2),...              % Find all objects in figure 2
                    'type','axes'),'position',[0 0 1 1],...     % that are axes, 
                    'DataAspectRatio',[Value(3) Value(1) 1]);   % and set the aspect ratio.
                set(findall(obj.figsHandles(3),...              % Find all objects in figure 3
                    'type','axes'),'position',[0 0 1 1],...     % that are axes,
                    'DataAspectRatio',[Value(1) Value(2) 1]);   % and set the aspect ratio.
            end
        end
        
        function showColorBar(obj,varargin)                     % Show an additional figure with the colorbars.
            X = 1/256;                                          % constant for one pixel in the colorbar;
            if isempty(obj.overVol)                             % When there is no overlay volume, ...
                N = 25;                                         % The full width of the bar is for the background volume.
                over = [];                                      % No overlay bar.
                line = [];                                      % And no line to separate the two.
            else                                                % If there is an overlay....
                N = 12;                                         % this is the width of each bar.
                over = ceil((1:-X:X)*size(obj.overMap,1))';     % Make a 256 pixel high image.
                over = repmat(over,[1,N]);                      % Repeat for the width of the bar.
                over = reshape(obj.overMap(over,:),256,N,3);    % Make it the correct color (overlay)
                line = zeros(256,1,3);                          % The separation line is black.
            end
            back = ceil((1:-X:X)*size(obj.backMap,1))';         % Make the bar for the background, 256 pixel high.
            back = repmat(back,[1,N]);                          % repeat for the width of the bar
            back = reshape(obj.backMap(back,:),256,N,3);        % Make it the correct color
            linelr = zeros(256,1,3); linebt = zeros(1,27,3);    % The lines left/right and bottom/top
            colors = [linelr,back,line,over,linelr];            % The colorbar + vertical lines.
            colors = [linebt;colors;linebt];                    % Add horizontal lines.
            if ~isempty(obj.colorBarFig) && ...                 % Does the figure already exist?
                    ishandle(obj.colorBarFig)                   % ...
                figure(obj.colorBarFig)                         % Make it active.
            else                                                % If there is no window yet 
                if nargin>1                                     % Check if this function call was from the user (nargin==1) or from a setPROPERTY function (nargin~=1) 
                    return                                      % If it was from the setPROPERTY and there is no window, don't make one.
                end                                             % Otherwise,
                obj.colorBarFig = figure('Menubar','none');     % ... make one
            end
            imshow(colors);                                     % Show the colorbar(s)
            hold on;                                            % Start drawing lines and writing text.
            plot([1 27 NaN 1 27 NaN 1 27],[129.5 129.5 NaN 64.25 64.25 NaN 192.75 192.75],'k'); % The horizontal lines.
            br = obj.backRange;                                 % The background range.
            text(1,2,sprintf('%2.3f  ',br(2)),...               % Display some background range values.
                'HorizontalAlignment','right');                 % ...
            text(1,257,sprintf('%2.3f  ',br(1)),...             % ...
                'HorizontalAlignment','right');                 % ...
            text(1,129.5,sprintf('%2.3f  ',mean(br)),...        % ...
                'HorizontalAlignment','right');                 % ...
            text(1,64.25,sprintf('%2.3f  ',br(2)-diff(br)/4),...% ...
                'HorizontalAlignment','right');                 % ...
            text(1,192.75,sprintf('%2.3f  ',br(1)+diff(br)/4),...%...
                'HorizontalAlignment','right');                 % ...
            if ~isempty(obj.overVol)                            % When a overlay volume is available
                or = obj.overRange;                             % use its range
                text(27,2,sprintf('  %2.3f',or(2)));            % and display some values.
                text(27,257,sprintf('  %2.3f',or(1)));          % ...
                text(27,129.5,sprintf('  %2.3f',mean(or)));     % ...
                text(27,64.25,sprintf('  %2.3f',...             % ...
                    or(2)-diff(or)/4));                         % ...
                text(27,192.75,sprintf('  %2.3f',...            % ...
                    or(1)+diff(or)/4));                         % ...
            end
            hold off                                            % End writing lines and text.
        end
    end
end

Contact us