physics_data_mapper

PURPOSE ^

PHYSICS_DATA_MAPPER maps img.physics data to elem or node data

SYNOPSIS ^

function img = physics_data_mapper(img, reverse)

DESCRIPTION ^

PHYSICS_DATA_MAPPER maps img.physics data to elem or node data
 img = physics_data_mapper(img) will only work if there is only a single
 physics data field on the img, throwing an error otherwise. 
 For multi-physics images, img.physics_data_mapper must be specified. It
 can be either a name of the appropriate physics data field on the img, or
 a function that will handle the data differently.
 
 To avoid confusion, the physics currently in use by image data will be
 specified in a descriptive string tag img.current_physics

 img = physics_data_mapper(img, TRUE) will reverse the process updating
 the current physics with the data from img.elem_data or img.node_data.

 Examples:
  imdl = mk_common_model('a2c2',8);
  c = 3*ones(length(imdl.fwd_model.elems),1);
  img = eidors_obj('image','fwd_model',imdl.fwd_model);
  img.conductivity.elem_data = c;
  img = physics_data_mapper(img);

  img.resistivity.elem_data = 1./c;
  img.physics_data_mapper = 'resistivity';
  img = physics_data_mapper(img);

  img.physics_data_mapper = 'some_function_that_takes_an_image';
  img = physics_data_mapper(img);

 KNOWN ISSUES:
   - doesn't fully support image arrays

 See also: MK_IMAGE, SUPPORTED_PHYSICS

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function img = physics_data_mapper(img, reverse)
0002 %PHYSICS_DATA_MAPPER maps img.physics data to elem or node data
0003 % img = physics_data_mapper(img) will only work if there is only a single
0004 % physics data field on the img, throwing an error otherwise.
0005 % For multi-physics images, img.physics_data_mapper must be specified. It
0006 % can be either a name of the appropriate physics data field on the img, or
0007 % a function that will handle the data differently.
0008 %
0009 % To avoid confusion, the physics currently in use by image data will be
0010 % specified in a descriptive string tag img.current_physics
0011 %
0012 % img = physics_data_mapper(img, TRUE) will reverse the process updating
0013 % the current physics with the data from img.elem_data or img.node_data.
0014 %
0015 % Examples:
0016 %  imdl = mk_common_model('a2c2',8);
0017 %  c = 3*ones(length(imdl.fwd_model.elems),1);
0018 %  img = eidors_obj('image','fwd_model',imdl.fwd_model);
0019 %  img.conductivity.elem_data = c;
0020 %  img = physics_data_mapper(img);
0021 %
0022 %  img.resistivity.elem_data = 1./c;
0023 %  img.physics_data_mapper = 'resistivity';
0024 %  img = physics_data_mapper(img);
0025 %
0026 %  img.physics_data_mapper = 'some_function_that_takes_an_image';
0027 %  img = physics_data_mapper(img);
0028 %
0029 % KNOWN ISSUES:
0030 %   - doesn't fully support image arrays
0031 %
0032 % See also: MK_IMAGE, SUPPORTED_PHYSICS
0033 
0034 % (C) 2012 Bartlomiej Grychtol.
0035 % Licenced under GPL version 2 or 3
0036 % $Id: physics_data_mapper.m 4049 2013-05-23 11:43:36Z bgrychtol $
0037 
0038 if isstr(img) && strcmp(img,'UNIT_TEST'); do_unit_test; return; end
0039 
0040 if nargin < 2
0041    reverse = false;
0042 end
0043 % need to handle image arrays
0044 for i = 1:length(img)
0045    if reverse
0046       tmp(i) = map_data_to_physics(img(i));
0047    else
0048       tmp(i) = map_physics_to_data(img(i));
0049    end
0050 end
0051 img = tmp;
0052 end
0053 
0054 function img = map_physics_to_data(img);
0055 
0056 knownphysics = supported_physics;
0057 flds = fieldnames(img);
0058 phys = ismember(flds,knownphysics);
0059 
0060 switch sum(phys)
0061    case 0
0062       % no physics found, check for elem_data or node_data
0063       if ~( isfield(img,'elem_data') || isfield(img,'node_data'))
0064          error('No physics, elem_data or node_data found on img');
0065       else
0066          eidors_msg('@@@ No physics present on img. Assuming conductivity',3);
0067 % STUPID MATLAB CAN'T KEEP SYNTAX STRAIGHT BETWEEN VERSIONS
0068 %        img = setfield(img,{},'current_physics', 'conductivity');
0069 % NEED TO DO THIS, UGLY INEFFICIENT CODE
0070          for i=1:length(img)
0071             img(i).current_physics = 'conductivity';
0072          end
0073       end
0074       return      % returns img
0075    case 1
0076       ph = find(phys);
0077       if isfield(img.(flds{ph}),'func')
0078          % let the function handle the whole process
0079          img = feval(img.(flds{ph}).func, img);
0080          return
0081       else
0082          img = copy_physics_to_data(img, flds{ph});
0083       end
0084    otherwise
0085       % multiple physics
0086       try
0087          phys_fun = img.physics_data_mapper;
0088       catch
0089          error('Multiple physics found on img: img.physics_data_mapper required');
0090       end
0091       if ~isa(phys_fun, 'function_handle') && ismember(phys_fun,flds);
0092          img = copy_physics_to_data(img, phys_fun);
0093       else
0094          try
0095             img = feval(phys_fun,img);
0096          catch
0097             error('img.physics_data_mapper not understood');
0098          end
0099       end
0100 
0101 end
0102 end
0103 
0104 function img = copy_physics_to_data(img, phys)
0105 
0106 phys_flds = fieldnames(img.(phys));
0107 for i = 1:length(phys_flds)
0108    if isfield(img, phys_flds{i})
0109       eidors_msg('@@@ Overwriting img.%s',phys_flds{i},3);
0110       warning('EIDORS:OverwritingData', 'Overwriting img.%s',phys_flds{i});
0111    end
0112    % allow elem_data/node_data to be scalar
0113    if strcmp(phys_flds{i},'elem_data') && numel(img.(phys).elem_data) == 1
0114       n_elem = calc_num_elems(img.fwd_model);
0115       img.elem_data = ones(n_elem,1);
0116       img.elem_data(:) = img.(phys).elem_data;
0117    elseif strcmp(phys_flds{i},'node_data') 
0118       img.node_data = ones(size(img.fwd_model.nodes,1),1);
0119       img.node_data(:) = img.(phys).node_data;
0120    else
0121       img.(phys_flds{i}) = img.(phys).(phys_flds{i});
0122    end
0123 end
0124 img.current_physics = phys;
0125 end
0126 
0127 function n = calc_num_elems(fmdl)
0128 if isfield(fmdl, 'coarse2fine')
0129    n = size(fmdl.coarse2fine,2);
0130 else
0131    n = length(fmdl.elems);
0132 end
0133 end
0134 
0135 function img = copy_data_to_physics(img, phys)
0136 phys_flds = fieldnames(img.(phys));
0137 try
0138    for i = 1:length(phys_flds)
0139       img.(phys).(phys_flds{i}) = img.(phys_flds{i});
0140       img = rmfield(img, phys_flds{i});
0141    end
0142    img.current_physics = [];
0143 catch
0144    error('Fields specified by img.%s missing from img.',phys);
0145 end
0146 end
0147 
0148 function img = map_data_to_physics(img)
0149 try 
0150    curphys = img.current_physics;
0151 catch
0152    if isfield(img,'elem_data') || isfield(img, 'node_data')
0153       return % old type image, nothing to do
0154    else
0155       error('img.current_physics required');
0156    end
0157 end
0158 if ismember(curphys, fieldnames(img))
0159    img = copy_data_to_physics(img,curphys);
0160 elseif strcmp(curphys,'conductivity')
0161    % current_physics is conductivity, but there's no img.conductivity
0162    if ~any(ismember(fieldnames(img),supported_physics))
0163       % we're dealing with an old physics-oblivious image
0164       % nothing to do
0165       img.current_physics = [];
0166    else
0167       error('Cannot reverse %s mapping',curphys);
0168    end
0169 else
0170    try
0171       % user-provided physics_data_mapper must provide the reverse
0172       img = feval(curphys,img,1);
0173    catch 
0174       error('physics_data_mapper %s failed to reverse', curphys);
0175    end
0176 end
0177 end
0178 
0179 function do_unit_test
0180    ll = eidors_msg('log_level');
0181    eidors_msg('log_level',3);
0182    
0183    imdl = mk_common_model('a2c2',8);
0184    c = 3*ones(length(imdl.fwd_model.elems),1);
0185    img = eidors_obj('image','test_image','fwd_model',imdl.fwd_model)
0186    img.conductivity.elem_data = c;
0187    img = physics_data_mapper(img)
0188    
0189    img = physics_data_mapper(img) % give a msg at log_level 3
0190    
0191    img = physics_data_mapper(img,1) % reverse
0192    
0193    img.resistivity.elem_data = 1./c;
0194    img.physics_data_mapper = 'resistivity';
0195    img = physics_data_mapper(img)
0196    img.elem_data(1) %0.3333
0197    
0198    img.physics_data_mapper = @class; % some function that takes an image
0199    physics_data_mapper(img)
0200    
0201    eidors_msg('log_level',ll);
0202 end

Generated on Wed 29-May-2013 17:11:47 by m2html © 2005