eidors_obj

PURPOSE ^

EIDORS_OBJ: maintains EIDORS internals

SYNOPSIS ^

function [obj_id, extra_out] = eidors_obj(type,name, varargin )

DESCRIPTION ^

 EIDORS_OBJ: maintains EIDORS internals

 USAGE: to get eidors_version
     version = eidors_obj('eidors_version')

 USAGE: to get interpreter version:
     version = eidors_obj('interpreter_version')

 USAGE: to get path to EIDORS:
     path = eidors_obj('eidors_path');

 USAGE: to cache values (not recommended)
            obj_id = eidors_obj('set-cache',obj, cachename,value, [time])
     [obj, obj_id] = eidors_obj('get-cache',obj, cachename)

 this will get or set the values of cached properties of the object.

    example: % set jacobian
        obj_id = eidors_obj('set-cache',cache_obj, 'jacobian', J);

    example: % get jacobian or '[]' if not set
        [J, obj_id] = eidors_obj('get-cache',cache_obj, 'jacobian');

 It is recommended to combine in cache_obj the minimum set of variables on
 which the value to be cached depends.
    example: % cache_obj for jacobian
        cache_obj = {img.fwd_model.nodes, img.fwd_model.elems ...
                     img.elem_data, img.fwd_model.jacobian}

 NOTE that rather than directly using eidors_obj to set and get cache, it 
 is recommended to use eidors_cache with a function_handle.

   example:
        J = eidors_cache(@calc_jacobian_adjoint,img,'jacobian');

 See also: EIDORS_CACHE

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [obj_id, extra_out] = eidors_obj(type,name, varargin )
0002 % EIDORS_OBJ: maintains EIDORS internals
0003 %
0004 % USAGE: to get eidors_version
0005 %     version = eidors_obj('eidors_version')
0006 %
0007 % USAGE: to get interpreter version:
0008 %     version = eidors_obj('interpreter_version')
0009 %
0010 % USAGE: to get path to EIDORS:
0011 %     path = eidors_obj('eidors_path');
0012 %
0013 % USAGE: to cache values (not recommended)
0014 %            obj_id = eidors_obj('set-cache',obj, cachename,value, [time])
0015 %     [obj, obj_id] = eidors_obj('get-cache',obj, cachename)
0016 %
0017 % this will get or set the values of cached properties of the object.
0018 %
0019 %    example: % set jacobian
0020 %        obj_id = eidors_obj('set-cache',cache_obj, 'jacobian', J);
0021 %
0022 %    example: % get jacobian or '[]' if not set
0023 %        [J, obj_id] = eidors_obj('get-cache',cache_obj, 'jacobian');
0024 %
0025 % It is recommended to combine in cache_obj the minimum set of variables on
0026 % which the value to be cached depends.
0027 %    example: % cache_obj for jacobian
0028 %        cache_obj = {img.fwd_model.nodes, img.fwd_model.elems ...
0029 %                     img.elem_data, img.fwd_model.jacobian}
0030 %
0031 % NOTE that rather than directly using eidors_obj to set and get cache, it
0032 % is recommended to use eidors_cache with a function_handle.
0033 %
0034 %   example:
0035 %        J = eidors_cache(@calc_jacobian_adjoint,img,'jacobian');
0036 %
0037 % See also: EIDORS_CACHE
0038 
0039 % (C) 2005-10 Andy Adler. License: GPL version 2 or version 3
0040 % $Id: eidors_obj.m 5575 2017-06-21 02:26:53Z aadler $
0041 
0042 if nargin==0 || ~ischar(type)
0043    error('cannot call eidors_obj with no arguments');
0044 end
0045 
0046 switch type
0047    case 'set'
0048       obj_id= set_obj( name, varargin{:} );
0049    case 'get-cache'
0050       test_install
0051       obj_id = [];
0052       if status_check(varargin{1})
0053         [obj_id, extra_out] = get_cache_obj( name, varargin{:} );
0054       end
0055       
0056    case 'set-cache'
0057       test_install
0058       obj_id= [];
0059       if status_check(varargin{1})
0060           obj_id = set_cache_obj( name, varargin{:} );
0061       end
0062 
0063    case 'eidors_version'
0064       obj_id= '3.9';  % Update for New eidors version
0065       
0066    case 'eidors_path'
0067       global eidors_objects
0068       obj_id = eidors_objects.eidors_path;
0069 
0070    case 'interpreter_version'
0071       obj_id= test_versions;
0072 % TODO: Add these functions
0073 %  case 'eidors_path'
0074 %  case 'eidors_dev_path'
0075 %  case 'eidors_cache_path'
0076 
0077    case 'cache_init'
0078       cache_init;
0079       
0080    otherwise
0081       test_install
0082       obj_id= new_obj( type, name, varargin{:} );
0083 end
0084 
0085 function ok = status_check(name)
0086 ok = true;
0087 switch cache_status
0088     case 0
0089         ok = false;
0090     case 0.5
0091         dbs = dbstack;
0092         if cache_status(dbs(3).name) == 0
0093             ok = false;
0094         end
0095         if strcmp(dbs(3).name,'cache_shorthand') && cache_status(dbs(5).name) == 0
0096             ok = false;
0097         end
0098         if cache_status(name) == 0
0099            ok = false;
0100         end
0101 end
0102 
0103 function on = debug_status_check
0104 on = false;
0105 switch debug_status
0106     case 1
0107         on = true;
0108     case 0.5
0109         dbs = dbstack;
0110         if debug_status(dbs(3).name) == 1
0111             on = true;
0112         end
0113 end
0114 
0115 
0116 function out = cache_status(fname)
0117     global eidors_objects;
0118     if nargin == 0
0119         try
0120             out = eidors_objects.cache_enable;
0121         catch
0122             out = 1;
0123         end
0124     else
0125         out = ~any(strcmp(eidors_objects.cache_disabled_on,fname));
0126     end
0127 
0128     
0129 function out = debug_status(fname)   
0130    global eidors_objects;
0131    if nargin == 0
0132       try
0133          out = eidors_objects.debug_enable;
0134       catch
0135          out = 0;
0136       end
0137    else
0138       out = ~any(strcmp(eidors_objects.debug_enabled_on,fname));
0139    end
0140       
0141       
0142 function test_install
0143   global eidors_objects;
0144   if isfield(eidors_objects,'max_cache_size'); return; end % OK
0145   error('EIDORS not correctly started. Did you do ">>run /path/to/eidors/startup"');
0146 
0147 function verstr = test_versions;
0148       ver= version; ver(ver=='.')=' ';
0149       ver = sscanf(ver,'%f'); ver=ver(:);
0150 
0151       % Convert 7.8.1 to 7.008001
0152       verstr.ver = 1e-3.^(0:length(ver)-1) * ver(:); 
0153 
0154       if exist('OCTAVE_VERSION') == 5
0155          verstr.isoctave = 1;
0156       else
0157          verstr.isoctave = 0;
0158       end
0159 
0160       cptr = computer;
0161       if strcmp(cptr(end+(-1:0)), '64')
0162          verstr.is64bit = 1;
0163       else
0164          verstr.is64bit = 0;
0165       end
0166 
0167 function obj = set_obj( obj, varargin );
0168    global eidors_objects;
0169 
0170 %  eidors_objects.( obj_id ) = obj;
0171 %  eidors_objects.( obj_id ).cache= []; %clear cache
0172 %
0173 
0174    for idx= 1:2:nargin-1
0175 %     obj.( obj_id ).( varargin{idx} )= varargin{idx+1};
0176 % for matlab 6.1 compatibility
0177       eval(sprintf('obj.%s=varargin{%d};', varargin{idx},idx+1 ));
0178    end
0179 
0180 % val= get_cache_obj( obj, prop, dep_obj1, dep_obj2, ...,  cachename );
0181 function [value, obj_id] = get_cache_obj( obj, prop )
0182    global eidors_objects
0183    DEBUG = eidors_debug('query','eidors_obj');
0184    
0185    value= [];
0186    obj_id = [];
0187    
0188    if DEBUG, str = sprintf('cache request: %s ',prop); end
0189 
0190 % We don't do this since cache directories aren't defined (yet)
0191 %  [objlist, cachename]= proc_obj_list( varargin{:} );
0192    if ~isfield(eidors_objects, 'cache')
0193       cache_init;
0194       if DEBUG, fprintf('%s: NO CACHE FIELD\n',str); end
0195       return
0196    end
0197 
0198    if isempty(eidors_objects.cache.meta), 
0199       if DEBUG, fprintf('%s: NO META FIELD\n',str); end
0200       return 
0201    end
0202    c = eidors_objects.cache.cols;
0203 %    match = ismember(prop, eidors_objects.cache.meta(:,c.prop));
0204 %    if any(match)
0205    obj_id= calc_obj_id( { obj, prop} ); % recalculate in case obj changed
0206    
0207    if DEBUG, str = [str, obj_id]; end
0208 % if cachename is specified, then cache to that file, rather
0209 %  than to the standard eidors_objects location
0210 % TODO: fixthis - use ( ) for matlab > 6.0
0211 %  if ~isempty( cachename )
0212 %     test_for_cachdir;
0213 %     filename= [ eidors_objects.cachedir, '/' , prop, '_' cachename '.mat' ];
0214 %     if exist( filename, 'file')
0215 %        load(filename); %variable 'value' should be there
0216 %     end
0217 %  else
0218 
0219       if ~isfield( eidors_objects.cache, obj_id);
0220          if DEBUG, fprintf('%s: not found\n',str); end
0221          return
0222       end
0223 
0224       idx = find(strcmp(obj_id, eidors_objects.cache.meta(:,c.obj_id)), 1, 'first');
0225       if DEBUG && isempty(idx), fprintf('%s: EMPTY IDX !!\n',str); end
0226       if ~isempty(idx)
0227          eidors_objects.cache.meta{idx,c.time} = now;
0228          eidors_objects.cache.meta{idx,c.count} = eidors_objects.cache.meta{idx,c.count} + 1;
0229          eidors_objects.cache.meta{idx,c.score_eff} = calc_effort_score(...
0230             eidors_objects.cache.meta{idx,c.effort}, ...
0231             eidors_objects.cache.meta{idx,c.count}, ...
0232             eidors_objects.cache.meta{idx,c.prio});
0233       end
0234       value = eidors_objects.cache.(obj_id);
0235       if DEBUG, fprintf('%s: found\n',str); end
0236 %        value= eval(sprintf('eidors_objects.%s.cache.%s;',obj_id,prop));
0237 %          check_size(obj_id, prop);
0238 %  end
0239 %    end
0240 
0241 function obj_id = set_cache_obj( obj, prop, value, time )
0242    global eidors_objects
0243    obj_id = [];
0244    
0245    if ~cache_this( obj ) ; return ; end
0246 
0247    if nargin  < 4
0248       time = 1; % assume 1 sec
0249    end
0250    
0251    if ~isfield(eidors_objects,'cache');
0252       init_cache;
0253    end
0254 
0255    c = eidors_objects.cache.cols;
0256    
0257 % Cache directories aren't defined, yet
0258 %  [objlist, cachename]= proc_obj_list( varargin{:} );
0259 
0260    obj_id = calc_obj_id( {obj, prop} );
0261    
0262    prio = eidors_objects.cache_priority;
0263 
0264 %  if isempty(cachename)
0265 
0266       ws = whos('value');
0267       row(c.obj_id)   = {obj_id};
0268       row(c.prop)     = {prop};
0269       row(c.size)     = {ws.bytes};
0270       row(c.score_sz) = {calc_size_score(ws.bytes)};
0271       row(c.effort)   = {time};
0272       row(c.prio)     = {prio};
0273       row(c.count)    = {1};
0274       row(c.score_eff)= {calc_effort_score(time, 1, prio)};
0275       row(c.time)     = {now};
0276       
0277       if isfield(eidors_objects.cache, obj_id)
0278          idx = find(strcmp(obj_id, eidors_objects.cache.meta(:,c.obj_id)));
0279          eidors_msg('@@ replaced cache object %s { %s }', obj_id, prop,4);
0280          eidors_objects.cache.size = eidors_objects.cache.size ...
0281                                     - eidors_objects.cache.meta{idx,c.size};
0282                                 
0283       else
0284          idx = size(eidors_objects.cache.meta, 1) + 1;
0285       end
0286       eidors_objects.cache.meta(idx,:) = row;
0287       eidors_objects.cache.( obj_id ) = value;
0288       eidors_objects.cache.size = eidors_objects.cache.size + ws.bytes;
0289       check_size(obj_id, prop);
0290 %  else
0291 %     filename= [ eidors_objects.cachedir, '/' , prop, '_' cachename '.mat' ];
0292 %     save(filename, 'value');
0293 %  end
0294 
0295 function cache_init
0296    global eidors_objects;
0297    
0298    eidors_objects.cache = struct;
0299    eidors_objects.cache.meta = cell(0);
0300    eidors_objects.cache.cols.obj_id    = 1;
0301    eidors_objects.cache.cols.prop      = 2;
0302    eidors_objects.cache.cols.time      = 3;
0303    eidors_objects.cache.cols.size      = 4;
0304    eidors_objects.cache.cols.score_sz  = 5;
0305    eidors_objects.cache.cols.effort    = 6;
0306    eidors_objects.cache.cols.prio      = 7;
0307    eidors_objects.cache.cols.count     = 8;
0308    eidors_objects.cache.cols.score_eff = 9;
0309    eidors_objects.cache.size           = 0;
0310 
0311 function score = calc_size_score(sz)
0312    if iscell(sz)
0313       fn = @(b) round(10*log10(b / 1024));
0314       N = numel(sz);
0315       score = num2cell(cellfun(fn, sz));
0316    else
0317       score = round(10 * log10( sz / 1024));
0318    end
0319    
0320 function score = calc_effort_score( time, counts, prios)
0321    if iscell(time)
0322        score = num2cell( round(10*log10( cell2mat(time) .* cell2mat(counts))) +...
0323                                 cell2mat(prios));
0324    else
0325       score = round(10*log10(time .* counts)) + prios; 
0326    end
0327 
0328 
0329 function obj= new_obj( type, name, varargin );
0330    global eidors_objects
0331 
0332    if isstruct(name)
0333       obj= name;
0334       try
0335          name= obj.name;
0336       catch
0337          name= 'unknown';
0338       end
0339    end
0340 
0341    obj.type = type;
0342    obj.name = name;
0343    obj= set_obj(obj, varargin{:} );
0344 
0345 % This function hashes the value of the variable var
0346 % to create an obj_id. The goal is to allow proper caching
0347 % of calculated matrices, by detecting when a previous
0348 % calculation with same parameters has been made
0349 function obj_id= calc_obj_id( var )
0350    try 
0351       obj_id= eidors_var_id( var );
0352    catch
0353       global eidors_objects;
0354       if ~isfield(eidors_objects,'hash_type')
0355          eidors_objects.hash_type= 1e8+1; 
0356       end
0357 %if hashing code is unavailable, then disable caching function
0358       obj_id= sprintf('id_%031d%08d', 0,eidors_objects.hash_type );
0359       eidors_objects.hash_type= eidors_objects.hash_type + 1;
0360    end
0361 
0362 % Test whether the cachedir field has been set. This is
0363 %  where eidors will store cached calculations. If it has
0364 %  not been set, then create it as 'eidors_cache' in the
0365 %  current directory
0366 %
0367 % NOTE: This code is not (yet) used
0368 function test_for_cachdir
0369    global eidors_objects; 
0370    if ~isfield(eidors_objects, 'cachedir')
0371       cachedir= 'eidors_cache';
0372       eidors_objects.cachedir= [pwd,'/',cachedir];
0373 
0374       if ~exist( eidors_objects.cachedir, 'dir')
0375 % Now we need to ensure that cachedir exists. Because the
0376 % STUPID!!! matlab has a completely useless and nonstandard
0377 % mkdir function, we try this
0378          mkdir(pwd,cachedir); 
0379       end
0380    end
0381 
0382 % Test whether a cachedir function has been provided
0383 % (by testing whether the last entry is a string). If so,
0384 % return it in objlist, otherwise return []
0385 function [objlist, cachedir]= proc_obj_list( varargin );
0386    cachedir= [];
0387    if nargin==0
0388       objlist= {};
0389    elseif ischar(varargin{nargin})
0390       cachedir= varargin{nargin};
0391       objlist = varargin(1:nargin-1);
0392    else
0393       objlist = varargin(:);
0394    end
0395 
0396 function retval= cache_this( obj )
0397 % we choose not to cache data and images because this will
0398 % tend to fill up the workspace.
0399 % TODO: make the DONT_CACHE list use configuable
0400    if ~isstruct( obj); retval=1; return; end
0401    DONT_CACHE= {'data','image'};
0402    if any(strcmp( obj.type, DONT_CACHE));
0403       retval = 0;
0404    else
0405       retval = 1;
0406    end
0407 
0408 function check_size( obj_id , prop )
0409    global eidors_objects;   
0410 %    eidors_objects.( obj_id ).( prop ).last_used = now;
0411 
0412    max_memory= eidors_objects.max_cache_size;
0413 %    ww= whos('eidors_objects');
0414    if eidors_objects.cache.size  > max_memory
0415       eidors_cache('clear_max',floor(max_memory*.75));
0416    end
0417

Generated on Wed 21-Jun-2017 09:29:07 by m2html © 2005