{"id":20956526,"url":"https://github.com/bluebrain/libsonata","last_synced_at":"2025-03-04T04:07:29.601Z","repository":{"id":34778778,"uuid":"175239261","full_name":"BlueBrain/libsonata","owner":"BlueBrain","description":"A python and C++ interface to the SONATA format","archived":false,"fork":false,"pushed_at":"2024-11-26T16:23:46.000Z","size":1374,"stargazers_count":12,"open_issues_count":28,"forks_count":13,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-02-25T03:07:01.815Z","etag":null,"topics":["circuit","modelling","simulation","sonata"],"latest_commit_sha":null,"homepage":"https://libsonata.readthedocs.io/en/stable/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BlueBrain.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.txt","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-12T15:14:33.000Z","updated_at":"2024-11-13T14:37:01.000Z","dependencies_parsed_at":"2023-09-22T09:29:06.892Z","dependency_job_id":"ad60221b-f5f7-4170-9d40-6a8a86df5b54","html_url":"https://github.com/BlueBrain/libsonata","commit_stats":{"total_commits":247,"total_committers":25,"mean_commits":9.88,"dds":0.5546558704453441,"last_synced_commit":"35e905aaab87bddc1c602c8fa06e8b5dd7453ecc"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BlueBrain%2Flibsonata","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BlueBrain%2Flibsonata/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BlueBrain%2Flibsonata/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BlueBrain%2Flibsonata/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BlueBrain","download_url":"https://codeload.github.com/BlueBrain/libsonata/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241780511,"owners_count":20019061,"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":["circuit","modelling","simulation","sonata"],"created_at":"2024-11-19T01:26:31.695Z","updated_at":"2025-03-04T04:07:29.584Z","avatar_url":"https://github.com/BlueBrain.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"|banner|\n\n|license| |coverage| |docs|\n\nlibsonata\n=========\n\nC++ / Python reader for SONATA circuit files:\n`SONATA guide \u003chttps://github.com/AllenInstitute/sonata/blob/master/docs/SONATA_DEVELOPER_GUIDE.md\u003e`__\n\nInstallation\n------------\n\nInstalling from PyPI\n~~~~~~~~~~~~~~~~~~~~\n\n.. code-block:: shell\n\n   pip install libsonata\n\nInstalling as a Python package, directly from GitHub\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code-block:: shell\n\n   pip install git+https://github.com/BlueBrain/libsonata\n\nBuilding the C++ library\n~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code-block:: shell\n\n   git clone git@github.com:BlueBrain/libsonata.git --recursive\n   cd libsonata\n   mkdir build \u0026\u0026 cd build\n   cmake -DCMAKE_BUILD_TYPE=Release -DEXTLIB_FROM_SUBMODULES=ON ..\n   make -j\n\nSince `libsonata` uses backports for `std::optional` and `std::variant` which\nturn into their actual STL implementation once available, it's recommended to compile\n`libsonata` with the same C++ standard as the project linking to `libsonata`. This\nis done by passing `-DCMAKE_CXX_STANDARD={14,17}` to the `cmake` command above.\n\nUsage (Python)\n--------------\n\nNodes\n~~~~~\n\nNodeStorage\n+++++++++++\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e import libsonata\n\n   \u003e\u003e\u003e nodes = libsonata.NodeStorage('path/to/H5/file')\n\n   # list populations\n   \u003e\u003e\u003e nodes.population_names\n\n   # open population\n   \u003e\u003e\u003e population = nodes.open_population(\u003cname\u003e)\n\n\nNodePopulation\n++++++++++++++\n\n.. code-block:: pycon\n\n   # total number of nodes in the population\n   \u003e\u003e\u003e population.size\n\n   # attribute names\n   \u003e\u003e\u003e population.attribute_names\n\n   # get attribute value for single node, say 42\n   \u003e\u003e\u003e population.get_attribute('mtype', 42)\n\n   # ...or Selection of nodes (see below) =\u003e returns NumPy array with corresponding values\n   \u003e\u003e\u003e selection = libsonata.Selection(values=[1, 5, 9, 42])  # nodes 1, 5, 9, 42\n   \u003e\u003e\u003e mtypes = population.get_attribute('mtype', selection)\n   \u003e\u003e\u003e list(zip(selection.flatten(), mtypes))\n   [(1, u'mtype_of_1'), (5, u'mtype_of_5'), (9, u'mtype_of_9'), (42, u'mtype_of_42')]\n\n\nSelection\n+++++++++\n\nList of element IDs (either `node_id`, or `edge_id`) where adjacent IDs are grouped for the sake of efficient HDF5 file access.\nFor instance, `{1, 2, 3, 5}` sequence becomes `{[1, 4), [5, 6)}`.\n\n`Selection` can be instantiated from:\n - a sequence of scalar values (works for NumPy arrays as well)\n - a sequence of pairs (interpreted as ranges above, works for N x 2 NumPy arrays as well)\n\n`EdgePopulation` connectivity queries (see below) return ``Selection``\\ s as well.\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e selection = libsonata.Selection([1, 2, 3, 5])\n   \u003e\u003e\u003e selection.ranges\n   [(1, 4), (5, 6)]\n\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e selection = libsonata.Selection([(1, 4), (5, 6)])\n   \u003e\u003e\u003e selection.flatten()\n   [1, 2, 3, 5]\n   \u003e\u003e\u003e selection.flat_size\n   4\n   \u003e\u003e\u003e bool(selection)\n   True\n\n\nNode Sets\n+++++++++\n\nlibsonata can work with the Node Set concept, as described here: `SONATA guide: Node Sets File \u003chttps://github.com/AllenInstitute/sonata/blob/master/docs/SONATA_DEVELOPER_GUIDE.md#node-sets-file\u003e`__\nThis allows the definition of names for groups of cells, and a way to query them.\nlibsonata also allows for extended expressions, such as Regular expressions,and floating point tests, as described here: `SONATA extension: Node Sets \u003chttps://sonata-extension.readthedocs.io/en/latest/sonata_nodeset.html\u003e`__\n\n.. code-block:: pycon\n\n   # load a node set JSON file\n   \u003e\u003e\u003e node_sets = libsonata.NodeSets.from_file('node_sets.json')\n\n   # list node sets\n   \u003e\u003e\u003e node_sets.names\n   {'L6_UPC', 'Layer1', 'Layer2', 'Layer3', ....}\n\n   # get the selection of nodes that match in population\n   \u003e\u003e\u003e selection = node_sets.materialize('Layer1', population)\n\n   # node sets can also be loaded from a JSON string\n   \u003e\u003e\u003e node_sets_manual = libsonata.NodeSets(json.dumps({\"SLM_PPA_and_SP_PC\": {\"mtype\": [\"SLM_PPA\", \"SP_PC\"]}}))\n   \u003e\u003e\u003e node_sets_manual.names\n   {'SLM_PPA_and_SP_PC'}\n\n\nEdges\n~~~~~\n\nEdgeStorage\n+++++++++++\n\nPopulation handling for `EdgeStorage` is analogous to `NodeStorage`:\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e edges = libsonata.EdgeStorage('path/to/H5/file')\n\n   # list populations\n   \u003e\u003e\u003e edges.population_names\n\n   # open population\n   \u003e\u003e\u003e population = edges.open_population(\u003cname\u003e)\n\n\nEdgePopulation\n++++++++++++++\n\n.. code-block:: pycon\n\n   # total number of edges in the population\n   \u003e\u003e\u003e population.size\n\n   # attribute names\n   \u003e\u003e\u003e population.attribute_names\n\n   # get attribute value for single edge, say 123\n   \u003e\u003e\u003e population.get_attribute('delay', 123)\n\n   # ...or Selection of edges =\u003e returns NumPy array with corresponding values\n   \u003e\u003e\u003e selection = libsonata.Selection([1, 5, 9])\n   \u003e\u003e\u003e population.get_attribute('delay', selection) # returns delays for edges 1, 5, 9\n\n\n...with additional methods for querying connectivity, where the results are selections that can be applied like above\n\n.. code-block:: pycon\n\n   # get source / target node ID for the 42nd edge:\n   \u003e\u003e\u003e population.source_node(42)\n   \u003e\u003e\u003e population.target_node(42)\n\n   # query connectivity (result is Selection object)\n   \u003e\u003e\u003e selection_to_1 = population.afferent_edges(1)  # all edges with target node_id 1\n   \u003e\u003e\u003e population.target_nodes(selection_to_1)  # since selection only contains edges\n                                                # targeting node_id 1 the result will be a\n                                                # numpy array of all 1's\n   \u003e\u003e\u003e selection_from_2 = population.efferent_edges(2)  # all edges sourced from node_id 2\n   \u003e\u003e\u003e selection = population.connecting_edges(2, 1)  # this selection is all edges from\n                                                      # node_id 2 to node_id 1\n\n   # ...or their vectorized analogues\n   \u003e\u003e\u003e selection = population.afferent_edges([1, 2, 3])\n   \u003e\u003e\u003e selection = population.efferent_edges([1, 2, 3])\n   \u003e\u003e\u003e selection = population.connecting_edges([1, 2, 3], [4, 5, 6])\n\n\nReports\n~~~~~~~\n\nSpikeReader\n+++++++++++\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e import libsonata\n\n   \u003e\u003e\u003e spikes = libsonata.SpikeReader('path/to/H5/file')\n\n   # list populations\n   \u003e\u003e\u003e spikes.get_population_names()\n\n   # open population\n   \u003e\u003e\u003e population = spikes['\u003cname\u003e']\n\n\nSpikePopulation\n+++++++++++++++\n\n.. code-block:: pycon\n\n   # get all spikes [(node_id, timestep)]\n   \u003e\u003e\u003e population.get()\n   [(5, 0.1), (2, 0.2), (3, 0.3), (2, 0.7), (3, 1.3)]\n\n   # get all spikes betwen tstart and tstop\n   \u003e\u003e\u003e population.get(tstart=0.2, tstop=1.0)\n   [(2, 0.2), (3, 0.3), (2, 0.7)]\n\n   # get spikes attribute sorting (by_time, by_id, none)\n   \u003e\u003e\u003e population.sorting\n   'by_time'\n\n   Pandas can be used to create a dataframe and get a better representation of the data\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e import pandas\n\n   data = population.get()\n   df = pandas.DataFrame(data=data, columns=['ids', 'times']).set_index('times')\n   print(df)\n          ids\n   times\n   0.1      5\n   0.2      2\n   0.3      3\n   0.7      2\n   1.3      3\n\n\nSomaReportReader\n++++++++++++++++\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e somas = libsonata.SomaReportReader('path/to/H5/file')\n\n   # list populations\n   \u003e\u003e\u003e somas.get_population_names()\n\n   # open population\n   \u003e\u003e\u003e population_somas = somas['\u003cname\u003e']\n\n\nSomaReportPopulation\n++++++++++++++++++++\n\n.. code-block:: pycon\n\n   # get times (tstart, tstop, dt)\n   \u003e\u003e\u003e population_somas.times\n   (0.0, 1.0, 0.1)\n\n   # get unit attributes\n   \u003e\u003e\u003e population_somas.time_units\n   'ms'\n   \u003e\u003e\u003e population_somas.data_units\n   'mV'\n\n   # node_ids sorted?\n   \u003e\u003e\u003e population_somas.sorted\n   True\n\n   # get a list of all node ids in the selected population\n   \u003e\u003e\u003e population_somas.get_node_ids()\n   [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]\n\n   # get the DataFrame of the node_id values for the timesteps between tstart and tstop\n   \u003e\u003e\u003e data_frame = population_somas.get(node_ids=[13, 14], tstart=0.8, tstop=1.0)\n\n   # get the data values\n   \u003e\u003e\u003e data_frame.data\n   [[13.8, 14.8], [13.9, 14.9]]\n\n   # get the list of timesteps\n   \u003e\u003e\u003e data_frame.times\n   [0.8, 0.9]\n\n   # get the list of node ids\n   \u003e\u003e\u003e data_frame.ids\n   [13, 14]\n\n\nOnce again, pandas can be used to create a dataframe using the data, ids and times lists\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e import pandas\n\n   df = pandas.DataFrame(data_frame.data, columns=data_frame.ids, index=data_frame.times)\n   print(df)\n          13    14\n   0.8  13.8  14.8\n   0.9  13.9  14.9\n\n\nElementReportReader\n+++++++++++++++++++\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e elements = libsonata.ElementReportReader('path/to/H5/file')\n\n   # list populations\n   \u003e\u003e\u003e elements.get_population_names()\n\n   # open population\n   \u003e\u003e\u003e population_elements = elements['\u003cname\u003e']\n\n\nElementReportPopulation\n+++++++++++++++++++++++\n\n.. code-block:: pycon\n\n   # get times (tstart, tstop, dt)\n   \u003e\u003e\u003e population_elements.times\n   (0.0, 4.0, 0.2)\n\n   \u003e\u003e\u003e population_elements.get_node_ids()\n   [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]\n\n   # get the DataFrame of the node_id values for the timesteps between tstart and tstop\n   \u003e\u003e\u003e data_frame = population_elements.get(node_ids=[13, 14], tstart=0.8, tstop=1.0)\n\n   # get the data values (list of list of floats with data[time_index][element_index])\n   \u003e\u003e\u003e data_frame.data\n   [[46.0, 46.1, 46.2, 46.3, 46.4, 46.5, 46.6, 46.7, 46.8, 46.9], [56.0, 56.1, 56.2, 56.3, 56.4, 56.5, 56.6, 56.7, 56.8, 56.9]]\n\n   # get the list of timesteps\n   \u003e\u003e\u003e data_frame.times\n   [0.8, 1.0]\n\n   # get the list of (node id, element_id)\n   \u003e\u003e\u003e data_frame.ids\n   [(13, 30), (13, 30), (13, 31), (13, 31), (13, 32), (14, 32), (14, 33), (14, 33), (14, 34), (14, 34)]\n\n\nThe same way than with spikes and soma reports, pandas can be used to get a better representation of the data\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e import pandas\n\n   df = pandas.DataFrame(data_frame.data, columns=pandas.MultiIndex.from_tuples(data_frame.ids), index=data_frame.times)\n   print(df)\n          13                            14\n          30    30    31    31    32    32    33    33    34    34\n   0.8  46.0  46.1  46.2  46.3  46.4  46.5  46.6  46.7  46.8  46.9\n   1.0  56.0  56.1  56.2  56.3  56.4  56.5  56.6  56.7  56.8  56.9\n\nFor big datasets, using numpy arrays could greatly improve the performance\n\n.. code-block:: pycon\n\n   \u003e\u003e\u003e import numpy\n\n   np_data = numpy.asarray(data_frame.data)\n   np_ids = numpy.asarray(data_frame.ids).T\n   np_times = numpy.asarray(data_frame.times)\n\n   df = pandas.DataFrame(np_data, columns=pandas.MultiIndex.from_arrays(np_ids), index=np_times)\n\n\nAcknowledgements\n----------------\nThe development of this software was supported by funding to the Blue Brain Project, a research center of the École polytechnique fédérale de Lausanne (EPFL), from the Swiss government’s ETH Board of the Swiss Federal Institutes of Technology.\n\nThis research was supported by the EBRAINS research infrastructure, funded from the European Union’s Horizon 2020 Framework Programme for Research and Innovation under the Specific Grant Agreement No. 945539 (Human Brain Project SGA3).\nThis project/research has received funding from the European Union’s Horizon 2020 Framework Programme for Research and Innovation under the Specific Grant Agreement No. 785907 (Human Brain Project SGA2).\n\n\nLicense\n-------\n\nlibsonata is distributed under the terms of the GNU Lesser General Public License version 3,\nunless noted otherwise, for example, for external dependencies.\nRefer to `COPYING.LESSER` and `COPYING` files for details.\n\nCopyright (c) 2018-2022 Blue Brain Project/EPFL\n\nlibsonata is free software: you can redistribute it and/or modify\nit under the terms of the GNU Lesser General Public License version 3\nas published by the Free Software Foundation.\n\nlibsonata is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Lesser General Public License for more details.\n\nYou should have received a copy of the GNU Lesser General Public License\nalong with libsonata.  If not, see \u003chttps://www.gnu.org/licenses/\u003e.\n\n\n.. |license| image:: https://img.shields.io/pypi/l/libsonata\n                :target: https://github.com/BlueBrain/libsonata/blob/master/COPYING.LESSER\n\n.. |coverage| image:: https://coveralls.io/repos/github/BlueBrain/libsonata/badge.svg\n                 :target: https://coveralls.io/github/BlueBrain/libsonata\n\n.. |docs| image:: https://readthedocs.org/projects/libsonata/badge/?version=latest\n             :target: https://libsonata.readthedocs.io/\n             :alt: documentation status\n\n.. substitutions\n.. |banner| image:: docs/source/_images/libSonataLogo.jpg\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbluebrain%2Flibsonata","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbluebrain%2Flibsonata","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbluebrain%2Flibsonata/lists"}