Documente Academic
Documente Profesional
Documente Cultură
Scientific Visualization
Outline
Motivation
Scientific visualization software
Visualization with Python
Python performance optimizations
Development tools
Conclusion
Future plans
Discussion
May 22, 2014
Motivation
We need easy-to-use methods for:
visualizing and analyzing two- and threedimensional data sets, perhaps with a dynamic
component
creating publication-quality graphics
making glossy figures for high impact journals or
press releases
drawbacks
Gnuplot limited functionality
Xmgrace too old, requires OSF/Motif (X11)
OpenDX no longer maintained (2007)
ParaView not very intuitive
Mayavi2 not very responsive
MATLAB 5 floating, 3 user licenses (16K /year)
Mathematica expensive (~2.500 /user)
Octave, Scilab, Freemat no syntax compatibility
May 22, 2014
Remaining solutions
GUI + API:
ParaView
Mayavi2
API:
matplotlib
n.n.
Lets talk about this later
ParaView
10
Mayavi2
11
matplotlib
12
Problems so far
separated 2D and (hardware accelerated) 3D
world
some graphics backends "only" produce pictures
no presentation of continuous data streams
bare minimum level of interoperability
limited user interaction
poor performance on large data sets
APIs are partly device- and platform-dependent
May 22, 2014
13
14
15
16
17
18
19
20
Batteries included
NumPy package for numerical computation
SciPy collection of numerical algorithms and specific toolboxes
Matplotlib popular plotting package
Pandas provides high-performance, easy to use data structures
SymPy symbolic mathematics and computer algebra
IPython rich interactive interface (including IPython notebook)
Mayavi2 3D visualization framework, based on VTK
scikit-image algorithms for image processing
h5py, PyTables managing hierarchical datasets (HDF5)
21
Qt / wx
event loop
C / C++
GR
...
GR3
off-screen
rendering
socket
communication
direct
rendering
JavaScript
generation
POV-Ray
generation
C / ObjC
OpenGL
ES
Browser
WebGL
GKS
POV-Ray
gksqt
wx
X11
GLUT
wxGLCanvas
QGLWidget
Quartz
GKSTerm
Win32
Java
gksweb
PDF MOV
PS
0MQ SVG
OpenGL ...
HTML5
Highlights:
simultaneous output to multiple output devices
direct generation of MPEG4 image sequences
flicker-free display ("double buffering")
22
def rk4(x,
k1 = h
k2 = h
k3 = h
k4 = h
return
h, y, f):
* f(x, y)
* f(x + 0.5 * h, y + 0.5 * k1)
* f(x + 0.5 * h, y + 0.5 * k2)
* f(x + h, y + k3)
x + h, y + (k1 + 2 * (k2 + k3) + k4) / 6.0
theta = 70.0
# initial angle
gamma = 0.1
# damping coefficient
L = 1
# pendulum length
t = 0
dt = 0.04
state = array([theta * pi / 180, 0])
23
def rk4(x,
k1 = h
k2 = h
k3 = h
k4 = h
return
h, y, f):
* f(x, y)
* f(x + 0.5 * h, y + 0.5 * k1)
* f(x + 0.5 * h, y + 0.5 * k2)
* f(x + h, y + k3)
x + h, y + (k1 + 2 * (k2 + k3) + k4) / 6.0
!
!
...
24
... in real-time
import wave, pyaudio
import numpy
import gr
SAMPLES=1024
FS=44100
!
f
!
# Sampling frequency
wf = wave.open('Monty_Python.wav', 'rb')
pa = pyaudio.PyAudio()
stream = pa.open(format=pa.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(), rate=wf.getframerate(),
output=True)
!
...
!
data = wf.readframes(SAMPLES)
while data != '' and len(data) == SAMPLES * wf.getsampwidth():
stream.write(data)
amplitudes = numpy.fromstring(data, dtype=numpy.short)
power = abs(numpy.fft.fft(amplitudes / 65536.0))[:SAMPLES/2]
gr.clearws()
...
gr.polyline(SAMPLES/2, f, power)
gr.updatews()
data = wf.readframes(SAMPLES)
25
def display():
vertices, normals = gr3.triangulate(data, (1.0/160, 1.0/160, 1.0/200), (-0.5, -0.5, -0.5), isolevel)
mesh = gr3.createmesh(len(vertices)*3, vertices, normals, np.ones(vertices.shape))
gr3.drawmesh(mesh, 1, (0,0,0), (0,0,1), (0,1,0), (1,1,1), (1,1,1))
gr3.cameralookat(-2*math.cos(angle), -2*math.sin(angle), -0.25, 0, 0, -0.25, 0, 0, -1)
gr3.drawimage(0, width, 0, height, width, height, gr3.GR3_Drawable.GR3_DRAWABLE_OPENGL)
glutSwapBuffers()
gr3.clear()
gr3.deletemesh(ctypes.c_int(mesh.value))
def motion(x, y):
isolevel = 256*y/height
angle = -math.pi + 2*math.pi*x/width
glutPostRedisplay()
glutInit()
glutInitWindowSize(width, height)
glutCreateWindow("Marching Cubes Demo")
glutDisplayFunc(display)
glutMotionFunc(motion)
glutMainLoop()
26
... with Qt
27
28
29
Import PDF
import gr
(w, h, data) = gr.readimage("fs.pdf")
if w < h:
r = float(w)/h
gr.setviewport(0.5*(1-r), 0.5*(1+r), 0, 1);
else:
r = float(h)/w
gr.setviewport(0, 1, 0.5*(1-r), 0.5*(1+r));
gr.drawimage(0, 1, 0, 1, w, h, data)
gr.updatews()
30
31
def RunSimulation():
# defining materials
mAir = HomogeneousMaterial("Air", 0.0, 0.0)
mSubstrate = HomogeneousMaterial("Substrate", 6e-6, 2e-8)
mParticle = HomogeneousMaterial("Particle", 6e-4, 2e-8)
# collection of particles
cylinder_ff = FormFactorCylinder(radius, height)
cylinder = Particle(mParticle, cylinder_ff)
particle_layout = ParticleLayout()
particle_layout.addParticle(cylinder)
# interference function
interference = InterferenceFunction1DParaCrystal(distance, 3 * nanometer)
particle_layout.addInterferenceFunction(interference)
# air layer with particles and substrate form multi layer
air_layer = Layer(mAir)
air_layer.setLayout(particle_layout)
substrate_layer = Layer(mSubstrate)
multi_layer = MultiLayer()
multi_layer.addLayer(air_layer)
multi_layer.addLayer(substrate_layer)
# build and run experiment
simulation = Simulation()
simulation.setDetectorParameters(250, -4*degree, 4*degree, 250, 0*degree, 8*degree)
simulation.setBeamParameters(1.0 * angstrom, 0.2 * degree, 0.0 * degree)
simulation.setSample(multi_layer)
simulation.runSimulation()
return simulation.getIntensityData().getArray()
BornAgain
A software to simulate and fit neutron
and x-ray scattering at grazing incidence
(GISANS and GISAXS), using distortedwave Born approximation (DWBA)
def SetParameters(i):
radius = (1. + (3.0/Nframes)*i) * nanometer
height = (1. + (4.0/Nframes)*i) * nanometer
distance = (10. - (1.0/Nframes)*i) * nanometer
for i in range(100):
SetParameters(i)
result = RunSimulation()
gr.pygr.imshow(numpy.log10(numpy.rot90(result, 1)), cmap=gr.COLORMAP_PILATUS)
32
33
Coming soon:
Python moldyn package
34
35
36
in highest resolution
37
Performance optimizations
NumPy
module for handling multi-dimensional arrays (ndarray)
Numba (Anaconda)
just-in-time compilation driven by @autojit- or @jitdecorators (LLVM)
vectorization of ndarray based functions (ufuncs)
Numba Pro (Anaconda Accelerate)
parallel loops and ufuncs
execution of ufunfs on GPUs
Python GPU kernels
GPU optimized libraries (cuBLAS, cuFFT, cuRAND)
Josef Heinen, Forschungszentrum Jlich, Peter Grnberg Institute, Scientific IT Systems
38
Realization
NumPy
vector operations on ndarrays instead of loops
works in any NumPy Python environment
Numba (Anaconda)
add @jit and @autojit decorators
useful for many function calls with big arrays
Numba Pro (Anaconda Accelerate)
add @vectorize decorators
implementation of multi-core / GPU kernels in "Python"
switch to GPU-optimized features
useful only for "large" arrays
performance
39
Particle simulation
import
numpy as np
!
! numba.decorators import autojit
from
!
N
# number of particles
! = 300
M
# masses
! = 0.05 * np.ones(N)
size
# particle size
! = 0.04
!
!
@autojit
def
! step(dt, size, a):
# update positions
! a[0] += dt * a[1]
!
! n = a.shape[1]
! D = np.empty((n, n), dtype=np.float)
! for i in range(n):
for j in range(n):
!
dx = a[0, i, 0] - a[0, j, 0]
!
dy = a[0, i, 1] - a[0, j, 1]
!
D[i, j] = np.sqrt(dx*dx + dy*dy)
!
!
! ... # find pairs of particles undergoing a collision
! ... # check for crossing boundary
! return a
...
!
!
!a[0, :] = -0.5 + np.random.random((N, 2)) # positions
a[1,
! :] = -0.5 + np.random.random((N, 2)) # velocities
a[0,
! :] *= (4 - 2*size)
dt
! = 1. / 30
!
while
True:
!
! a = step(dt, size, a)
....
40
Diffusion
!
import
numpy
! numba.decorators import jit
from
!
! = 0.005
dx
! = 0.005
dy
! = 0.5
a
! = dx*dx*dy*dy/(2*a*(dx*dx+dy*dy))
dt
!
timesteps
= 300
!
! = int(1/dx)
nx
! = int(1/dy)
ny
! = numpy.zeros([nx,ny])
ui
! = numpy.zeros([nx,ny])
u
!
!
! diff_step(u, ui):
def
! for i in range(1,nx-1):
!
for j in range(1,ny-1):
!
uxx = ( ui[i+1,j] - 2*ui[i,j] + ui[i-1, j] )/(dx*dx)
!
uyy = ( ui[i,j+1] - 2*ui[i,j] + ui[i, j-1] )/(dy*dy)
!
u[i,j] = ui[i,j]+dt*a*(uxx+uyy)
!
!
diff_step_numba
= jit('void(f8[:,:], f8[:,:])')(diff_step)
!
! m in range(timesteps):
for
diff_step_numba(u,
diff_step
(u, ui)
! ui = numpy.copy(u)
...
41
Mandelbrot set
from numbapro import vectorize
import numpy as np
!
!
!
!
!
!
!
x = tid % width
y = tid / width
real = min_x + x * pixel_size_x
imag = min_y + y * pixel_size_y
c = complex(real, imag)
z = 0.0j
for i in range(iters):
z = z * z + c
if (z.real * z.real + z.imag * z.imag) >= 4:
return i
return 255
42
Performance comparison
Calculation of Mandelbrot set
43
% bash Anaconda-1.x.x-[Linux|MacOSX]-x86[_64].sh
% conda update conda
% conda update anaconda
44
Development tools
You can use your favorite editor and start Python in a shell. But
the impatient user should chose a development environment:
45
IPython console
46
IPython notebook
47
Spyder
48
PyCharm
49
Bokeh
import numpy as np
from scipy.integrate import odeint
from bokeh.plotting import *
sigma = 10
rho = 28
beta = 8.0/3
theta = 3 * np.pi / 4
!
solution = odeint(lorenz, initial, t)
!
x = solution[:, 0]
y = solution[:, 1]
z = solution[:, 2]
xprime = np.cos(theta) * x - np.sin(theta) * y
!
output_file("lorenz.html", title="lorenz.py example")
!
show()
May 22, 2014
# open a browser
Josef Heinen, Forschungszentrum Jlich, Peter Grnberg Institute, Scientific IT Systems
50
Resources
Website: http://gr-framework.org
PyPI: https://pypi.python.org/pypi/gr
Git Repository: http://github.com/jheinen/gr
Binstar: https://binstar.org/jheinen/gr
Talk: Scientific Visualization Workshop (PDF, HTML)
51
Website
52
Git-Repo
53
PyPI
54
Binstar
55
Conclusion
56
Future plans
57
!
Contact:
j.heinen@fz-juelich.de
@josef_heinen"
!
Thanks to:
Florian Rhiem, Ingo Heimbach, Christian Felder, David Knodt, Jrg Winkler, Fabian Beule,
Marcel Dck, Marvin Goblet, et al.
58