Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] Added read/write method for network object #651

Merged
merged 30 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5d78733
Added initial read/write method for network object
raj1701 May 24, 2023
6116c4e
Added __eq__ method for cell, section and network classes
raj1701 May 25, 2023
dc10f43
Added support for attribute gid_ranges
raj1701 May 25, 2023
7b51058
Added support for pos_dict
raj1701 May 25, 2023
eae7982
Attempt to remove circle ci errors
raj1701 May 25, 2023
44f8809
Added support for cell response
raj1701 May 25, 2023
9ee149e
Added support for external drives
raj1701 May 30, 2023
5f2053b
Added test for net after simulation and resolved bug in cell response
raj1701 Jun 2, 2023
c666eb8
Refactored code
raj1701 Jun 5, 2023
4f35e6f
Added support for external biases and connectivity
raj1701 Jun 5, 2023
08b14f2
Added support for extracellular arrays, threshold and delay
raj1701 Jun 6, 2023
622bd3e
Resolve mechs issue - Attempt 1
raj1701 Jun 7, 2023
6434328
Added overwrite option and resolved params issue
raj1701 Jun 14, 2023
0c4f73a
Added read/write for simulated/unsimulated network
raj1701 Jun 15, 2023
2461b71
Resolved errors in connectivity
raj1701 Jun 15, 2023
36f0580
Added support for saving object type
raj1701 Jun 18, 2023
535b6cf
Added tests for different models
raj1701 Jun 18, 2023
af1bcc4
Added smoke tests and refactored test code
raj1701 Jun 21, 2023
33826c7
Refactored code
raj1701 Jun 21, 2023
f029f11
Documentation attempt 1 and removing load mechanisms from other place
raj1701 Jun 22, 2023
91b663a
Added authors, removed params, simplified __eq__ and shortened test s…
raj1701 Jun 28, 2023
35330e8
Documentation attempt 2 - Added support for fill doc and copy doc
raj1701 Jun 29, 2023
5deb3c2
Shifted mne code to externals and finished documentation
raj1701 Jul 6, 2023
501b81f
Resolved all conflicts and made sure tests are passing
raj1701 Aug 30, 2023
523fb8c
Replaced tmpdir with tmp_path
raj1701 Aug 30, 2023
4f90f7f
Revorked documentation
raj1701 Sep 10, 2023
96965c6
Minor fixes
raj1701 Sep 19, 2023
79ab971
Updated documentation
raj1701 Sep 19, 2023
cda152e
Added tests, refactored code and changed function signatures
raj1701 Sep 27, 2023
ea4097c
Refactored __eq__ functions
raj1701 Oct 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions hnn_core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
from .cell_response import CellResponse, read_spikes
from .cells_default import pyramidal, basket
from .parallel_backends import MPIBackend, JoblibBackend
from .io import read_network

__version__ = '0.4.dev0'
103 changes: 101 additions & 2 deletions hnn_core/cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ def _get_gaussian_connection(src_pos, target_pos, nc_dict,
return weight, delay


def node_to_str(node):
return node[0] + "," + str(node[1])


class _ArtificialCell:
"""The ArtificialCell class for initializing a NEURON feed source.

Expand Down Expand Up @@ -220,6 +224,52 @@ def __init__(self, L, diam, Ra, cm, end_pts=None):
def __repr__(self):
return f'L={self.L}, diam={self.diam}, cm={self.cm}, Ra={self.Ra}'

def __eq__(self, other):
ntolley marked this conversation as resolved.
Show resolved Hide resolved
if not isinstance(other, Section):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this is tested explicitly

return NotImplemented
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I think this is why the pytest.raises test didn't work. You're returning NotImplemented, but you actually need to do raise NotImplemented (check out how the other errors get raised)


# Check equality for mechs
for mech_name in self.mechs.keys():
self_mech = self.mechs[mech_name]
other_mech = other.mechs[mech_name]
for attr in self_mech.keys():
if self_mech[attr] != other_mech[attr]:
return False

# Check end_pts
for self_end_pt, other_end_pt in zip(self.end_pts, other.end_pts):
if self_end_pt != other_end_pt:
if np.testing.assert_almost_equal(self_end_pt,
raj1701 marked this conversation as resolved.
Show resolved Hide resolved
other_end_pt, 5):
print(self_end_pt)
print(other_end_pt)
return False

# Check all other attributes
if (self.L != other.L or
self.diam != other.diam or
self.Ra != other.Ra or
self.cm != other.cm or
self.nseg != other.nseg or
self.syns != other.syns):
return False

return True

def to_dict(self):
raj1701 marked this conversation as resolved.
Show resolved Hide resolved
section_data = dict()
section_data['L'] = self.L
section_data['diam'] = self.diam
section_data['cm'] = self.cm
section_data['Ra'] = self.Ra
section_data['end_pts'] = self.end_pts
section_data['nseg'] = self.nseg
# Need to solve the partial function problem
# in mechs
section_data['mechs'] = self.mechs
section_data['syns'] = self.syns
return section_data

@property
def L(self):
return self._L
Expand Down Expand Up @@ -355,6 +405,57 @@ def __repr__(self):
class_name = self.__class__.__name__
return f'<{class_name} | gid={self._gid}>'

def __eq__(self, other):
if not isinstance(other, Cell):
return NotImplemented
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs a test

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert (net == "net") == False.
Is this test fine?

if not (self.name == other.name and
self.pos == other.pos and
self.synapses == other.synapses and
self.cell_tree == other.cell_tree and
self.sect_loc == other.sect_loc and
self.dipole_pp == other.dipole_pp and
self.vsec == other.vsec and
self.isec == other.isec and
self.tonic_biases == other.tonic_biases):
return False

if not (self.sections.keys() == other.sections.keys()):
return False

for key in self.sections.keys():
if self.sections[key] != other.sections[key]:
return False

return True
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should add a test in test_cell.py for this ... simple way to test is:

cell2 = cell.copy()
assert cell2 == cell


def to_dict(self):
raj1701 marked this conversation as resolved.
Show resolved Hide resolved
cell_data = dict()
cell_data['name'] = self.name
cell_data['pos'] = self.pos
cell_data['sections'] = dict()
for key in self.sections:
cell_data['sections'][key] = self.sections[key].to_dict()
cell_data['synapses'] = self.synapses
# cell_data['cell_tree'] = self.cell_tree
if self.cell_tree is None:
cell_data['cell_tree'] = None
else:
cell_tree_dict = dict()
for parent, children in self.cell_tree.items():
key = node_to_str(parent)
value = list()
for child in children:
value.append(node_to_str(child))
cell_tree_dict[key] = value
cell_data['cell_tree'] = cell_tree_dict
cell_data['sect_loc'] = self.sect_loc
cell_data['gid'] = self.gid
cell_data['dipole_pp'] = self.dipole_pp
cell_data['vsec'] = self.vsec
cell_data['isec'] = self.isec
cell_data['tonic_biases'] = self.tonic_biases
return cell_data

@property
def gid(self):
return self._gid
Expand Down Expand Up @@ -444,8 +545,6 @@ def _set_biophysics(self, sections):
if isinstance(val, list):
seg_xs, seg_vals = val[0], val[1]
for seg, seg_x, seg_val in zip(sec, seg_xs, seg_vals):
# Checking equality till 5 decimal places
np.testing.assert_almost_equal(seg.x, seg_x, 5)
setattr(seg, attr, seg_val)
else:
setattr(sec, attr, val)
Expand Down
255 changes: 255 additions & 0 deletions hnn_core/docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
"""The documentation functions."""

docdict = dict()
# Define docdicts

docdict[
"net"
] = """
net : Instance of Network object
The Network object
"""

docdict[
"fname"
] = """
fname : str | Path object
Full path to the output file (.hdf5)
"""

docdict[
"overwrite"
] = """
overwrite : Boolean
True : Overwrite existing file
False : Throw error if file already exists
"""

docdict[
"save_unsimulated"
] = """
save_unsimulated : Boolean
True : Do not save the Network simulation output
False : Save complete Network as provided in input
"""

docdict[
"read_raw"
] = """
read_raw : Boolean
True : Read unsimulated network
False : Read simulated network
"""

docdict[
"section_description"
] = """
section description
-------------------
L : float
length of a section in microns.
diam : float
diameter of a section in microns.
cm : float
membrane capacitance in micro-Farads.
Ra : float
axial resistivity in ohm-cm.
end_pts : list of [x, y, z]
The start and stop points of the section.
mechs : dict
Mechanisms to insert in this section. The keys
are the names of the mechanisms and values
are the properties.
syns : list of str
The synaptic mechanisms to add in this section.
"""

docdict[
"cell_description"
] = f"""
cell_name : str
Name of the cell
pos : tuple
The (x, y, z) coordinates.
sections : dict of Section
Dictionary with keys as section name.
synapses : dict of dict
Keys are name of synaptic mechanism. Each synaptic mechanism
has keys for parameters of the mechanism, e.g., 'e', 'tau1',
'tau2'.
topology : list of list
The topology of cell sections. Each element is a list of
4 items in the format
[parent_sec, parent_loc, child_sec, child_loc] where
parent_sec and parent_loc are float between 0 and 1
specifying the location in the section to connect and
parent_sec and child_sec are names of the connecting
sections.
raj1701 marked this conversation as resolved.
Show resolved Hide resolved
sect_loc : dict of list
Can have keys 'proximal' or 'distal' each containing
gid : int
GID of the cell in a network (or None if not yet assigned)
dipole_pp : list of h.Dipole()
The Dipole objects (see dipole.mod).
vsec : dict
Recording of section specific voltage. Must be enabled
by running simulate_dipole(net, record_vsec=True) or
simulate_dipole(net, record_vsoma=True)
isec : dict
Contains recording of section specific currents indexed
by synapse type (keys can be soma_gabaa, soma_gabab etc.).
Must be enabled by running simulate_dipole(net, record_isec=True)
or simulate_dipole(net, record_isoma=True)
tonic_biases : list of h.IClamp
The current clamps inserted at each section of the cell
for tonic biasing inputs.

{docdict['section_description']}
"""

docdict[
"gid_range_description"
] = """
start : int
Start of the gid_range
stop : int
End of the gid_range
"""

docdict[
"external_drive_description"
] = """
name : str
Unique name for the drive
dynamics : dict
Parameters describing how the temporal dynamics of spike trains in the
drive. The keys are specific to the type of drive ('evoked', 'bursty',
etc.).
location : str
Target location of synapses.
cell_specific : bool
Whether each artifical drive cell has 1-to-1 (True, default) or
all-to-all (False) connection parameters.
weights_ampa : dict or None
Synaptic weights (in uS) of AMPA receptors on each targeted cell
type (dict keys).
weights_nmda : dict or None
Synaptic weights (in uS) of NMDA receptors on each targeted cell
type (dict keys).
probability : dict or float
Probability of connection between any src-target pair.
Use dict to create probability->cell mapping. If float, applies to
all target cell types
synaptic_delays : dict or float
Synaptic delay (in ms) at the column origin, dispersed laterally as
a function of the space_constant. If float, applies to all target
cell types.
event_seed : int
Optional initial seed for random number generator.
conn_seed : int
Optional initial seed for random number generator
n_drive_cells : int | 'n_cells'
The number of drive cells that each contribute an independently
sampled synaptic spike to the network according to the Gaussian
time distribution (mu, sigma).
events : list
Contains the spike times of exogeneous inputs.
"""

docdict[
"external_bias_description"
] = """
cell_type : str
The cell type whose cells will get the tonic input.
amplitude : float
The amplitude of the input.
t0 : float
The start time of tonic input (in ms).
tstop : float
The end time of tonic input (in ms).
"""

docdict[
"connection_description"
] = """
target_type : str
Cell type of target gids.
target_gids : list of int
Identifer for targets of source cells
num_targets : int
Number of unique target gids.
src_type : str
Cell type of source gids.
src_gids : list of int
Identifier for source cells.
num_srcs : int
Number of unique source gids.
gid_pairs : dict
dict indexed by src gids
loc : str
Target location of synapses.
receptor : str
Synaptic receptor of connection.
nc_dict : dict
Contains information about delay, weight, lamtha etc.
allow_autapses : bool
If True, allow connecting neuron to itself.
probability : float
Probability of connection between any src-target pair.
"""

docdict[
"extracellular_array_description"
] = """
positions : tuple | list of tuple
The (x, y, z) coordinates (in um) of the extracellular electrodes.
conductivity : float
Extracellular conductivity, in S/m
method : str
Approximation to use.
min_distance : float
To avoid numerical errors in calculating potentials, apply a minimum
distance limit between the electrode contacts and the active neuronal
membrane elements that act as sources of current.
times : array-like, shape (n_times,) | None
Optionally, provide precomputed voltage sampling times for electrodes
at `positions`.
voltages : array-like, shape (n_trials, n_electrodes, n_times) | None
Optionally, provide precomputed voltages for electrodes at
``positions``.
"""

docdict[
"network_file_content_description"
] = """
object_type : str
Type of object (Network) saved
N_pyr_x : int
N_pyr_y : int
threshold : float
Firing threshold of all cells.
celsius : float
cell_types : dict of Cell Object
key : name of cell type
value : Cell object
gid_ranges : dict of dict
key : cell name or drive name
value : dict
pos_dict : dict
key : cell type name
value : All co-ordintes of the cell types
cell_response : Instance of Cell Response Object
The Cell Response object
external_drives : dict of dict
key : external drive name
value : dict
external_biases : dict of dict
key : external bias name
value : dict
connectivity : list of dict
rec_arrays : dict of Extracellular Arrays
key : extracellular array name
value : Instance of Extracellular Array object
delay : float
Synaptic delay in ms.
"""
Loading