Skip to content

ndmspc/ndmvr-core

Repository files navigation

ndmvr-aframe

Package for creating 3D visualization of histograms.

Built on top of A-Frame

Features

  • A-Frame components for rendering histogram.
  • Components have customizable functionality.
  • RxJs predefined subjects to communicate internally.
  • Ability to make connection to websocket.

Getting started

NOTE: In this tutorial Vite with vanilla js is used, if you want to use different Vite template please see Vite guide.

To build your own application from scratch you can do.

npm create vite@latest my-app -- --template vanilla
npm install
npm install @ndmspc/ndmvr-aframe
npm run dev

Configuration Documentation

This project supports a flexible JSON configuration to control positioning, scaling, padding, and visual styling of histograms and canvases.
Below is the reference for each configuration section.

Configuration can be passed through config subject.

configSubjectGet().next(config);

The configuration is contained within a main config object.

{
  "config": { ... }
}

camera

This section is intended to configure the camera's position. Note: This feature is not yet functional.

"camera": {
  "position": { "x": 0, "y": 0, "z": 0 }
}

canvas

Controls the main canvas mesh.
Position: sets canvas location.
Rotation: in degrees.
Scale: width/height/depth scaling (Three.js units).

"canvas": {
    "position": { "x": 0, "y": 5, "z": -15 },
    "rotation": { "x": 10, "y": 0, "z": 0 },
    "scale":    { "x": 10, "y": 10, "z": 0 }
}

histogramMatrix

Controls all nested histograms.
Position: moves the histogram matrix as a whole.
Scale: dimensions in Three.js units.

"histogramPads": {
   "position": { "x": 0, "y": 0, "z": 10 },
   "scale":    { "x": 10, "y": 5, "z": 10 }
}

jsrootHistogramMatrix

Controls histograms rendered via JSROOT renderer.
Position: moves the JSROOT-rendered histogram.
Scale: in 0–1 percentage, relative scaling factor applied to the whole histogram.

"histogramPads": {
   "position": { "x": 0, "y": 0, "z": 10 },
   "scale":    { "x": 10, "y": 5, "z": 10 }
}

padding

Controls spacing between nested histograms.
default: applies to all TH1/TH2/TH3 histograms.
layer: overrides default for specific histogram layers.

"padding": {
   "default": { "x": 0.1, "y": 0.1, "z": 0.1 },
   "layer": [
       { "x": 0.1, "y": 0.1, "z": 0.1 }
   ]
}

TH1ZScale

Controls depth of TH1 bins.
Values are 0–1 (percentage):

0 = no depth,
1 = full depth.

default: applies to all TH1 histograms.
layer: overrides default for specific layers.

"TH1ZScale": {
   "default": 0.8,
   "layer": [0.2, 1, 1, 1]
}

Color

Defines bin colors as gradients.
min/max: hex strings (e.g. "0x0000ff").
Gradient is calculated between min and max according to bin content (0 → max bin content).
default: applied to all histograms.
layer: overrides default per layer.
set: overrides both default and layer for specific sets of histograms.

"color": {
   "default": { "min": "0x0000ff", "max": "0xff0000" },
   "layer": [],
   "set": [
       { "min": "0x222222", "max": "0xffaa00" },
       { "min": "0x00ffff", "max": "0xff7f00" },
       { "min": "0x00ff00", "max": "0x800080" },
       { "min": "0x0000ff", "max": "0xff0000" }
   ]
}

How to pass functions to component

  • You can pass single or array of functions to function subject.
  • event identifies type of event on which the component will then listen to.
  • target identifies objects to whose will those functions will bind to.
    • entity is type of A-Frame entity.
    • id is id of A-Frame component id in scene.
  • function is plain js function which will be started when the event is triggered.

NOTE: Initialization of components can take some time at the start, so it is better to wait 100ms with setTimeout.

const functions = [
  {
    event: "click",
    target: {
      entity: "histogram",
      id: [1, 2],
    },
    function: function (data) {
      const scale = data.target.object3D.scale;
      if (scale.x > 3) {
        scale.x = 1;
        scale.y = 1;
        scale.z = 1;
      }
      data.target.object3D.scale.set(
        scale.x * 1.1,
        scale.y * 1.1,
        scale.z * 1.1,
      );
    },
  },
  {
    event: "mouseenter",
    target: {
      entity: "histogram",
      id: "*",
    },
    function: function (data) {
      console.log(data);
    },
  },
];

setTimeout(() => functionSubjectGet().addFunctions(functions), 100);

How to create connection to websocket

BrokerManager provides functionality duplex websocket connection.

  1. Using createWsFromParams.

In parameters of URL then needs to be URLs of websockets, also option for automatic connections.

// URL e.g. http://host?ws=ws://localhost:8088&autoConnect=true
brokerManagerGet().createWsFromParams(
  new URL(window.location.href).searchParams,
);
  1. Using createWs.

Arguments of this function is string of URL and boolean value for autoConnect.

After creating connection
  • After creation of brokers which handles websocket connections you can then.

    • Subscribe for incoming messages and set what should be the callback when the message arrives.
    brokerManagerGet()
      .getSubject()
      .subscribe((v) => {
        console.log(v);
      });
    • Send messages back to server
    brokerManagerGet().getBrokerByUrl(URL, autoConnect)
           .send(JSON.stringify({"your data goes here"}));

Histogram render example

You can see example of rendered histogram at: our Gitlab pages

This example uses histogram component. If you want to use it in your app you can pass root json object to it via:

  • histogram_source_url which is part of the schema of this component.

    <a-entity
      id="histogram18bins"
      position="-140 0 0"
      histogram="histogram_source_url:../../public/histograms/TH3variableBinning55x57x34.json;"
    >
    </a-entity>
  • Assigning id to it and passing the root json object by rxjs histogramSubject.

    <a-entity id="histogram1" position="0 0 0" histogram> </a-entity>
    import { parse } from "jsroot";
    histogramSubjectGet().next({ id: "histogram1", obj: parse(v) });

Dynamic rendering of histogram

histogram component also supports dynamic rendering of histogram.

On how to set it up yourself you can get inspired with our stress test.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages