<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Slicing
Ipyvolume has no special support for slicing 3d volumes, but has the options to support this. To understand how to do this, we will create a 3d plot, with a plane, which will be controlled using the mouse, and later on texture map this with the same data as the volumetric data.
Simple guassian blob
Lets start with a simple scatter plot.
Step1:  Now, we add a plane at z=0.
Step2:  By holding the shift key and hovering the mouse at the edges of the bounding box (or activate slice mode in the toolbar, and click), we modify the slice_z property. By linking the slice_z property to the z_offset property of the mesh/plane, we can interactively move the plane. Note that in order to change the z_offset, you need to hover the mouse at the sides of the bounding box, which means you need to make sides of the bounding box visible.
Step3:  Adding a texture
This plane can be texture mapped with additional information, for instance, a heatmap. We use vaex with maplotlib to create a simple 2d heatmap PIL Image.
Step4:  On just download an image
Step5:  And assign it to the plane's texture. Note that we should also set its u and v coordinates, so we know where the edges of the texture map should go
Step6:  Slicing a volume
We can also, texture map a mesh (a plane is a mesh) with a 3d texture, from the volumetric data.
Step7:  We now add 3 planes, and pass our volume so it can be used as a texture map.
Step8:  Again, by connecting the slice coordinates to the offsets of the planes, we can create 3 slicing planes that can be controlled interactively.
Step9:  Note that you can save the output to an html file, and the slicing will still work without a connected kernel.
<ASSISTANT_TASK:>
Python Code:
import ipyvolume as ipv
fig = ipv.figure()
scatter = ipv.examples.gaussian(show=False)
ipv.show()
Explanation: Slicing
Ipyvolume has no special support for slicing 3d volumes, but has the options to support this. To understand how to do this, we will create a 3d plot, with a plane, which will be controlled using the mouse, and later on texture map this with the same data as the volumetric data.
Simple guassian blob
Lets start with a simple scatter plot.
End of explanation
plane = ipv.plot_plane("z");
Explanation: Now, we add a plane at z=0.
End of explanation
import ipywidgets as widgets
widgets.jslink((fig, 'slice_z'), (plane, 'z_offset'));
Explanation: By holding the shift key and hovering the mouse at the edges of the bounding box (or activate slice mode in the toolbar, and click), we modify the slice_z property. By linking the slice_z property to the z_offset property of the mesh/plane, we can interactively move the plane. Note that in order to change the z_offset, you need to hover the mouse at the sides of the bounding box, which means you need to make sides of the bounding box visible.
End of explanation
## Uncomment to try
# import vaex
# import matplotlib.pylab as plt
# import PIL.Image
# df = vaex.from_arrays(x=scatter.x, y=scatter.y)
# fig2d = plt.figure()
# ax = fig2d.add_axes([0, 0, 1, 1])
# df.viz.heatmap(df.x, df.y, shape=64, show=False, colorbar=False, tight_layout=False)
# fig2d.axes[0].axis('off');
# plt.draw()
# image = PIL.Image.frombytes('RGB', fig2d.canvas.get_width_height(), fig2d.canvas.tostring_rgb())
# plt.close()
# image
Explanation: Adding a texture
This plane can be texture mapped with additional information, for instance, a heatmap. We use vaex with maplotlib to create a simple 2d heatmap PIL Image.
End of explanation
# example how put a png as texture
import PIL.Image
import requests
import io
url = 'https://vaex.io/img/logos/spiral-small.png'
r = requests.get(url, stream=True)
f = io.BytesIO(r.content)
image = PIL.Image.open(f)
Explanation: On just download an image:
End of explanation
plane.u = [0.0, 1.0, 1.0, 0.0]
plane.v = [0.0, 0.0, 1.0, 1.0]
plane.texture = image
Explanation: And assign it to the plane's texture. Note that we should also set its u and v coordinates, so we know where the edges of the texture map should go:
End of explanation
import ipyvolume as ipv
fig = ipv.figure()
volume = ipv.examples.head(show=False, description="Patient X")
ipv.show()
Explanation: Slicing a volume
We can also, texture map a mesh (a plane is a mesh) with a 3d texture, from the volumetric data.
End of explanation
slice_x = ipv.plot_plane('x', volume=volume, description="Slice X", description_color="black", icon="mdi-knife")
slice_y = ipv.plot_plane('y', volume=volume, description="Slice Y", description_color="black", icon="mdi-knife")
slice_z = ipv.plot_plane('z', volume=volume, description="Slice Z", description_color="black", icon="mdi-knife",
                         visible=False)
Explanation: We now add 3 planes, and pass our volume so it can be used as a texture map.
End of explanation
import ipywidgets as widgets
widgets.jslink((fig, 'slice_x'), (slice_x, 'x_offset'))
widgets.jslink((fig, 'slice_y'), (slice_y, 'y_offset'))
widgets.jslink((fig, 'slice_z'), (slice_z, 'z_offset'));
Explanation: Again, by connecting the slice coordinates to the offsets of the planes, we can create 3 slicing planes that can be controlled interactively.
End of explanation
# uncomment to save
ipv.save("slice.html", devmode=True)
Explanation: Note that you can save the output to an html file, and the slicing will still work without a connected kernel.
End of explanation
<END_TASK>