Scientific Visualization with GR
CC Attribution 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Heinen, Josef
Josef Heinen - Scientific Visualization with GR Python developers often get frustrated when managing visualization packages that cover the specific needs in scientific or engineering environments. The GR framework could help. GR is a library for visualization applications ranging from publication-quality 2D graphs to the creation of complex 3D scenes and can easily be integrated into existing Python environments or distributions like Anaconda. - Python has long been established in software development departments of research and industry, not least because of the proliferation of libraries such as *SciPy* and *Matplotlib*. However, when processing large amounts of data, in particular in combination with GUI toolkits (*Qt*) or three-dimensional visualizations (*OpenGL*), it seems that Python as an interpretative programming language may be reaching its limits. - *Outline* - Introduction (1 min) - motivation - GR framework (2 mins) - layer structure - output devices and capabilities - GR3 framework (1 min) - layer structure - output capabilities (3 mins) - high-resolution images - POV-Ray scenes - OpenGL drawables - HTML5 / WebGL - Simple 2D / 3D examples (2 min) - Interoperability (PyQt/PySide, 3 min) - How to speed up Python scripts (4 mins) - Numpy - Numba (Pro) - Animated visualization examples (live demos, 6 mins) - physics simulations - surfaces / meshes - molecule viewer - MRI voxel data - Outlook
 Joseph Heinrich is head of the scientific IT systems group at the Forschungszentrum Jürich in Germany and he will be giving a talk on the visualization system. Okay, thanks. Have a welcome. So okay, first of all, thank you for coming here this morning. My name is Joseph Heinrich and together with my colleagues I'm working on different projects at Forschungszentrum Jürich. Most of them are visualization systems and I'm proud to have the opportunity to give this talk here at EuroPython about GR, a framework for visualization systems. So let me start with a question. Who is already using some scientific software with Python such like Medplotlib, Mayavi, VTK or... Okay, that's a big number. As mentioned, I'm working at a research company and in the past years it turned out that there is a growing need for better and faster visualization software, especially scientists need easy-to-use methods for visualizing two and three-dimensional data sets, possibly with a dynamic component. And they want to create publication quality graphics and videos for their publications probably in the Internet. And they want to make glossy figures for high-impact journals or press releases. At first glance, those methods don't seem to be very challenging but we are talking about it later. There are a lot of scientific plotting methods we need such as line bar graphs, curve plots, scatter plots, all these things you see on the slide here. In principle, this is nothing challenging and there are dozens of solutions for all these kinds of plotting methods. There are also powerful software libraries for scientific applications in Python. Those listed here on this slide are the most popular ones, I think. Maybe I've forgotten one. But we all know Medplotlib, which is the workhorse and the defect of standard concerning graphics in Python. And there's even MyAvi for three-dimensional applications, MyAvi, which is very powerful and based on VTK. And it offers an application interface called MLab, which can be used in your own scripts. There's VTK, it's very versatile, but it's difficult to learn because it's a very low-level system. And we have tools like Wispy and OpenGL, which are both very fast and which are limited to 3D and which are really the lowest-level APIs for graphics with Python. And there are also some GUI tools, just like QWT, with its corresponding 3D equivalents. And the problem with this is that they are currently unmaintained, at least for what my information is. So there are some problems so far. And the main problem, I think, is that the 2D world and the accelerated 3D world are separated. You won't find a tool which provides services for both 3D and 3D graphics. And another problem is that some graphics backends only produce kind of figures. So it's not possible to present continuous data streams from life sources. And also, I've made the experience that there's only a bare minimum level of interoperability. So user interaction is somehow limited with these tools. Also, if we are talking about analyzing large data sets, we often see that there's only a poor performance. And also, these APIs are partly device and platform-independent. So your own scripts will suffer from some system dependencies after the time. Okay, so let's Python get up and running and push for Python. There is a very nice distribution which has been introduced to you in the keynote this morning. It's called Anaconda. And I would really like to recommend this distribution as it's very easy to install a complete scientific Python stack. But I think we need something more. For example, we need some more performance. And this can also be achieved by Anaconda at once. For example, number, which is also be mentioned this morning, which is capable of accelerating number of your Python applications based, which contain NumPy code, even on GPU hardware or multi-core processors. And I will give some examples later. There's something more. We also want to achieve more graphics performance and interoperability. And for this purpose, I would like to introduce our GR framework, which is a universal framework for cross-platform visualization. And the main key points are that it has a procedural graphics back end. So you can really present continuous data streams. And it has built-in device drivers so you can visualize both 2D and 3D scenes in one canvas. And there's a very good interoperability with GUI toolkits so you can establish a very good user interaction. And as you can see in the bottom part of the slide, it's also very easy to install. So this would be our complete scientific Python distribution. I think we have everything we need, especially we have more performance and interoperability. So let me give some examples how this looks live. You can see here a numeric simulation of a damp pendulum. The calculation is done in the RKV, RK4 function. You can see which is simply a numerical integration of this differential equation. And you can see that you can mix graphics with test formulas. And you can do all these things live while your script is running. You don't have to produce figures or something like this. The same works for 3D. You can see it here. In this case, visualization is done with an API which has been written by a colleague of mine, Florian Riem. And he has written an openGL layer for GR, which is called GR3. And you see it's very performant and it does its job. You can even visualize live signals from ray files or from the microphone. And with lock x-axis, and this all runs in real time. These are all things which are very hard to realize with other tools. You can do this also in 3D. Adjust, push the audio away so you can focus on the graphics. So the frequency spectrum is, in this case, visualized by a surface plot, which is realized with openGL and it's that fast as you could see. You can also produce graphics with user interaction. You can see here an MRI application which renders some MRI data through a margin cubes algorithm, which is part of our software and which can be rendered very, very fast and moved with a mouse. So let's talk again about performance. We not only have some needs for more graphics performance, but also for numerical performance. And as mentioned before, there's something called NUMBER which is part of Anaconda, but you also can install it for your own. And there's NUMBER PRO which has some additional features. It's part of Anaconda Accelerate, which costs a few bucks. I don't know the actual price. It's capable of calculating NUMPAI expressions on the GPU, so you can write your own GPU kernels in Python. And it's a very nice tool and it's worth to look at this software. And there are even other tools like KU, BLAST KU, FFT, KURAND, those tools are just dedicated to CUDA hardware. So in this case, you can see how you can profit from such software. You see particle simulation which is very slow, currently running at three frames per second. And just by adding some decorators and an import statement for sure, you can increase the performance by times 15, I think. So you don't have to change your code and you can speed up your application enormously. This is calculated in real time. This would not be possible with poor Python. If you run this simulation in Python, I think each frame is about three seconds. In this case, it was paralyzed or vectorized. This is several examples in our demo suite. Just take a look at the website and you will see how the different optimizations work. So let me introduce some of our success stories. We have integrated our software in several of our applications. We are working both for experimental physicists and for theoretical physicists. And this is something for our instruments. It's a live display for a small-angle neutron diffractometer. And as you could see, you can set the region of interest and the surface is generated in real time. You can rotate it, you can flip the axis, and there's even more. And all this can be done in real time. So this is another example. Here we are processing a huge data set. And it's also done in real time. And this was formally done by a proprietary solution. And with a GR framework, we could embed this into a QT4 application, which was a replacement for the existing solution, and which is much faster, which can produce movies and all these funny things. There's another example here. Nicos is a very complex network-based control system, which is used at the Proxima's reactor mention in Munich for all the instruments which do neutron scattering. And in this case, we replaced by QVT, QWT application with a QTGR application. And it was much faster, it was more responsive, it had some additional features which we didn't have before. So this is a case study to see how fast you can simulate data. Born is a software for simulating neutron and X-ray scattering. To compare it, it was a replacement for medplotlib at this point, and it uses a single call. It's the line just in the bottom of the left side. And if you look at the old code, if you compare the old source code with a new one, well, that's only one line and an export statement to generate a movie, for example. So it's not such complicated to produce movies with a GR framework. So what are the conclusions? The use of Python with our GR framework and Numba, and perhaps Numba Pro extensions, allows the realization of high-performance visualization applications, both in scientific and technical environments. And the GR framework can seamlessly be integrated into any Python environment. So I would suggest to use Anaconda. The integration is simply done by a C-type mechanism, so you can also use it in your own Python distribution. And the combination, Condor and Anaconda, provide a very easy to manage and ready to use Python distributions that can be enhanced by the use of our GR framework, especially with its functions for real-time or 3D visualization functions. So what's next? We are not far from implementing a molecular dynamics package, which will produce such results. We have already all this stuff written in C, and we simply have to write some simple wrappers which will then be integrated into our GR framework. And with this framework, you will be able to do things like this here. This is a simulation which has been calculated on a very big machine, and the data is read with a simple Python script, and then rendered with a GR3 library. You can then export this scene to, for example, Povray, and produce high-quality graphics like shown in the right side of the slide. And you can even do this in highest resolution if you give the correct parameters to those routines. And you can see here it's a very realistic presentation of a DNA. So what are our future plans? Well, we have thought to combine the power of MADplotlib and GR, and we think it should be possible, and the basic idea is to use GR as a MADplotlib back-end. So this would speed up MADplotlib, and all your MADplotlib scripts would profit from this speedup. I think it's possible we didn't start this development, but I think there's a good chance that we get these things running. And there are even more challenges. You learned about Bokeh this morning, and I think this should also be possible. Once we have the MADplotlib integration, it should also be possible to connect those scripts to the Bokeh back-end, which Travis mentioned this morning in the keynote. At this point, I think we should talk to Travis to cooperate. On this slide, you find some resources. There's a website for our framework. There's a Git repu. It's posted on the Py package index. We even have first Beanstar binary distributions for the GR framework, and the talk should be online on this link, which you can find out later. So some closing words. Maybe you hate me after this, but I think that's important. I think that visualization software could be even better if the prerequisites of an application would be described in terms of usability, responsiveness, and interoperability, instead of a list of software with module dependencies. We should use native APIs on the different systems instead of GUI toolkits, and release updates should not break version compatibility. This is something that I have observed very often. So let me end up, and thank you for your attention. Thanks for this great talk. One of the features of Macplotlib that I find very convenient is its integration with iPython notebook, and I play with the visualization before I integrate it into some application or save a high resolution copy for publication or something like that. So I wonder if is the GR framework compatible with iPython notebook, and I use it from there? Right now it's not, but because there's some discrepancy. On the one side we are talking about immediate mode graphics, and with iPython notebook there's just a sequence of commands, and maybe if we get our Macplotlib back-end running as we consider that it could work, then it might be possible to use it in iPython, but I'm not sure about this. Thank you. We'll do our best. Thanks. I'm doing a lot of training of neural networks inside CYthon, almost completely outside of Glober and Teptoloc. Would it be possible for me to bind to CAPIs or CYthon APIs that are excluding Glober and Teptoloc, or do I have to bind back through Python then? As I want to visualize the training of the network during the training process, I think this would be really cool for that. I'm not sure about this. I think we have to talk about this after the session. Sorry. Are there any more questions? Okay, I have a question. When you use the Specterize decorator, and you use the same code in the limited or the basic number version, will this just do nothing, complain with the name error or something, or import error? Is the Specterize decorator available? I mean, even if it does nothing in the basic number version. So, do you mean if it's not present on your machine? Yeah, okay. I mean, for example, you have the Specterize, which I think I understood only works for the pro version, and if you have only the basic version and sort the number. The problem is that the pro version is capable of pushing those LLVM code on your GPU, and the public version is only capable of parallelizing on your own CPU. So, the pro version is only needed if you want to use your GPU for the computing of NumPy operations. What I meant is if I get code from you, which has the Specterize decorator, and I only have the basic version installed, will it just not vectorize but otherwise ignore the vectorize decorator? No, this would not work. So, if you want to try those demos, you really have to purchase the pro version. There are a lot of other demos which don't depend on the pro version. Okay, thanks a lot. Okay, if there are no questions, have been added? Okay, so thanks again. Yeah.
 Joseph Heinrich is head of the scientific IT systems group at the Forschungszentrum  Jürich in Germany and he will be giving a talk on the visualization system.  Okay, thanks. Have a welcome.  So okay, first of all, thank you for coming here this morning. My name is Joseph Heinrich  and together with my colleagues I'm working on different projects at Forschungszentrum Jürich.  Most of them are visualization systems and I'm proud to have the opportunity to give this talk here  at EuroPython about GR, a framework for visualization systems.  So let me start with a question. Who is already using some scientific software with Python  such like Medplotlib, Mayavi, VTK or... Okay, that's a big number.  As mentioned, I'm working at a research company and in the past years it turned out that there is a growing need  for better and faster visualization software, especially scientists need easy-to-use methods  for visualizing two and three-dimensional data sets, possibly with a dynamic component.  And they want to create publication quality graphics and videos for their publications probably in the Internet.  And they want to make glossy figures for high-impact journals or press releases.  At first glance, those methods don't seem to be very challenging but we are talking about it later.  There are a lot of scientific plotting methods we need such as line bar graphs, curve plots,  scatter plots, all these things you see on the slide here.  In principle, this is nothing challenging and there are dozens of solutions for all these kinds of plotting methods.  There are also powerful software libraries for scientific applications in Python.  Those listed here on this slide are the most popular ones, I think.  Maybe I've forgotten one.  But we all know Medplotlib, which is the workhorse and the defect of standard concerning graphics in Python.  And there's even MyAvi for three-dimensional applications, MyAvi, which is very powerful and based on VTK.  And it offers an application interface called MLab, which can be used in your own scripts.  There's VTK, it's very versatile, but it's difficult to learn because it's a very low-level system.  And we have tools like Wispy and OpenGL, which are both very fast and which are limited to 3D  and which are really the lowest-level APIs for graphics with Python.  And there are also some GUI tools, just like QWT, with its corresponding 3D equivalents.  And the problem with this is that they are currently unmaintained, at least for what my information is.  So there are some problems so far.  And the main problem, I think, is that the 2D world and the accelerated 3D world are separated.  You won't find a tool which provides services for both 3D and 3D graphics.  And another problem is that some graphics backends only produce kind of figures.  So it's not possible to present continuous data streams from life sources.  And also, I've made the experience that there's only a bare minimum level of interoperability.  So user interaction is somehow limited with these tools.  Also, if we are talking about analyzing large data sets, we often see that there's only a poor performance.  And also, these APIs are partly device and platform-independent.  So your own scripts will suffer from some system dependencies after the time.  Okay, so let's Python get up and running and push for Python.  There is a very nice distribution which has been introduced to you in the keynote this morning.  It's called Anaconda.  And I would really like to recommend this distribution as it's very easy to install a complete scientific Python stack.  But I think we need something more.  For example, we need some more performance.  And this can also be achieved by Anaconda at once.  For example, number, which is also be mentioned this morning, which is capable of accelerating number of your Python applications based,  which contain NumPy code, even on GPU hardware or multi-core processors.  And I will give some examples later.  There's something more.  We also want to achieve more graphics performance and interoperability.  And for this purpose, I would like to introduce our GR framework, which is a universal framework for cross-platform visualization.  And the main key points are that it has a procedural graphics back end.  So you can really present continuous data streams.  And it has built-in device drivers so you can visualize both 2D and 3D scenes in one canvas.  And there's a very good interoperability with GUI toolkits so you can establish a very good user interaction.  And as you can see in the bottom part of the slide, it's also very easy to install.  So this would be our complete scientific Python distribution.  I think we have everything we need, especially we have more performance and interoperability.  So let me give some examples how this looks live.  You can see here a numeric simulation of a damp pendulum.  The calculation is done in the RKV, RK4 function.  You can see which is simply a numerical integration of this differential equation.  And you can see that you can mix graphics with test formulas.  And you can do all these things live while your script is running.  You don't have to produce figures or something like this.  The same works for 3D. You can see it here.  In this case, visualization is done with an API which has been written by a colleague of mine, Florian Riem.  And he has written an openGL layer for GR, which is called GR3.  And you see it's very performant and it does its job.  You can even visualize live signals from ray files or from the microphone.  And with lock x-axis, and this all runs in real time.  These are all things which are very hard to realize with other tools.  You can do this also in 3D.  Adjust, push the audio away so you can focus on the graphics.  So the frequency spectrum is, in this case, visualized by a surface plot,  which is realized with openGL and it's that fast as you could see.  You can also produce graphics with user interaction.  You can see here an MRI application which renders some MRI data through a margin cubes algorithm,  which is part of our software and which can be rendered very, very fast and moved with a mouse.  So let's talk again about performance.  We not only have some needs for more graphics performance, but also for numerical performance.  And as mentioned before, there's something called NUMBER which is part of Anaconda,  but you also can install it for your own.  And there's NUMBER PRO which has some additional features.  It's part of Anaconda Accelerate, which costs a few bucks.  I don't know the actual price.  It's capable of calculating NUMPAI expressions on the GPU,  so you can write your own GPU kernels in Python.  And it's a very nice tool and it's worth to look at this software.  And there are even other tools like KU, BLAST KU, FFT, KURAND,  those tools are just dedicated to CUDA hardware.  So in this case, you can see how you can profit from such software.  You see particle simulation which is very slow,  currently running at three frames per second.  And just by adding some decorators and an import statement for sure,  you can increase the performance by times 15, I think.  So you don't have to change your code and you can speed up your application enormously.  This is calculated in real time.  This would not be possible with poor Python.  If you run this simulation in Python, I think each frame is about three seconds.  In this case, it was paralyzed or vectorized.  This is several examples in our demo suite.  Just take a look at the website and you will see how the different optimizations work.  So let me introduce some of our success stories.  We have integrated our software in several of our applications.  We are working both for experimental physicists and for theoretical physicists.  And this is something for our instruments.  It's a live display for a small-angle neutron diffractometer.  And as you could see, you can set the region of interest  and the surface is generated in real time.  You can rotate it, you can flip the axis, and there's even more.  And all this can be done in real time.  So this is another example.  Here we are processing a huge data set.  And it's also done in real time.  And this was formally done by a proprietary solution.  And with a GR framework, we could embed this into a QT4 application,  which was a replacement for the existing solution,  and which is much faster, which can produce movies and all these funny things.  There's another example here.  Nicos is a very complex network-based control system,  which is used at the Proxima's reactor mention in Munich  for all the instruments which do neutron scattering.  And in this case, we replaced by QVT, QWT application with a QTGR application.  And it was much faster, it was more responsive,  it had some additional features which we didn't have before.  So this is a case study to see how fast you can simulate data.  Born is a software for simulating neutron and X-ray scattering.  To compare it, it was a replacement for medplotlib at this point,  and it uses a single call.  It's the line just in the bottom of the left side.  And if you look at the old code, if you compare the old source code with a new one,  well, that's only one line and an export statement to generate a movie, for example.  So it's not such complicated to produce movies with a GR framework.  So what are the conclusions?  The use of Python with our GR framework and Numba, and perhaps Numba Pro extensions,  allows the realization of high-performance visualization applications,  both in scientific and technical environments.  And the GR framework can seamlessly be integrated into any Python environment.  So I would suggest to use Anaconda.  The integration is simply done by a C-type mechanism,  so you can also use it in your own Python distribution.  And the combination, Condor and Anaconda,  provide a very easy to manage and ready to use Python distributions  that can be enhanced by the use of our GR framework,  especially with its functions for real-time or 3D visualization functions.  So what's next?  We are not far from implementing a molecular dynamics package,  which will produce such results.  We have already all this stuff written in C,  and we simply have to write some simple wrappers which will then be integrated into our GR framework.  And with this framework, you will be able to do things like this here.  This is a simulation which has been calculated on a very big machine,  and the data is read with a simple Python script,  and then rendered with a GR3 library.  You can then export this scene to, for example, Povray,  and produce high-quality graphics like shown in the right side of the slide.  And you can even do this in highest resolution  if you give the correct parameters to those routines.  And you can see here it's a very realistic presentation of a DNA.  So what are our future plans?  Well, we have thought to combine the power of MADplotlib and GR,  and we think it should be possible,  and the basic idea is to use GR as a MADplotlib back-end.  So this would speed up MADplotlib,  and all your MADplotlib scripts would profit from this speedup.  I think it's possible we didn't start this development,  but I think there's a good chance that we get these things running.  And there are even more challenges.  You learned about Bokeh this morning,  and I think this should also be possible.  Once we have the MADplotlib integration,  it should also be possible to connect those scripts to the Bokeh back-end,  which Travis mentioned this morning in the keynote.  At this point, I think we should talk to Travis to cooperate.  On this slide, you find some resources.  There's a website for our framework.  There's a Git repu.  It's posted on the Py package index.  We even have first Beanstar binary distributions for the GR framework,  and the talk should be online on this link,  which you can find out later.  So some closing words.  Maybe you hate me after this,  but I think that's important.  I think that visualization software could be even better if the prerequisites  of an application would be described in terms of usability,  responsiveness, and interoperability,  instead of a list of software with module dependencies.  We should use native APIs on the different systems instead of GUI toolkits,  and release updates should not break version compatibility.  This is something that I have observed very often.  So let me end up, and thank you for your attention.  Thanks for this great talk.  One of the features of Macplotlib that I find very convenient  is its integration with iPython notebook,  and I play with the visualization before I integrate it into some application  or save a high resolution copy for publication or something like that.  So I wonder if is the GR framework compatible with iPython notebook,  and I use it from there?  Right now it's not, but because there's some discrepancy.  On the one side we are talking about immediate mode graphics,  and with iPython notebook there's just a sequence of commands,  and maybe if we get our Macplotlib back-end running  as we consider that it could work,  then it might be possible to use it in iPython,  but I'm not sure about this.  Thank you.  We'll do our best.  Thanks.  I'm doing a lot of training of neural networks inside CYthon,  almost completely outside of Glober and Teptoloc.  Would it be possible for me to bind to CAPIs or CYthon APIs  that are excluding Glober and Teptoloc,  or do I have to bind back through Python then?  As I want to visualize the training of the network during the training process,  I think this would be really cool for that.  I'm not sure about this.  I think we have to talk about this after the session.  Sorry.  Are there any more questions?  Okay, I have a question.  When you use the Specterize decorator,  and you use the same code in the limited or the basic number version,  will this just do nothing,  complain with the name error or something, or import error?  Is the Specterize decorator available?  I mean, even if it does nothing in the basic number version.  So, do you mean if it's not present on your machine?  Yeah, okay.  I mean, for example, you have the Specterize,  which I think I understood only works for the pro version,  and if you have only the basic version and sort the number.  The problem is that the pro version is capable of pushing those LLVM code on your GPU,  and the public version is only capable of parallelizing on your own CPU.  So, the pro version is only needed if you want to use your GPU  for the computing of NumPy operations.  What I meant is if I get code from you, which has the Specterize decorator,  and I only have the basic version installed,  will it just not vectorize but otherwise ignore the vectorize decorator?  No, this would not work.  So, if you want to try those demos,  you really have to purchase the pro version.  There are a lot of other demos which don't depend on the pro version.  Okay, thanks a lot.  Okay, if there are no questions, have been added?  Okay, so thanks again. Yeah.
