Skip to content
Advertisement

How to add custom values to nodes of plotly graph

I’m trying to add values to nodes of plotly graph but there is an issue.

Code:

<html>
  <head>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
    <style>
      .graph-container {
        display: flex;
        justify-content: center;
        align-items: center;
      }

      .main-panel {
        width: 70%;
        float: left;
      }

      .side-panel {
        width: 30%;
        background-color: lightgray;
        min-height: 300px;
        overflow: auto;
        float: right;
      }
    </style>
  </head>
  <body>
    <div class="graph-container">
      <div id="myDiv" class="main-panel"></div>
      <div id="lineGraph" class="side-panel"></div>
    </div>
    <script>
      var nodes = [
        { x: 0, y: 0, z: 0, value: [1, 2, 3] },
        { x: 1, y: 1, z: 1, value: [4, 5, 6] },
        { x: 2, y: 0, z: 2, value: [7, 8, 9] },
        { x: 3, y: 1, z: 3, value: [10, 11, 12] },
        { x: 4, y: 0, z: 4, value: [13, 14, 15] }
      ];

      var edges = [
        { source: 0, target: 1 },
        { source: 1, target: 2 },
        { source: 2, target: 3 },
        { source: 3, target: 4 }
      ];

      var x = [];
      var y = [];
      var z = [];

      for (var i = 0; i < nodes.length; i++) {
        x.push(nodes[i].x);
        y.push(nodes[i].y);
        z.push(nodes[i].z);
      }

      var xS = [];
      var yS = [];
      var zS = [];
      var xT = [];
      var yT = [];
      var zT = [];

      for (var i = 0; i < edges.length; i++) {
        xS.push(nodes[edges[i].source].x);
        yS.push(nodes[edges[i].source].y);
        zS.push(nodes[edges[i].source].z);
        xT.push(nodes[edges[i].target].x);
        yT.push(nodes[edges[i].target].y);
        zT.push(nodes[edges[i].target].z);
      }

      var traceNodes = {
        x: x, y: y, z: z,
        mode: 'markers',
        marker: { size: 12, color: 'red' },
        type: 'scatter3d',
        text: [0, 1, 2, 3, 4],
        hoverinfo: 'text',
        hoverlabel: {
          bgcolor: 'white'
        },
        customdata: nodes.map(function(node) {
            if (node.value !== undefined)
               return node.value;
        }),
        type: 'scatter3d'
      };

      var layout = {
        margin: { l: 0, r: 0, b: 0, t: 0 }
      };

      Plotly.newPlot('myDiv', [traceNodes], layout, { displayModeBar: false });

      document.getElementById("myDiv").on("plotly_click", function(data){
      var nodeIndex = data.points[0].pointIndex;
      var values = nodes[nodeIndex].value;
      console.log(values);

      Plotly.newPlot('lineGraph', [{ x: [0, 1, 2], y: values, type: 'scatter3d'}], {
      margin: { t: 0 }
      });
      });
    </script>
   </body>
</html>

var values = nodes[nodeIndex].value; is not able to access the node values.

Suggestions on how to fix this will be really helpful.

EDIT0:

<html>
  <head>
    <script src="https://cdn.plot.ly/plotly-1.58.5.min.js"></script>
    <style>
      .graph-container {
        display: flex;
        justify-content: center;
        align-items: center;
      }

      .main-panel {
        width: 70%;
        float: left;
      }

      .side-panel {
        width: 30%;
        background-color: lightgray;
        min-height: 300px;
        overflow: auto;
        float: right;
      }
    </style>
  </head>
  <body>
    <div class="graph-container">
      <div id="myDiv" class="main-panel"></div>
      <div id="lineGraph" class="side-panel"></div>
    </div>
    <script>
      var nodes = [
        { x: 0, y: 0, z: 0, value: [1, 2, 3] },
        { x: 1, y: 1, z: 1, value: [4, 5, 6] },
        { x: 2, y: 0, z: 2, value: [7, 8, 9] },
        { x: 3, y: 1, z: 3, value: [10, 11, 12] },
        { x: 4, y: 0, z: 4, value: [13, 14, 15] }
      ];

      var edges = [
        { source: 0, target: 1 },
        { source: 1, target: 2 },
        { source: 2, target: 3 },
        { source: 3, target: 4 }
      ];

      var x = [];
      var y = [];
      var z = [];

      for (var i = 0; i < nodes.length; i++) {
        x.push(nodes[i].x);
        y.push(nodes[i].y);
        z.push(nodes[i].z);
      }

      var xS = [];
      var yS = [];
      var zS = [];
      var xT = [];
      var yT = [];
      var zT = [];

      for (var i = 0; i < edges.length; i++) {
        xS.push(nodes[edges[i].source].x);
        yS.push(nodes[edges[i].source].y);
        zS.push(nodes[edges[i].source].z);
        xT.push(nodes[edges[i].target].x);
        yT.push(nodes[edges[i].target].y);
        zT.push(nodes[edges[i].target].z);
      }

      var traceNodes = {
        x: x, y: y, z: z,
        mode: 'markers',
        marker: { size: 12, color: 'red' },
        type: 'scatter3d',
        text: [0, 1, 2, 3, 4],
        hoverinfo: 'text',
        hoverlabel: {
          bgcolor: 'white'
        },
        customdata: nodes.map(function(node) {
            if (node.value !== undefined)
               return node.value;
        }),
        type: 'scatter3d'
      };

      var layout = {
        margin: { l: 0, r: 0, b: 0, t: 0 }
      };

      Plotly.newPlot('myDiv', [traceNodes], layout, { displayModeBar: false });
      const ymax = Math.max(...nodes.map(n => n.value).flat());

      document.getElementById("myDiv").on("plotly_click", function(data){
      var nodeIndex = data.points[0].pointNumber;
      var values = nodes[nodeIndex].value;
      console.log(values);

      Plotly.newPlot('lineGraph', [{ x: [0, 1, 2], y: values, type: 'scatter3d'}], {
      margin: { t: 0 },
      yaxis: {autorange: false, range: [0, ymax + 1]}
      });
      });
    </script>
   </body>
