-2

The following code comes from an example on http://cars9.uchicago.edu/software/python/lmfit/parameters.html.

from lmfit import minimize, Minimizer, Parameters, Parameter, report_fit
import numpy as np
# create data to be fitted
x = np.linspace(0, 15, 301) 
data = (5. * np.sin(2 * x - 0.1) * np.exp(-x*x*0.025) +
np.random.normal(size=len(x), scale=0.2) )
# define objective function: returns the array to be minimized
def fcn2min(params, x, data):
    """ model decaying sine wave, subtract data"""
    amp = params['amp']
    shift = params['shift']
    omega = params['omega']
    decay = params['decay']
    model = amp * np.sin(x * omega + shift) * np.exp(-x*x*decay)
    return model - data
# create a set of Parameters
params = Parameters()
params.add('amp', value= 10, min=0)
params.add('decay', value= 0.1)
params.add('shift', value= 0.0, min=-np.pi/2., max=np.pi/2)
params.add('omega', value= 3.0)
# do fit, here with leastsq model
minner = Minimizer(fcn2min, params, fcn_args=(x, data))
result = minner.minimize()
# calculate final result
final = data + result.residual
# write error report
report_fit(result)
# try to plot results
try:
    import pylab
    pylab.plot(x, data, 'k+')
    pylab.plot(x, final, 'r')
    pylab.show()
except:
    pass

I tried to run this code in Canopy. When using Canopy 64 bit for Python 3.5 it ran fine. I need to use it in Canopy 32 using Python 2.7. When I changed to use the other editor, it no longer worked. Here is the issue it gives me:

     13     omega = params['omega']
     14     decay = params['decay']
---> 15     model = amp * np.sin(x * omega + shift) * np.exp(-x*x*decay)
     16     return model - data
     17 # create a set of Parameters
AttributeError: 'numpy.float64' object has no attribute 'sin' 

I am confused because the only thing I changed is the version of Python and the version of Canopy. Could this be caused by difference between Python 2.7 and Python 3.5?

kotval
  • 120
  • 2
  • 10
  • 4
    Could you insert `print(type(np))` after the `decay = ...` line and report the output? – hilberts_drinking_problem Aug 01 '17 at 18:53
  • 6
    I doubt it. This error implies that `np` is bound to a `numpy.float64` object. Do you assign to `np = ` somehwere? – juanpa.arrivillaga Aug 01 '17 at 18:53
  • @YakymPirozhenko the result of `print(type(np))` after `decay = ...` was `` – kotval Aug 01 '17 at 18:58
  • @juanpa.arrivillaga I did not assign `np` anywhere. The only code is that which is shown above. – kotval Aug 01 '17 at 18:58
  • 1
    How, exactly, are you running this? – juanpa.arrivillaga Aug 01 '17 at 19:00
  • @juanpa.arrivillaga In the Enthought Canopy 32 bit editor. – kotval Aug 01 '17 at 19:01
  • 1
    **How exactly**? In an interactive interpreter session? – juanpa.arrivillaga Aug 01 '17 at 19:03
  • 1
    @juanpa.arrivillaga I am running it by saving it as test.py and then running `python test.py` in the Canopy Command Prompt. Further version information: `Welcome to Canopy's interactive data-analysis environment! Type '?' for more information. Python 2.7.13 |Enthought, Inc. (x86)| (default, Mar 2 2017, 16:00:27) [MSC v.1500 32 bit (Intel)]` – kotval Aug 01 '17 at 19:13
  • The issue is not what `np` is, but that the argument has become an object array. A simple testcase is `np.sin([np.float64(2), None])`, which gives the same error – Eric Aug 01 '17 at 21:44
  • Can you print out `x * omega + shift`? – Eric Aug 01 '17 at 21:48
  • @Eric printing `x * omega + shift` gives `[0.0 0.15000000000000002 0.30000000000000004 0.45000000000000007 0.60000000000000009 0.75 0.90000000000000013 1.05 1.2000000000000002 1.3500000000000001 1.5 1.6500000000000001 1.8000000000000003 1.9500000000000002 2.1000000000000001 2.25 2.4000000000000004 ....... 43.350000000000001 43.5 43.650000000000006 43.800000000000004 43.950000000000003 44.100000000000001 44.25 44.400000000000006 44.550000000000004 44.700000000000003 44.850000000000001 45.0]` – kotval Aug 02 '17 at 00:18
  • Somewhere in your code (not showing above) you are shadowing `np`. This is, `np` is no longer the `numpy` module, but you are assigning a `numpy.float64` to `np` at somepoint in your code. – Imanol Luengo Aug 02 '17 at 07:24
  • @Imanol: you're misdiagnosing - see my above comment. – Eric Aug 05 '17 at 16:29
  • @kotval: what is the `type(...)` and `(...).dtype` of that result? – Eric Aug 05 '17 at 16:30

1 Answers1

1

Please verify the version of lmfit being used for each version of Python. Prior to lmfit version 0.9.4, you would need to use amp = params['amp'].value (and so on: param.value for all parameters).

That is, params['amp'] is an instance of an lmfit.Parameter -- it has several attributes, including .value holding it's floating point valuepy. It was only with version 0.9.4 that automatic coercion to numpy arrays became possible.

M Newville
  • 7,486
  • 2
  • 16
  • 29