home *** CD-ROM | disk | FTP | other *** search
- /*
-
- Make spots and stripes with reaction-diffusion.
-
- The spot-formation system is described in the article:
-
- "A Model for Generating Aspects of Zebra and Other Mammailian
- Coat Patterns"
- Jonathan B. L. Bard
- Journal of Theoretical Biology, Vol. 93, No. 2, pp. 363-385
- (November 1981)
-
- The stripe-formation system is described in the book:
-
- Models of Biological Pattern Formation
- Hans Meinhardt
- Academic Press, 1982
-
-
- Permission is granted to modify and/or distribute this program so long
- as the program is distributed free of charge and this header is retained
- as part of the program.
-
- Copyright (c) Greg Turk, 1991
-
- */
-
- #include <stdio.h>
- #include <math.h>
-
- extern double atof();
- extern double drand48();
-
- float frand();
-
- /* screen stuff */
-
- int xsize = 30;
- int ysize = 30;
- int psize = 4;
-
- /* simulation variables */
-
- int interval = 200;
- int value_switch = 1;
- int stripe_flag = 0;
-
- #define STRIPES 1
- #define SPOTS 2
-
- #define MAX 200
-
- float a[MAX][MAX];
- float b[MAX][MAX];
- float c[MAX][MAX];
- float d[MAX][MAX];
- float e[MAX][MAX];
-
- float da[MAX][MAX];
- float db[MAX][MAX];
- float dc[MAX][MAX];
- float dd[MAX][MAX];
- float de[MAX][MAX];
-
- float ai[MAX][MAX];
-
- float p1,p2,p3;
-
- float diff1,diff2;
-
- float arand;
- float a_steady;
- float b_steady;
-
- float beta_init;
- float beta_rand;
-
- float speed = 1.0;
-
- int sim = 1;
-
-
- /******************************************************************************
- Main routine.
- ******************************************************************************/
-
- main (argc,argv)
- int argc;
- char *argv[];
- {
- char *s;
-
- /* parse the command line options */
-
- while(--argc >0 && (*++argv)[0]=='-') {
- for(s = argv[0]+1; *s; s++)
- switch(*s) {
- case 'n':
- xsize = atoi (*++argv);
- ysize = atoi (*++argv);
- if (xsize > MAX || ysize > MAX)
- printf ("oops, too large a screen size\n");
- argc -= 2;
- break;
- case 'x':
- stripe_flag = 1;
- break;
- default:
- break;
- }
- }
-
- /* setup graphics */
-
- init_graphics (psize * xsize, psize * ysize, 40);
- set_pixel_size (psize);
-
- /* make spots or stripes */
-
- if (stripe_flag)
- do_stripes();
- else
- do_spots();
- }
-
-
- /******************************************************************************
- Run Meinhardt's stripe-formation system.
- ******************************************************************************/
-
- do_stripes()
- {
- p1 = 0.04;
- p2 = 0.06;
- p3 = 0.04;
-
- diff1 = 0.009;
- diff2 = 0.2;
-
- arand = 0.02;
-
- sim = STRIPES;
- value_switch = 1;
- compute();
- }
-
-
- /******************************************************************************
- Run Turing reaction-diffusion system.
- ******************************************************************************/
-
- do_spots()
- {
- beta_init = 12;
- beta_rand = 0.1;
-
- a_steady = 4;
- b_steady = 4;
-
- diff1 = 0.25;
- diff2 = 0.0625;
-
- p1 = 0.2;
- p2 = 0.0;
- p3 = 0.0;
-
- sim = SPOTS;
- value_switch = 2;
- compute();
- }
-
-
- /******************************************************************************
- Diffuse and react.
- ******************************************************************************/
-
- compute()
- {
- int k;
- int iterations = 99999999;
-
- /* calculate semistable equilibria */
-
- semi_equilibria();
-
- /* start things diffusing */
-
- for (k = 0; k < iterations; k++) {
-
- if (k % interval == 0) {
- printf ("iteration %d\n", k);
- switch (value_switch) {
- case 1:
- show(a);
- break;
- case 2:
- show(b);
- break;
- case 3:
- show(c);
- break;
- case 4:
- show(d);
- break;
- case 5:
- show(e);
- break;
- default:
- printf ("bad switch in compute: %d\n", value_switch);
- break;
- }
- }
-
- /* perform reaction and diffusion */
-
- switch (sim) {
- case STRIPES:
- multiplicative_help();
- break;
- case SPOTS:
- turing();
- break;
- default: break;
- }
- }
- }
-
-
- /******************************************************************************
- Create stripes with what Hans Meinhardt calls a two-species balance.
- ******************************************************************************/
-
- multiplicative_help()
- {
- int i,j;
- int iprev,inext,jprev,jnext;
- float aval,bval,cval,dval,eval;
- float ka,kc,kd;
- float temp1,temp2;
- float dda,ddb;
- float ddd,dde;
-
- /* compute change in each cell */
-
- for (i = 0; i < xsize; i++) {
-
- ka = -p1 - 4 * diff1;
- kc = -p2;
- kd = -p3 - 4 * diff2;
-
- iprev = (i + xsize - 1) % xsize;
- inext = (i + 1) % xsize;
-
- for (j = 0; j < ysize; j++) {
-
- jprev = (j + ysize - 1) % ysize;
- jnext = (j + 1) % ysize;
-
- aval = a[i][j];
- bval = b[i][j];
- cval = c[i][j];
- dval = d[i][j];
- eval = e[i][j];
-
- temp1 = 0.01 * aval * aval * eval * ai[i][j];
- temp2 = 0.01 * bval * bval * dval;
-
- dda = a[i][jprev] + a[i][jnext] + a[iprev][j] + a[inext][j];
- ddb = b[i][jprev] + b[i][jnext] + b[iprev][j] + b[inext][j];
- ddd = d[i][jprev] + d[i][jnext] + d[iprev][j] + d[inext][j];
- dde = e[i][jprev] + e[i][jnext] + e[iprev][j] + e[inext][j];
-
- da[i][j] = aval * ka + diff1 * dda + temp1 / cval;
- db[i][j] = bval * ka + diff1 * ddb + temp2 / cval;
- dc[i][j] = cval * kc + temp1 + temp2;
- dd[i][j] = dval * kd + diff2 * ddd + p3 * aval;
- de[i][j] = eval * kd + diff2 * dde + p3 * bval;
- }
- }
-
- /* affect change */
-
- for (i = 0; i < xsize; i++)
- for (j = 0; j < ysize; j++) {
- a[i][j] += (speed * da[i][j]);
- b[i][j] += (speed * db[i][j]);
- c[i][j] += (speed * dc[i][j]);
- d[i][j] += (speed * dd[i][j]);
- e[i][j] += (speed * de[i][j]);
- }
- }
-
-
- /******************************************************************************
- Turing's reaction-diffusion equations.
- ******************************************************************************/
-
- turing()
- {
- int i,j;
- int iprev,inext,jprev,jnext;
- float aval,bval;
- float ka;
- float dda,ddb;
- float Diff1,Diff2;
-
- Diff1 = diff1 / 2.0;
- Diff2 = diff2 / 2.0;
- ka = p1 / 16.0;
-
- /* compute change in each cell */
-
- for (i = 0; i < xsize; i++) {
-
- iprev = (i + xsize - 1) % xsize;
- inext = (i + 1) % xsize;
-
- for (j = 0; j < ysize; j++) {
-
- jprev = (j + ysize - 1) % ysize;
- jnext = (j + 1) % ysize;
-
- aval = a[i][j];
- bval = b[i][j];
-
- dda = a[i][jprev] + a[i][jnext] + a[iprev][j] + a[inext][j] - 4 * aval;
- ddb = b[i][jprev] + b[i][jnext] + b[iprev][j] + b[inext][j] - 4 * bval;
-
- da[i][j] = ka * (16 - aval * bval) + Diff1 * dda;
- db[i][j] = ka * (aval * bval - bval - c[i][j]) + Diff2 * ddb;
- }
- }
-
- /* affect change */
-
- for (i = 0; i < xsize; i++)
- for (j = 0; j < ysize; j++) {
- a[i][j] += (speed * da[i][j]);
- b[i][j] += (speed * db[i][j]);
- if (b[i][j] < 0)
- b[i][j] = 0;
- }
- }
-
-
- /******************************************************************************
- Calculate semi-stable equilibria.
- ******************************************************************************/
-
- semi_equilibria()
- {
- int i,j;
- float ainit,binit;
- float cinit,dinit,einit;
-
- ainit = binit = cinit = dinit = einit = 0;
-
- /* figure the values */
-
- switch (sim) {
-
- case STRIPES:
- for (i = 0; i < xsize; i++) {
-
- ainit = p2 / (2 * p1);
- binit = ainit;
- cinit = 0.02 * ainit * ainit * ainit / p2;
- dinit = ainit;
- einit = ainit;
-
- for (j = 0; j < ysize; j++) {
- a[i][j] = ainit;
- b[i][j] = binit;
- c[i][j] = cinit;
- d[i][j] = dinit;
- e[i][j] = einit;
- ai[i][j] = 1 + frand (-0.5 * arand, 0.5 * arand);
- }
- }
- break;
-
- case SPOTS:
- for (i = 0; i < xsize; i++)
- for (j = 0; j < ysize; j++) {
- a[i][j] = a_steady;
- b[i][j] = b_steady;
- c[i][j] = beta_init + frand (-beta_rand, beta_rand);
- }
- break;
-
- default:
- printf ("bad case in semi_equilibria\n");
- break;
- }
- }
-
-
- /******************************************************************************
- Switch for picking array to rescale.
- ******************************************************************************/
-
- do_rescale (index,min,max)
- int index;
- float min,max;
- {
- switch (index) {
- case 1:
- rescale_values (a, min, max);
- break;
- case 2:
- rescale_values (b, min, max);
- break;
- case 3:
- rescale_values (c, min, max);
- break;
- case 4:
- rescale_values (d, min, max);
- break;
- case 5:
- rescale_values (e, min, max);
- break;
- default:
- printf ("bad switch in do_rescale: %d\n", index);
- break;
- }
- }
-
-
- /******************************************************************************
- Rescale values in array.
-
- Entry:
- values - array to rescale
- min_final - minimum value to map to
- max_final - maximum value to map to
- ******************************************************************************/
-
- rescale_values (values,min_final,max_final)
- float values[MAX][MAX];
- float min_final;
- float max_final;
- {
- int i,j;
- float val;
- float min = 1e20;
- float max = -1e20;
-
- /* find minimum and maximum values */
-
- for (i = 0; i < xsize; i++)
- for (j = 0; j < ysize; j++) {
- if (values[i][j] < min)
- min = values[i][j];
- if (values[i][j] > max)
- max = values[i][j];
- }
-
- if (min == max) {
- min = max - .001;
- max = min + .002;
- }
-
- /* rescale the values */
-
- for (i = 0; i < xsize; i++)
- for (j = 0; j < ysize; j++) {
- val = (values[i][j] - min) / (max - min);
- val = min_final + val * (max_final - min_final);
- values[i][j] = val;
- }
- }
-
-
- /******************************************************************************
- Display the activator.
- ******************************************************************************/
-
- show(values)
- float values[MAX][MAX];
- {
- int i,j;
- float output;
- float min = 1e20;
- float max = -1e20;
-
- /* find minimum and maximum values */
-
- for (i = 0; i < xsize; i++)
- for (j = 0; j < ysize; j++) {
- if (values[i][j] < min)
- min = values[i][j];
- if (values[i][j] > max)
- max = values[i][j];
- }
-
- if (min == max) {
- min = max - 1;
- max = min + 2;
- }
-
- printf ("min max diff: %f %f %f\n", min, max, max - min);
-
- /* display the values */
-
- for (i = 0; i < xsize; i++)
- for (j = 0; j < ysize; j++) {
- output = (values[i][j] - min) / (max - min);
- output = output * 255.0;
- writepixel (i, j, (int) output);
- }
-
- flushbuffers();
- }
-
-
- /******************************************************************************
- Pick a random number between min and max.
- ******************************************************************************/
-
- float frand(min, max)
- float min,max;
- {
- return (min + drand48() * (max - min));
- }
-
-