0001 function out = mk_thorax_model(str, varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
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=='-')
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;
0110 end
0111 fmdl = fix_boundary(fmdl);
0112 STL.vertices = fmdl.nodes;
0113 STL.faces = fmdl.boundary;
0114 stl_write(STL,stlfile, 'txt');
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
0226
0227
0228
0229 end
0230
0231 function test_predef_models
0232 models = mk_thorax_model('list');
0233 n_models = numel(models);
0234
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
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