Introduction

This module contains two distinct methods for:

  1. Particle visualisation
  2. Coarse grained data visualisation

These methods both leverage three.js to render the visualisations in the browser. Visualisation options are controlled by setting the URL of the browser correctly.

Installation

To be able to view local data, that data needs to be served from a local server. This can be done by using the TexturingServer described elsewhere, or if no texturing is needed, two lightweight servers are included that work under Python or JS:

TexturingServer method

Follow the instructions to compile the TexturingServer.

JS Method

  1. Install node.js. Try sudo apt-get install nodejs (tested with node.js v11.13.0)
  2. Install required packages by running npm install express cors glob

Python method

This should work under python2 or python3, with no additional dependencies, so as long as you have either of these installed on your system you have no need to install anything

Usage

  1. Navigate to the main github directory and run node server.js or python server.py or ./Texturing/TexturingServer to start a web server which will be used to serve local files.
  2. Open visualise/index.html in chrome or firefox. Supermedium is recommended if you want to use VR.
  3. Visualisation flags can either be hardcoded in index.html or can be set via the URL, for example: index.html?fname=Samples/SpinnerD5/&view_mode=rotations

Flags:

  • fname: folder name where data is stored. Trailing slash is optional. Default is Samples/D4/
  • display_type: VR, keyboard or anaglyph. Default is keyboard.
  • view_mode: undefined (normal and default), catch_particle, rotations, rotations2, velocity or rotation_rate. rotations requires the TexturingServer to be running and works in any number of dimensions. rotations2 can be computed in the browser, and can be used with any server, and does the calculations on the GPU at render time, but only works for N = 3 or 4.
  • autoplay: true or false to start time marching on load. Default is false.
  • rate: float that sets the speed of time marching. Units are DEM time units\second. Default is 5.0.
  • shadows: true or false to render shadows. Default is true.
  • quality: int to set quality of rendering. Higher is more compute expensive. Default is 5.
  • zoom: float to set how much to zoom in. Default is 20.
  • pinky: only used if view_mode is catch_particle. int that sets which particle to render in pink. Default is 100.
  • cache: true or false to cache local data in the browser. Default is false.
  • hard_mode: true or false to disable tori in VR mode to make things harder for the user. Default is false. This is meant to be more 'fun' but YMMV.
  • no_axes: include this flag to disable drawing of axes.
  • no_walls: include this flag to disable drawing of walls.
  • quasicrystal: true or false to view in quasicrystal mode. Default is false.
  • mercury: true or false to load MercuryDPM data instead of NDDEM data. Default is false.
  • colour_scheme: set to inverted to invert global colour scheme to have a white background.
  • rotate_torus: float to rotate the torus around the x1 axis in degrees
  • record: true or false to save frames when autoplay is ticked. Default is false.
  • initial_camera_location: three numbers (e.g. initial_camera_location=1,2,3) to set the initial camera location if so desired.
  • camera_target: three numbers (e.g. camera_target=1,2,3) to set what the camera is pointing at if so desired.
  • t0: float to set the initial timestep to display. Default is 0.
  • binary: if included, this flag loads from binary data instead of csv data. You can convert csv to binary data using the included script binarise_output.py in the scripts folder.

An example command that works for me, when the TexturingServer is running: /path/to/index.html?fname=D5Cristal/&view_mode=D4&colour_scheme=inverted&time=350&rate=5&display_type=keyboard

Particle visualisation

Below is the default output of the visualisation software for a 3D simulation of spheres flowing down an inclined plane. You can manually move through time, or enable auto playing in the top right. The speed it is playing can be controlled with the "Rate" parameter.

Getting around in ND

But what about dimensions higher than 3? For this, we need some way to project particles from higher dimensions down to 3D. In this example, we will project a 3D sphere down to a 2D circle by slicing it. Move the pink plane on the left around with the slider and see the resulting size of the circle on the right. The circle is largest when the sphere is sliced through its centre.

Now, lets try that same thing, but we are going to slice a 5D hypersphere with a 3D volume. For this, there are two coordinates for where we are slicing, which you can control with the sliders. The torus on the right hand side represents where we are in these two dimensions. Notice how as you move around, the small pink ball moves. This small pink ball represents the location of the hypersphere relative to these two coordinates. The sphere on the left is again largest when we slice through its centre — when the ball is at the centre of the black cross

Let's now go and look at inclined plane flow in 5D

Particle rotation

To be able to see a particle rotate, we need to attach a texture to it. Here is how we visualise the earth rotating.

In 3D, there are three directions that an object can rotate in.

As we can't render the textures needed to do this without a local installation, here is a video explaining how rotations work

Trying out VR (this will look blank if you don't have a VR headset attached)

Coarse grained data

Reference

build_world

Initialise the threejs scene, adding everything necessary, such as camera, controls, lighting etc.

build_world()

update_higher_dims_left

Get the current orientation of the left hand controller and set world coordinates appropriately

update_higher_dims_left()

update_higher_dims_right

Get the current orientation of the right hand controller and set world coordinates appropriately

update_higher_dims_right()

add_left_oculus_model

Add the left oculus controller

add_left_oculus_model(controller: number)
Parameters
controller (number) controller number (0 or 1)

add_right_oculus_model

Add the right oculus controller

add_right_oculus_model(controller: number)
Parameters
controller (number) controller number (0 or 1)

add_vive_models

Add the two vive controllers

add_vive_models()

make_camera

Make the camera and position it

make_camera()

add_renderer

Add the renderer and associated VR warnings if necessary

add_renderer()

add_gui

Add the non-VR GUI and set all sliders

add_gui()

add_controllers

Add the non-VR and/or VR controllers and associated buttons

add_controllers()

aim_camera

If the current example requires a specific direction for the camera to face at all times (e.g. a 1D or 2D simulation) then set that

aim_camera()

make_axes

Make the axes, including labels and arrows

make_axes()

make_lights

Make the scene lighting

make_lights()

make_walls

Make any necessary walls

make_walls()

add_torus

Add the torus(es) as necessary

add_torus()

remove_everything

Remove everything from scene - very useful for presentation mode when we don't want to kill the computer by loading multiple scenes simultaneously

remove_everything()

make_initial_sphere_texturing

Make the initial texturing if showing rotations

make_initial_sphere_texturing()

make_initial_spheres_Mercury

Load particles from MercuryDPM file format - NOTE: THIS IS NOT WORKING YET

make_initial_spheres_Mercury()

make_initial_spheres_CSV

Make the initial particles

make_initial_spheres_CSV()

load_textures

Load textures from TexturingServer

load_textures(t: number, Viewpoint: number)
Parameters
t (number) timestep
Viewpoint (number) where we are in D>3 space

update_spheres_texturing

Update textures from TexturingServer

update_spheres_texturing(t: number)
Parameters
t (number) timestep

update_spheres_CSV

Update sphere locations

update_spheres_CSV(t: number, changed_higher_dim_view: number)
Parameters
t (number) timestep
changed_higher_dim_view (number) flag to determine if we have changed which dimensions we are representing --- NOTE: CURRENTLY NOT DOING ANYTHING

onWindowResize

Update camera and renderer if window size changes

onWindowResize()

check_if_won

In catch_mode, let the user know if they found the pink ball

check_if_won()

animate

Animation loop that runs every frame

animate()

render

Do the actual rendering

render()

remove_loading_screen

Remove loading screen

remove_loading_screen()