|
| 1 | +Plotting Examples |
| 2 | +================= |
| 3 | + |
| 4 | +We have included a few functions to generate plots of CHAMP domains and resolution parameter estimates in the |
| 5 | +singlelayer and multilayer cases. We encourage you to make your own application-specific plotting code as well (the |
| 6 | +source code in modularitypruning.plotting is very straightforward and may provide inspiration). |
| 7 | + |
| 8 | +Plotting Single-Layer CHAMP Domains and Resolution Parameter Estimates |
| 9 | +---------------------------------------------------------------------- |
| 10 | + |
| 11 | +.. autofunction:: modularitypruning.plotting.plot_estimates |
| 12 | + |
| 13 | +An example on the Karate Club network is as follows. |
| 14 | + |
| 15 | +.. code-block:: python |
| 16 | +
|
| 17 | + import igraph as ig |
| 18 | + import matplotlib.pyplot as plt |
| 19 | + from modularitypruning.champ_utilities import CHAMP_2D |
| 20 | + from modularitypruning.parameter_estimation_utilities import ranges_to_gamma_estimates |
| 21 | + from modularitypruning.louvain_utilities import repeated_parallel_louvain_from_gammas |
| 22 | + from modularitypruning.plotting import plot_estimates |
| 23 | + import numpy as np |
| 24 | +
|
| 25 | + # get Karate Club graph in igraph |
| 26 | + G = ig.Graph.Famous("Zachary") |
| 27 | +
|
| 28 | + # run louvain 100K times on this graph from gamma=0 to gamma=2 (takes ~2-3 seconds) |
| 29 | + partitions = repeated_parallel_louvain_from_gammas(G, np.linspace(0, 2, 10 ** 5)) |
| 30 | +
|
| 31 | + # run CHAMP to obtain the dominant partitions along with their regions of optimality |
| 32 | + ranges = CHAMP_2D(G, partitions, gamma_0=0.0, gamma_f=2.0) |
| 33 | +
|
| 34 | + # append gamma estimate for each dominant partition onto the CHAMP domains |
| 35 | + gamma_estimates = ranges_to_gamma_estimates(G, ranges) |
| 36 | +
|
| 37 | + # plot gamma estimates and domains of optimality |
| 38 | + plt.rc('text', usetex=True) |
| 39 | + plt.rc('font', family='serif') |
| 40 | + plot_estimates(gamma_estimates) |
| 41 | + plt.title(r"Karate Club CHAMP Domains of Optimality and $\gamma$ Estimates", fontsize=14) |
| 42 | + plt.xlabel(r"$\gamma$", fontsize=14) |
| 43 | + plt.ylabel("Number of communities", fontsize=14) |
| 44 | + plt.show() |
| 45 | +
|
| 46 | +which generates |
| 47 | + |
| 48 | +.. image:: ../example_figures/figure_plot_estimates.png |
| 49 | + |
| 50 | +Plotting Multi-Layer CHAMP domains and Resolution Parameter Estimates |
| 51 | +--------------------------------------------------------------------- |
| 52 | + |
| 53 | +.. autofunction:: modularitypruning.plotting.plot_2d_domains_with_estimates |
| 54 | + |
| 55 | +An example on a realization of multilayer synthetic network in :doc:`../source/basic_multilayer_example` is as follows. |
| 56 | + |
| 57 | +.. code-block:: python |
| 58 | +
|
| 59 | + from modularitypruning.champ_utilities import CHAMP_3D |
| 60 | + from modularitypruning.louvain_utilities import (repeated_parallel_louvain_from_gammas_omegas, |
| 61 | + check_multilayer_louvain_capabilities) |
| 62 | + from modularitypruning.parameter_estimation_utilities import domains_to_gamma_omega_estimates |
| 63 | + from modularitypruning.plotting import plot_2d_domains_with_estimates |
| 64 | + import matplotlib.pyplot as plt |
| 65 | + import numpy as np |
| 66 | +
|
| 67 | + # fail if version of louvain does not support multilayer optimization |
| 68 | + check_multilayer_louvain_capabilities() |
| 69 | +
|
| 70 | + # run louvain on a uniform grid (10K samples) of gamma and omega (takes ~3 seconds) |
| 71 | + gamma_range = (0.5, 1.5) |
| 72 | + omega_range = (0, 2) |
| 73 | + parts = repeated_parallel_louvain_from_gammas_omegas(G_intralayer, G_interlayer, layer_vec, |
| 74 | + gammas=np.linspace(*gamma_range, 100), |
| 75 | + omegas=np.linspace(*omega_range, 100)) |
| 76 | +
|
| 77 | + # run CHAMP to obtain the dominant partitions along with their regions of optimality |
| 78 | + domains = CHAMP_3D(G_intralayer, G_interlayer, layer_vec, parts, |
| 79 | + gamma_0=gamma_range[0], gamma_f=gamma_range[1], |
| 80 | + omega_0=omega_range[0], omega_f=omega_range[1]) |
| 81 | +
|
| 82 | + # append resolution parameter estimates for each dominant partition onto the CHAMP domains |
| 83 | + domains_with_estimates = domains_to_gamma_omega_estimates(G_intralayer, G_interlayer, layer_vec, |
| 84 | + domains, model='temporal') |
| 85 | +
|
| 86 | + # plot resolution parameter estimates and domains of optimality |
| 87 | + plt.rc('text', usetex=True) |
| 88 | + plt.rc('font', family='serif') |
| 89 | + plot_2d_domains_with_estimates(domains_with_estimates, xlim=omega_range, ylim=gamma_range) |
| 90 | + plt.title(r"CHAMP Domains and ($\omega$, $\gamma$) Estimates", fontsize=16) |
| 91 | + plt.xlabel(r"$\omega$", fontsize=20) |
| 92 | + plt.ylabel(r"$\gamma$", fontsize=20) |
| 93 | + plt.gca().tick_params(axis='both', labelsize=12) |
| 94 | + plt.tight_layout() |
| 95 | + plt.show() |
| 96 | +
|
| 97 | +which generates |
| 98 | + |
| 99 | +.. image:: ../example_figures/figure_plot_2d_domains_with_estimates.png |
| 100 | + |
| 101 | +There are other similar functions |
| 102 | + * :meth:`~modularitypruning.plotting.plot_2d_domains` essentially plots the above without arrows showing resolution |
| 103 | + parameter estimates |
| 104 | + * :meth:`~modularitypruning.plotting.plot_2d_domains_with_ami` plots CHAMP domains, colored by the AMI between each |
| 105 | + partition and a ground truth |
| 106 | + * :meth:`~modularitypruning.plotting.plot_2d_domains_with_num_communities` plots CHAMP domains, colored by number |
| 107 | + of communities |
| 108 | + |
| 109 | +For example, the last function generates |
| 110 | + |
| 111 | +.. image:: ../example_figures/figure_plot_2d_domains_with_num_communities.png |
| 112 | + |
| 113 | +Plotting Multiplex Community Structure of a Single Partition |
| 114 | +------------------------------------------------------------ |
| 115 | + |
| 116 | +.. autofunction:: modularitypruning.plotting.plot_multiplex_community |
| 117 | + |
| 118 | +An example from the Lazega Law Firm network is as follows |
| 119 | + |
| 120 | +.. code-block:: python |
| 121 | +
|
| 122 | + from modularitypruning.plotting import plot_multiplex_community |
| 123 | + import matplotlib.pyplot as plt |
| 124 | + import numpy as np |
| 125 | +
|
| 126 | + num_layers = 3 |
| 127 | + layer_vec = [i // 71 for i in range(num_layers * 71)] |
| 128 | + membership = [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, |
| 129 | + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 130 | + 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, |
| 131 | + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 132 | + 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, |
| 133 | + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 134 | + 2, 2, 2] |
| 135 | +
|
| 136 | + plt.rc('text', usetex=True) |
| 137 | + plt.rc('font', family='serif') |
| 138 | + ax = plot_multiplex_community(np.array(membership), np.array(layer_vec)) |
| 139 | + ax.set_xticks(np.linspace(0, num_layers, 2 * num_layers + 1)) |
| 140 | + ax.set_xticklabels(["", "Advice", "", "Coworker", "", "Friend", ""], fontsize=14) |
| 141 | + plt.title(f"Multiplex Communities", fontsize=14) |
| 142 | + plt.ylabel("Node ID", fontsize=14) |
| 143 | + plt.show() |
| 144 | +
|
| 145 | +which generates |
| 146 | + |
| 147 | +.. image:: ../example_figures/figure_plot_multiplex_community.png |
0 commit comments