spm_eeg_lgainmat.m 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. function [L,D] = spm_eeg_lgainmat(D,Is,channels)
  2. % Load or compute if necessary a gain matrix
  3. % FORMAT [L,D] = spm_eeg_lgainmat(D,Is,channels)
  4. % D - Data structure
  5. % Is - indices of vertices
  6. %
  7. % L - Lead-field or gain matrix L(:,Is)
  8. %__________________________________________________________________________
  9. % Copyright (C) 2008-2017 Wellcome Trust Centre for Neuroimaging
  10. % Karl Friston
  11. % $Id: spm_eeg_lgainmat.m 7255 2018-02-07 22:06:07Z vladimir $
  12. SVNrev = '$Rev: 7255 $';
  13. %-Get gain or lead-field matrix
  14. %--------------------------------------------------------------------------
  15. val = D.val;
  16. forward = D.inv{val}.forward;
  17. for ind = 1:numel(forward)
  18. modality = forward(ind).modality;
  19. %-Channels
  20. %----------------------------------------------------------------------
  21. if isequal(modality, 'MEG')
  22. chanind = D.indchantype({'MEG', 'MEGPLANAR'}, 'GOOD');
  23. else
  24. chanind = D.indchantype(modality, 'GOOD');
  25. end
  26. if ~isempty(chanind)
  27. forward(ind).channels = D.chanlabels(chanind);
  28. else
  29. error(['No good ' modality ' channels were found.']);
  30. end
  31. end
  32. if nargin < 3
  33. channels = [forward(:).channels];
  34. end
  35. try
  36. fname = D.inv{val}.gainmat;
  37. G = load(fullfile(D.path, fname)); % Relative path
  38. label = G.label;
  39. G = G.G;
  40. if numel(label) ~= size(G, 1) || ~all(ismember(channels, label))
  41. error('Gain matrix has an incorrect number of channels.');
  42. end
  43. catch
  44. spm('sFnBanner', mfilename, SVNrev);
  45. spm('Pointer', 'Watch');
  46. G = {};
  47. label = {};
  48. for ind = 1:numel(forward)
  49. %-Create a new lead-field matrix
  50. %==================================================================
  51. %-Head Geometry (create tesselation file)
  52. %------------------------------------------------------------------
  53. vert = forward(ind).mesh.vert;
  54. face = forward(ind).mesh.face;
  55. %-Normals
  56. %------------------------------------------------------------------
  57. norm = spm_mesh_normals(struct('faces',face,'vertices',vert),true);
  58. vol = forward(ind).vol;
  59. if ischar(vol)
  60. vol = ft_read_vol(vol);
  61. end
  62. modality = forward(ind).modality;
  63. if isfield(forward, 'siunits') && forward(ind).siunits
  64. units = D.units(D.indchannel(forward(ind).channels));
  65. sens = forward(ind).sensors;
  66. siunits = isempty(strmatch('unknown', units));
  67. else
  68. siunits = false;
  69. sens = D.inv{val}.datareg(ind).sensors;
  70. end
  71. %-Forward computation
  72. %------------------------------------------------------------------
  73. [vol, sens] = ft_prepare_vol_sens(vol, sens, 'channel', forward(ind).channels);
  74. nvert = size(vert, 1);
  75. spm_progress_bar('Init', nvert, ['Computing ' modality ' leadfields']);
  76. if nvert > 100, Ibar = floor(linspace(1, nvert,100));
  77. else Ibar = [1:nvert]; end
  78. if ~isequal(ft_voltype(vol), 'interpolate')
  79. Gxyz = zeros(length(forward(ind).channels), 3*nvert);
  80. for i = 1:nvert
  81. if siunits
  82. Gxyz(:, (3*i - 2):(3*i)) = ft_compute_leadfield(vert(i, :), sens, vol,...
  83. 'dipoleunit', 'nA*m', 'chanunit', units);
  84. else
  85. Gxyz(:, (3*i - 2):(3*i)) = ft_compute_leadfield(vert(i, :), sens, vol);
  86. end
  87. if any(Ibar == i)
  88. spm_progress_bar('Set', i);
  89. end
  90. end
  91. else
  92. if siunits
  93. Gxyz = ft_compute_leadfield(vert, sens, vol, 'dipoleunit', 'nA*m', 'chanunit', units);
  94. else
  95. Gxyz = ft_compute_leadfield(vert, sens, vol);
  96. end
  97. end
  98. spm_progress_bar('Clear');
  99. spm_progress_bar('Init', nvert, ['Orienting ' modality ' leadfields']);
  100. G{ind} = zeros(size(Gxyz, 1), size(Gxyz, 2)/3);
  101. for i = 1:nvert
  102. G{ind}(:, i) = Gxyz(:, (3*i- 2):(3*i))*norm(i, :)';
  103. if ismember(i,Ibar)
  104. spm_progress_bar('Set', i);
  105. end
  106. end
  107. spm_progress_bar('Clear');
  108. %-Condition the scaling of the lead-field
  109. %------------------------------------------------------------------
  110. [Gs, scale] = spm_cond_units(G{ind});
  111. if siunits && abs(log10(scale))>2
  112. warning(['Scaling expected to be 1 for SI units, actual scaling ' num2str(scale)]);
  113. G{ind} = Gs;
  114. else
  115. scale = 1;
  116. end
  117. label = [label; forward(ind).channels(:)];
  118. forward(ind).scale = scale;
  119. end
  120. if numel(G) > 1
  121. G = cat(1, G{:});
  122. else
  123. G = G{1};
  124. end
  125. %-Save
  126. %----------------------------------------------------------------------
  127. D.inv{val}.gainmat = ['SPMgainmatrix_' spm_file(D.fname, 'basename') '_' num2str(val) '.mat'];
  128. save(fullfile(D.path, D.inv{val}.gainmat), 'G', 'label', spm_get_defaults('mat.format'));
  129. D.inv{val}.forward = forward;
  130. save(D);
  131. spm('Pointer', 'Arrow');
  132. end
  133. [sel1, sel2] = spm_match_str(channels, label);
  134. if length(sel2) ~= numel(channels)
  135. error('Did not find a match for all the requested channels.');
  136. end
  137. L = sparse(G(sel2, :));
  138. %-Retain selected sources if necessary
  139. %--------------------------------------------------------------------------
  140. if nargin > 1 && ~isempty(Is)
  141. L = L(:,Is);
  142. end
  143. D.inv{val}.forward = forward;