3 % model of the human follicle growth
5 % two chemical components are assumed to be characteristic
for the
6 % growth of human follicles.
8 % A deterministic model
for the two species is given by a positive
9 % feedback loop, a bistable
switch, i.e. 2-d nonlinear ODE.
11 % An approximation to the Chemical Master Equation gives a linear
14 % here, the state vector is the probability of states (pair of number of two
15 % chemical components) and the matrix A describes the change in
16 % these probabilities over time. The number of states is
17 % p = (range+1)*(range+2)/2
19 % The output is given by params.output_type:
20 % 'separatrix': an average over a subset of states, the ones below
21 % the "separatrix", which are assumed to be still "in rest",
22 % i.e. waiting for their growth specified by model.output_range
23 % 'expectation_M': the expectation of M state is computed
24 % 'expectation_N': the expectation of N state is computed
26 % Q: D.h. die Zellen oberhalb der separatrix sind einfach abgestorben, oder zur
29 % Explanations from S. Waldherr "A stochastic switch for the
30 % primordial to primary transition in follicle growth", IST
31 % internal report (2009-04-09) v1
33 % Bernard Haasdonk 22.9.2009
38 model = lin_ds_model_default;
39 model.data_const_in_time = 1;
43 %%%%%%%%%%%%%%%%%%%%%%% parameters from steffen
48 if isfield(params,
'range')
49 model.range = params.range;
51 model.range = 50; % connected with end time, increase e.g. to 50 later
53 if isfield(params,'output_range')
54 model.output_range = params.output_range;
56 model.output_range = model.range; % connected with end time, increase e.g. to 50 later
58 if (model.output_range > model.range)
59 error('please choose output range <= range');
61 % determines the initial distribution in a lower left triangle
62 if isfield(params,'init_range')
63 model.init_range = params.init_range;
68 if isfield(params,'reg_epsilon')
69 model.reg_epsilon = params.reg_epsilon;
71 model.reg_epsilon = 0;
73 if ~isfield(params,'output_type')
74 params.output_type = 'separatrix';
77 % u1 = 0.01+(i-6)*0.001;
78 % u2 = 0.01+(i-6)*0.0005;
79 % k1 = 4*u1+(i-6)*0.0001;
82 % parameterlist(i,1:5)= [k1 u1 u2 V1 V2];
84 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
86 %model_data = my_ds_gen_model_data(model);
94 % used as components later:
95 %model.k1 = model.k1fact * model.u1;
96 %model.V1 = model.V1fact * model.u1;
97 %model.V2 = model.V2fact * model.u2;
99 model.mu_names = {
'u1',
'u2'};
100 %model.mu_names = {
'u1',
'u2',
'k1fact',
'V1fact',
'V2fact'};
101 model.mu_ranges = {[0.005,0.02],[0.005,0.02]};
103 %model.T = 1000000; % Minutes, i.e. 1.9 Jahre
105 %model.T = 1000000; % Minutes, i.e. 1.9 Jahre
107 model.T = 10000000; % Minutes, i.e. 19 Jahre
109 %model.T = 5000000; % Minutes, i.e. 9.5 Jahre
111 %model.T = 50000000; % Minutes, i.e. 95 Jahre
113 %disp(
'nt to be adjusted later!!!') => 500 OK!!
114 model.affinely_decomposed = 1;
115 model.A_function_ptr = @A_func;
116 % ratio of first to second ellipses axes
117 %model.A_axes_ratio = 2;
118 %model.A_axes_ratio = 2;
119 model.B_function_ptr = @B_func;
120 switch params.output_type
122 model.C_function_ptr = @C_func_separatrix;
124 model.C_function_ptr = @C_func_expectation_M;
126 model.C_function_ptr = @C_func_expectation_N;
128 error(
'params.output_type not known');
130 model.D_function_ptr = @D_func;
131 model.x0_function_ptr = @x0_func;
132 % shift of x0 in third coordinate
134 model.u_function_ptr = @(model) 0; % define u constant
135 %model.u_function_ptr = @(model) sin(4*model.t);
136 %model.u_function_ptr = @(model) 0; % define u constant 0
137 %model.u_function_ptr = @(model) model.t; % define u = 1 * t
138 model.G_matrix_function_ptr = ...
139 @(model,model_data) speye(model.dim_x,model.dim_x);
140 % the following lead to both larger C1 and C2!!!
141 %model.G_matrix_function_ptr = @(model) diag([2,0.5,1]);
142 %model.G_matrix_function_ptr = @(model) diag([0.5,2,1]);
144 %
set function pointers to main model methods
145 model.gen_model_data = @my_ds_gen_model_data;
146 %model.detailed_simulation = @lin_ds_detailed_simulation;
147 model.gen_detailed_data = @my_ds_gen_detailed_data;
148 %model.gen_reduced_data = @lin_ds_gen_reduced_data;
149 %model.rb_simulation = @lin_ds_rb_simulation;
150 %model.plot_sim_data = @my_ds_plot_sim_data;
151 model.plot_sim_data_state = @plot_state_probabilities;
152 model.plot_slice = @my_plot_slice;
153 model.axis_tight = 1;
155 %model.rb_reconstruction = @lin_ds_rb_reconstruction;
156 % determin model data, i.e. matrix components, matrix G
158 model.orthonormalize = @model_orthonormalize_qr_no_perm;
160 model_data = gen_model_data(model); % matrix components
161 model.dim_x = size(model_data.X,2);
162 model.dim_y = size(model_data.C_components{1},1);
164 if isfield(params,
'output_plot_indices')
165 model.output_plot_indices = params.output_plot_indices;
167 model.output_plot_indices = 1:model.dim_y;
170 model.theta = 1; % implicit discretization
172 % be sure to determine correct constants once, if anything in the
173 % problem setting has changed!!
175 %model.error_estimation = 1; % model is capable of error_estimation
176 model.enable_error_estimator = 1;
177 if ~isfield(params,'estimate_bounds')
178 params.estimate_bounds = 0;
180 % the following only needs to be performed, if the model is changed.
181 if (params.estimate_bounds == 0)
183 model.state_bound_constant_C1 = 1 ;
184 if ~isequal(params.output_type,'separatrix')
185 warning('please adjust the computation of the error estimator constants!')
187 model.output_bound_constant_C2 = sqrt(model.dim_x);
188 elseif params.estimate_bounds == 1
189 model.estimate_lin_ds_nmu = 3;
190 model.estimate_lin_ds_nX = 10;
191 model.estimate_lin_ds_nt = 10;
193 [C1,C2] = lin_ds_estimate_bound_constants(model,model_data)
194 model.state_bound_constant_C1 = C1;
195 model.output_bound_constant_C2 = C2;
197 model.estimate_lin_ds_nmu = 3;
198 model.estimate_lin_ds_nX = 10;
199 model.estimate_lin_ds_nt = 10;
201 [C1,C2] = lin_ds_estimate_bound_constants(model,model_data)
202 model.state_bound_constant_C1 = C1;
203 model.output_bound_constant_C2 = C2;
207 model.inner_product_matrix_algorithm =@(model,model_data) ...
208 speye(model.dim_x,model.dim_x);
210 model.error_algorithm = @(u1,u2,dummy1,dummy2) ...
211 sqrt(max(sum((u1-u2).^2),0));
214 %model.error_norm = 'l2';
215 %% 'RB_extension_max_error_snapshot'};
216 model.RB_stop_timeout = 4*60*60; % 4 hours
217 model.RB_stop_epsilon = 1e-10;
218 model.RB_error_indicator = 'error'; % true error
220 %model.RB_error_indicator = 'estimator'; % Delta from rb_simulation
222 model.RB_stop_Nmax = 200;
223 model.RB_generation_mode = 'greedy_uniform_fixed';
224 model.RB_numintervals = [4,4];
225 model.RB_detailed_train_savepath = 'follicle_model_detailed_train';
226 model.orthonormalize = @model_orthonormalize_qr;
230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
231 % functions defining the dynamical system and input/initial data
232 function A = A_func(model,model_data);
234 A = eval_affine_decomp(@A_components,@A_coefficients,...
237 function Acomp = A_components(model,model_data)
244 A1 = sparse([],[],[],p,p,7*p); % for k1
245 A2 = sparse([],[],[],p,p,7*p); % for u1
246 A3 = sparse([],[],[],p,p,7*p); % for u2
247 A4 = sparse([],[],[],p,p,7*p); % for V1
248 A5 = sparse([],[],[],p,p,7*p); % for V2
249 A6 = -speye(p,p); % for regularization
252 j = find ((X(1,:)==X(1,m)+1) & (X(2,:)==X(2,m)));
255 j = find((X(1,:)==X(1,m)-1) & (X(2,:)==X(2,m)));
258 j = find((X(1,:)==X(1,m)) & (X(2,:)==X(2,m)-1));
260 A4(m,m) = -X(2,m)^h/(M1^h+X(2,m)^h);
261 j = find((X(1,:)==X(1,m)+1) & (X(2,:)==X(2,m)));
262 A4(j,m) = X(2,m)^h/(M1^h+X(2,m)^h);
263 A5(m,m)= -X(1,m)^h/(M2^h+X(1,m)^h);
264 j = find((X(1,:)==X(1,m)) & (X(2,:)==X(2,m)+1));
265 A5(j,m) = X(1,m)^h/(M2^h+X(1,m)^h);
268 Acomp = {A1, A2, A3, A4, A5, A6};
270 function Acoeff = A_coefficients(model)
273 % Acoeff = [model.k1, model.u1, model.u2, model.V1, model.V2];
274 k1 = model.k1fact * model.u1;
275 V1 = model.V1fact * model.u1;
276 V2 = model.V2fact * model.u2;
277 Acoeff = [k1, model.u1, model.u2, V1, V2, model.reg_epsilon];
279 function B = B_func(model,model_data)
281 B = eval_affine_decomp(@B_components,@B_coefficients,model,model_data);
283 function Bcomp = B_components(model,model_data)
285 Bcomp = {zeros(model.dim_x,1)};
287 function Bcoeff = B_coefficients(model)
291 function C = C_func_separatrix(model,model_data)
293 C = eval_affine_decomp(@C_components_separatrix,...
294 @C_coefficients,model,model_data);
296 function C = C_func_expectation_M(model,model_data)
297 % C_func_expectation_M
298 C = eval_affine_decomp(@C_components_expectation_M,...
299 @C_coefficients,model,model_data);
301 function C = C_func_expectation_N(model,model_data)
302 % C_func_expectation_N
303 C = eval_affine_decomp(@C_components_expectation_N,...
304 @C_coefficients,model,model_data);
306 function Ccomp = C_components_separatrix(model,model_data)
307 % C_components_separatrix
308 i = find((model_data.Ms+model_data.Ns)<=model.output_range);
309 C = zeros(1,model.dim_x);
312 % Ccomp = {ones(1,model.dim_x)};
313 %Ccomp = {[2,0,1],[0,2,1]};
315 function Ccomp = C_components_expectation_M(model,model_data)
316 % C_components_expectation_M
317 C = model_data.Ms(:)
';
320 function Ccomp = C_components_expectation_N(model,model_data)
321 % C_components_expectation_N
322 C = model_data.Ns(:)';
325 function Ccoeff = C_coefficients(model)
328 %Ccoeff = [model.C_weight,1-model.C_weight];
330 function D = D_func(model,model_data)
333 %D = [0;0]; % no decomposition required
for scheme
334 D = [0]; % no decomposition required
for scheme
336 function x0 = x0_func(model,model_data)
338 x0 = eval_affine_decomp(@x0_components,@x0_coefficients,model,model_data);
340 function x0comp = x0_components(model,model_data)
343 %
if model.init_range == 0
344 % x0comp = {eye(model.dim_x,1)};
346 i = ((model_data.Ms+model_data.Ns)<=model.init_range);
347 %i = (model_data.Ms<=1);
348 x0comp = {i(:)/sum(i)}; % sum should be 1!
351 function x0coeff = x0_coefficients(model)
355 function model_data = my_ds_gen_model_data(model)
356 % model data generation
357 s = 1; % state counter
358 % generate list of states X and output weight vector
359 Ms = zeros(1,(model.range+1)*model.range/2);
360 Ns = zeros(1,(model.range+1)*model.range/2);
362 for n=0:(model.range-m)
369 p = s-1; % number of states
371 %model_data = lin_ds_gen_model_data(model);
376 if model.affinely_decomposed
377 model.decomp_mode = 1;
378 % the following call is extremely expensive: 30 seconds!!!!
379 % therefore caching is activated
380 % model_data.A_components = model.A_function_ptr(model,model_data);
382 model.A_function_ptr,model,model_data);
383 model_data.B_components = model.B_function_ptr(model,model_data);
384 model_data.C_components = model.C_function_ptr(model,model_data);
386 % model_data.D_components = model.D_function_ptr(model);
387 model_data.x0_components = model.x0_function_ptr(model,model_data);
389 model_data.G = model.G_matrix_function_ptr(model,[]);
391 params.xnumintervals = model.range+1;
392 params.ynumintervals = model.range+1;
393 params.xrange = [-0.5,model.range+0.5];
394 params.yrange = [-0.5,model.range+0.5];
398 model_data.plot_grid =
rectgrid(params);
399 model_data.plot_nm_index_vector = ...
400 model_data.Ms + model_data.Ns*(model.range+1)+1;
402 function detailed_data = my_ds_gen_detailed_data(model,model_data)
403 % detailed data generation
404 detailed_data = lin_ds_gen_detailed_data(model,model_data);
406 detailed_data.plot_grid = model_data.plot_grid;
407 detailed_data.plot_nm_index_vector = model_data.plot_nm_index_vector;
409 function p = plot_state_probabilities(model,model_data,sim_data,params)
410 % plot of trajectory and output
412 %p = lin_ds_plot_sim_data(model,model_data,sim_data,params);
415 %grid = Grids.rectgrid(params);
416 U = nan((model.range+1)*(model.range+1),size(sim_data.X,2));
417 U(model_data.plot_nm_index_vector,1:end)= sim_data.X;
419 %U(nm_index_vector,1) = model_data.Ns;
420 %U(nm_index_vector,2) = model_data.Ms;
421 %params.plot_function = @plot_element_data;
422 merged_plot_params = merge_model_plot_params(model, params);
423 merged_plot_params.plot_function =
'plot_element_data';
424 plot_data_sequence(model,model_data.plot_grid,U,merged_plot_params)
428 if ~isfield(model,'plot_title')
429 title('state probabilities');
431 title(model.plot_title);
434 function p = my_plot_slice(model,model_data,sim_data,params)
436 U = nan((model.range+1)*(model.range+1),1);
437 U(model_data.plot_nm_index_vector)= sim_data.X(:,params.timestep+1);
439 %U(nm_index_vector,1) = model_data.Ns;
440 %U(nm_index_vector,2) = model_data.Ms;
441 %params.plot_function = @plot_element_data;
442 params.plot_function = 'plot_element_data';
443 if ~isfield(params,'clim') && isfield(model,'clim')
444 params.clim = model.clim;
446 p = plot_element_data(U,model_data.plot_grid,params);
450 title('state probabilities');
452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453 % CODE FROM STEFFEN, RESP HANWEI LI:
454 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
459 % $$$ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
460 % $$$ % define parameter
467 % $$$ u1 = 0.01+(i-6)*0.001;
468 % $$$ u2 = 0.01+(i-6)*0.0005;
469 % $$$ k1 = 4*u1+(i-6)*0.0001;
472 % $$$ parameterlist(i,1:5)= [k1 u1 u2 V1 V2];
476 % $$$ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477 % $$$ % build the nominal model
480 % $$$ s = 1; % state counter
482 % $$$ % generate list of states X
485 % $$$ for n=0:(range-m)
486 % $$$ X(:,s) = [m;n];
490 % $$$ p = s-1; % number of states
492 % $$$ % defining propensity functions
493 % $$$ a1 = @(x) (parameterlist(inomi,1)+parameterlist(inomi,4)*x(2)^h/(M1^h+x(2)^h));
494 % $$$ a2 = @(x) parameterlist(inomi,2)*x(1);
495 % $$$ a3 = @(x) parameterlist(inomi,5)*x(1)^h/(M2^h+x(1)^h);
496 % $$$ a4 = @(x) parameterlist(inomi,3)*x(2);
498 % $$$ A = sparse([],[],[],p,p,7*p);
500 % $$$ A(m,m) = -(a1(X(:,m))+a2(X(:,m))+a3(X(:,m))+a4(X(:,m)));
501 % $$$ j = find((X(1,:)==X(1,m)+1) & (X(2,:)==X(2,m)));
502 % $$$ A(j,m) = a1(X(:,m));
503 % $$$ j = find((X(1,:)==X(1,m)-1) & (X(2,:)==X(2,m)));
504 % $$$ A(j,m) = a2(X(:,m));
505 % $$$ j = find((X(1,:)==X(1,m)) & (X(2,:)==X(2,m)+1));
506 % $$$ A(j,m) = a3(X(:,m));
507 % $$$ j = find((X(1,:)==X(1,m)) & (X(2,:)==X(2,m)-1));
508 % $$$ A(j,m) = a4(X(:,m));
512 % $$$ % KoeffizientenZerlegung
513 % $$$ clear A1; % for k1
514 % $$$ A1 = sparse([],[],[],p,p,7*p);
517 % $$$ j = find ((X(1,:)==X(1,m)+1) & (X(2,:)==X(2,m)));
521 % $$$ clear A2; % for u1
522 % $$$ A2 = sparse([],[],[],p,p,7*p);
524 % $$$ A2(m,m) = -X(1,m);
525 % $$$ j = find((X(1,:)==X(1,m)-1) & (X(2,:)==X(2,m)));
526 % $$$ A2(j,m) = X(1,m);
529 % $$$ clear A3; % for u2
530 % $$$ A3 = sparse([],[],[],p,p,7*p);
532 % $$$ A3(m,m) = -X(2,m);
533 % $$$ j = find((X(1,:)==X(1,m)) & (X(2,:)==X(2,m)-1));
534 % $$$ A3(j,m) = X(2,m);
537 % $$$ clear A4; % for V1
538 % $$$ A4 = sparse([],[],[],p,p,7*p);
540 % $$$ A4(m,m) = -X(2,m)^h/(M1^h+X(2,m)^h);
541 % $$$ j = find((X(1,:)==X(1,m)+1) & (X(2,:)==X(2,m)));
542 % $$$ A4(j,m) = X(2,m)^h/(M1^h+X(2,m)^h);
545 % $$$ clear A5; % for V2
546 % $$$ A5 = sparse([],[],[],p,p,7*p);
548 % $$$ A5(m,m)= -X(1,m)^h/(M2^h+X(1,m)^h);
549 % $$$ j = find((X(1,:)==X(1,m)) & (X(2,:)==X(2,m)+1));
550 % $$$ A5(j,m) = X(1,m)^h/(M2^h+X(1,m)^h);
553 % $$$ % state space of the nominal system
557 % $$$ D = zeros(1,p);
558 % $$$ sys=ss(A,B,C,D);
560 % $$$ %Model reduction, sysb is a balanced realization for sys.sysb=T*sys*T^-1
561 % $$$ [sysb,g,T,Ti]= balreal(sys);
563 % $$$ sysr = modred(sysb,[n:p],'del');
565 % $$$ a2 = zeros(p-n+1,n-1);
566 % $$$ V = T^-1*[a1;a2];
567 % $$$ W = T'*[a1;a2];
569 % $$$ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570 % $$$ % compare the reduced system with different parameters with the original system
573 % $$$ % Ar = k1*A1r+u1*A2r+u2*A3r+V1*A4r+V2*A5r
574 % $$$ % Air = W'*Ai*V
575 % $$$ Ar = parameterlist(i,1)*W'*A1*V + parameterlist(i,2)*W'*A2*V + parameterlist(i,3)*W'*A3*V + parameterlist(i,4)*W'*A4*V + parameterlist(i,5)*W'*A5*V;
578 % $$$ % original system
579 % $$$ a1 = @(x) (parameterlist(i,1)+parameterlist(i,4)*x(2)^h/(M1^h+x(2)^h));
580 % $$$ a2 = @(x) parameterlist(i,2)*x(1);
581 % $$$ a3 = @(x) parameterlist(i,5)*x(1)^h/(M2^h+x(1)^h);
582 % $$$ a4 = @(x) parameterlist(i,3)*x(2);
584 % $$$ A = sparse([],[],[],p,p,7*p);
586 % $$$ A(m,m) = -(a1(X(:,m))+a2(X(:,m))+a3(X(:,m))+a4(X(:,m)));
587 % $$$ j = find((X(1,:)==X(1,m)+1) & (X(2,:)==X(2,m)));
588 % $$$ A(j,m) = a1(X(:,m));
589 % $$$ j = find((X(1,:)==X(1,m)-1) & (X(2,:)==X(2,m)));
590 % $$$ A(j,m) = a2(X(:,m));
591 % $$$ j = find((X(1,:)==X(1,m)) & (X(2,:)==X(2,m)+1));
592 % $$$ A(j,m) = a3(X(:,m));
593 % $$$ j = find((X(1,:)==X(1,m)) & (X(2,:)==X(2,m)-1));
594 % $$$ A(j,m) = a4(X(:,m));
598 % $$$ subplot(4,3,i);
601 % $$$ [t,x]=ode15s(@(t,x) A*x, [0 1000000], x0);
602 % $$$ plot(t,sum(x'),'r');
606 % $$$ % reduced system
608 % $$$ x2=x1(1:(n-1),:);
609 % $$$ [tr,xr]=ode15s(@(tr,xr) Ar*xr, [0 1000000], x2);
612 % $$$ for m = 1:size(xr,1)
613 % $$$ y(m)=sysr.c*xr(m,:)';
617 % $$$ xlabel('zeit t');