[Avida-SVN] r3357 - branches/developers/avida-edward/source/python/AvidaGui2

welsberr at myxo.css.msu.edu welsberr at myxo.css.msu.edu
Wed Aug 5 09:45:51 PDT 2009


Author: welsberr
Date: 2009-08-05 12:45:50 -0400 (Wed, 05 Aug 2009)
New Revision: 3357

Added:
   branches/developers/avida-edward/source/python/AvidaGui2/change_notes.txt
   branches/developers/avida-edward/source/python/AvidaGui2/mypython
   branches/developers/avida-edward/source/python/AvidaGui2/pyAvidaEdCtrl.py
   branches/developers/avida-edward/source/python/AvidaGui2/pyDiversitySandbox.py
   branches/developers/avida-edward/source/python/AvidaGui2/pyGridMaster.py
   branches/developers/avida-edward/source/python/AvidaGui2/pyMDMkEnv.py
   branches/developers/avida-edward/source/python/AvidaGui2/pyMDSetupFormView.ui
   branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_MDView.ui
   branches/developers/avida-edward/source/python/AvidaGui2/pyPRNGState.py
Modified:
   branches/developers/avida-edward/source/python/AvidaGui2/pyEduWorkspaceCtrl.py
   branches/developers/avida-edward/source/python/AvidaGui2/pyFreezerCtrl.py
   branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_GraphCtrl.py
   branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_PetriDishCtrl.py
   branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_StatsCtrl.py
   branches/developers/avida-edward/source/python/AvidaGui2/pyPetriConfigureCtrl.py
   branches/developers/avida-edward/source/python/AvidaGui2/pyPetriConfigureView.ui
   branches/developers/avida-edward/source/python/AvidaGui2/pyPetriDishCtrl.py
   branches/developers/avida-edward/source/python/AvidaGui2/pyReadFreezer.py
   branches/developers/avida-edward/source/python/AvidaGui2/pyWriteAvidaCfgEvent.py
   branches/developers/avida-edward/source/python/AvidaGui2/pyWriteToFreezer.py
Log:
Additional files for the Multi-Dish version



Added: branches/developers/avida-edward/source/python/AvidaGui2/change_notes.txt
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/change_notes.txt	                        (rev 0)
+++ branches/developers/avida-edward/source/python/AvidaGui2/change_notes.txt	2009-08-05 16:45:50 UTC (rev 3357)
@@ -0,0 +1,11 @@
+
+
+Code for grabbing the population genomes is in
+
+pyPetriDishCtrl.py :
+  def extractPopulationSlot(self, send_reset_signal = False, send_quit_signal = False):
+
+Will need to do that to compute diversity metrics
+
+
+

Added: branches/developers/avida-edward/source/python/AvidaGui2/mypython
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/mypython	                        (rev 0)
+++ branches/developers/avida-edward/source/python/AvidaGui2/mypython	2009-08-05 16:45:50 UTC (rev 3357)
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# Build environment python
+# /Users/welsberr/aed_env/Build/AvidaOneStepLocal/bin/python $1
+
+# Run-time python
+/Users/welsberr/avida/avida-ed/Avida-Ed-onestep-qt3/Build/avida_bld/Avida-ED/bin/Avida-ED.app/Contents/MacOS/python $1


Property changes on: branches/developers/avida-edward/source/python/AvidaGui2/mypython
___________________________________________________________________
Name: svn:executable
   + *

Added: branches/developers/avida-edward/source/python/AvidaGui2/pyAvidaEdCtrl.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyAvidaEdCtrl.py	                        (rev 0)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyAvidaEdCtrl.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -0,0 +1,66 @@
+"""
+
+pyAvidaCtrl.py
+
+Routines to handle running avidacore plus updating a database backend.
+
+Theory of operation:
+
+Initialize, run, pause, or reset a single instance of Avida
+
+Within a run: 
+- collect data on a per-update basis.
+
+"""
+
+class AvidaCtrl():
+    def __init__(self):
+        """
+        Basic initialization for Avida instance
+        """
+        pass
+
+    def beginRun(self):
+        """
+        Start a run based on current settings
+        """
+        pass
+
+    def pauseRun(self):
+        """
+        Pause an ongoing run
+        """
+        pass
+
+    def killRun(self):
+        """
+        Take down a run.
+        """
+
+        pass
+
+    def atUpdate(self):
+        """
+        Method called at the end of an update. 
+        This is a place to connect things that should run at 
+        each update.
+        
+        """
+        pass
+
+    def perUpdateDataDump(self):
+        """
+        Method to dump the data from a run at each update
+        """
+        # Check for being in a run, exit if not
+        # Go through entire multidish to extract informtion
+        # Cell traversal
+        # Organism:
+        # - Is it new? Add a new record?
+        # - Fitness, Met. Rate, Gest. Time, 
+        # - Phenotype
+        # Population properties
+        # Diversity measures
+        pass
+
+

Added: branches/developers/avida-edward/source/python/AvidaGui2/pyDiversitySandbox.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyDiversitySandbox.py	                        (rev 0)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyDiversitySandbox.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -0,0 +1,529 @@
+#!/Users/welsberr/avida/avida-ed/Avida-Ed-onestep-qt3/Build/AvidaOneStepLocal/bin/python
+
+# Python program to test various diversity measures
+
+import os 
+import sys
+import math
+
+import random                                                                                                                                                                                                                      
+# From tutorial:
+# >>> random.choice(['apple', 'pear', 'banana'])
+# 'apple'
+# >>> random.sample(xrange(100), 10)   # sampling without replacement
+# [30, 83, 16, 4, 8, 81, 41, 50, 18, 33]
+# >>> random.random()
+# random float
+# 0.17970987693706186
+# >>> random.randrange(6)    
+# random integer chosen from range(6)
+
+from UserDict import UserDict
+
+class UnrealWorld():
+    """
+    UnrealWorld provides a class for generating an x by y grid of random
+    or mutated genotypes and phenotypes.
+    """
+    # Class properties 
+    genealts = "abcdefghijklmnopqrstuvwxyz"
+    phenalts = "01"
+    slength = 50
+    mutrate = 0.02
+    uw = []
+
+    # Class methods
+
+    def __init__(self,x=300,y=300,mutrate=0.02):
+        """
+        __init__ for UnrealWorld, sets up genome and phenotypes for a randomly generated
+        population.
+        """
+        parent = ""
+        for ii in range(x):         # (ii = 0; ii < x; ii++):
+            for jj in range(y):     # (jj = 0; jj < y; jj++):
+                self.uw[ii][jj] = self.mutgenome(self.slength,parent,self.genealts,self.mutrate)
+                print self.uw[ii][jj]
+                print "\n"
+
+    def mutgenome(self, slength=50, parent="", alts="01", mutrate=0.02):
+        """
+        mutgenome generates a new genome of a specified length. If the parent
+        genome is blank, all bases are randomly determined. Else the parent 
+        genome is copied except if a random variable fals below the mutation
+        rate, in which case it is randomly picked.
+        """
+        # Start with a blank string
+        mystr = ""
+        # Now copy or generate bases as needed
+        for kk in range(0, slength-1):      # (kk = 0; kk < slength; kk++):
+            myrand = random.random()
+            if ((kk >= len(parent)) or (myrand <= mutrate)):
+                # Select newbase from alternatives
+                mystr += alts[random.randrange(len(alts))]
+            else:
+                mystr += parent[kk]
+        return mystr
+
+class diversity():
+    """
+    diversity: a class to provide a variety of methods for measures of diversity
+
+    There are a number of arguments given at Lou Jost's site that look convincing
+    that there is a distinction between a diversity index and a diversity measure.
+    Jost gives the formulae for converting common diversity indices into diversity
+    measures, which have the form of estimates of effective number of species. Therefore,
+    I am adding those to the diversity results from various methods here.
+
+    Site: http://www.loujost.com/Statistics%20and%20Physics/Diversity%20and%20Similarity/DiversitySimilarityHome.htm
+    """
+    def __init__(self):
+        """
+        __init__ there is no initialization required
+        """
+        pass
+
+    def factorial(self,x):
+        """
+        factorial
+        Provides a factorial function to handle large values of x. Essentially chooses
+        to approximate the factorial when x exceeds a threshold.
+        """
+        # Regular factorial processing
+        # if (300 > x):
+        if (0):
+            xf = 1;
+            for ii in range(2,x+1):
+                xf *= ii
+        else:                     # Too big, so aproximate
+            # Stirling's approximation
+            # n! ~ n^n e^(-n) sqrt(2 * pi * n) (1 + 1/(12n))
+            xf = (x ** x) * (math.e ** (-x)) * math.sqrt(2 * math.pi * x) * (1.0 + 1.0 / (12 * x))
+        return xf
+
+
+    def nmatches(self,s1,s2):
+        """
+        nmatches
+
+        Returns the number of characters that match between
+        two strings.
+        """
+        mc = 0
+        mn = min(len(s1),len(s2))
+        for ii in range(mn):
+            if (s1[ii] == s2[ii]):
+                mc += 1
+        return((mc,mn))
+
+    def ndiffs(self,s1,s2):
+        """
+        ndiffs
+
+        Returns the number of differences between two strings.
+        """
+        (mc,mn) = self.nmatches(s1,s2)
+
+        return ((mn - mc, mn))
+
+    def addToDictWithIncrement(self,dict,key):
+        """
+        addToDict
+
+        It is common to use a dict to collect frequency information,
+        where each added key matching a previously added key
+        increments the associated value.  This is fine except for the
+        case of a thus-far-unique key not yet in the dictionary, which
+        has to be handled differently in order not to throw the
+        KeyError exception. Python dictionaries are touchier than Perl
+        hashes, and the initial entry cannot trigger a retrieval of a
+        null value; a KeyError exception is thrown.  Thus, all
+        additions need to be handled in a way that eliminates the
+        KeyError on new key problem.
+        """
+        a = dict.get(key,0)
+        a += 1
+        dict[key] = a
+
+
+    def qlambda(self,n,q,pop):
+        """
+        qlambda measure at basis of all diversity metrics
+        Based on paper by Lou Jost
+
+        Inputs :
+        n, number of samples, if n==0 then do the whole population
+        q, the order, this is what frequencies are raised to
+        pop, the population to work on
+        """
+        popsize = len(pop)
+        if ((n > popsize) or (0 >= n)):
+            n = popsize
+
+        # Load xotypes with all the strings we want to analyze, either
+        # a sample or the whole population
+        # This assumes that n << popsize when n < popsize. There could be
+        # trouble with this is n is only slightly smaller than popsize, 
+        # as it then is essentially trying to find a rare value by random
+        # search. To fix that, an alternate method within the first
+        # if clause should handle putting together the indices that would
+        # not be used, and then filling xotypes with the complementary
+        # set of indices.
+        # Initial workaround: limit restricted sample case to less than
+        # half the total population. This should keep the efficiency 
+        # reasonably high.
+        if (n < (popsize * 0.5)):             # Sample point randomly without replacement
+
+            ndx = -1                          # Initial assignment should throw an error if used
+            xotypes = {}                      # Clear the temporary dictionary for genotype or phenotype
+            ndxs = {}                         # Clear the temporary dictionary of indices
+
+            for ii in range(n):               # Find an unused index for every sample point
+                done = 0                      # Initialize control flag for index selection
+
+                while (0 == done):            # Repeat until we have an unused index
+                    ndx = random.randrange(n) # Pick a candidate randomly
+                    a = ndxs.get(ndx,0)       # Has it already been picked?
+
+                    if (0 == a):              # New index, accept it
+                        done = 1              # Flag to stop the while loop
+
+                self.addToDictWithIncrement(xotypes,pop[ndx]) # Add the genotype/phenotype to the dict
+                self.addToDictWithIncrement(ndxs,ndx)         # Add the index to the used index dict
+        else:
+            xotypes = {}                                # Clear the temporary dict
+            for ii in pop:                              # Repeat for every entry in the population
+                self.addToDictWithIncrement(xotypes,ii) # Add to the dict
+
+        # Now the strings to analyze are in xotypes, so do the analysis
+        psum = 0.0
+        # Try it with a list completion
+        psum = math.sum([(v / n) ** q  for k, v in xotypes.iteritems()])
+
+        return((psum,n))
+
+
+    def base_diversity(self,pop):
+        """
+        base_diversity
+
+        This calculates the diversity described as "gene diversity" in email
+        on Avida-ED capability.
+
+        For each base, calculate h' on the frequencies of bases seen among all
+        members of the population.
+        """
+        n = len(pop)      # Find the total population size
+        #print "len(pop) = %d" % (n)
+
+        # Estimate upper bound on length of genome
+        bc = len(pop[0]) * 1       # Factor of 1 assumes all strings are the same length
+
+        hs = []                    # Clear the h' array
+        for ii in range(bc):       # For each base
+            # print "ii = %d" % (ii) 
+            basecnt = {}           # Clear the base counting dict
+            basen = 0              # Clear the counter for number of samples
+            
+            for jj in range(n):    # For every member of the population
+                # Only process if the length is right
+                if (bc <= len(pop[jj])):
+                    #print "pop[%d][%d], pop[%d] = %s" % (jj,ii,jj,pop[jj])
+                    #print "jj = %d, len(%s) = %d, char[%d] = %s" % (jj,pop[jj],len(pop[jj]),ii,pop[jj][ii])
+                    #print "continuing"
+                    self.addToDictWithIncrement(basecnt,pop[jj][ii])  # Increment a counter for each base found
+                    basen += 1    # Increment the count of bases 
+
+            # Initialize temporary variables
+            psum2 = 0.0
+            pf = 0.0
+            pf2 = 0.0
+            h = 0.0
+
+            for kk in basecnt:            # For every different base observed
+                pf = (basecnt[kk] * 1.0) / (basen * 1.0)  # Calculate the frequency of the base
+                pf2 = pf * pf             # Calculate the squared frequency
+                psum2 += pf2              # Add to a running sum of the squared frequencies
+                h = 1.0 - psum2           # Find h' for this base as 1 - sum of squared frequencies
+                hs.append(h)                # Save h' in array
+
+        hhat = 0.0           # Initialize the whole-string H estimate
+        for ii in hs:        # For all the h's
+            hhat += ii       # Add to a sum
+        hhat = hhat / bc     # Take the average h' per base
+            
+        #print "hhat = %7.5f, basen = %d" % (hhat,basen)
+
+        return(hhat)         # Return the estimated h' per base
+
+    def tide_diversity(self,pop,s):
+        """
+        tide_diversity
+
+        This calculates the diversity measure described as "nucleotide
+        diversity" in email on Avida-ED capability.
+
+        This compares pairs of Avidians and calculates h' based on the 
+        scaled proportion of differences between the Avidians.
+
+        Inputs:
+        pop : array of strings representing genotypes, phenotypes, or whatever.
+        s : sample size, 0 = whole population, 0.0 < s < 1.0 is a proportion, otherwise an absolute number of samples
+        """
+
+        popsize = len(pop)
+        totalsamples = ((popsize * popsize) - popsize) * 0.5    # Triangular non-identical pairs
+        pcnt = 0
+        dcsum = 0.0
+
+        if (s == 0):
+            """
+            Do the whole population.
+            """
+            #print "tide_diversity: whole population"
+            for ii in range(len(pop)):
+                for jj in range(len(pop)):
+                    if (ii < jj):                
+                        pcnt += 1
+                        # print "Getting diffs for $pop[$ii] and $pop[$jj]\n"
+                        (dc,dm) = self.ndiffs(pop[ii],pop[jj])
+                        dcsum += dc / len(pop[ii])
+
+        else:
+
+            pairs = {}   # Clear the pairs dict
+            if (1.0 <= s):
+                """ 
+                Sample a specific number of pairs chosen randomly.
+                """
+                samples = int(min(s,totalsamples,popsize))
+                #print "tide_diversity: specific sample of population = %d" % (samples)
+            else:
+                """
+                Sample a fraction of the available pairs.
+                """
+
+                tsamp = s * totalsamples
+                samples = int(min(max(s * totalsamples,1),popsize))
+                #print "totalsamples=%d, proportion=%7.5f, intermediate=%7.5f, samples=%d" % (totalsamples,s,tsamp,samples)
+                #print "tide_diversity: proportion of population = %d" % (samples)                
+            if (samples < totalsamples):
+                #print "samples = " + str(samples) + ",totalsamples = " + str(totalsamples)
+                #print "finding %d samples out of " % (samples) + str(totalsamples)
+                for ii in range(samples):
+                    # Find an unexamined pair
+                    done = 0
+                    while (0 == done):
+                        r1 = random.randrange(popsize)
+                        r2 = random.randrange(popsize)
+                        
+                        if (r1 != r2):
+                            a = min(r1,r2)
+                            b = max(r1,r2)
+                            # Are those actual values in the population?
+                            if (0 < min(len(pop[a]),len(pop[b]))):
+                                k = "%d;%d" % (a,b)
+                                self.addToDictWithIncrement(pairs,k)
+                                if (1 == pairs[k]):
+                                    done = 1
+                        
+                    pcnt += 1
+                    # print "Getting diffs for $pop[$ii] and $pop[$jj]\n"
+                    (dc,dm) = self.ndiffs(pop[a],pop[b])
+                    dcsum += (dc * 1.0) / (len(pop[a]) * 1.0)
+                    #print "difference count = %d, dcsum = %7.5f" % (dc,dcsum)
+        
+        if (0 < pcnt):
+            ave_pi = dcsum / (pcnt * 1.0)
+        else:
+            ave_pi = 0.0
+        return(pcnt,ave_pi)  # Return the number of pairs and the average
+
+    def shannon_via_q(self,n,q,pop):
+        h = 0.0
+        res = self.qlambda(n,q,pop)
+        return((n,h))
+
+
+
+    def shannon_mf(self,aos,lnbase):
+        """
+        shannon_mf
+        This method finds the Shannon diversity measure H based on the 
+        machine formula provided by Lloyd et al. 1968.
+        
+        Input: aos = an array of strings
+        All needed properties are extracted from those found in the array of
+        strings provided.
+        """
+        # H' = (c / N) * (log(N!) - sum(log(n_i)))
+
+        # Set c as the conversion factor to change the logarithm base
+        c = lnbase
+        # Find N as the number of strings in aos
+        
+        # Collect the frequencies of appearance of each non-empty string
+        # Do this by setting up a temporary dictionary
+        mydict = {}    # Clear the temporary dict
+        
+        N = 0          # Initialize N
+        for ii in aos: # For every string in the array/list
+            if ("" != ii):                             # If the string is non-empty
+                # print "adding %s to dict" % (ii)     # Debug output
+                self.addToDictWithIncrement(mydict,ii) # Add it to the frequency-tracking dict
+                N += 1                                 # Increment the string count
+         
+        # print "N = %d" % (N)                           # Debug output
+
+        # Now sum up the individual frequency data
+        # This could require taking the factorial of a very large number,
+        # so use an approximation if the result will be very large
+        thesum = 0.0;                 
+        #for key in range(**mydict):
+        #    value = mydict{key}
+        #    thesum += math.log(self.factorial(value))
+
+        # Get the sum via list comprehension
+        # thesum = sum(math.log(self.factorial(elem)) for elem in mydict.values)
+
+        
+        # print "summing up"      # Debug output
+        if (0):                 # So don't do it this way
+            for k, v in mydict.iteritems():
+                thesum += math.log(self.factorial(v))
+            theh = (lnbase / N) * (math.log(self.factorial(N)) - thesum)
+
+        # Old school
+        p = 0.0                            # Initialize frequency
+        psum = 0.0                         # Initialize sum of frequencies
+        for k, v in mydict.iteritems():    # For every string that appears
+            # $p = $gens{$_} / $popsize;   
+            # $psum += $p * log($p);
+            p = float(v) / N               # Calculate the frequency 
+            psum += p * math.log(p)        # Add to the summation
+
+        theh = - psum                      # Negate to make it H'
+
+        ens = math.exp(theh)               # Get effective number of species per Jost
+
+        return ((theh,N,ens))
+
+    def ginisimpson(self,aos):
+        """
+        ginisimpson
+        
+
+sub find_div2 {
+    local(@pop) = @_;
+    local($_,$ii,$jj,$pcnt);
+
+    $pcnt = 0;
+    $dcsum = 0.0;
+    for ($ii = 0; $ii < $#pop; $ii++) {
+	for ($jj = $ii+1; $jj <= $#pop; $jj++) {
+	    if ($ii < $jj) {                
+		$pcnt++;
+		# print "Getting diffs for $pop[$ii] and $pop[$jj]\n";
+		($dc,$dm) = &ndiffs($pop[$ii],$pop[$jj]);
+		$dcsum += $dc / length($pop[$ii]);
+	    }
+	}
+    }
+
+    $pi = $dcsum / $pcnt;
+    print "$pi = $dcsum / $pcnt;\n";
+
+    return($pi,$pcnt);
+}
+        """
+        pcnt = 0 
+        dcsum = 0.0
+        for ii in range(aos):
+            for jj in range(aos):
+                if (jj < ii):
+                    pcnt += 1
+                    # Count differences between two strings
+                    (dc, dm) = self.ndiffs(aos[ii],aos[jj])
+                    
+                    # Normalize for string length and sum
+                    dcsum = dc / min(len(aos[ii]),len(aos[jj]))
+
+        pi = dcsum / pcnt
+        
+        # multiple values being returned, so use a tuple
+        return((pi,pcnt))
+
+
+    def ginisimpson_timed(self,aos):
+        """
+        ginisimpson_timed
+
+sub find_div2_timed_dt {
+    local($seconds, at pop) = @_;
+    local($_,$ii,$jj,$pcnt);
+
+    #$t0 = DateTime->now;
+
+    $popsize = $#pop + 1;
+    $pcnt = 0;
+    $dcsum = 0.0;
+    undef(%pairs);
+    $td = 0.0;
+    do {
+	# Get the population indices for a pair randomly
+	$trycnt = 0;
+	
+	$bad = 0;
+	do {
+	    $ok = 0;
+	    $r1 = int(rand($popsize));
+	    $r2 = int(rand($popsize));
+	    unless ($r1 == $r2) { 
+		$ii = &min($r1,$r2);
+		$jj = &max($r1,$r2);
+		$key = join(";",$ii,$jj);
+		unless (defined $pairs{$key}) {
+		    $ok = 1;
+		}
+	    }
+	    if ((0.4 * $popsize) < $trycnt++) {
+		$bad = 1;
+	    }
+	} until ($ok || $bad);
+	
+	# print "$key\n";
+	if ($bad) {
+	    $pi = $dcsum / $pcnt;
+	    # print "$td: $pi = $dcsum / $pcnt;\n";
+	    
+	    return($pi,$pcnt);
+	}
+
+	# Compare them
+	$pcnt++;
+	($dc,$dm) = &ndiffs($pop[$ii],$pop[$jj]);
+	$dcsum += $dc / length($pop[$ii]);
+	
+	# Are we out of time?
+	#$t1 = DateTime->now;
+	#$td = $t1 - $t0;
+	#$tds = $td->offset;
+	$tds = $pcnt / 16000;
+	#print "td = $tds, seconds = $seconds\n";
+    } while ($seconds > $tds);
+
+    #print "Out of while loop\n";
+
+    $pi = $dcsum / $pcnt;
+    print "$tds: $pi = $dcsum / $pcnt;\n";
+
+    return($pi,$pcnt);
+}
+        """
+        
+
+        pass
+
+
+
+    

