Interactive HTML with Python and X3D: a red dice example
------Created January 2015 by F.P.A.Vogt for the ANITA astroinformatics summer school 2015. Initial version included in the 2015 PhD thesis of Vogt at the Australian National University (DOI:10.4225/13/5553E63D6A79A). Published in updated form as supplementary material in Vogt+, ApJ 818, 115 (2016).
Questions, comments : frederic.vogt@alumni.anu.edu.au
If you find this code useful for your research, please cite the following article accordingly:
Vogt, Owen, Verdes-Montenegro & Borthakur, Advanced Data Visualization in Astrophysics: the X3D Pathway, ApJ 818, 115 (2016). (arXiv; ADS)
------
This file illustrates how to create high quality interactive HTML documents using the X3D & X3DOM approach. The input 3-D models used in this example were created using the Mayavi module in Python, but any 3-D model stored as an X3D file can be included within an HTML page in the same way. This document does NOT explore the full potential of the X3D standard ! The interested reader is referred to the detailed X3DOM documentation for more details.
First thing first, one should ensure that the web browser currently used does support X3DOM here. See this page for a detailed list of all supported web browsers. This HTML document has been tested successfully with Firefox, Safari and Chrome.
Let us now get started by displaying a simple green dice (see also green_dice.html for a fully stripped-down version).
Once the 3D model has loaded, it can be freely rotated, zoomed in/out and panned around. The X3D file was generated using the Python script green_dice.py, and is included in the most straight-forward manner inside the HTML page as follows:
<html>
<head>
<title>Python + X3D dices</title>
<script type='text/javascript' src='x3dom/x3dom.js'> </script>
<link rel='stylesheet' type='text/css' href='x3dom/x3dom.css'></link>
<style>
x3d{
border:2px solid darkorange;
}
</style>
</head>
<body>
<x3d width='1000px' height='400px', margin-left='300px'>
<scene>
<inline url="./data/green_dice.x3d" nameSpaceName="GreenDice" mapDEFToID="true" onclick=''/>
</scene>
</x3d>
</body></html>
For this specifc example, the result looks and behaves just fine, and there isn't much else needed. One should note that in order to allow for offline access to the interactive model, the files x3dom.js and x3dom.css can included with an HTML document as supplementary material. Alternatively, substituting the following lines :
will result in an interactive HTML document that doesn't require a local copy of the x3dom.css and x3dom.js files at the price of being solely accessible when connected to the World Wide Web.
All these issues are unfortunate limitations of the existing Mayavi/VTK X3D exporter that will hopefully be corrected in the future. In anycase, all these issues can already be corrected manually inside the X3D file itself as follows. All the modifications to the original X3D file (red_dice.x3d) are tagged with a comment line with the structure
With these modifications, the red dice now looks as it should. <script type='text/javascript' src='http://www.x3dom.org/x3dom/release/x3dom.js'> </script>
<link rel='stylesheet' type='text/css' href='http://www.x3dom.org/x3dom/release/x3dom.css'></link>
Most likely, many Astrophysical models will be more complex than this simple green dice example, and might include transparent layers, text, colorbars, etc ... One might also want to add interaction buttons to the scene to show/hide certain datasets, direct the attention of readers to certain features, move to pre-set points-of-view, etc ... Let us have a look at some of these additions using the example below: a red semi-transparent dice with two spheres inside it.
This example was generated using the red_dice.py Python script, specifically designed to hit some of the current limits of the Mayavi X3D exporter (namely, the VTK X3D Exporter v0.9.1). Hence, some visual issues are present in the interactive model above, including:
<!-- FPAV: ... -->
in the corrected X3D file (red_dice_mod.x3d) for rapid identification.
<Apperance sortKey="0">
. The counter goes from in to out , i.e. ''0'' indicates the inner-most transparent layer, etc ...
<DepthMode readOnly="true"></DepthMode>
scale="0.02 0.02 0.02"
option in the <FontStyle> tag and the solid="false"
option in the <Text> tag, respectively. One should note that although one could alter the text size directly within the FontStyle
tag via the size="10"
parameter, our experiments have shown that a few text elements with large sizes (e.g. size="40"
) can very significantly slow down the load-time of a model. In such a case, one ought to reduce the size
value and increase the scale
instead.
<Transform translation="0 0 0" rotation="0 0 1 -0" scale="1 1 1">
. The rotation in the X3D format is a set of 4 numbers. The first three define the x, y and z component of the rotation vector in 3-D (i.e. the vector perpendicular to the plane of rotation), while the 4th element is the rotation angle in radians.
on="false"
option inside the different <DirectionLight>
tags. In our experience, leaving a single headlight on will usually give the best results.
One might now wish to add more features. Of particular interest for Astrophysical applications are interaction buttons (for specific points of view and datasets visibility), and colorbars.
DEF="my_layer_name"
tag inside the <Material>
tag for each layer. Unfortunately, layer names attributed inside Mayavi are currently NOT exported to X3D by the Mayavi/VTK X3D exporter, that replaces them with generic ones (which must then be replaced manually inside the X3D file). To hide a given layer, one simply sets its transparency to 100%. To do so, one first defines a function inside the HTML page, e.g. in the present case for the white sphere (labelled as ''outer_sphere'' in the X3D file) inside the red dice:
<script>
function setSphere()
{
if(document.getElementById('RedDiceFixed__outer_sphere').getAttribute('transparency')!= '0.5')
document.getElementById('RedDiceFixed__outer_sphere').setAttribute('transparency', '0.5');
else
document.getElementById('RedDiceFixed__outer_sphere').setAttribute('transparency', '1');
}
</script>
And then one adds an interaction button that calls this function with:
<button onclick="setSphere();" style="color:FireBrick">White sphere</button>
The function then switches the transparency of the layer between 100% (invisible) and 50% (semi-transparent, the original value) each time the button is clicked.
<x3d>
tag inside the HTML document with
<OrthoViewpoint id="front" bind='false' centerOfRotation='0,0,0' description='front view' fieldOfView='[-1,-1,1,1]' isActive='false'
metadata='X3DMetadataObject' orientation='0,0,0,3.14' position='0,0,10' zFar='100' zNear='-10' ></OrthoViewpoint>
Viewpoints can also be defined directly in the X3D file. Specific viewpoints can then be activated by the reader via buttons defined as follows in the HTML document:
<button onclick="document.getElementById('front').setAttribute('set_bind','true');">Front</button>
In addition, a reset button for the current view can be created using:
<button onclick="document.getElementById('red_cube_fixed').runtime.resetView();">Reset View</button>
And for simplicity and clarity when defining several generic viewpoints, these can be toogled in a row using:
<button onclick="document.getElementById('red_cube_fixed').runtime.nextView();">Next View</button>
<background backUrl="..."></background>
. For consistency, one also ought to remove any background definition inside the X3D file by commenting out the corresponding command <!-- <Background skyColor="0.5 0.5 0.5"/> -->
. doPickPass
attribute as follows: < scene doPickPass="false">
. < Billboard> ... </Billboard>
tags. See this page for more details.<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.3//EN"
"http://www.web3d.org/specifications/x3d-3.3.dtd">
<X3D profile="Immersive" version="3.3" xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance"
xsd:noNamespaceSchemaLocation="http://www.web3d.org/specifications/x3d-3.3.xsd">
Similarly, one might also want to expand the metadata information regarding the file, e.g. in the present case with <meta name="title" content="red_dice_mod.x3d"/>
, <meta name="creator" content=" ..."
and <meta name="description" content=" ..." />
.
Pulling everything together, the corrected/upgraded red dice example looks like this:
Compared to the default red dice imported in HTML straight from Python, this second example is better behaved and more reader friendly. Action buttons are especially useful to direct the reader's attention to specific elements of a given model easily.
The X3D Validator is an online tool that allows to inspect one's X3D files and check for errors and syntax issues within. While X3DOM specific syntax (such as doPickPass
and DepthMode
) will raise errors, this tool remains useful to iron-out any significant syntax issue before releasing/publishing an X3D file. For X3D files generated with Mayavi, one error raised by the Validator is that inside Text
node, strings should be defined with both single AND double quotation marks (e.g. < Text string=' " What a string ! " '></Text>
). But text strings exported from Mayavi via the VTK X3D Exporter v0.9.1 only have a double quotation marks, which the X3D Validator flags accordingly.
Further information on the different nodes and syntax elements available in the X3D & X3DOM standards is available in the official X3DOM documentation. Authors publishing their interactive Figures in AAS journals ought to use a width of 600 pixels for the interactive X3D panel width - the standard size adopted (and required) by these publications.