Josef_Heinen_-_Scientific_Visualization_with_GR_0_383.png Josef_Heinen_-_Scientific_Visualization_with_GR_384_3071.png Josef_Heinen_-_Scientific_Visualization_with_GR_3072_3743.png Josef_Heinen_-_Scientific_Visualization_with_GR_3744_5663.png Josef_Heinen_-_Scientific_Visualization_with_GR_5664_5975.png Josef_Heinen_-_Scientific_Visualization_with_GR_5976_6611.png Josef_Heinen_-_Scientific_Visualization_with_GR_6612_7535.png Josef_Heinen_-_Scientific_Visualization_with_GR_7536_9047.png Josef_Heinen_-_Scientific_Visualization_with_GR_9048_10403.png Josef_Heinen_-_Scientific_Visualization_with_GR_10404_10859.png Josef_Heinen_-_Scientific_Visualization_with_GR_10860_11303.png Josef_Heinen_-_Scientific_Visualization_with_GR_11304_11795.png Josef_Heinen_-_Scientific_Visualization_with_GR_11796_11903.png Josef_Heinen_-_Scientific_Visualization_with_GR_11904_12359.png Josef_Heinen_-_Scientific_Visualization_with_GR_12360_13703.png Josef_Heinen_-_Scientific_Visualization_with_GR_13704_15995.png Josef_Heinen_-_Scientific_Visualization_with_GR_15996_17015.png Josef_Heinen_-_Scientific_Visualization_with_GR_17016_18755.png Josef_Heinen_-_Scientific_Visualization_with_GR_18756_19583.png Josef_Heinen_-_Scientific_Visualization_with_GR_19584_20687.png Josef_Heinen_-_Scientific_Visualization_with_GR_20688_21899.png Josef_Heinen_-_Scientific_Visualization_with_GR_21900_23531.png Josef_Heinen_-_Scientific_Visualization_with_GR_23532_24095.png Josef_Heinen_-_Scientific_Visualization_with_GR_24096_25247.png Josef_Heinen_-_Scientific_Visualization_with_GR_25248_25343.png Josef_Heinen_-_Scientific_Visualization_with_GR_25344_27731.png Josef_Heinen_-_Scientific_Visualization_with_GR_27732_30923.png Josef_Heinen_-_Scientific_Visualization_with_GR_30924_34799.png Josef_Heinen_-_Scientific_Visualization_with_GR_34800_34947.png