# A simple calculator to calculate the frequency of a recessive allele

It's based on the Hardy-Weinberg formula. I used the easygui module because I don't fully understand events in Tkinter yet. It's my first relatively useful script so any constructive criticism would be helpful.

``````from __future__ import division
import sys
from easygui import *
def calculate_frequency(recessive,total):
q = (recessive/total)**0.5 #square root of q^2
p = 1-q #since p + q = 1, p = 1-q
hzDominantNum = round((p**2)*total,2) #number of homozygous dominant, not percent
hzRecessiveNum = round((q**2)*total,2)
heterozygousNum = round((2*p*q)*total,2)
hzDominantFreq = round((p**2)*100,2) #frequency (percent)
hzRecessiveFreq = round((q**2)*100,2)
heterozygousFreq = round((2*p*q)*100,2)
return hzDominantNum,hzRecessiveNum,heterozygousNum,hzDominantFreq,hzRecessiveFreq,heterozygousFreq #returns all calculations to be printed
while True: #loops program until terminated
msg = "Leave Total as 100 if you want to enter the percent." #main message lets user know how to input as percent
fieldNames = ["How many have the recessive trait","Total population"]
fieldValues = ['',100] #first one is blank, the second is defaulted to 100 to make inputing percents easier
test = 0 #tests if the proper information has been entered. Test will equal 1 if the conditions are met.
while test == 0:
fieldValues = multenterbox(msg=msg, title='Enter information about the population', fields=fieldNames, values=fieldValues)
if fieldValues == None: sys.exit() #None is returned when the user clicks "Cancel"
elif not fieldValues[0].isdigit() or not fieldValues[1].isdigit():
if not ccbox("Please fill out all fields.",'ERROR',('OK','Quit')): sys.exit()
elif int(fieldValues[0])>int(fieldValues[1]):
if not ccbox("The amount of people with the recessive trait can't be bigger than the total population.",'ERROR',('OK','Quit')): sys.exit()
else: test=1
recessive = int(fieldValues[0])
total = int(fieldValues[1])

hzDominantNum,hzRecessiveNum,heterozygousNum,hzDominantFreq,hzRecessiveFreq,heterozygousFreq = calculate_frequency(recessive,total)
#displays all the information
msg = str(hzDominantNum)+'/'+str(total)+' ('+str(hzDominantFreq)+'%) are normal (homozygous dominant).\n'+'''
'''+str(heterozygousNum)+'/'+str(total)+' ('+str(heterozygousFreq)+'%) are carriers (heterozygous).\n'+'''
'''+str(hzRecessiveNum)+'/'+str(total)+' ('+str(hzRecessiveFreq)+'%) have the recessive trait (homozygous recessive).'
#sees if user wants to quit or continue
if not ccbox(msg=msg, title='RESULTS', choices=('Continue', 'Quit'), image=None): sys.exit()
``````
-

Some suggestions:

• call variables `this_way` not `thisWay`
• put your interaction with user into separate functions
• if code will be splited properly you will be able to user `return` and `while True:` instead of `test` variable
• return object or dict from `calculate_frequency` rather than long tuple
• don't create strings like that:

str(hzDominantNum)+'/'+str(total)+' ('+str(hzDominantFreq)+'%) are normal (homozygous dominant).\n'

this is mutch better:

``````'%f/%f (%d%%) are normal (homozygous dominant).\n' % (hzDominantNum, total, hzDominantFreq)
``````

if you have to run this as a program do it this way:

``````def main():
print "test"

if __name__ == "__main__":
main()
``````
-
Good advice. What exactly is the purpose of adding a main loop if I want to run it as a program? –  nagasgura Aug 21 '12 at 0:21
that's not a main loop, but the `if __name__ == "__main__":` entrypoint is used so that you can also reuse `module.calculate_frequency` from another file later if you want to; this also makes it much easier to write unit tests –  Useless Aug 21 '12 at 13:47
`1 + 1` and not `1+1`
`value, value` and not `value,value`