{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Visualizing Information Diffusion" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import random\n", "\n", "import networkx as nx\n", "import matplotlib as mpl\n", "import matplotlib.pyplot as plt\n", "from matplotlib.animation import FuncAnimation\n", "import matplotlib.gridspec as gridspec\n", "from matplotlib.ticker import MaxNLocator\n", "\n", "from IPython import display \n", "\n", "from numpy.linalg import norm" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Typographical fine-tuning" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "mpl.rcParams['font.family'] = 'sans-serif'\n", "mpl.rcParams['font.sans-serif'] = 'Open sans'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setting up the parameters" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "number_of_nodes = 1000\n", "number_of_isolated_nodes = 100\n", "distance_threshold = 0.1\n", "density = 0.15" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Creating a pseudo-random graph" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "G = nx.Graph()\n", "G.add_nodes_from(range(0, number_of_nodes))\n", "isolated = random.sample(list(G.nodes()), number_of_isolated_nodes)\n", "\n", "pos = nx.random_layout(G)\n", "\n", "for node_a in G.nodes:\n", " for node_b in G.nodes:\n", " if node_a != node_b and ((node_a in isolated and node_b in isolated) or (node_a not in isolated and node_b not in isolated)):\n", " distance = norm(pos[node_a] - pos[node_b])\n", " if distance <= distance_threshold and random.random() < density:\n", " G.add_edge(node_a, node_b)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "start_node = 9\n", "distances = list(nx.bfs_layers(G, start_node))\n", "\n", "informed = {}\n", "for distance, nodes in enumerate(distances):\n", " if distance == 0:\n", " informed[distance] = nodes\n", " else:\n", " informed[distance] = informed[distance-1] + nodes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Animating" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def update(frame, G, informed, ax_network, ax_cdf):\n", " ax_network.clear()\n", "\n", " colors = ['orangered' if node in informed[frame] else 'royalblue' for node in G.nodes]\n", " nx.draw_networkx_nodes(G, pos, node_color=colors, edgecolors='black', node_size=30, linewidths=0.25, ax=ax_network, margins=0)\n", " nx.draw_networkx_edges(G, pos, width=0.5, edge_color='gray', min_source_margin=0, min_target_margin=0, ax=ax_network)\n", "\n", " cdf = {distance: len(v)/len(G.nodes) for distance, v in informed.items()}\n", " ax_cdf.plot(range(0, frame+1), [cdf[l] for l in range(0, frame+1)], color='orangered')" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = plt.figure(figsize=(16, 9), )\n", "gs = gridspec.GridSpec(3, 4, figure=fig)\n", "\n", "ax1 = fig.add_subplot(gs[0:3, 0:3], aspect='auto')\n", "ax1.clear()\n", "ax1.set_axis_off()\n", "\n", "for spine in ax1.spines.values():\n", " spine.set_visible(False)\n", "\n", "ax2 = fig.add_subplot(gs[1, 3], aspect='auto')\n", "ax2.set(xlim=(0, len(informed)), ylim=(0, 1.0))\n", "ax2.xaxis.set_major_locator(MaxNLocator(integer=True))\n", "ax2.grid(True)\n", "ax2.set_xlabel('Distance')\n", "ax2.set_ylabel('Reachable participants')\n", "\n", "plt.tight_layout()\n", "\n", "\n", "animation = FuncAnimation(fig, update, frames=len(informed), interval=800, repeat=False, fargs=(G, informed, ax1, ax2), blit=False)\n", "video = animation.to_html5_video()\n", "html = display.HTML(video)\n", "display.display(html) \n", "\n", "plt.close() \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.4" } }, "nbformat": 4, "nbformat_minor": 2 }