0

I am trying to add gradient colors in edges of a force directed graph made in Plotly.js. I have taken the input through Json file and have also used 'color_continuous_scale' to add the colors. But the desired result is not coming.

Full code:

<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>

      fetch('data.json')
        .then(response => response.json())
        .then(data => {
          var nodes = data.nodes;
          var edges = data.edges;
        
          
        
    
      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);


      }

  const edge_x  = [];
  const edge_y  = [];
  const edge_z  = [];

  for (var i = 0; i < edges.length; i++) {
    const a = nodes[data.edges[i].source];
    const b = nodes[data.edges[i].target];
    edge_x.push(a.x, b.x, null);
    edge_y.push(a.y, b.y, null);
    edge_z.push(a.z, b.z, null);
  }

  const traceEdges = {
    x: edge_x,
    y: edge_y,
    z: edge_z,
    type: 'scatter3d',
    mode: 'lines',
    line: { color: 'traceEdges', color_continuous_scale: 'Inferno', width: 10},
    opacity: 0.8
  };

     
      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',[traceEdges, traceNodes], layout);

      // 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>

Here is the image of the plot that has been created

As you can see in the above image that the plot is showing only one color in the edges. I want to change this attribute to gradient coloring. Any changes in the code will be welcomed.

1 Answers1

1

You need to specify a color array so that values from that array can be mapped to a colorscale :

color - Sets the line color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to line.cmin and line.cmax if set.

colorscale - Sets the colorscale. Has an effect only if in line.color is set to a numerical array. The colorscale must be an array containing arrays mapping a normalized value to an rgb, rgba, hex, hsl, hsv, or named color string [...]. Alternatively, colorscale may be a palette name string [...].

For example by setting color: edge_y, edges are colored according to their positioning on the y axis (y coordinates of the source and target nodes) :

const traceEdges = {
  x: edge_x,
  y: edge_y,
  z: edge_z,
  type: 'scatter3d',
  mode: 'lines',
  line: {
    autocolorscale: false,
    colorscale: 'Cividis',
    color: edge_y,
    width: 10
  },
  opacity: 0.8,
};

output screenshot

Nb. color_continuous_scale is specific to plotly.express (python), and the 'Inferno' color scale as well. You can't use it with plotly.js.

EricLavault
  • 12,130
  • 3
  • 23
  • 45
  • Is the length of edge_y = number of nodes ? For example, if numerical values are assigned to source node and target nodes, is the edge colored based on these values? Or could we assign a numerical value/ (weight) for each edge? – Natasha Feb 14 '23 at 15:12
  • The length of edge_y (of edge_x and edge_z as well) corresponds to the number of edges multiplied by three (one edge coordinate is represented by one [source, target, null] triplet). For the second question, edges are colored according to the 'color' property, so first you would need to map those values or weight in a dedicated array which you can then specify as the 'color' array. – EricLavault Feb 14 '23 at 16:47
  • If you don't mind, could you please show an example for this? – Natasha Feb 14 '23 at 18:06
  • Could you please check this post https://stackoverflow.com/questions/75450595/how-to-give-different-colors-to-the-cones-in-plotly-js ? – Natasha Feb 14 '23 at 18:08
  • @Natasha We can control how line segments are colored in a 3d scatter plot using a color array (using edge_y, or more generally any of the x/y/z values _is_ an example, though I could develop a bit so feel free to ask "how to color edges according to their weight ?" but be more specific because I'm not sure what you are missing). However regarding cones traces, it seems they don't have this property (color), so I don't know if it's possible to decide arbitrarily how each cone should be colored. – EricLavault Feb 15 '23 at 14:30