2
\$\begingroup\$

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()
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

Some suggestions:

  • call variables this_way not thisWay
  • use less comments
  • 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()
\$\endgroup\$
2
  • \$\begingroup\$ Good advice. What exactly is the purpose of adding a main loop if I want to run it as a program? \$\endgroup\$
    – nagasgura
    Aug 21, 2012 at 0:21
  • \$\begingroup\$ 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 \$\endgroup\$
    – Useless
    Aug 21, 2012 at 13:47
1
\$\begingroup\$

Whitespace!
1 + 1 and not 1+1
value, value and not value,value

Blank lines after imports, loops, function definitions and after five lines of code without (just kidding about the latter)

Break your lines if they're getting too long (http://www.python.org/dev/peps/pep-0008/#maximum-line-length)

And generally have a look at PEP8

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.