Helios Network Visualization

_images/logo.png

About

Overview

What is Helios ?

Mission Statement

The purpose of Helios is to make it easy to perform graph/network Visualization …

Features

Efficient

Robust

Multiplatform

License

Helios is distributed under the MIT License

Credits

Go to Community page to see who have been involved in the development of Helios.

Bug reports and support

Please report any issues via https://github.com/fury-gl/helios/issues. All types of issues are welcome including bug reports, documentation typos, feature requests and so on.

License

Blog

Installation

Helios supports Python 3.7+.

Dependencies

The mandatory dependencies are:

  • numpy >= 1.7.1

  • vtk >= 8.1.0

  • fury

The optional dependencies are:

  • opencv

  • cugraph

Installation with PyPi

In a terminal, issue the following command

pip install helios

Installation via Source

Step 1. Get the latest source by cloning this repo

git clone https://github.com/fury-gl/helios.git

Step 2. Install requirements

pip install -r requirements.txt

Step 3. Install helios via

pip install -e .

Step 4: Enjoy!

Running the Tests

Let’s install all required packages for the running the test

pip install -r requirements.txt
pip install -r requirements_dev.txt

There are two ways to run Helios tests:

  • From the command line. You need to be on the Helios package folder

pytest -svv helios
  • To run a specific test file

pytest -svv helios/tests/test_actor.py
  • To run a specific test directory

pytest -svv helios/tests
  • To run a specific test function

pytest -svv -k "test_my_function_name"

Running the Tests Offscreen

Helios is based on VTK which uses OpenGL for all its rendering. For a headless rendering, we recommend to install and use Xvfb software on linux or OSX. Since Xvfb will require an X server (we also recommend to install XQuartz package on OSX). After Xvfb is installed you have 2 options to run Helios tests:

  • First option

export DISPLAY=:0
Xvfb :0 -screen 1920x1080x24 > /dev/null 2>1 &
pytest -svv fury
  • Second option

export DISPLAY=:0
xvfb-run --server-args="-screen 0 1920x1080x24" pytest -svv fury

Populating our Documentation

In our docs folder structure above:

  • source is the folder that contains all *.rst files.

  • tutorials is the directory where we have all python scripts that describe how to use the api.

  • examples being the Helios app showcases.

Building the documentation

Step 1. Install all required packages for the documentation generation

pip install -U -r requirements.txt
pip install -U -r requirements_docs_sys.txt

Step 2. Go to the docs folder and run the following command to generate it (Linux and macOS)

make -C . clean && make -C . html

To generate the documentation without running the examples

make -C . clean && make -C . html-no-examples

or under Windows

make clean
make html

To generate the documentation without running the examples under Windows

make clean
make html-no-examples

Step 3. Congratulations! the build folder has been generated! Go to build/html and open with browser index.html to see your generated documentation.

Getting Started

Start by importing Helios.

import numpy as np

Examples

Visualize Interdisciplinary map of the journals network

The goal of this app is to show an overview of the journals network structure as a complex network. Each journal is shown as a node and their connections indicates a citation between two of them.

First, let’s import some useful functions

from os.path import join as pjoin
from fury import colormap as cmap
from fury.window import record
import numpy as np

Then let’s download some available datasets.

from fury.data.fetcher import fetch_viz_wiki_nw

from helios import NetworkDraw
from helios.layouts.force_directed import HeliosFr

files, folder = fetch_viz_wiki_nw()
categories_file, edges_file, positions_file = sorted(files.keys())

Out:

Dataset is already in place. If you want to fetch it again please first remove the folder /home/devmessias/.fury/examples/wiki_nw
More information about complex networks can be found in this papers: https://arxiv.org/abs/0711.3199

We read our datasets

positions = np.loadtxt(pjoin(folder, positions_file))
positions = np.random.normal(scale=10, size=positions.shape)
categories = np.loadtxt(pjoin(folder, categories_file), dtype=str)
edges = np.loadtxt(pjoin(folder, edges_file), dtype=int)

We attribute a color to each category of our dataset which correspond to our nodes colors.

category2index = {category: i
                  for i, category in enumerate(np.unique(categories))}


index2category = np.unique(categories)

categoryColors = cmap.distinguishable_colormap(nb_colors=len(index2category))

colors = np.array([categoryColors[category2index[category]]
                   for category in categories])

We define our node size

