-
Notifications
You must be signed in to change notification settings - Fork 2
Home
BlenDaViz requires Blender version 2.8 or above and is not compatible with any previous version due to syntax changes. It also requires the Python libraries numpy, scipy, eqtools and matplotlib, which can be installed via your package manager or via pip.
Note that the version of the library must correspond to the version of the inbuilt Python of Blender, rather than the one installed on your system. If both match you are lucky and have an easy installation. If not you need to follow some simple steps, as explained below.
After the successful installation of Blender and the required libraries you need to download the BlenDaViz library and can store it wherever on your PC, say ~/libs/blendaviz
. You now need to set your PYTHONPATH
variable on your system, which can be different depending on what operating system you are using and what shell (bash or tcsh). On any Unix system (Linux, MacOS, BSD) using bash just add this to your ~/.bashrc
:
export PYTHONPATH=$PYTHONPATH:~/libs
To make suer Python in Blender uses this environmental variable, you need to start Blender using:
blender --python-use-system-env
Once you start Blender, open a Python console in Blender and type import blendaviz as blt
and you are good to go.
If your already installed Blender and Python libraries work together, there is no need to read this section. If you are trying to use BlenDaViz on a computer that requires a manual installation of Blender and the libraries or if you are on a computer for which you do not have root/admin access follow this guide.
-
Download and extract/install Blender 2.80+.
-
Extract the file. There will be an executable within the directory. Let us call this directory
blender_dir
. -
Install the required Python libraries for the correct version. For this you need to verify the version of the inbuilt Python of Blender. You find this in the directory
2.8X/python/bin/
and replaceX
with the right Blender version. For Blender 2.81 this ispython3.7m
. Now install the required libraries using pip for the correct Python version:
cd blender_dir/2.8X/python/bin
./python3.7m -m ensurepip
./python3.7m -m pip install numpy
./python3.7m -m pip install scipy
./python3.7m -m pip install eqtools
./python3.7m -m pip install matplotlib
./python3.7m -m pip install scikit-image
- Upgrade the installed libraries (recommended). You should do this step in case you are getting error messages when using the plotting commands.
./python3.7m -m pip install numpy --upgrade
./python3.7m -m pip install scipy --upgrade
./python3.7m -m pip install eqtools --upgrade
./python3.7m -m pip install matplotlib --upgrade
Open Blender and within Blender a Python console. Import BlendaViz and numpy:
import blendaviz as blt
import numpy as np
In this simple line plot we will create some data and plot them. We will also see how we can manipulate existing plots.
# Create the data.
y = np.linspace(0, 6*np.pi, 20)
x = 2*np.cos(y/2)
z = 2*np.sin(y/2)
# Generate the scatter plot.
pl = blt.plot(x, y, z, marker='cube', radius=0.7)
# Change the color.
pl.color = np.ones([x.shape[0], 4])
pl.color[:, 0] = np.linspace(0, 1, 20)
pl.color[:, 1] = 0
pl.plot()
For rendering the image we need a camera and lights. A camera should already exist. If not click into the 3d view, press SHIFT + a
and select Camera
. Now place it at (26.8, 20.2, 25.6) with rotation (47.7, -1, 113).
Now place two lights anywhere in the scene, one with rotation (85, 180, 75) and one with rotation (-180, 120, -90). Change the type to Sun
and set the strength to 2. Now you can render the scene by pressing F12.
A line plot is very similar to a marker plot. It draws the data points as a line/tube.
import blendaviz as blt
import numpy as np
# Generate the data.
y = np.linspace(0, 6*np.pi, 400)
x = 2*np.cos(y)
z = 2*np.sin(y)
# Generate the line plot.
pl = blt.plot(x, y, z, radius=0.5)
We can plot 2d data arrays using mesh
. We need two 2d arrays containing the x and y coordinates of the data points.
import numpy as np
import blendaviz as blt
# Generate the data.
x0 = np.linspace(-3, 3, 20)
y0 = np.linspace(-3, 3, 20)
x, y = np.meshgrid(x0, y0, indexing='ij')
z = (1 - x**2-y**2)*np.exp(-(x**2+y**2)/5)
# Genereate the mesh plot.
mesh = blt.mesh(x, y, z)
For three-dimensional vector arrays we can user quiver to plot the vector field as arrows. We need the x, y and z-coordinates of the data points as 3d arrays.
import numpy as np
import blendaviz as blt
# Generate the data.
x = np.linspace(-3, 3, 3)
y = np.linspace(-7, 7, 7)
z = np.linspace(-3, 3, 3)
xx, yy, zz = np.meshgrid(x, y, z, indexing='ij')
uu = 0.3*(xx + yy)
vv = 0.3*xx
ww = 0.3*zz + 0.8
# Genereate the quiver plot.
quiver = blt.quiver(xx, yy, zz, uu, vv, ww, length='magnitude', color='magnitude')
Three-dimensional scalar fields can be plotted using contour
. We need the x, z and z-coordinates of the data points as 3d arrays.
import blendaviz as blt
# Generate the data.
x = np.linspace(-2, 2, 21)
y = np.linspace(-2, 2, 21)
z = np.linspace(-2, 2, 21)
xx, yy, zz = np.meshgrid(x, y, z, indexing='ij')
phi = np.sin(3*xx) + np.cos(2*yy) + np.sin(zz)
# Genereate the contour plot.
contour = blt.contour(phi, xx, yy, zz)
A three-dimensional vector field can be plotted as streamlines. For that we need specify the three components of the vector field as 3d arrays, the coordinates of the data points as 3d arrays and the position or number of seeds. If the number of seeds is passed, they will be randomly distributed within the domain.
import numpy as np
import blendaviz as blt
# Generate the data.
x = np.linspace(-4, 4, 100)
y = np.linspace(-4, 4, 100)
z = np.linspace(-4, 4, 100)
xx, yy, zz = np.meshgrid(x, y, z, indexing='ij')
u = -yy*np.exp(-np.sqrt(xx**2+yy**2) - zz**2)
v = np.ones_like(u)*0.1
w = xx*np.exp(-np.sqrt(xx**2+yy**2) - zz**2)
# Define the position of the seeds.
seeds = np.array([np.random.random(10)*2-1, np.zeros(10), np.random.random(10)*2-1]).T
# Generate the streamline plot.
streamlines = blt.streamlines(x, y, z, u, v, w, seeds=seeds, integration_time=100, integration_steps=80)
There are a few occasions that you do not want to start the Blender GUI, like you don't have any compatible graphics driver installed on your system, you want to run the plot in the background, or you are on a cluster with SSH access. Computationally intensive rendering should be ideally done on a powerful computer and done over night or even several days. Here we outline how to make a plot without the GUI.
We present two methods for performing a background plot. The first method is the easier one, but it requires the usage of the GUI to set up the scene, i.e. light, camera and additional rendering options. The second methods requires more coding, but is runs purely in the background.
- Open Blender and remove the default cube.
- Place the camera and light at a suitable position.
- Adjust any other scene and rendering options.
- Save your scence to something like
my_plot.blend
. - Prepare the plotting routine using BlenDaViz and save it to something like
my_plot.py
. - Start Blender from the command line using the prepared scene and the plotting script.
blender --background my_plot.blend -P my_plot.py
This requires a few lines of coding, as we perform all of the steps done in the GUI using the Blender Python commands. Not all of the below steps are required, but highly recommended.
The steps in the script are basically:
- Remove any existing objects from the default scene, like the default cube at the origin.
- Add a suitable light and camera. You should know the extends of your plot for positioning the camera.
- (Optionally, Recommended) Adjust the background and rendering options.
- Perform the BlenDaViz plot.
- Render the scene and save the image.
You then need to run the script using
blender -P my_script.py
It should be evident that using a loop you can generate animations through a sequence of images. You can use ffmpeg to put the images into a video file.
# line_plot_background.py
'''
Plotting example for a line plot in the background.
Usage:
blender -P line_plot_background.py
'''
import blendaviz as blt
import numpy as np
import bpy
# Delete all existing objects, like the default cube, light and camera.
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
# Place the light.
bpy.ops.object.light_add(type='SUN', radius=2, location=(0, 0, 0))
# Place a camera.
bpy.ops.object.camera_add(enter_editmode=False, align='VIEW', location=(30, 3*np.pi, 0),
rotation=(np.pi/2, 0., np.pi/2))
bpy.context.scene.camera = bpy.data.objects['Camera']
# Change the background color.
bpy.data.worlds["World"].node_tree.nodes["Background"].inputs[0].default_value = (1, 1, 1, 1)
bpy.data.worlds["World"].node_tree.nodes["Background"].inputs[1].default_value = 5
bpy.context.scene.world.cycles_visibility.scatter = False
bpy.context.scene.world.cycles_visibility.diffuse = False
bpy.context.scene.world.cycles_visibility.glossy = False
bpy.context.scene.world.cycles_visibility.transmission = False
# Change the rendering options.
bpy.context.scene.render.engine = 'CYCLES'
bpy.context.scene.render.threads_mode = 'FIXED'
bpy.context.scene.render.threads = 4
bpy.context.scene.cycles.samples = 256
bpy.context.scene.render.resolution_x = 1920
bpy.context.scene.render.resolution_y = 1080
# Generate the data.
y = np.linspace(0, 6*np.pi, 400)
x = 2*np.cos(y)
z = 2*np.sin(y)
# Generate the line plot.
pl = blt.plot(x, y, z, radius=0.5)
# Render the image.
bpy.data.scenes['Scene'].render.filepath = 'line_plot.png'
bpy.ops.render.render(write_still=True)