Attribute VB_Name = "Module5" ' Function Name: AlleleSet() ' Parameters Byval: row, leftColumn, rightColumn ' Return type: Array ' Description: Find all the different alleles at a particular locus. Public Function AlleleSet(ByVal row, ByVal leftColumn, ByVal rightColumn) ' [DECLARE VARIABLES] Dim allele As Variant, alleleArray() As Variant, colony As Variant Dim column As Integer, colonyColumn As Integer, counter As Integer, startRow As Integer Dim needToAdd As Boolean Dim nullAllele As String ' [INITIALISE VARIABLES] colonyColumn = 1 ' Refers to column A. colony = ActiveSheet.Cells(row, colonyColumn).Value ' Retrieves name of the colony. startRow = row ReDim alleleArray(1) ' Re-size the dynamic array. alleleArray(1) = ActiveSheet.Cells(row, leftColumn).Value nullAllele = "." Do While (alleleArray(1) = nullAllele) ' Ensures that dots(.) are not considered part of the allele set. row = row + 1 alleleArray(1) = ActiveSheet.Cells(row, leftColumn).Value Loop ' [RE-INITIALISE VARIABLES] row = startRow ' The following For-Loop scans down the left column first, then the right column. This is ' easier than scanning from left to right and down at the same time. For column = leftColumn To rightColumn Do needToAdd = True allele = ActiveSheet.Cells(row, column).Value If (allele <> nullAllele) Then ' Ensures null alleles are not considered to be part of the allele set. For counter = 1 To UBound(alleleArray) ' Tests whether current test allele has already been added to the allele set. If (allele = alleleArray(counter)) Then needToAdd = False Exit For End If Next counter If (needToAdd) Then ReDim Preserve alleleArray(UBound(alleleArray) + 1) ' Increases array size as required. alleleArray(UBound(alleleArray)) = allele End If End If row = row + 1 Loop While (Module2.CheckColony(row, colony, colonyColumn)) ' Loops whilst in the same colony. row = startRow Next column ' Move to next column of a particular locus. AlleleSet = alleleArray sizeOfAlleleSet = UBound(AlleleSet) ' Stores the number of elements in the allele set (ie: its size). End Function ' Function Name: Combinations() ' Parameters Byval: AlleleSet ' Return type: Array ' Description: Determines all the possible allele combinations based on the AlleleSet. Public Function Combinations(ByVal AlleleSet) ' [DECLARE VARIABLES] Dim combinationsArray() As Variant Dim count As Integer, counter As Integer, pivot As Integer ' [INITIALISE VARAIBLES] ' The ReDim statement sets dimensions of the array. The dimensions are easily found ' by noticing that the maximum number of combinations achieved by fixing the first allele ' and varing the second, is one less than the size of the allele set. ReDim combinationsArray((UBound(AlleleSet) - 1), (UBound(AlleleSet) - 1), 2) pivot = 1 For count = 1 To (UBound(AlleleSet) - 1) ' Iterates for the first dimension of the combinationsArray. For counter = 1 To (UBound(AlleleSet) - 1) ' Iterates for the second dimension of the combinationsArray. If ((count + counter) > sizeOfAlleleSet) Then Exit For Else combinationsArray(count, counter, pivot) = AlleleSet(count) ' Store values in array. combinationsArray(count, counter, pivot + 1) = AlleleSet(count + counter) End If Next counter Next count Combinations = combinationsArray End Function ' Subroutine Name: OneOfTwoAlleles() ' Parameters Byval: Combinations, row, leftColumn, rightColumn, colonyNum, lociNum ' Description: Determines the queen's genotype at a particular locus, based on the presence ' of either one of two alleles being present in each indiviual worker of the colony. Public Sub OneOfTwoAlleles(ByVal Combinations, ByVal row, ByVal leftColumn, ByVal rightColumn, ByVal colonyNum, ByVal lociNum) ' [DECLARE VARIABLES] Dim allele1 As Variant, allele2 As Variant, colony As Variant Dim saveCombination(1, 2) As Variant, skipArray() As Variant Dim colonyColumn As Integer, startRow As Integer, iterator As Integer Dim count As Integer, counter As Integer, record As Integer, pivot As Integer Dim present As Boolean, answer As Boolean ' [INITIALISE VARAIBLES] colonyColumn = 1 ' Corresponds to column A. Ie: where the user enters the colony names. colony = ActiveSheet.Cells(row, colonyColumn).Value ' Retrieves the first colony name. count = 1 counter = 1 startRow = row ' Assigns the value of the parameter "row" to startRow. record = 1 pivot = 1 ' The following two lines retrieve the first allele combination to be tested for the case where ' the Queen is heterozygous and 1 of 2 alleles is present in every worker sampled (within ' a single colony). saveCombination(1, 1) = Combinations(count, counter, pivot) saveCombination(1, 2) = Combinations(count, counter, pivot + 1) Do Do present = False ' Default setting which says that a specific combination is not present in every worker sampled. allele1 = ActiveSheet.Cells(row, leftColumn).Value ' Retrieve allele value. allele2 = ActiveSheet.Cells(row, rightColumn).Value If ((allele1 = allele2) And (allele1 = ".")) Then row = row + 1 ' Skip a null result. Else ' IF-statement tests whether the current test combination is valid for the i-th individal. If ((allele1 = Combinations(count, counter, pivot)) Or (allele1 = Combinations(count, counter, pivot + 1))) Then present = True ElseIf ((allele2 = Combinations(count, counter, pivot)) Or (allele2 = Combinations(count, counter, pivot + 1))) Then present = True End If If (present) Then row = row + 1 ' Test combination was valid. Test again on the (i + 1)th worker. If (present = False) Then ' Test combination is not valid for the i-th worker. NextCombination: counter = counter + 1 If ((count + counter) > sizeOfAlleleSet) Then ' Determines when to jump to the next group of possible combinations. If count <= (sizeOfAlleleSet - 2) Then ' Ensures that the subcripts stay within the valid dimesions of the combinations array. count = count + 1 counter = 1 saveCombination(1, 1) = Combinations(count, counter, pivot) ' Move to next combination to be tested. Else Exit Do End If End If saveCombination(1, 2) = Combinations(count, counter, pivot + 1) ' The following For-Loop enables EzyMate to skip possible "1 of 2 allele" scenarios that ' fail the statistical test. For iterator = 1 To (record - 1) If ((saveCombination(1, 1) = skipArray(1, iterator)) And (saveCombination(1, 2) = skipArray(2, iterator))) Then GoTo NextCombination End If Next iterator row = startRow End If End If Loop While (CheckColony(row, colony, colonyColumn)) answer = CheckAnswer(leftColumn, rightColumn, colonyNum, saveCombination, skipArray, record) ' Statistical test. If (answer = False) Then ' [RE-INITIALISE VARIABLES]. count = 1 counter = 1 row = startRow End If Loop While (answer = False) Call Choice(lociNum, saveCombination) End Sub ' Function Name: CheckAnswer() ' Parameters Byval: leftColumn, rightColumn, colonyNum, saveCombinations ' Parameters by reference: skipArray, record ' Return type: Boolean ' Description: Statistically Checks the output of HeterozygousQueen(). Private Function CheckAnswer(ByVal leftColumn, ByVal rightColumn, ByVal colonyNum, ByVal saveCombination, skipArray, record) As Boolean ' [DECLARE VARIABLES] Dim allele1 As Variant, allele2 As Variant, colony As Variant Dim row As Integer, numOfOccurance As Integer, colonyColumn As Integer, pivot As Integer Dim answer As Double ' [INITIALISE VARAIBLES] numOfOccurance = 0 row = 2 pivot = 1 colonyColumn = 1 colony = ActiveSheet.Cells(row, colonyColumn).Value CheckAnswer = True ' Possible "1 of 2" allele case is correct. Do allele1 = ActiveSheet.Cells(row, leftColumn).Value allele2 = ActiveSheet.Cells(row, rightColumn).Value If ((saveCombination(1, 1) = allele1) And (saveCombination(1, 2) <> allele2)) Then numOfOccurance = numOfOccurance + 1 ElseIf ((saveCombination(1, 2) <> allele1) And (saveCombination(1, 1) = allele2)) Then numOfOccurance = numOfOccurance + 1 End If row = row + 1 Loop While (Module2.CheckColony(row, colony, colonyColumn)) answer = numOfOccurance / endColony(colonyNum) ' Ratio of alleles. Select Case (answer) ' Looks for an approx. 50:50 ratio between maternal alleles. Case Is < 0.45: CheckAnswer = False Case Is > 0.55: CheckAnswer = False End Select ' Adds those combinations that may match the "1 of 2" allele case, but fail the statisic test, to the ' skip array. Thus future combinations containing those elements are immediately known to be wrong and ' are not checked again by EzyMate - saving run time. If (CheckAnswer = False) Then ReDim Preserve skipArray(2, record) skipArray(pivot, record) = saveCombination(1, 1) skipArray(pivot + 1, record) = saveCombination(1, 2) record = record + 1 End If End Function ' Subroutine Name: Choice() ' Parameters Byval: lociNum, saveCombinations ' Description: Determines which allele to add to the queen's genotype. Private Sub Choice(ByVal lociNum, ByVal saveCombination) ' [DECLARE VARIABLES] Dim alleleNum As Integer ' [INITIALISE VARAIBLES] alleleNum = 1 ' The IF-statement simply determines which allele to save to the Queen's genotype, and which ' position of the array to store it in. If (queenArray(lociNum, alleleNum) = saveCombination(1, 1)) Then queenArray(lociNum, alleleNum + 1) = saveCombination(1, 2) ElseIf (queenArray(lociNum, alleleNum + 1) = saveCombination(1, 1)) Then queenArray(lociNum, alleleNum) = saveCombination(1, 2) ElseIf (queenArray(lociNum, alleleNum) = saveCombination(1, 2)) Then queenArray(lociNum, alleleNum + 1) = saveCombination(1, 1) Else queenArray(lociNum, alleleNum) = saveCombination(1, 1) End If End Sub