Skip to content

Commit

Permalink
first draft unipartite network widget
Browse files Browse the repository at this point in the history
  • Loading branch information
d-callan committed Dec 4, 2023
1 parent eb143d8 commit c9d306a
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 4 deletions.
2 changes: 1 addition & 1 deletion R/server.R
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ server <- function(input, output, session) {
file1 <- NULL
file2 <- NULL
} else if (upload_state$file1 == 'uploaded' && (is.null(upload_state$file2) || upload_state$file2 == 'reset')) {
shiny::showNotification('Please upload the second file.', type = 'error')
file1 <- input$fileUpload
file2 <- NULL
} else if (upload_state$file2 == 'uploaded' && (is.null(upload_state$file1) || upload_state$file1 == 'reset')) {
Expand Down Expand Up @@ -193,6 +192,7 @@ server <- function(input, output, session) {
return(edgeList)
})

# eventually offer the option to show either bipartite or unipartite for any input data
output$correlationNetwork <- renderUI({
if (is.null(data1$matrix)) {
return(NULL)
Expand Down
2 changes: 1 addition & 1 deletion R/unipartiteNetwork.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ unipartiteNetwork <- function(data, width = NULL, height = NULL, elementId = NUL
filter(source %in% unique_sources & target %in% unique_targets) %>%
distinct(source, target, .keep_all = TRUE)

params <- list(data = list(links = edge_data, column1NodeIds = unique_sources, column2NodeIds = unique_targets))
params <- list(data = list(links = edge_data, nodes = data.frame(id = unique(c(unique_sources, unique_targets)))))
attr(params, 'TOJSON_ARGS') <- list(dataframe = 'rows')

network <- htmlwidgets::createWidget(
Expand Down
106 changes: 104 additions & 2 deletions inst/htmlwidgets/unipartitenetwork.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,111 @@ HTMLWidgets.widget({
function renderValue(x) {
svg.selectAll('*').remove();

// TODO make a network
// see insipiration here https://observablehq.com/@chakreshiitgn/bipartite-network-of-teams
var links = x.data.links;
var nodes = x.data.nodes;

// Force Diagram
var simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.id))
.force("charge", d3.forceManyBody().strength(-500))
.force("center", d3.forceCenter(width / 2, height / 2));

var link = svg
.selectAll(".link")
.data(links)
.enter()
.append("polyline") //Create as polyline for arrows
.attr("stroke", "Gray")
.attr("stroke-width",d => Math.sqrt(d.value)) // Set default stroke width
.attr("marker-mid", "url(#end)"); // Add Marker

// Create nodes
var node = svg
.append("g")
.selectAll(".node")
.data(nodes)
.enter()
.append("circle")
.attr("r", 5)
//.attr("r", d=>5+d.degree) // add degree to data later to bring this back
.call(d3.drag(simulation)).attr('class', 'node');

return svg.node();
var nodeLinkStatus = {};
links.forEach(d => {
nodeLinkStatus[`${d.source.index},${d.target.index}`] = 1;
});

function isConnected(a, b) {
return nodeLinkStatus[`${a.index},${b.index}`] || nodeLinkStatus[`${b.index},${a.index}`] || a.index === b.index;
}

// Node interactibility
node.on('mouseover',function (d) {
node.style('stroke-opacity', function (o) {
var thisOpacity = 0;
if(isConnected(d, o)){
thisOpacity = 1;
} else{
thisOpacity = 0.3;
}
this.setAttribute('fill-opacity', thisOpacity);

return thisOpacity;
});

link.style('opacity', function(l) {
if (d === l.source || d === l.target){
return 1;
} else{
return 0.2;
}
});


var xpos =d.x;
var ypos = d.y;
var tgrp = svg.append("g")
.attr("id", "tooltip")
.attr("transform", (d, i) => `translate(${xpos+10},${ypos})`);
tgrp.append("rect")
.attr("width", "140px")
.attr("height", "24px")
.attr("fill", "gray")
tgrp.append("text")
.attr("x", 5)
.attr("y", 14)
.attr("text-anchor", "left")
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("font-weight", "bold")
.attr("fill", "white")
.text(`${d.id}`);
});

node.on('mouseout',function (d) {
node.style('stroke-opacity', function (o) {
this.setAttribute('fill-opacity', 1);
return 1;
});
link.style('opacity',1);
link.style('stroke-width', d => Math.sqrt(d.value));
d3.select("#tooltip").remove();
});

// Simulation tick
simulation.on("tick", () => {
link.attr("points", function(d) {
return d.source.x + "," + d.source.y + " " +
(d.source.x + d.target.x)/2 + "," + (d.source.y + d.target.y)/2 + " " +
d.target.x + "," + d.target.y; });

node
.attr("cx", d => d.x)
.attr("cy", d => d.y);
});

return svg.node();
}

return {
Expand Down

0 comments on commit c9d306a

Please sign in to comment.