From: Vincent on
Is there an easy way to get Mathematica to interpret custom code when
a FittedModel is called with a custom argument, for example if I have

modelfit = NonlinearModelFit[...]

modelfit ["EstimatedPower"]

which would then call my own code using the modelfit object to compute
something?
I know that it's trivial to achieve the same functionality just
calling the function on the variable, but I rather like the object
orientet like syntax of adding my own figures to the FittedModel
object.

From: Darren Glosemeyer on
Vincent wrote:
> Is there an easy way to get Mathematica to interpret custom code when
> a FittedModel is called with a custom argument, for example if I have
>
> modelfit = NonlinearModelFit[...]
>
> modelfit ["EstimatedPower"]
>
> which would then call my own code using the modelfit object to compute
> something?
> I know that it's trivial to achieve the same functionality just
> calling the function on the variable, but I rather like the object
> orientet like syntax of adding my own figures to the FittedModel
> object.
>
>

There currently isn't a mechanism in place for this. A possibility if
you really want an object oriented approach could be to define a new
operator that will get properties via FittedModel if possible and from
other definitions when added.

In[1]:= nlm = NonlinearModelFit[Range[10]^2, b*Exp[a*x], {a, b}, x];

(* get property from built-in code for defined properties *)
In[2]:= myModelProperties[model : FittedModel[{"Nonlinear", __},
__]][prop_] :=
model[prop] /; MemberQ[model["Properties"], prop]

(* give the definition for a new property *)
In[3]:= myModelProperties[model : FittedModel[{"Nonlinear", __}, __]][
"SinVariance"] := Sin[model["EstimatedVariance"]]

(* define a construct for lists of properties *)
In[4]:= myModelProperties[model : FittedModel[{"Nonlinear", __}, __]][
vals : {_String ...}] := Map[myModelProperties[model], vals]

(* this is our new object *)
In[5]:= op = myModelProperties[nlm];

(* get single newly defined and pre-existing properties and get both in
a list at once *)
In[6]:= op["SinVariance"]

Out[6]= 0.618074

In[7]:= op["BestFit"]

0.288603 x
Out[7]= 5.86625 E

In[8]:= op[{"SinVariance", "BestFit"}]

0.288603 x
Out[8]= {0.618074, 5.86625 E }

For lists of properties, the code above may be slower than the built-in
FittedModel property code because the FittedModel code re-uses shared
intermediate results while the code above does not.

Darren Glosemeyer
Wolfram Research

From: Vincent on
On Jul 9, 2:33 am, Darren Glosemeyer <darr...(a)wolfram.com> wrote:
> Vincent wrote:
> > Is there an easy way to get Mathematica to interpret custom code when
> > a FittedModel is called with a custom argument, for example if I have
>
> > modelfit = NonlinearModelFit[...]
>
> > modelfit ["EstimatedPower"]
>
> > which would then call my own code using the modelfit object to compute
> > something?
> > I know that it's trivial to achieve the same functionality just
> > calling the function on the variable, but I rather like the object
> > orientet like syntax of adding my own figures to the FittedModel
> > object.
>
> There currently isn't a mechanism in place for this. A possibility if
> you really want an object oriented approach could be to define a new
> operator that will get properties via FittedModel if possible and from
> other definitions when added.
>
> In[1]:= nlm = NonlinearModelFit[Range[10]^2, b*Exp[a*x], {a, b}, x];
>
> (* get property from built-in code for defined properties *)
> In[2]:= myModelProperties[model : FittedModel[{"Nonlinear", __},
> __]][prop_] :=
> model[prop] /; MemberQ[model["Properties"], prop]
>
> (* give the definition for a new property *)
> In[3]:= myModelProperties[model : FittedModel[{"Nonlinear", __}, __]][
> "SinVariance"] := Sin[model["EstimatedVariance"]]
>
> (* define a construct for lists of properties *)
> In[4]:= myModelProperties[model : FittedModel[{"Nonlinear", __}, __]][
> vals : {_String ...}] := Map[myModelProperties[mode=
l], vals]
>
> (* this is our new object *)
> In[5]:= op = myModelProperties[nlm];
>
> (* get single newly defined and pre-existing properties and get both in
> a list at once *)
> In[6]:= op["SinVariance"]
>
> Out[6]= 0.618074
>
> In[7]:= op["BestFit"]
>
> 0.288603 x
> Out[7]= 5.86625 E
>
> In[8]:= op[{"SinVariance", "BestFit"}]
>
> 0.288603 x
> Out[8]= {0.618074, 5.86625 E }
>
> For lists of properties, the code above may be slower than the built-in
> FittedModel property code because the FittedModel code re-uses shared
> intermediate results while the code above does not.
>
> Darren Glosemeyer
> Wolfram Research

Thank you very much for your reply, I found it very helpful, and the
idea of making new classes when you want to extend the properties of a
current class seems very much in line with object oriented thinking.
While trying to solve the problem on my own i came by a different
method, which however did not allow list of properties. By
unprotecting string and making a definition for it, you get something
like what I wanted

ClearAttributes[String,Protected]
FittedModule[a__]["EstimatedPower"]^:=findpower[fittedModule[a]]
SetAttributes[String,Protected]

Now I'm thinking that this is very bad, since Mathematica now makes an
additional check everytime a sting is input to a function, is this
correct? I was thinking you could get by this simply considering
EstimatedPower a symbol, which allows you to just call the
FittedModels with syntax like mld[EstimatedPower], which is almost the
same except for the quotes. This would only be checked specifically
when the EstimatedPower property is requested right?

SetAttibutes[EstimatedPower,Protected]
FittedModule[a__][EstimatedPower]^:=findpower[fittedModule[a]]

I'm going to go with a solution like what you posted, however if you
or anyone else would care to comment on these two examples I would be
very happy to see if my understanding of up/downvalues is way off.