poc: add BrianExporter and BrianImporter skeleton#80
Draft
Sanchit2662 wants to merge 1 commit intobrian-team:masterfrom
Draft
poc: add BrianExporter and BrianImporter skeleton#80Sanchit2662 wants to merge 1 commit intobrian-team:masterfrom
Sanchit2662 wants to merge 1 commit intobrian-team:masterfrom
Conversation
Adds a minimal working proof-of-concept for network serialization to a portable .brian ZIP archive (model.json + arrays.npz). BrianExporter.serialize() wraps the existing collect_*() functions from baseexport/collector.py and fills three gaps that BaseExporter omits: - converts Quantity objects in collector output to JSON-safe dicts - captures state variable values after net.run() via var.get_value() - captures _synaptic_pre/_synaptic_post arrays for exact connectivity restoration (critical for probabilistic connections) BrianImporter.load() reconstructs NeuronGroups and Synapses from the archive, restoring connectivity via syn.connect(i=, j=) and state variables via var.set_value() after connect(). 11 tests in tests/test_poc_exporter.py cover archive structure, Quantity serialization, state capture, connectivity arrays, and NeuronGroup/Synapses round-trips. Signed-off-by: Sanchit2662 <sanchit2662@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
I'm applying for GSoC 2026 to work on serialization/deserialization for Brian2 models, results, and input data. This is a proof-of-concept showing I understand the existing brian2tools codebase and have a concrete approach to the problem.
This is the brian2tools half of the PoC. The other half lives in the brian2 repo and demonstrates portable state checkpointing using
_full_state()/_restore_from_full_state(): brian-team/brian2#1799What I built
brian2tools/baseexport/exporter.pyBrianExporter.serialize(net, 'file.brian')I built this by wrapping the existing
collect_*()functions fromcollector.pyusing the sameCOLLECTOR_MAPpattern I found inBaseExporter.network_run()(device.py:151). While reading through the code I identified three gaps that BaseExporter deliberately omits because it operates before the simulation runs:_json_safe(): converts Quantity objects in collector output to JSON-safe dicts. The concrete problem:collect_Equations()(collector.py:212) storeseqs.unitas a raw Quantity, which breaksjson.dumps(). I serialize it as{'__type__': 'quantity', 'value': ..., 'dim': [7-element SI exponent tuple]}usingDimension._dimsdirectly._collect_state(): captures actual state variable values viavar.get_value()after the run. Since BaseExporter intercepts code generation before the simulation, it never sees the values._collect_connectivity(): captures_synaptic_pre/_synaptic_postarrays. I noticed thatcollect_Synapses()(collector.py:565) only stores theconnect()arguments condition string,p,n— not the resulting index arrays. For probabilistic connections (p=0.1), re-running that condition on load gives different synapses every time. Storing the arrays fixes this.brian2tools/baseimport/importer.pyBrianImporter.load('file.brian') → (net, namespace)I mapped each field in the
collect_*()output back to the corresponding Brian2 constructor. For example,_reconstruct_neurongroup()pulls threshold/reset/refractory fromng_dict['events']['spike'](the structure fromcollect_Events()atcollector.py:225), and_reconstruct_synapses()resolves source/target usingcollect_SpikeSource()'s Subgroup dict form. Connectivity is restored viasyn.connect(i=arr, j=arr)— not by re-running the original condition. State variables are restored afterconnect()soDynamicArrayVariablesizes are correct first.11 tests in
tests/test_poc_exporter.pycovering archive structure, Quantity serialization, state capture, connectivity arrays, and full NeuronGroup/Synapses round-trips.What this isn't
net.run(), not viaset_device()Questions for reviewers
I'm using
var.owner.name != obj.nameto filter out variables owned by other objects (clocks etc.) — is there a more idiomatic way to do this check?collect_Synapses()atcollector.py:629drops non-scalar delays. Should I capture them the same way I capture_synaptic_pre/_synaptic_post, or is there a better hook?For Synapses reconstruction I use
str(obj.equations)as the model string. Is there a more reliable canonical form I should use instead?