function vaargout = lyngby_ui_voxelmask(varargin) 

% lyngby_ui_voxelmask	- User interface for voxelmask editing 
%
%       function lyngby_ui_voxelmask(command,parameter1) 
%
%       This function is used to control the window for setting up the
%       VOXEL_MASK global variable. 
%
%       The VOXEL_MASK variable is usually "VOXEL_MASK = 1" which means
%       that all voxels are included (ie, no voxelmask). If VOXEL_MASK
%       is sparse the number of rows should correspond to the full
%       volume and the number of columns to the number of voxels in
%       the masked volume.
%
%       Select the appropriate command from the popup menu and press
%       "Go!". The VOXEL_MASK global variable will be updated and the
%       window can be closed with the "Close" button.
% 
%       "~isnan from first volume" means that all voxels different from
%       NaN in the first volume (corresponding to FILENAME_STARTINDEX)
%       will be included in the mask. 
%
%       "~isnan from ANALYZE file" will read an user-specified ANALYZE
%       file and include voxels in the mask that are different from
%       NaN. 
%
%       "~0 from ANALYZE file" will read an user-specified ANALYZE
%       file and include voxels in the mask that are different from
%       0. 
%
%       "Threshold from first volume" will find the voxels in the
%       first volume that are above the threshold.
%
%       This function is called from lyngby_ui_loadfile when the
%       'voxel mask' 'edit' button is pressed. The 'Apply' button
%       should be pressed before the voxel mask is called. 
%
%       Example:
%         % Reduce the volume with the voxel mask
%         lyngby_global
%         V_big   = lyngby_getvolume(FILENAME_STARTINDEX);
%         V_small = V_big * VOXEL_MASK;
%
%         % To get back to the full volume transpose the voxelmask
%         V_big2  = V_small * VOXEL_MASK';
%
%       See also LYNGBY, LYNGBY_UI_MAIN, LYNGBY_UI_LOADFILE,
%                LYNGBY_GLOBAL.  
%
% $Id: lyngby_ui_voxelmask.m,v 1.3 2003/09/15 10:28:44 fnielsen Exp $

    % Global variables
    lyngby_global
    lyngby_ui_global
    lyngby_ui_option
	   
     
    if nargin == 0 

      fig = figure('position',[ 218 55 500 230 ],... 
	  'resize','on','tag','lyngby_ui_voxelmask',... 
	  'visible','off',...
	  'name', 'lyngby - Voxelmask setup',...
	  'numbertitle', 'off',...
	  'color', UI_COLOUR_FRAME); 

      ButtonHeight = 0.1;
      ButtonRow1 = 0.05;
      yHigh = 0.17;
 
      frameControl = uicontrol(...
          'Units','normalized',... 
          'ForegroundColor',UI_COLOR_FRONT,... 
          'BackgroundColor',UI_COLOUR_WINBACK,...
          'Position',[ 0.08 0.025 0.84 0.15 ],... 
          'String','',... 
          'Style','frame',... 
          'Tag','framecontrol',... 
          'UserData',''); 
            
      buttonClose = uicontrol(... 
	  'Callback', 'lyngby_ui_voxelmask(''buttonClose'', gcbo, guidata(gcbo))',...
	  'ForegroundColor', UI_COLOR_FRONT,...
	  'BackgroundColor', UI_COLOUR_BUTTON,...
	  'String','Close',... 
	  'Style','pushbutton',... 
	  'Units','normalized',... 
	  'Position',[ 0.62 ButtonRow1 0.14 ButtonHeight ],...
	  'Tag','buttonClose',... 
	  'UserData',''); 
      buttonHelp = uicontrol(... 
	  'Callback', 'lyngby_ui_voxelmask(''buttonHelp'', gcbo, guidata(gcbo))',...
	  'ForegroundColor', UI_COLOR_FRONT,...
	  'BackgroundColor', UI_COLOUR_BUTTON,...
	  'String','Help',... 
	  'Style','pushbutton',... 
	  'Units','normalized',... 
	  'Position',[ 0.77 ButtonRow1 0.14 ButtonHeight ],...
	  'Tag','buttonHelp');

	  
      buttonLoad = uicontrol(... 
	  'Callback', 'lyngby_ui_voxelmask(''buttonLoad'')',...
	  'ForegroundColor', UI_COLOR_FRONT,...
	  'BackgroundColor', UI_COLOUR_BUTTON,...
	  'String','Load ...',... 
	  'Style','pushbutton',... 
	  'Units','normalized',... 
	  'Position',[ 0.05 yHigh 0.1 ButtonHeight ],...
	  'Tag','buttonLoad',... 
	  'visible', 'off',...
	  'UserData',''); 
      buttonSaveAs = uicontrol(... 
	  'Callback', 'lyngby_ui_voxelmask(''buttonSaveAs'')',...
	  'ForegroundColor', UI_COLOR_FRONT,...
	  'BackgroundColor', UI_COLOUR_BUTTON,...
	  'String','Save as ...',... 
	  'Style','pushbutton',... 
	  'Units','normalized',... 
	  'Position',[ 0.16 yHigh 0.13 ButtonHeight ],...
	  'Tag','buttonSaveAs',... 
	  'visible', 'off',...
	  'UserData',''); 
      buttonReread = uicontrol(... 
	  'Callback', 'lyngby_ui_voxelmask(''buttonReread'')',...
	  'ForegroundColor', UI_COLOR_FRONT,...
	  'BackgroundColor', UI_COLOUR_BUTTON,...
	  'String','Reread lyngby_voxelmask',... 
	  'Style','pushbutton',... 
	  'Units','normalized',... 
	  'Position',[ 0.31 yHigh 0.25 ButtonHeight ],...
	  'visible', 'off',...
	  'Tag','buttonReread');
      buttonLoadPara = uicontrol(... 
	  'Callback', 'lyngby_ui_voxelmask(''buttonLoadPara'')',...
	  'ForegroundColor', UI_COLOR_FRONT,...
	  'BackgroundColor', UI_COLOUR_BUTTON,...
	  'String','Read data_voxelmask.m',... 
	  'Style','pushbutton',... 
	  'Units','normalized',... 
	  'Position',[ 0.050 ButtonRow1 0.25 ButtonHeight ],...
	  'visible', 'off',...
	  'Tag','buttonLoadPara'); 
      buttonSavePara = uicontrol(... 
	  'Callback', 'lyngby_ui_voxelmask(''buttonSavePara'')',...
	  'ForegroundColor', UI_COLOR_FRONT,...
	  'BackgroundColor', UI_COLOUR_BUTTON,...
	  'String','Save to data_voxelmask.mat',... 
	  'Style','pushbutton',... 
	  'Units','normalized',... 
	  'Position',[ 0.31 ButtonRow1 0.27 ButtonHeight ],...
	  'Tag','buttonSavePara',... 
	  'visible', 'off',...
	  'UserData',''); 
      
      buttonAction = uicontrol(... 
	  'Callback', 'lyngby_ui_voxelmask(''buttonAction'', gcbo, guidata(gcbo))',...
	  'ForegroundColor', UI_COLOR_FRONT,...
	  'BackgroundColor', UI_COLOUR_BUTTON,...
	  'String','Go!',... 
	  'Style','pushbutton',... 
	  'Units','normalized',... 
	  'Position',[ 0.49 ButtonRow1 0.07 ButtonHeight ],...
	  'Tag','buttonAction',... 
	  'UserData',''); 
      popupType = uicontrol(... 
	  'ForegroundColor',UI_COLOR_FRONT,... 
	  'BackgroundColor',UI_COLOUR_BUTTON,...
	  'Units','normalized',... 
	  'Position',[ 0.09 ButtonRow1 0.39 ButtonHeight ],... 
	  'HorizontalAlignment','left',... 
	  'String',[...
	    'Choose a command, then press Go!|',...
	    'Reset (to no voxelmask)|', ...
	    '~isnan from first volume|', ...
	    'AND ~isnan from first volume|', ...
	    '~isnan from ANALYZE file|', ...
	    '~0 from ANALYZE file|', ...
	    'Threshold from first volume', ...
	    ],...
	  'Style','popupmenu',... 
	  'TooltipString', [ ...
	    'Choose a command here and press the "Go!" button' ...
	    ], ...
	  'Tag','popupType'); 

  
      %  Axes and Text Object Creation 
      
      axesVoxelmask = axes(... 
	  'Units','normalized', ... 
	  'Position',[ 0.08 0.34 0.84 0.56 ],... 
	  'Xgrid','off', ... 
	  'Ygrid','off', ... 
	  'Xlim',[ 0 1 ],... 
	  'Ylim',[ 0 1 ],... 
	  'Clipping','on', ... 
	  'Tag','axesVoxelmask', ... 
	  'Visible', 'on', ...
	  'UserData',''); 

      hg           = guihandles(fig);  % Initialize it to contain handles
      guidata(fig, hg);                % Store the structure
      set(fig, 'visible', 'on');

      V = lyngby_getvolume(FILENAME_STARTINDEX);
      
      subplot(1,2,1)
      hist(V, 100)
      xlabel('Voxel intensity')
      ylabel('Frequency')
      title('First volume histogram, Before');
      pos = get(gca, 'position');
      set(gca, 'position', [ pos(1) 0.3 pos(3) 0.6 ]);
      
      subplot(1,2,2)
      hist(V*VOXEL_MASK, 100)
      xlabel('Voxel intensity')
      ylabel('Frequency')
      title('After');
      pos = get(gca, 'position');
      set(gca, 'position', [ pos(1) 0.3 pos(3) 0.6 ]);
      
    elseif ischar(varargin{1})
      % Invoke uicontrol callback
      try
        [varargout{1:nargout}] = feval(varargin{:}); 
      catch
        disp(lasterr);
      end
    
    else
      error('lyngby_ui_global called with wrong command')
    end


