[Master Index] [Index for Toolbox]

overlapping_sphere

(Toolbox/overlapping_sphere.m in BrainStorm 2.0 (Alpha))


Function Synopsis

Sphere = overlapping_sphere(Channel,SubjectFV, VERBOSE, GRAPHICS)

Help Text

OVERLAPPING_SPHERE - Create overlapping spheres for E/MEG channels.
 function Sphere = overlapping_sphere(Channel,SubjectFV, VERBOSE, GRAPHICS)
 
 Channel is an array of structures.
 Channel.Loc, a matrix of locations of the sensor coil centers, one column per coil
 Channel.Orient, corresponding matrix of orientations, null in the case of EEG
 Channel.Weight, relative weights to each coil. Used here in the least-squares (default is 1).
 Channel.Type, 'MEG','EEG' are the only supported types
 Channel.Comment, unused here.

 SubjectFV.vertices contains the vertices information (3 x Nverts)
 SubjectFV.faces contains the corresponding faces information (Nfaces x 3)
  The faces information is used for determining the surface normals
  and for visualization.

 VERBOSE = 1 (optional), text info.
 GRAPHICS = 1 (optional), graphics displayed

 Sphere is an array of structures
 For each Channel, returns 
  Sphere.Center, a 3 x 1 center location and 
  Sphere.Radius, the corresponding radius.
  Sphere.Weight is a weighting vector for coloring the vertices to indicate
  the relative surface weights.
  Sphere.Approx is the identified surface weights on the sphere.

  Sphere.Center and Sphere.Radius should be transferred to fields in the 
   structure HeadModel.Param

Cross-Reference Information

This function calls
This function is called by

Listing of function C:\BrainStorm_2001\Toolbox\overlapping_sphere.m

function Sphere = overlapping_sphere(Channel,SubjectFV, VERBOSE, GRAPHICS)
%OVERLAPPING_SPHERE - Create overlapping spheres for E/MEG channels.
% function Sphere = overlapping_sphere(Channel,SubjectFV, VERBOSE, GRAPHICS)
% 
% Channel is an array of structures.
% Channel.Loc, a matrix of locations of the sensor coil centers, one column per coil
% Channel.Orient, corresponding matrix of orientations, null in the case of EEG
% Channel.Weight, relative weights to each coil. Used here in the least-squares (default is 1).
% Channel.Type, 'MEG','EEG' are the only supported types
% Channel.Comment, unused here.
%
% SubjectFV.vertices contains the vertices information (3 x Nverts)
% SubjectFV.faces contains the corresponding faces information (Nfaces x 3)
%  The faces information is used for determining the surface normals
%  and for visualization.
%
% VERBOSE = 1 (optional), text info.
% GRAPHICS = 1 (optional), graphics displayed
%
% Sphere is an array of structures
% For each Channel, returns 
%  Sphere.Center, a 3 x 1 center location and 
%  Sphere.Radius, the corresponding radius.
%  Sphere.Weight is a weighting vector for coloring the vertices to indicate
%  the relative surface weights.
%  Sphere.Approx is the identified surface weights on the sphere.
%
%  Sphere.Center and Sphere.Radius should be transferred to fields in the 
%   structure HeadModel.Param

%<autobegin> ---------------------- 16-Jun-2004 16:50:21 -----------------------
% --------- Automatically Generated Comments Block Using AUTO_COMMENTS ---------
%
% CATEGORY: Forward Modeling
%
% Alphabetical list of external functions (non-Matlab):
%   toolbox\bst_message_window.m
%   toolbox\colnorm.m
%   toolbox\overlapping_sphere_fmins.m
%   toolbox\plot3d.m
%   toolbox\source_grid.m
%   toolbox\tesselate.m
%   toolbox\view_surface.m
%   toolbox\weighting_scalar.m
%
% At Check-in: $Author: Mosher $  $Revision: 19 $  $Date: 6/16/04 3:16p $
%
% This software is part of BrainStorm Toolbox Version 2.0 (Alpha) 16-Jun-2004
% 
% Principal Investigators and Developers:
% ** Richard M. Leahy, PhD, Signal & Image Processing Institute,
%    University of Southern California, Los Angeles, CA
% ** John C. Mosher, PhD, Biophysics Group,
%    Los Alamos National Laboratory, Los Alamos, NM
% ** Sylvain Baillet, PhD, Cognitive Neuroscience & Brain Imaging Laboratory,
%    CNRS, Hopital de la Salpetriere, Paris, France
% 
% See BrainStorm website at http://neuroimage.usc.edu for further information.
% 
% Copyright (c) 2004 BrainStorm by the University of Southern California
% This software distributed  under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPL
% license can be found at http://www.gnu.org/copyleft/gpl.html .
% 
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%<autoend> ------------------------ 16-Jun-2004 16:50:21 -----------------------


