I'm using a dictionary's get() method to choose a case based on a variable key value. Problem is, it keeps choosing the wrong case for the key. I'm not sure if I'm using the right words to explain it, but the code should make it clear enough.
di_eqns = {"PSME": Pred_PSME(liLn), "ABAM":Pred_ABAM(liLn), \
"ABCO":Pred_Abies(liLn), "ABGR":Pred_Abies(liLn), \
"ABLA":Pred_Abies(liLn), "ABMA":Pred_Abies(liLn), \
"ABSH":Pred_Abies(liLn), "ABPR":Pred_ABPR(liLn), \
"CADE27":Pred_Cedar(liLn), "CHLA":Pred_Cedar(liLn), \
"CHNO":Pred_Cedar(liLn), "THPL":Pred_Cedar(liLn), \
"LALY":Pred_LALY(liLn), "LAOC":Pred_LAOC(liLn), \
"PIEN":Pred_PIEN(liLn), "PISI":Pred_PISI(liLn), \
"PIAL":Pred_Pinus(liLn), "PIJE":Pred_Pinus(liLn), \
"PIMO3":Pred_Pinus(liLn), "PICO":Pred_PICO(liLn), \
"PILA":Pred_PILA(liLn), "PIPO":Pred_PIPO(liLn), \
"TSHE":Pred_TSHE(liLn), "TSME":Pred_TSME(liLn), \
"JUOC":Pred_JUOC(liLn), "TABR":Pred_TSHE(liLn), \
"ALRU2":Pred_ALRU2(liLn), "ACCI":Pred_SMBGr(liLn), \
"ACGL":Pred_SMBGr(liLn), "ACMA3":Pred_ACMA3(liLn), \
"CONU4":Pred_ACMA3(liLn), "ALRH2":Pred_AACWGr(liLn), \
"SASC":Pred_AACWGr(liLn), "SALIX":Pred_AACWGr(liLn), \
"ARME":Pred_ARME(liLn), "BEPA":Pred_BEPA(liLn), \
"BEPAC":Pred_BEPA(liLn), "CHCH7":Pred_CHCH7(liLn), \
"FRLA":Pred_MHGr(liLn), "PREM":Pred_MHGr(liLn), \
"PRVI":Pred_MHGr(liLn), "PRUNU":Pred_MHGr(liLn), \
"LIDE3":Pred_LIDE3(liLn), "POBAT":Pred_POBAT(liLn), \
"POTR5":Pred_POTR5(liLn), "QUCH2":Pred_QUCH2(liLn), \
"QUGA4":Pred_QUGA4(liLn), "QUKE":Pred_QUKE(liLn), \
"UMCA":Pred_UMCA(liLn)}
try: li_pred = di_eqns.get(liLn[2])
Here is the list (a line from a text file) that the key was taken from when it went to the wrong function (it went to Pred_PSME
):
['1347189', '20571', 'PIEN', 'Picea engelmannii', 'Y', 'Y', '66.294',
'0.3452', '35.7418', '', '5.0996', '0', '1', '1.1324', '3.2803', '2.3057',
'16.7282', '5520.306', '127.30', '70.73', '92.10', '0.00', '5.68', '2.37',
'7.25', '79.16', '76.79', '290.15', '219.41', '135.37', '0.00', '0.00',
'951.78', '719.74', '259.68', '251.89', '444.05', '0.00', '0.00', '',
'12.70', '10.16', '15.24', '0.02', '0.04', '0.19', '0.19', '0.00', '0.00',
'0.42', '0.32', '0.11', '0.11\r\n']
Anyone know why this is happening and how to fix it? Let me know if there is any additional info you need. Also, I'm open to suggestions for a better name for this question.
ADDENDUM: Sorry I didn't make this question clearer originally. I'm still a beginner in python and new to Stack Overflow; I wasn't aware it was ambiguous and I was under the impression we were supposed to make our questions as concise as possible and irrelevant details were undesirable.
This is the goal of the program, to read lines from a file, each line being the measurements from a tree from one of multiple forest inventory plots, and for each line, run certain species specific equations on the tree represented by the first few values in the line, then add up the results of the equations for all the trees in each plot.
The section of code I included above reads the third value from the line, which is the species code for the tree represented in the line, and passes the line to the function that contains the specific equations for that species of tree.
Based on the answers I've gotten already, it sounds like when the dictionary definition above is read, it runs through every single function listed. I wanted something that would basically do what select case would do in other languages. I got the idea of using a dictionary and the get method from another Q&A on Stack Overflow.
I only want to run the function that matches the species code in the list of the line each time the program loops over a new line. What I've noticed happening is that it seems that this dictionary is passing lines to the wrong function because I put an error catching bit of code in the Pred_PSME
function that prints the line value when there is an error (there was also an error that kept popping up in calculating one of the equation values in Pred_PSME
, which is why I added that debugging code), and it printed the line included above.
Maybe I'm misunderstanding how the dictionary full of function names works. I guess my question would be, write code that would send the list of the elements in a line to the function that matches the species code given in liLn[2]
?
In another language you would use select case
on the value of liLn[2]
, with each case being one of the keys listed in the dictionary and the commands for each case being the commands in the functions whose names are listed in the values of the dictionary.
Here is the code that leads up to the dictionary and more context for the dictionary:
def Main():
srcf = open(bkp, 'r')
old_fcid = 0
li_fBQI = []
i = 0
for line in srcf:
liLn = line.split(',')
liLn = stripquotes(liLn)
#Check if it's the first line, if so, jump to next line.
if len(liLn) < 2: continue
if HdrLine(liLn[:2]): continue
fcid = liLn[1]
#Check line fcid against last fcid
if old_fcid != 0 and fcid != old_fcid:
#Write the FCID BQI tallies to file
Write_fBQIs(old_fcid, li_fBQI)
#Reset FCID BQI tallies
li_fBQI = []
old_fcid = fcid
#Calc BQI's for the tree
li_tBQI = BQI_Calc(liLn)
#Add tree BQI's to the FCID tallies
li_fBQI = AddBQI(li_tBQI, li_fBQI)
if i % 1000 == 0: print 'Finished line #' + str(i)
i += 1
#ADD: Write last FCID's BQI's to file
Write_fBQIs(old_fcid, li_fBQI)
srcf.close()
def BQI_Calc(liLn):
di_eqns = {"PSME": Pred_PSME(liLn), "ABAM":Pred_ABAM(liLn), \
"ABCO":Pred_Abies(liLn), "ABGR":Pred_Abies(liLn), \
"ABLA":Pred_Abies(liLn), "ABMA":Pred_Abies(liLn), \
"ABSH":Pred_Abies(liLn), "ABPR":Pred_ABPR(liLn), \
"CADE27":Pred_Cedar(liLn), "CHLA":Pred_Cedar(liLn), \
"CHNO":Pred_Cedar(liLn), "THPL":Pred_Cedar(liLn), \
"LALY":Pred_LALY(liLn), "LAOC":Pred_LAOC(liLn), \
"PIEN":Pred_PIEN(liLn), "PISI":Pred_PISI(liLn), \
"PIAL":Pred_Pinus(liLn), "PIJE":Pred_Pinus(liLn), \
"PIMO3":Pred_Pinus(liLn), "PICO":Pred_PICO(liLn), \
"PILA":Pred_PILA(liLn), "PIPO":Pred_PIPO(liLn), \
"TSHE":Pred_TSHE(liLn), "TSME":Pred_TSME(liLn), \
"JUOC":Pred_JUOC(liLn), "TABR":Pred_TSHE(liLn), \
"ALRU2":Pred_ALRU2(liLn), "ACCI":Pred_SMBGr(liLn), \
"ACGL":Pred_SMBGr(liLn), "ACMA3":Pred_ACMA3(liLn), \
"CONU4":Pred_ACMA3(liLn), "ALRH2":Pred_AACWGr(liLn), \
"SASC":Pred_AACWGr(liLn), "SALIX":Pred_AACWGr(liLn), \
"ARME":Pred_ARME(liLn), "BEPA":Pred_BEPA(liLn), \
"BEPAC":Pred_BEPA(liLn), "CHCH7":Pred_CHCH7(liLn), \
"FRLA":Pred_MHGr(liLn), "PREM":Pred_MHGr(liLn), \
"PRVI":Pred_MHGr(liLn), "PRUNU":Pred_MHGr(liLn), \
"LIDE3":Pred_LIDE3(liLn), "POBAT":Pred_POBAT(liLn), \
"POTR5":Pred_POTR5(liLn), "QUCH2":Pred_QUCH2(liLn), \
"QUGA4":Pred_QUGA4(liLn), "QUKE":Pred_QUKE(liLn), \
"UMCA":Pred_UMCA(liLn)}
try:
li_pred = di_eqns.get(liLn[2])
except:
print '\n\n', 50*'-', 'ERROR: Couldn\'t find equations for the spp',\
'code:', liLn[2]
#Calc derivative quantities
.....and the function continues from there
Here is an example of the functions listed in the dictionary. Pred_PSME is the one that I mentioned above. An error kept occuring in the stem bark (sb) calculation, so I added some debugging code, thats how I found out that it was sent the PIEN tree, which is why I started this question:
def Pred_PSME(liLn):
dbh = float(liLn[6])
fol = exp(log(float(liLn[19])) + pqty(.0627, 123))
lbr = exp((-3.6941 + 2.1382*log(dbh)) + pqty(.057, 123))
dbr = exp((-3.529 + 1.7503*log(dbh)) + pqty(.079, 85))
sw = exp(log(float(liLn[20])) + pqty(.0311, 99))
try:
sb = exp(log(float(liLn[21])) + pqty(.0324, 99))
except:
Badtree(liLn)
print dbh, liLn
ts = exp(-3.0396 + 2.5951*log(0.865 * mtd) + pqty(.0311, 99)) +\
exp(-4.3103 + 2.4300*log(0.865 * mtd) + pqty(.0324, 99))
br = lbr +dbr
agb_nf = br + sw + sb
agb = agb_nf + fol
return [fol, br, sw, sb, agb, agb_nf, ts]
def Pred_ARME(liLn):
dbh = float(liLn[6])
agb_nf = float(liLn[27]) + tvariate(57) * 1.23 * (1 + 1/60)**(1/2)
agb = agb_nf / (1 - folpct)
fol = agb - agb_nf
br = sw = sb = ts = 0
return [fol, br, sw, sb, agb, agb_nf, ts]
I hope this made things clearer. Please let me know if there are any more questions. BTW, what does everyone mean when they say "code smell"? Also, I'm having some trouble with formatting text for this site. Is there a way to ident a code block on this site 4 spaces without manually adding 4 spaces to every line? Thanks.