{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "a0df6b80-19ba-4156-8c4d-9300880c11cb", "metadata": {}, "outputs": [], "source": [ "install.packages(\"devtools\")\n", "library(devtools)\n", "devtools::install_local('/home/jovyan/gganimate-0.1.1.tar.gz')\n", "devtools::install_local('/home/jovyan/ggraph-d15fd149babe9ad32316474b9a178e019f376ba6.zip')\n", "library(gganimate)\n", "library(ggraph)\n", "library(igraph)\n", "library(RColorBrewer)" ] }, { "cell_type": "code", "execution_count": null, "id": "b4e87fb8-b58e-4309-adfc-2a7cfe9afbd8", "metadata": {}, "outputs": [], "source": [ "# Originally for data from http://konect.uni-koblenz.de/networks/sociopatterns-infectious\n", "# as part of a museum exhibit on spread of infections http://www.sociopatterns.org/deployments/infectious-sociopatterns/\n", "# and the paper http://www.sociopatterns.org/publications/whats-in-a-crowd-analysis-of-face-to-face-behavioral-networks/\n", "\n", "# Code adapted from https://gist.github.com/thomasp85/eee48b065ff454e390e1\n", "# and from https://gist.github.com/jalapic/612036977d9f9c773107681bc4a46d58\n", "\n", "infect <- read.table('/home/jovyan/networkDynamicsLabels.txt', skip = 0, sep = ' ', stringsAsFactors = FALSE)\n", "infect$V3 <- NULL \n", "names(infect) <- c('from', 'to', 'time')\n", "infect$timebins <- as.numeric(cut(infect$time, breaks = 150)) # lower means more bursty, i.e. breaks = 10\n", "\n", "# We want that nice fading effect so we need to add extra data for the trailing\n", "infectAnim <- lapply(1:10, function(i) {infect$timebins <- infect$timebins + i; infect$delay <- i; infect})\n", "infect$delay <- 0\n", "infectAnim <- rbind(infect, do.call(rbind, infectAnim))\n", "\n", "infectGraph <- graph_from_data_frame(infectAnim, directed = F)\n", "\n", "# We use only original data for the layout\n", "subGr <- subgraph.edges(infectGraph, which(E(infectGraph)$delay == 0))\n", "V(subGr)$degree <- degree(subGr)\n", "V(subGr)$group <- cluster_louvain(subGr)$membership\n", "lay <- createLayout(subGr, 'igraph', algorithm = 'fr') # change spatial layout of network\n", "\n", "# Then we reassign the full graph with edge trails\n", "attr(lay, 'graph') <- infectGraph\n", "\n", "# Now we create the graph with timebins as frame\n", "p <- ggraph(data = lay, layout = 'fr', aes(frame = timebins)) + \n", " geom_node_point(size = .025, col = \"white\") + # change size & color of inactive nodes\n", " geom_node_point(aes(alpha=0.6), size = .025, colour = factor(lay$group), show.legend = FALSE) + # change size & color of active nodes\n", " # geom_edge_link0(aes(frame = timebins, alpha = delay, width = delay), edge_colour = '#dccf9f') + \n", " geom_edge_link0(aes(frame = timebins, alpha = delay, width = delay, colour = factor(node1.group)), data = gEdges(nodePar = 'group'), show.legend = FALSE) +\n", " # geom_edge_link0(aes(frame = timebins, alpha = delay, width = delay, colour = node1.degree), data = gEdges(nodePar = 'degree'), show.legend = FALSE) +\n", " scale_edge_alpha(range = c(1, 0), guide = 'none') + \n", " scale_edge_width(range = c(0.25, 0.75), trans = 'exp', guide = 'none') + # change edge width\n", " scale_size(guide = 'none') + \n", " expand_limits(x = c(min(lay$x), max(lay$x)), y = c(min(lay$y), max(lay$y))) +\n", " ggforce::theme_no_axes() + \n", " theme(plot.background = element_rect(fill = '#000000'), # change background color\n", " panel.background = element_blank(), \n", " panel.border = element_blank(), \n", " plot.title = element_text(color = '#cecece'))\n", "\n", "infect" ] }, { "cell_type": "code", "execution_count": null, "id": "049bdcfe-7af0-4876-8f4b-fee828c265ab", "metadata": {}, "outputs": [], "source": [ "# Note if the animation surpasses the memory usage of the notebook, it will crash.\n", "# reduce memory by changing image size, image resolution, making network smaller, \n", "# changing interval, and/or changing breaks\n", "\n", "# And then we animate\n", "animation::ani.options(interval=0.01) # change speed of frame transitions\n", "\n", "gganim <- gganimate(p, '/home/jovyan/sparkingCuriosity.gif', title_frame = FALSE,\n", " ani.width = 400, ani.height = 400, res=100) # change image size and resolution\n" ] } ], "metadata": { "kernelspec": { "display_name": "R", "language": "R", "name": "ir" }, "language_info": { "codemirror_mode": "r", "file_extension": ".r", "mimetype": "text/x-r-source", "name": "R", "pygments_lexer": "r", "version": "4.0.2" } }, "nbformat": 4, "nbformat_minor": 5 }