mk_lung_image

PURPOSE ^

MK_LUNG_IMAGE create an image with lung and heart contrasts from a model

SYNOPSIS ^

function img = mk_lung_image(mdl, opt, cmd)

DESCRIPTION ^

MK_LUNG_IMAGE create an image with lung and heart contrasts from a model
 MK_LUNG_IMAGE defines the lungs, heart and diaphragm as ellipsoids and
 creates an image with these organs out of the supplied eidors fwd_model.

 Typical usage:

 IMG = MK_LUNG_IMAGE(MDL) uses default options for shape, position and
  contrast. 
 IMG = MK_LUNG_IMAGE(MDL, OPT) uses the specified options (see below).
 IMG = MK_LUNG_IMAGE(MDL, OPT, 'show') also generate a figure with 4 views
  of the produced image

 Additional utilities:

 OPT = MK_LUNG_IMAGE(MDL,'options') returns the default options for the 
  given model, and does not generate an image.
 MK_LUNG_IMAGE(MDL, OPT, 'diagnostic') shows the supplied model together 
  with the organ ellipsoids as defined by the supplied options. This usage
  has no return parameters.

 The options input OPT is a struct with the following fields and defaults:
             bkgnd_val: 1          - image value for the background
              lung_val: 0.2000     - image value for the lungs
             heart_val: 1.5000     - image value for the hearts
      left_lung_center: ctr + [  .24    0   -1/3]*scale
     right_lung_center: ctr + [ -.24    0   -1/3]*scale
          heart_center: ctr + [ 0.07  -1/6     0]*scale
      diaphragm_center: ctr + [ 0     -1/4  -2/3]*scale
            heart_axes: [ 1/6  1/5   1/4 ]*scale
        left_lung_axes: [ 8/30 1/3  25/30]*scale
       right_lung_axes: [ 8/30 1/3  25/30]*scale
        diaphragm_axes: [22/30 19/30  2/5]*scale
 where ctr is the center of the bounding box of the model, and scale is 
 the smaller of the bounding box's x dimension divided by 7/6 and its y 
 dimension. Each organ is an ellipsoid with the corresponding center and
 axes. 
 NOTE that only options that deviate from defaults need be specified.

 Example:
    mdl = mk_thorax_model('female');       % female thorax
    img = mk_lung_image(mdl);
    subplot(131)
    show_fem(img) 
    % it seems that the heart definition goes outside the model
    % let's correct the default options
    opt = mk_lung_image(mdl, 'options');   % get default options 
    corr = 20;
    opt.heart_center(2)        = opt.heart_center(2)      + corr;
    opt.left_lung_center(2)    = opt.left_lung_center(2)  + corr;
    opt.right_lung_center(2)   = opt.right_lung_center(2) + corr;
    opt.diaphragm_center(2)    = opt.diaphragm_center(2)  + corr;
    img = mk_lung_image(mdl, opt);
    subplot(132)
    show_fem(img)
    % it's hard to tell because the model has very big elements.
    % let's make a diagnostic plot to verify the organ definitions fit inside 
    % the model (independent of model maxh)
    subplot(133)
    mk_lung_image(mdl,opt,'diagnostic');  

 CITATION_REQUEST:
 AUTHOR: Bartlomiej Grychtol, Beat Müller and Andy Adler
 TITLE: 3D EIT image reconstruction with GREIT
 JOURNAL: Physiological Measurement
 VOL: 37
 YEAR: 2016

 See also: ELEM_SELECT, MK_THORAX_MODEL

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function img = mk_lung_image(mdl, opt, cmd)
0002 %MK_LUNG_IMAGE create an image with lung and heart contrasts from a model
0003 % MK_LUNG_IMAGE defines the lungs, heart and diaphragm as ellipsoids and
0004 % creates an image with these organs out of the supplied eidors fwd_model.
0005 %
0006 % Typical usage:
0007 %
0008 % IMG = MK_LUNG_IMAGE(MDL) uses default options for shape, position and
0009 %  contrast.
0010 % IMG = MK_LUNG_IMAGE(MDL, OPT) uses the specified options (see below).
0011 % IMG = MK_LUNG_IMAGE(MDL, OPT, 'show') also generate a figure with 4 views
0012 %  of the produced image
0013 %
0014 % Additional utilities:
0015 %
0016 % OPT = MK_LUNG_IMAGE(MDL,'options') returns the default options for the
0017 %  given model, and does not generate an image.
0018 % MK_LUNG_IMAGE(MDL, OPT, 'diagnostic') shows the supplied model together
0019 %  with the organ ellipsoids as defined by the supplied options. This usage
0020 %  has no return parameters.
0021 %
0022 % The options input OPT is a struct with the following fields and defaults:
0023 %             bkgnd_val: 1          - image value for the background
0024 %              lung_val: 0.2000     - image value for the lungs
0025 %             heart_val: 1.5000     - image value for the hearts
0026 %      left_lung_center: ctr + [  .24    0   -1/3]*scale
0027 %     right_lung_center: ctr + [ -.24    0   -1/3]*scale
0028 %          heart_center: ctr + [ 0.07  -1/6     0]*scale
0029 %      diaphragm_center: ctr + [ 0     -1/4  -2/3]*scale
0030 %            heart_axes: [ 1/6  1/5   1/4 ]*scale
0031 %        left_lung_axes: [ 8/30 1/3  25/30]*scale
0032 %       right_lung_axes: [ 8/30 1/3  25/30]*scale
0033 %        diaphragm_axes: [22/30 19/30  2/5]*scale
0034 % where ctr is the center of the bounding box of the model, and scale is
0035 % the smaller of the bounding box's x dimension divided by 7/6 and its y
0036 % dimension. Each organ is an ellipsoid with the corresponding center and
0037 % axes.
0038 % NOTE that only options that deviate from defaults need be specified.
0039 %
0040 % Example:
0041 %    mdl = mk_thorax_model('female');       % female thorax
0042 %    img = mk_lung_image(mdl);
0043 %    subplot(131)
0044 %    show_fem(img)
0045 %    % it seems that the heart definition goes outside the model
0046 %    % let's correct the default options
0047 %    opt = mk_lung_image(mdl, 'options');   % get default options
0048 %    corr = 20;
0049 %    opt.heart_center(2)        = opt.heart_center(2)      + corr;
0050 %    opt.left_lung_center(2)    = opt.left_lung_center(2)  + corr;
0051 %    opt.right_lung_center(2)   = opt.right_lung_center(2) + corr;
0052 %    opt.diaphragm_center(2)    = opt.diaphragm_center(2)  + corr;
0053 %    img = mk_lung_image(mdl, opt);
0054 %    subplot(132)
0055 %    show_fem(img)
0056 %    % it's hard to tell because the model has very big elements.
0057 %    % let's make a diagnostic plot to verify the organ definitions fit inside
0058 %    % the model (independent of model maxh)
0059 %    subplot(133)
0060 %    mk_lung_image(mdl,opt,'diagnostic');
0061 %
0062 % CITATION_REQUEST:
0063 % AUTHOR: Bartlomiej Grychtol, Beat Müller and Andy Adler
0064 % TITLE: 3D EIT image reconstruction with GREIT
0065 % JOURNAL: Physiological Measurement
0066 % VOL: 37
0067 % YEAR: 2016
0068 %
0069 % See also: ELEM_SELECT, MK_THORAX_MODEL
0070 
0071 % (C) 2015-2016 Bartlomiej Grychtol. License: GPL version 2 or 3
0072 % $Id: mk_lung_image.m 6485 2022-12-28 14:34:32Z aadler $
0073 
0074 citeme(mfilename);
0075 
0076 if nargin>0 && ischar(mdl) && strcmp(mdl,'UNIT_TEST')
0077    do_unit_test; return;
0078 end
0079 
0080 if nargin == 1, opt = struct; end
0081 returnopt = false;
0082 if nargin == 2 && ischar(opt) && strcmp(opt,'options')
0083    returnopt = true;
0084    clear opt;
0085    opt = struct;
0086 end
0087 opt = parse_opt(mdl,opt);
0088 if returnopt
0089    img = opt;
0090    return
0091 end
0092 
0093 if nargin == 3 && ischar(cmd) && strcmp(cmd, 'diagnostic')
0094    show_organs(mdl,opt);
0095    return
0096 end
0097 
0098 elem_data = define_elem_data(mdl, opt);
0099 
0100 img = mk_image(mdl,elem_data);
0101 
0102 if nargin==3 && ischar(cmd) && strcmp(cmd, 'show')
0103    show4views(img);
0104 end
0105 end
0106 
0107 function elem_data = define_elem_data(mdl, opt)
0108 
0109    el_str = '(x- %f).^2/%f^2 + (y- %f).^2/%f^2 + (z- %f).^2/%f^2 <= 1';
0110    pack = @(x,y) mat2cell(reshape([x' y']',1,[])',ones(1, 2*numel(x)))';
0111 
0112 
0113    args = pack(opt.left_lung_center, opt.left_lung_axes);
0114    ll_str = sprintf(el_str, args{:});
0115    ll_fcn = inline(ll_str,'x','y','z');
0116    left_lung = elem_select(mdl,ll_fcn);
0117 
0118    args = pack(opt.right_lung_center, opt.right_lung_axes);
0119    rl_str = sprintf(el_str, args{:});
0120    rl_fcn = inline(rl_str,'x','y','z');
0121    right_lung = elem_select(mdl,rl_fcn);
0122 
0123    lung = min(1,left_lung + right_lung);
0124 
0125    args = pack(opt.diaphragm_center, opt.diaphragm_axes);
0126    dia_str = sprintf(el_str, args{:});
0127    dia_fcn = inline(dia_str,'x','y','z');
0128    diaphragm = elem_select(mdl,dia_fcn);
0129 
0130    lung = max(0,lung - diaphragm);
0131 
0132    args = pack(opt.heart_center, opt.heart_axes);
0133    hrt_str = sprintf(el_str, args{:});
0134    hrt_fcn = inline(hrt_str,'x','y','z');
0135    heart = elem_select(mdl, hrt_fcn);
0136 
0137    lung = max(0, lung - heart);
0138 
0139    elem_data = ...
0140        opt.bkgnd_val ...
0141        - (opt.bkgnd_val-opt.lung_val)*lung ...
0142        - (opt.bkgnd_val-opt.heart_val)*heart;
0143 end
0144 
0145 function show_organs(mdl, opt)
0146    show_fem(mdl)
0147    hold on
0148    pack = @(x) mat2cell(x',ones(1,numel(x)))';
0149    args = pack([opt.left_lung_center opt.left_lung_axes]);
0150    [x y z] = ellipsoid(args{:});
0151    surf(x,y,z,'FaceColor','b');
0152 
0153    args = pack([opt.right_lung_center opt.right_lung_axes]);
0154    [x y z] = ellipsoid(args{:});
0155    surf(x,y,z,'FaceColor','b');
0156 
0157    args = pack([opt.heart_center opt.heart_axes]);
0158    [x y z] = ellipsoid(args{:});
0159    surf(x,y,z,'FaceColor','r');
0160 
0161 
0162    args = pack([opt.diaphragm_center opt.diaphragm_axes]);
0163    [x y z] = ellipsoid(args{:});
0164    surf(x,y,z,'FaceColor','g');
0165    hold off
0166 end
0167 
0168 function show4views(img)
0169     subplot(221)
0170     h = show_fem(img);
0171     set(h,'linewidth',.1)
0172     subplot(222)
0173     h = show_fem(img);
0174     set(h,'linewidth',.1)
0175     view([0 90])
0176     subplot(223)
0177     h = show_fem(img);
0178     set(h,'linewidth',.1)
0179     view([90,0])
0180     subplot(224)
0181     h = show_fem(img);
0182     set(h,'linewidth',.1)
0183     view([0 0])
0184 end
0185 
0186 function opt = parse_opt(fmdl,opt)
0187    minnode = min(fmdl.nodes);
0188    maxnode = max(fmdl.nodes);
0189    bb = maxnode-minnode;
0190    scale = min( bb(1:2) ./ [7/6 1]); % the default values below fit a model of these proportions best
0191    ctr = minnode + bb/2;
0192 
0193    opt = set_default(opt, 'bkgnd_val',          1  );
0194    opt = set_default(opt, 'lung_val' ,           .2);
0195    opt = set_default(opt, 'heart_val',          1.5);
0196     
0197    opt = set_default(opt, 'left_lung_center',  ctr + [  .24    0   -1/3]*scale);
0198    opt = set_default(opt, 'right_lung_center', ctr + [ -.24    0   -1/3]*scale);
0199    opt = set_default(opt, 'heart_center',      ctr + [ 0.07  -1/6     0]*scale);
0200    opt = set_default(opt, 'diaphragm_center',  ctr + [ 0     -1/4  -2/3]*scale);
0201    
0202    opt = set_default(opt, 'heart_axes',        [ 1/6  1/5   1/4 ]*scale);
0203    opt = set_default(opt, 'left_lung_axes' ,   [ 8/30 1/3  25/30]*scale);
0204    opt = set_default(opt, 'right_lung_axes',   [ 8/30 1/3  25/30]*scale);
0205    opt = set_default(opt, 'diaphragm_axes',    [22/30 19/30  2/5]*scale);
0206 end
0207 
0208 function s = set_default(s, fname, defval)
0209    if ~isfield(s,fname)
0210        s.(fname) = defval;
0211    end
0212 end
0213 
0214 
0215 function do_unit_test
0216 mdl = ng_mk_ellip_models([400 180 150 10],4,10);
0217 img = mk_lung_image(mdl);
0218 subplot(231)
0219 show_fem(img);
0220 
0221 % sclaing should have no effect
0222 mdl.nodes = 3*mdl.nodes;
0223 img = mk_lung_image(mdl);
0224 subplot(232)
0225 show_fem(img);
0226 
0227 % shorter model should show a "slice"
0228 mdl = ng_mk_ellip_models([200 180 150 10],4,10);
0229 img = mk_lung_image(mdl);
0230 subplot(233)
0231 show_fem(img);
0232 
0233 % it should still fit into the male torso
0234 mdl = mk_thorax_model('male');
0235 img = mk_lung_image(mdl);
0236 subplot(234)
0237 show_fem(img);
0238 
0239 % the female model seems to need adjustements
0240 mdl = mk_thorax_model('female');       % female thorax
0241 opt = mk_lung_image(mdl, 'options');   %
0242 corr = 20;
0243 opt.heart_center(2)        = opt.heart_center(2)      + corr;
0244 opt.left_lung_center(2)    = opt.left_lung_center(2)  + corr;
0245 opt.right_lung_center(2)   = opt.right_lung_center(2) + corr;
0246 opt.diaphragm_center(2)    = opt.diaphragm_center(2)  + corr;
0247 subplot(235)
0248 % make a diagnostic plot to verify the organ definitions fit inside the
0249 % model (independent of model maxh)
0250 mk_lung_image(mdl,opt,'diagnostic');  
0251 % show_fem(img);
0252 
0253 return
0254 
0255 mdl = mk_thorax_model('grychtol2016a_male_thorax');
0256 img = mk_lung_image(mdl);
0257 subplot(236)
0258 show_fem(img);
0259 
0260 end

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