# root-project/jsroot

Switch branches/tags
Nothing to show
0f88a92 May 15, 2018
2 contributors

### Users who have contributed to this file

836 lines (577 sloc) 42.7 KB

# JavaScript ROOT

The JSROOT project intends to implement ROOT graphics for web browsers. Reading of binary ROOT files is supported. It is the successor of the JSRootIO project.

## Installing JSROOT

In most practical cases it is not necessary to install JSROOT - it can be used directly from project web sites https://root.cern/js/ and http://jsroot.gsi.de/.

When required, there are following alternatives to install JSROOT on other web servers:

• use bower package manager and invoke bower install jsroot
• clone master branch from repository

One could use JSROOT directly from local file system. If source code was unpacked/checked-out in /home/user/jsroot/ subfolder, one could just open it in browser with file:///home/user/jsroot/index.htm address.

## Drawing objects in JSROOT

The main page of the JSROOT project provides the possibility to interactively open ROOT files and draw objects like histogram or canvas.

To automate files loading and objects drawing, one can provide number of URL parameters in address string like:

• file - name of the file, which will be automatically open with page loading
• localfile - automatically activate dialog for selecting local ROOT files
• json - name of JSON file with stored ROOT object like histogram or canvas
• item - item name to be displayed
• opt - drawing option for the item
• items - array of items name
• opts - array of drawing options for the items
• title - set browser title
• layout - can be 'simple', 'flex', 'collapsible', 'tabs', 'gridNxM', 'horizNMK', 'vertNMK'
• browser - layout of the browser 'float', 'fix', 'no', 'off'
• nobrowser - do not display file browser (same as browser=no)
• float - display floating browser (same as browser=float)
• status - configure status line 'no' (default), 'off' (completely disable), 'size'
• optimize - drawing optimization 0:off, 1:only large histograms (default), 2:always
• paltte - id of default color palette, 51..121 - new ROOT6 palette (default 57)
• interactive - enable/disable interactive functions 0 - disable all, 1 - enable all
• noselect - hide file-selection part in the browser (only when file name is specified)
• mathjax - use MathJax for latex output
• latex - 'off', 'symbols', 'normal', 'mathjax', 'alwaysmath' control of TLatex processor
• style - name of TStyle object to define global JSROOT style
• toolbar - show canvas tool buttons 'off', 'on' and 'popup', 'left' or 'right' for position, 'vert' for vertical
• divsize - fixed size in pixels for main div element like &dvisize=700x400

For instance:

Following layouts are supported:

• simple - available space used for single object (default)
• collapsible - fix-sized canvas group behind each other and can be collapsed individually
• flex - creates as many frames as necessary, each can be individually moved/enlarged
• tabs - tabs widget
• gridNxM - fixed-size grid with NxM frames
• gridiNxM - grid with NxM frames with possibility to adjust frames sizes
• vertN - N frames sorted in vertical direction (like gridi1xN)
• horizN - N frames sorted in horizontal direction (like gridiNx1)
• vert121 - 3 frames sorted in vertical direction, second frame divided on two sub-frames
• horiz32_12 - 2 horizontal frames with 3 and 2 subframes, and 1/3 and 2/3 as relative size

When specifying files, items or opts parameters, array of strings could be provided like files=['file1.root','file2.root']. One could skip quotes when specifying elements names items=[file1.root/hpx,file2.root/hpy] or opts=['',colz].

As item name, URL to existing image can be provided like item=img:http://server/image.png. Such image will be just inserted in the existing layout. One could specify option "scale" to automatically scale image to available space.

Many examples of URL string usage can be found on JSROOT examples page.

One can very easy integrate JSROOT graphic into arbitrary HTML pages using a iframe tag:

<iframe width="700" height="400"
src="https://root.cern/js/latest/?nobrowser&file=../files/hsimple.root&item=hpxpy&opt=colz">
</iframe>


## Supported ROOT classes by JSROOT

List of supported classes and draw options:

More examples of supported classes can be found on: https://root.cern/js/latest/examples.htm

## Superimposing draw objects

In the URL string one could use "+" sign to specify objects superposition:

