Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
A Python library using Altair for declarative, data-driven network visualisation.
Tidy, legible graph visualisations can be elusive. Alph helps by bringing together effective styling, layout and pruning options from across the Python ecosystem.
Best bet is probably to dive straight into the examples, and come back to the API documentation below as needed.
pos
structure (a dict like {node_id: (x,y), ...}
)pip install alph
for graphviz layout support, install graphviz on your platform - e.g. brew install graphviz
on Mac,
sudo apt install libgraphviz-dev graphviz
on Colab, Debian, Ubuntu etc - or download the installer
Install alph with graphviz support:
pip install "alph[graphviz]"
Install the ForceAtlas2 layout library from our fork, along with cython for speedup
pip install cython "git+https://github.com/connectedcompany/forceatlas2.git"
Why is the ForceAtlas2 install separate?
ForceAtlas2 is a classic, user feedback led layout algorithm from the Gephi team, and the ForceAtlas2 library implementation is an excellent, performant Python port. There are two things to be aware of:
GPL licence - the ForceAtlas2 library, and some of the works it is derived from, are GPL licensed - hence care is needed when distributing and linking to it. We thus intend to keep its install optional long term. Since alph uses a plugin design for layout providers, this is straightforward for us to accommodate, and maintain explicit separation for use cases where GPL is an issue.
Our fork - recently, releases of the library have been sporadic - though there is stated intent for regular maintenance to resume. In the meantime, we've created a temporary fork to be able to roll in changes. Currently, our fork incorporates a simple change that enables deterministic layouts.
Simply call the alph
function with desired options.
Minimally, given a weighted network G:
from alph import alph
G = ...
alph(G, weight_attr="weight")
See examples
. Here's an overview:
Some of the supported layouts (from the layouts gallery example):
Use of geolocation coordinates for graph layout, (from the flight routes example):
Basic styling (from the styling example):
A styled interaction network (from the dolphins example):
"Combo"-style layout (experimental) - category-driven node grouping with edge weight aggregation, from the Les Mis example:
args
for specific layouts - for example, for neato: args="-Goverlap=scale -Gstart=123"
arg | type(s) | default | description |
---|---|---|---|
G | Networkx Graph | graph to visualise | |
weight_attr | str | edge weight attribute, for weighted graphs | |
layout_fn | function | ForceAtlas2 | Function that, given a graph, returns a layout |
node args | dict | See below | |
edge args | dict | See below | |
combo_group_by | str or list | Attribute to use to create grouped combo nodes | |
combo_layout_fn | function | Fruchterman-Reingold | Layout function for combo nodes |
combo_node_args | dict | See below | |
combo_edge_args | dict | See below | |
combo_edge_weight_agg_attr | dict | Attribute to use to weigh combo edges; if set, overrides weight_attr. Can use values given via combo_edge_agg_attrs. If not set and weight_attr not given, falls back to simple edge count. | |
combo_edge_agg_attrs | dict | Pandas groupby-style dict, describing how to aggregate edge attributes that span nodes - for example {"combo_edge_attr_name": ("edge_attr_name", "sum")} | |
combo_edge_weight_threshold | dict | Drop edges below this weight | |
include_edgeless_combo_nodes | dict | Whether or not to incorporate disconnected combo nodes | |
combo_node_additional_attrs | dict | Attributes to add to combo nodes | |
edge_node_additional_attrs | dict | Attributes to add to combo node edges, like {"edge_attr_name": agg_fn} ; agg fn is applied across all attr values for edges that link grouped nodes | |
combo_empty_attr_action | drop, group or promote | drop | What to do with nodes that have an empty value for the combo_group_by attribute |
combo_size_scale_domain | 2-item list or tuple | [0, 25] | Lower/upper bound of num nodes to apply to combo node size range |
combo_size_scale_range | 2-item list or tuple | [6**2, 180**2] | Combo node size range |
combo_inner_graph_scale_factor | float | 0.6 | Scale down inner graph to fit inside combo nodes by this factor - normally <1 |
non_serializable_datetime_format | str | %d %b %Y | Format string for non-serialisable date / time types that otherwise break Altair |
width | int | 800 | Figure width (px) |
height | int | 600 | Figure height (px) |
prop_kwargs | dict | Optional properties such as title | |
padding | int | Padding inside figure edges. No node centres will be placed outside this boundary. | |
nodes_layer_params | selection or other | Altair params to be added to the nodes layer via .add_params() - typically a selection |
arg | type(s) | default |
---|---|---|
size | int, alt.* | 400 |
tooltip_attrs | list | |
fill | str, alt.* | #000 |
opacity | float, alt.* | 1 |
stroke | str, alt.* | #565656 |
strokeWidth | int, alt.* | 0 |
halo_offset | int | |
halo_opacity | float, alt.* | 1 |
halo_stroke | str, alt.* | #343434 |
halo_strokeWidth | int, alt.* | 2 |
label_attr | str | |
label_offset | int | 6 |
label_size | int | 10 |
label_color | str | black |
arg | type(s) | default |
---|---|---|
weight_attr | str | weight |
color | str, alt.* | #606060 |
opacity | float , alt.* | alt.Size(weight_attr, scale=alt.Scale(range=[0.3, 1]) if weighted, 1 otherwise |
strokeWidth | int, alt.* | alt.Size(weight_attr, scale=alt.Scale(range=[0.1, 5]) if weighted, 2 otherwise |
seed
to layout functions where possible, for repeatable layoutsNode size
attribute does not support all Altair options - currently only
alt.value
and alt.Size
with linear domain
and range
scales. More can be
added as needed.
This is a design choice, made to not burden the user with calculating things like label and halo positions when node sizes vary. Will review this tradeoff based on in-use experience.
One combo level currently supported
FAQs
alph
We found that alph demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.