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

Generated on Tue 31-Dec-2019 17:03:26 by m2html © 2005