Mercurial > hg > ishara
comparison general/algo/iterate_timed.m @ 6:0ce3c2070089
Removed duplicate code and fixed doc in timed_action.
author | samer |
---|---|
date | Mon, 14 Jan 2013 14:33:37 +0000 |
parents | general/algo/iterate_timed2.m@e44f49929e56 |
children | beb8a3f4a345 |
comparison
equal
deleted
inserted
replaced
5:8972a4071294 | 6:0ce3c2070089 |
---|---|
1 function api=iterate_timed(varargin) | 1 function Sched=iterate_timed(nextfn,X0,T,varargin) |
2 % iterate_timed - Iterate function under control of timer | 2 % iterate_timed - Iterate function under control of timer |
3 % | 3 % |
4 % iterate_timed :: | 4 % iterate_timed :: |
5 % (A=>A) ~'state transformer action', | 5 % (A=>A) ~'state transformer action', |
6 % A ~'initial state', | 6 % A ~'initial state', |
7 % real ~'timer between updates in seconds', | 7 % real ~'timer between updates in seconds' |
8 % options iterate_timed_options ~'options (see below)' | 8 % options { |
9 % -> sched(A) ~'scheduler API'. | |
10 % | |
11 % iterate_timed :: | |
12 % cell { | |
13 % (A=>A) ~'state transformer action', | |
14 % A ~'initial state' | |
15 % } ~'iterated system as a cell array', | |
16 % real ~'timer between updates in seconds', | |
17 % options iterate_timed_options ~'options (see below)' | |
18 % -> sched(A) ~'scheduler API'. | |
19 % | |
20 % iterate_timed_options = { | |
21 % drawnow :: {0,1} /0 ~'call drawnow after each iteration'; | 9 % drawnow :: {0,1} /0 ~'call drawnow after each iteration'; |
22 % busy_mode :: {'queue','drop'} /'queue' ~'See TIMER'; | 10 % busy_mode :: {'queue','drop'} /'queue' ~'See TIMER'; |
23 % exec_mode :: {'fixedRate','fixedDelay','fixedSpacing'} /'fixedRate' ~'See TIMER'; | 11 % exec_mode :: {'fixedRate','fixedDelay','fixedSpacing'} /'fixedRate' ~'See TIMER'; |
24 % its :: natural / inf ~'iteration limit'; | 12 % its :: natural / inf ~'iteration limit'; |
25 % onstart :: A->void / @nop ~'do this when timer starts'; | 13 % onstart :: (A=>void)/ @nop ~'do this when timer starts'; |
26 % onstop :: A->void / @nop ~'do this when timer stops'; | 14 % onstop :: (A=>void)/ @nop ~'do this when timer stops'; |
27 % onfinish :: A->void / @nop ~'do this when iterator terminates'; | 15 % onfinish :: (A=>void)/ @nop ~'do this when iterator terminates'; |
28 % pre :: A->void / [] ~'something to do before each iteration'; | 16 % pre :: (A=>void)/ @nop ~'do before each iteration'; |
29 % post :: A->void / [] ~'something to do after each iteration'; | 17 % post :: (A=>void)/ @nop ~'do after each iteration'; |
30 % drawnow :: bool / 0 ~'whether to update graphics every it'; | |
31 % defer :: bool / 0 ~'if true then don't start the timer'; | 18 % defer :: bool / 0 ~'if true then don't start the timer'; |
32 % props :: {[[_]]} / {} ~'extra name/value pairs for timer' | 19 % -> timer, (A=>void) ~'function to seek to given state'. |
33 % } | |
34 % | 20 % |
35 % sched(A) ::= struct { | |
36 % dispose :: void => void; | |
37 % isrunning :: void => bool; | |
38 % startat :: real => void; | |
39 % start :: void => void; | |
40 % stop :: void => void; | |
41 % rewind :: void => void; | |
42 % getstate :: void => A; | |
43 % setstate :: A => void | |
44 % }. | |
45 % | |
46 % NB: Unlike ITERATE, this does NOT respect the id, save, and recover properties. | 21 % NB: Unlike ITERATE, this does NOT respect the id, save, and recover properties. |
47 % Neither does it respect the OPTPAUSE property 'pause'. | 22 % Neither does it respect the OPTPAUSE property 'pause'. |
48 | 23 |
49 warning('off','MATLAB:TIMER:STARTDELAYPRECISION'); | |
50 warning('off','MATLAB:TIMER:RATEPRECISION'); | |
51 | |
52 if iscell(varargin{1}) | |
53 [nextfn,X0]=varargin{1}{:}; | |
54 T=varargin{2}; | |
55 options=varargin(3:end); | |
56 else | |
57 nextfn=varargin{1}; | |
58 X0=varargin{2}; | |
59 T=varargin{3}; | |
60 options=varargin(4:end); | |
61 end | |
62 | |
63 opts=prefs('its',inf,'drawnow',0, 'quiet', 0, 'defer', 0, ... | 24 opts=prefs('its',inf,'drawnow',0, 'quiet', 0, 'defer', 0, ... |
64 'busy_mode','queue','exec_mode','fixedRate', ... | 25 'busy_mode','queue','exec_mode','fixedRate', ... |
65 'onfinish',@nop,'onstart',@nop,'onstop',@nop,options{:}); | 26 'onfinish',@nop,'onstart',@nop,'onstop',@nop,varargin{:}); |
27 | |
28 it={nextfn,X0}; | |
29 if isfield(opts,'pre') || isfield(opts,'post') | |
30 it=bracket_it(it, getparam(opts,'pre',@nop), getparam(opts,'post',@nop)); | |
31 end | |
32 if opts.drawnow, it=drawnow_it(it); end | |
33 stfn=it{1}; | |
66 | 34 |
67 X=X0; %% !!! NB: this is a mutable shared local variable used by timercb | 35 Sched=rsched(@action,it{2},T,nows,opts,'defer',1,... |
36 'onstart',@onstart,'onstop',@onstop,'onfinish',@onfinish); | |
37 if ~opts.defer, Sched.start(); end | |
68 | 38 |
69 if ~isfield(opts,'pre') && ~isfield(opts,'post') && ~opts.drawnow | 39 function [err,s]=action(t_sched,dt,s), err=nows-t_sched; s=stfn(s); end |
70 stfn=nextfn; % streamlined version with no checks | 40 function onstart(X,t_sched,t_actual), status('starting',X,t_actual); opts.onstart(X); end |
71 else % version with calls to pre,post, and drawnow | 41 function onstop(X,t_actual), status('stopping',X,t_actual); opts.onstop(X); end |
72 prefn=getparam(opts,'pre',@nop); | 42 function onfinish(t_actual), status('finishing',[],t_actual); opts.onfinish(); end |
73 postfn=getparam(opts,'post',@nop); | 43 function status(msg,x,t), |
74 stfn=@bracket; | 44 if ~opts.quiet |
75 end | 45 fprintf('| %s at %s with %s\n',msg,mat2str(t),tostring(x)); |
76 | |
77 tm=timer('ExecutionMode',opts.exec_mode,'BusyMode',opts.busy_mode, ... | |
78 'TimerFcn',@timercb,'StartFcn',@startfn,'StopFcn',@stopfn, ... | |
79 'TasksToExecute',opts.its,'Period',T); | |
80 | |
81 api=struct( ... | |
82 'dispose', @()delete(tm), ... | |
83 'isrunning',@()isrunning(tm), ... | |
84 'startat', @(t)startat(tm,t/86400), ... | |
85 'start', @()start(tm), ... | |
86 'stop', @()stop(tm), ... | |
87 'rewind', @()setstate(X0), ... | |
88 'getstate', @getstate, ... | |
89 'setstate', @setstate ... | |
90 ); | |
91 | |
92 if ~opts.defer, start(tm); end | |
93 | |
94 function setstate(x), X=x; end | |
95 function x=getstate, x=X; end | |
96 | |
97 function X=bracket(X), | |
98 prefn(X); X=nextfn(X); postfn(X); | |
99 if opts.drawnow, drawnow; end | |
100 end | |
101 | |
102 function startfn(tm,a) | |
103 if ~opts.quiet, status(tm,'starting',X,a.Data.time); end | |
104 opts.onstart(X); | |
105 end | |
106 | |
107 function stopfn(tm,a) | |
108 if ~opts.quiet, status(tm,'stopping',X,a.Data.time); end | |
109 opts.onstop(X); | |
110 if isempty(X), | |
111 if ~opts.quiet, status(tm,'finished',X,a.Data.time); end | |
112 opts.onfinish(X); | |
113 end | 46 end |
114 end | |
115 | |
116 % well, we have mutable variables captured by closure so we may | |
117 % as well use them... | |
118 function timercb(tm,ev) | |
119 if isempty(X), stop(tm); else, X=stfn(X); end | |
120 end | 47 end |
121 end | 48 end |
122 | 49 |
123 function status(tm,msg,x,t), | 50 function it=drawnow_it(it), |
124 fprintf('| %s %s at %s with %s\n',get(tm,'name'),msg,mat2str(t),tostring(x)); | 51 f=it{1}; it{1}=@fdraw; |
52 function x=fdraw(x), x=f(x); drawnow; end | |
125 end | 53 end |
126 | 54 |