-
-
Notifications
You must be signed in to change notification settings - Fork 507
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
VTK volume viewer export color mapper informations to python side #1073
Conversation
49edbd2
to
1172866
Compare
Ready to merge? |
No I'd like to modify documentation before |
What do you think to had something like that to the gallery? import param
import panel as pn
import holoviews as hv
import pyvista as pv
from pyvista import examples
from scipy.ndimage import zoom
pn.extension('vtk')
hv.extension('bokeh')
class ImageSmoother(param.Parameterized):
smooth_fun = param.Parameter(default=None)
order = param.Selector(default=1, objects=[1,2,3])
zoom = param.Integer(default=2, bounds=(1,10))
def __init__(self, **params):
super().__init__(**params)
self._update_fun()
@param.depends('order', 'zoom', watch=True)
def _update_fun(self):
self.smooth_fun = lambda x: zoom(x, zoom=self.zoom, order=self.order)
@property
def stream(self):
return hv.streams.Params(self, parameters=['smooth_fun'])
# Download a volumetric dataset
vol = examples.download_head()
volume = pn.panel(vol, sizing_mode='stretch_both', height=400, display_slices=True, orientation_widget=True)
volume_controls = volume.controls(jslink=False, parameters=['render_background', 'display_volume', 'display_slices',
'slice_i', 'slice_j', 'slice_k', 'rescale'])
toggle_parallel_proj = pn.widgets.Toggle(name='Parallel Projection', value=False)
def update_camera_projection(*evts):
volume.camera['parallelProjection'] = evts[0].new
volume.param.trigger('camera')
toggle_parallel_proj.param.watch(update_camera_projection, ['value'], onlychanged=True)
stream_i = hv.streams.Params(volume, parameters=['slice_i'], rename={'slice_i':'si'})
stream_j = hv.streams.Params(volume, parameters=['slice_j'], rename={'slice_j':'sj'})
stream_k = hv.streams.Params(volume, parameters=['slice_k'], rename={'slice_k':'sk'})
stream_mapper = hv.streams.Params(volume, parameters=['mapper'])
smoother = ImageSmoother()
stream_smooth = smoother.stream
arr = vol.active_scalar.reshape(vol.dimensions, order='F')
def image_slice_i(si, mapper, smooth_fun):
low = mapper['low'] if mapper else arr.min()
high = mapper['high'] if mapper else arr.max()
cmap = mapper['palette'] if mapper else 'fire'
lbrt = vol.extent[4], vol.extent[2], vol.extent[5], vol.extent[3]
im_i = hv.Image(smooth_fun(arr[si,::-1,:]), bounds=lbrt, kdims=['z','y'], vdims='Intensity')
frame_width = 500
frame_height = int(frame_width * (lbrt[2]-lbrt[0])/(lbrt[3]-lbrt[1]))
return im_i.opts(hv.opts.Image(clim=(low, high), cmap=cmap, frame_width=frame_width, frame_height=frame_height))
def image_slice_j(sj, mapper, smooth_fun):
low = mapper['low'] if mapper else arr.min()
high = mapper['high'] if mapper else arr.max()
cmap = mapper['palette'] if mapper else 'fire'
lbrt = vol.extent[4], vol.extent[0], vol.extent[5], vol.extent[1]
im_j = hv.Image(smooth_fun(arr[::-1,sj,:]), bounds=lbrt, kdims=['z','x'], vdims='Intensity')
frame_width = 500
frame_height = int(frame_width * (lbrt[2]-lbrt[0])/(lbrt[3]-lbrt[1]))
return im_j.opts(hv.opts.Image(clim=(low, high), cmap=cmap, frame_width=frame_width, frame_height=frame_height))
def image_slice_k(sk, mapper, smooth_fun):
low = mapper['low'] if mapper else arr.min()
high = mapper['high'] if mapper else arr.max()
cmap = mapper['palette'] if mapper else 'fire'
lbrt = vol.extent[2], vol.extent[0], vol.extent[3], vol.extent[1]
im_k = hv.Image(smooth_fun(arr[::-1,:,sk]), bounds=lbrt, kdims=['y','x'], vdims='Intensity')
frame_width = 500
frame_height = int(frame_width * (lbrt[2]-lbrt[0])/(lbrt[3]-lbrt[1]))
return im_k.opts(hv.opts.Image(clim=(low, high), cmap=cmap, frame_width=frame_width, frame_height=frame_height))
hv.opts.defaults(hv.opts.Image(invert_axes=True, data_aspect=1))
dmap_i = hv.DynamicMap(image_slice_i, streams=[stream_i, stream_mapper, stream_smooth])
dmap_j = hv.DynamicMap(image_slice_j, streams=[stream_j, stream_mapper, stream_smooth])
dmap_k = hv.DynamicMap(image_slice_k, streams=[stream_k, stream_mapper, stream_smooth])
controller = pn.WidgetBox(toggle_parallel_proj, *volume_controls[1:], pn.Param(smoother, parameters=['zoom', 'order']))
pn.Row(pn.Column(pn.Row(controller, volume), pn.Row(dmap_i, dmap_j)), dmap_k, sizing_mode='stretch_height').show() |
Codecov Report
@@ Coverage Diff @@
## master #1073 +/- ##
==========================================
- Coverage 88.1% 87.77% -0.33%
==========================================
Files 105 105
Lines 12380 12590 +210
==========================================
+ Hits 10907 11051 +144
- Misses 1473 1539 +66
Continue to review full report at Codecov.
|
Wow, how did you do the draggable layout? |
I used http://golden-layout.com/ |
Very cool, you used it as a custom template? |
Yes i tried to mix different aspects of panel
Le jeu. 6 févr. 2020 à 18:27, Philipp Rudiger <notifications@github.com> a
écrit :
… Very cool, you used it as a custom template?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1073?email_source=notifications&email_token=AENMGS3ZQCDCZZ2P7IGRXQTRBRCATA5CNFSM4KQMKZE2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOELACD4Y#issuecomment-583016947>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AENMGS7ND3FPL7QO2GQOQYDRBRCATANCNFSM4KQMKZEQ>
.
|
ffbf0ac
to
88f0526
Compare
Going to merge and get this in 0.8.1 pretending it's a simple enhancement 😄 |
6636f8a
to
033ce54
Compare
@xavArtley The VTKVolume.mapper isn't syncing for me in the notebook, any idea what's going on there? |
Actually for me it's not sync too in the notebook but only when I use the
tempate. If I use panel Row and Columns it works as expected.
Le sam. 8 févr. 2020 à 00:51, Philipp Rudiger <notifications@github.com> a
écrit :
… @xavArtley <https://github.com/xavArtley> The VTKVolume.mapper isn't
syncing for me in the notebook, any idea what's going on there?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1073?email_source=notifications&email_token=AENMGSY3PHSCYHK34LUBOO3RBXXY5A5CNFSM4KQMKZE2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOELFAGAA#issuecomment-583664384>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AENMGSZ5OE4ZCO57GSD3QM3RBXXY5ANCNFSM4KQMKZEQ>
.
|
I haven't read all the template documentation to handle template in notebook. I will make some modifications instead of testing the document title |
I found something strange when looking at |
This is in fact expected, templates have to do some funny stuff to linking set up. |
@philippjfr Do you think it should be possible to set data_aspect=1 to images while keeping layout responsivness? |
Would definitely need some special handling I think only bokeh figures currently support aspect handling out of the box. |
@philippjfr Python 2 failed on master because the property
|
@xavArtley I'm happy to defer to your judgement here. Given that we are dropping python 2 support in about a week and there will be only one more release, I'm happy to skip this test for py2 if pyvista>=0.23 doesn't support py2. |
The notebook for this (VTKSlicer.ipynb) does not successfully link the controls with the image. E.g. slicing does not work, neither does selecting the background. |
@xavArtley I was testing locally. It had to do with the Jupyter extensions. It didn't return anything in Jupyter notebook. In Jupyter lab it showed the window but didn't have any interactivity. Turns out the reason was because I hadn't installed the pyviz extension. Problem solved! Thanks for your help. |
With this PR we begin to have a real 3d slicer