function varargout = buttonAction(h, hg)
    lyngby_global

    cmd = get(hg.popupType, 'value');
    if cmd == 1
      % Nothing
    elseif cmd == 2
      % Reset
      VOXEL_MASK = 1;
      lyngby_log('Resetting VOXEL_MASK = 1');
    elseif cmd == 3
      % Voxel that are not NaN in the first volume
      lyngby_log('Reading first volume');
      V = lyngby_getvolume(FILENAME_STARTINDEX);
      i = find(~isnan(V));
      if isempty(i)
	% There are no voxels in the mask
	VOXEL_MASK = 1;
      elseif length(i) == length(V)
	% All voxels from the original volume is in the mask, so the
	% mask is not necessary
	VOXEL_MASK = 1;
      else
	VOXEL_MASK = sparse(i, 1:length(i), 1, length(V), length(i));
	lyngby_log(sprintf('%d voxels in mask', length(i)));
      end
    elseif cmd == 4
      % Voxel that are not NaN in the first volume ANDed to the
      % present voxel mask
      lyngby_log('Reading first volume');
      V = lyngby_getvolume(FILENAME_STARTINDEX);
      i = find(~isnan(V));
      if isempty(i)
	lyngby_ui_message([ ...
	      'There are no voxels in the mask. The old voxel mask ' ...
	      'is maintained']);
      elseif length(i) == length(V)
      	lyngby_ui_message([ ...
	      'All voxels are in the mask. The old voxel mask ' ...
	      'is maintained']);
      else
	i_old = find(sum(VOXEL_MASK,2));
	i = intersect(i, i_old);          % AND the two masks
	VOXEL_MASK = sparse(i, 1:length(i), 1, length(V), length(i));
	lyngby_log(sprintf('%d voxels in mask', length(i)));
      end

    elseif cmd == 5 | cmd == 6
      % Voxel that are not NaN in an ANALYZE file
      [filename, pathname] = uigetfile('*.hdr', ...
	  'Pick an ANALYZE file (.img or .hdr)');
      if ~(isequal(filename, 0) | isequal(pathname,0))
	lyngby_log('Reading ANALYZE volume');
	V = lyngby_read_analyze(fullfile(pathname, filename));
	V1 = lyngby_getvolume(FILENAME_STARTINDEX);
	if prod(size(V)) ~= prod(size(V1))
	  lyngby_ui_message([ ...
		'Masking analyze file and first volume file have ' ...
		'different sizes']);
	else	
	  if cmd == 5
	    i = find(~isnan(V));
	  elseif cmd == 6
	    i = find(V~=0);
	  else
	    error('Internal error')
	  end
	  if isempty(i)
	    VOXEL_MASK = 1;
	    lyngby_ui_message('There are no voxels in the mask');
	  elseif length(i) == length(V)
	    % All voxels from the original volume is in the mask, so the
	    % mask is not necessary
	    VOXEL_MASK = 1;
	    lyngby_ui_message('All voxels in mask');
	  else
	    VOXEL_MASK = sparse(i, 1:length(i), 1, length(V), length(i));
	    lyngby_log(sprintf('%d voxels in mask', length(i)));
	  end
	end
      end
    elseif cmd == 7
      % Threshold 
      V1 = lyngby_getvolume(FILENAME_STARTINDEX);
      answer = inputdlg('Threshold', 'Threshold in first volume', 1, ...
	  cellstr(num2str(max(V1)/4)));
      threshold = str2double(answer);
      if isreal(threshold)
	i = find(V1>threshold);
	if isempty(i)
	  VOXEL_MASK = 1;
	  lyngby_ui_message('There are no voxels in the mask');
	elseif length(i) == length(V1)
	  % All voxels from the original volume is in the mask, so the
	  % mask is not necessary
	  VOXEL_MASK = 1;
	  lyngby_ui_message('All voxels in mask');
	else
	  VOXEL_MASK = sparse(i, 1:length(i), 1, length(V1), length(i));
	  lyngby_log(sprintf('%d voxels in mask', length(i)));
	end
      else
	error('Could not inteprete threshold input');
      end
    else
      error('Internal error');
    end

    V = lyngby_getvolume(FILENAME_STARTINDEX);

    subplot(1,2,1)
    hist(V, 100)
    xlabel('Voxel intensity')
    ylabel('Frequency')
    title('First volume histogram, Before');
    pos = get(gca, 'position');
    set(gca, 'position', [ pos(1) 0.3 pos(3) 0.6 ]);
    
    subplot(1,2,2)
    hist(V*VOXEL_MASK, 100)
    xlabel('Voxel intensity')
    ylabel('Frequency')
    title('After');
    pos = get(gca, 'position');
    set(gca, 'position', [ pos(1) 0.3 pos(3) 0.6 ]);


    
    
    
function varargout = buttonClose(h, hg)
    close(get(h, 'parent'));
    
    
function varargout = buttonHelp(h, hg)
    helpwin('lyngby_ui_voxelmask');















