Home | News | Documentation | Download

JSRoot exporting GDML geometry to threejs json format using node

Hello,

I am currently working on high energy physics event visualization using modern web technologies (here you can see the current prototype: http://157.230.77.34/). JSRoot is capable of reading TGeo objects from a .root file with three.js I am able to render them in the browser, starting from an example such as JavaScript ROOT API examples.

However I only managed to do this in a browser, I would like to be able to write a program to convert TGeo geometries in .root files to three.js .json so I can import them into my viewer.

I think the best way would be using node.js, but I couldn’t manage to properly read the geometry of a root file with it, since I have never used node.js before and there are very little examples of jsroot for node.js. Would this be possible? Or perhaps its not because of limitations of three.js in node.js?

I would really appreciate if you could provide me with an example of such a conversion in the easiest way possible so I can integrate it into my program.

Also my goal is to convert GDML to three.js json format, but I don’t think jsroot supports reading directly from GDML, right? My idea was to use the root http server to read the gdml files and convert them into root files, but if there is an easier way to do this, please let me know.

Also I have noticed that the names of the volumes are lost once you export the geometry loaded into three.js into .json, is this the expected behavior? I think it would make much more sense to have the name field of the json be populated with the name of the node instead of it being empty.

Thank you very much for your work!

Hi and welcome on the forum,

It is possible to use JSROOT in node.js environment.
There is big test suite, which runs in node.js
Also there are several examples directly in JSROOT repository.

GDML is not supported in JSROOT and it is not planned.
Therefore you should use ROOT code to import GDML into ROOT geometry classes.

After Easter holidays I provide a short demo which converts ROOT geometry in three.js JSON.
“name” attributes were never exported by JSOOT, but this can be very easily implemented.

Regards,
Sergey

1 Like

Hello Sergey,

Thank you for your response, I hope you are enjoying the holidays.

Thanks to the examples, I managed to use ROOT and THttpServer to read gdml/root geometry files and serve them as serialized TEveGeoShapeExtract (like what can be found in https://root.cern/js/files/geom/simple_alice.json.gz). Now I would only need to convert these into three.js scenes / JSON objects.

Sadly with my current knowledge of node/js it has been impossible so far to achieve this, I only managed to make SVG images of my geometry, following the example (which by the way, I think it uses a deprecated MakeSVG instead of makeSVG and doesn’t run on the latest version of jsroot, I made a pull request here: Fix example geomsvg.js not working on current version by lobis · Pull Request #211 · root-project/jsroot · GitHub with the easy fix.).

Running the SVG example made me wonder if its possible to generate projections (using option projx/y/z) at specific plane heights (e.g. z = 100). I couldn’t find anything in the documentation and if its possible it would be really useful to me.

Actually I have been able to generate the three.js scenes following the examples in JavaScript ROOT examples. My problem is that I want to use React for my project and so far it has been impossible to get it to work with jsroot, so I though I would work directly with the threejs json generated by another node.js application.

Regarding React, I could only find this piece of information: react app and jsroot · Issue #165 · root-project/jsroot · GitHub from 2018. The user claims to have found a workaround in which can be found (probably) in GitHub - mvala/react-jsroot-example, but I couldn’t get it to work with the latest jsroot version. If you have any insight in this topic I would also be thankful.

Regarding the name problem, as you say it would be easy to insert them into the threejs json since they are in the jsroot gse json, so this is not an issue anymore.

Thanks for providing me with an example, I will try to do it myself in the meantime (starting from Namespace: GEO).

Regards,
Luis.

After more time than I would like to admit, I managed to do it. It was worthwhile though, since I learned quite a bit from this :slight_smile:

Here is a full example exporting a geometry from a root file to the three.js json format:

let jsroot = require("jsroot");
let fs = require("fs");
var zlib = require('zlib');

console.log('JSROOT version', jsroot.version);


function exportGeometry(obj) {

    let opt = { numfaces: 100000, numnodes: 1000, wireframe: false };
    if (d.has("all")) {
        opt.numfaces *= 100;
        opt.numnodes *= 100;
    }

    if (d.has("dflt") || d.has("dflt_colors"))
        opt.dflt_colors = true;

    let volumes = obj.fMasterVolume.fNodes.arr
    let top_volumes_names = []
    for (var i in volumes) {
        const name = volumes[i].fName
        top_volumes_names.push(name)
        console.log(i, name)
    }

    let obj3d = jsroot.GEO.build(obj, opt);

    if (!obj3d) return;

    let data = obj3d.toJSON();

    data["info"] = []
    // add additional info to json
    for (var i in top_volumes_names) {
        const name = top_volumes_names[i]
        console.log(i, name, data["geometries"][i])
        data["info"].push(top_volumes_names[i])
    }

    const outputFileName = "geometry.json";
    fs.writeFileSync(outputFileName, JSON.stringify(data));
    // save also compressed
    out = fs.createWriteStream(outputFileName + ".gz");
    var gzip = zlib.createGzip();
    const input = fs.createReadStream(outputFileName);
    input.pipe(gzip).pipe(out);
}

function main() {
    d = jsroot.decodeUrl();
    {
        let filename = "path/to/your/file.root"
        if (filename.indexOf(".root") > 0) {
            // it is a ROOT file, must include a 'geo' key with the geometry (TGeoManager)
            let itemname = "geo";
            jsroot.openFile(filename)
                .then(file => file.readObject(itemname))
                .then(exportGeometry);
        }
    }
}


jsroot.require('geom').then(main);

I add in function JSROOT.GEO.build() export of object names.
Available in master branch, will be released soon as 6.1 version

1 Like