Analogue, one could specify individual draw options for superimposed objects

Here "logy" option will be used for "hpx1" item and "hist" option for "hprof;1" item.

While draw option can include "+" sign itself, for superposition one could specify arrays of items and draw options like:

## TTree draw

JSROOT provides possibility to display TTree data, using TTree::Draw syntax:

Histogram ranges and binning defined after reading first 1000 entries from the tree. Like in ROOT, one could configure histogram binning and range directly:

One and two dimensional draw expressions can be resulted into TGraph object, using ">>Graph" as output:

For any integer value one can accumulate histogram with value bits distribution, specifying as output ">>bits(16)" or ">>bits":

There is special handling of TBits objects:

It is allowed to use different expressions with branch values:

Such expression can include arithmetical operations and all methods, provided in JavaScript Math class:

In the expression one could use "Entry$" and "Entries$" variables.

One also could specify cut condition, separating it with "::" from the rest draw expression like:

Contrary to the normal ROOT, JSROOT allows to use "(expr?res1:res2)" operator (placed into brackets):

It is possible to "dump" content of any branch (by default - first 10 entries):

Or one could dump values produced with draw expression (also first 10 entries by default):

Working with array indexes is supported. By default, all elements in array are used for the drawing. One could specify index for any array dimension (-1 means last element in the array). For instance, dump last element from event.fTracks array:

For any array or collection kind one could extract its size with expression:

At the end of expression one can add several parameters with the syntax:

<draw_expession>;par1name:par1value;par2name:par2value


Following parameters are supported:

• "first" - id of the first entry to process
• "entries" - number of entries to process
• "monitor" - periodically show intermediate draw results (interval in milliseconds)
• "maxrange" - maximal number of ranges in single HTTP request
• "accum" - number of accumulated values before creating histogram
• "htype" - last letter in histogram type like "I", "F", "D", "S", "L", "C"
• "hbins" - number of bins on each histogram axis
• "drawopt" - drawing option for produced histogram
• "graph" - draw into TGraph object

## Geometry viewer

JSROOT implements display of TGeo objects like:

Following classes are supported by geometry viewer:

• TGeoVolume
• TGeoNode
• TGeoManager (master volume will be displayed)
• TEveGeoShapeExtract (used in EVE)

Following draw options could be specified (separated by semicolon or ';'):

• axis - draw axis coordinates
• z - set z axis direction up (normally y axis is up and x looks in user direction)
• clipx/clipy/clipz - enable correspondent clipping panel
• clip or clipxyz - enable all three clipping panels
• ssao - enable Smooth Lighting Shader (or Screen Space Ambient Occlusion)
• wire - instead of filled surfaces only wireframe will be drawn
• more - show 2 times more volumes as usual (normally ~2000 volumes or ~100000 elementary faces are shown)
• more3 - show 3 times more volumes as usual
• all - try to display all geometry volumes (may lead to browser hanging)
• highlight - force highlighting of selected volume, normally activated for moderate-size geometries
• nohighlight - disable volumes highlighting (can be activated via context menu)
• hscene - enable highlight of extra objects like tracks or hits
• hsceneonly - enable only highlight of extra objects like tracks or hits
• nohscene - disable highlight of extra objects like tracks or hits
• macro:name.C - invoke ROOT configuration macro
• dflt - set default volumes colors as TGeoManager::DefaultColors() does
• transpXY - set global transparency value (XY is number between 1 and 99)
• zoomFACTOR - set initial zoom factor (FACTOR is integer value from 1 to 10000, default is 100)
• rotate - enable automatic rotation of the geometry
• tracks - show tracks from TGeoManager
• dray - calculate rendering order using raytracing (extensive calculations)
• dbox - use distance to nearest point from bounding box for rendering order (default)
• dpnt - use distance to shape center as rendering order
• dsize - use volume size as rendering order
• ddflt - let three.js to calculate rendering order

It is possible to display only part of geometry model. For instance, one could select sub-item like:

Or one can use simple selection syntax (work only with first-level volumes):

Syntax uses '+' sign to enable visibility flag of specified volume and '-' sign to disable visibility. One could use wildcard symbol like '+TUBE1*'.

