TLDR; Python script for radial convergence plots that can be found here.
You might have encountered this type of graph before, they’re usually used to present relationships between different entities/parameters/factors and they typically look like this:
In the context of our work, I have seen them used to present sensitivity analysis results, where we are interested in both the individual significance of a model parameter, but also the extent of its interaction with others. For example, in Butler et al. (2014) they were used to present First, Second, and Total order parameter sensitivities as produced by a Sobol’ Sensitivity Analysis.
I set out to write a Python script to replicate them. Calvin Whealton has written a similar script in R, and the same functionality also exists within Rhodium. I just wanted something with a bit more flexibility, so I wrote this script that produces two types of these graphs, one with straight lines and one with curved (which are prettier IMO). The script takes dictionary items as inputs, either directly from SALib and Rhodium (if you are using it to display Sobol results), or by importing them (to display anything else). You’ll need one package to get this to run: NetworkX. It facilitates the organization of the nodes in a circle and it’s generally a very stable and useful package to have.
I made these graphs to display results the results of a Sobol analysis I performed on the model parameters of a system I am studying (a, b, c, d, h, K, m, sigmax, and sigmay). The node size indicates the first order index (S1) per parameter, the node border thickness indicates the total order index (ST) per parameter, and the thickness of the line between two nodes indicates the secord order index (S2). The colors, thicknesses, and sizes can be easily changed to fit your needs. The script for these can be found here, and I will briefly discuss what it does below.
After loading the necessary packages (networkx, numpy, itertools, and matplotlib) and data, there is some setting parameters that can be adapted for the figure generation. First, we can define a significance value for the indices (here set to 0.01). To keep all values just set it to 0. Then we have some stylistic variables that basically define the thicknesses and sizes for the lines and nodes. They can be changed to get the look of the graph to your liking.
# Set min index value, for the effects to be considered significant index_significance_value = 0.01 node_size_min = 15 # Max and min node size node_size_max = 30 border_size_min = 1 # Max and min node border thickness border_size_max = 8 edge_width_min = 1 # Max and min edge thickness edge_width_max = 10 edge_distance_min = 0.1 # Max and min distance of the edge from the center of the circle edge_distance_max = 0.6 # Only applicable to the curved edges
The rest of the code should just do the work for you. It basically does the following:
- Define basic variables and functions that help draw circles and curves, get angles and distances between points
- Set up graph with all parameters as nodes and draw all second order (S2) indices as lines (edges in the network) connecting the nodes. For every S2 index, we need a Source parameter, a Target parameter, and the Weight of the line, given by the S2 index itself. If you’re using this script for other data, different information can fit into the line thickness, or they could all be the same.
- Draw nodes and lines in a circular shape and adjust node sizes, borders, and line thicknesses to show the relative importance/weight. Also, annotate text labels on each node and adjust their location accordingly. This produces the graph with the straight lines.
- For the graph with the curved lines, define function that will generate the x and y coordinates for them, and then plot using matplotlib.
I would like to mention this script by Enrico Ubaldi, based on which I developed mine.