radii = 1 + np.random.rand(len(positions))

Lets create our edges now. They will indicate a citation between two nodes. OF course, the colors of each edges will be an interpolation between the two node that it connects.

#edgesPositions = []
edgesColors = []
for source, target in edges:
    #edgesPositions.append(np.array([positions[source], positions[target]]))
    edgesColors.append(np.array([colors[source], colors[target]]))

#edgesPositions = np.array(edgesPositions)
edgesColors = np.average(np.array(edgesColors), axis=1)

Our data preparation is ready, it is time to visualize them all. We start to build 2 actors that we represent our data : sphere_actor for the nodes and lines_actor for the edges.

network_draw = NetworkDraw(
        positions=positions,
        colors=colors,
        scales=4,
        node_edge_width=0,
        edge_line_color=edgesColors,
        marker='3d',
        edges=edges,
)
layout = HeliosFr(edges, network_draw, update_interval_workers=10)

layout.start()

The final step ! Visualize and save the result of our creation! Please, switch interactive variable to True if you want to visualize it.

interactive = False
if not interactive:
    import time
    time.sleep(10)
    layout.stop()

if interactive:
    network_draw.showm.initialize()
    network_draw.showm.start()

record(
    network_draw.showm.scene, out_path='viz_helios.png', size=(600, 600))
viz helios

Total running time of the script: ( 0 minutes 14.288 seconds)

Gallery generated by Sphinx-Gallery

Minmum Distortion Embedding with Anchored Constraints

viz mde
import numpy as np
import time
from fury.window import record

from helios import NetworkDraw
from helios.layouts.mde import MDE

# from https://github.com/cvxgrp/pymde/blob/main/examples/anchor_constraints.ipynb

depth = 9
n_items = 2**(depth + 1) - 1

edges = []
stack = [0]
while stack:
    root = stack.pop()
    first_child = root*2 + 1
    second_child = root*2 + 2
    if first_child < n_items:
        edges.append([root, first_child])
        stack.append(first_child)
    if second_child < n_items:
        edges.append([root, second_child])
        stack.append(second_child)

# these are the indices of the nodes that we will pin in place
anchors = np.arange(2**depth) + 2**depth - 1


radius = 20

# pin the root to be at (0, 0), and the leaves to be spaced uniformly on a circle
angles = np.linspace(0, 2*np.pi, anchors.shape[0] + 1)[1:]
anchors_pos = radius * np.stack([np.sin(angles), np.cos(angles)], axis=1)
centers = np.random.normal(size=(n_items, 2))*5
centers[anchors] = anchors_pos.copy()


network_draw = NetworkDraw(
        positions=centers,
        scales=.4,
        node_edge_width=0,
        #colors=(1, 0,0),
        edge_line_opacity=.5,
        edge_line_color=(0, 0, 0),
        marker='3d',
        window_size=(500, 500),
        edges=np.array(edges)
)

mde = MDE(
    np.array(edges), network_draw,
    constraint_name='anchored',
    anchors=anchors.astype('float32'),
    anchors_pos=anchors_pos.astype('float32'),
    use_shortest_path=True
)


interactive = False
if not interactive:
    mde.start(
        100, 1, 300,
        record_positions=False, without_iren_start=True)
    time.sleep(30)
    mde.stop()
else:
    mde.start(
        3, 300, 1,
        record_positions=True, without_iren_start=False)

if interactive:
    network_draw.showm.initialize()
    network_draw.showm.start()

record(
    network_draw.showm.scene, out_path='viz_mde.png', size=(600, 600))

Total running time of the script: ( 0 minutes 30.180 seconds)

Gallery generated by Sphinx-Gallery

Gallery generated by Sphinx-Gallery

Contributing

Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.

You can contribute in many ways:

Types of Contributions

Report Bugs

Report bugs at https://github.com/fury-gl/helios/issues.

If you are reporting a bug, please include:

  • Any details about your local setup that might be helpful in troubleshooting.

  • Detailed steps to reproduce the bug.

Fix Bugs

Look through the GitHub issues for bugs. Anything tagged with “bug” is open to whoever wants to implement it.

Implement Features

Look through the GitHub issues for features. Anything tagged with “feature” is open to whoever wants to implement it.

Write Documentation