Another way to configure visibility flags is usage of ROOT macros, which typically looks like:

{
TGeoManager::Import("http://root.cern/files/alice2.root");
gGeoManager->DefaultColors();
//   gGeoManager->SetVisLevel(4);
gGeoManager->GetVolume("HALL")->InvisibleAll();
gGeoManager->GetVolume("ZDCC")->InvisibleAll();
gGeoManager->GetVolume("ZDCA")->InvisibleAll();
...
gGeoManager->GetVolume("ALIC")->Draw("ogl");
new TBrowser;
}


Example of such macro can be found in root tutorials.

From provided macro only following calls will be executed in JSROOT:

• gGeoManager->DefaultColors()
• gGeoManager->GetVolume("HALL")->InvisibleAll()
• gGeoManager->GetVolume("HALL")->SetTransparency(30)
• gGeoManager->GetVolume("HALL")->SetLineColor(5)
• gGeoManager->GetVolume("ALIC")->Draw("ogl")

All other will be ignored.

Example of major LHC detectors:

Other detectors examples:

Together with geometry one could display tracks (TEveTrack) and hits (TEvePointSet, TPolyMarker3D) objects. Either one do it interactively by drag and drop, or superimpose drawing with + sign like:

There is a problem of correct rendering of transparent volumes. To solve problem in general is very expensive (in terms of computing power), therefore several approximation solution can be applied:

• dpnt: distance from camera view to the volume center used as rendering order
• dbox: distance to nearest point from bonding box used as rendering order (default)
• dsize: volume size is used as rendreing order, can be used for centered volumes with many shells around
• dray: use raycasting to sort volumes in order they appear along rays, comming out of camera point
• ddflt: default three.js method for rendering transparent volumes
For different geometries different methods can be applied. In any case, all opaque volumes rendered first.

## Reading ROOT files from other servers

In principle, one could open any ROOT file placed in the web, providing the full URL to it like:

But one should be aware of Same-origin policy, when the browser blocks requests to files from domains other than current web page. To enable CORS on Apache web server, hosting ROOT files, one should add following lines to .htaccess file:

<IfModule mod_headers.c>
<FilesMatch "\.root">
</FilesMatch>
</IfModule>


Alternative - enable CORS requests in the browser. It can be easily done with CORS Everywhere plugin for the Firefox browser or Allow CORS plugin for the Chrome browser.

Next solution - install JSROOT on the server hosting ROOT files. In such configuration JSROOT does not issue CORS requests, therefore server and browsers can be used with their default settings. A simplified variant of such solution - copy only the top index.htm file from JSROOT package and specify the full path to JSRootCore.js script like:

...
<script type="text/javascript" src="https://root.cern/js/latest/scripts/JSRootCore.js?gui"></script>
...


In the <div> element with "simpleGUI" id one can specify many custom parameters, which are allowed in the URL string:

...
<div id="simpleGUI" path="files/path" files="userfile1.root;subdir/usefile2.root">
</div>
...


JSROOT can read files from local file system using HTML5 FileReader functionality. Main limitation here - user should interactively select files for reading. There is button "..." on the main JSROOT page, which starts file selection dialog. If valid ROOT file is selected, JSROOT will be able to normally read content of such file.

One could try to invoke such dialog with "localfile" parameter in URL string:

It could happen, that due to security limitations automatic popup will be blocked.

For debuging purposes one can install JSROOT on local file system and let read ROOT files from the same location. Like:

• file:///home/user/jsroot/index.htm?file=hsimple.root&item=hpx

But this works only with Firefox.

## JSROOT with THttpServer

THttpServer provides http access to objects from running ROOT application. JSROOT is used to implement the user interface in the web browsers.

The layout of the main page coming from THttpServer is similar to the file I/O one. One could browse existing items and display them. A snapshot of running server can be seen on the demo page.

One could also specify similar URL parameters to configure the displayed items and drawing options.

It is also possible to display one single item from the THttpServer server like:

https://root.cern/js/latest/httpserver.C/Files/job1.root/hpxpy/draw.htm?opt=colz

## Data monitoring with JSROOT

