1

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.

4
  • What it the issue? I have tried on JSFiddle and I got 3D plot successfully with your code. Commented Feb 8, 2023 at 11:17
  • I want to see a line graph on the side panel (right) when nodes are clicked Commented Feb 8, 2023 at 11:18
  • @NIKUNJKOTHIYA console throws error at line ` var values = nodes[nodeIndex].value; ` Commented Feb 8, 2023 at 11:19
  • Yaa I got it error Commented Feb 8, 2023 at 11:28

1 Answer 1

1

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>
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks a lot. Could you please check my edit? I'm not sure if document.getElementById('myDiv').on('plotly_click', function(data) has to be modified. Could you please post a complete answer?
Yes I just added the complete code. You were missing the type: 'scatter', mode: 'lines' part for the linegraph in the plotly_click handler.
This works great! If multiple nodes are clicked, can we plot multiple lines at the same time? Could you please suggest how this can be done?
I'm not sure you can select multiple points in 3d, but supposing it's possible, you would use the plotly_selected event instead of plotly_click, then in the handler you would iterate over data.points and build one trace for each selected point, append those traces in a data array and finally call Plotly.newPlot('lineGraph', data, ...).
Thanks a lot, I tried plotly_selected but this is not working. If you don't mind could you please check stackoverflow.com/questions/75413890/… ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.