> I have found this patch useful for data analysis using Reinteract so
> that I can modify plots by changing the x and y scales, adding
> gridlines, adding titles and axis lables, etc. Basically, it just
> creates the plot in the PlotResult constructor, and just returned by
> create_widget (not actually created within it) when it needs to be
> displayed in the notebook.
>
> So in the notebook file it looks like this:
>
> w=plot(x, cos(x), 'r--', # red dashed lines
> x, sin(x), 'bo') # blue circles
> a=w.widget.axes.legend(['cos(x)','sin(x)'], pad=0.1)
> a=w.widget.axes.set_title('Y vs X')
> a=w.widget.axes.set_xlabel('X Axis Label')
> a=w.widget.axes.set_ylabel('Y Axis Label')
> a=w.widget.axes.set_position((0.1,0.1,0.85,0.85))
> a=w.widget.axes.set_xlim(0,7)
> a=w.widget.axes.set_ylim(-1,1)
> a=w.widget.axes.set_xticks(linspace(0,7,8))
> a=w.widget.axes.set_yticks(linspace(-1,1,5))
> a=w.widget.axes.grid(True)
> w
> #The plot doesn't display until here
The problem with the above is that it counts on side effects ... we
are continually modifying the axes object. Normally reinteract would
try to make a copy of the 'w' object in this case, which would blow up
since it's not a "pure data" object that can be easily copied. You've
worked around that by using the dummy assignments.. reinteract guesses
that a=b.foo() doesn't modify b, but there are still problems ... if
you, say, deleted one of those lines, then the effect of the deleted
line would still remain.
I've thought about this some in this particular context.
1. We could extend the plot command to allow setting more stuff in a
single command:
plot(x, cos(x), 'r--',
x, sin(x), 'bo',
legend=['cos(x)', 'sin(x)'],
title='Y vs X'
...)
This is no longer strictly compatible with the matplotlib plot()
command (in matplotlib, kwargsfor plot set line parameters), but I
don't think that matters much. The cool thing about this is that it is
easily extensible to allowing interactive manipulation of the result
widget. The result object could be provided a handle that points back
to the statement that created it. Then as the user interactively, say,
changed the title, the creation statement would be updated to match.
2. We could add setters on the custom result object for these things.
Since the custom result object *can* be copied, there is no longer a
problem with side effects.
r = plot(x, cos(x), 'r--', x , sin(x), 'bo')
r.set_legend(['cos(x)', 'sin(x)')
r.set_title('Y vs. X')
...
r
3. You could group all the side effects into a single chunk like:
if True:
w=plot(x, cos(x), 'r--', # red dashed lines
x, sin(x), 'bo') # blue circles
w.widget.axes.legend(['cos(x)','sin(x)'], pad=0.1)
w.widget.axes.set_title('Y vs X')
w
Ugly, and requires the user to understand a lot about how reinteract
works internally.
4. reinteract could be smarter about non-copyable objects. If it knows
that an object is being mutated that it can't make a copy of, it could
automatically consider the whole series of statements from the
creation to the last mutator as a single logical group, so if you edit
one line in it, it re-exectutes all the lines. (See also
http://www.reinteract.org/trac/ticket/38)
Some work on 4. is going to be necesary in the long run, but the
ability to extend to interactive editing I think makes 1. a more
interesting approach for this particular problem. Does this make any
sense for the other types of result widgets you have created?
- Owen
>> 4. reinteract could be smarter about non-copyable objects. If it knows
>> that an object is being mutated that it can't make a copy of, it could
>> automatically consider the whole series of statements from the
>> creation to the last mutator as a single logical group, so if you edit
>> one line in it, it re-exectutes all the lines. (See alsohttp://www.reinteract.org/trac/ticket/38)
>
> I think this is a feature that is eventually required. With the
> DataSet data analysis class I created I have methods like appendColumn()
> that can return errors if the user goes back an edits some like above the
> call to that method but not above the creation of the DataSet object
> it is being called on, since the column it is trying to append will
> already exist. But this may be just that Reinteract doesn't know that the
> appendColumn method is modifying the DataSet object, and thus
> doesn't copy it, because the DataSet objects can be copied by
> copy.deepcopy, and such.
Reinteract uses a shallow copy on the objects. While a deep copy is
more correct,
if the mutation is a "shallow" ... something like Array.append() then
you are paying
a big penalty in memory usage and time unnecessarily.
My thought here is that (at least for modules we control), we could us
decorators
on methods:
@reinteract.const
define get_something(self): ...
@reinteract.shallow_copy
define set_member(self): ...
@reinteract.deep_copy
define change_stuff(self):...
You could also imagine specifying a particular copy member function to use for a
particular method.
>> Some work on 4. is going to be necesary in the long run, but the
>> ability to extend to interactive editing I think makes 1. a more
>> interesting approach for this particular problem. Does this make any
>> sense for the other types of result widgets you have created?
>
> The only other result widget I created was one to display one of my
> DataSet objects in a table. Currently this table is read only, and
> it is a little counter intuitive to the user since sorting by columns of
> the table does not really modify the DataSet itself.
Hmm, non-modifcation much what I'd expect, but maybe I'm just too much
of programmer :-)
> The tables are a little different from the case of plotting in that my
> table() function takes a DataSet object as a parameter then builds
> a GTK TreeView based on the data within it and displays that by
> returning a TableResult that contains a TableWidget. So in this
> case if you interactively modified the table it is not clear if the
> DataSet itself should be modified or if the call to table() should
> be modified to *display* the table in the way the user has
> interactively sorted it. If I were to allow the table's data to be
> edited, I think that would only really make sense if these changes
> propagated to the DataSet object. Although, my DataSet
> object currently does not support modifying individual cells anyway.
Again I'd be surprised if editing was possible or if it changed the dataset.
But I think there is some room for "interactive inputs". For example, I was
creating some worksheets earlier to analyze sound files. For a worksheet
like that, it would be neat to be able to pick different sound files with a
file chooser, then interactively select the segment of sound you wanted
to analyze.
I'm not exactly sure how that would work. It could be something in the
code like:
sound = load_sound('foo.wav', 0.3, 0.512);
where the loud_sound statement both a) loads the sound b) knows how to find the
currently executing reinteract statement and add a control underneath it
[ Foo.wav ] [ Browse ]
Start [ 5.3 ] seconds End [ 11.4 ] seconds [ Play ]
Where as you adjusted the controls the text of the statement chnaged.
Or maybe it's
split out so that you declare the dependencies for a reinteract
worksheet in some sort
of magic comment at the top of the worksheet and controls are added above the
worksheet to load the data for the worksheet before the start of the code of the
worksheet.
> If you are interested in seeing my table or DataSet code, let me know
> and I can send you the latest versions.
I took a brief look earlier at the versions you posted to
http://www.reinteract.org/trac/ticket/33, but it wasn't immediately clear to me
offhand how they were intended to be used. Do you have a screenshot
or example worksheet (real or artificial) that gives an example of how
they work?
- Owen
Yeah, that works for something quick.
That exactly mirrors my thoughts on the issue.
> Interactively modifying a DataSet objects themselves (which I hinted
> at before) probably does not make any sense at all the more I think about
> it. It would end up being very messy and not really useful.
I think there's a separate potential feature where you can add data files
to a notebook as a "data library". Then there might be grid views for entering
and editing data there separate from worksheets.
>> I took a brief look earlier at the versions you posted to
>> http://www.reinteract.org/trac/ticket/33, but it wasn't immediately clear to me
>> offhand how they were intended to be used. Do you have a screenshot
>> or example worksheet (real or artificial) that gives an example of how
>> they work?
>
> I when I get a chance, l put together an example worksheet and a
> screenshot and send them to you along with the latest copies of the
> classes, so you can see what they are used.
Cool.
- Owen