### Monitoring with http server

The best possibility to organize the monitoring of data from a running application is to use THttpServer. In such case the client can always access the latest changes and request only the items currently displayed in the browser. To enable monitoring, one should activate the appropriate checkbox or provide monitoring parameter in the URL string like:

https://root.cern/js/latest/httpserver.C/Files/job1.root/hprof/draw.htm?monitoring=1000

The parameter value is the update interval in milliseconds.

### JSON file-based monitoring

Solid file-based monitoring (without integration of THttpServer into application) can be implemented in JSON format. There is the TBufferJSON class, which is capable to convert any (beside TTree) ROOT object into JSON. Any ROOT application can use such class to create JSON files for selected objects and write such files in a directory, which can be accessed via web server. Then one can use JSROOT to read such files and display objects in a web browser.

There is a demonstration page showing such functionality: https://root.cern/js/latest/demo/demo.htm. This demo page reads in cycle 20 json files and displays them.

If one has a web server which already provides such JSON file, one could specify the URL to this file like:

Here the same problem with Cross-Origin Request can appear. If the web server configuration cannot be changed, just copy JSROOT to the web server itself.

### Binary file-based monitoring (not recommended)

Theoretically, one could use binary ROOT files to implement monitoring. With such approach, a ROOT-based application creates and regularly updates content of a ROOT file, which can be accessed via normal web server. From the browser side, JSROOT could regularly read the specified objects and update their drawings. But such solution has three major caveats.

First of all, one need to store the data of all objects, which only potentially could be displayed in the browser. In case of 10 objects it does not matter, but for 1000 or 100000 objects this will be a major performance penalty. With such big amount of data one will never achieve higher update rate.

The second problem is I/O. To read the first object from the ROOT file, one need to perform several (about 5) file-reading operations via http protocol. There is no http file locking mechanism (at least not for standard web servers), therefore there is no guarantee that the file content is not changed/replaced between consequent read operations. Therefore, one should expect frequent I/O failures while trying to monitor data from ROOT binary files. There is a workaround for the problem - one could load the file completely and exclude many partial I/O operations by this. To achieve this with JSROOT, one should add "+" sign at the end of the file name. Of course, it only could work for small files.

If somebody still wants to use monitoring of data from ROOT files, could try link like:

In this particular case, the histogram is not changing.

## JSROOT API

JSROOT can be used in arbitrary HTML pages and disaplay data, produced without ROOT-based applications.

Many different examples of JSROOT API usage can be found on JSROOT API examples page.

Before JSROOT can be used, all appropriate scripts should be loaded. HTML pages where JSROOT is used should include the JSRootCore.js script. The <head> section of the HTML page should have the following line:

<script type="text/javascript" src="https://root.cern/js/latest/scripts/JSRootCore.js?2d"></script>


Here, the default location of JSROOT is specified. One could have a local copy on the file system or on a private web server. When JSROOT is used with THttpServer, the address looks like:

<script type="text/javascript" src="http://your_root_server:8080/jsrootsys/scripts/JSRootCore.js?2d"></script>


In URL string with JSRootCore.js script one can specify which JSROOT functionality should be loaded:

+ '2d' basic drawing functionality, support TPad/TCanvas/TFrame
+ 'hist' histograms drawing
+ 'more2d' more classes for 2D drawing like TH2/TF1/TEllipse
+ '3d' 3D drawing for 2D/3D histograms
+ 'geo' 3D drawing of TGeo classes
+ 'io' binary file I/O
+ 'tree' TTree functionality
+ 'mathjax' loads MathJax.js and use it for latex output
+ 'openui5' load and configure OpenUI5 toolkit
+ 'gui' default gui for offline/online applications


For instance, to load functionality with normal 2D graphics and binary ROOT files support, one should specify:

<script type="text/javascript" src="https://root.cern/js/latest/scripts/JSRootCore.min.js?2d&io"></script>


One could use minified version of all scripts (as shown in example) - this reduce page loading time significantly.

After main JSRootCore.js script is loaded, one can configure different options in JSROOT.gStyle object. It is instance of the TStyle object and contains similar properties. For instance, one can change stat format:

