Hi Sean,


On Fri, Nov 18, 2016 at 6:09 PM, Sean Fackler <swfackler@lbl.gov> wrote:
Dear Matt,

I’ve been fitting with Larch and found a few issues with some of the functions from code based on the example: examples/fitting/doc_example2a.lar. It’s for fitting two gaussians and an error function. Briefly, the two issues are related to fitting parameters for erf() and asymmetrical distribution functions like lognormal() or breit_wigner() not outputting results.

1. When trying to define parameters for the error function erf() in the params Group I get the following error: 

ufunc 'erf' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe’’. 




It appears to originate when minimizing and using the defined function. However if I simply define erf_cen=531 (explicit definition) and leave other definitions for erf_amp and erf_wid alone, minimize() appears to work but obviously does not fit for centering of the error function. That’s my current workaround. Any comments on this or a better solution would be appreciated. You can find the particular section of code on line 139 of the attached script where I redefine params so it “works". The attached data-set is also included so you can also see my fit.


When reporting a problem, please try to isolate the actual problem as much as possible.  Your script is too long and complex to easily read and try to debug.  It also runs for a long time.   So, I would say "your script worked" -- it ran for a while without error before I killed it.   It took me a while to figure out what precisely you were saying was not working.

I suspect that the problem is with some of the magic that makes

    p1 = pars.amp1 * gaussian(data.e, pars.cen1, pars.wid1)
    p2 = pars.amp2 * gaussian(data.e, pars.cen2, pars.wid2)
    p3 = pars.amp3 * gaussian(data.e, pars.cen3, pars.wid3)
    e1 = pars.off + pars.erf_amp * erf(pars.erf_wid * (data.e - pars.erf_cen)) 

when 'pars.erf_wid' is a Parameter object and 'data.e' is a Pandas.Series --neither of these are precisely numeric objects, and though coercion to a number works most of the time, it looks like it is not working inside the erf() function call.  I believe that if you explicitly use the 'value' attribute of the parameters, this will work better:

   e1 = pars.off + pars.erf_amp * erf(pars.erf_wid.value * (data.e - pars.erf_cen.value))

FWIW, it works for gaussian() because each function argument is really a numpy array, pandas Series, or a Parameter, but with erf() the argument is a pandas.Series (or numpy array) of object type.

I believe these coercion issues are fixed in lmfit (which started as a side-project of Larch, has taken on a life of its own).  In fact, the basic fitting and lineshapes thing in Larch should just be replaced with lmfit.   More people are using this so it's gotten far ahead of Larch especially for fitting data to sums of lineshapes.    The Peak Fitting GUI I'm working on uses Larch for much of the processing, but lmfit for the actual fitting -- I'm hoping to get a first-release of this out soon.   You might find lmfit somewhat easier to work with than Larch fitting too...

Anyway, the short answer is: try using "pars.PAR.value" instead of "pars.PAR" if you run into trouble -- that will really be a float, not some Parameter object that tries to act like a float.
 
--Matt Newville <newville at cars.uchicago.edu> 630-252-0431