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 than2 / 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, namedn.gif
,ne.gif
,e.gif
,se.gif
,s.gif
,sw.gif
,w.gif
andnw.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 scripteg/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
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.