0

I am not able to figure out what I am doing wrong in the following html code. I have a JSON file with a "cohesive" attribute which is a continuous variable. I want to draw a force directed graph on D3JS using the JSON file with the node color reflecting the difference in cohesive energy. When I run this script, I don't get any errors but there is no output as well. I just started with HTML scripting so please forgive me if I am making a very silly error but I would really appreciate if someone could point out what I am doing wrong.

function convertRange(value, r1, r2) {
  return (value - r1[0]) * (r2[1] - r2[0]) / (r1[1] - r1[0]) + r2[0];
}
var svg = d3.select("svg"),
  width = +svg.attr("width"),
  height = +svg.attr("height");

var colorScale = d3.scaleLinear(d3.interpolateViridis);

var simulation = d3.forceSimulation()
  .force("link", d3.forceLink().id(function(d) {
    return d.id;
  }))
  .force("charge", d3.forceManyBody())
  .force("center", d3.forceCenter(width / 2, height / 2));

d3.json("Perovskite_info.json", function(error, graph) {
  if (error) throw error;

  var link = svg.append("g")
    .attr("class", "links")
    .selectAll("line")
    .data(graph.links)
    .enter().append("line")
    .attr("stroke-width", function(d) {
      return Math.sqrt(d.value);
    });

  var node = svg.append("g")
    .attr("nodes")
    .selectAll("circle")
    .data(graph.nodes)
    .enter().append("circle")
    .attr("r", 5)
    .attr("fill", function(d) {
      return colorScale(convertRange(d.cohesive_en, [1.6, 7.2], [0, 1]));
    })
    .call(d3.drag()
      .on("start", dragstarted)
      .on("drag", dragged)
      .on("end", dragended));

  node.append("title")
    .text(function(d) {
      return d.id;
    });

  simulation
    .nodes(graph.nodes)
    .on("tick", ticked);

  simulation.force("link")
    .links(graph.links);

  function ticked() {
    link
      .attr("x1", function(d) {
        return d.source.x;
      })
      .attr("y1", function(d) {
        return d.source.y;
      })
      .attr("x2", function(d) {
        return d.target.x;
      })
      .attr("y2", function(d) {
        return d.target.y;
      });

    node
      .attr("cx", function(d) {
        return d.x;
      })
      .attr("cy", function(d) {
        return d.y;
      });
  }
});

function dragstarted(d) {
  if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragged(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function dragended(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
}
.links line {
  stroke: #999;
  stroke-opacity: 0.6;
}

.nodes circle {
  stroke: black;
  stroke-width: 1.5px;
}
<script src="https://d3js.org/d3.v5.min.js"></script>

<h1>Cohesive Energy Calculation</h1>

<svg width="1060" height="800"></svg>

This is how one my json begins:

{"directed": false, "multigraph": false, "graph": {}, "nodes": [{"pos": [-37.50340668168362, -0.6442713601030169], "cohesive_en": 5.752120797750001, "cohesive": 5.752120797750001, "cluster": 1, "similarity": 0.6371195466189876, "id": "PrCoO3"},

For the full JSON please follow this link: https://api.myjson.com/bins/m3gd8

Edit: So I figured out what the problems were:

First off, as one of the answers stated, I was using d3.v5 but using the d3v4 api to import data. Secondly, I also needed to import the d3 interpolate module which I hadn't done. So the code wasn't working. This question was asked at a point where I had done d3 for 2 days so the quality of the code is low.

1 Answers1

0

you use a D3v4 API of loading a file.

D3v5 use the Fetch API

// d3.json("Perovskite_info.json", function(error, graph) {
d3.json("Perovskite_info.json").then( function(graph) {
    //if (error) throw error;

Then there is a problem in how you add the nodes compared to the links but you will find that.

Why do the colorScale Math yourself in convertRange?

There is no color yet but that is a different problem.

rioV8
  • 24,506
  • 3
  • 32
  • 49