mk_thorax_model

PURPOSE ^

MK_THORAX_MODEL FEM models of the thorax

SYNOPSIS ^

function out = mk_thorax_model(str, varargin)

DESCRIPTION ^

MK_THORAX_MODEL FEM models of the thorax

 MK_THORAX_MODEL provides a shorthand to predefined thorax FEMs and 
 for using contributed models with PLACE_ELEC_ON_SURF. You may be asked
 to download missing files. Specialized MK_THORAX_MODEL_* functions
 provide additional presets and options.

 MK_THORAX_MODEL(shapestr,elec_pos, elec_shape, maxh) where:
  shapestr    - a string specifying the underlying model.
                Run MK_THORAX_MODEL('list_shapes') for a list.
  elec_pos    - a vector specifying electrode positions.
                See PLACE_ELEC_ON_SURF for details.
  elec_shape  - a vector specifying electrode shapes.
                See PLACE_ELEC_ON_SURF for details.
  This usage returns a fwd_model structure.

 MK_THORAX_MODEL(modelstr) provides quick access to predefined models.
 Run MK_THORAX_MODEL('list') for a list. This usage returns either a 
 fwd_model or an image structure. Specialized MK_THORAX_MODEL_* functions
 provide additional presets.

 MK_THORAX_MODEL('list_shapes') lists available thorax shapes without 
  electrodes.

 MK_THORAX_MODEL('list') lists available predefined models.


 See also: MK_THORAX_MODEL_BP3D, MK_THORAX_MODEL_GRYCHTOL2016a,
 PLACE_ELEC_ON_SURF, MK_LIBRARY_MODEL

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function out = mk_thorax_model(str, varargin)
0002 %MK_THORAX_MODEL FEM models of the thorax
0003 %
0004 % MK_THORAX_MODEL provides a shorthand to predefined thorax FEMs and
0005 % for using contributed models with PLACE_ELEC_ON_SURF. You may be asked
0006 % to download missing files. Specialized MK_THORAX_MODEL_* functions
0007 % provide additional presets and options.
0008 %
0009 % MK_THORAX_MODEL(shapestr,elec_pos, elec_shape, maxh) where:
0010 %  shapestr    - a string specifying the underlying model.
0011 %                Run MK_THORAX_MODEL('list_shapes') for a list.
0012 %  elec_pos    - a vector specifying electrode positions.
0013 %                See PLACE_ELEC_ON_SURF for details.
0014 %  elec_shape  - a vector specifying electrode shapes.
0015 %                See PLACE_ELEC_ON_SURF for details.
0016 %  This usage returns a fwd_model structure.
0017 %
0018 % MK_THORAX_MODEL(modelstr) provides quick access to predefined models.
0019 % Run MK_THORAX_MODEL('list') for a list. This usage returns either a
0020 % fwd_model or an image structure. Specialized MK_THORAX_MODEL_* functions
0021 % provide additional presets.
0022 %
0023 % MK_THORAX_MODEL('list_shapes') lists available thorax shapes without
0024 %  electrodes.
0025 %
0026 % MK_THORAX_MODEL('list') lists available predefined models.
0027 %
0028 %
0029 % See also: MK_THORAX_MODEL_BP3D, MK_THORAX_MODEL_GRYCHTOL2016a,
0030 % PLACE_ELEC_ON_SURF, MK_LIBRARY_MODEL
0031 
0032 % (C) 2015-2024 Bartlomiej Grychtol. License: GPL version 2 or 3
0033 % $Id: mk_thorax_model.m 7061 2024-12-08 16:40:33Z aadler $
0034 
0035 if nargin>0 && ischar(str) 
0036    switch(str)
0037       case 'UNIT_TEST';
0038          do_unit_test; return;
0039       case 'list_shapes'
0040          out = list_basic_shapes; return;
0041       case 'list'
0042          out = list_predef_models; return;
0043    end
0044 end
0045 
0046 opt.fstr = 'mk_thorax_model';
0047 out = eidors_cache(@do_mk_thorax_model,[{str}, varargin(:)'],opt);
0048 switch out.type
0049    case 'image'
0050       out.fwd_model = mdl_normalize(out.fwd_model, 'default');
0051    case 'fwd_model'
0052       out = mdl_normalize(out, 'default');
0053    otherwise
0054       error('Produced struct with unrecognized type');
0055 end
0056 end
0057 
0058 function out = do_mk_thorax_model(str, elec_pos, elec_shape, maxh)
0059 
0060 if ismember(str,list_predef_models)
0061    out = build_predef_model(str);
0062    return
0063 end
0064 
0065 if ~ismember(str, list_basic_shapes)
0066    error('Shape str "%s" not understood.',str);
0067 end
0068 
0069 if ~any(str=='-') % basic shaps have no hyphens
0070    out = build_basic_model(str);
0071    if nargin > 1
0072       out = place_elec_on_surf(out,elec_pos,elec_shape,[],maxh);
0073       out = fix_boundary(out);
0074    end
0075 else
0076    out = build_advanced_model(str, elec_pos, elec_shape, maxh);
0077 end
0078 end
0079 
0080 function ls = list_basic_shapes
0081    ls = {'male','female','bp3d','bp3d-organs'};
0082 end
0083 
0084 function out = build_basic_model(str)
0085 switch(str)
0086    case {'male', 'female'}
0087       out = eidors_cache(@remesh_at_model, {str});
0088    case 'bp3d'
0089       out = mk_thorax_model_bp3d();
0090 end
0091 end
0092 
0093 function out = build_advanced_model(str, elec_pos, elec_shape, maxh)
0094 switch(str)
0095    case {'bp3d-organs'}
0096       out = mk_thorax_model_bp3d(elec_pos, elec_shape, maxh, 'fine');
0097 end
0098 end
0099 
0100 function out = remesh_at_model(str)
0101    tmpnm  = tempname;
0102    
0103    stlfile = [tmpnm '.stl'];
0104    volfile = [tmpnm '.vol'];
0105    
0106    contrib = 'at-thorax-mesh'; file =  sprintf('%s_t_mdl.mat',str);
0107    load(get_contrib_data(contrib,file));
0108    if strcmp(str,'male')
0109       fmdl.nodes = fmdl.nodes - 10; % center the model
0110    end
0111    fmdl = fix_boundary(fmdl);
0112    STL.vertices = fmdl.nodes;
0113    STL.faces    = fmdl.boundary;
0114    stl_write(STL,stlfile, 'txt'); % netgen only works well with txt files
0115    opt.stloptions.yangle = 55;
0116    opt.stloptions.edgecornerangle = 5;
0117    opt.meshoptions.fineness = 6;
0118    opt.options.meshsize = 30;
0119    opt.options.minmeshsize = 10;
0120    opt.stloptions.resthsurfcurvfac = 2;
0121    opt.stloptions.resthsurfcurvenable = 1;
0122    opt.stloptions.chartangle = 30;
0123    opt.stloptions.outerchartangle = 90;
0124    ng_write_opt(opt);
0125    call_netgen(stlfile,volfile);
0126    out=ng_mk_fwd_model(volfile,[],[],[],[]);
0127    delete(stlfile);
0128    delete(volfile);
0129    delete('ng.opt');
0130    
0131    out = rmfield(out,...
0132       {'mat_idx','boundary_numbers'});
0133    
0134 end
0135 
0136 
0137 function ls = list_predef_models
0138    ls = {'adult_male_bp3d_1x32'
0139          'adult_male_bp3d_2x16'
0140          'adult_male_bp3d_1x32_organs'
0141          'adult_male_bp3d_2x16_organs'
0142          'adult_male_grychtol2016a_1x32'
0143          'adult_male_grychtol2016a_2x16'
0144          'adult_male_thorax_1x32'
0145          'adult_male_thorax_1x16'
0146          'adult_male_thorax_2x16'
0147          'adult_female_thorax_1x32'
0148          'adult_female_thorax_1x16'
0149          'adult_female_thorax_2x16'};
0150 end
0151 
0152 function out = build_predef_model(str)
0153    switch str
0154       case 'adult_male_grychtol2016a_1x32'
0155          out = mk_thorax_model_grychtol2016a('1x32_ring');
0156          
0157       case 'adult_male_grychtol2016a_2x16'
0158          out = mk_thorax_model_grychtol2016a('2x16_planar');
0159 
0160       case 'adult_male_bp3d_1x32'
0161          out = mk_thorax_model_bp3d('1x32_ring');
0162 
0163       case 'adult_male_bp3d_2x16'
0164          out = mk_thorax_model_bp3d('2x16_planar');
0165 
0166       case 'adult_male_bp3d_1x32_organs'
0167          out = mk_thorax_model_bp3d('1x32_ring', 'fine');
0168 
0169       case 'adult_male_bp3d_2x16_organs'
0170          out = mk_thorax_model_bp3d('2x16_planar', 'fine');
0171 
0172       case 'adult_male_thorax_1x32'
0173          eth32 = cumsum([0.1 0.2*ones(1,15) 0.25 0.2*ones(1,15)])/6.45;
0174          ep = 360*eth32' - 90; ep(:,2) = 175;
0175          out = mk_thorax_model('male',ep,[5 0 .5],10);
0176       case 'adult_male_thorax_1x16'
0177          eth16 = cumsum([0.2 0.4*ones(1,7) 0.5 0.4*ones(1,7)])/6.5;
0178          ep = 360*eth16' - 90; ep(:,2) = 175;
0179          out = mk_thorax_model('male',ep,[5 0 .5],10);
0180       case 'adult_male_thorax_2x16'
0181          eth16 = cumsum([0.2 0.4*ones(1,7) 0.5 0.4*ones(1,7)])/6.5;
0182          ep1= 360*eth16' - 90; ep1(:,2) = 200;
0183          ep2= 360*eth16' - 90; ep2(:,2) = 150;
0184          out = mk_thorax_model('male',[ep1;ep2],[5 0 .5],10);
0185       case 'adult_female_thorax_1x32'
0186          eth32 = cumsum([0.1 0.2*ones(1,15) 0.25 0.2*ones(1,15)])/6.45;
0187          ep = 360*eth32' - 90; ep(:,2) = 175;
0188          out = mk_thorax_model('female',ep,[5 0 .5],10);
0189       case 'adult_female_thorax_1x16'
0190          eth16 = cumsum([0.2 0.4*ones(1,7) 0.5 0.4*ones(1,7)])/6.5;
0191          ep = 360*eth16' - 90; ep(:,2) = 175;
0192          out = mk_thorax_model('female',ep,[5 0 .5],10);
0193       case 'adult_female_thorax_2x16'
0194          eth16 = cumsum([0.2 0.4*ones(1,7) 0.5 0.4*ones(1,7)])/6.5;
0195          ep1= 360*eth16' - 90; ep1(:,2) = 250;
0196          ep2= 360*eth16' - 90; ep2(:,2) = 175;
0197          out = mk_thorax_model('female',[ep1;ep2],[5 0 .5],10);
0198    end
0199 end
0200 
0201 
0202 function do_unit_test
0203    clf
0204    test_predef_models;
0205    figure
0206    subplot(221)
0207    show_fem(mk_thorax_model('male'));
0208    
0209    subplot(222)
0210    show_fem(mk_thorax_model('female'));
0211 
0212    subplot(223)
0213    eth16 = 360*cumsum([0.2 0.4*ones(1,7) 0.5 0.4*ones(1,7)])/6.5 - 90; eth16 = eth16';
0214    eth32 = 360*cumsum([0.1 0.2*ones(1,15) 0.25 0.2*ones(1,15)])/6.45 - 90; eth32 = eth32';
0215    ep = eth16; ep(:,2) = 150;
0216    ep(17:48,1) = eth32; ep(17:48,2) = 175;
0217    ep(49:64,1) = eth16; ep(49:64,2) = 200;
0218    mdl = mk_thorax_model('male',ep,[5 0 .5],10);
0219    show_fem(mdl);
0220 
0221    subplot(224)
0222    mdl = mk_thorax_model('female',ep,[5 0 .5],10);
0223    show_fem(mdl);
0224 
0225    % This doens't work with mk_thorax_model
0226 %  ng_write_opt('MSZCYLINDER',[0,0,50,0,0,60,180,5]);
0227 %  show_fem(mk_thorax_model('male'));
0228    
0229 end
0230 
0231 function test_predef_models
0232    models = mk_thorax_model('list');
0233    n_models = numel(models);
0234 %    sqrt_n_models = ceil(sqrt(n_models));
0235    error_list = {};
0236    for i = 1:numel(models)
0237       eidors_msg('\n\n\n DOING  MODEL (%s)\n\n\n',models{i},0);
0238       try
0239          mdl = mk_thorax_model(models{i});
0240       catch
0241          error_list = [error_list, models(i)];
0242          continue;
0243       end
0244    
0245 %       subplot(sqrt_n_models, sqrt_n_models,i);
0246       show_fem(mdl,[0,1,0]); axis off;
0247       title(models{i},'Interpreter','none');
0248       drawnow
0249    end
0250    if ~isempty(error_list)
0251       disp('There were errors in generating the following models:')
0252       disp(error_list);
0253    end
0254 end

Generated on Sun 29-Dec-2024 11:41:59 by m2html © 2005