spm_eeg_invertiter.m 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. function [Dtest,modelF,allF]=spm_eeg_invertiter(Dtest,Npatchiter,funcname,patchind)
  2. % Function to perform several MSP type inversions with different
  3. % pseudo-randomly selected priors- in this case single cortical patches
  4. %
  5. % Npatchiter: number of iterations
  6. % funcname is name of MSP alogorithm: current (spm_eeg_invert) or classic (spm_eeg_invert_classic)
  7. % patchind is an optional list of indices of vertices which will be patch
  8. % centres. patchind will have size Npatchiter*Np (where Np is number of patches set in
  9. % inverse.Np )
  10. % if Dtest{1}.inv{val}.inverse.mergeflag==1 then merges Npatchiter posterior current
  11. % distributions, else replaces posterior with best of the iterations.
  12. % __________________________________________________________________________
  13. % Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging
  14. %
  15. % Gareth Barnes
  16. % $Id: spm_eeg_invertiter.m 6367 2015-03-09 15:02:25Z gareth $
  17. if nargin<2,
  18. Npatchiter=[];
  19. end;
  20. if nargin<3,
  21. error('No function call specified');
  22. end;
  23. if nargin<4,
  24. patchind=[];
  25. end;
  26. if isempty(Npatchiter),
  27. Npatchiter=16;
  28. end;
  29. if numel(Dtest)>1,
  30. error('only works with single datasets at the moment');
  31. end;
  32. val=Dtest{1}.val;
  33. Nvert=size(Dtest{1}.inv{val}.mesh.tess_mni.vert,1);
  34. Np=Dtest{1}.inv{val}.inverse.Np;
  35. allF=zeros(Npatchiter,1);
  36. fprintf('Checking leadfields');
  37. [L Dtest{1}] = spm_eeg_lgainmat(Dtest{1}); % Generate/load lead field- this stops it being done at each iteration
  38. if isempty(patchind),
  39. disp('Reseting random number seed ! and then generating random patch centres ');
  40. rand('state',0);
  41. %% make random patch centers, except on the first iteration when we keep to a fixed stepsize
  42. for f=1:Npatchiter,
  43. tmp=randperm(Nvert);
  44. allIp(f).Ip=tmp(1:Np);
  45. end;
  46. allIp(1).Ip=[]; %% fix the step size of the first patch set (uses default MSP indices)
  47. else
  48. for f=1:Npatchiter,
  49. allIp(f).Ip=patchind(f,:);
  50. end;
  51. end;
  52. modelF=[];
  53. bestF=-Inf;
  54. for patchiter=1:Npatchiter,
  55. %Din=Dtest{1};
  56. %Dout=Din;
  57. Ip=allIp(patchiter).Ip;
  58. disp(sprintf('patchiter %d/%d',patchiter,Npatchiter));
  59. switch funcname,
  60. case 'Classic',
  61. Dtest{1}.inv{val}.inverse.Ip=Ip;
  62. Dtest{1} = spm_eeg_invert_classic(Dtest{1});
  63. case 'Current',
  64. warning('Patch centres are currently fixed for this algorithm (iteration will have no effect!)');
  65. Dtest{1} = spm_eeg_invert(Dtest{1}); %
  66. %Dout.inv{val}.inverse.Ip=Ip;
  67. otherwise
  68. error('unknown function');
  69. end;
  70. if (Dtest{1}.inv{val}.inverse.mergeflag==1), %% will need all posteriors to merge them (could consider getting rid of worst ones here to save memory
  71. modelF(patchiter).inverse=Dtest{1}.inv{val}.inverse;
  72. else %% just keep track of best inversion
  73. if Dtest{1}.inv{val}.inverse.F>bestF,
  74. modelF(1).inverse=Dtest{1}.inv{val}.inverse;
  75. bestF=Dtest{1}.inv{val}.inverse.F;
  76. end;
  77. end;
  78. allF(patchiter)=Dtest{1}.inv{val}.inverse.F;
  79. end; % for patchiter
  80. %% will use these to merge posteriors or take best one
  81. [bestF,bestind]=max(allF);
  82. disp('model evidences relative to maximum:')
  83. sort(allF-bestF)
  84. %% for 1 iteration or for best solution
  85. Dtest{1}.inv{val}.inverse=modelF(1).inverse; %% return best model (only 1 model saved in this option)
  86. Dtest{1}.inv{val}.inverse.allF=allF;
  87. if Npatchiter>1, %% keep iterations if more than 1
  88. if (Dtest{1}.inv{val}.inverse.mergeflag==1)
  89. Dtest{1}.inv{val}.inverse=modelF(bestind).inverse; % start with best model so far
  90. Qpriors=sparse(zeros(Npatchiter,size(modelF(1).inverse.qC,1)));
  91. for patchiter=1:Npatchiter,
  92. Qpriors(patchiter,:)=modelF(patchiter).inverse.qC;
  93. end;
  94. disp('Merging posterior distributions..');
  95. ugainfiles=Dtest{1}.inv{val}.gainmat;
  96. surfind=ones(Npatchiter,1);
  97. %% now mix the posteriors
  98. [Dtest{1}] = spm_eeg_invert_classic_mix(Dtest{1},val,Qpriors,surfind,ugainfiles);
  99. Dtest{1}.inv{val}.comment{1}=sprintf('Merged posterior of %d solutions',Npatchiter);
  100. mixF=Dtest{1}.inv{val}.inverse.F;
  101. if mixF-bestF<0
  102. warning('Merged solution is worse than the best');
  103. end;
  104. disp(sprintf('Improvement (when +ve) over best iteration %3.2f',mixF-bestF));
  105. else % NO merge - just take the best
  106. disp('Using best patch set to current estimate');
  107. Dtest{1}.inv{val}.comment{1}=sprintf('Best F of %d solutions',Npatchiter);
  108. end; % if BMA
  109. end;
  110. spm_eeg_invert_display(Dtest{1});