{"id":13688694,"url":"https://github.com/hypercoil/hyve","last_synced_at":"2026-01-18T12:11:19.974Z","repository":{"id":187406187,"uuid":"665643796","full_name":"hypercoil/hyve","owner":"hypercoil","description":"Interactive and static 3D visualisation for functional brain mapping","archived":false,"fork":false,"pushed_at":"2024-09-25T06:42:06.000Z","size":4832,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-03T07:19:58.634Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hypercoil.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-12T16:58:51.000Z","updated_at":"2024-08-20T12:37:29.000Z","dependencies_parsed_at":"2023-11-06T03:33:05.328Z","dependency_job_id":"c50127aa-fadf-46ee-8408-82e95797ac5d","html_url":"https://github.com/hypercoil/hyve","commit_stats":null,"previous_names":["hypercoil/hyve"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hypercoil%2Fhyve","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hypercoil%2Fhyve/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hypercoil%2Fhyve/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hypercoil%2Fhyve/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hypercoil","download_url":"https://codeload.github.com/hypercoil/hyve/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224274679,"owners_count":17284627,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T15:01:20.376Z","updated_at":"2026-01-18T12:11:14.929Z","avatar_url":"https://github.com/hypercoil.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# ``hyve``\nInteractive and static 3D visualisation for functional brain mapping\n\n``hyve`` (``hypercoil`` visualisation engine) is a Python package for interactive and static 3D visualisation of functional brain mapping data. It was originally designed to be used in conjunction with the [``hypercoil``](https://github.com/hypercoil/) project for differentiable programming in the context of functional brain mapping, but can be used independently.\n\nThis system is currently under development, and the API is accordingly subject to sweeping changes without notice. In particular, before using this system, be aware of the *major* limitations that exist, detailed under the *v1.0.0* header here (and soon to be added as issues). Documentation is also extremely sparse, but will be added in the near future. To get a sense of how the package might look and feel when it is more mature, you can take a look at the test cases in the ``tests`` directory.\n\n``hyve`` allows for the visualisation of 3D data in a variety of formats, including volumetric data, surface meshes, and 3-dimensional network renderings. It is built using a rudimentary quasi-functional programming paradigm, allowing users to compose new plotting utilities for their data by chaining together functional primitives. The system is designed to be modular and extensible, and can be easily extended to support new data types and visualisation techniques. It is built on top of the ``pyvista`` library and therefore uses VTK as its rendering backend. The system is also capable of combining visualisations as panels of a SVG figure.\n\n## Installation\n\n``hyve`` can be installed from PyPI using ``pip``:\n\n```bash\npip install hyve==0.0.2\n```\n\nThe below examples also require installation of the ``hyve-examples`` package, which can be installed from PyPI using ``pip``:\n\n```bash\npip install hyve-examples\n```\n\n## Contributing\n\nSuggestions for improvement and contributions are welcome. Please open an issue or submit a pull request if you have any ideas for how to improve the package. ``hyve`` is not feature-complete and is still under active development, so there are many opportunities for improvement. There are also likely to be many bugs, so please open an issue if you encounter any problems.\n\n## Basic usage\n\nThe following example demonstrates how to use ``hyve`` to visualise a 3D surface mesh and create a HTML-based interactive visualisation (built on the ``trame`` library) that can be viewed in a web browser:\n\n```python\nfrom hyve_examples import get_null400_cifti\nfrom hyve.flows import plotdef\nfrom hyve.transforms import (\n    surf_from_archive,\n    surf_scalars_from_cifti,\n    parcellate_colormap,\n    vertex_to_face,\n    plot_to_html,\n)\n\nplot_f = plotdef(\n    surf_from_archive(),\n    surf_scalars_from_cifti('parcellation'),\n    parcellate_colormap('parcellation', 'network'),\n    vertex_to_face('parcellation'),\n    plot_to_html(\n        fname_spec=(\n            'scalars-{surfscalars}_hemisphere-{hemisphere}_cmap-network'\n        ),\n    ),\n)\nplot_f(\n    template='fsLR',\n    load_mask=True,\n    parcellation_cifti=get_null400_cifti(),\n    surf_projection=['veryinflated'],\n    hemisphere=['left', 'right'],\n    window_size=(800, 800),\n    output_dir='/tmp',\n)\n```\n\nThe HTML files generated by this example will be written to ``/tmp/scalars-parcellation_hemisphere-left_cmap-network_scene.html`` and ``/tmp/scalars-parcellation_hemisphere-right_cmap-network_scene.html``. These files can be opened in a web browser to view the interactive visualisation.\n\nNote that, unlike many other plotting libraries, ``hyve`` does not provide a single function that can be used to generate a plot. Instead, it provides a set of functional primitives that can be chained together to create a custom plotting pipeline using the ``plotdef`` function. This allows users to create new plotting utilities by composing primirives. For example, the ``plot_f`` function used in the example above is a composition of the ``surf_from_archive``, ``surf_scalars_from_cifti``, ``parcellate_colormap``, ``vertex_to_face``, and ``plot_to_html`` functions with a unified base plotter. The ``plot_f`` function can be used to generate a plot by passing it a set of keyword arguments that specify the data to be plotted and the visualisation parameters. The ``plot_f`` function can also be used to generate a plot from a set of keyword arguments that specify the data to be plotted and the visualisation parameters.\n\nThis approach allows users to create new plotting utilities without having to write much new code, but it can be difficult to understand at first.\n\nIt's also possible to use ``hyve`` to create static visualisations. For example, the following example creates glass brain visualisations of the pain network from Xu et al. (2020) (10.1016/j.neubiorev.2020.01.004).\n\n```python\nfrom hyve_examples import get_pain_thresh_nifti\nfrom hyve.flows import plotdef\nfrom hyve.transforms import (\n    surf_from_archive,\n    points_scalars_from_nifti,\n    plot_to_image,\n    save_snapshots,\n)\n\n\nnii = get_pain_thresh_nifti()\nplot_f = plotdef(\n    surf_from_archive(),\n    points_scalars_from_nifti('pain'),\n    plot_to_image(),\n    save_snapshots(\n        fname_spec=(\n            'scalars-{pointsscalars}_view-{view}'\n        ),\n    ),\n)\nplot_f(\n    template='fsaverage',\n    surf_projection=('pial',),\n    surf_alpha=0.3,\n    pain_nifti=nii,\n    points_scalars_cmap='magma',\n    views=('dorsal', 'left', 'anterior'),\n    output_dir='/tmp',\n)\n```\n\nAnd the below code demonstrates how to use ``hyve`` to create a static PNG image of a BrainNetViewer-like scene of a 3D brain network embedded in a surface mesh:\n\n```python\nimport numpy as np\nimport pandas as pd\n\nfrom hyve_examples import (\n    get_schaefer400_synthetic_conmat,\n    get_schaefer400_cifti,\n)\nfrom hyve.flows import plotdef\nfrom hyve.flows import add_network_data\nfrom hyve.transforms import (\n    surf_from_archive,\n    surf_scalars_from_cifti,\n    parcellate_colormap,\n    add_node_variable,\n    add_edge_variable,\n    plot_to_image,\n    save_snapshots,\n    node_coor_from_parcels,\n    build_network,\n    add_network_overlay,\n)\n\n# Get a parcellation and the corresponding connectivity matrix\nparcellation = get_schaefer400_cifti()\ncov = pd.read_csv(\n    get_schaefer400_synthetic_conmat(), sep='\\t', header=None\n).values\n\n# Select some nodes and edges to be highlighted\nvis_nodes_edge_selection = np.zeros(400, dtype=bool)\nvis_nodes_edge_selection[0:5] = True\nvis_nodes_edge_selection[200:205] = True\n\n# Define a plotting function\nplot_f = plotdef(\n    surf_from_archive(),\n    surf_scalars_from_cifti('parcellation', plot=False),\n    add_network_data(\n        add_node_variable('vis'),\n        add_edge_variable(\n            'vis_conn',\n            threshold=10,\n            topk_threshold_nodewise=True,\n            absolute=True,\n            incident_node_selection=vis_nodes_edge_selection,\n            emit_degree=True,\n        ),\n        add_edge_variable(\n            'vis_internal_conn',\n            absolute=True,\n            connected_node_selection=vis_nodes_edge_selection,\n        ),\n    ),\n    node_coor_from_parcels('parcellation'),\n    build_network('vis'),\n    parcellate_colormap('parcellation', 'network', target='node'),\n    plot_to_image(),\n    save_snapshots(\n        fname_spec=(\n            'network-schaefer400_view-{view}'\n        ),\n    ),\n)\n\n# Generate a plot\nplot_f(\n    template='fsLR',\n    surf_projection='inflated',\n    surf_alpha=0.2,\n    parcellation_cifti=parcellation,\n    node_radius='vis_conn_degree',\n    node_color='index',\n    edge_color='vis_conn_sgn',\n    edge_radius='vis_conn_val',\n    vis_nodal=vis_nodes_edge_selection.astype(int),\n    vis_conn_adjacency=cov,\n    vis_internal_conn_adjacency=cov,\n    views=('dorsal', 'left', 'posterior'),\n    output_dir='/tmp',\n)\n```\n\nHere is another, more involved example, this time demonstrating how to use ``hyve`` to create a static SVG figure:\n\n```python\nimport templateflow.api as tflow\nfrom hyve.elements import TextBuilder\nfrom hyve_examples import get_null400_cifti\nfrom hyve.flows import plotdef\nfrom hyve.transforms import (\n    surf_from_archive,\n    surf_scalars_from_nifti,\n    add_surface_overlay,\n    save_grid,\n    plot_to_image,\n)\n\n# Annotate the panels of the figure so that the figure builder knows\n# where to place different elements. Note that we'll need a layout with\n# 9 panels, so we'll be creating a 3x3 grid of images when we parameterise\n# the plot definition below.\nannotations = {\n    0: dict(\n        hemisphere='left',\n        view='lateral',\n    ),\n    1: dict(view='anterior'),\n    2: dict(\n        hemisphere='right',\n        view='lateral',\n    ),\n    3: dict(view='dorsal'),\n    4: dict(elements=['title', 'scalar_bar']),\n    5: dict(view='ventral'),\n    6: dict(\n        hemisphere='left',\n        view='medial',\n    ),\n    7: dict(view='posterior'),\n    8: dict(\n        hemisphere='right',\n        view='medial',\n    ),\n}\n\n# Define a plotting function\nplot_f = plotdef(\n    surf_from_archive(),\n    add_surface_overlay(\n        'GM Density',\n        surf_scalars_from_nifti(\n            'GM Density', template='fsaverage', plot=True\n        ),\n    ),\n    plot_to_image(),\n    save_grid(\n        n_cols=3, n_rows=3, padding=10,\n        canvas_size=(1800, 1500),\n        canvas_color=(0, 0, 0),\n        fname_spec='scalars-gmdensity_view-all_page-{page}',\n        scalar_bar_action='collect',\n        annotations=annotations,\n    ),\n)\n\n# Generate a plot\nplot_f(\n    template='fsaverage',\n    gm_density_nifti=tflow.get(\n        template='MNI152NLin2009cAsym',\n        suffix='probseg',\n        label='GM',\n        resolution=2\n    ),\n    gm_density_clim=(0.2, 0.9),\n    gm_density_below_color=None,\n    gm_density_scalar_bar_style={\n        'name': None,\n        'orientation': 'h',\n    },\n    surf_projection=('pial',),\n    # This won't be the recommended way to add a title in the future.\n    elements={\n        'title': (\n            TextBuilder(\n                content='GM density',\n                bounding_box_height=192,\n                font_size_multiplier=0.2,\n                font_color='#cccccc',\n                priority=-1,\n            ),\n        ),\n    },\n    load_mask=True,\n    hemisphere=['left', 'right', None],\n    views={\n        'left': ('medial', 'lateral'),\n        'right': ('medial', 'lateral'),\n        'both': ('dorsal', 'ventral', 'anterior', 'posterior'),\n    },\n    output_dir='/tmp',\n    window_size=(600, 500),\n)\n```\n\n## Feature roadmap\n\n### v1.0.0\n\nSeveral critical features are missing from the alpha version of ``hyve``. We will do our best to be responsive to issues that arise as a consequence of the inevitable breaking API changes that arise as this functionality is implemented. In particular, the following features are significant enough that the API cannot be considered stable until they are implemented:\n\n- [x] Disambiguation and filtering of graphical elements according to metadata. Currently, the layout system does not support matching metadata in any graphical elements other than snapshots. For instance, scalar bars cannot be routed according to grouping specifications. This can be implemented by first making snapshots a graphical raster element and then modifying the code to match metadata for any elements. This is a critical feature that is necessary for creating many publication-ready figures with multiple panels and plot elements: currently, most figures must be edited manually because there is no control over, for instance, what scalar bars are placed in the SVG.\n- [x] Uniform backend for all geometric primitives and topo-transforms. Currently, the way that different geometric primitives are handled is inconsistent--networks (correctly) have a ``ggplot``-like API that allows mapping different variables to different visual properties, while surfaces and volumes are still missing this functionality. Additionally, the handling and filtering of data by hemisphere should be lifted into a topo-transform, so that it can be applied to any geometric primitive. Finally, the naming of aesthetic mappings (e.g., ``radius``, ``rlim``, and ``rmap``; ``color``, ``clim``, and ``cmap``) should be made more principled. This is a critical feature that is necessary before we extend the library to support new geometric primitives.\n- [x] Improving reusability of plot protocols. Currently, plot protocols created by ``hyve.plotdef`` have many parameters fixed at the time of creation, which undermines their reusability. This should be changed by having the parameterisation of primitives spliced into protocols at the time of creation set default values to arguments, while allowing the user to override these defaults at the time of calling the protocol.\n- [ ] Reconcile and formalise the relationship between the argument mapper (of the core visualisation loop) and the overlay system. Currently the system cannot handle this situation reasonably, and often not at all. This issue arises only when both are used in conjunction with one another, which we haven't seen much need for yet--but for which the need certainly exists. The user should be provided a way of controlling the desired behaviour when, for instance, vector-valued data are passed to multiple overlays--is an \"outer\" (product) or \"inner\" (zip) broadcast desired?\n\n### Future releases\n\nAmong others, the following features are planned for future releases:\n\n- More 3D visual primitives, including contours, reconstructed regional surfaces, and voxel block volumes.\n- Support for grouping semantics in figure parameterisations, allowing users to specify that certain parameters should be applied to multiple elements at once according to shared metadata (e.g., same hemisphere), or that the same layout should be applied groupwise in a single figure (e.g., to visualise multiple parcellations or surface projections).\n- Joining the outputs from multiple calls to the core plotting automapper into a single figure.\n- Floating plot elements that are not anchored to a specific panel, and whose parameters can be defined in relation to a plot page, plot group, or plot panel. This feature could be used to add inset plots, colorbars, and legends to a figure.\n- More interactive ``pyvista`` widgets, for instance to allow users to slice volumes or to select a subset of nodes or edges to highlight in a plot.\n- Control over lighting, texture, material, etc. of 3D scenes and objects.\n- Transformations for adding panel and plot elements.\n- Postprocessing of snapshots (with the option to filter by metadata), e.g., background removal, cropping, and resizing.\n- Additional SVG plot elements, including text, drop shadows, and shapes.\n- Additional cameras, for instance close-up views of specific regions of interest.\n- Injection of vector plots generated by other libraries, such as ``matplotlib``, into ``hyve`` figures. Injection of raster and vector graphic files as elements in ``hyve`` figures.\n- Self-documenting parameterisation of plot definitions.\n\nIf there is another feature you would like to see in ``hyve``, please [open an issue](https://github.com/hypercoil/hyve/issues/new/choose) to let us know! We are also interested in hearing which of the above features would be most useful to you, so that we can prioritise our development efforts accordingly. Finally, if you would like to contribute to the development of ``hyve``, please open an issue or pull request on GitHub. We will add a more detailed guide for contributions in the near future.\n\n## Alternative options\n\nWhile ``hyve`` is designed to be modular and extensible, some users might prefer a library with a more stable and intuitive API, or one that uses a backend that is simpler to install. If you are looking for a more user-friendly alternative, you might consider the following more mature libraries:\n\n- [``netplotbrain``](https://github.com/wiheto/netplotbrain): A Python library that supports many of the same kinds of plots, but is more user-friendly and uses ``matplotlib`` as its visualisation backend.\n- [``surfplot``](https://github.com/danjgale/surfplot): A lightweight VTK-based package (using the ``brainspaces`` library) that provides a user-friendly interface and produces simple and high-quality figures out of the box.\n- [``pysurfer``](https://github.com/nipy/PySurfer): A Python library for visualising and manipulating surface-based neuroimaging data that is built on top of VTK (using the ``mayavi`` library) and provides a ``tksurfer``-like user experience.\n- [``brainnetviewer``](https://www.nitrc.org/projects/bnv/): A MATLAB-based package that provides a GUI for visualising brain networks and surface-based neuroimaging data. A top-quality library that is widely used in the community, but it is built on a proprietary platform and is not easily extensible.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhypercoil%2Fhyve","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhypercoil%2Fhyve","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhypercoil%2Fhyve/lists"}