JSROOT.gStyle.fStatFormat = "7.5g"


Or specify custom format for the X/Y object values:

JSROOT.gStyle.XValuesFormat = "4.2g"
JSROOT.gStyle.YValuesFormat = "6.1f"


When JSROOT installed with bower package manager, one could re-use basic libraries like d3.js or three.js from bower itself. For that one should add bower into URL:

<script type="text/javascript" src="vendor/jsroot/scripts/JSRootCore.js?bower&2d&io"></script>


Bower support will be automatically enabled when script path conatin "bower_components/jsroot/" string.

One also could use bower and gulp to produce single script with all libraries included.
This is shown in the example https://github.com/root-project/jsroot/tree/master/demo/gulp

### Use of JSON

It is strongly recommended to use JSON when communicating with ROOT application. THttpServer provides a JSON representation for every registered object with an url address like:

http://your_root_server:8080/Canvases/c1/root.json


Such JSON representation generated using the TBufferJSON class. One could create JSON file for any ROOT object directly, just writing in the code:

...
obj->SaveAs("file.json");
...


To access data from a remote web server, it is recommended to use the XMLHttpRequest class. JSROOT provides a special method to create such object and properly handle it in different browsers. For receiving JSON from a server one could use following code:

var req = JSROOT.NewHttpRequest("http://your_root_server:8080/Canvases/c1/root.json", 'object', userCallback);
req.send(null);


In the callback function one gets JavaScript object (or null in case of failure)

If JSON string was obtained by different method, it should be parsed with:

var obj = JSROOT.parse(json_string);


### Objects drawing

After an object has been created, one can directly draw it. If HTML page has <div> element:

...
<div id="drawing"></div>
...


One could use the JSROOT.draw function:

JSROOT.draw("drawing", obj, "colz");


The first argument is the id of the HTML div element, where drawing will be performed. The second argument is the object to draw and the third one is the drawing option.

Here is complete running example ans source code:

var filename = "https://root.cern/js/files/th2ul.json.gz";
JSROOT.NewHttpRequest(filename, 'object', function(obj) {
JSROOT.draw("drawing", obj, "lego");
}).send();


In very seldom cases one need to access painter object, created in JSROOT.draw() function. This can be done via call back (forth argument) like:

JSROOT.draw("drawing", obj, "colz", function(painter) {
console.log('Object type in painter', painter.GetObject()._typename);
});


One is also able to update the drawing with a new version of the object:

// after some interval request object again
JSROOT.redraw("drawing", obj2, "colz");


The JSROOT.redraw() function will call JSROOT.draw if the drawing was not performed before.

In the case when changing of HTML layout leads to resize of element with JSROOT drawing, one should call JSROOT.resize() to let JSROOT adjust drawing size. One should do:

JSROOT.resize("drawing");


As second argument one could specify exact size for draw elements like:

JSROOT.resize("drawing", { width: 500, height: 200 } );


To correctly cleanup JSROOT drawings from HTML element, one should call:

JSROOT.cleanup("drawing");


### File API

JSROOT defines the TFile class, which can be used to access binary ROOT files. One should always remember that all I/O operations are asynchronous in JSROOT. Therefore, callback functions are used to react when the I/O operation completed. For example, reading an object from a file and displaying it will look like:

var filename = "https://root.cern/js/files/hsimple.root";
JSROOT.OpenFile(filename, function(file) {
JSROOT.draw("drawing", obj, "colz");
});
});


Here is running example and source code

### TTree API

Simple TTree::Draw operation can be performed with following code:

var filename = "https://root.cern/js/files/hsimple.root";
JSROOT.OpenFile(filename, function(file) {
JSROOT.draw("drawing", obj, "px:py::pz>5");
});
});


var filename = "https://root.cern/js/files/hsimple.root";
JSROOT.OpenFile(filename, function(file) {

var selector = new JSROOT.TSelector();

var cnt = 0, sumpx = 0, sumpy = 0;

selector.Begin = function() {
// function called before reading of TTree starts
}

selector.Process = function() {
// function called for every entry
sumpx += this.tgtobj.px;
sumpy += this.tgtobj.py;
cnt++;
}

selector.Terminate = function(res) {
if (!res || (cnt===0)) return;
var meanpx = sumpx/cnt, meanpy = sumpy/cnt;
console.log('Results', meanpx, meanpy);
}

tree.Process(selector);

});
});