Modified: branches/developers/avida-edward/source/python/AvidaGui2/pyEduWorkspaceCtrl.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyEduWorkspaceCtrl.py	2009-08-04 03:26:21 UTC (rev 3356)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyEduWorkspaceCtrl.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -43,10 +43,10 @@
   # filter function:
   plugins = filter(lambda f: (os.path.splitext(f)[1] == '.ae_plugin'), names)
 
-  #print "plugin_visitor: arg:", arg
-  #print "plugin_visitor: dirname:", dirname
-  #print "plugin_visitor: names:", names
-  #print "plugin_visitor: plugins:", plugins
+  print "plugin_visitor: arg:", arg
+  print "plugin_visitor: dirname:", dirname
+  print "plugin_visitor: names:", names
+  print "plugin_visitor: plugins:", plugins
 
   # Save the system path as is, so it can be restored later.
   sys_path = sys.path
@@ -56,7 +56,7 @@
   for plugin in plugins:
     # Put together the path to this plugin
     plugin_path = os.path.abspath(os.path.join(dirname, plugin))
-    #print "plugin_visitor: plugin_path:", plugin_path
+    print "plugin_visitor: plugin_path:", plugin_path
     
     # Alter the system path temporarily
     sys.path = [plugin_path] + sys_path
@@ -75,7 +75,7 @@
       # into the Avida instance
       p.construct(edu_workspace_ctrl.m_session_mdl)
 
-      #print "plugin_visitor: p:", p
+      print "plugin_visitor: p:", p
     except Exception, details:
       # Handle exceptions so that all the plugins can be tried
       print "Exception:", details

Modified: branches/developers/avida-edward/source/python/AvidaGui2/pyFreezerCtrl.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyFreezerCtrl.py	2009-08-04 03:26:21 UTC (rev 3356)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyFreezerCtrl.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -269,6 +269,8 @@
     self.m_session_mdl.m_session_mdtr.emit(PYSIGNAL("freezerItemsSelectedSig"),
       ("",))
 
+    self.m_session_mdl.m_session_mdtr.emit(PYSIGNAL("refreshSubDishList"), ())
+    
   # if mouse is pressed on list item prepare its info to be dragged        
 
   def pressed_itemSlot(self, item):
@@ -354,6 +356,7 @@
 
       descr("item.text(0) is: ",str(item.text(0)))
       descr("file_name is", file_name)
+      self.m_session_mdl.m_session_mdtr.emit(PYSIGNAL("statusBarMessageSig"), ("Large dishes may take a few minutes to process. Be patient.",))
       self.m_session_mdl.m_session_mdtr.emit(PYSIGNAL("doDefrostDishSig"),
         (item.text(0), thawed_item,))
       descr("BDB -- item.text(0) = " + str(item.text(0)))
@@ -371,6 +374,7 @@
         short_name = short_name[:-5]
         in_file_name = os.path.join(in_file_name, "petri_dish")
       thawed_item = pyReadFreezer(in_file_name)