Helios could always use more documentation, whether as part of the official Helios docs, in docstrings, or even on the web in blog posts, articles, and such. Helios uses [Sphinx](http://www.sphinx-doc.org/en/stable/index.html) to generate documentation. Please follow the [numpy coding style](https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard) - and of course - [PEP8](https://www.python.org/dev/peps/pep-0008/) for docstring documentation.

Submit Feedback

The best way to send feedback is to file an issue at https://github.com/fury-gl/helios/issues.

If you are proposing a feature:

  • Explain in detail how it would work.

  • Keep the scope as narrow as possible, to make it easier to implement.

  • Remember that this is a volunteer-driven project, and that contributions are welcome :)

Get Started!

Pull Request Guidelines

Before you submit a pull request, check that it meets these guidelines:

  1. The pull request should include tests.

  2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.md.

  3. The pull request should work for Python3.7, 3.8, 3.9 and for PyPy.

Publishing Releases

Checklist before Releasing

  • Review the open list of Helios issues. Check whether there are outstanding issues that can be closed, and whether there are any issues that should delay the release. Label them !

  • Review and update the release notes. Review and update the Changelog file. Get a partial list of contributors with something like:

    git shortlog -nse v0.1.0..
    

    where v0.1.0 was the last release tag name.

    Then manually go over git shortlog v0.1.0.. to make sure the release notes are as complete as possible and that every contributor was recognized.

  • Use the opportunity to update the .mailmap file if there are any duplicate authors listed from git shortlog -ns.

  • Add any new authors to the AUTHORS file.

  • Check the copyright years in docs/source/conf.py and LICENSE

  • Check the examples and tutorial - we really need an automated check here.

  • Make sure all tests pass on your local machine (from the <helios root> directory):

    cd ..
    pytest -s --verbose --doctest-modules helios
    cd helios # back to the root directory
    
  • Check the documentation doctests:

    cd docs
    make -C . html
    cd ..
    
  • The release should now be ready.

Doing the release

  • Update release-history.rst in the documentation if you have not done so already. You may also highlight any additions, improvements, and bug fixes.

  • Type git status and check that you are on the master branch with no uncommitted code.

  • Now it’s time for the source release. Mark the release with an empty commit, just to leave a marker. It makes it easier to find the release when skimming through the git history:

    git commit --allow-empty -m "REL: vX.Y.Z"
    
  • Tag the commit:

    git tag -am 'Second public release' vX.Y.Z  # Don't forget the leading v
    

    This will create a tag named vX.Y.Z. The -a flag (strongly recommended) opens up a text editor where you should enter a brief description of the release.

  • Verify that the __version__ attribute is correctly updated:

    import helios
    helios.__version__  # should be 'X.Y.Z'
    

    Incidentally, once you resume development and add the first commit after this tag, __version__ will take on a value like X.Y.Z+1.g58ad5f7, where +1 means “1 commit past version X.Y.Z” and 58ad5f7 is the first 7 characters of the hash of the current commit. The letter g stands for “git”. This is all managed automatically by versioneer and in accordance with the specification in PEP 440.

  • Push the new commit and the tag to master:

    git push origin master
    git push origin vX.Y.Z
    
  • Register for a PyPI account and Install twine, a tool for uploading packages to PyPI:

    python3 -m pip install --upgrade twine
    
  • Remove any extraneous files:

    git clean -dfx
    

    If you happen to have any important files in your project directory that are not committed to git, move them first; this will delete them!

  • Publish a release on PyPI:

    python setup.py sdist
    python setup.py bdist_wheel
    twine upload dist/*
    
  • Check how everything looks on pypi - the description, the packages. If necessary delete the release and try again if it doesn’t look right.

  • Set up maintenance / development branches

    If this is this is a full release you need to set up two branches, one for further substantial development (often called ‘trunk’) and another for maintenance releases.

    • Branch to maintenance:

      git co -b maint/X.Y.Z
      

      Push with something like git push upstream-rw maint/0.6.x --set-upstream

    • Start next development series:

      git co main-master
      

      Next merge the maintenace branch with the “ours” strategy. This just labels the maintenance branch info.py edits as seen but discarded, so we can merge from maintenance in future without getting spurious merge conflicts:

      git merge -s ours maint/0.6.x
      

      Push with something like git push upstream-rw main-master:master

    If this is just a maintenance release from maint/0.6.x or similar, just tag and set the version number to - say - 0.6.2.dev.

  • Push the tag with git push upstream-rw 0.6.0

Community