Appendix A. ChromoFlow pseudo-source code


BEGIN PROGRAM CHROMOFLOW():
  // Set default program parameters
  READ_SIMULATION_PARAMETERS();
  READ_GENOME_MAP();
  READ_ALLELE_FREQUENCIES();
  READ_PEDIGREE_DATA();
  INIT_SIMULATION();
  SIMULATE();
	// Produce reports with results
END PROGRAM CHROMOFLOW()
BEGIN FUNCTION READ_SIMULATION_PARAMETERS():

	// Open command file or read commands from keyboard

	// Get filenames for population, genome map and allele frequencies

	Read in RareAlleleFrequency	// Default = 0.05 

	Read in SimRecombination?	// Simulate recombination

	Read in SimCensus?	// Simulate for census years. Default is generation

	Read in FirstYear	// First census year

	Read in LastYear	// Last census year

	Read in Runs	// Number of runs (iterations)

END FUNCTION READ_SIMULATION_PARAMETERS()
BEGIN FUNCTION READ_GENOME_MAP();

	// Create data structure to store chromosome information

  FOR (each Chromosome):

		FOR (each Locus on Chromosome):

			Read in LocusSite	// in centi-Morgans

		END FOR (Locus) LOOP

	END FOR (Chromosome) LOOP

END FUNCTION READ_GENOME_MAP()
BEGIN FUNCTION READ_ALLELE_FREQUENCIES();

	// Create data structure to store allelic variants per locus

	FOR (each Locus):

		FOR (each Allele):

			Read in Frequency

		END FOR (Allele) LOOP

	END FOR (Locus) LOOP

END FUNCTION READ_ALLELE_FREQUENCIES()
BEGIN FUNCTION READ_PEDIGREE_DATA():

	// Read number of individuals from Master file 

	// Create data structure to store pedigree records

	FOR (each Individual):

		Read in StudbookID	// Unique ID for each individual

		Read in SireID	    // Studbook ID of sire, wild or unknown

		Read in DamID	    // Studbook ID of dam, wild or unknown	

		Read in Sex        // Male, female or unknown	

		Read in Origin     // Wild, captive or unknown

		Read in BirthDate

		Read in DeathDate	// Empty if alive

	END FOR (Individual) LOOP

	// Read number of move records from Move file

	// Create data structure to store records with move data

	FOR (each Move):

		Read in StudbookID	  // See Master loop

		Read in MoveDate

		Read in NewLocation	// Breeding group or population

	END FOR (Move) LOOP

	// Sort move records on date

END FUNCTION READ_PEDIGREE_DATA()
BEGIN FUNCTION INIT_SIMULATION():

	// Sort pedigree data on date of birth

	COMPUTE_GENERATION();

	IF (SimCensus?):

		COMPUTE_CENSUS();

	END IF (SimCensus?)

	WILD_GENETIC_VARIATION(); // Genetic variation in source population	

	CREATE_LIBRARY_WITH_HOMOLOGUES();

	CREATE_INDIVIDUAL_GENOMES();

END FUNCTION INIT_SIMULATION()

BEGIN FUNCTION COMPUTE_GENERATION();

	FOR (each Individual):

		// Individual is a (potential) founder

		IF (Animals is born in source population):

			Set Generation  = 0 	

			CONTINUE (Individual) LOOP

		END IF(Potential founder)

		IF (Sire is UNKNOWN):

			Set Generation = 0	

		ELSE

			Set Generation = Generation of Sire

		END IF (Sire)

		IF (Dam unequals UNKNOWN) AND 

			(Generation of Dam is larger than generation of Sire):

			Set Generation = Generation of Dam

		END IF (Dam)

		Add 1 to Generation	// Individual with unknown parents is F1

		Add 1 to GenerationGroup->Size 

	END FOR (Individual) LOOP		

END FUNCTION COMPUTE_GENERATION()
BEGIN FUNCTION COMPUTE_CENSUS();

	Set CensusYears = (LastYear - FirstYear) + 1

	// Create data structure to store living animals for each census year

	FOR (each Year):		

		FOR (each Individual):

			IF (Alive at the end of Year)

				Add 1 to YearGroup->Size

			END IF (Alive)

		END FOR (Individual) LOOP

	END FOR (Year) LOOP

