NAME

Tk::Taxis - Perl extension for simulating biological taxes

SYNOPSIS

use Tk::Taxis;
my $taxis = $mw->Taxis( -width => 200, -height => 100 )->pack();
$taxis->configure( -population => 20 );
$taxis->taxis() while 1;

ABSTRACT

Simulates the biological movement called taxis

DESCRIPTION

Organisms such as bacteria respond to gradients in chemicals, light, etc, by a process called taxis ('movement'). This module captures some of the spirit of this model of organismal movement. Bacteria are unable to measure differential gradients of chemicals along the length of their cells. Instead, they measure the concentration at a given point, move a little, measure it again, then if they find they are running up a concentration gradient, they reduce their tumbling frequency (the probability that they will randomly change direction). In this way, they effect a random walk that is biased up the gradient.

METHODS

Tk::Taxis is a composite widget, so to invoke a new instance, you need to call it in the usual way...

my $taxis = $mw->Taxis( -option => value )->pack();
$taxis->configure ( -option => value );
my $number = $taxis->cget( -option );

or similar. This widget is a composite, based on Frame and inplementing a Canvas. Configurable options are mostly forwarded to the Canvas subwidget, which be directly accessed by the Subwidget('canvas') method. Options specific to the Tk::Taxis widget are listed below. If you try to pass in values too low or high (as specified below), the module will carp (if warnings are enabled) and use a default minimum or maximum instead. These options can be set in the constructor, and get/set by the standard cget and configure methods.

  • -width

    Sets the width of the taxis arena. Defaults to 400.

  • -height

    Sets the height of the taxis arena. You are advised to set the height and width when constructing the widget, rather than configuring them after the event, as this will result in repeated redrawings of the canvas. Defaults to 200.

  • -tumble

    This sets the default tumble frequency, i.e. the tumble frequency when the critters are moving down the concentration gradient. No sanity checking is done, but a tumble frequency of 1 is unlikely to get you very far. Defaults to 0.03.

  • -preference

    This takes a numeric argument indicating the preference the critters have for the right hand side of the taxis arena. When the critters are moving up the gradient (to the right), their tumble frequency will be equal to the default tumble divided by the absolute value of this number. Negative preferences will reverse the taxis. Values in the interval [-1, +1] will be truncated to 1, since the tumble frequency does not increase above the default in reality (this is not how negative taxis is achieved). Defaults to 100.

  • -speed

    This sets the speed of the critters. When the critters are moved, the run length is essentially set to rand( width_of_canvas ) * speed * cos rotation. If there is no rotation, the maximum run length will be simply be the width of the canvas multiplied by the speed. If you try to set a speed lower than 2 / width_of_canvas, it will be ignored, and this mimimum value will be used instead otherwise your critters, moving a fractional number of pixels, will sit there and spin like tops. Defaults to 0.006.

  • -population

    This takes an integer argument to configure the size of the population. If cget( -population ) is called, the return vale depends on context: the total population is returned in scalar context, but in list context, the numbers of critters on the left and right are returned in that order. Defaults to 10.

  • -images

    This takes a string argument which is the path to a directory containing images to display as critters. If this begins with an @ sign, this will be taken to be a real path. Otherwise, it will be taken to be a default image set. This may currently be 'woodlice' or 'bacteria' (these images are located in directories of the same name in @INC/Tk/Taxis/images/). There must be eight images, named n.gif, ne.gif, e.gif, se.gif, s.gif, sw.gif, w.gif and nw.gif, each showing the critter in a different orientation (n being vertical, e being pointing to the right, etc). Defaults to 'woodlice'.

  • -left_fill

    This takes an colour string argument (e.g. "red" or "#00FF44") to set the fill colour of the left hand side of the arena.

  • -right_fill

    This takes an colour string argument to set the fill colour of the right hand side of the arena.

These options can also all be called as similarly named methods. There is also one additional public method...

  • taxis()

    This executes one cycle of the taxis simulation. Embed calls to this in a while loop to run the simulation. See the script eg/woodlice.pl for an example of how to embed an interruptable loop within a handrolled main-loop, or CAVEATS below.

Two final methods available are image_height and image_width, which get/set the height and width of the image used as a critter. It is inadvisable to set these, but the Tk::Taxis::Critter class requires read-only access to them.

SCRIPTS

The module installs a script called woodlice.pl in your perl's bin directory which is a fully functional simulation demonstrating the use of the module.

CAVEATS

Those used to writing...

MainLoop();

in every Tk script should note that because the simulation requires its own event loop within the event loop of the main program, this will not work out of the box. The best solution I have found is this...

# import some semantics 
use Tk qw( DoOneEvent DONT_WAIT );
use Tk::Taxis;
use Time::HiRes;
my $mw = new MainWindow;
my $taxis = $mw->Taxis()->pack();

# this tells us whether we are running the simulation or not
my $running = 1;

# minimum refresh rate
my $refresh = 0.02; # 20 ms

# home-rolled event loop
while ( 1 )
{
  my $finish = $refresh + Time::HiRes::time;
  $taxis->taxis() if $running;
  while ( Time::HiRes::time < $finish  )
    # take up some slack time if the loop executes very quickly
  { 
    DoOneEvent( DONT_WAIT );
  }
}

# arrange for a start/stop Button or similar to invoke this callback
sub start_toggle
{
	$running = $running ? 0 : 1;
}

As every call to taxis involves iterating over the entire population, when that population is small, the iterations occur more quickly than when the population is large. This event loop ensures that small populations do not whizz around madly (as would be the case if we used a simple while loop), whilst ensuring that large populations do not cause the script to hang in deep recursion (as would be the case if we used a timed repeat callback and a default MainLoop()).

SEE ALSO

Tk::Taxis::Critter

AUTHOR

Steve Cook, <steve@steve.gb.com>

COPYRIGHT AND LICENSE

Copyright 2003 by Steve Cook

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.