On Wednesday 21 January 2004 12:22 pm, Daniel Carter wrote:
Dear Bruce --
I've read as much material as I can find and I can't figure out how to use the restrain parameter in the Guess, Set, Def parameters window in Artemis.
Say I want to limit Amp between 0.7 to 1.0, how do I do it? Do I use restrain or def and then what to I enter in the "Math Expressions field." I really need to find more info on what can be entered in math expr. field.
Thanks, Dan Carter Hunter College NY, NY
Dan, I trust you won't mind if I answer your question on the Ifeffit mailing list. That way others can see the question and you might hear words of wisdom from some of the gurus who hang out on the list. As to what can be entered in the math expression field, well -- just that. Any valid math expression (which can be as simple as a number or a complex combination of functions and infix binary operators) goes in there. If you "def" a parameter to be a number (e.g. def foo=5), that is the same as setting it to a number (e.g. set foo=5).. If you def a parameter to be a set parameter, i.e. set a = 5 def b = a that will, in effect, be the same as setting both a and b to 5, although deffing parameters in this way can often be a pleasant convenience at the user interface level. Things get more interesting when you start using more extensive math expressions. Take this, for example: guess a = 0 def b = abs(a) a will then float in the fit and may be positive or may be negative. b will always be positive, but its value will depend on where a ends up as a floating variable. Another example. Consider a mixed first shell with 6 atoms. Further suppose that about half of them are of atom X and the rest are atom Y. You might float an s02 variable and then use a weighting parameter to adjust the relative amounts of atoms X and Y. guess amp = 0.9 # this is our s02 parameter guess frac = 0.5 def amp_x = amp * frac def amp_y = amp * (1-frac) You would then use amp_x and amp_y as the s02 path parameters when you go define paths. In the fit, both the s02 and the mixing fraction would be determined. Alright.... that gives you some sense of the kinds of math expressions you can use. Binary operators (+ - * / ^ for addition, subtraction, multiplication, division, and exponentiation) are all available. Many functions (such as abs(), exp(), cos(), and so on) are also available. See the Ifeffit manual on Matt's web site for the full list of functions. So, finally, I am going start answering your question about getting an s02 value to come out between 0.7 and 1.0. There are two ways, constraints and restraints. You can constrain (i.e. force) that parameter to be between those values. To do this you can use the standard min/max idiom. guess a = 0.9 def b = min( max(0.7, a), 1.0 ) Deconstruct that idiom by working from the inside out. The "max(0.7, a)" part forces b to be no smaller than 0.7. If a drifts below 0.7, b will then be pegged at 0.7. The "min()" part does the same thing on the other side. If a is above 0.7, then b will equal a. But if a drifts above 1.0, then b will equal 1.0. Using a constraint is fairly simple. A bit more complicated is the use of a restraint. I trust that Matt or Scott will help me out if I mis-state anything at this point. The logic of a restraint is a bit different than a constraint. With a restraint, you want to penalize the fit if the value of the parameter drifts too far away from some acceptable value. So we will set the restraint up in this way: guess amp_guess = 0.85 set amp_target = 0.85 set scale = 100 restrain amp = abs(amp_guess - amp_target) * scale So, what does this all mean? Well, amp_guess is the floating parameter which will, well, float during the fit. amp_target is the value that you think the amplitude should be. I chose the midpoint of your range for this example. Before I explain scale and the actual restraint, let's talk about how Matt implemented restraints in Ifeffit. Ifeffit decides on its set of best-fit values by minimizing a statistical metric called chi-square. This is essentially the sum of the difference of squares between the data and the theory evaluated only over the fitting range and normalized in a way that considers the approximate amount of information left unused in the fit. The best-fit values are those that minimize chi-square. When you use a restraint, you add one more term to the quantity that is minimized during the fit. That is, the *sum* of chi-square and all of your restraints are minimized. Thus the restraint offers an incentive to the fit to meet the criteria of the restraint (or, equivalently, a penalty for not meeting the criteria), without forcing it to do so. Probably, the sum of chi-square and the restraints will be minimized when the constraint is minimized, but it is allowed for the guess parameter upon which the restraint depends to drift away from the restraining condition so long as the *sum* of chi-square and the restraint is minimized. OK? So, in the math expressions above, I have made a restraint that gives a penalty when the value of amp_guess drifts away from amp_target in either direction. The scale parameter is chosen to adjust the importance of the restraint. Since scale is a multiplicative parameter, the restraint will be more important (in the context of minimizing the sum of chi-square and the restraint) if scale is larger and the restraint will be less important if scale is smaller. How big should scale be? Well that depends on how big chi-square is for your fits and how strong of a restraint you actually want. Basically the scale parameter lets you fine tune the importance of the restraint. A word of caution. Restraints can be dangerous. Here is a quiz: Why is this definition of the restraint a bad idea? set scale = -100 restrain amp = abs(amp_guess - amp_target) * scale Finally, I never actually told you how to set up a restraint that offers no penalty if the s02 is between 0.7 and 1.0 but to start applying a penalty if it drifts out of that range. I'm leaving that as an exercise for the reader. I am doing so largely because I can't think of the answer off the top of my head. ;-) Hope that helps and don't hesitate to ask more questions on the mailing list in the future. B -- Bruce Ravel ----------------------------------- ravel@phys.washington.edu Code 6134, Building 3, Room 222 Naval Research Laboratory phone: (1) 202 767 5947 Washington DC 20375, USA fax: (1) 202 767 1697 NRL Synchrotron Radiation Consortium (NRL-SRC) Beamlines X11a, X11b, X23b National Synchrotron Light Source Brookhaven National Laboratory, Upton, NY 11973 My homepage: http://feff.phys.washington.edu/~ravel EXAFS software: http://feff.phys.washington.edu/~ravel/software/exafs/
Hi Bruce, I agree with most of your answer to Dan about setting constraints and restraints, but I think I'd fail the 'quiz' you gave:
A word of caution. Restraints can be dangerous. Here is a quiz: Why is this definition of the restraint a bad idea?
set scale = -100 restrain amp = abs(amp_guess - amp_target) * scale
where you had
guess amp_guess = 0.85 set amp_target = 0.85 set scale = 100 restrain amp = abs(amp_guess - amp_target) * scale
as a recommended way to set just such a constraint. I believe there's no difference. Am I missing something? The sign of the restraint's value won't matter, and restrain amp = 100 * (amp_guess - amp_target) would be equivalent to both of the above. The restraint's value is jsut another element of the array of 'misfit', can be negative, and the fit will attempt to bring the restraint close to zero.
Finally, I never actually told you how to set up a restraint that offers no penalty if the s02 is between 0.7 and 1.0 but to start applying a penalty if it drifts out of that range. I'm leaving that as an exercise for the reader. I am doing so largely because I can't think of the answer off the top of my head. ;-)
It's not pretty, but I think this will effectively set penalties for going above and below some value: guess target = 0.8 set lo_val = 0.7 set up_val = 1.0 set scale = 100.0 def penalty = (max((target-lo_val), abs(target-lo_val)) - min((target-up_val),-abs(target-up_val)) + lo_val - up_val)*scale This penalty could then be used as a restraint. Whereas contraints give an infinite penalty for going above some value, this allows the target value to fall outside the desired range, but gives a finite penalty that increases linearly as with 'distance' from the desired range. Setting just a lower or upper bound would go like this: lower_penalty = max((target-lo_val), abs(target-lo_val))-(target-lo_val) upper_penalty = -min((target-up_val),-abs(target-up_val))+(target-up_val) To visualize this, an array of penalties can be plotted v. value (with scale set to 1): lo_val = 0.7 up_val = 1.0 target = 0.8 # array of target values m.vals = range(0,2,0.05) m.lower_p = max((m.vals-lo_val), abs(m.vals-lo_val))-(m.vals-lo_val) m.upper_p = -min((m.vals-up_val),-abs(m.vals-up_val))+(m.vals-up_val) m.penalty = (max((m.vals-lo_val), abs(m.vals-lo_val)) - min((m.vals-up_val),-abs(m.vals-up_val))+ lo_val-up_val) newplot m.vals, m.penalty, style=linespoints2 plot m.vals, m.lower_p plot m.vals, m.upper_p --Matt
On Thursday 22 January 2004 11:57 am, Matt Newville wrote:
I agree with most of your answer to Dan about setting constraints
and restraints, but I think I'd fail the 'quiz' you gave:
A word of caution. Restraints can be dangerous. Here is a quiz: Why is this definition of the restraint a bad idea?
set scale = -100 restrain amp = abs(amp_guess - amp_target) * scale
where you had
guess amp_guess = 0.85 set amp_target = 0.85 set scale = 100 restrain amp = abs(amp_guess - amp_target) * scale
as a recommended way to set just such a constraint. I believe there's no difference. Am I missing something?
No... probably I am missing something. It seems to me that if you use the absolute value to force the difference to be a positive number, then set the scale to a negative number, that would *reward* a large difference rather than *penalize* it. But perhaps I am confused in how the restraints are added to chi-square. I am under the impression that restraints are added as written to chi-square. This seems consistent with the language in section 7.9 of the reference manual. However, if the restraint is squared before adding to chi-square then what I said about the negative value of the scaling term is clearly wrong. I should point out that I have not actually looked at the source code... B -- Bruce Ravel ----------------------------------- ravel@phys.washington.edu Code 6134, Building 3, Room 222 Naval Research Laboratory phone: (1) 202 767 5947 Washington DC 20375, USA fax: (1) 202 767 1697 NRL Synchrotron Radiation Consortium (NRL-SRC) Beamlines X11a, X11b, X23b National Synchrotron Light Source Brookhaven National Laboratory, Upton, NY 11973 My homepage: http://feff.phys.washington.edu/~ravel EXAFS software: http://feff.phys.washington.edu/~ravel/software/exafs/
Hi Bruce,
It seems to me that if you use the absolute value to force the difference to be a positive number, then set the scale to a negative number, that would *reward* a large difference rather than *penalize* it.
Nope, the idea is to make the value of the restraint 0. Negative and positive errors in the value are penalized equally.
But perhaps I am confused in how the restraints are added to chi-square. I am under the impression that restraints are added as written to chi-square. This seems consistent with the language in section 7.9 of the reference manual. However, if the restraint is squared before adding to chi-square then what I said about the negative value of the scaling term is clearly wrong.
A restraint is an additional element in the vector to be minimized. chi-square is the sum of squares of the elements of this vector. I guess I should fix the document! --Matt
participants (2)
-
Bruce Ravel
-
Matt Newville