</html>

I made the corrections suggested in the answer below but the I am still not able to see the line graph when nodes in the main panel are clicked.

Advertisement

Answer

Use pointNumber instead of pointIndex. You also need to fix the type of the second plot, for which I also suggest to set a fixed axis range (otherwise the axis will reset for each selected point) :

// max y value for the line plot
const ymax = Math.max(...nodes.map(n => n.value).flat());

document.getElementById('myDiv').on('plotly_click', function(data){
  var nodeIndex = data.points[0].pointNumber;
  var values = nodes[nodeIndex].value;

  Plotly.newPlot('lineGraph', [{
    type: 'scatter',
    mode: 'lines',
    x: [0, 1, 2],
    y: values
  }], {
    margin: { t: 0 },
    yaxis: {autorange: false, range: [0, ymax + 1]}
  });
});

For reference, here is the event data structure for 3d plots :

{
  points: [{
    curveNumber: 2,  // index in data of the trace associated with the selected point
    pointNumber: 2,  // index of the selected point
    x: 5,        // x value
    y: 600,      // y value
    z: 12,       // z value
    data: {/* */},       // ref to the trace as sent to Plotly.newPlot associated with the selected point
    fullData: {/* */},   // ref to the trace including all of the default attributes
   xaxis: {/* */},   // ref to x-axis object (i.e layout.xaxis) associated with the selected point
   yaxis: {/* */}    // ref to y-axis object " "
   zaxis: {/* */}    // ref to z-axis object " "
  }, {
    /* similarly for other selected points */
  }]
}

One last thing, don’t use plotly-latest.js or its minified version anymore. While still referenced here and there in the documentation, they are stuck at version 1.58.5.

Please note that as of v2 the “plotly-latest” outputs will no longer be updated on the CDN, and will stay at the last v1 patch v1.58.5. Therefore, to use the CDN with plotly.js v2 and higher, you must specify an exact plotly.js version.


Here is the complete code :

<html>
  <head>
    <script src="https://cdn.plot.ly/plotly-2.18.1.min.js"></script>
    <style>
      .graph-container {
        display: flex;
        justify-content: center;
        align-items: center;
      }

      .main-panel {
        width: 70%;
        float: left;
      }

      .side-panel {
        width: 30%;
        background-color: lightgray;
        min-height: 300px;
        overflow: auto;
        float: right;
      }
    </style>
  </head>
  <body>
    <div class="graph-container">
      <div id="myDiv" class="main-panel"></div>
      <div id="lineGraph" class="side-panel"></div>
    </div>
    <script>
      var nodes = [
        { x: 0, y: 0, z: 0, value: [1, 2, 3] },
        { x: 1, y: 1, z: 1, value: [4, 5, 6] },
        { x: 2, y: 0, z: 2, value: [7, 8, 9] },
        { x: 3, y: 1, z: 3, value: [10, 11, 12] },
        { x: 4, y: 0, z: 4, value: [13, 14, 15] }
      ];

      var edges = [
        { source: 0, target: 1 },
        { source: 1, target: 2 },
        { source: 2, target: 3 },
        { source: 3, target: 4 }
      ];

      var x = [];
      var y = [];
      var z = [];

      for (var i = 0; i < nodes.length; i++) {
        x.push(nodes[i].x);
        y.push(nodes[i].y);
        z.push(nodes[i].z);
      }

      var xS = [];
      var yS = [];
      var zS = [];
      var xT = [];
      var yT = [];
      var zT = [];

      for (var i = 0; i < edges.length; i++) {
        xS.push(nodes[edges[i].source].x);
        yS.push(nodes[edges[i].source].y);
        zS.push(nodes[edges[i].source].z);
        xT.push(nodes[edges[i].target].x);
        yT.push(nodes[edges[i].target].y);
        zT.push(nodes[edges[i].target].z);
      }

      var traceNodes = {
        x: x, y: y, z: z,
        mode: 'markers',
        marker: { size: 12, color: 'red' },
        type: 'scatter3d',
        text: [0, 1, 2, 3, 4],
        hoverinfo: 'text',
        hoverlabel: {
          bgcolor: 'white'
        },
        customdata: nodes.map(function(node) {
            if (node.value !== undefined)
               return node.value;
        }),
        type: 'scatter3d'
      };

      var layout = {
        margin: { l: 0, r: 0, b: 0, t: 0 }
      };

      Plotly.newPlot('myDiv', [traceNodes], layout, { displayModeBar: false });

      // max y value for the line plot
      const ymax = Math.max(...nodes.map(n => n.value).flat());

      document.getElementById('myDiv').on('plotly_click', function(data){
        var nodeIndex = data.points[0].pointNumber;
        var values = nodes[nodeIndex].value;

        Plotly.newPlot('lineGraph', [{
            type: 'scatter',
            mode: 'lines',
            x: [0, 1, 2],
            y: values
        }], {
            margin: { t: 0 },
            yaxis: {autorange: false, range: [0, ymax + 1]}
        });
      });
    </script>
   </body>
</html>
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement