Home > phiwave > @slover > paint.m

paint

PURPOSE ^

method to display slice overlay

SYNOPSIS ^

function obj = paint(obj, params)

DESCRIPTION ^

 method to display slice overlay
 FORMAT paint(obj, params)
 
 Inputs 
 obj         - slice overlay object
 params      - optional structure containing extra display parameters
               - refreshf - overrides refreshf in object
               - clf      - overrides clf in object 
               - userdata - if 0, does not add object to userdata field
               (see below)

 Outputs
 obj         - which may have been filled with defaults
 
 paint attaches the object used for painting to the 'UserData' field of
 the figure handle, unless instructed not to with 0 in userdata flag

 $Id: paint.m,v 1.2 2005/05/06 22:59:56 matthewbrett Exp $

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function obj = paint(obj, params)
0002 % method to display slice overlay
0003 % FORMAT paint(obj, params)
0004 %
0005 % Inputs
0006 % obj         - slice overlay object
0007 % params      - optional structure containing extra display parameters
0008 %               - refreshf - overrides refreshf in object
0009 %               - clf      - overrides clf in object
0010 %               - userdata - if 0, does not add object to userdata field
0011 %               (see below)
0012 %
0013 % Outputs
0014 % obj         - which may have been filled with defaults
0015 %
0016 % paint attaches the object used for painting to the 'UserData' field of
0017 % the figure handle, unless instructed not to with 0 in userdata flag
0018 %
0019 % $Id: paint.m,v 1.2 2005/05/06 22:59:56 matthewbrett Exp $
0020 
0021 fig_struct_fields = {'Position', 'Units'};
0022 
0023 if nargin < 2
0024   params = [];
0025 end
0026 params = mars_struct('fillafromb', params, ...
0027              struct('refreshf', obj.refreshf,...
0028                 'clf', obj.clf, ...
0029                 'userdata', obj.userdata));
0030 
0031 % Fill any needed defaults
0032 obj = fill_defaults(obj); 
0033 
0034 % check if object can be painted
0035 if isempty(obj.img)
0036   warning('No images, object cannot be painted')
0037   return
0038 end
0039 
0040 % get coordinates for plane
0041 X=1;Y=2;Z=3;
0042 dims = obj.slicedef;
0043 xmm = dims(X,1):dims(X,2):dims(X,3);
0044 ymm = dims(Y,1):dims(Y,2):dims(Y,3);
0045 zmm = obj.slices;
0046 [y x] = meshgrid(ymm,xmm');
0047 vdims = [length(xmm),length(ymm),length(zmm)];
0048 
0049 % no of slices, and panels (an extra for colorbars)
0050 nslices = vdims(Z);
0051 minnpanels = nslices;
0052 cbars = 0;
0053 if ~isempty(obj.cbar)
0054   cbars = length(obj.cbar);
0055   minnpanels = minnpanels+cbars;
0056 end
0057 
0058 % Get figure data.  The figure may be dead, in which case we may want to
0059 % revive it.  If so, we set position etc as stored.
0060 % If written to, the axes may be specified already
0061 dead_f = ~ishandle(obj.figure);
0062 figno = figure(obj.figure);
0063 if dead_f
0064   set(figno, obj.figure_struct);
0065 end
0066 
0067 % (re)initialize axes and stuff
0068 
0069 % check if the figure is set up correctly
0070 if ~params.refreshf
0071   axisd = flipud(findobj(obj.figure, 'Type','axes','Tag', 'slice overlay panel'));
0072   npanels = length(axisd);
0073   if npanels < vdims(Z)+cbars;
0074     params.refreshf = 1;
0075   end
0076 end
0077 if params.refreshf
0078   % clear figure, axis store
0079   if params.clf, clf; end
0080   axisd = [];
0081 
0082   % prevent print inversion problems
0083   set(figno,'InvertHardCopy','off');
0084 
0085   % put copy of object into UserData for callbacks
0086   if params.userdata
0087     set(figno, 'UserData', obj);
0088   end
0089   
0090   % calculate area of display in pixels
0091   parea = obj.area.position;
0092   if ~strcmp(obj.area.units, 'pixels')
0093     ubu = get(obj.figure, 'units');
0094     set(obj.figure, 'units','pixels');
0095     tmp = get(obj.figure, 'Position');
0096     ascf = tmp(3:4);
0097     if ~strcmp(obj.area.units, 'normalized')
0098       set(obj.figure, 'units',obj.area.units);
0099       tmp = get(obj.figure, 'Position');
0100       ascf = ascf ./ tmp(3:4);
0101     end
0102     set(figno, 'Units', ubu);
0103     parea = parea .* repmat(ascf, 1, 2);
0104   end
0105   asz = parea(3:4);
0106   
0107   % by default, make most parsimonious fit to figure
0108   yxratio = length(ymm)*dims(Y,2)/(length(xmm)*dims(X,2));
0109   if isempty(obj.xslices)
0110     % iteration needed to optimize, surprisingly.  Thanks to Ian NS
0111     axlen(X,:)=asz(1):-1:1;
0112     axlen(Y,:)=yxratio*axlen(X,:);
0113     panels = floor(asz'*ones(1,size(axlen,2))./axlen);
0114     estnpanels = prod(panels);
0115     tmp = find(estnpanels >= minnpanels);
0116     if isempty(tmp)
0117       error('Whoops, cannot fit panels onto figure');
0118     end
0119     b = tmp(1); % best fitting scaling
0120     panels = panels(:,b);
0121     axlen = axlen(:, b);
0122   else
0123     % if xslices is specified, assume X is flush with X figure dimensions
0124     panels([X:Y],1) = [obj.xslices; 0];
0125     axlen([X:Y],1) = [asz(X)/panels(X); 0];
0126   end
0127   
0128   % Axis dimensions are in pixels.  This prevents aspect ratio rescaling
0129   panels(Y) = ceil(minnpanels/panels(X));
0130   axlen(Y) = axlen(X)*yxratio;
0131   
0132   % centre (etc) panels in display area as required
0133   divs = [Inf 2 1];the_ds = [0;0];
0134   the_ds(X) = divs(strcmp(obj.area.halign, {'left','center','right'}));
0135   the_ds(Y) = divs(strcmp(obj.area.valign, {'bottom','middle','top'}));
0136   startc = parea(1:2)' + (asz'-(axlen.*panels))./the_ds;
0137   
0138   % make axes for panels
0139   r=0;c=1;
0140   npanels = prod(panels);
0141   lastempty = npanels-cbars;
0142   for i = 1:npanels
0143     % panel userdata
0144     if i<=nslices
0145       u.type = 'slice';
0146       u.no   = zmm(i);
0147     elseif i > lastempty
0148       u.type = 'cbar';
0149       u.no   = i - lastempty;
0150     else
0151       u.type = 'empty';
0152       u.no   = i - nslices;
0153     end
0154     axpos = [r*axlen(X)+startc(X) (panels(Y)-c)*axlen(Y)+startc(Y) axlen'];
0155     axisd(i) = axes(...
0156     'Parent',figno,...
0157     'XTick',[],...
0158     'XTickLabel',[],...
0159     'YTick',[],...
0160     'YTickLabel',[],...
0161     'Box','on',...
0162     'XLim',[1 vdims(X)],...
0163     'YLim',[1 vdims(Y)],...
0164     'Units', 'pixels',...
0165     'Position',axpos,...
0166     'Tag','slice overlay panel',...
0167     'UserData',u);
0168     r = r+1;
0169     if r >= panels(X)
0170       r = 0;
0171       c = c+1;
0172     end
0173   end
0174 end
0175 
0176 % sort out labels
0177 if ischar(obj.labels)
0178   do_labels = ~strcmp(lower(obj.labels), 'none');
0179 else
0180   do_labels = 1;
0181 end
0182 if do_labels
0183   labels = obj.labels;
0184   if iscell(labels.format)
0185     if length(labels.format)~=vdims(Z)
0186       error(...
0187       sprintf('Oh dear, expecting %d labels, but found %d',...
0188           vdims(Z), length(labels.contents)));
0189     end
0190   else
0191     % format string for mm from AC labelling
0192     fstr = labels.format;
0193     labels.format = cell(vdims(Z),1);
0194     acpt = obj.transform * [0 0 0 1]';
0195     for i = 1:vdims(Z)
0196       labels.format(i) = {sprintf(fstr,zmm(i)-acpt(Z))};
0197     end
0198   end
0199 end
0200 
0201 % split images into picture and contour
0202 itypes = {obj.img(:).type};
0203 tmp = strcmpi(itypes, 'contour');
0204 contimgs = find(tmp);
0205 pictimgs = find(~tmp);
0206 
0207 % modify picture image colormaps with any new colours
0208 npimgs = length(pictimgs);
0209 lrn = zeros(npimgs,3);
0210 cmaps = cell(npimgs);
0211 for i = 1:npimgs
0212   cmaps(i)={obj.img(pictimgs(i)).cmap};
0213   lrnv = {obj.img(pictimgs(i)).outofrange{:}, obj.img(pictimgs(i)).nancol};
0214   for j = 1:length(lrnv)
0215     if prod(size(lrnv{j}))==1
0216       lrn(i,j) = lrnv{j};
0217     else
0218       cmaps(i) = {[cmaps{i}; lrnv{j}(1:3)]};
0219       lrn(i,j) = size(cmaps{i},1);
0220     end
0221   end
0222 end
0223 
0224 % cycle through slices displaying images
0225 nvox = prod(vdims(1:2));
0226 pandims = [vdims([2 1]) 3]; % NB XY transpose for display
0227 
0228 zimg = zeros(pandims);
0229 for i = 1:nslices
0230   ixyzmm = [x(:)';y(:)';ones(1,nvox)*zmm(i);ones(1,nvox)];
0231   img = zimg;
0232   for j = 1:npimgs
0233     thisimg = obj.img(pictimgs(j));
0234     i1 = sf_slice2panel(thisimg, ixyzmm, obj.transform, vdims);
0235     % rescale to colormap
0236     [csdata badvals]= pr_scaletocmap(...
0237     i1,...
0238     thisimg.range(1),...
0239     thisimg.range(2),...
0240     thisimg.cmap,...
0241     lrn(j,:));
0242     % take indices from colormap to make true colour image
0243     iimg = reshape(cmaps{j}(csdata(:),:),pandims);
0244     tmp = repmat(logical(~badvals),[1 1 3]);
0245     if strcmpi(thisimg.type, 'truecolour') 
0246       img(tmp) = img(tmp) + iimg(tmp)*thisimg.prop;
0247     else % split colormap effect
0248       img(tmp) = iimg(tmp)*thisimg.prop;
0249     end
0250   end
0251   % threshold out of range values
0252   img(img>1) = 1;
0253   
0254   image('Parent', axisd(i),...
0255     'ButtonDownFcn', obj.callback,...
0256     'CData',img);
0257 
0258   
0259   % do contour plot
0260   for j=1:length(contimgs)
0261     thisimg = obj.img(contimgs(j));
0262     i1 = sf_slice2panel(thisimg, ixyzmm, obj.transform, vdims);
0263     if any(any(isfinite(i1)))
0264       i1(i1<min(thisimg.range))=min(thisimg.range);
0265       i1(i1>max(thisimg.range))=max(thisimg.range);
0266       if mars_struct('isthere', thisimg, 'linespec')
0267     linespec = thisimg.linespec;
0268       else
0269     linespec = 'w-';
0270       end
0271       axes(axisd(i));
0272       set(axisd(i),'NextPlot','add');
0273       if mars_struct('isthere', thisimg, 'contours')
0274     [c h] = contour(i1, thisimg.contours, linespec);
0275       else
0276     [c h] = contour(i1, linespec);
0277       end
0278       if ~isempty(h)
0279     if ~mars_struct('isthere', thisimg, 'linespec') 
0280       % need to reset colours
0281       % assumes contour value is in line UserData
0282       % as seemed to be the case
0283       convals = get(h, 'UserData');
0284       if ~iscell(convals),convals = {convals};end
0285       if ~isempty(convals)
0286         [csdata badvals] = pr_scaletocmap(...
0287         cat(1, convals{:}), ...
0288         thisimg.range(1),...
0289         thisimg.range(2),...
0290         thisimg.cmap,...
0291         [1 size(thisimg.cmap,1) 1]);
0292         colvals = thisimg.cmap(csdata(:),:)*thisimg.prop;
0293         set(h, {'Color'}, num2cell(colvals, 2));
0294       end
0295     end
0296     if mars_struct('isthere', thisimg, 'linewidth')
0297       set(h, 'LineWidth', thisimg.linewidth);
0298     end
0299       end
0300     end
0301   end  
0302 
0303   if do_labels
0304     text('Parent',axisd(i),...
0305      'Color', labels.colour,...
0306      'FontUnits', 'normalized',...
0307      'VerticalAlignment','bottom',...
0308      'HorizontalAlignment','left',...
0309      'Position', [1 1],...
0310      'FontSize',labels.size,...
0311      'ButtonDownFcn', obj.callback,...
0312      'String', labels.format{i});
0313   end
0314 end
0315 for i = (nslices+1):npanels
0316    set(axisd(i),'Color',[0 0 0]);
0317 end
0318 % add colorbar(s)
0319 for i = 1:cbars
0320   axno = axisd(end-cbars+i);
0321   cbari = obj.img(obj.cbar(i));
0322   cml = size(cbari.cmap,1);
0323   p = get(axno, 'Position');; % position of last axis
0324   cw = p(3)*0.2;
0325   ch = p(4)*0.75;
0326   pc = p(3:4)/2;
0327   [axlims idxs] = sort(cbari.range);
0328   a=axes(...
0329       'Parent',figno,...
0330       'XTick',[],...
0331       'XTickLabel',[],...
0332       'Units', 'pixels',...
0333       'YLim', axlims,...   
0334       'FontUnits', 'normalized',...
0335       'FontSize', 0.075,...
0336       'YColor',[1 1 1],...
0337       'Tag', 'cbar',...
0338       'Box', 'off',...
0339       'Position',[p(1)+pc(1)-cw/2,p(2)+pc(2)-ch/2,cw,ch]...
0340       );
0341   ih = image('Parent', a,...
0342     'YData', axlims(idxs),...     
0343     'CData', reshape(cbari.cmap,[cml,1,3]));
0344 end % colourbars
0345 
0346 % Get stuff for figure, in case it dies later
0347 obj.figure_struct = mars_struct('split', get(figno), fig_struct_fields);
0348 
0349 return
0350 
0351 % subfunctions
0352 % ------------
0353 
0354 function i1 = sf_slice2panel(img, xyzmm, transform, vdims)
0355 % to voxel space of image
0356 vixyz = inv(transform*img.vol.mat)*xyzmm;
0357 % raw data
0358 if mars_struct('isthere', img.vol, 'imgdata')
0359   V = img.vol.imgdata;
0360 else
0361   V = img.vol;
0362 end
0363 i1 = spm_sample_vol(V,vixyz(1,:),vixyz(2,:),vixyz(3,:), ...
0364             [img.hold img.background]);
0365 if mars_struct('isthere', img, 'func')
0366   eval(img.func);
0367 end
0368 % transpose to reverse X and Y for figure
0369 i1 = reshape(i1, vdims(1:2))';
0370 return

Generated on Wed 06-Jul-2005 18:07:21 by m2html © 2003