[kepler-users] attributeChanged method?
Christopher Brooks
cxh at eecs.berkeley.edu
Mon Jan 12 11:50:01 PST 2009
Hi,
Ptolemy has the notion of lazy evaluation of attributes, which
means that the value of an attribute should only be determined when
the value is needed. See ptolemy.kernel.util.Settable for
details and see the Ptolemy Design Document.
See also ptolemy.data.expr.Variable, which has a setLazy() method.
That _might_ do what you want.
The easiest way to track down this problem would be to see
where the use the debugger or print a stack trace inside
attributeChanged().
I added
new Exception("Inside attributeChanged " + attribute).printStackTrace();
to TrigFunction.attributeChanged(),
public void attributeChanged(Attribute attribute)
throws IllegalActionException {
if (attribute == function) {
new Exception("Inside attributeChanged " +
attribute).printStackTrace();
String functionName = function.stringValue();
When I run
$PTII/bin/vergil $PTII/ptolemy/actor/lib/test/auto/TrigFunction.xml
I get:
java.lang.Exception: Inside attributeChanged
ptolemy.data.expr.StringParameter {.TrigFunction.TrigFunction2.function}
"cos"
at ptolemy.actor.lib.TrigFunction.attributeChanged(TrigFunction.java:159)
at ptolemy.data.expr.Variable._setTokenAndNotify(Variable.java:1987)
at ptolemy.data.expr.Variable._evaluate(Variable.java:1641)
at ptolemy.data.expr.Variable._propagate(Variable.java:1727)
at ptolemy.data.expr.Variable.validate(Variable.java:1425)
at ptolemy.moml.MoMLParser.endDocument(MoMLParser.java:663)
at com.microstar.xml.XmlParser.doParse(XmlParser.java:162)
at com.microstar.xml.XmlParser.parse(XmlParser.java:132)
at ptolemy.moml.MoMLParser.parse(MoMLParser.java:1401)
at ptolemy.moml.MoMLParser.parse(MoMLParser.java:1338)
at ptolemy.moml.MoMLParser.parse(MoMLParser.java:1289)
at
ptolemy.actor.gui.PtolemyEffigy$Factory.createEffigy(PtolemyEffigy.java:413)
at ptolemy.actor.gui.EffigyFactory.createEffigy(EffigyFactory.java:215)
at ptolemy.actor.gui.Configuration.openModel(Configuration.java:666)
at ptolemy.actor.gui.Configuration.openModel(Configuration.java:626)
at ptolemy.actor.gui.MoMLApplication._openModel(MoMLApplication.java:833)
at ptolemy.actor.gui.MoMLApplication._parseArg(MoMLApplication.java:964)
at ptolemy.actor.gui.MoMLApplication._parseArgs(MoMLApplication.java:1053)
at ptolemy.vergil.VergilApplication._parseArgs(VergilApplication.java:360)
at ptolemy.actor.gui.MoMLApplication.<init>(MoMLApplication.java:215)
at ptolemy.vergil.VergilApplication.<init>(VergilApplication.java:101)
at ptolemy.vergil.VergilApplication$1.run(VergilApplication.java:144)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
at
java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:300)
at
java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:210)
at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:200)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:195)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:187)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)
This indicates that attributeChanged is being called by the MoMLparser,
which ends up validating a variable. Using a debugger could help
track down which variable is being evaluated, but it is presumably
the function parameter of TrigFunction.
Looking at MoMLParser, the code that eventually calls attributeChanged()
is:
// Force evaluation of parameters so that any listeners are
notified.
// This will also force evaluation of any parameter that
this variable
// depends on.
Iterator parameters = _paramsToParse.iterator();
// As an optimization, if there are multiple instances of
// SharedParameter in the list that are shared, we only
// validate the first of these. This prevents a square-law
// increase in complexity, because each validation of an
// instance of SharedParameter causes validation of all
// its shared instances. EAL 9/10/06.
HashSet parametersValidated = new HashSet();
while (parameters.hasNext()) {
Settable param = (Settable) parameters.next();
if (parametersValidated.contains(param)) {
continue;
}
// NOTE: We used to catch exceptions here and issue
// a warning only, but this has the side effect of blocking
// the mechanism in PtolemyQuery that carefully prompts
// the user for corrected parameter values.
try {
--> param.validate();
So, we are evaluating all the parameters so that we can notify
listeners. This would not be that easy to avoid.
So, I insert setLazy(true) into the constructor:
public TrigFunction(CompositeEntity container, String name)
throws NameDuplicationException, IllegalActionException {
super(container, name);
// parameters
function = new StringParameter(this, "function");
---> function.setLazy(true);
function.setExpression("sin");
Then, when I open the model, attributeChanged() is no longer called,
but it is called when I run the model. This might do what you want.
Another possible solution would be to have the initial value of the
Attribute set to a dummy value that was ignored until you properly set it.
Someone else might have a better answer to this one . . .
_Christopher
turuncu at be.itu.edu.tr wrote:
> Hi,
>
> I try to fill few StringParameter fields using a method. So, I put that
> method into particular location in the attributeChanged method as you
> expected. In fact that this method is also called when the model is
> loaded. So, how can i prevent the fill the parameter fields when the model
> is loaded. I just want to call "parameter fill" method only when i change
> the value of the specific parameter field.
>
> Any suggestion will be helpful.
> Thanks for your help,
>
> --ufuk
>
>
--
Christopher Brooks (cxh at eecs berkeley edu) University of California
CHESS Executive Director US Mail: 337 Cory Hall
Programmer/Analyst CHESS/Ptolemy/Trust Berkeley, CA 94720-1774
ph: 510.643.9841 fax:510.642.2718 (Office: 545Q Cory)
home: (F-Tu) 707.665.0131 (W-F) 510.655.5480
More information about the Kepler-users
mailing list