+      self.m_session_mdl.m_session_mdtr.emit(PYSIGNAL("statusBarMessageSig"), ("Large dishes may take a few minutes to process. Be patient.",))
       self.m_session_mdl.m_session_mdtr.emit(PYSIGNAL("doDefrostDishSig"),
         (short_name, thawed_item,))
       self.m_session_mdl.m_session_mdtr.emit(PYSIGNAL("freezerItemDoubleClicked"),
@@ -405,6 +409,7 @@
         file_name = str(item.text(0)) + ".empty"
       elif str(top_level.text(0)).startswith(" Populated Dish"):
         file_name = str(item.text(0)) + ".full"
+        print "pyFreezerCtrl : rebuilding filename %s" % (file_name)
       elif str(top_level.text(0)).startswith(" Organism"):
         file_name = str(item.text(0)) + ".organism"
       file_name = os.path.join(self.m_session_mdl.m_current_freezer, file_name)

Added: branches/developers/avida-edward/source/python/AvidaGui2/pyGridMaster.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyGridMaster.py	                        (rev 0)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyGridMaster.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -0,0 +1,114 @@
+# -*- coding: utf-8 -*-
+
+### pyGridMaster
+# Created 2009/02/03 by Wesley R. Elsberry
+#
+# Python module to handle client/server grid transformations in Avida-ED plugin.
+# The server must allow clients to contribute dishes.
+
+
+# class pySuperDish:
+    ### Class to handle multiple contributed dishes
+    
+class Grids:
+    def __init__(self,sx=5,sy=5,cx=60,cy=60):
+        # Set default values
+        self.serverGridXDefault = sx
+        self.serverGridYDefault = sy
+        self.clientGridXDefault = cx
+        self.clientGridYDefault = cy
+        self.serverGridExists = False
+        
+    # Grid transformations
+    # Generic methods of mapping client dishes of arbitrary size together
+    # into one server dish, and for mapping back to client dishes
+    #
+
+    def clientCell2ServerCell(self,inx,iny,igx,igy,snx,sny,sgc):
+        """
+        Client dish of size (snx,sny) with cell sgc maps to a server dish cell igc
+        given server dish grid size of (inx,iny) and sub-dish of (igx,igy)
+
+        Inputs:
+        inx = # of subdishes in a row
+        iny = # of subdishes in a column
+        igx = index in row of multidish placement for subdish (base 1)
+        igy = index in column of multidish placement for subdish (base 1)
+        snx = # of cells in row of subdish
+        sny = # of cells in column of subdish
+        sgc = cell index in subdish
+
+        Output:
+        igc = cell index in multidish (base 0)
+        """
+        irw = inx * snx      # server grid row width
+        iro = (igx-1) * snx  # server grid row offset
+        sgco = sgc / snx     # client grid column offset, integer division
+        sgro = sgc % snx     # client grid row offset
+        ico = sgc / irw      # server grid column offset, integer division
+        igc = (sgro + iro) + (sgco * irw) + (((igy - 1) * irw) * sny)
+        # Now get ix, iy from grid cell
+        ix = igc % irw
+        iy = igc / irw
+        return igc, ix, iy
+
+    def serverCell2ClientCell(self,inx,iny,snx,sny,igc):
+        """
+        Server grid cell igc in dish size (inx,iny) of sub-grids of size (snx,sny)
+        maps back to client grid (sgx,sgy) and client cell (sgc)
+
+        Inputs:
+        inx = # of subdishes in a row
+        iny = # of subdishes in a column
+        snx = # of cells in row of subdish
+        sny = # of cells in column of subdish
+        igc = cell index in multidish
+
+        Output:
+        list containing
+        sgc = cell index in subdish (base 0)
+        sgx = index in row of subdish (base 0)
+        sgy = index in column of subdish (base 0)
+        """
+        # print "serverCell2ClientCell(%s, %s, %s, %s, %s)" % (inx, iny, snx, sny, igc)
+        irw = inx * snx      # server grid row width
+        igx = ((igc % irw) / snx) + 1  # Needs integer division 
+        igy = (igc / (irw * sny)) + 1  # Needs integer division
+        sgx = ((igc % irw) % snx) + 1  # 
+        sgy = ((igc / irw) + 1) - ((igy - 1) * sny)
+        sgc = ((sgy - 1) * snx) + (sgx - 1)
+        # Which subdish did this come from?
+        sgpos = ((igy - 1) * inx) + igx - 1
+        ccelldata = [sgc, sgx, sgy, igx, igy, sgpos]
+        return ccelldata
+
+
+    def makeServerGrid(self, XSize, YSize):
+        if (self.serverGridExists):
+            # Error; redundant call to make the server grid, ignore
+            return -1
+        # Set up server grid
+        self.serverGridExists = True
+        
+
+"""
+Self-test
+"""
+if __name__ == "__main__":
+    sd_nrow = 4
+    sd_ncol = 4
+    sd_rowsize = 30
+    sd_colsize = 30
+    mygrid = Grids(sd_nrow,sd_ncol,sd_rowsize,sd_colsize)
+
+    mdcell = 1
+    sdinfo = mygrid.serverCell2ClientCell(sd_nrow,sd_ncol,sd_rowsize,sd_colsize,mdcell)
+    print "%s = mygrid.serverCell2ClientCell(%s,%s,%s,%s,%s)" % (sdinfo,sd_nrow,sd_ncol,sd_rowsize,sd_colsize,mdcell)
+
+    mdcell = 2 + sd_rowsize * 1
+    sdinfo = mygrid.serverCell2ClientCell(sd_nrow,sd_ncol,sd_rowsize,sd_colsize,mdcell)
+    print "%s = mygrid.serverCell2ClientCell(%s,%s,%s,%s,%s)" % (sdinfo,sd_nrow,sd_ncol,sd_rowsize,sd_colsize,mdcell)
+
+    mdcell = 3 + sd_rowsize * 2
+    sdinfo = mygrid.serverCell2ClientCell(sd_nrow,sd_ncol,sd_rowsize,sd_colsize,mdcell)
+    print "%s = mygrid.serverCell2ClientCell(%s,%s,%s,%s,%s)" % (sdinfo,sd_nrow,sd_ncol,sd_rowsize,sd_colsize,mdcell)

Added: branches/developers/avida-edward/source/python/AvidaGui2/pyMDMkEnv.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyMDMkEnv.py	                        (rev 0)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyMDMkEnv.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -0,0 +1,371 @@
+"""
+pyMkEnv.py
+
+Module to assist in writing out Avida environment files for Multi-Dish runs.
+"""
+
+import pyGridMaster
+
+class MkEnv():
+    """
+    MkEnv
+
+    Class with methods for environment-writing
+    """
+    
+    def __init__(self, mdx, mdy, sdx, sdy):
+        # Number of sub-dishes in a row
+        self.mdx = mdx
+        # Number of sub-dishes in a column
+        self.mdy = mdy
+        # Number of cells in a sub-dish row
+        self.sdx = sdx
+        # Number of cells in a sub-dish column
+        self.sdy = sdy
+
+        self.resources = ('not', 'nand', 'and', 'orn', 'oro', 'andn', 'nor', 'xor', 'equ', )
+        self.reactions = ('NOT', 'NAND', 'AND', 'ORN', 'ORO', 'ANDN', 'NOR', 'XOR', 'EQU', )
+
+        self.grid = pyGridMaster.Grids(self.mdx,self.mdy,self.sdx,self.sdy)
+
+        # Dictionary of tasks, resources, reactions, and rewards
+        self.rrr = {'not':('not','NOT',1, ),
+                    'nand':('nand','NAND',1, ),
+                    'and':('and','AND',2, ),
+                    'orn':('orn','ORN',2, ),
+                    'or':('or','OR',3, ),
+                    'andn':('andn','ANDN',3, ),
+                    'nor':('nor','NOR',4, ),
+                    'xor':('xor','XOR',4, ),
+                    'equ':('equ','EQU',5, )
+                    }
+
+        # Need to order the tasks
+        self.tasks = ('not', 'nand', 'and', 'orn', 'or', 'andn', 'nor', 'xor', 'equ', )
+
+    def mkTemplate(self,envTempName):
+        """
+        mkTemplate
+
+        Method to output an enviroment file suitable for processing to
+        a specific set of sub-dish settings. This sets up
+        spatially-defined resources that span the entire multi-dish,
+        but specifies each resource-subgrid pair separately.
+        
+        Implementation: Each sub-dish gets its own resource/reaction/task definition.
+        """
+
+        f_env = open(envTempName, 'w')
+ 
+        f_env.write("###############\n")
+        f_env.write("#\n")
+        f_env.write("# Multi-Dish environment template file\n")
+        f_env.write("#\n")
+        f_env.write("###############\n\n")
+
+        # List of resources
+
+        # All logic-9 resources get an entry per sub-dish, with coordinates
+        # defined to fit the boundary of the sub-dish.
+
+        print "Setting resources"
+        for mx in range(1,self.mdx+1):
+            for my in range(1,self.mdy+1):
+
+                #if (((3 == mx) and (3 == my)) or ((4 == mx) and (4==my))):
+                #if ((3 == mx) and (3 != my)):
+                if (1):
+                #if (my < (self.mdy - 1)):    
+                    # Find upper left and lower right grid cells for the
+                    # subdish in the multi-dish
+                    
+                    mdcul,mdulx,mduly = self.grid.clientCell2ServerCell(self.mdx,self.mdy,mx,my,self.sdx,self.sdy,0)
+                    mdclr,mdlrx,mdlry = self.grid.clientCell2ServerCell(self.mdx,self.mdy,mx,my,self.sdx,self.sdy,self.sdx*self.sdy - 1)
+
+                    print "UL %s ULX %s ULY %s LR %s LRX %s LRY %s" % (mdcul, mdulx, mduly, mdclr, mdlrx, mdlry) 
+                    #mdlry /= 2
+                    #print "UL %s ULX %s ULY %s LR %s LRX %s LRY %s" % (mdcul, mdulx, mduly, mdclr, mdlrx, mdlry) 
+
+                    inflow = self.sdx * self.sdy * 1.0
+                    outflow = 0.1
+
+                    for ii in self.tasks:
+                        tstr = "RESOURCE %s%s%s%s" + \
+                            ":initial=0.00001" + \
+                            ":geometry=torus" + \
+                            ":inflow=%s" + \
+                            ":outflow=%s" + \
+                            ":inflowx1=%s" + \
+                            ":inflowx2=%s" + \
+                            ":inflowy1=%s" + \
+                            ":inflowy2=%s" + \
+                            ":outflowx1=%s" + \
+                            ":outflowx2=%s" + \
+                            ":outflowy1=%s" + \
+                            ":outflowy2=%s" + \
+                            ":xgravity=0" + \
+                            ":ygravity=0" + \
+                            ":xdiffuse=0" + \
+                            ":ydiffuse=0\n"
+                        f_env.write(tstr % ("res_",self.rrr[ii][0],mx,my,
+                                            inflow,outflow,
+                                            mdulx,mdlrx,
+                                            mduly,mdlry,
+                                            mdulx,mdlrx,
+                                            mduly,mdlry))
+
+                f_env.write("\n")
+
+        f_env.write("\n\n")
+        
+        for mx in range(1,self.mdx+1):
+            for my in range(1,self.mdy+1):
+
+                # if ((3 == mx) and (3 == my)):
+                # if (((3 == mx) and (3 == my)) or ((4 == mx) and (4==my))):
+                #if ((3 == mx) and (3 != my)):
+                #if (1):
+                if (my < (self.mdy - 1)):    
+                    for ii in self.tasks:
+                        tstr = "REACTION  %s%s%s%s  %s   process" + \
+                            ":resource=%s%s%s%s" + \
+                            ":value=1.0" + \
+                            ":max=1.0" + \
+                            ":min=0.001" + \
+                            ":frac=0.5:" + \
+                            "product=%s%s%s%s" + \
+                            ":conversion=1.0:" + \
+                            "type=pow" + \
+                            " requisite" + \
+                            ":max_count=1\n" 
+                        f_env.write(tstr % ("REA_",self.rrr[ii][1],mx,my,
+                                            self.rrr[ii][0],
+                                            "res_",self.rrr[ii][0],mx,my,
+                                            "res_",self.rrr[ii][0],mx,my))
+
+                f_env.write("\n")
+
+        f_env.write("\n\n")
+        f_env.close()
+
+    def mkEnvFile(self,envName,sgv):
+        """
+        mkTemplate
+
+        Method to output an enviroment file specifying a set of
+        sub-dish settings. This sets up spatially-defined resources
+        that span the entire multi-dish, but specifies each
+        resource-subgrid pair separately.
+        
+        Inputs:
+        envName : filename of environment configuration file
+        sgv : dictionary with the task information
+        """
+
+        f_env = open(envTempName, 'w')
+ 
+        f_env.write("###############\n")
+        f_env.write("#\n")
+        f_env.write("# Multi-Dish environment template file\n")
+        f_env.write("#\n")
+        f_env.write("###############\n\n")
+
+        # List of resources
+        # All logic-9 resources get an entry.
+        endidx = self.mdx * self.sdx - 1
+        for ii in self.rrr:
+            tstr = "RESOURCE %s" + \
+                ":initial=0.1" + \
+                ":geometry=torus" + \
+                ":inflow=1.0" + \
+                ":outflow=0.0" + \
+                ":inflowx1=0" + \
+                ":inflowx2=%s" + \
+                ":inflowy1=0" + \
+                ":inflowy2=%s" + \
+                ":outflowx1=0" + \
+                ":outflowx2=%s" + \
+                ":outflowy1=0" + \
+                ":outflowy2=%s" + \
+                ":xgravity=0" + \
+                ":ygravity=0" + \
+                ":xdiffuse=0" + \
+                ":ydiffuse=0\n"
+            f_env.write(tstr % (self.rrr[ii][0],endidx,endidx,endidx,endidx))
+
+        f_env.write("\n\n")
+        
+        for ii in self.rrr:
+            tstr = "REACTION  %s  %s   process" + \
+                ":value=1.0" + \
+                ":max=1.0" + \
+                ":min=0.001" + \
+                ":frac=0.5:" + \
+                "product=%s" + \
+                ":conversion=1.0:" + \
+                "type=pow" + \
+                " requisite" + \
+                ":max_count=1\n" 
+            f_env.write(tstr % (self.rrr[ii][1],self.rrr[ii][0],self.rrr[ii][0]))
+
+        f_env.write("\n\n")
+
+        # Cell section. Write out complete set of resources and ranges.
+        for mx in range(1,self.mdx+1):
+            for my in range(1,self.mdy+1):
+                sdkey = ','.join(mx,my)
+                print sdkey
+        
+                f_env.write("\n# Sub-dish [%s,%s]\n" % (mx,my))
+                for ii in self.sgv:
+                    f_env.write("CELL %s:" % (ii))
+        
+                    sdrange = []
+                    for jj in range(self.sdy):
+                        mdc = self.grid.clientCell2ServerCell(self.mdx,self.mdy,mx,my,self.sdx,self.sdy,jj * self.sdx)
+                        subrange = "%s..%s" % (mdc, mdc + self.sdx - 1)
+                        sdrange.append(subrange)
+                    thisrange = ",".join(sdrange)
+                    f_env.write(thisrange)
+                    
+                    f_env.write(":initial=1.0:inflow=0.0:outflow=0.0\n")
+                        
+        f_env.close()
+
+    def mkMDTemplate(self,envTempName,mdset):
+        """
+        mkMDTemplate
+
+        Method to output an enviroment file suitable for processing to
+        a specific set of sub-dish settings. This sets up
+        spatially-defined resources that span the entire multi-dish,
+        but specifies each resource-subgrid pair separately.
+        
+        Implementation: Each sub-dish gets its own resource/reaction/task definition.
+        """
+        print "pyMDMkEnv.mkMDTemplate()"
+
+        # Base-0 or Base-1 for position encoding in keys?
+        base1 = False       # Use Base-0, not Base-1
+        # base1 = True      # Use Base-1, not Base-0
+
+        print mdset
+
+        f_env = open(envTempName, 'w')
+ 
+        f_env.write("###############\n")
+        f_env.write("#\n")
+        f_env.write("# Multi-Dish environment file\n")
+        f_env.write("#\n")
+        f_env.write("###############\n\n")
+
+        # List of resources
+
+        # All logic-9 resources get an entry per sub-dish, with coordinates
+        # defined to fit the boundary of the sub-dish.
+
+        print "Setting resources"
+        for mx in range(1,self.mdx+1):
+            for my in range(1,self.mdy+1):
+
+                #if (((3 == mx) and (3 == my)) or ((4 == mx) and (4==my))):
+                #if ((3 == mx) and (3 != my)):
+                if (1):
+                #if (my < (self.mdy - 1)):    
+                    # Find upper left and lower right grid cells for the
+                    # subdish in the multi-dish
+                    
+                    mdcul,mdulx,mduly = self.grid.clientCell2ServerCell(self.mdx,self.mdy,mx,my,self.sdx,self.sdy,0)
+                    mdclr,mdlrx,mdlry = self.grid.clientCell2ServerCell(self.mdx,self.mdy,mx,my,self.sdx,self.sdy,self.sdx*self.sdy - 1)
+
+                    print "UL %s ULX %s ULY %s LR %s LRX %s LRY %s" % (mdcul, mdulx, mduly, mdclr, mdlrx, mdlry) 
+                    #mdlry /= 2
+                    #print "UL %s ULX %s ULY %s LR %s LRX %s LRY %s" % (mdcul, mdulx, mduly, mdclr, mdlrx, mdlry) 
+
+                    inflow = self.sdx * self.sdy * 1.0
+                    outflow = 0.1
+
+                    for ii in self.tasks:
+                        tstr = "RESOURCE %s%s%s%s" + \
+                            ":initial=0.00001" + \
+                            ":geometry=torus" + \
+                            ":inflow=%s" + \
+                            ":outflow=%s" + \
+                            ":inflowx1=%s" + \
+                            ":inflowx2=%s" + \
+                            ":inflowy1=%s" + \
+                            ":inflowy2=%s" + \
+                            ":outflowx1=%s" + \
+                            ":outflowx2=%s" + \
+                            ":outflowy1=%s" + \
+                            ":outflowy2=%s" + \
+                            ":xgravity=0" + \
+                            ":ygravity=0" + \
+                            ":xdiffuse=0" + \
+                            ":ydiffuse=0\n"
+                        # Set inflow and outflow differently based on whether the resource is "YES" in MD dict
+                        if (base1):
+                            # Base-1 for x,y position
+                            currkey = "RES_%s%s_%s" % (mx,my,str(ii).upper())
+                        else:
+                            # Base-0 for x,y position
+                            currkey = "RES_%s%s_%s" % (mx-1,my-1,str(ii).upper())
+                        # Check for reward of this task in this subdish
+                        # Two steps: does the key exist? Then, what is the value?
+                        if (mdset.has_key(currkey) and ("YES" == mdset[currkey])):
+                            print "currkey YES : %s" % (currkey)
+                            inflow = self.sdx * self.sdy * 1.0
+                            outflow = 0.1
+                        else:
+                            print "currkey NO : %s" % (currkey)
+                            inflow = self.sdx * self.sdy * 0.000001
+                            outflow = 0.9
+
+                        f_env.write(tstr % ("res_",self.rrr[ii][0],mx,my,
+                                            inflow,outflow,
+                                            mdulx,mdlrx,
+                                            mduly,mdlry,
+                                            mdulx,mdlrx,
+                                            mduly,mdlry))
+
+                        print tstr % ("res_",self.rrr[ii][0],mx,my,
+                                      inflow,outflow,
+                                      mdulx,mdlrx,
+                                      mduly,mdlry,
+                                      mdulx,mdlrx,
+                                      mduly,mdlry)
+
+
+                f_env.write("\n")
+
+        f_env.write("\n\n")
+        
+        for mx in range(1,self.mdx+1):
+            for my in range(1,self.mdy+1):
+
+                if (1):
+                    for ii in self.tasks:
+                        tstr = "REACTION  %s%s%s%s  %s   process" + \
+                            ":resource=%s%s%s%s" + \
+                            ":value=1.0" + \
+                            ":max=1.0" + \
+                            ":min=0.001" + \
+                            ":frac=0.5:" + \
+                            "product=%s%s%s%s" + \
+                            ":conversion=1.0:" + \
+                            "type=pow" + \
+                            " requisite" + \
+                            ":max_count=1\n" 
+                        f_env.write(tstr % ("REA_",self.rrr[ii][1],mx,my,
+                                            self.rrr[ii][0],
+                                            "res_",self.rrr[ii][0],mx,my,
+                                            "res_",self.rrr[ii][0],mx,my))
+                        print tstr % ("REA_",self.rrr[ii][1],mx,my,
+                                      self.rrr[ii][0],
+                                      "res_",self.rrr[ii][0],mx,my,
+                                      "res_",self.rrr[ii][0],mx,my)
+
+                f_env.write("\n")
+
+        f_env.write("\n\n")
+        f_env.close()

Added: branches/developers/avida-edward/source/python/AvidaGui2/pyMDSetupFormView.ui
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyMDSetupFormView.ui	                        (rev 0)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyMDSetupFormView.ui	2009-08-05 16:45:50 UTC (rev 3357)
@@ -0,0 +1,493 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>md_setup_Form</class>
+<widget class="QWidget">
+    <property name="name">
+        <cstring>md_setup_Form</cstring>
+    </property>
+    <property name="geometry">
+        <rect>
+            <x>0</x>
+            <y>0</y>
+            <width>801</width>
+            <height>648</height>
+        </rect>
+    </property>
+    <property name="caption">
+        <string>Multi-Dish</string>
+    </property>
+    <widget class="QTabWidget">
+        <property name="name">
+            <cstring>tabWidget2</cstring>
+        </property>
+        <property name="geometry">
+            <rect>
+                <x>10</x>
+                <y>10</y>
+                <width>790</width>
+                <height>630</height>
+            </rect>
+        </property>
+        <widget class="QWidget">
+            <property name="name">
+                <cstring>tab</cstring>
+            </property>
+            <attribute name="title">
+                <string>Multi-Dish Setup</string>
+            </attribute>
+            <widget class="QGroupBox">
+                <property name="name">
+                    <cstring>setMDParams_groupBox</cstring>
+                </property>
+                <property name="geometry">
+                    <rect>
+                        <x>0</x>
+                        <y>0</y>
+                        <width>500</width>
+                        <height>170</height>
+                    </rect>
+                </property>
+                <property name="title">
+                    <string>Step 1: Set Multi-Dish Parameters</string>
+                </property>
+                <widget class="QPushButton">
+                    <property name="name">
+                        <cstring>md_set_values_pushButton</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>11</x>
+                            <y>129</y>
+                            <width>117</width>
+                            <height>32</height>
+                        </rect>
+                    </property>
+                    <property name="text">
+                        <string>Set Values</string>
+                    </property>
+                </widget>
+                <widget class="QLabel">
+                    <property name="name">
+                        <cstring>md_values_textLabel</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>134</x>
+                            <y>129</y>
+                            <width>345</width>
+                            <height>32</height>
+                        </rect>
+                    </property>
+                    <property name="text">
+                        <string>MD: </string>
+                    </property>
+                </widget>
+                <widget class="QLabel">
+                    <property name="name">
+                        <cstring>md_name_textLabel</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>12</x>
+                            <y>100</y>
+                            <width>107</width>
+                            <height>22</height>
+                        </rect>
+                    </property>
+                    <property name="text">
+                        <string>Multi-Dish name</string>
+                    </property>
+                </widget>
+                <widget class="QLineEdit">
+                    <property name="name">
+                        <cstring>md_name_lineEdit</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>125</x>
+                            <y>100</y>
+                            <width>353</width>
+                            <height>22</height>
+                        </rect>
+                    </property>
+                    <property name="text">
+                        <string>md-</string>
+                    </property>
+                </widget>
+                <widget class="QLabel">
+                    <property name="name">
+                        <cstring>sdy_textLabel</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>12</x>
+                            <y>66</y>
+                            <width>116</width>
+                            <height>26</height>
+                        </rect>
+                    </property>
+                    <property name="text">
+                        <string>SubDishes /  col</string>
+                    </property>
+                </widget>
+                <widget class="QSpinBox">
+                    <property name="name">
+                        <cstring>sdy_spinBox</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>134</x>
+                            <y>66</y>
+                            <width>116</width>
+                            <height>26</height>
+                        </rect>
+                    </property>
+                    <property name="minValue">
+                        <number>1</number>
+                    </property>
+                    <property name="value">
+                        <number>4</number>
+                    </property>
+                </widget>
+                <widget class="QLabel">
+                    <property name="name">
+                        <cstring>sdx_textLabel</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>12</x>
+                            <y>32</y>
+                            <width>116</width>
+                            <height>26</height>
+                        </rect>
+                    </property>
+                    <property name="text">
+                        <string>SubDishes / row</string>
+                    </property>
+                </widget>
+                <widget class="QSpinBox">
+                    <property name="name">
+                        <cstring>sdx_spinBox</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>134</x>
+                            <y>32</y>
+                            <width>116</width>
+                            <height>26</height>
+                        </rect>
+                    </property>
+                    <property name="minValue">
+                        <number>1</number>
+                    </property>
+                    <property name="value">
+                        <number>4</number>
+                    </property>
+                </widget>
+                <widget class="QLabel">
+                    <property name="name">
+                        <cstring>sdnx_textLabel</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>258</x>
+                            <y>32</y>
+                            <width>155</width>
+                            <height>26</height>
+                        </rect>
+                    </property>
+                    <property name="text">
+                        <string>Grid Cells / SubDish row</string>
+                    </property>
+                </widget>
+                <widget class="QSpinBox">
+                    <property name="name">
+                        <cstring>sdnx_spinBox</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>419</x>
+                            <y>32</y>
+                            <width>59</width>
+                            <height>26</height>
+                        </rect>
+                    </property>
+                    <property name="minValue">
+                        <number>1</number>
+                    </property>
+                    <property name="value">
+                        <number>30</number>
+                    </property>
+                </widget>
+                <widget class="QLabel">
+                    <property name="name">
+                        <cstring>sdny_textLabel</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>258</x>
+                            <y>66</y>
+                            <width>155</width>
+                            <height>26</height>
+                        </rect>
+                    </property>
+                    <property name="text">
+                        <string>Grid Cells / SubDish  col</string>
+                    </property>
+                </widget>
+                <widget class="QSpinBox">
+                    <property name="name">
+                        <cstring>sdny_spinBox</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>419</x>
+                            <y>66</y>
+                            <width>59</width>
+                            <height>26</height>
+                        </rect>
+                    </property>
+                    <property name="minValue">
+                        <number>1</number>
+                    </property>
+                    <property name="value">
+                        <number>30</number>
+                    </property>
+                </widget>
+            </widget>
+            <widget class="QGroupBox">
+                <property name="name">
+                    <cstring>generateMulti_Dish_groupBox</cstring>
+                </property>
+                <property name="geometry">
+                    <rect>
+                        <x>508</x>
+                        <y>442</y>
+                        <width>250</width>
+                        <height>130</height>
+                    </rect>
+                </property>
+                <property name="title">
+                    <string>Step 3. Generate Multi-Dish</string>
+                </property>
+                <widget class="QPushButton">
+                    <property name="name">
+                        <cstring>md_generate_pushButton</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>22</x>
+                            <y>58</y>
+                            <width>200</width>
+                            <height>32</height>
+                        </rect>
+                    </property>
+                    <property name="text">
+                        <string>Generate Multi-Dish</string>
+                    </property>
+                </widget>
+            </widget>
+            <widget class="QGroupBox">
+                <property name="name">
+                    <cstring>setSubDishLayout_groupBox</cstring>
+                </property>
+                <property name="geometry">
+                    <rect>
+                        <x>0</x>
+                        <y>170</y>
+                        <width>500</width>
+                        <height>420</height>
+                    </rect>
+                </property>
+                <property name="title">
+                    <string>Step 2. Layout SubDishes</string>
+                </property>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>layout20</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>12</x>
+                            <y>28</y>
+                            <width>460</width>
+                            <height>50</height>
+                        </rect>
+                    </property>
+                    <hbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>sd_pick_textLabel</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Choose SubDish</string>
+                            </property>
+                        </widget>
+                        <widget class="QComboBox">
+                            <property name="name">
+                                <cstring>sd_pick_comboBox</cstring>
+                            </property>
+                        </widget>
+                        <widget class="QPushButton">
+                            <property name="name">
+                                <cstring>sd_list_refresh_pushButton</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Refresh</string>
+                            </property>
+                        </widget>
+                    </hbox>
+                </widget>
+                <widget class="QTextEdit">
+                    <property name="name">
+                        <cstring>md_layout_textEdit</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>12</x>
+                            <y>146</y>
+                            <width>480</width>
+                            <height>230</height>
+                        </rect>
+                    </property>
+                    <property name="font">
+                        <font>
+                            <family>Courier New</family>
+                            <bold>1</bold>
+                        </font>
+                    </property>
+                </widget>
+                <widget class="QLabel">
+                    <property name="name">
+                        <cstring>sd_pos_in_md_textLabel</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>14</x>
+                            <y>90</y>
+                            <width>247</width>
+                            <height>46</height>
+                        </rect>
+                    </property>
+                    <property name="text">
+                        <string>Choose SubDish Position in Multi-Dish</string>
+                    </property>
+                </widget>
+                <widget class="QSpinBox">
+                    <property name="name">
+                        <cstring>sd_pos_in_md_spinBox</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>277</x>
+                            <y>100</y>
+                            <width>73</width>
+                            <height>26</height>
+                        </rect>
+                    </property>
+                    <property name="minValue">
+                        <number>1</number>
+                    </property>
+                </widget>
+                <widget class="QPushButton">
+                    <property name="name">
+                        <cstring>sd_add_pushButton</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>12</x>
+                            <y>378</y>
+                            <width>480</width>
+                            <height>32</height>
+                        </rect>
+                    </property>
+                    <property name="text">
+                        <string>Add SubDish To Multi-Dish Layout</string>
+                    </property>
+                </widget>
+            </widget>
+        </widget>
+        <widget class="QWidget">
+            <property name="name">
+                <cstring>tab</cstring>
+            </property>
+            <attribute name="title">
+                <string>Multi-Dish Statistics</string>
+            </attribute>
+            <widget class="QGroupBox">
+                <property name="name">
+                    <cstring>MDRunStatistics_groupBox</cstring>
+                </property>
+                <property name="geometry">
+                    <rect>
+                        <x>0</x>
+                        <y>0</y>
+                        <width>760</width>
+                        <height>280</height>
+                    </rect>
+                </property>
+                <property name="title">
+                    <string>Run Statistics</string>
+                </property>
+                <widget class="QTextEdit">
+                    <property name="name">
+                        <cstring>MDRunStatistics_textEdit</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>0</x>
+                            <y>20</y>
+                            <width>760</width>
+                            <height>260</height>
+                        </rect>
+                    </property>
+                    <property name="font">
+                        <font>
+                            <family>Courier New</family>
+                            <pointsize>11</pointsize>
+                        </font>
+                    </property>
+                </widget>
+            </widget>
+            <widget class="QGroupBox">
+                <property name="name">
+                    <cstring>MDDiversity_groupBox</cstring>
+                </property>
+                <property name="geometry">
+                    <rect>
+                        <x>0</x>
+                        <y>280</y>
+                        <width>760</width>
+                        <height>310</height>
+                    </rect>
+                </property>
+                <property name="title">
+                    <string>Multi-Dish Diversity</string>
+                </property>
+                <widget class="QTextEdit">
+                    <property name="name">
+                        <cstring>MDDiversity_textEdit</cstring>
+                    </property>
+                    <property name="geometry">
+                        <rect>
+                            <x>-2</x>
+                            <y>22</y>
+                            <width>760</width>
+                            <height>290</height>
+                        </rect>
+                    </property>
+                    <property name="font">
+                        <font>
+                            <family>Courier New</family>
+                            <pointsize>11</pointsize>
+                        </font>
+                    </property>
+                </widget>
+            </widget>
+        </widget>
+    </widget>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>

Modified: branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_GraphCtrl.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_GraphCtrl.py	2009-08-04 03:26:21 UTC (rev 3356)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_GraphCtrl.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -77,6 +77,13 @@
       self.m_graph_ctrl.setAxisAutoScale(QwtPlot.xBottom)
       self.m_graph_ctrl.setAxisAutoScale(QwtPlot.yLeft)
 
+
+      # @WRE: attach a grid
+      self.m_graph_ctrl.m_grid = Qwt.QwtPlotGrid()
+      self.m_graph_ctrl.m_grid.attach(self.m_graph_ctrl)
+      self.m_graph_ctrl.m_grid.setPen(QPen(Qt.black, 0, Qt.DotLine))
+
+
     self.m_graph_ctrl.replot()
       
   def setAvidaSlot(self, avida):

Added: branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_MDView.ui
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_MDView.ui	                        (rev 0)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_MDView.ui	2009-08-05 16:45:50 UTC (rev 3357)
@@ -0,0 +1,590 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>pyOnePop_MDView</class>
+<comment>
+Python:from pyOrgSquareCtrl import pyOrgSquareCtrl
+</comment>
+<widget class="QWidget">
+    <property name="name">
+        <cstring>pyOnePop_MDView</cstring>
+    </property>
+    <property name="geometry">
+        <rect>
+            <x>19</x>
+            <y>0</y>
+            <width>334</width>
+            <height>400</height>
+        </rect>
+    </property>
+    <property name="sizePolicy">
+        <sizepolicy>
+            <hsizetype>0</hsizetype>
+            <vsizetype>5</vsizetype>
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+        </sizepolicy>
+    </property>
+    <property name="minimumSize">
+        <size>
+            <width>0</width>
+            <height>0</height>
+        </size>
+    </property>
+    <property name="maximumSize">
+        <size>
+            <width>32767</width>
+            <height>400</height>
+        </size>
+    </property>
+    <property name="caption">
+        <string>pyOnePop_MDView</string>
+    </property>
+    <hbox>
+        <property name="name">
+            <cstring>unnamed</cstring>
+        </property>
+        <widget class="QGroupBox">
+            <property name="name">
+                <cstring>groupBox4</cstring>
+            </property>
+            <property name="sizePolicy">
+                <sizepolicy>
+                    <hsizetype>0</hsizetype>
+                    <vsizetype>5</vsizetype>
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                </sizepolicy>
+            </property>
+            <property name="maximumSize">
+                <size>
+                    <width>32767</width>
+                    <height>30000</height>
+                </size>
+            </property>
+            <property name="font">
+                <font>
+                    <family>Arial</family>
+                    <pointsize>10</pointsize>
+                    <bold>1</bold>
+                </font>
+            </property>
+            <property name="title">
+                <string>Population Diversity</string>
+            </property>
+            <property name="toolTip" stdset="0">
+                <string>Information on single highlighted organism from population</string>
+            </property>
+            <vbox>
+                <property name="name">
+                    <cstring>unnamed</cstring>
+                </property>
+            </vbox>
+        </widget>
+        <widget class="QGroupBox">
+            <property name="name">
+                <cstring>groupBox5</cstring>
+            </property>
+            <property name="sizePolicy">
+                <sizepolicy>
+                    <hsizetype>0</hsizetype>
+                    <vsizetype>5</vsizetype>
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                </sizepolicy>
+            </property>
+            <property name="maximumSize">
+                <size>
+                    <width>32767</width>
+                    <height>32767</height>
+                </size>
+            </property>
+            <property name="font">
+                <font>
+                    <family>Arial</family>
+                    <pointsize>10</pointsize>
+                    <bold>1</bold>
+                </font>
+            </property>
+            <property name="frameShape">
+                <enum>GroupBoxPanel</enum>
+            </property>
+            <property name="title">
+                <string>Population Statistics</string>
+            </property>
+            <property name="toolTip" stdset="0">
+                <string>Information about the entire population of organisms in the petri dish</string>
+            </property>
+            <vbox>
+                <property name="name">
+                    <cstring>unnamed</cstring>
+                </property>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>layout56</cstring>
+                    </property>
+                    <hbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>textLabel14_3_3_2_2</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>5</hsizetype>
+                                    <vsizetype>5</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="minimumSize">
+                                <size>
+                                    <width>0</width>
+                                    <height>20</height>
+                                </size>
+                            </property>
+                            <property name="maximumSize">
+                                <size>
+                                    <width>32767</width>
+                                    <height>20</height>
+                                </size>
+                            </property>
+                            <property name="font">
+                                <font>
+                                    <bold>0</bold>
+                                </font>
+                            </property>
+                            <property name="text">
+                                <string>Population Size:</string>
+                            </property>
+                        </widget>
+                        <spacer>
+                            <property name="name">
+                                <cstring>spacer6_2</cstring>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                            <property name="sizeType">
+                                <enum>Expanding</enum>
+                            </property>
+                            <property name="sizeHint">
+                                <size>
+                                    <width>20</width>
+                                    <height>10</height>
+                                </size>
+                            </property>
+                        </spacer>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>m_num_orgs</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>5</hsizetype>
+                                    <vsizetype>5</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="font">
+                                <font>
+                                    <bold>0</bold>
+                                </font>
+                            </property>
+                            <property name="text">
+                                <string>-</string>
+                            </property>
+                        </widget>
+                    </hbox>
+                </widget>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>layout64</cstring>
+                    </property>
+                    <hbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>textLabel14_3_3</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>5</hsizetype>
+                                    <vsizetype>5</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="maximumSize">
+                                <size>
+                                    <width>32767</width>
+                                    <height>40</height>
+                                </size>
+                            </property>
+                            <property name="font">
+                                <font>
+                                    <bold>0</bold>
+                                </font>
+                            </property>
+                            <property name="text">
+                                <string>Avg. Fitness:</string>
+                            </property>
+                        </widget>
+                        <spacer>
+                            <property name="name">
+                                <cstring>spacer6_2_2</cstring>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                            <property name="sizeType">
+                                <enum>Expanding</enum>
+                            </property>
+                            <property name="sizeHint">
+                                <size>
+                                    <width>85</width>
+                                    <height>16</height>
+                                </size>
+                            </property>
+                        </spacer>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>m_avg_fitness</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>7</hsizetype>
+                                    <vsizetype>5</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="maximumSize">
+                                <size>
+                                    <width>3000</width>
+                                    <height>3000</height>
+                                </size>
+                            </property>
+                            <property name="font">
+                                <font>
+                                    <bold>0</bold>
+                                </font>
+                            </property>
+                            <property name="text">
+                                <string>-</string>
+                            </property>
+                            <property name="alignment">
+                                <set>AlignVCenter|AlignRight</set>
+                            </property>
+                        </widget>
+                    </hbox>
+                </widget>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>layout59</cstring>
+                    </property>
+                    <hbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>textLabel14_3_3_2_2_2_3</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>5</hsizetype>
+                                    <vsizetype>5</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="maximumSize">
+                                <size>
+                                    <width>32767</width>
+                                    <height>40</height>
+                                </size>
+                            </property>
+                            <property name="font">
+                                <font>
+                                    <bold>0</bold>
+                                </font>
+                            </property>
+                            <property name="text">
+                                <string>Avg. Metabolic Rate:</string>
+                            </property>
+                        </widget>
+                        <spacer>
+                            <property name="name">
+                                <cstring>spacer6_2_2_2</cstring>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                            <property name="sizeType">
+                                <enum>Expanding</enum>
+                            </property>
+                            <property name="sizeHint">
+                                <size>
+                                    <width>20</width>
+                                    <height>10</height>
+                                </size>
+                            </property>
+                        </spacer>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>m_avg_merit</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>5</hsizetype>
+                                    <vsizetype>5</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="font">
+                                <font>
+                                    <bold>0</bold>
+                                </font>
+                            </property>
+                            <property name="text">
+                                <string>-</string>
+                            </property>
+                        </widget>
+                    </hbox>
+                </widget>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>layout60</cstring>
+                    </property>
+                    <hbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>textLabel14_3_3_2_2_2</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>5</hsizetype>
+                                    <vsizetype>5</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="maximumSize">
+                                <size>
+                                    <width>32767</width>
+                                    <height>40</height>
+                                </size>
+                            </property>
+                            <property name="font">
+                                <font>
+                                    <bold>0</bold>
+                                </font>
+                            </property>
+                            <property name="text">
+                                <string>Avg. Gestation:</string>
+                            </property>
+                        </widget>
+                        <spacer>
+                            <property name="name">
+                                <cstring>spacer6_2_2_2_2</cstring>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                            <property name="sizeType">
+                                <enum>Expanding</enum>
+                            </property>
+                            <property name="sizeHint">
+                                <size>
+                                    <width>20</width>
+                                    <height>10</height>
+                                </size>
+                            </property>
+                        </spacer>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>m_avg_gest</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>5</hsizetype>
+                                    <vsizetype>5</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="font">
+                                <font>
+                                    <bold>0</bold>
+                                </font>
+                            </property>
+                            <property name="text">
+                                <string>-</string>
+                            </property>
+                        </widget>
+                    </hbox>
+                </widget>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>layout62</cstring>
+                    </property>
+                    <hbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>textLabel14_3_3_2_2_2_4_2</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>5</hsizetype>
+                                    <vsizetype>5</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="maximumSize">
+                                <size>
+                                    <width>32767</width>
+                                    <height>40</height>
+                                </size>
+                            </property>
+                            <property name="font">
+                                <font>
+                                    <bold>0</bold>
+                                </font>
+                            </property>
+                            <property name="text">
+                                <string>Avg. Age (updates):</string>
+                            </property>
+                        </widget>
+                        <spacer>
+                            <property name="name">
+                                <cstring>spacer6_2_2_2_3_2</cstring>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                            <property name="sizeType">
+                                <enum>Expanding</enum>
+                            </property>
+                            <property name="sizeHint">
+                                <size>
+                                    <width>20</width>
+                                    <height>10</height>
+                                </size>
+                            </property>
+                        </spacer>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>m_avg_age</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>5</hsizetype>
+                                    <vsizetype>5</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="font">
+                                <font>
+                                    <bold>0</bold>
+                                </font>
+                            </property>
+                            <property name="text">
+                                <string>-</string>
+                            </property>
+                        </widget>
+                    </hbox>
+                </widget>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>layout61</cstring>
+                    </property>
+                    <hbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>textLabel14_3_3_2_2_2_4</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>5</hsizetype>
+                                    <vsizetype>5</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="maximumSize">
+                                <size>
+                                    <width>32767</width>
+                                    <height>40</height>
+                                </size>
+                            </property>
+                            <property name="font">
+                                <font>
+                                    <bold>0</bold>
+                                </font>
+                            </property>
+                            <property name="text">
+                                <string></string>
+                            </property>
+                        </widget>
+                        <spacer>
+                            <property name="name">
+                                <cstring>spacer6_2_2_2_3</cstring>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                            <property name="sizeType">
+                                <enum>Expanding</enum>
+                            </property>
+                            <property name="sizeHint">
+                                <size>
+                                    <width>20</width>
+                                    <height>10</height>
+                                </size>
+                            </property>
+                        </spacer>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>m_avg_genome_length</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>5</hsizetype>
+                                    <vsizetype>5</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="font">
+                                <font>
+                                    <bold>0</bold>
+                                </font>
+                            </property>
+                            <property name="text">
+                                <string></string>
+                            </property>
+                        </widget>
+                    </hbox>
+                </widget>
+            </vbox>
+        </widget>
+    </hbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>

Modified: branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_PetriDishCtrl.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_PetriDishCtrl.py	2009-08-04 03:26:21 UTC (rev 3356)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_PetriDishCtrl.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -116,7 +116,7 @@
       lineage_range = len(self.m_session_mdl.m_ancestors_dict)
       non_normalized_index = int(label) + 1
       normalized_index = float(non_normalized_index) / float(lineage_range)
-      print "self.m_petri_dish_ctrl is: ", self.m_petri_dish_ctrl
+      # print "self.m_petri_dish_ctrl is: ", self.m_petri_dish_ctrl
       a_sensible_color = self.m_petri_dish_ctrl.m_color_lookup_functor(normalized_index)
 
       #the following ugly code is brought to you by the fact that I can't delete objects
@@ -236,6 +236,10 @@
     if (e.source is self):
       return
 
+    self.m_session_mdl.m_session_mdtr.emit(PYSIGNAL("statusBarMessageSig"), ("Large dishes may take a few minutes to process. Be patient.",))
+    self.repaint()
+
+
     current_page = self.m_petri_dish_widget_stack.visibleWidget()
     current_page_int = self.m_petri_dish_widget_stack.id(current_page)
 
@@ -311,6 +315,9 @@
     
   def DefrostSlot(self, dish_name, petri_dict):
       descr()
+      self.m_session_mdl.m_session_mdtr.emit(PYSIGNAL("statusBarMessageSig"), ("Large dishes may take a few minutes to process. Be patient.",))
+      self.repaint()
+
       self.m_session_mdl.m_session_mdtr.emit(PYSIGNAL("raisePopViewSig"),())
 
 #    if self.isVisible():
@@ -345,6 +352,7 @@
           else:
             return
 
+      
       self.RenameDishSlot(dish_name)
       self.finishedPetriDish = False
       self.m_session_mdl.m_session_mdtr.emit(PYSIGNAL("FillDishSig"), 
@@ -358,6 +366,9 @@
       self.m_session_mdl.m_session_mdtr.emit(
        PYSIGNAL("restartPopulationSig"), (self.m_session_mdl, ))
 
+      self.m_session_mdl.m_session_mdtr.emit(
+        PYSIGNAL("refreshSubDishList"), ())
+      
 
   def finishedPetriDishSlot(self):
     descr()

Modified: branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_StatsCtrl.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_StatsCtrl.py	2009-08-04 03:26:21 UTC (rev 3356)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyOnePop_StatsCtrl.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -8,6 +8,8 @@
 from pyOnePop_StatsView import pyOnePop_StatsView
 from pyOrgSquareCtrl import pyOrgSquareCtrl
 import os
+from pyGridMaster import Grids 
+from AvidaCore import cConfig
 
 class pyOnePop_StatsCtrl(pyOnePop_StatsView):
 
@@ -80,7 +82,9 @@
   def avidaUpdatedSlot(self):
     # print "pyOnePop_StatsCtrl.avidaUpdatedSlot() called.\n"
     stats = self.m_avida.m_population.GetStats()
-             
+    
+    self.m_session_mdl.md_runstats["AVERAGES"] = {}
+         
     #STATISTICS WINDOW
     string_output_length = 7
 
@@ -95,6 +99,8 @@
       avg_fitness = "%.2g" %(stats.GetAveFitness())
       self.m_avg_fitness.setText(avg_fitness)
 
+    self.m_session_mdl.md_runstats["AVERAGES"]["AVG_FITNESS"] = avg_fitness
+
     # i got rid of dominant stats, jmc
 #    dom_fitness = str(stats.GetDomFitness())
 #    string_length = len(dom_fitness)
@@ -105,6 +111,7 @@
 
     num_orgs = stats.GetNumCreatures()
     self.m_num_orgs.setText(QString("%1").arg(num_orgs))
+    self.m_session_mdl.md_runstats["TOTAL_ORGS"] = num_orgs
 
     avg_gest = "%d" %(stats.GetAveGestation())
 #    string_length = len(avg_gest)
@@ -112,12 +119,16 @@
 #      avg_gest = avg_gest + '0'
 #      string_length = string_length+1
     self.m_avg_gest.setText(QString("%1").arg(avg_gest))
+    self.m_session_mdl.md_runstats["AVERAGES"]["AVG_GESTATION"] = avg_gest
+    
  
     avg_merit = "%d" %(stats.GetAveMerit())
     self.m_avg_merit.setText(QString("%1").arg(avg_merit))
+    self.m_session_mdl.md_runstats["AVERAGES"]["AVG_MERIT"] = avg_merit
 
     avg_age = "%d" %(stats.GetAveCreatureAge())
     self.m_avg_age.setText(QString("%1").arg(avg_age))
+    self.m_session_mdl.md_runstats["AVERAGES"]["AVG_AGE"] = avg_age
 
     avg_genome_length = "%d" %(stats.GetAveSize())
 #    self.m_avg_genome_length.setText(QString("%1").arg(avg_genome_length))
@@ -125,16 +136,25 @@
 
     #TASK OUTLOOK 
     # @WRE: get current update of run
-    age_now ="%d" %(stats.GetUpdate())
+    age_now ="%d" % (stats.GetUpdate())
+    self.m_session_mdl.md_runstats["UPDATE"] = age_now
 
+    self.m_session_mdl.md_runstats["TASKS"] = []
+    self.m_session_mdl.md_runstats["TASKSRAW"] = []
+
     num_not = str(stats.GetTaskLastCount(0))
     # @WRE: adding first completion
     if ((int(self.m_stat_task_first_complete[0]) <= 0) and (0 < int(num_not))):
       self.m_stat_task_first_complete[0] = age_now
     if ((int(self.m_stat_task_first_complete[0]) > 0) or (0 < int(num_not))):
       self.m_num_not.setText("%s (1st@ %d)" %(num_not, int(self.m_stat_task_first_complete[0])))
+      mdrsstr = "Not: %s (1st@ %d)" % (num_not, int(self.m_stat_task_first_complete[0]))
     else:
       self.m_num_not.setText(num_not)
+      mdrsstr = "Not: %s" % (num_not)
+
+    self.m_session_mdl.md_runstats["TASKS"].append(mdrsstr)
+    self.m_session_mdl.md_runstats["TASKSRAW"].append(num_not)
     
     num_nand = str(stats.GetTaskLastCount(1))
     # @WRE: adding first completion
@@ -142,75 +162,124 @@
       self.m_stat_task_first_complete[1] = age_now
     if ((int(self.m_stat_task_first_complete[1]) > 0) or (0 < int(num_nand))):
       self.m_num_nand.setText("%s (1st@ %d)" %(num_nand, int(self.m_stat_task_first_complete[1])))
+      mdrsstr = "Nand: %s (1st@ %d)" % (num_nand, int(self.m_stat_task_first_complete[1]))
     else:
       self.m_num_nand.setText(num_nand)
+      mdrsstr = "Nand: %s" % (num_nand)
 
+    self.m_session_mdl.md_runstats["TASKS"].append(mdrsstr)
+    self.m_session_mdl.md_runstats["TASKSRAW"].append(num_nand)
+
     num_and = str(stats.GetTaskLastCount(2))
     # @WRE: adding first completion
     if ((int(self.m_stat_task_first_complete[2]) <= 0) and (0 < int(num_and))):
       self.m_stat_task_first_complete[2] = age_now
     if ((int(self.m_stat_task_first_complete[2]) > 0) or (0 < int(num_and))):
       self.m_num_and.setText("%s (1st@ %d)" %(num_and, int(self.m_stat_task_first_complete[2])))
+      mdrsstr = "And: %s (1st@ %d)" % (num_and, int(self.m_stat_task_first_complete[2]))
     else:
       self.m_num_and.setText(num_and)
+      mdrsstr = "And: %s" % (num_and)
 
+    self.m_session_mdl.md_runstats["TASKS"].append(mdrsstr)
+    self.m_session_mdl.md_runstats["TASKSRAW"].append(num_and)
+
     num_ornot = str(stats.GetTaskLastCount(3))
     # @WRE: adding first completion
     if ((int(self.m_stat_task_first_complete[3]) <= 0) and (0 < int(num_ornot))):
       self.m_stat_task_first_complete[3] = age_now
     if ((int(self.m_stat_task_first_complete[3]) > 0) or (0 < int(num_ornot))):
       self.m_num_ornot.setText("%s (1st@ %d)" %(num_ornot, int(self.m_stat_task_first_complete[3])))
+      mdrsstr = "Orn: %s (1st@ %d)" % (num_ornot, int(self.m_stat_task_first_complete[3]))
     else:
       self.m_num_ornot.setText(num_ornot)
+      mdrsstr = "Orn: %s" % (num_ornot)
 
+    self.m_session_mdl.md_runstats["TASKS"].append(mdrsstr)
+    self.m_session_mdl.md_runstats["TASKSRAW"].append(num_ornot)
+
     num_or = str(stats.GetTaskLastCount(4))
     # @WRE: adding first completion
     if ((int(self.m_stat_task_first_complete[4]) <= 0) and (0 < int(num_or))):
       self.m_stat_task_first_complete[4] = age_now
     if ((int(self.m_stat_task_first_complete[4]) > 0) or (0 < int(num_or))):
       self.m_num_or.setText("%s (1st@ %d)" %(num_or, int(self.m_stat_task_first_complete[4])))
+      mdrsstr = "Or: %s (1st@ %d)" % (num_or, int(self.m_stat_task_first_complete[4]))
     else:
       self.m_num_or.setText(num_or)
+      mdrsstr = "Or: %s" % (num_or)
 
+    self.m_session_mdl.md_runstats["TASKS"].append(mdrsstr)
+    self.m_session_mdl.md_runstats["TASKSRAW"].append(num_or)
+
     num_andnot = str(stats.GetTaskLastCount(5))
     # @WRE: adding first completion
     if ((int(self.m_stat_task_first_complete[5]) <= 0) and (0 < int(num_andnot))):
       self.m_stat_task_first_complete[5] = age_now
     if ((int(self.m_stat_task_first_complete[5]) > 0) or (0 < int(num_andnot))):
       self.m_num_andnot.setText("%s (1st@ %d)" %(num_andnot, int(self.m_stat_task_first_complete[5])))
+      mdrsstr = "Andn: %s (1st@ %d)" % (num_andnot, int(self.m_stat_task_first_complete[5]))
     else:
       self.m_num_andnot.setText(num_andnot)
+      mdrsstr = "Andn: %s" % (num_andnot)
 
+    self.m_session_mdl.md_runstats["TASKS"].append(mdrsstr)
+    self.m_session_mdl.md_runstats["TASKSRAW"].append(num_andnot)
+
     num_nor = str(stats.GetTaskLastCount(6))
     # @WRE: adding first completion
     if ((int(self.m_stat_task_first_complete[6]) <= 0) and (0 < int(num_nor))):
       self.m_stat_task_first_complete[6] = age_now
     if ((int(self.m_stat_task_first_complete[6]) > 0) or (0 < int(num_nor))):
       self.m_num_nor.setText("%s (1st@ %d)" %(num_nor, int(self.m_stat_task_first_complete[6])))
+      mdrsstr = "Nor: %s (1st@ %d)" % (num_nor, int(self.m_stat_task_first_complete[6]))
     else:
       self.m_num_nor.setText(num_nor)
+      mdrsstr = "Nor: %s" % (num_nor)
 
+    self.m_session_mdl.md_runstats["TASKS"].append(mdrsstr)
+    self.m_session_mdl.md_runstats["TASKSRAW"].append(num_nor)
+
     num_xor = str(stats.GetTaskLastCount(7))
     # @WRE: adding first completion
     if ((int(self.m_stat_task_first_complete[7]) <= 0) and (0 < int(num_xor))):
       self.m_stat_task_first_complete[7] = age_now
     if ((int(self.m_stat_task_first_complete[7]) > 0) or (0 < int(num_xor))):
       self.m_num_xor.setText("%s (1st @ %d)" %(num_xor, int(self.m_stat_task_first_complete[7])))
+      mdrsstr = "Xor: %s (1st@ %d)" % (num_xor, int(self.m_stat_task_first_complete[7]))
     else:
       self.m_num_xor.setText(num_xor)
+      mdrsstr = "Xor: %s" % (num_xor)
 
+    self.m_session_mdl.md_runstats["TASKS"].append(mdrsstr)
+    self.m_session_mdl.md_runstats["TASKSRAW"].append(num_xor)
+
     num_equals = str(stats.GetTaskLastCount(8))
     # @WRE: adding first completion
     if ((int(self.m_stat_task_first_complete[8]) <= 0) and (0 < int(num_equals))):
       self.m_stat_task_first_complete[8] = age_now
     if ((int(self.m_stat_task_first_complete[8]) > 0) or (0 < int(num_equals))):
       self.m_num_equals.setText("%s (1st@ %d)" %(num_equals, int(self.m_stat_task_first_complete[8])))
+      mdrsstr = "Equ: %s (1st@ %d)" % (num_equals, int(self.m_stat_task_first_complete[8]))
     else:
       self.m_num_equals.setText(num_equals)
+      mdrsstr = "Equ: %s" % (num_equals)
+
+    self.m_session_mdl.md_runstats["TASKS"].append(mdrsstr)
+    self.m_session_mdl.md_runstats["TASKSRAW"].append(num_equals)
     
     if self.m_clicked_cell_number>= 0:
       self.updateOrgReportSlot(self.m_clicked_cell_item)
 
+    # @WRE: Whole population statistics for diversity and multi-dish
+    self.doWholePopStats()    
+
+    # Launch updates for Multi-Dish display
+    self.m_session_mdl.m_session_mdtr.emit(
+      PYSIGNAL("haveMDDiversityUpdate"), ())
+    self.m_session_mdl.m_session_mdtr.emit(
+      PYSIGNAL("haveMDRunStatsUpdate"), ())
+
   def notButtonClickedSlot(self):
     self.m_stat_task_button_states[0] = self.m_not_button.state()
     self.m_session_mdl.m_session_mdtr.emit(
@@ -350,6 +419,8 @@
     phenotype = organism.GetPhenotype()
     genotype = organism.GetGenotype()
 
+    # print "organism at %s : gen.= %s , phen.= %s" % (self.m_clicked_cell_number,genotype,phenotype)
+
     # print info about the org clicked on 
 
     self.m_session_mdl.m_current_cell_genome = str(organism.GetGenome().AsString())
@@ -560,3 +631,215 @@
     self.m_num_xor.setText("-")
     self.m_num_equals.setText("-")
     self.m_stat_task_first_complete = [0,0,0,0,0,0,0,0,0]
+
+  def getPhenotypeStr(self,grid_cell):
+    """
+    getPhenotypeStr
+
+    Method to return a string representing the phenotype.
+    Represention: 1 if the task was done, 0 if not. Nine places
+    for the logic-9 environment.
+    """
+
+    clicked_cell = self.m_avida.m_population.GetCell(int(grid_cell))
+
+    organism = clicked_cell.GetOrganism()
+    phenotype = organism.GetPhenotype()
+    # genotype = organism.GetGenotype()
+
+    phenstr = ""
+
+    # get the Tarray of tasks
+    m_clickedOrg_task_count = phenotype.GetLastTaskCount()
+
+    num_not_clickedOrg = m_clickedOrg_task_count[0]
+    if num_not_clickedOrg>0:
+      phenstr = "1"
+    else:
+      phenstr = "0"
+
+    num_nand_clickedOrg = m_clickedOrg_task_count[1]
+    if num_nand_clickedOrg>0:
+      phenstr = phenstr + "1"
+    else:
+      phenstr = phenstr + "0"
+
+    num_and_clickedOrg = m_clickedOrg_task_count[2]
+    if num_and_clickedOrg>0:
+      phenstr = phenstr + "1"
+    else:
+      phenstr = phenstr + "0"
+
+    num_ornot_clickedOrg = m_clickedOrg_task_count[3]
+    if num_ornot_clickedOrg>0:
+      phenstr = phenstr + "1"
+    else:
+      phenstr = phenstr + "0"
+
+    num_or_clickedOrg = m_clickedOrg_task_count[4]
+    if num_or_clickedOrg>0:
+      phenstr = phenstr + "1"
+    else:
+      phenstr = phenstr + "0"
+
+    num_andnot_clickedOrg = m_clickedOrg_task_count[5]
+    if num_andnot_clickedOrg>0:
+      phenstr = phenstr + "1"
+    else:
+      phenstr = phenstr + "0"
+
+    num_nor_clickedOrg = m_clickedOrg_task_count[6]
+    if num_nor_clickedOrg>0:
+      phenstr = phenstr + "1"
+    else:
+      phenstr = phenstr + "0"
+
+    num_xor_clickedOrg = m_clickedOrg_task_count[7]
+    if num_xor_clickedOrg>0:
+      phenstr = phenstr + "1"
+    else:
+      phenstr = phenstr + "0"
+
+    num_equals_clickedOrg = m_clickedOrg_task_count[8]
+    if num_equals_clickedOrg>0:
+      phenstr = phenstr + "1"
+    else:
+      phenstr = phenstr + "0"
+
+    return phenstr
+
+  def doWholePopStats(self):
+    """
+    doWholePopStats
+
+    These stats are especially needed to fulfill requirements for the
+    Multi-Dish version of Avida-ED.
+
+    Theory of operation: once per update, go over the entire population, 
+    getting useful statistics, including diversity measures. Display the
+    diversity measures on screen. If possible, save them to a database.
+    """
+
+    # pop : a list of occupied cells
+    # popsize : how many occupied cells we have
+    # popgen : dictionary: cell => genome
+    # popphen : dictionary: cell => phenotypes
+
+    # Getting ancestor string:
+    # self.m_session_mdl.m_cell_num_ancestor_name_dict[str(self.m_clicked_cell_number)])
+    # Pattern: name-pos-cell
+    # Can't count on "name" not including "-" characters, so use negative indexing
+
+    # Get gridmaster object to translate cell locations if multi-dish
+    if (True == self.m_session_mdl.m_is_multi_dish):
+      grid = Grids(self.m_session_mdl.m_multi_dish_dict["MD_SD_X"],
+                   self.m_session_mdl.m_multi_dish_dict["MD_SD_Y"],
+                   self.m_session_mdl.m_multi_dish_dict["MD_SD_SIZEX"],
+                   self.m_session_mdl.m_multi_dish_dict["MD_SD_SIZEY"])
+      md_sds = int(self.m_session_mdl.m_multi_dish_dict["MD_SD_X"]) * int(self.m_session_mdl.m_multi_dish_dict["MD_SD_Y"])
+
+    # Collect diversity data
+    # Clear the dictionary
+    self.m_session_mdl.md_diversity = {}
+
+    # Establish dictionaries
+    self.m_session_mdl.md_diversity["POP_GEN"] = {}
+    self.m_session_mdl.md_diversity["POP_PHEN"] = {}
+
+    self.m_session_mdl.md_diversity["NATIVES"] = {}
+    self.m_session_mdl.md_diversity["IMMIGRANTS"] = {}
+    self.m_session_mdl.md_diversity["EMIGRANTS"] = {}
+
+    self.m_session_mdl.md_diversity["POP_COUNTS"] = {}
+
+    # Establish lists and counters
+    self.m_session_mdl.md_diversity["POP_GEN"]["TOTAL"] = []
+    self.m_session_mdl.md_diversity["POP_COUNTS"]["TOTAL"] = 0
+    if (True == self.m_session_mdl.m_is_multi_dish): # if multi-dish
+      for ii in range(md_sds): # number of subdishes
+        self.m_session_mdl.md_diversity["POP_GEN"][str(ii)] = []
+        self.m_session_mdl.md_diversity["POP_COUNTS"][str(ii)] = 0
+
+    self.m_session_mdl.md_diversity["POP_PHEN"]["TOTAL"] = []
+    if (True == self.m_session_mdl.m_is_multi_dish): # if multi-dish
+      for ii in range(md_sds): # number of subdishes
+        self.m_session_mdl.md_diversity["POP_PHEN"][str(ii)] = []
+
+    if (True == self.m_session_mdl.m_is_multi_dish): # if multi-dish
+      for ii in range(md_sds): # number of subdishes
+        self.m_session_mdl.md_diversity["NATIVES"][str(ii)] = 0
+        self.m_session_mdl.md_diversity["IMMIGRANTS"][str(ii)] = 0
+        self.m_session_mdl.md_diversity["EMIGRANTS"][str(ii)] = 0
+
+    #self.session_model.md_diversity["POP_GEN"] = {}
+    #self.m_avida.m_population.GetCell(int(self.m_clicked_cell_number)).IsOccupied()
+
+    # For all the cells in the population
+    # Borrowed control flow from pyPetriDishCtrl.py
+    if self.m_avida is not None:
+      self.m_change_list = self.m_avida.m_avida_threaded_driver.GetChangeList()
+      self.m_world_w = cConfig.GetWorldX()
+      self.m_world_h = cConfig.GetWorldY()
+    else:
+      self.m_world_w = 30
+      self.m_world_h = 30
+    # print "Avida-ED world w = %s, h = %s" % (self.m_world_w,self.m_world_h)
+    if self.m_avida != None:
+      for x in range(self.m_world_w):
+        for y in range(self.m_world_h):
+          cell_ndx = x + self.m_world_w*y
+          
+          cell = self.m_avida.m_population.GetCell(cell_ndx)
+          # Check: is it occupied?
+          if cell.IsOccupied() == True:
+            self.m_session_mdl.md_diversity["POP_COUNTS"]["TOTAL"] += 1
+            
+            organism = cell.GetOrganism()
+            genome = organism.GetGenome()
+            phenotype = organism.GetPhenotype()
+            # population_dict[cell.GetID()] = str(genome.AsString())
+            # ancestor_dict[cell.GetID()] = str(organism.GetLineageLabel())
+
+            # Get the genome string
+            thisgenstr = str(genome.AsString())
+            self.m_session_mdl.md_diversity["POP_GEN"]["TOTAL"].append(thisgenstr)
+
+            # Get the phenotype string
+            thisphenstr = self.getPhenotypeStr(cell.GetID())
+            # print "Phenotype string %s" % (thisphenstr)
+            self.m_session_mdl.md_diversity["POP_PHEN"]["TOTAL"].append(thisphenstr)
+
+            # If MD
+            if (True == self.m_session_mdl.m_is_multi_dish): # if multi-dish
+
+              # Figure out the ancestral subdish position
+              ll = str(organism.GetLineageLabel())
+              # anc = self.m_session_mdl.m_ancestors_dict[cell.GetID()]
+              anc = self.m_session_mdl.m_ancestors_dict[str(ll)]
+              anclist = anc.split("-")
+              anc_pos = anclist[-2]
+              #print "Org at %s has ancestor %s, anc. SD pos. %s" % (cell_ndx,anc,anc_pos)
+              
+              # Figure out the current subdish position
+              sdinfo = grid.serverCell2ClientCell(int(self.m_session_mdl.m_multi_dish_dict["MD_SD_X"]),
+                                                  int(self.m_session_mdl.m_multi_dish_dict["MD_SD_Y"]),
+                                                  int(self.m_session_mdl.m_multi_dish_dict["MD_SD_SIZEX"]),
+                                                  int(self.m_session_mdl.m_multi_dish_dict["MD_SD_SIZEY"]),
+                                                  int(cell_ndx))
+              #print "sdinfo: %s" % (sdinfo)
+              cur_pos = sdinfo[-1]
+              #print "Anc. pos = %s, Cur. pos = %s" % (anc_pos, cur_pos)
+              # Increment count in native or immigrant tally for subdish
+              if (int(anc_pos) == int(cur_pos)):
+                #print "add to native count"
+                self.m_session_mdl.md_diversity["NATIVES"][str(cur_pos)] += 1
+              else:
+                self.m_session_mdl.md_diversity["IMMIGRANTS"][str(cur_pos)] += 1
+                self.m_session_mdl.md_diversity["EMIGRANTS"][str(anc_pos)] += 1
+
+              # SubDish diversity data
+              self.m_session_mdl.md_diversity["POP_GEN"][str(cur_pos)].append(thisgenstr)
+              self.m_session_mdl.md_diversity["POP_PHEN"][str(cur_pos)].append(thisphenstr)
+
+    pass
+

Added: branches/developers/avida-edward/source/python/AvidaGui2/pyPRNGState.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyPRNGState.py	                        (rev 0)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyPRNGState.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -0,0 +1,211 @@
+"""
+pyPRNGState.py
+
+Provides a global stack for interrupting the use of the global C++ pseudo-random number generator and 
+using it for a set of computations.
+
+Provides a registry for status and pause functions for processes that use the global C++ PRNG.
+
+"""
+
+#import ctools
+#from AvidaCore import cAnalyzeGenotype, cGenome, cInstruction, cInstUtil, cRandom, cString, cTools
+from AvidaCore import cRandom, cTools
+
+import qt
+
+class StackType():
+    """
+    StackType
+    Abstract stack data type. 
+    Mostly a direct use of Python list methods, but offers the "top" 
+    operation in addition and a push() alias for append().
+    """
+    def __init__(self):
+        # A list is the basic data structure
+        # An empty list is the start
+        self.stk = []
+    
+    def push(self,item):
+        # Add an item to the top of the stack
+        self.stk.append(item)
+
+    def pop(self):
+        # Remove an item from the top of the stack
+        return(self.stk.pop())
+
+    def top(self):
+        return(self.stk[-1])
+
+# Make the class one that can generate and receive signals by basing it on
+# a Qt object. Not used so far, but doesn't hurt to have it.
+class PRNGState(QObject):
+    """
+    PRNGState
+
+    Theory of operation:
+
+    A PRNGState object should be instantiated on the start of Avida-ED.
+
+    All processes requiring the use of the global pseudo-random number
+    generator (PRNG) should provide six items: 
+    - name of the process
+    - a method that provides the status of the process
+    - a method that pauses the process
+    - a method that will resume the process
+    - whether the random seed to be used is based on time()
+    - a random seed value (will be 1 for the Organism view)
+
+    The global PRNG-using process should be added to the PRNGState with
+    the add() method before it first begins. The add() method will set up
+    the global PRNG state and preserve the state needed by any previous
+    user. The process may then be started safely.
+
+    On end of the current process, the PRNGState remove() method should 
+    be called, which will restore the previous user process by setting
+    the PRNG state last used and then running the resume() function of the
+    prior process.
+    
+    """
+    def setPRNG(self,prng_state):
+        """
+        setPRNG
+        Method to restore a global PRNG state preparatory to resuming a 
+        PRNG-using process.
+        """
+        # Restore random number generator state.
+        cTools.globalRandom().Clone(prng_state)
+
+    def resetPRNG(self,seed_based_on_time,seed):
+        """
+        resetPRNG
+        Method to start the PRNG with a new seed.
+        """
+        # Reset random number generator state.
+        if self.m_seed_based_on_time:
+            cTools.globalRandom().ResetSeed(-1)
+        else:
+            cTools.globalRandom().ResetSeed(seed)
+
+    def __init__(self):
+        """
+        __init__
+        Create the various dictionaries and data structures to handle the global PRNG.
+        """
+        # Create empty status dict
+        self.status = {}
+        # Create empty pause dict
+        self.pause = {}
+        # Create empty resume dict
+        self.resume = {}
+        
+        # Create an empty global PRNG users and state stacks
+        self.users = StackType()
+        self.states = StackType()
+
+    def add(self,processname,statusfunc,pausefunc,resumefunc,seed_based_on_time,seed):
+        """
+        add
+        Method to add a process to the users stack, pausing any previous global PRNG-using
+        process.
+        """
+        # A process needs the global PRNG
+        # Pause the currently running global PRNG user, if there is one
+        olduser = self.users.top()
+        if (None <> olduser):      # If there is no current user, nothing special need be done
+            # Need to pause the old user of the global PRNG
+            self.pause[olduser]()
+            # Push the global PRNG state for the just-paused process
+            # Save random number generator state.
+            random_number_generator_state = cRandom(cTools.globalRandom())
+            self.states.push(random_number_generator_state)
+        # Now set the new process up for global PRNG use
+        self.users.push(processname)
+        self.status[processname] = statusfunc
+        self.pause[processname] = pausefunc
+        self.resume[processname] = resumefunc
+        self.resetPRNG(seed_based_on_time,seed)
+
+    def remove(self):
+        """
+        remove
+        Method to remove the top value from the users stack and
+        restore the prior PRNG state.
+        """
+        ruser = self.users.pop()
+        prng_state = self.states.pop()
+        if (None == prng_state):       # This is a problem; should never happen
+            print "PRNG remove ERROR: None state encountered. **** VERY BAD THING ****"
+        else:
+            # There is a prior state, so set it up
+            setPRNG(prng_state)
+            # Now to resume the process of the prior user
+            olduser = self.states.top()
+            if (None <> olduser):
+                self.resume[olduser]()
+
+
+
+
+class AbstractProc(QObject):
+    def __init__(self,name):
+        self.name = name
+        self.run_state = "Not started"
+
+    def status(self):
+        return(self.run_state)
+
+    def pause(self):
+        self.run_state = "Paused"
+
+    def resume(self):
+        self.run_state = "Running"
+
+    def stop(self):
+        self.run_state = "Stopped"
+
+    def do_process(self):
+        if ("Running" == self.run_State):
+            self.process_step()
+
+    def process_step(self):
+        pass
+
+
+class ProcA(AbstractProc):
+    def __init__(self,name):
+        AbstractProc.__init__(name)
+
+    def status(self):
+        return(self.run_state)
+
+    def pause(self):
+        self.run_state = "Paused"
+
+    def resume(self):
+        self.run_state = "Running"
+
+    def stop(self):
+        self.run_state = "Stopped"
+
+    def do_process(self):
+        if ("Running" == self.run_State):
+            self.process_step()
+
+    def process_step(self):
+        pass
+        
+
+
+if (1): # Testing
+
+    print "Testing PRNGState...\n"
+    myprngctrl = PRNGState()
+
+
+    proca = ProcA("ProcA")
+
+
+    print "ProcA name = %s, state = %s\n" % (proca.name,proca.status())
+
+    print "Testing PRNGState... Done.\n";

Modified: branches/developers/avida-edward/source/python/AvidaGui2/pyPetriConfigureCtrl.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyPetriConfigureCtrl.py	2009-08-04 03:26:21 UTC (rev 3356)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyPetriConfigureCtrl.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -234,6 +234,10 @@
   def FillDishSlot(self, dish_name, petri_dict):
     
     self.full_petri_dict = petri_dict.dictionary
+
+    print "Dictionary sections:"
+    print self.full_petri_dict.keys()
+
     settings_dict =  petri_dict.dictionary["SETTINGS"]
 
     # Erase all items for the ancestor list 
@@ -451,12 +455,19 @@
 
 
   def CreateFilesFromPetriSlot(self, out_dir = None):
+    # print "**********************      CreateFilesFromPetriSlot  *************************************************"
 
     # The input files will be placed in a python generated temporary directory
     # ouput files will be stored in tmp_dir/output until the data is frozen
     # (ie saved)
-
-    self.full_petri_dict["SETTINGS"] = self.Form2Dictionary()
+    
+    # @WRE: Problem here with non-square layouts
+    # Figure out if we've read a full petri dish. If so, we already have all the "SETTINGS" we need.
+    if (self.full_petri_dict.has_key("CELLS")):
+      #print "Not calling Form2Dictionary"
+      pass
+    else:
+      self.full_petri_dict["SETTINGS"] = self.Form2Dictionary()
     write_object = pyWriteAvidaCfgEvent(self.full_petri_dict,
       self.m_session_mdl, 
       self.m_session_mdl.m_current_workspace,
@@ -465,8 +476,10 @@
     self.m_session_mdl.m_session_mdtr.emit(
       PYSIGNAL("doInitializeAvidaPhaseIISig"), 
       (os.path.join(self.m_session_mdl.m_tempdir, "avida_cfg.avida"),))
+    print "Using temporary directory %s" % (self.m_session_mdl.m_tempdir)
       
   def Form2Dictionary(self):
+    # print "Form2Dictionary"
     settings_dict = {}
     
     # Write START_CREATUREi for all the organisms in the Ancestor Icon View
@@ -539,12 +552,22 @@
     return settings_dict
     
   def FreezePetriSlot(self, population_dict = None, ancestor_dict = None, send_reset_signal = False, send_quit_signal = False):
+    print "pyPetriConfigureCtrl.FreezePetriSlot()"
     if len(population_dict) == 0:
       freeze_empty_only_flag = True;
     else:
       freeze_empty_only_flag = False;
     tmp_dict = {}
-    tmp_dict["SETTINGS"] = self.Form2Dictionary()
+
+    # @WRE: Handle multi-dish case 
+    if (True == self.m_session_mdl.m_is_multi_dish):
+      print "Multi-Dish case"
+      tmp_dict["MULTI_DISH"] = self.m_session_mdl.m_multi_dish_dict
+      # ??? Need to carry over settings from previous, not collect them from the form
+      tmp_dict["SETTINGS"] = self.Form2Dictionary()
+    else:
+      print "Regular dish case"
+      tmp_dict["SETTINGS"] = self.Form2Dictionary()
     m_pop_up_freezer_file_name = pyFreezeDialogCtrl()
     file_name = m_pop_up_freezer_file_name.showDialog(self.m_session_mdl, freeze_empty_only_flag)
     file_name_len = len(file_name.rstrip())
@@ -578,7 +601,6 @@
         self.m_session_mdl.saved_empty_dish = True
       else:
         self.m_session_mdl.saved_full_dish = True
-
     
       # Have program redraw the freezer menu pane
 
@@ -689,6 +711,8 @@
           freezer_item_name_temp = freezer_item_name
           self.m_session_mdl.new_empty_dish = True
         thawed_item = pyReadFreezer(freezer_item_name_temp)
+        print "WRE: new status bar message signal."
+        self.m_session_mdl.m_session_mdtr.emit(PYSIGNAL("statusBarMessageSig"), ("Large dishes may take a few minutes to process. Be patient.",))
         self.m_session_mdl.m_session_mdtr.emit(PYSIGNAL("doDefrostDishSig"),
           (os.path.splitext((os.path.split(str(freezer_item_name))[1]))[0], thawed_item,))
 

Modified: branches/developers/avida-edward/source/python/AvidaGui2/pyPetriConfigureView.ui
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyPetriConfigureView.ui	2009-08-04 03:26:21 UTC (rev 3356)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyPetriConfigureView.ui	2009-08-05 16:45:50 UTC (rev 3357)
@@ -238,7 +238,7 @@
                                     <number>1</number>
                                 </property>
                                 <property name="maxValue">
-                                    <number>100</number>
+                                    <number>300</number>
                                 </property>
                                 <property name="lineStep">
                                     <number>1</number>
@@ -253,7 +253,7 @@
                                     <enum>Horizontal</enum>
                                 </property>
                                 <property name="toolTip" stdset="0">
-                                    <string>&lt;p&gt;Set the height and width of the petri dish (1 to 100)&lt;/p&gt;</string>
+                                    <string>&lt;p&gt;Set the height and width of the petri dish (1 to 300)&lt;/p&gt;</string>
                                 </property>
                             </widget>
                             <widget class="QLayoutWidget" row="1" column="1">

Modified: branches/developers/avida-edward/source/python/AvidaGui2/pyPetriDishCtrl.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyPetriDishCtrl.py	2009-08-04 03:26:21 UTC (rev 3356)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyPetriDishCtrl.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -27,6 +27,7 @@
     self.clearWState(Qt.WState_Polished)
 
   def construct(self, session_mdl):
+    print "pyPetriDishCtrl.construct()"
     self.m_session_mdl = session_mdl
     self.m_avida = None
 
@@ -102,11 +103,13 @@
                  self.vbarScrollPrevLineSlot)    
 
   def doStartAvidaSlot (self):
+    print "pyPetriDishCtrl.doStartAvidaSlot"
 #    self.m_avida_has_started = True //replacing with the session_mdl version
 
     self.m_session_mdl.m_avida_has_started = True
 
   def restart(self):
+    print "pyPetriDishCtrl.restart"
     self.m_cell_info = None
     self.m_changed_cell_items = []
     self.m_color_lookup_functor = None
@@ -144,6 +147,7 @@
       self.m_canvas)
 
   def setAvidaSlot(self, avida):
+    print "pyPetriDishCtrl.setAvidaSlot()"
     descr(avida)
     old_avida = self.m_avida
     self.m_avida = avida
@@ -205,6 +209,7 @@
     self.updateCellItems(True)
 
   def setDragSlot(self, org_clicked_on_item = None):
+    print "pyPetriDishCtrl.setDragSlot()"
     descr(org_clicked_on_item)
     if org_clicked_on_item:
       clicked_cell_num = org_clicked_on_item.m_population_cell.GetID()
@@ -313,7 +318,7 @@
       if self.m_canvas: self.m_canvas.update()
 
   def extractPopulationSlot(self, send_reset_signal = False, send_quit_signal = False):
-
+    print "pyPetriDishCtrl.extractPopulationSlot()"
     # If there is an active Avida object find all the cells that are occupied
     # and place them in a dictionary.  Fire off the signal for the next freezer
     # phase with that signal.

Modified: branches/developers/avida-edward/source/python/AvidaGui2/pyReadFreezer.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyReadFreezer.py	2009-08-04 03:26:21 UTC (rev 3356)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyReadFreezer.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -5,6 +5,7 @@
 class pyReadFreezer:
 
   def __init__(self, in_file_name = None):
+    print "pyReadFreezer.__init__()"
     self.file_name = in_file_name
     self.dictionary = {}
     freezefile = open(self.file_name)
@@ -27,12 +28,18 @@
         if line[0] == "*":
           section_key = line[1:].upper()
           self.dictionary[section_key] = {}
+          print "Added dictionary section '%s'" % (section_key)
+
+
         else:
 
           # split into key and value (which could be multiple words)
 
           var_name, value = line.split(' ',1)
           self.dictionary[section_key][var_name.upper()] = value
+
+    # ??? debug, turn off
+    # print self.dictionary["SETTINGS"]
 	
   def GetDictionary(self):
     return self.dictionary

Modified: branches/developers/avida-edward/source/python/AvidaGui2/pyWriteAvidaCfgEvent.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyWriteAvidaCfgEvent.py	2009-08-04 03:26:21 UTC (rev 3356)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyWriteAvidaCfgEvent.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -6,6 +6,8 @@
 
 from descr import *
 
+from pyMDMkEnv import *
+
 # Class to write the working avida_cfg, event and environment files based on 
 # the contents of settings dictionary
 
@@ -23,21 +25,36 @@
       settings_dict = {}
     else:
       settings_dict = in_dict["SETTINGS"]
+      self.m_settings_dict = settings_dict
+      print "pyWriteAvidaCfgEvent.__init__()"
+      print settings_dict
 	
     # Copies default event file and add to the 
     # temporary dictionary where the input files will live
 
     shutil.copyfile(os.path.join(workspace_dir, "events.default"), os.path.join(tmp_in_dir, "events.cfg"))
     
+    # Assume that it is not a multi-dish, disprove that later
+    self.m_session_mdl.m_is_multi_dish = False
+
     # If this is a full petri dish inject all the organisms, otherwise
     # inject the start creature in the center of the grid
 
     
     #if we have a full petri dish...
+    # Existence of "CELLS" section defines a full petri dish, except if this is the research version
     if in_dict.has_key("CELLS") and \
        (not (os.path.exists(os.path.join(workspace_dir,"research.version")))): 
+
+      print " - full petri dish"
+
+      # Local reference to "CELLS"
       cells_dict = in_dict["CELLS"]
+      # Local reference to "ORGANISMS"
       organisms_dict = in_dict["ORGANISMS"]
+
+      print " - dish has %s organisms and %s cells" % (len(organisms_dict.keys()),len(cells_dict.keys()))
+
       self.m_session_mdl.m_founding_cells_dict = cells_dict
 
       if in_dict.has_key("ANCESTOR_NAMES"):
@@ -58,6 +75,14 @@
       self.m_session_mdl.m_global_num_of_ancestors = \
         len(session_mdl.m_cell_num_ancestor_name_dict)
 
+      # @WRE: Multi-dish?
+      if (in_dict.has_key("MULTI_DISH")):
+        self.m_session_mdl.m_multi_dish_dict = in_dict["MULTI_DISH"]
+      else:
+        self.m_session_mdl.m_multi_dish_dict = {}
+      if (0 < len(self.m_session_mdl.m_multi_dish_dict.keys())):
+        self.m_session_mdl.m_is_multi_dish = True
+
     #if it is not a full petri dish
     else:
       self.m_session_mdl.m_cell_num_ancestor_name_dict = {}
@@ -71,6 +96,8 @@
         world_x = settings_dict["WORLD-X"]
         world_y = settings_dict["WORLD-Y"]
 
+        print "World size set as x = %s, y = %s" % (world_x, world_y)
+
         # Count all ancestors with the name of the form START_CREATUREx
 
         num_ancestors = 0
@@ -105,6 +132,12 @@
 
     settings_dict["EVENT_FILE"] = os.path.join(tmp_in_dir, "events.cfg")
     settings_dict["ENVIRONMENT_FILE"] = os.path.join(tmp_in_dir, "environment.cfg")
+
+    # @WRE: Handle Multi-Dish case separately
+    #if (True == self.m_session_mdl.m_is_multi_dish):
+    #  self.writeMDEnvironmentFile(workspace_dir, settings_dict, self.m_session_mdl.m_multi_dish_dict)
+    #else: # Regular dish case
+
     self.writeEnvironmentFile(workspace_dir, settings_dict)
     settings_dict["INST_SET"] = os.path.join(tmp_in_dir, "inst_set.default")
     avida_cfg_file_name = self.writeAvidaCfgFile(workspace_dir, tmp_in_dir, \
@@ -195,51 +228,73 @@
 
   def writeEnvironmentFile(self, workspace_dir, settings_dict):
  
-    orig_environment_file = open(os.path.join(workspace_dir, "environment.default"))
-    lines = orig_environment_file.readlines()
-    orig_environment_file.close()
-    out_environment_file = open(settings_dict["ENVIRONMENT_FILE"], "w")
-    for line in lines:
-      comment_start = line.find("#")
-      if comment_start > -1:
-        if comment_start == 0:
-          clean_line = ""
+    if (False == self.m_session_mdl.m_is_multi_dish):   # This is not a multi-dish, so use the normal processing
+      orig_environment_file = open(os.path.join(workspace_dir, "environment.default"))
+      lines = orig_environment_file.readlines()
+      orig_environment_file.close()
+      out_environment_file = open(settings_dict["ENVIRONMENT_FILE"], "w")
+      for line in lines:
+        comment_start = line.find("#")
+        if comment_start > -1:
+          if comment_start == 0:
+            clean_line = ""
+          else:
+            clean_line = line[:comment_start]
         else:
-          clean_line = line[:comment_start]
-      else:
-        clean_line = line;
-      clean_line = clean_line.strip()
-      if len(clean_line) > 0:
-        split_out = string.split(clean_line)
-        command_name = split_out[0].upper()
+          clean_line = line;
+        clean_line = clean_line.strip()
+        if len(clean_line) > 0:
+          split_out = string.split(clean_line)
+          command_name = split_out[0].upper()
+  
+          # if it is a reaction line check further (otherwise print the line)
+  
+          if command_name == "REACTION":
+            resource_name = split_out[1].upper()
+            resource_key = "REWARD_" + resource_name
+            task_name = split_out[2]
+  
+            # If the there is a reward key for this resource check further
+            # (otherwise print the line)
+   
+            if settings_dict.has_key(resource_key) == True:
+  
+              # If the value of the reward key is true print it out as is 
+              # (otherwise print out as a zero bonus)
+  
+              if settings_dict[resource_key] == "YES":
+                out_environment_file.write(line)
+              else:
+                out_environment_file.write("REACTION " + resource_name + " " +
+                                  task_name + " process:value=0.0:type=add\n")
+            else:
+              out_environment_file.write(line)
+          else:
+            out_environment_file.write(line)  
+      out_environment_file.close()
+    else:
+      # This is where the multi-dish processing happens
+      # Need to write out both RESOURCE and REACTION definitions for spatial resources
+      # Need to make sure the order of initial resources corresponds to the canonical order
+      # for in-run tracking to work.
 
-        # if it is a reaction line check further (otherwise print the line)
+      # ???
+      # Get a MkEnv object
+      # print self.m_settings_dict
+      print self.m_session_mdl.m_multi_dish_dict
 
-        if command_name == "REACTION":
-          resource_name = split_out[1].upper()
-          resource_key = "REWARD_" + resource_name
-          task_name = split_out[2]
+      mkenv = MkEnv(int(self.m_session_mdl.m_multi_dish_dict["MD_SD_X"]),
+                    int(self.m_session_mdl.m_multi_dish_dict["MD_SD_Y"]),
+                    int(self.m_session_mdl.m_multi_dish_dict["MD_SD_SIZEX"]),
+                    int(self.m_session_mdl.m_multi_dish_dict["MD_SD_SIZEY"]))
 
-          # If the there is a reward key for this resource check further
-          # (otherwise print the line)
- 
-          if settings_dict.has_key(resource_key) == True:
+      # Have it write out the environment file
+      out_environment_file = str(settings_dict["ENVIRONMENT_FILE"])
+      mkenv.mkMDTemplate(out_environment_file,self.m_session_mdl.m_multi_dish_dict)
+      
+          
+      pass
 
-            # If the value of the reward key is true print it out as is 
-            # (otherwise print out as a zero bonus)
-
-            if settings_dict[resource_key] == "YES":
-              out_environment_file.write(line)
-            else:
-              out_environment_file.write("REACTION " + resource_name + " " +
-                                task_name + " process:value=0.0:type=add\n")
-          else:
-            out_environment_file.write(line)
-        else:
-          out_environment_file.write(line)
-
-    out_environment_file.close()
-
   def modifyEventFile(self, cells_dict, organisms_dict, ancestor_link_dict, merits_dict,
     event_file_name, tmp_out_dir = None):
 

Modified: branches/developers/avida-edward/source/python/AvidaGui2/pyWriteToFreezer.py
===================================================================
--- branches/developers/avida-edward/source/python/AvidaGui2/pyWriteToFreezer.py	2009-08-04 03:26:21 UTC (rev 3356)
+++ branches/developers/avida-edward/source/python/AvidaGui2/pyWriteToFreezer.py	2009-08-05 16:45:50 UTC (rev 3357)
@@ -20,7 +20,13 @@
 
     elif out_file_name.endswith(".full"):
       is_dish = True
-      self.simplifyPopulation(in_dict)
+      if (in_dict.has_key("MULTI_DISH")):
+        # Multi-dish already has correct set of population links
+        self.simplifyPopulation(in_dict)
+        pass
+      else:
+        # Other dishes require fixup
+        self.simplifyPopulation(in_dict)
       out_file_name = os.path.join(out_file_name, 'petri_dish')
 
     elif out_file_name.endswith(".empty"):
@@ -40,6 +46,7 @@
     elif is_dish == True:
 
       for section in in_dict.keys():
+        print "writing out section '%s'" % (str(section))
     
         # Always print out the petri dishes settings and if it is a full dish
         # print out the cell and organism information
@@ -55,6 +62,7 @@
     out_freezer_file.close()
     
   def simplifyPopulation(self, in_dict = None):
+    print "simplifyPopulation"
     if in_dict.has_key("POPULATION"):
       pop_dict = in_dict["POPULATION"]
       del in_dict["POPULATION"]




More information about the Avida-cvs mailing list