I have been trying endlessly to figure out why the variable c in the program below is not been returned. Rather, I was getting an error that says NameError: name 'c' is not defined. I have searched for solutions online, including here, but no answer offered a desirable solution yet. How can I print the content of *c *? Any assistance from you will be much appreciated. Thanks.
# obs=observation, p=model data, s=projected data
def bias_correction(obs, p, s, method='delta', nbins=10, extrapolate=None):
if (method == 'eqm') and (nbins > 1):
binmid = np.arange((1./nbins)*0.5, 1., 1./nbins)
qo = mquantiles(obs[np.isfinite(obs)], prob=binmid)
qp = mquantiles(p[np.isfinite(p)], prob=binmid)
p2o = interp1d(qp, qo, kind='linear', bounds_error=False)
c = p2o(s)
if extrapolate is None:
c[s > np.max(qp)] = qo[-1]
c[s < np.min(qp)] = qo[0]
elif extrapolate == 'constant':
c[s > np.max(qp)] = s[s > np.max(qp)] + qo[-1] - qp[-1]
c[s < np.min(qp)] = s[s < np.min(qp)] + qo[0] - qp[0]
elif method == 'delta':
c = obs + (np.nanmean(s) - np.nanmean(p))
elif method == 'scaling_add':
c = s - np.nanmean(p) + np.nanmean(obs)
elif method == 'scaling_multi':
c = (s/np.nanmean(p)) * np.nanmean(obs)
else:
raise ValueError("incorrect method, choose from 'delta', 'scaling_add', 'scaling_multi' or 'eqm'")
return c # c is the bias-corrected series for s
Here is the image of the full error message.
Thank you all for your kind responses. Fortunately, a friend just helped me figure it out now, and I taught I should share it.
C is from a function, so it is an output term of the function. It isn't a standalone variable.So I need to run the function to produce the output
Here is what I ran that produced my desired output.
obs = ref_sliced.tmp
p = mod_interp.tmp
s = future_interp.tmp
bias_correction(obs, p, s, method='delta',
nbins=10, extrapolate=None)
Related
I've been playing around with sympy and decided to make an arbitrary equations solver since my finance class was getting a little dreary. I wrote a basic framework and started playing with some examples, but some work and some don't for some reason.
from sympy import *
import sympy.mpmath as const
OUT_OF_BOUNDS = "Integer out of bounds."
INVALID_INTEGER = "Invalid Integer."
INVALID_FLOAT = "Invalid Float."
CANT_SOLVE_VARIABLES = "Unable to Solve for More than One Variable."
CANT_SOLVE_DONE = "Already Solved. Nothing to do."
# time value of money equation: FV = PV(1 + i)**n
# FV = future value
# PV = present value
# i = growth rate per perioid
# n = number of periods
FV, PV, i, n = symbols('FV PV i n')
time_value_money_discrete = Eq(FV, PV*(1+i)**n)
time_value_money_continuous = Eq(FV, PV*const.e**(i*n))
def get_sym_num(prompt, fail_prompt):
while(True):
try:
s = input(prompt)
if s == "":
return None
f = sympify(s)
return f
except:
print(fail_prompt)
continue
equations_supported = [['Time Value of Money (discrete)', [FV, PV, i, n], time_value_money_discrete],
['Time Value of Money (continuous)',[FV, PV, i, n], time_value_money_continuous]]
EQUATION_NAME = 0
EQUATION_PARAMS = 1
EQUATION_EXPR = 2
if __name__ == "__main__":
while(True):
print()
for i, v in enumerate(equations_supported):
print("{}: {}".format(i, v[EQUATION_NAME]))
try:
process = input("What equation do you want to solve? ")
if process == "" or process == "exit":
break
process = int(process)
except:
print(INVALID_INTEGER)
continue
if process < 0 or process >= len(equations_supported):
print(OUT_OF_BOUNDS)
continue
params = [None]*len(equations_supported[process][EQUATION_PARAMS])
for i, p in enumerate(equations_supported[process][EQUATION_PARAMS]):
params[i] = get_sym_num("What is {}? ".format(p), INVALID_FLOAT)
if params.count(None) > 1:
print(CANT_SOLVE_VARIABLES)
continue
if params.count(None) == 0:
print(CANT_SOLVE_DONE)
continue
curr_expr = equations_supported[process][EQUATION_EXPR]
for i, p in enumerate(params):
if p != None:
curr_expr = curr_expr.subs(equations_supported[process][EQUATION_PARAMS][i], params[i])
print(solve(curr_expr, equations_supported[process][EQUATION_PARAMS][params.index(None)]))
This is the code I have so far. I guess I can strip it down to a basic example if need be, but I was also wondering if there was a better way to implement this sort of system. After I have this down, I want to be able to add arbitrary equations and solve them after inputting all but one parameter.
For example, if I put in (for equation 0), FV = 1000, PV = 500, i = .02, n is empty I get 35.0027887811465 which is the correct answer. If I redo it and change FV to 4000, it returns an empty list as the answer.
Another example, when I input an FV, PV, and an n, the program seems to hang. When I input small numbers, I got RootOf() answers instead of a simple decimal.
Can anyone help me?
Side note: I'm using SymPy 0.7.6 and Python 3.5.1 which I'm pretty sure are the latest
This is a floating point accuracy issue. solve by default plugs solutions into the original equation and evaluates them (using floating point arithmetic) in order to sort out false solutions. You can disable this by setting check=False. For example, for Hugh Bothwell's code
for fv in range(1870, 1875, 1):
sols = sp.solve(eq.subs({FV:fv}), check=False)
print("{}: {}".format(fv, sols))
which gives
1870: [66.6116466112007]
1871: [66.6386438584579]
1872: [66.6656266802551]
1873: [66.6925950919998]
1874: [66.7195491090752]
I don't have an answer, but I do have a much simpler demonstration case ;-)
import sympy as sp
FV, n = sp.symbols("FV n")
eq = sp.Eq(FV, sp.S("500 * 1.02 ** n"))
# see where it breaks
for fv in range(1870, 1875, 1):
sols = sp.solve(eq.subs({FV:fv}))
print("{}: {}".format(fv, sols))
which produces
1870: [66.6116466112007]
1871: [66.6386438584579]
1872: []
1873: []
1874: []
At a guess this is where the accuracy breaks down enough that it can't find a verifiable solution for n?
Also, while poking at this I did a fairly extensive rewrite which you may find useful. It does pretty much the same as your code but in a much more loosely-coupled fashion.
import sympy as sp
class Equation:
def __init__(self, label, equality_str, eq="=="):
self.label = label
# parse the equality
lhs, rhs = equality_str.split(eq)
self.equality = sp.Eq(sp.sympify(lhs), sp.sympify(rhs))
# index free variables by name
self.vars = {var.name: var for var in self.equality.free_symbols}
def prompt_for_values(self):
# show variables to be entered
var_names = sorted(self.vars, key=str.lower)
print("\nFree variables are: " + ", ".join(var_names))
print("Enter a value for all but one (press Enter to skip):")
# prompt for values by name
var_values = {}
for name in var_names:
value = input("Value of {}: ".format(name)).strip()
if value:
var_values[name] = sp.sympify(value)
# convert names to Sympy variable references
return {self.vars[name]:value for name,value in var_values.items()}
def solve(self):
values = self.prompt_for_values()
solutions = sp.solve(self.equality.subs(values))
# remove complex answers
solutions = [sol.evalf() for sol in solutions if sol.is_real]
return solutions
def __str__(self):
return str(self.equality)
# Define some equations!
equations = [
Equation("Time value of money (discrete)", "FV == PV * (1 + i) ** n"),
Equation("Time value of money (continuous)", "FV == PV * exp(i * n)" )
]
# Create menu
menu_lo = 1
menu_hi = len(equations) + 1
menu_prompt = "\n".join(
[""]
+ ["{}: {}".format(i, eq.label) for i, eq in enumerate(equations, 1)]
+ ["{}: Exit".format(menu_hi)]
+ ["? "]
)
def get_int(prompt, lo=None, hi=None):
while True:
try:
value = int(input(prompt))
if (lo is None or lo <= value) and (hi is None or value <= hi):
return value
except ValueError:
pass
def main():
while True:
choice = get_int(menu_prompt, menu_lo, menu_hi)
if choice == menu_hi:
print("Goodbye!")
break
else:
solutions = equations[choice - 1].solve()
num = len(solutions)
if num == 0:
print("No solutions found")
elif num == 1:
print("1 solution found: " + str(solutions[0]))
else:
print("{} solutions found:".format(num))
for sol in solutions:
print(sol)
if __name__ == "__main__":
main()
Below is my code for a barcode generator for dna sequencing. When I enter nothing for the mingc and max gc, the interpreter does not give any results. Did I use the correct format, ex. if mincg ='': etc.
import random
nucl_list = ['A', 'C', 'G', 'T']
length = 10
print '\nEnter desired GC content range in percentages (i.e. 50 ->50%)'
# ask for desired GC content range
mingc = raw_input("Minimum GC content (default is 40):")
if mingc == '':
mingc = 40
else:
mingc = float(mingc) / 100
maxgc = raw_input("Maximum GC content (default is 60):")
if maxgc == '':
maxgc = 60
else:
maxgc = float(maxgc) / 100
def gc_cont(barcode):
gc = 0.0
for base in range(length):
if barcode[base] == 'C' or barcode[base] == 'G':
gc += 1
else:
gc += 0
cont = gc / length
return cont
barcode = ''
while barcode == '':
for i in range(length):
barcode += random.choice(nucl_list)
#print barcode
if maxgc >= gc_cont(barcode) >= mingc:
bar_code = barcode
print bar_code
else:
barcode = ''`enter code here`
You did use the right format here (although it's often more Pythonic to use if not mingc: than if mingc == '':).
If you want to see that for yourself, you can put a print "inside if" in the if statement, or print repr(mingc) to verify that it shows what you expected, or just print mingc after the if/else to see that the code you expected was executed, or run it in the debugger. It's worth learning how to do that.
But anyway, that's not your problem here. Your problem is that you put the wrong code inside the if body. Compare:
if maxgc == '':
maxgc = 60
else:
maxgc = float(maxgc) / 100
So, if the user types 60, you're going to set maxgc to float(60) / 100, or 0.6.
But if the user just hits enter to get the default, he doesn't get 0.6, he gets 60.
I had this working and now I cannot figure out what I did to make it not function the way I intend it to. When the program is called by the pyshell it asks the questions as it is supposed to but when the reply is given this is where it loses it mind. It was working and would call the function I have defined but now it will not do so.
I might just redefine the responses to use numbers instead of strings to make it easier and faster to complete the entries, but at the moment it is not working so there is no point in doing that until I can get it figured out.
The error is in the run_time() section, it is not calling the function as it should be, I might be missing something. I want it to call the function when the proper response is given.
I did try:
k = (query())
f = function_list[k]
f()
This did not worth either, so I am stuck. I appreciate any help.
def f_to_c():
temp = int(input("How warm is it out?"))
f_or_c = str(input("Is it C or F?"))
if f_or_c == 'c' or f_or_c == 'C':
updatedtemp = float(temp * 9 / 5 + 32)
print (updatedtemp, 'F')
elif f_or_c == 'f' or f_or_c == 'F':
updatedtemp = float((temp - 32) * 5 / 9)
print (updatedtemp, 'C')
def calc_trapezoid_area():
height = float(Input('What is the height of the trapezoid?'))
length1 = float(Input('What is the length of the bottom base?'))
length2 = float(Input('What is the length of the top base?'))
formula = float((1 / 2 * (length1 + length2)) * height)
print ("The area of the trapezoid is:", (formula))
def cal_circle():
pi = float(245850922 / 78256779)
rad_or_diam = str(input('Diameter or Radius?'))
width = float(input('What is the %s of your Circle?' % rad_or_diam))
if rad_or_diam == 'r' or rad_or_diam == 'R':
print (float(pi * width ** 2))
elif rad_or_diam == 'd' or rad_or_diam == 'D':
print (float(pi * width))
def query():
query = str(input('What would you like to calculate? Degrees, Trapezoids, or Circles?')).lower
function_list = {
"degrees": f_to_c,
"trapezoids": calc_trapezoid_area,
"circles": cal_circle
}
def run_time():
try:
f = function_list[query()]
f()
except KeyError:
print ("You messed up!")
if __name__ == '__main__':
while True:
run_time()
x = str(input('True or False?'))
if x == 'True':
break
There are two problems with your query function:
It doesn't return anything; and
It doesn't call lower.
Instead, try:
def query():
prompt = 'What would you like to calculate? Degrees, Trapezoids, or Circles?'
return input(prompt).lower()
Note the following:
input already returns a string, no need to call str();
You need to explicitly return the value; and
Parentheses () are required to actually call lower, otherwise you return the method itself.
Also, in f_to_c, "flaot" != "float".
Finally, you could improve your run_time function, minimising the amount of code in the try block:
try:
f = function_list[query()]
except KeyError:
print ("You messed up!")
else:
f()
This prevents a KeyError from f() being accidentally silenced.
I need to code a program that can get values from this
Very interesting question. Actually, in your case, it is very simple. You can parse the entire source string with ast module, like this
import ast
import operator
functions = {
"add": operator.add,
"abs": operator.abs,
"multiply": operator.mul
}
def recursive_evaluation(current_element):
if isinstance(current_element, ast.Module):
return recursive_evaluation(current_element.body[0].value)
elif isinstance(current_element, ast.Call):
function = functions[current_element.func.id]
args = [recursive_evaluation(item) for item in current_element.args]
return function(*args)
elif isinstance(current_element, ast.Num):
return current_element.n
else:
raise ValueError("Unknown Element " + str(current_element))
source = "abs(add(add(9465,38),multiply(add(63303,146),46)))"
print recursive_evaluation(ast.parse(source))
source = "add(1, -2)"
print recursive_evaluation(ast.parse(source))
source = "abs(add(1, -2))"
print recursive_evaluation(ast.parse(source))
Output
2928157
-1
1
Interesting problem, here is a potential solution. No doubt you could make a much more elegant solution using libraries or lambdas etc. as thefourtheye did in their answer, but this seems to work.
I have done a few test cases at the bottom, set the global verbose to True if you want debug info:
# globals
verbose = False # set to True if you want debug info printed
max_iter = 1000 # this stops infinate loops incase the code does not allow for some input
def solve(problem_str):
def multiply(arg_list):
x = 1
for i in arg_list:
x *= i
return x
def find_innermost(x_str):
a, b, c, i = [0], [0], 0, 0
while True:
i += 1
start = a[-1]+1
a.append(x_str.find('(', start)) # find next (
b.append(x_str.find(',', start)) # find next ,
c = x_str.find(')', start) # find next )
if (a[-1] > c) or (a[-1] == -1):
if (b[-2] > a[-3]) and (b[-2] < a[-2]):
return x_str[b[-2]+1:c+1]
else:
return x_str[a[-3]+1:c+1]
if i >= max_iter:
raise Exception("Infinite loop")
def do_sum(x_str):
args = [int(x) for x in x_str[x_str.find('(')+1:x_str.find(')')].split(',')]
task = x_str[:3].lower()
if task == 'add':
return sum(args)
elif task == 'sub':
return args[0] - sum(args[1:])
elif task == 'abs':
return abs(args.pop())
elif task == 'mul':
return multiply(args)
else:
print x_str + ': Task not recognised, please modify program or input'
raise Exception("Invalid input")
i = 0
while True:
i += 1
if verbose: print 'debug: problem_str:', problem_str
if problem_str.count('(') > 1:
x_str = find_innermost(problem_str)
else:
x_str = problem_str
if verbose: print '.'*6, 'x_str:\t', x_str
x = do_sum(x_str)
if verbose: print '.'*6, 'x:\t', x, '\n'
problem_str = problem_str.replace(x_str, str(x))
if problem_str.count('(') == 0:
return int(problem_str)
if i >= max_iter:
raise Exception("Infinite loop")
if __name__ == '__main__':
p1 = 'abs(add(add(9465,38),multiply(add(63303,146),46)))'
p2 = 'abs(add(multiply(95,multiply(-1,multiply(13,18875))),multiply(-1,add(18293,26))))'
p3 = 'abs(add(subtract(add(add(151,26875),122),254),subtract(237,multiply(-1,56497))))'
r1, r2, r3 = solve(p1), solve(p2), solve(p3)
print 'p1 evaluates to:', r1
print 'p2 evaluates to:', r2
print 'p3 evaluates to:', r3
Let me know if you have any questions about the code.
So i wrote this code and it passes the first test case, and fails all the rest. However, I can't seem to find an input that breaks it. Maybe it's because I've been staring at the code too long, but i would appreciate any help.
The algorithm uses two priority queues for the smallest and largest halves of the current list. Here's the code:
#!/bin/python
import heapq
def fix(minset, maxset):
if len(maxset) > len(minset):
item = heapq.heappop(maxset)
heapq.heappush(minset, -item)
elif len(minset) > (len(maxset) + 1):
item = heapq.heappop(minset)
heapq.heappush(maxset, -item)
N = int(raw_input())
s = []
x = []
for i in range(0, N):
tmp = raw_input()
a, b = [xx for xx in tmp.split(' ')]
s.append(a)
x.append(int(b))
minset = []
maxset = []
for i in range(0, N):
wrong = False
if s[i] == "a":
if len(minset) == 0:
heapq.heappush(minset,-x[i])
else:
if x[i] > minset[0]:
heapq.heappush(maxset, x[i])
else:
heapq.heappush(minset, -x[i])
fix(minset, maxset)
elif s[i] == "r":
if -x[i] in minset:
minset.remove(-x[i])
heapq.heapify(minset)
elif x[i] in maxset:
maxset.remove(x[i])
heapq.heapify(maxset)
else:
wrong = True
fix(minset, maxset)
if len(minset) == 0 and len(maxset) == 0:
wrong = True
if wrong == False:
#Calculate median
if len(minset) > len(maxset):
item = - minset[0]
print int(item)
else:
item = ((-float(minset[0])) + float(maxset[0])) / 2
if item.is_integer():
print int(item)
continue
out = str(item)
out.rstrip('0')
print out
else:
print "Wrong!"
Your original was not so legible, so first I made it object-oriented:
MedianHeapq supports methods rebalance(), add(), remove(), size(), median(). We seriously want to hide the members minset,maxset from the client code, for all sorts of sensible reasons: prevent client from swapping them, modifying them etc. If client needs to see them you just write an accessor.
We also added a __str__() method which we will use to debug visually and make your life easier.
Also added legibility changes to avoid the indexing with [i] everywhere, rename s,x arrays to op,val, add prompts on the raw_input(), reject invalid ops at the input stage.
Your actual computation of the median confuses me (when do you want float and when integer? the rstrip('0') is a bit wack), so I rewrote it, change that if you want something else.
A discussion of the algorithm is here.
Now it is legible and self-contained. Also makes it testable.
You might be making sign errors in your code, I don't know, I'll look at that later.
Next we will want to automate it by writing some PyUnit testcases. doctest is also a possibility. TBC.
Ok I think I see a bug in the sloppiness about locating the median. Remember the minset and maxset can have a size mismatch of +/-1. So take more care about precisely where the median is located.
#!/bin/python
import heapq
class MedianHeapq(object):
def __init__(self):
self.minset = []
self.maxset = []
def rebalance(self):
size_imbalance = len(self.maxset) - len(self.minset)
if len(self.maxset) > len(self.minset):
#if size_imbalance > 0:
item = heapq.heappop(self.maxset)
heapq.heappush(self.minset, -item)
#elif size_imbalance < -1:
elif len(self.minset) > (len(self.maxset) + 1):
item = heapq.heappop(self.minset)
heapq.heappush(self.maxset, -item)
def add(self, value, verbose=False):
if len(self.minset) == 0:
heapq.heappush(self.minset,-value)
else:
if value > self.minset[0]:
heapq.heappush(self.maxset, value)
else:
heapq.heappush(self.minset, -value)
self.rebalance()
if verbose: print self.__str__()
return False
def remove(self,value,verbose=False):
wrong = False
if -value in self.minset:
minset.remove(-value)
heapq.heapify(self.minset)
elif value in maxset:
maxset.remove(value)
heapq.heapify(self.maxset)
else:
wrong = True
self.rebalance()
if verbose: print self.__str__()
return wrong
def size(self):
return len(self.minset)+len(self.maxset)
def median(self):
if len(self.minset) > len(self.maxset):
item = - self.minset[0]
return int(item)
else:
item = (-self.minset[0] + self.maxset[0]) / 2.0
# Can't understand the intent of your code here: int, string or float?
if item.is_integer():
return int(item)
# continue # intent???
else:
return item
# The intent of this vv seems to be round floats and return '%.1f' % item ??
#out = str(item)
#out.rstrip('0') # why can't you just int()? or // operator?
#return out
def __str__(self):
return 'Median: %s Minset:%s Maxset:%s' % (self.median(), self.minset,self.maxset)
# Read size and elements from stdin
N = int(raw_input('Size of heap? '))
op = []
val = []
while(len(val)<N):
tmp = raw_input('a/r value : ')
op_, val_ = tmp.split(' ')
if op_ not in ['a','r']: # reject invalid ops
print 'First argument (operation) must be a:Add or r:Remove! '
continue
op.append(op_)
val.append(int(val_))
mhq = MedianHeapq()
for op_,val_ in zip(op,val): # use zip to avoid indexing with [i] everywhere
wrong = False
if op_ == 'a':
wrong = mhq.add(val_)
elif op_ == 'r':
wrong = mhq.remove(val_)
assert (mhq.size()>0), 'Heap has zero size!'
assert (not wrong), 'Heap structure is wrong!'
if not wrong:
print mhq.__str__()