Here is running example and source code

This examples shows how read TTree from binary file and create JSROOT.TSelector object. Logically it is similar to original TSelector class - for every read entry TSelector::Process() method is called. Selected branches can be accessed from tgtobj data member. At the end of tree reading TSelector::Terminate() method will be called.

As second parameter of tree.Process() function one could provide object with arguments

var args = { numentries: 1000, firstentry: 500 };
tree.Process(selector, args);


### TGeo API

Any supported TGeo object can be drawn with normal JSROOR.draw() function.

If necessary, one can create three.js model for supported object directly and use such model separately. This can be done with the function:

var opt = { numfaces: 100000};
var obj3d = JSROOT.GEO.build(obj, opt);


Following options can be specified:

• numfaces - approximate maximal number of faces in three.js model (default 100000)
• numnodes - approximate maximal number of meshes in three.js model (default 1000)
• doubleside - use double-side material (default only front side is set)
• wireframe - show wireframe for created materials (default - off)

When transparent volumes appeared in the model, one could use JSROOT.GEO.produceRenderOrder() function to correctly set rendering order. It should be used as:

JSROOT.GEO.produceRenderOrder(scene, camera.position, 'box');


Following methods can be applied: "box", "pnt", "size", "ray" and "dflt". See more info in draw options description for TGeo classes.

Here is running example and source code.

### Use with Node.js

Starting from version 5.2.0, JSROOT can be used in Node.js. To install it, use:

[shell] npm install jsroot


To use in the Node.js scripts, one should add following line:

 var jsroot = require('jsroot');


Using JSROOT functionality, one can open binary ROOT files (local and remote), parse ROOT JSON, create SVG output. For example, to create SVG image with lego plot, one should do:

var jsroot = require("jsroot");
var fs = require("fs");

jsroot.OpenFile("https://root.cern/js/files/hsimple.root", function(file) {
jsroot.MakeSVG( { object: obj, option: "lego2", width: 1200, height: 800 }, function(svg) {
fs.writeFileSync("lego2.svg", svg);
});
});
});


It is also possible to convert any JavaScript object into ROOT JSON string, using JSROOT.toJSON() function. Like:

var jsroot = require("jsroot");
var fs = require("fs");

jsroot.OpenFile("https://root.cern/js/files/hsimple.root", function(file) {
var json = jsroot.toJSON(obj);
fs.writrFileSync("hpxpy.json", json);
});
});


Such JSON string could be parsed by any other JSROOT-based application.

### Use with OpenUI5

OpenUI5 is a web toolkit for developers to ease and speed up the development of full-blown HTML5 web applications. Since version 5.3.0 JSROOT provides possibility to use OpenUI5 functionality together with JSROOT.

First problem is bootstraping of OpenUI5. Most easy solution - specify openui5 URL parameter when loading JSROOT:

  <script type="text/javascript"
</script>


JSROOT uses https://openui5.hana.ondemand.com to load latest stable version of OpenUI5. After loading is completed, specified initialization function will be called, where JSROOT.sap can be used as normal sap variable. Simple way to start any custom application is:

  <script type="text/javascript">
function doInit() {
jQuery.sap.registerModulePath("sap.m.sample.NavContainer", "./");
new JSROOT.sap.m.App ({
pages: [
new JSROOT.sap.m.Page({
title: "Nav Container",
enableScrolling : true,
content: [ new sap.ui.core.ComponentContainer({
name : "sap.m.sample.NavContainer"
})]
})
]
}).placeAt("content");
}
</script>


There are small details when using OpenUI5 with THttpServer. First of all, location of JSROOT scripts should be specified as jsrootsys/scripts/JSRootCore.js. And when trying to access files from local disk, one should specify /currentdir/ folder:

jQuery.sap.registerModulePath("sap.m.sample.NavContainer", "/currentdir/");