mk_library_model

PURPOSE ^

MK_LIBRARY_MODEL - FEM models based on library shapes

SYNOPSIS ^

function out = mk_library_model(shape,elec_pos,elec_shape,maxsz,nfft,scale)

DESCRIPTION ^

MK_LIBRARY_MODEL - FEM models based on library shapes 

 MK_LIBRARY_MODEL(shape,elec_pos,elec_shape,maxsz,nfft) where:
   shape -  a cell array of strings and
     shape{1} is the shape_library model used
          (run shape_libary('list') to get a list
     shape{2} is the the boundary. If absent, 'boundary' is assumed.
     shape{3..} are strings specifying additional inclusions (such as
     lungs)
   elec_pos - a vector specifying electrode positions. See
     NG_MK_EXTRUDED_MODEL for details. To use the electrode positions
     stored in the 'electrode' field in the shape_libary, specify elec_pos
     as 'original'
   elec_shape - a vector specifying electrode shapes. See
     NG_MK_EXTRUDED_MODEL for details.
   maxsz - maximum FEM size (default: course mesh)
   nfft  - number of points to create along the boundary (default: 50)
     If nfft==0, no interpolation takes place.
   scale - avoids some Netgen issues by scaling the contours before 
     calling netgen and scaling the resulting model back afterwards
     (default: 1). Note that electrode and maxh specifications are not
     scaled.

 QUICK ACCESS TO COMMON MODELS:
   MK_LIBRARY_MODEL(str) where str is a single string specifying a model.
   Use MK_LIBRARY_MODEL('list') to obtain a list of available models.

 PATH TO LIBRARY MODELS
   'LIBRARY_PATH' - get or set library path

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function out = mk_library_model(shape,elec_pos,elec_shape,maxsz,nfft,scale)
0002 %MK_LIBRARY_MODEL - FEM models based on library shapes
0003 %
0004 % MK_LIBRARY_MODEL(shape,elec_pos,elec_shape,maxsz,nfft) where:
0005 %   shape -  a cell array of strings and
0006 %     shape{1} is the shape_library model used
0007 %          (run shape_libary('list') to get a list
0008 %     shape{2} is the the boundary. If absent, 'boundary' is assumed.
0009 %     shape{3..} are strings specifying additional inclusions (such as
0010 %     lungs)
0011 %   elec_pos - a vector specifying electrode positions. See
0012 %     NG_MK_EXTRUDED_MODEL for details. To use the electrode positions
0013 %     stored in the 'electrode' field in the shape_libary, specify elec_pos
0014 %     as 'original'
0015 %   elec_shape - a vector specifying electrode shapes. See
0016 %     NG_MK_EXTRUDED_MODEL for details.
0017 %   maxsz - maximum FEM size (default: course mesh)
0018 %   nfft  - number of points to create along the boundary (default: 50)
0019 %     If nfft==0, no interpolation takes place.
0020 %   scale - avoids some Netgen issues by scaling the contours before
0021 %     calling netgen and scaling the resulting model back afterwards
0022 %     (default: 1). Note that electrode and maxh specifications are not
0023 %     scaled.
0024 %
0025 % QUICK ACCESS TO COMMON MODELS:
0026 %   MK_LIBRARY_MODEL(str) where str is a single string specifying a model.
0027 %   Use MK_LIBRARY_MODEL('list') to obtain a list of available models.
0028 %
0029 % PATH TO LIBRARY MODELS
0030 %   'LIBRARY_PATH' - get or set library path
0031 
0032 % (C) 2011 Bartlomiej Grychtol. License: GPL version 2 or version 3
0033 % $Id: mk_library_model.m 6487 2022-12-28 14:42:32Z aadler $
0034 
0035 % Fill in defaults:
0036 if nargin < 6; scale = 1;          end
0037 if nargin < 5; nfft = 50;          end
0038 
0039 if ischar(shape)
0040     switch shape
0041         case 'LIBRARY_PATH'
0042             switch nargin
0043                 case 1
0044                     out = get_path;
0045                 case 2
0046                     set_path(elec_pos);
0047             end
0048         case 'list'
0049             out = list_predef_model_strings;
0050         case 'UNIT_TEST'
0051             out = do_unit_test; return;
0052         otherwise
0053             out = predef_model(shape);
0054             out = mdl_normalize(out, 0); % not normalized by default
0055     end
0056 else
0057    if ~iscell(shape)
0058       shape = {shape, 'boundary'};
0059    elseif numel(shape) == 1
0060       shape{2} = 'boundary';
0061    end
0062    fname = make_filename(shape,elec_pos,elec_shape,maxsz, nfft, scale);
0063    out = load_stored_model(fname);
0064    if ~isempty(out)
0065       return
0066    end
0067    s_shape = split_var_strings(shape(2:end));
0068    shapes = shape_library('get',shape{1},s_shape(1,:));
0069    if ~iscell(shapes), shapes = {shapes}; end
0070    %apply any indeces specified
0071    for i = 1:numel(shapes)
0072       eval(sprintf('shapes{i} = %f*shapes{i}%s;',scale,s_shape{2,i}));
0073    end
0074    if ischar(elec_pos) && strcmp(elec_pos,'original')
0075       el = shape_library('get',shape{1},'electrodes');
0076       electh= atan2(el(:,2),el(:,1))*180/pi;
0077       elec_pos = [electh,0.5*ones(size(electh))];
0078    end
0079    
0080    if nfft > 0
0081       [fmdl, mat_idx] = ng_mk_extruded_model({scale,shapes,[4,nfft],maxsz},...
0082          elec_pos,elec_shape);
0083    else
0084       [fmdl, mat_idx] = ng_mk_extruded_model({scale,shapes,0,maxsz},...
0085          elec_pos,elec_shape);
0086    end
0087    fmdl.nodes = fmdl.nodes/scale;
0088    fmdl.mat_idx = mat_idx;
0089    store_model(fmdl,fname)
0090    out = fmdl;
0091    out = mdl_normalize(out, 0); % not normalized by default
0092 end
0093 
0094 
0095 
0096 
0097 function out = load_stored_model(fname)
0098 out = [];
0099 fname = [get_path '/' fname '.mat'];
0100 if exist(fname,'file')
0101    eidors_msg('MK_LIBRARY_MODEL: Using stored model');
0102    if exist('OCTAVE_VERSION');
0103       load(file_in_loadpath(fname));
0104    else
0105       load(fname);
0106    end
0107    out = fmdl;
0108 end
0109 
0110 function store_model(fmdl,fname)
0111    fname = [get_path '/' fname '.mat'];
0112    if exist('OCTAVE_VERSION');
0113       savver = '-v7';
0114    else
0115       savver = '-v7.3';  
0116    end
0117    save(fname,savver,'fmdl');
0118 
0119 function out = build_if_needed(cmd,str)
0120 out = load_stored_model(str);
0121 if isempty(out)
0122    if ~iscell(cmd)
0123       cmd = {cmd};
0124    end 
0125    for i = 1:length(cmd)
0126       if i ==1
0127          eval(['out = ' cmd{i} ';']);
0128       else
0129          eval(cmd{i});
0130       end
0131    end
0132    store_model(out,str);
0133 end
0134 
0135 %%%%%
0136 % Lists predefined models (append when adding)
0137 function out = list_predef_model_strings
0138 out = {
0139     'adult_male_16el';
0140     'adult_male_32el';
0141     'adult_male_16el_lungs';
0142     'adult_male_32el_lungs';
0143     'adult_male_grychtol2016a_1x32';
0144     'adult_male_grychtol2016a_2x16';
0145     'adult_male_thorax_1x32';
0146     'adult_male_thorax_1x16';
0147     'adult_male_thorax_2x16';
0148     'adult_female_thorax_1x32';
0149     'adult_female_thorax_1x16';
0150     'adult_female_thorax_2x16';
0151     'cylinder_16x1el_coarse';
0152     'cylinder_16x1el_fine';
0153     'cylinder_16x1el_vfine';   
0154     'cylinder_16x2el_coarse';
0155     'cylinder_16x2el_fine';
0156     'cylinder_16x2el_vfine';
0157     'neonate_16el';
0158     'neonate_32el';
0159     'neonate_16el_lungs';
0160     'neonate_32el_lungs';
0161     'pig_23kg_16el';
0162     'pig_23kg_32el';
0163     'pig_23kg_16el_lungs';
0164     'pig_23kg_32el_lungs';
0165     'lamb_newborn_16el';
0166     'lamb_newborn_32el';
0167     'lamb_newborn_16el_lungs';
0168     'lamb_newborn_32el_lungs';
0169     'lamb_newborn_16el_organs';
0170     'lamb_newborn_32el_organs';
0171 %     'lamb_newborn_32el_organs';
0172     'beagle_16el';
0173     'beagle_32el';
0174     'beagle_16el_lungs';
0175     'beagle_32el_lungs';
0176     'beagle_16el_rectelec';
0177     'beagle_32el_rectelec';
0178     'beagle_16el_lungs_rectelec';
0179     'beagle_32el_lungs_rectelec';
0180     };
0181 
0182 %%%%%
0183 % Use predefined model
0184 function out = predef_model(str)
0185 switch str
0186     case 'adult_male_16el'
0187         out = mk_library_model({'adult_male','boundary'},...
0188             [16 1 0.5],[0.05],0.08);
0189     case 'adult_male_32el'
0190         out = mk_library_model({'adult_male','boundary'},...
0191             [32 1 0.5],[0.05],0.08);
0192     case 'adult_male_16el_lungs'
0193         out = mk_library_model({'adult_male','boundary','left_lung','right_lung'},...
0194             [16 1 0.5],[0.05],0.08);
0195     case 'adult_male_32el_lungs'
0196         out = mk_library_model({'adult_male','boundary','left_lung','right_lung'},...
0197             [32 1 0.5],[0.05],0.08);
0198     case 'adult_male_grychtol2016a_1x32'
0199         out = mk_thorax_model_grychtol2016a('1x32_ring');
0200         out = out.fwd_model;
0201     case 'adult_male_grychtol2016a_2x16'
0202         out = mk_thorax_model_grychtol2016a('2x16_planar');
0203         out = out.fwd_model;
0204     case 'adult_male_thorax_1x32'
0205        eth32 = cumsum([0.1 0.2*ones(1,15) 0.25 0.2*ones(1,15)])/6.45;
0206        ep = 360*eth32' - 90; ep(:,2) = 15;
0207        out = mk_thorax_model('male',ep,[5 0 .5],10);
0208     case 'adult_male_thorax_1x16'
0209        eth16 = cumsum([0.2 0.4*ones(1,7) 0.5 0.4*ones(1,7)])/6.5;
0210        ep = 360*eth16' - 90; ep(:,2) = 175;
0211        out = mk_thorax_model('male',ep,[5 0 .5],10);
0212     case 'adult_male_thorax_2x16'
0213        eth16 = cumsum([0.2 0.4*ones(1,7) 0.5 0.4*ones(1,7)])/6.5;
0214        ep1= 360*eth16' - 90; ep1(:,2) = 200;
0215        ep2= 360*eth16' - 90; ep2(:,2) = 150;
0216        out = mk_thorax_model('male',[ep1;ep2],[5 0 .5],10);
0217     case 'adult_female_thorax_1x32'
0218        eth32 = cumsum([0.1 0.2*ones(1,15) 0.25 0.2*ones(1,15)])/6.45;
0219        ep = 360*eth32' - 90; ep(:,2) = 175;
0220        out = mk_thorax_model('female',ep,[5 0 .5],10);
0221     case 'adult_female_thorax_1x16'
0222        eth16 = cumsum([0.2 0.4*ones(1,7) 0.5 0.4*ones(1,7)])/6.5;
0223        ep = 360*eth16' - 90; ep(:,2) = 175;
0224        out = mk_thorax_model('female',ep,[5 0 .5],10);
0225     case 'adult_female_thorax_2x16'
0226        eth16 = cumsum([0.2 0.4*ones(1,7) 0.5 0.4*ones(1,7)])/6.5;
0227        ep1= 360*eth16' - 90; ep1(:,2) = 200;
0228        ep2= 360*eth16' - 90; ep2(:,2) = 150;
0229        out = mk_thorax_model('female',[ep1;ep2],[5 0 .5],10);
0230         
0231     case 'cylinder_16x1el_coarse'
0232        out = build_if_needed(...
0233           'ng_mk_cyl_models([10,15],[16,5],[0.5,0,0.18])', str);
0234     case 'cylinder_16x1el_fine' 
0235        out = build_if_needed(...
0236           'ng_mk_cyl_models([10,15,1.1],[16,5],[0.5,0,0.15])',str);
0237     case 'cylinder_16x1el_vfine' 
0238         out = build_if_needed(...
0239            'ng_mk_cyl_models([10,15,0.8],[16,5],[0.5,0,0.08])',str);
0240     case 'cylinder_16x2el_coarse' 
0241         out = build_if_needed(...
0242            'ng_mk_cyl_models([30,15],[16,10,20],[0.5,0,0.18])',str);
0243     case 'cylinder_16x2el_fine'  
0244         out = build_if_needed(...
0245            'ng_mk_cyl_models([30,15,1.5],[16,10,20],[0.5,0,0.15])',str);
0246     case 'cylinder_16x2el_vfine' 
0247         out = build_if_needed(...
0248            'ng_mk_cyl_models([30,15,0.8],[16,10,20],[0.5,0,0.08])',str);
0249         
0250         
0251     case 'neonate_16el'
0252         out = mk_library_model({'neonate','boundary'},[16 1 0.5],[0.1 0 -1 0 60],0.08,49);
0253     case 'neonate_32el'
0254         out = mk_library_model({'neonate','boundary'},[32 1 0.5],[0.06 0 -1 0 60],0.08,49);
0255     case 'neonate_16el_lungs'
0256         out = mk_library_model({'neonate','boundary','left_lung','right_lung'},[16 1 0.5],[0.1 0 -1 0 60],0.08,49);
0257     case 'neonate_32el_lungs'
0258         out = mk_library_model({'neonate','boundary','left_lung','right_lung'},[32 1 0.5],[0.06 0 -1 0 60],0.08,49);
0259         
0260     case 'pig_23kg_16el'
0261         out = mk_library_model({'pig_23kg','boundary'},...
0262             [16 1 0.5],[0.05 0 -1 0 60],0.08);
0263     case 'pig_23kg_32el'
0264         out = mk_library_model({'pig_23kg','boundary'},...
0265             [32 1 0.5],[0.05 0 -1 0 60],0.08);
0266     case 'pig_23kg_16el_lungs'
0267         out = mk_library_model({'pig_23kg','boundary','lungs(1:2:end,:)'},...
0268             [16 1 0.5],[0.05 0 -1 0 60],0.08);
0269     case 'pig_23kg_32el_lungs'
0270         out = mk_library_model({'pig_23kg','boundary','lungs(1:2:end,:)'},...
0271             [32 1 0.5],[0.05 0 -1 0 60],0.08);    
0272 
0273     case 'lamb_newborn_16el'
0274 %        out = build_if_needed(...
0275 %           {['ng_mk_extruded_model({208,208*',...
0276 %             'shape_library(''get'',''lamb_newborn'',''boundary'')',...
0277 %             ',0,10},[16,1.995,104],[1])'],'out.nodes = out.nodes/204;'}, ...
0278 %           str);
0279          out = mk_library_model({'lamb_newborn','boundary'},[16,1.995,104],[1],10,0,208);
0280     case 'lamb_newborn_32el'
0281          % Very sensitive to the .980 offset. This is the only I can find that works.
0282          out = mk_library_model({'lamb_newborn','boundary'},[32,1.980,104],[1],15,50,208);
0283          out.electrode = out.electrode([2:32,1]);
0284     case 'lamb_newborn_16el_organs'
0285        out = mk_library_model({'lamb_newborn','boundary','lungs','heart'},[16,1.995,104],[1],10,0,208);
0286     case 'lamb_newborn_16el_lungs'
0287        out = mk_library_model({'lamb_newborn','boundary','lungs'},[16,1.995,104],[1],10,0,208);
0288     case 'lamb_newborn_32el_lungs'
0289          % Very sensitive to the .980 offset. This is the only I can find that works.
0290          out = mk_library_model({'lamb_newborn','boundary','lungs'},[32,1.980,104],[1],15,50,208);
0291          out.electrode = out.electrode([2:32,1]);
0292     case 'lamb_newborn_32el_organs'
0293          % Very sensitive to the .980 offset. This is the only I can find that works.
0294          out = mk_library_model({'lamb_newborn','boundary','lungs','heart'},[32,1.980,104],[1],15,50,208);
0295          out.electrode = out.electrode([2:32,1]);
0296 %     case 'lamb_newborn_32el_organs'
0297     case 'beagle_16el';
0298       scale = 49;
0299       out = mk_library_model({'beagle','boundary'}, ...
0300          [16 1 scale*0.5],[2,0,0.10],10,0,49);
0301     case 'beagle_32el';
0302       scale = 49;
0303       out = mk_library_model({'beagle','boundary'}, ...
0304          [32 1 scale*0.5],[2,0,0.10],10,0,49);
0305     case 'beagle_16el_rectelec';
0306       scale = 49;
0307       out = mk_library_model({'beagle','boundary'}, ...
0308          [16 1 scale*0.5],8*[0.25,1,0.05],10,0,49);
0309     case 'beagle_32el_rectelec';
0310       scale = 49;
0311       out = mk_library_model({'beagle','boundary'}, ...
0312          [16 1 scale*0.5],8*[0.25,1,0.05],10,0,49);
0313 
0314     case 'beagle_16el_lungs';
0315       scale = 49;
0316       out = mk_library_model({'beagle','boundary','left_lung','right_lung'}, ...
0317          [16 1 scale*0.5],[2,0,0.10],10,0,49);
0318 
0319     case 'beagle_16el_lungs_rectelec';
0320       scale = 49;
0321       out = mk_library_model({'beagle','boundary','left_lung','right_lung'}, ...
0322          [16 1 scale*0.5],8*[0.25,1,0.05],10,0,49);
0323 
0324     case 'beagle_32el_lungs';
0325       scale = 49;
0326       out = mk_library_model({'beagle','boundary','left_lung','right_lung'}, ...
0327          [32 1 scale*0.5],[2,0,0.10],10,0,49);
0328 
0329     case 'beagle_32el_lungs_rectelec';
0330       scale = 49;
0331       out = mk_library_model({'beagle','boundary','left_lung','right_lung'}, ...
0332          [32 1 scale*0.5],8*[0.25,1,0.05],10,0,49);
0333          
0334     otherwise
0335         error('No such model');
0336 end
0337 %give the model a name
0338 out.name = str;
0339 
0340 
0341 function str = make_filename(shape, elec_pos, elec_shape, ...
0342                              maxsz, nfft, scale);
0343 %at this point, shape is a cell array of strings e.g. {'pig_23kg','lungs')
0344 str = shape{1};
0345 shape(1) = []; %remove the first element
0346 shape = sort(shape); %sort the others
0347 for i = 1:numel(shape)
0348     str = [str '_' shape{i}];
0349 end
0350 str = [str '_EP'];
0351 for i = 1:numel(elec_pos)
0352     str = [str '_' num2str(elec_pos(i))];
0353 end
0354 str = [str '_ES'];
0355 if ischar(elec_shape)
0356     str = [str '_' elec_shape];
0357 else
0358     for i = 1:numel(elec_shape)
0359         str = [str '_' num2str(elec_shape(i))];
0360     end
0361 end
0362 if ~isempty(maxsz)
0363     str = [str '_maxsz_' num2str(maxsz)];
0364 end
0365 if ~isempty(nfft)
0366     str = [str '_nfft_' num2str(nfft)];
0367 end
0368 if ~isempty(scale)
0369     str = [str '_scale' num2str(scale)];
0370 end
0371 
0372 %remove colons
0373 str = strrep(str,':','-');
0374 
0375 function clean = split_var_strings(strc)
0376 for i = 1:numel(strc)
0377     [clean{1,i} clean{2,i}] = strtok(strc{i},'([{');
0378 end
0379 
0380 
0381 function out = get_path
0382 global eidors_objects
0383 out = eidors_objects.model_cache;
0384 
0385 function set_path(val)
0386 global eidors_objects
0387 eidors_objects.model_cache = val;
0388 %if folder doesn't exist, create it
0389 if ~exist(val,'dir')
0390     ver= eidors_obj('interpreter_version');
0391     if ver.ver<4 || ver.ver>=7
0392        mkdir(val);
0393     else
0394  % matlab 6.x has a stupid mkdir function
0395        system(['mkdir ',val]); 
0396     end
0397 end
0398 
0399 function out = do_unit_test
0400 models = mk_library_model('list');
0401 n_models = numel(models);
0402 sqrt_n_models = ceil(sqrt(n_models));
0403 for i = 1:numel(models)
0404     eidors_msg('\n\n\n DOING  MODEL (%s)\n\n\n',models{i},0);
0405     mdl = mk_library_model(models{i});
0406     img = mk_image(mdl,1);
0407     try   
0408         n = numel(mdl.mat_idx); 
0409     catch
0410         n =1; 
0411     end
0412     if n >1
0413         for j = 2:n
0414             img.elem_data(mdl.mat_idx{j}) = 0.25;
0415         end
0416     end
0417     subplot(sqrt_n_models, sqrt_n_models,i);
0418     show_fem(img,[0,1,0]); axis off;
0419     title(models{i},'Interpreter','none');
0420     drawnow
0421 end
0422 
0423 
0424 out = mk_library_model({'pig_23kg','boundary','lungs(1:2:end,:)'},[32 1 0.5],[0.05 0 -1 0 60],0.08);
0425

Generated on Fri 30-Dec-2022 19:44:54 by m2html © 2005