DPdl
DPdl

Reputation: 755

Optimization using scipy_optimize

I am trying to optimize a function using curve_fit of scipy.optimize. Here is my code.

import pandas as pd
import numpy as np
from scipy.optimize import curve_fit

xdata = [row[0] for row in pd.read_excel("C:\\Users\\310967\\Desktop\\Scholar\\Wound Chelation Draft\\ChelationFiles.xlsx", sheetname="Case2Data",skiprows=0).as_matrix()]
ydata = [row[1] for row in pd.read_excel("C:\\Users\\310967\\Desktop\\Scholar\\Wound Chelation Draft\\ChelationFiles.xlsx", sheetname="Case2Data",skiprows=0).as_matrix()]
SF = [row[4] for row in pd.read_excel("C:\\Users\\310967\\Desktop\\Scholar\\Wound Chelation Draft\\ChelationFiles.xlsx", sheetname="Case2Data",skiprows=0).as_matrix()]
uncertainty = [(np.sqrt(np.exp(np.log(a)**2)-1))*b for a,b in zip(SF, ydata)]

Tau = [0,1,5,7]



def func(x, I, E, ic1, ic2, ih1, ih2):

    def iu(t):
        return ((0.01295*np.exp(-0.645974*t))+(4.3688e-4*np.exp(-0.04251*t))+(5.642452e-5*np.exp(-0.00160863*t)))

    def ic(t,tj):
        if t > tj:
            return ic1*np.exp(-0.693/ih1*(t-tj))+ic1*np.exp(-0.693/ih1*(t-tj))
        else:
            return 0

    def listofic(t):
        list1 = []
        for tj in Tau:
            list1.append(ic(t,tj))
        return list1

    def Kj(tj):
        return iu(tj+1)*(E-1)/(ic(1,0)-iu(tj+1))

    def listofKj():
        list2 = []
        for tj in Tau:
            list2.append(Kj(tj))
        return list2

    Kjs = listofKj()

    def listofOneMinusKj(t):
        list3 = []
        for a in Tau:
            if t > a:
                value = 1-Kj(a)
            else:
                value = 1
            list3.append(value)
        return list3

    return (iu(x)*np.prod(listofOneMinusKj(x))+sum([a*b for a,b in zip(Kjs,listofic(x))]))*I


popt, pcov = curve_fit(func, xdata, ydata, sigma=uncertainty)
print(popt)

When I run the above code, I get an error stating that "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()". This is referring to the part "if t>a" in the function listofOneMinusKj(t).

However, if I run the following code, despite there being a "if t>a", the code runs like I expect it to. I was wondering what the issue is with the code above.

import numpy as np
Tau = [0,1,5,7]

def func(x, I, E, ic1, ic2, ih1, ih2):

    def iu(t):
        return ((0.01295*np.exp(-0.645974*t))+(4.3688e-4*np.exp(-0.04251*t))+(5.642452e-5*np.exp(-0.00160863*t)))

    def ic(t,tj):
        if t > tj:
            return ic1*np.exp(-0.693/ih1*(t-tj))+ic1*np.exp(-0.693/ih1*(t-tj))
        else:
            return 0

    def listofic(t):
        list1 = []
        for tj in Tau:
            list1.append(ic(t,tj))
        return list1

    def Kj(tj):
        return iu(tj+1)*(E-1)/(ic(1,0)-iu(tj+1))

    def listofKj():
        list2 = []
        for tj in Tau:
            list2.append(Kj(tj))
        return list2

    Kjs = listofKj()

    def listofOneMinusKj(t):
        list3 = []
        for a in Tau:
            if t > a:
                value = 1-Kj(a)
            else:
                value = 1
            list3.append(value)
        return list3

    return (iu(x)*np.prod(listofOneMinusKj(x))+sum([a*b for a,b in zip(Kjs,listofic(x))]))*I

print(func(1,400,12.5,0.99,0.01,0.55,10))

Upvotes: 1

Views: 78

Answers (2)

Nico Albers
Nico Albers

Reputation: 1696

Scipy Optimizes Curve Fitting Procedure tries to give the full vector of xdata into your function func. You pass that to listofOneMinusKj.

Therefore t > a (or passed as x > a) produces a vector of bools. Than the following error is triggered:

"The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"

This error occurs because you can't check if a vector of length > 1 is true. Like suggested, you could use (t > a).any() to check, if any value of t is bigger than a or (t > a).all() to check, if all values of t are bigger.

Upvotes: 2

ev-br
ev-br

Reputation: 26110

One way of debugging these sorts of issues is to throw an import pdb; pdb.set_trace() incantation just above the line the traceback points to. Then run your code, and it'll stop at the breakpoint --- and you can interactively explore various objects and step through the code. Here you'll likely find that either t or a is a numpy array when called by curve_fit, and you can't just do if array > another_array.

Upvotes: 1

Related Questions