glue-viz / glue-vispy-viewers

3-d data viewers for glue based on VisPy
http://glueviz.org/en/stable/whatsnew/experimental_3d.html#experimental-3d
BSD 2-Clause "Simplified" License
25 stars 21 forks source link

Starting glue-3d-viewer session from python #109

Open bmorris3 opened 8 years ago

bmorris3 commented 8 years ago

It would be great to have an example that demonstrates how to start a glue session from python using the Vispy 3D scatter plot. For example, in the glue docs there is an example for Programmatically configuring plots, and I don't know where to start to make a similar script for a 3D plot.

I've found that I can do the following to start a session

from glue.core import DataCollection, Data
from glue.app.qt.application import GlueApplication
from glue_vispy_viewers.scatter.scatter_viewer import VispyScatterViewer

data = Data(...)
dc = DataCollection([data])

# create a GUI session
ga = GlueApplication(dc)

scatter = ga.new_data_viewer(VispyScatterViewer)
scatter.add_data(data)

but I haven't figured out how to assign data columns to the x/y/z attributes, or assign the colormap.

astrofrog commented 8 years ago

@bmorris3 - add this:

options = scatter.options_widget()

options.x_att = data.id['x']
options.y_att = data.id['y']
options.z_att = data.id['z']

ga.exec_()

will explain a little later today :)

astrofrog commented 8 years ago

Basically the way the 3D viewers are implemented, the options are all stored inside the options widget (the panel in the lower left of glue) and I tried to avoid storing them again in the widget itself, hence the convoluted way above to set what's shown in my example. We need to make the API for all viewers more uniform.

bmorris3 commented 8 years ago

That helps! I still can't figure out how to add a colormap to the (x,y,z) points – is the widget in the middle-left of glue accessible as the one in the lower left is via options = scatter.options_widget()?

astrofrog commented 8 years ago

Ah right yes, those options are layer specific, so you can access them with (e.g. for the first layer):

layer = scatter.layers
layer.color_mode = 'linear'
layer.cmap = <a matplotlib colormap>

You can tab-complete layer. to find out more options. Note that if you run the code from IPython and replace ga.exec_ by ga.show, you will be able to continue trying to set things from IPython and have them update in the application.

bmorris3 commented 8 years ago

When I look at the default layer.cmap, I see that it's an instance of matplotlib.colors.ListedColormap. When I try to set layer.map to my own ListedColormap, I get the following error even though the colormap successfully changes to viridis:

from matplotlib.colors import ListedColormap
cmap = ListedColormap(plt.cm.viridis(np.linspace(0, 1, 256)))
layer.cmap = cmap
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-41-bfe3ecb48bfa> in <module>()
     31 from matplotlib.colors import ListedColormap
     32 cmap = ListedColormap(plt.cm.viridis(np.linspace(0, 1, 256)))
---> 33 layer.cmap = cmap
     34 
     35 #ga.exec_()

/Users/bmmorris/anaconda/lib/python3.5/site-packages/glue/external/echo.py in __set__(self, instance, value)
     62         new = self.__get__(instance)
     63         if old != new:
---> 64             self.notify(instance, old, new)
     65 
     66     def setter(self, func):

/Users/bmmorris/anaconda/lib/python3.5/site-packages/glue/external/echo.py in notify(self, instance, old, new)
     85             return
     86         for cback in self._callbacks.get(instance, []):
---> 87             cback(new)
     88         for cback in self._2arg_callbacks.get(instance, []):
     89             cback(old, new)

/Users/bmmorris/anaconda/lib/python3.5/site-packages/glue/utils/qt/widget_properties.py in update_widget(value)
    264     def update_widget(value):
    265         try:
--> 266             idx = _find_combo_data(widget, value)
    267         except ValueError:
    268             if value is None:

/Users/bmmorris/anaconda/lib/python3.5/site-packages/glue/utils/qt/widget_properties.py in _find_combo_data(widget, value)
    362     i = widget.findData(value)
    363     if i == -1:
--> 364         raise ValueError("%s not found in combo box" % value)
    365     else:
    366         return i

ValueError: <matplotlib.colors.ListedColormap object at 0x130fd9ba8> not found in combo box