Parameter user_data and Parameters.add() by reference

10 views
Skip to first unread message

Nathan Kelley-Hoskins

unread,
Jan 9, 2025, 7:40:13 AMJan 9
to lmfit-py
Hi everyone,

I've got two questions:

a) When I add stuff to a Parameter()'s user_data, it doesn't seem to stay with it when you add the parameter to a Parameters() object.  This seems like a bug? or is it intentional?  See example:

import lmfit
p1 = lmfit.Parameter( name='norm' , value=1, vary=True, user_data={'units':'photons/MeV' } )
print( 'p1.user_data:', p1.user_data )
pars = lmfit.Parameters()
pars.add( 'bkg_norm', p1 )
print( "pars['bkg_norm'].user_data:", pars['bkg_norm'].user_data )

which outputs:

p1.user_data: {'units': 'photons/MeV'}
pars['bkg_norm'].user_data: None

I kinda thought the user_data would stay with it wherever it goes?  Is there a way to make this more permanent, aside from re-adding the user_data after every Parameters.Add() call?

b) I also noticed that, when you add a Parameter() to a Parameters() object, I think its only adding a copy of the Parameter(), rather than a reference to the original Parameter()?  See example:

import lmfit
A = lmfit.Parameter( name='original' , value=1, vary=True, user_data={'units':'photons/MeV' } )
pars = lmfit.Parameters()
pars.add( 'copy', A )
print( pars['copy'] )
pars['copy'].value = 2  # we change the copy to value 2 here...
print( pars['copy'] )
print( A ) # but the original doesn't change :(

which outputs:

<Parameter 'copy', value=<Parameter 'original', value=1, bounds=[-inf:inf]>, bounds=[-inf:inf]>
<Parameter 'copy', value=2, bounds=[-inf:inf]>
<Parameter 'original', value=1, bounds=[-inf:inf]>

Is there a way to add a parameter by reference, rather than a copy?

Thanks for your help.

- Nathan

matt.n...@gmail.com

unread,
Jan 9, 2025, 11:25:30 AMJan 9
to lmfi...@googlegroups.com

Hi Nathan,

 

a) When I add stuff to a Parameter()'s user_data, it doesn't seem to stay with it when you add the parameter to a Parameters() object.  This seems like a bug? or is it intentional?  See example:

 

import lmfit
p1 = lmfit.Parameter( name='norm' , value=1, vary=True, user_data={'units':'photons/MeV' } )
print( 'p1.user_data:', p1.user_data )
pars = lmfit.Parameters()
pars.add( 'bkg_norm', p1 )
print( "pars['bkg_norm'].user_data:", pars['bkg_norm'].user_data )

 

It does seem plausible that

     pars.add( 'bkg_norm', p1 )

 

should work as you expect, but it does not.  It creates a Parameter named ‘bkg_norm’ with a *value* that is your `p1` Parameter.   Probably not what you want. It turns out that

     pars.add(p1)

 

would add that Parameter (and by reference, not making a copy), with a name of `norm`.

 

I would say that it would be OK if `Parameters.add(name, value)` check if the *value* is a Parameter, and use that, with the newly supplied name.  And use any additional keyword options to update that Parameter.

 

It would also be reasonable for `Parameter.add()` to take a `user_data` argument and use that for a newly created Parameter – it currently does not.

 

 

b) I also noticed that, when you add a Parameter() to a Parameters() object, I think its only adding a copy of the Parameter(), rather than a reference to the original Parameter()?  See example:

 

import lmfit
A = lmfit.Parameter( name='original' , value=1, vary=True, user_data={'units':'photons/MeV' } )
pars = lmfit.Parameters()
pars.add( 'copy', A )
print( pars['copy'] )
pars['copy'].value = 2  # we change the copy to value 2 here...
print( pars['copy'] )
print( A ) # but the original doesn't change :(

 

Again, currently,

     pars.add(A)

 

does not make a copy.   Now,

    pars.add(name, parameter)

 

does not make a copy either, but it does not do what you want  – it is sort of not even a good use of the API.   I am willing to say that the intent there is clear, and it should work, but it does not currently.

 

But also:  a Parameters object (and all its Parameter objects) are copied every time you do a fit.   This is a feature, and relying on Parameter identity is probably not a wise strategy

 

Hope that helps,

 

--Matt

--
You received this message because you are subscribed to the Google Groups "lmfit-py" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lmfit-py+u...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/lmfit-py/a033a500-599c-4373-8373-81bd39110856n%40googlegroups.com.

Reply all
Reply to author
Forward
0 new messages