Closed martinal closed 7 years ago
One draft of widget based user interface:
# maybe it is nice to have a mesh class
mesh = Mesh (cells, coordinates )
# or maybe it can be passed as any other array:
f = Data(array)
# array may be same object, forced upload anyway
f.update(array)
# explicit control of data naming and sharing
group = DataGroup()
group.add(fname, f)
group.update(fname, array) # calls f.update(array)
group.add(name, array) # shortcut, wraps array in Data
encoding1 = Encoding()
encoding1.add (name, desc)
encoding1.add ("channel name", { field: "data name", ...})
encoding1.update(name, desc)
encoding1.update((name, "field"), "other data name")
# create some plot configurations
surf = Surface(mesh, data, encoding1)
xray = XRay(mesh, data, encoding2)
# setup figure
f = Figure(axes, [surf, xray], renderer=pythreejs.Renderer(...), camera=...)
Another attempt, dropping the explicit data dict and encoding dict and using widget object references instead of names. Trying to mimic some of the bqplot interface here.
class Mesh(Widget):
celltype = Unicode("tetrahedron").tag(sync=True)
cells = Array().tag(sync=True)
coordinates = Array().tag(sync=True)
class Field(Widget):
mesh = Instance(Mesh).tag(sync=True)
space = Unicode("P1").tag(sync=True)
values = Array().tag(sync=True)
class ScalarLUT(Widget):
values = Array().tag(sync=True)
interpolation = Unicode("linear").tag(sync=True)
class ColorLUT(Widget):
values = Array().tag(sync=True)
interpolation = Unicode("linear").tag(sync=True)
class Indicators(Widget):
values = Array().tag(sync=True)
dim = CInt().tag(sync=True)
# Unstructured mesh
mesh = Mesh(cells=cells, coordinates=coordinates)
# Cellwise constant field over mesh
field0 = Field(mesh=mesh, values=values, space="P0")
field0.update(new_values)
# Cellwise continuous linear field over mesh
field1 = Field(mesh=mesh, values=values, space="P1")
field1.update(new_values)
# Cellwise discontinuous linear field over mesh
field2 = Field(mesh=mesh, values=values, space="D1")
field2.update(new_values)
# Cell indicator values over mesh
ind3 = Indicators(mesh=mesh, values=values, dim=3)
ind3.update(new_values)
# Facet indicator values over mesh
ind2 = Indicators(mesh=mesh, values=values, dim=2)
ind2.update(new_values)
# Lookup tables
lut0 = ScalarLUT(values=[0.2, 0.4, 0.7, 1.0], interpolation="nearest")
lut1 = ScalarLUT(values=[0, 1], interpolation="linear")
lut2 = ColorLUT(values=[[1,0,0], [0,0,1]], interpolation="linear")
# Plot configurations can be packaged in dicts
surf_encoding = {
"color": { "field": field0, "lut": lut0 },
"wireframe": { "enable": true, "width": 0.05, "color": "black" },
"restrict": { "indicators": ind3, "enabled_value": 7 },
}
# But the encoding is really just passed as keyword arguments
surf = Surface(mesh, **surf_encoding)
xray = XRay(mesh, density=field1)
# Setup figure
axes = [...]
marks = [surf, xray] # bqplot calls this marks, from data visualization literature
fig = Figure(axes, marks,
# Allow passing renderer and camera but create these by default if not provided:
renderer=pythreejs.Renderer(...), camera=pythreejs.Camera(...))
display(fig)
@vidartf pushed a notebook with some further refinement of the above to this branch: https://github.com/martinal/jupyter-unray/tree/widget-redesign
Current setup is similar to the above. Needs some iteration, fixes, and polish, but closing this unspecific issue.
I have some ideas on paper, will write it up later. This can also be a testing ground for generic data/encoding/plot/figure widgets to extract into a separate library. To be discussed!