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 6518 2022-12-30 21:12:32Z 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 = []; extra_out= [];
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.11';  % 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       % build numbers are too large and interfere
0152       ver(4:end) = [];
0153 
0154       % Convert 7.8.1 to 7.008001
0155       verstr.ver = 1e-3.^(0:length(ver)-1) * ver(:); 
0156 
0157       if exist('OCTAVE_VERSION') == 5
0158          verstr.isoctave = 1;
0159       else
0160          verstr.isoctave = 0;
0161       end
0162 
0163       cptr = computer;
0164       if strcmp(cptr(end+(-1:0)), '64')
0165          verstr.is64bit = 1;
0166       else
0167          verstr.is64bit = 0;
0168       end
0169 
0170 function obj = set_obj( obj, varargin );
0171    global eidors_objects;
0172 
0173 %  eidors_objects.( obj_id ) = obj;
0174 %  eidors_objects.( obj_id ).cache= []; %clear cache
0175 %
0176 
0177    for idx= 1:2:nargin-1
0178       obj.( varargin{idx} )= varargin{idx+1};
0179    end
0180 
0181 % val= get_cache_obj( obj, prop, dep_obj1, dep_obj2, ...,  cachename );
0182 function [value, obj_id] = get_cache_obj( obj, prop )
0183    global eidors_objects
0184    DEBUG = eidors_debug('query','eidors_obj');
0185    
0186    value= [];
0187    obj_id = [];
0188    
0189    if DEBUG, str = sprintf('cache request: %s ',prop); end
0190 
0191 % We don't do this since cache directories aren't defined (yet)
0192 %  [objlist, cachename]= proc_obj_list( varargin{:} );
0193    if ~isfield(eidors_objects, 'cache')
0194       cache_init;
0195       if DEBUG, fprintf('%s: NO CACHE FIELD\n',str); end
0196       return
0197    end
0198 
0199    obj_id= calc_obj_id( { obj, prop} );
0200 
0201    if isempty(eidors_objects.cache.meta), 
0202       if DEBUG, fprintf('%s: NO META FIELD\n',str); end
0203       return 
0204    end
0205    c = eidors_objects.cache.cols;
0206 %    match = ismember(prop, eidors_objects.cache.meta(:,c.prop));
0207 %    if any(match)
0208    
0209    if DEBUG, str = [str, obj_id]; end
0210 % if cachename is specified, then cache to that file, rather
0211 %  than to the standard eidors_objects location
0212 % TODO: fixthis - use ( ) for matlab > 6.0
0213 %  if ~isempty( cachename )
0214 %     test_for_cachdir;
0215 %     filename= [ eidors_objects.cachedir, '/' , prop, '_' cachename '.mat' ];
0216 %     if exist( filename, 'file')
0217 %        load(filename); %variable 'value' should be there
0218 %     end
0219 %  else
0220 
0221       if ~isfield( eidors_objects.cache, obj_id);
0222          if DEBUG, fprintf('%s: not found\n',str); end
0223          return
0224       end
0225 
0226       idx = find(strcmp(obj_id, eidors_objects.cache.meta(:,c.obj_id)), 1, 'first');
0227       if DEBUG && isempty(idx), fprintf('%s: EMPTY IDX !!\n',str); end
0228       if ~isempty(idx)
0229          eidors_objects.cache.meta{idx,c.time} = now;
0230          eidors_objects.cache.meta{idx,c.count} = eidors_objects.cache.meta{idx,c.count} + 1;
0231          eidors_objects.cache.meta{idx,c.score_eff} = calc_effort_score(...
0232             eidors_objects.cache.meta{idx,c.effort}, ...
0233             eidors_objects.cache.meta{idx,c.count}, ...
0234             eidors_objects.cache.meta{idx,c.prio});
0235       end
0236       value = eidors_objects.cache.(obj_id);
0237       if DEBUG, fprintf('%s: found\n',str); end
0238 %        value= eval(sprintf('eidors_objects.%s.cache.%s;',obj_id,prop));
0239 %          check_size(obj_id, prop);
0240 %  end
0241 %    end
0242 
0243 function obj_id = set_cache_obj( obj, prop, value, time )
0244    global eidors_objects
0245    obj_id = [];
0246    
0247    if ~cache_this( obj ) ; return ; end
0248 
0249    if nargin  < 4
0250       time = 1; % assume 1 sec
0251    end
0252    
0253    if ~isfield(eidors_objects,'cache');
0254       init_cache;
0255    end
0256 
0257    c = eidors_objects.cache.cols;
0258    
0259 % Cache directories aren't defined, yet
0260 %  [objlist, cachename]= proc_obj_list( varargin{:} );
0261 
0262    obj_id = calc_obj_id( {obj, prop} );
0263    
0264    prio = eidors_objects.cache_priority;
0265 
0266 %  if isempty(cachename)
0267 
0268       ws = whos('value');
0269       row(c.obj_id)   = {obj_id};
0270       row(c.prop)     = {prop};
0271       row(c.size)     = {ws.bytes};
0272       row(c.score_sz) = {calc_size_score(ws.bytes)};
0273       row(c.effort)   = {time};
0274       row(c.prio)     = {prio};
0275       row(c.count)    = {1};
0276       row(c.score_eff)= {calc_effort_score(time, 1, prio)};
0277       row(c.time)     = {now};
0278       
0279       if isfield(eidors_objects.cache, obj_id)
0280          idx = find(strcmp(obj_id, eidors_objects.cache.meta(:,c.obj_id)));
0281          eidors_msg('@@ replaced cache object %s { %s }', obj_id, prop,4);
0282          eidors_objects.cache.size = eidors_objects.cache.size ...
0283                                     - eidors_objects.cache.meta{idx,c.size};
0284                                 
0285       else
0286          idx = size(eidors_objects.cache.meta, 1) + 1;
0287       end
0288       eidors_objects.cache.meta(idx,:) = row;
0289       eidors_objects.cache.( obj_id ) = value;
0290       eidors_objects.cache.size = eidors_objects.cache.size + ws.bytes;
0291       check_size(obj_id, prop);
0292 %  else
0293 %     filename= [ eidors_objects.cachedir, '/' , prop, '_' cachename '.mat' ];
0294 %     save(filename, 'value');
0295 %  end
0296 
0297 function cache_init
0298    global eidors_objects;
0299    
0300    eidors_objects.cache = struct;
0301    eidors_objects.cache.meta = cell(0);
0302    eidors_objects.cache.cols.obj_id    = 1;
0303    eidors_objects.cache.cols.prop      = 2;
0304    eidors_objects.cache.cols.time      = 3;
0305    eidors_objects.cache.cols.size      = 4;
0306    eidors_objects.cache.cols.score_sz  = 5;
0307    eidors_objects.cache.cols.effort    = 6;
0308    eidors_objects.cache.cols.prio      = 7;
0309    eidors_objects.cache.cols.count     = 8;
0310    eidors_objects.cache.cols.score_eff = 9;
0311    eidors_objects.cache.size           = 0;
0312 
0313 function score = calc_size_score(sz)
0314    if iscell(sz)
0315       fn = @(b) round(10*log10(b / 1024));
0316       N = numel(sz);
0317       score = num2cell(cellfun(fn, sz));
0318    else
0319       score = round(10 * log10( sz / 1024));
0320    end
0321    
0322 function score = calc_effort_score( time, counts, prios)
0323    if iscell(time)
0324        score = num2cell( round(10*log10( cell2mat(time) .* cell2mat(counts))) +...
0325                                 cell2mat(prios));
0326    else
0327       score = round(10*log10(time .* counts)) + prios; 
0328    end
0329 
0330 
0331 function obj= new_obj( type, name, varargin );
0332    global eidors_objects
0333 
0334    if isstruct(name)
0335       obj= name;
0336       try
0337          name= obj.name;
0338       catch
0339          name= 'unknown';
0340       end
0341    end
0342 
0343    obj.type = type;
0344    obj.name = name;
0345    obj= set_obj(obj, varargin{:} );
0346 
0347 % This function hashes the value of the variable var
0348 % to create an obj_id. The goal is to allow proper caching
0349 % of calculated matrices, by detecting when a previous
0350 % calculation with same parameters has been made
0351 function obj_id= calc_obj_id( var )
0352    try 
0353       obj_id= eidors_var_id( var );
0354    catch
0355       global eidors_objects;
0356       if ~isfield(eidors_objects,'hash_type')
0357          eidors_objects.hash_type= 1e8+1; 
0358       end
0359 %if hashing code is unavailable, then disable caching function
0360       obj_id= sprintf('id_%031d%08d', 0,eidors_objects.hash_type );
0361       eidors_objects.hash_type= eidors_objects.hash_type + 1;
0362    end
0363 
0364 % Test whether the cachedir field has been set. This is
0365 %  where eidors will store cached calculations. If it has
0366 %  not been set, then create it as 'eidors_cache' in the
0367 %  current directory
0368 %
0369 % NOTE: This code is not (yet) used
0370 function test_for_cachdir
0371    global eidors_objects; 
0372    if ~isfield(eidors_objects, 'cachedir')
0373       cachedir= 'eidors_cache';
0374       eidors_objects.cachedir= [pwd,'/',cachedir];
0375 
0376       if ~exist( eidors_objects.cachedir, 'dir')
0377 % Now we need to ensure that cachedir exists. Because the
0378 % STUPID!!! matlab has a completely useless and nonstandard
0379 % mkdir function, we try this
0380          mkdir(pwd,cachedir); 
0381       end
0382    end
0383 
0384 % Test whether a cachedir function has been provided
0385 % (by testing whether the last entry is a string). If so,
0386 % return it in objlist, otherwise return []
0387 function [objlist, cachedir]= proc_obj_list( varargin );
0388    cachedir= [];
0389    if nargin==0
0390       objlist= {};
0391    elseif ischar(varargin{nargin})
0392       cachedir= varargin{nargin};
0393       objlist = varargin(1:nargin-1);
0394    else
0395       objlist = varargin(:);
0396    end
0397 
0398 function retval= cache_this( obj )
0399 % we choose not to cache data and images because this will
0400 % tend to fill up the workspace.
0401 % TODO: make the DONT_CACHE list use configuable
0402    if ~isstruct( obj); retval=1; return; end
0403    DONT_CACHE= {'data','image'};
0404    if any(strcmp( obj.type, DONT_CACHE));
0405       retval = 0;
0406    else
0407       retval = 1;
0408    end
0409 
0410 function check_size( obj_id , prop )
0411    global eidors_objects;   
0412 %    eidors_objects.( obj_id ).( prop ).last_used = now;
0413 
0414    max_memory= eidors_objects.max_cache_size;
0415 %    ww= whos('eidors_objects');
0416    if eidors_objects.cache.size  > max_memory
0417       eidors_cache('clear_max',floor(max_memory*.75));
0418    end
0419

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