chart = {
const buffer = fetchProgress("https://raw.githubusercontent.com/datadesk/cpi/d582252c644b90d48918a4cba951baf3c03c9629/cpi/cpi.db", {mode: "cors"})
nodes.forEach( function(element) {
element.Degree = findDegree(flinks).find(o => o.key === element.id)
});
let gnodes = (range+1)? nodes.filter(d=> d.Degree.value > 2 ) : nodes
const simulation = d3.forceSimulation(gnodes)
.force("link", d3.forceLink(glinks).id(d => d.id)
.strength(function (d) {return (4/d.MR);})
.iterations(1)
)
.force("charge", d3.forceManyBody()
.strength(- 200 * d3_array.count(nodes, d => d.index))
)
.force("collide", d3.forceCollide(d3_array.count(nodes, d => d.index))
.strength(1)
.iterations(1)
)
.force("x", d3.forceX()
.strength(0.1)
.x(width / 2))
.force("y", d3.forceY()
.strength(0.1)
.y(height / 2));
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);
const g = svg.append("g").attr("transform", "1")
const link = g.append("g")
.attr("stroke", "#999")
.attr("stroke-opacity", 1)
.selectAll("line")
.data(glinks)
.join("line")
.attr("stroke-width", d => (15/Math.sqrt(d.MR)))
.style("stroke", color_link);
const globalNode = g.append("g")
//.attr("stroke", "#fff")
//.attr("stroke-width", 0.05 * (d3_array.count(nodes, d => d.index)));
const tooltip = d3tip()
.style('color', 'white')
//.style('border', 'solid 2px black')
.style('background-color', 'rgba(0,0,0,0.5)')
.style('border-radius', '4px')
.style("padding", "6px")
.style('float', 'left')
.style('font-family', 'Nunito')
.style("font-size", "14px")
.offset([-10,50])
.html(d => `<div style='float: right'>
Gene Name: ${d.full_name} <br/>
AGI Locus: ${d.id} <br/>
GO: ${d.GO.map(a => `<li>${a}`)}<br/>
</div>`)
svg.call(tooltip)
const node = globalNode
.selectAll("circle")
.data(gnodes)
.join("circle")
//.attr("r", d => 0.3 * Math.sqrt(d.connectivity -1) * (d3_array.count(nodes, d => d.index)))
.attr("r", d => (d3_array.count(nodes, d => d.index)))
.attr("fill", function(o) { console.log(o.GO.indexOf(dropdown))
if (o.GO.indexOf(dropdown) != -1){return GO_json[dropdown].Color}else{return "white"}})
.attr("stroke", color_border)
.attr("stroke-width", 0.2 * (d3_array.count(nodes, d => d.index)))
.call(drag(simulation))
.on('mouseover.fade', fade(0.1))
.on('mouseover', tooltip.show)
.on('mouseout.fade', fade(1))
.on('mouseout', tooltip.hide)
.on('dblclick', go_to_node);
function go_to_node(d) {
//window.location = "http://plantregeneration.snu.ac.kr/regenomics/single-gene-coex-ajax/?dataset_B=all&query_B=";
const dataset = $('#dataset-B').val(); // get the selected subject ID from the HTML dropdown list \
const species = new URL(location.href).searchParams.get('species')
console.log(dataset)
$.ajax({ // initialize an AJAX request
type: "GET",
url: "dblclick_single_gene_coex_ajax",
data: {
'dataset_B': dataset,
'query_B' : d.id,
'species' : species
},
success: function (data) { // `data` is from view function
$('#single-coex-network').html(data);
}
})
}
const textElements = g.append('g')
.selectAll('text')
.data(gnodes)
.enter().append('text')
.text(node => node.alias)
.attr('font-size', d => 1 * (d3_array.count(nodes, d => d.index)))
.attr("font-family", "Nunito")
.attr("font-weight", "bold")
.attr("fill", "#000000")
//.attr('dx', d => -0.5 * Math.sqrt(d.connectivity -1) * (d3_array.count(nodes, d => d.index)))
.attr('dy', d => 2 * (d3_array.count(nodes, d => d.index)))
.attr("text-anchor", "middle")
.attr("pointer-events", "none");
function fade(opacity) {
return d => {
node.style('opacity', function (o) { return isConnected(d, o) ? 1 : opacity
});
textElements.style('opacity', function (o) { return isConnected(d, o) ? 1 : opacity
});
link.style('stroke-opacity', o => (o.source === d || o.target === d ? 1 : opacity));
if(opacity === 1){
node.style('opacity', 1)
link.style('stroke-opacity', 1)
}
};
}
const linkedByIndex = {};
flinks.forEach(d => {
linkedByIndex[`${d.source},${d.target}`] = true;
});
console.log(linkedByIndex)
function isConnected(a, b) {
return linkedByIndex[`${a.id},${b.id}`] || linkedByIndex[`${b.id},${a.id}`] || a.index === b.index;
}
simulation.on("tick", () => {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
textElements
.attr("x", d => d.x)
.attr("y", d => d.y);
node
.attr("cx", d => d.x)
.attr("cy", d => d.y);
});
invalidation.then(() => simulation.stop());
let zoomLvl = 0.5;
let lastK = 0;
svg.call(d3.zoom()
.scaleExtent([0.5,10])
.on("zoom", zoomed))
.on("dblclick.zoom", null);
function zoomed() {
let e = d3.event
if(Math.log2(e.transform.k) >= 0.5 && lastK != e.transform.k){
lastK = e.transform.k;
console.log("zoomed");
zoomLvl =Math.log2(e.transform.k);
console.log(zoomLvl)
globalNode.attr("stroke-width", zoomLvl );
link.attr("stroke-width", d => (15/Math.sqrt(d.MR)) * zoomLvl);
}
g.attr("transform", e.transform);
}
return svg.node();
}