END FUNCTION COMPUTE_CENSUS()
BEGIN FUNCTION WILD_GENETIC_VARIATION();

	FOR (each Locus):

		FOR (each Allele):	            // Allelic variant at locus

			IF (Frequency is larger than 0):

				Add 1 to WildAlleles	// Total number of alleles in source

				Add (Frequency ^ 2) to Locus->GeneIdentity

			END IF (Frequency)

			// Test if locus is polymorphic

			IF (Frequency equals or is larger than RareAlleleFrequency) AND

				(Allele->Frequency equals or is smaller than (1 - RareAlleleFrequency):

				Set Locus->Polymorphic? = TRUE

			END IF (Frequency)

		END FOR (Allele) LOOP

		IF (Locus->Polymorphic?):

			Add 1 to WildPolymorpishm	// Number of polymorphic loci in source

		END IF (Locus is polymorphic)

		Add Locus->GeneIdentity to WildGeneIdentity

	END FOR (Locus) LOOP

	Set WildPolymorphism = WildPolymorphism / Loci 

	Set WildGeneIdentity = WildGeneIdentity / Loci

	Set WildGeneDiversity = 1 - WildGeneIdentity

	Set WildHeterozygosity = WildGenediversity 	// Assume H - W equilibrium

END FUNCTION WILD_GENETIC_VARIATION()


BEGIN FUNCTION CREATE_LIBRARY_WITH_HOMOLOGUES():

	IF (SimRecombination?):

		// Create data structure to store diploid set for each individual

	ELSE

		// Create data structure to store diploid set of chromosomes 
		    // for each founder

	END IF/ELSE (SimRecombination?)

END FUNCTION CREATE_LIBRARY_WITH_HOMOLOGUES()


BEGIN FUNCTION CREATE_INDIVIDUAL_GENOMES(): FOR (each Individual): // Create data structure to store ID's of diploid set of chromosomes (homologues) IF (Animal is born in source population): // Potential founder // Link homologue ID's in library to individual according sequence of creation END IF (Potential founder) END FOR (Individual) LOOP END FUNCTION CREATE_INDIVIDUAL_GENOMES()
BEGIN FUNCTION SIMULATE():

	FOR (each Run):

		// Initialize pseudo random generator

		ASSIGN_ALLELES_TO_FOUNDERS();

		ASSIGN_ALLELES_TO_DESCENDANTS();

		RUN_RESULTS();

	END FOR (Run) LOOP 

	SIMULATION_RESULTS();

END FUNCTION SIMULATE()
BEGIN FUNCTION ASSIGN_ALLELES_TO_FOUNDERS():

	FOR (each Founder):

		FOR (each Homologue):		

			FOR (each Locus at homologue):

				Set Allele = SAMPLE_WILD_ALLELE(Locus);

			END FOR (Locus at homologue ) LOOP

		END FOR (Homologue) LOOP

	END FOR (Founder) LOOP

END FUNCTION ASSIGN_ALLELES_TO_FOUNDERS()
BEGIN FUNCTION SAMPLE_WILD_ALLELE(Locus):

	// Get number of allelic variants for locus in source population

	IF (not Locus->Polymorphic?):

		RETURN(1)	// Only one allellic variant

	END IF (Locus->Polymorphic)		

	// Temporary variables

	Set RandomFrequency = RANDOM(0..1) 				

	Set LowerFrequency = 0

	Set UpperFrequency = 0

	FOR (each Allele):	// Allelic variants at locus

		Add Locus->Allele->Frequency to UpperFrequency

		IF	(RandomFrequency equals or is larger than LowerFrequency) AND

			(RandomFrequency is smaller than UpperFrequency) :

			RETURN(Allele number)	// Number in range 1 .. Locus->Alleles

		END IF (RandomFrequency)

		Set LowerFrequency = Upper frequency

	END FOR (Allele) LOOP

END FUNCTION SAMPLE_WILD_ALLELE()
BEGIN FUNCTION ASSIGN_ALLELES_TO_DESCENDANTS():

	FOR (each Individual):

		IF (Generation > 0):

			FOR (each Chromosome):

				IF (SimRecombination?):

 					Set Homologue1->ID = CROSS_OVER(Chromosome, 

													SireID->Chromosome);

    				Set Homologue2->ID = CROSS_OVER(Chromosome, 

													DamID->Chromosome);

				ELSE

		   	   		Set Homologue1->ID = MENDELIAN(SireID->Chromosome);

					Set Homologue2->ID = MENDELIAN(DamID->Chromosome);

				END IF/ELSE (SimRecombination?)

			END FOR (Chromosome) LOOP

		END IF (Generation)

	END FOR (Individual) LOOP

END FUNCTION ASSIGN_ALLELES_TO_DESCENDANTS()
BEGIN FUNCTION CROSS_OVER(Chromosome, ParentChromosome):

	// Retrieve data on locus map of chromosome

	// Make copies of both homologues of parental chromosome

	// Chromatids 1 and 2 refer to homologue 1, chromatids 3 and 4 to
homologue 2	  

	FOR (each Locus on chromosome starting at second)

    // Get map site of previous locus in centi-Morgans from top

    // Get map site of locus in centi-Morgans of top

		Set Frequency = MORGANS_TO_FREQUENCY( LocusSite - PreviousLocusSite) *
2 

		IF (RANDOM(0..1) is smaller than Frequency):

			Set Recombination? = TRUE

      // Select randomly which chromatids 1 or 2 interact with chromatids 3 or
4 

			FOR (each Locus after chiasma):		

        // Swap alleles between selected chromatids

			END FOR (Locus after chiasma) LOOP

		END IF (Recombination?)

	END FOR (Locus on chromosome) LOOP

	IF  (Recombination?):

 		Set Chromatid = RANDOM_INTEGER(1..4)

		// Add selected chromatid to library with homologues and assign
HomologueID

	ELSE

		Set HomologueID = MENDELIAN(ParentChromosome);

	END IF/ELSE (Recombination?)

	RETURN( HomologueID )

END FUNCTION CROSS_OVER()
BEGIN FUNCTION MORGANS_TO_FREQUENCY( centiMorgans ):

  // Computes for double-strand model

  r =  0.5 * (1.0 - EXPONENTIAL( -2.0 * centiMorgans )  )

	RETURN ( r )	 	

END FUNCTION MORGANS_TO_FREQUENCY()
BEGIN FUNCTION MENDELIAN(ParentChromosome):

	IF (RANDOM_INTEGER(1..2) is 1):

		RETURN(ParentChromosome->Homologue1->ID)

	ELSE

		RETURN(ParentChromosome->Homologue2->ID)

	END IF/ELSE (Homologue)

END FUNCTION MENDELIAN()
BEGIN FUNCTION RUN_RESULTS():

	// Type of group depends on simulation settings (generation or census)

	FOR (each Group):

		FOR (each Individual in Group):

			FOR (each Chromosome):

				// Get both homologues of individual

				FOR (each Locus on Chromosome):

					// Get alleles at both homologues

					IF (Allele1 <> Allele2):

						Add 1 to Group->Heterozygosity

					END IF (Different alleles)

					Add 1 to Allele1->Frequency

					Add 1 to Allele2->Frequency

				END FOR (Locus at chromosome) LOOP

			END FOR (Chromosome) LOOP


		END FOR (Individidual) LOOP			

		FOR (each Locus):

			FOR (each Allelelic variant at locus)

				Set Allele->Frequency = Allele->Frequency / ( 2 * Group->Size)

				Add (Allele->Frequency^2) to Group->GeneIdentity

				IF (Allele->Frequency equals or is larger than RareAlleleFrequency) AND

					(Allele->Frequency equals or is smaller than (1 - RareAlleleFrequency)
):

					Set Locus->Polymorphic = TRUE;

				END IF (Allele->Frequency)

				IF (Allele->Frequency > 0):

					Add 1 to Group->Allele->Number

				END IF (Allele frequency)

			END FOR (Allelic variant at locus) LOOP

			IF (Locus->Polymorphic?):

				Add 1 to Group->Polymorphism

			END IF (Locus->Polymorphic?)

		END FOR (Locus) LOOP

		// Compute averages per group:

		// observed heterozygosity, gene identity (and gene diversity) over all loci, 
polymorphism

		// Store values as fractions of values in the source (wild) population 

	END FOR (Group) LOOP

END FUNCTION RUN_RESULTS()
BEGIN FUNCTION SIMULATION_RESULTS();

	FOR (each Group):

		// Compute  average and variance over runs:

		// proportion of heterozygous loci, gene diversity, polymorphism, number of
alleles

		// fraction of runs where value < (0.95 * average) for previous measures

	END FOR (Group) LOOP		

END FUNCTION SIMULATION_RESULTS()