% /---Script Author--------------------------------------\
% |                                                      |
% | *** John C. Mosher, Ph.D.                            |
% |  Biophysics Group                                    |
% \------------------------------------------------------/

% History ---------------------------------------------------- 
% Date of creation: Janurary 2001
% Date of modification: March 2002                  
%
% March 22, 2002 : SB Altered: Script header / response to VERBOSE mode
%                  / replaced FMINS by FMINSEARCH
% JCM 08-Sep-2003  Commenting
% JCM 18-Nov-2003 Replacing .Vertices and .Faces with .vertices and .faces 
%                 in the structure SubjectFV to be
%                 consistent with the bst_headmodeler call.
% SB  15-Jun-2004 Minor graphics enhancements
% ------------------------------------------------------------


% Calculate the Normals

if ~exist('VERBOSE','var') | isempty(VERBOSE),
   VERBOSE = 0; % default is silent running
end

if ~exist('GRAPHICS','var') | isempty(GRAPHICS),
   GRAPHICS = 0; % default is no display
end

%figure(windfind('Junk'))
% Matlab has the unusual spec of vertices being n x 3, not 3 x n, in patch.
hp = patch('faces',SubjectFV.faces,'vertices',SubjectFV.vertices','Visible','off');
Normals = get(hp,'VertexNormals');
[ignore,Normals] = colnorm(Normals'); % transpose and unit norm of each vertex
delete(hp)
%close(gcf)

Nc = length(Channel); % how many channels to process
% allocate
[Sphere(1:Nc)] = deal(struct('Center',[],'Radius',[],'Weight',[],'Approx',[]));

if VERBOSE
    hwait = waitbar(0,sprintf('Fitting Spheres to %.0f Channels',Nc));
    set(hwait,'units','norm'); % set units to normalized
    hwait_pos = get(hwait,'position');
    set(hwait,'position',[hwait_pos(1) 0.1 hwait_pos(3:4)]); % shift to bottom away from other images
    drawnow
end

for i = 1:Nc, % for each channel
    % Calculate the surface weight for the true shape
    if isempty(Channel(i).Weight)
        Channel(i).Weight = 1;    
    end
    
    Sphere(i).Weight = weighting_scalar(Channel(i).Loc,Channel(i).Orient,...
        Channel(i).Weight,SubjectFV.vertices, Normals);
    
    % initialize the guess of a sphere center as the weighted average of the
    % vertices
    %  tempCenter = mean(SubjectFV.vertices.*[[1;1;1]*Sphere(i).Weight],2); % weighted avg
    tempCenter = mean(SubjectFV.vertices,2);
    
    % distance from sensor to center is
    tempD = colnorm(Channel(i).Loc(:,1) - tempCenter);
    
    if(0)
        % initialize radius as average distance to center
        tempR = mean(colnorm(...
            SubjectFV.vertices - tempCenter(:,ones(1,size(SubjectFV.vertices,2)))));
    else
        % 11/5/99 above was nice idea, but sometimes yielded radii larger than sensor distance,
        %  due to neck region. So keep it easy
        tempR = min(.9*tempD,abs(tempD - 0.03)); % come in 3 cm, handle pathological cases
    end
    
    % grid something comparable
    testL = source_grid(tempD,tempR,1/1000,.3)'; % sparse sampling
    testL = [testL [testL(1:2,:);-testL(3,:)]]; % upper and lower hemispheres
    
    testL = testL + tempCenter(:,ones(1,size(testL,2)));
    
    % scan over this grid for weighting scalars, find the best match
    
    BestGridPt = 1; % assume first
    best_err = overlapping_sphere_fmins([testL(:,1);tempR],...
        Sphere(i).Weight,Channel(i).Loc,Channel(i).Orient,Channel(i).Weight,SubjectFV.vertices);
    for iGrid = 2:size(testL,2), % for each additional grid point
        test_err = overlapping_sphere_fmins([testL(:,iGrid);tempR],...
            Sphere(i).Weight,Channel(i).Loc,Channel(i).Orient,Channel(i).Weight,SubjectFV.vertices);
        if(test_err < best_err),
            BestGridPt = iGrid;
        end
    end
    
    % set start of search here.
    tempCenter = testL(:,iGrid);
    tempR = mean(colnorm(...
        SubjectFV.vertices - tempCenter(:,ones(1,size(SubjectFV.vertices,2)))));

    if VERBOSE 
        bst_message_window({...
                sprintf('Channel # %d / %d',i,length(Channel)),...    
                sprintf('Initial location is %2.2f %2.2f %2.2f (cm)',100*tempCenter),...
                sprintf('Initial radius is %2.2f (cm)',100*tempR)})
    end
        
    
    X = fminsearch('overlapping_sphere_fmins',[tempCenter;tempR],[],...
        Sphere(i).Weight,Channel(i).Loc,Channel(i).Orient,Channel(i).Weight,SubjectFV.vertices);
    Sphere(i).Center = X(1:3); % the location
    
    [err,sc,Radius] = overlapping_sphere_fmins(X,...
        Sphere(i).Weight,Channel(i).Loc,Channel(i).Orient,Channel(i).Weight,SubjectFV.vertices);
    Sphere(i).Radius = Radius; % the radius, mapped back depending on the Case Switch. 
    Sphere(i).Approx = sc;
    
    
    if VERBOSE,
       
       if GRAPHICS & i == 1,
          fig_os = figure;
          set(fig_os,'Name','Overlapping-Sphere Fitting')
          r = ceil(sqrt(length(Channel))); % Number of rows for following subplot
          c = ceil(sqrt(length(Channel)));
          FigName = get(fig_os,'Name');
       end
       
       bst_message_window({...
             sprintf('Final location is %2.2f %2.2f %2.2f (cm)',100*Sphere(i).Center),...
             sprintf('Final radius is %2.2f (cm)',100*Sphere(i).Radius),' '});
       
        
       if GRAPHICS,
          figure(fig_os)
          axx = subplot(r,c,i);
          if i == 1
              [hf,hs,hl] = view_surface(FigName,...
                  SubjectFV.faces,SubjectFV.vertices,abs(Sphere(i).Weight));
              set(hs,'facealpha',.8)
              set(hs,'edgecolor','flat');
              camlight, lighting gouraud    
          else % Spare time by just copying the basic scalp objects
              C = copyobj([hs,hl],axx);
              axes(axx)
              axis off, 
              hs = C(1);
          end
          hold on
          [ignore,ignore,ignore,SVerts,SFaces] = tesselate(Sphere(i).Radius,.15*Sphere(i).Radius,'full');
          SVerts = SVerts'; % columns are vertices
          [ignore,SNormals] = colnorm(SVerts);
          SVerts = SVerts + Sphere(i).Center*ones(1,size(SVerts,2));  
          % Channel graph object
          p=patch('vertices',SVerts','faces',SFaces','facecolor',[1 .8 .8],'edgecolor',[1 .5 .5]);
          plot3d(Channel(i).Loc','g+')
          set(p,'Facealpha',.6,'edgecolor','none')
          
          axis vis3d tight equal
          view(-90,0);
          drawnow
          
          figure(hwait) % bring to foreground
       end
       
       waitbar(i/Nc,hwait); % update waitbar
       drawnow
       
    end
    
end

if(VERBOSE),
    close(hwait);
end

return


Produced by color_mat2html, a customized BrainStorm 2.0 (Alpha) version of mat2html on Tue Oct 12 12:05:14 2004
Cross-Directory links are: ON