An integrated <i>i</i> <i>n vitro</i> platform and biophysical modeling approach for studying synaptic transmission in isolated neuronal pairs.
The 13 matches · 1 of them tie a paragraph to a whole file, not to given lines: a weak match, whose lines are not tinted
- [1] § STAR★Methods › Method details › Data analysis: Neuronal pair identification and synaptic pair calculation ↔ Scripts_Shelf/waveform_analysis.py, lines 68–130 · score 0.86 · peak trough ratio, repolarization slope, recovery slope, waveform metrics, half width, amplitude
- [2] § STAR★Methods › Method details › Data analysis: Neuronal pair identification and synaptic pair calculation ↔ src/cmos_analyzer/spikeinterface_metrics.py, lines 17–140 · score 0.84 · peak trough ratio, repolarization slope, recovery slope, waveform metrics, Spikeinterface, amplitude
- [3] § STAR★Methods › Method details › Electrophysiology › Stimulation paradigm ↔ src/cmos_recorder/Recorder_Class.py, lines 261–355 · score 0.78 · pulse duration, stimulation pulses, stimulation parameters, spontaneous recording, biphasic, DIV
- [4] § STAR★Methods › Method details › Data analysis: Neuronal pair identification and synaptic pair calculation ↔ src/Calculator_Class.py, lines 426–494 · score 0.77 · bivariate transfer entropy, multivariate transfer entropy, IDTxl, preselection, prefiltered, maximized
- [5] § STAR★Methods › Method details › Data analysis: Neuronal pair identification and synaptic pair calculation ↔ IDtxl/idtxl/bivariate_te.py, lines 177–326 · score 0.75 · temporal search depth, maximum temporal search, bivariate transfer entropy, IDTxl, JIDT, surrogate
- [6] § STAR★Methods › Method details › Computational model › Membrane potential ↔ network.py, lines 28–124 · score 0.70 · membrane capacitance, membrane potential, axial, cm, passive, segment
- [7] § Results › Structural motifs enforce axonal directionality in pre- and postsynaptic neuronal pairs ↔ Paper_scripts/Filled_channels_plotter.ipynb, lines 15–72 · score 0.62 · neurite growth direction, en passant, backward, heart
- [8] § Results › Structural motifs enforce axonal directionality in pre- and postsynaptic neuronal pairs ↔ Paper_scripts/Filled_channels_plotter.ipynb, lines 15–72 · score 0.55 · neurite growth direction, en passant, backward, heart
- [9] § STAR★Methods › Method details › Data analysis: Prediction of firing probability with machine learning models ↔ src/Converter_Class.py, the whole file · a weak match · score 0.53 · extremum electrode, spike occurs, traces, window, trained
- [10] § Results › Simulation-based inference finds the biophysical parameter space from the microelectrode-array data of neuronal pairs ↔ parameter_distribution_map_vs_lowprob.py, lines 174–228 · score 0.52 · axon diameter, low probability, NMDA, AMPA, latency, MAP
- [11] § Results › Simulation-based inference finds the biophysical parameter space from the microelectrode-array data of neuronal pairs ↔ stimulation_parameter_distribution.py, lines 174–228 · score 0.52 · axon diameter, low probability, NMDA, AMPA, latency, post
- [12] § STAR★Methods › Quantification and statistical analysis ↔ IDtxl/idtxl/embedding_optimization_ais_Rudelt.py, lines 13–131 · score 0.52 · confidence interval, standard deviation, Python
- [13] § STAR★Methods › Method details › Model fitting › Summary features ↔ network.py, lines 989–1030 · score 0.51 · spike detections, presynaptic neuron, axon, delay
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Python · 1,999 lines · 80 KB · no license · 2 matches
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- """
- This is part of the LFPy package that was altered for the single_synapse project.
- Specifically, we have changed:
- - the draw_ran_pos method in the NetworkPopulation to Draw random locations for POP_SIZE cells uniformly distributed within a cylinder.
- - connect neurons using connect_AMPA_NMDA function instead of connect_synapse in the Network class. For each synapse, we create two Exp2Synapses,/
- one for AMPA and one for NMDA, and connect them to the target cell. The target cell is triggered by a spike detector on the source cell at a compartment that is
- the closest to the synapse location.
- """
- import numpy as np
- import os
- import scipy.stats as stats
- import h5py
- import neuron
- from neuron import units
- from LFPy.templatecell import TemplateCell
- import scipy.sparse as ss
- from warnings import warn, filterwarnings
- def flattenlist(lst):
- return [item for sublist in lst for item in sublist]
- ##########################################################################
- # NetworkCell class that has a create_synapse method that
- # creates a synapse on the target cell, and a create_spike_detector method that
- # allows for connecting to a synapse on a target cell. All other methods and
- # attributes are inherited from the standard LFPy.TemplateCell class
- ##########################################################################
- class NetworkCell(TemplateCell):
- """
- Similar to `LFPy.TemplateCell` with the addition of some attributes and
- methods allowing for spike communication between parallel RANKs.
- This class allow using NEURON templates with some limitations.
- This takes all the same parameters as the Cell class, but requires three
- more template related parameters
- Parameters
- ----------
- morphology: str
- path to morphology file
- templatefile: str
- File with cell template definition(s)
- templatename: str
- Cell template-name used for this cell object
- templateargs: str
- Parameters provided to template-definition
- v_init: float
- Initial membrane potential. Default to -65.
- Ra: float
- axial resistance. Defaults to 150.
- cm: float
- membrane capacitance. Defaults to 1.0
- passive: bool
- Passive mechanisms are initialized if True. Defaults to True
- passive_parameters: dict
- parameter dictionary with values for the passive membrane mechanism in
- NEURON ('pas'). The dictionary must contain keys 'g_pas' and 'e_pas',
- like the default: passive_parameters=dict(g_pas=0.001, e_pas=-70)
- extracellular: bool
- switch for NEURON's extracellular mechanism. Defaults to False
- dt: float
- Simulation time step. Defaults to 2**-4
- tstart: float
- initialization time for simulation <= 0 ms. Defaults to 0.
- tstop: float
- stop time for simulation > 0 ms. Defaults to 100.
- nsegs_method: 'lambda100' or 'lambda_f' or 'fixed_length' or None
- nseg rule, used by NEURON to determine number of segments.
- Defaults to 'lambda100'
- max_nsegs_length: float or None
- max segment length for method 'fixed_length'. Defaults to None
- lambda_f: int
- AC frequency for method 'lambda_f'. Defaults to 100
- d_lambda: float
- parameter for d_lambda rule. Defaults to 0.1
- delete_sections: bool
- delete pre-existing section-references. Defaults to True
- custom_code: list or None
- list of model-specific code files ([.py/.hoc]). Defaults to None
- custom_fun: list or None
- list of model-specific functions with args. Defaults to None
- custom_fun_args: list or None
- list of args passed to custom_fun functions. Defaults to None
- pt3d: bool
- use pt3d-info of the cell geometries switch. Defaults to False
- celsius: float or None
- Temperature in celsius. If nothing is specified here
- or in custom code it is 6.3 celcius
- verbose: bool
- verbose output switch. Defaults to False
- Examples
- --------
- >>> import LFPy
- >>> cellParameters = {
- >>> 'morphology': '<path to morphology.hoc>',
- >>> 'templatefile': '<path to template_file.hoc>',
- >>> 'templatename': 'templatename',
- >>> 'templateargs': None,
- >>> 'v_init': -65,
- >>> 'cm': 1.0,
- >>> 'Ra': 150,
- >>> 'passive': True,
- >>> 'passive_parameters': {'g_pas': 0.001, 'e_pas': -65.},
- >>> 'dt': 2**-3,
- >>> 'tstart': 0,
- >>> 'tstop': 50,
- >>> }
- >>> cell = LFPy.NetworkCell(**cellParameters)
- >>> cell.simulate()
- See also
- --------
- Cell
- TemplateCell
- """
- def __init__(self, **args):
- # suppress some warnings if section references belonging to other
- # NetworkCell instances are found
- filterwarnings(action='ignore',
- message="(?=.*(sections detected))",
- category=UserWarning)
- # instantiate parent class
- super().__init__(**args)
- # create list netconlist for spike detecting NetCon object(s)
- self._hoc_sd_netconlist = neuron.h.List()
- self._hoc_sd_pre_netconlist = neuron.h.List()
- # create list of recording device for action potentials
- self.spikes = []
- # create list of random number generators used with synapse model
- self.rng_list = []
- # create separate list for networked synapses
- self.netconsynapses = []
- # create recording device for membrane voltage
- self.somav = neuron.h.Vector()
- for sec in self.somalist:
- self.somav.record(sec(0.5)._ref_v)
- def __finitialize__(self):
- pass
- def create_synapse(self, cell, sec, x=0.5, syntype=neuron.h.ExpSyn,
- synparams=dict(tau=2., e=0.),
- assert_syn_values=False):
- """
- Create synapse object of type syntype on sec(x) of cell and
- append to list cell.netconsynapses
- TODO: Use LFPy.Synapse class if possible.
- Parameters
- ----------
- cell: object
- instantiation of class NetworkCell or similar
- sec: neuron.h.Section object,
- section reference on cell
- x: float in [0, 1],
- relative position along section
- syntype: hoc.HocObject
- NEURON synapse model reference, e.g., neuron.h.ExpSyn
- synparams: dict
- parameters for syntype, e.g., for neuron.h.ExpSyn we have:
- tau: float, synapse time constant
- e: float, synapse reversal potential
- assert_syn_values: bool
- if True, raise AssertionError if synapse attribute values do not
- match the values in the synparams dictionary
- Raises
- ------
- AssertionError
- """
- # create a synapse object on the target cell
- syn = syntype(x, sec=sec)
- if hasattr(syn, 'setRNG'):
- # Create the random number generator for the synapse
- rng = neuron.h.Random()
- # not sure if this is how it is supposed to be set up...
- rng.MCellRan4(
- np.random.randint(
- 0,
- 2**32 - 1),
- np.random.randint(
- 0,
- 2**32 - 1))
- rng.uniform(0, 1)
- # used for e.g., stochastic synapse mechanisms (cf. BBP
- # microcircuit portal files)
- syn.setRNG(rng)
- cell.rng_list.append(rng) # must store ref to rng object
- cell.netconsynapses.append(syntype(x, sec=sec))
- for key, value in synparams.items():
- setattr(cell.netconsynapses[-1], key, value)
- # check that synapses are parameterized correctly
- if assert_syn_values:
- try:
- np.testing.assert_almost_equal(
- getattr(cell.netconsynapses[-1], key), value)
- except AssertionError:
- raise AssertionError('{} = {} != {}'.format(
- key, getattr(cell.netconsynapses[-1], key), value))
- def create_spike_detector(self, target=None, threshold=-10.,
- weight=0.0, delay=0.0):
- """
- Create spike-detecting NetCon object attached to the cell's soma
- midpoint, but this could be extended to having multiple spike-detection
- sites. The NetCon object created is attached to the cell's
- `_hoc_sd_netconlist` attribute, and will be used by the Network class
- when creating connections between all presynaptic cells and
- postsynaptic cells on each local RANK.
- Parameters
- ----------
- target: None (default) or a NEURON point process
- threshold: float
- spike detection threshold
- weight: float
- connection weight (not used unless target is a point process)
- delay: float
- connection delay (not used unless target is a point process)
- """
- # create new NetCon objects for the connections. Activation times will
- # be triggered on the somatic voltage with a given threshold.
- for sec in self.somalist:
- # print("section", sec)
- self._hoc_sd_netconlist.append(neuron.h.NetCon(sec(0.5)._ref_v,
- target,
- sec=sec))
- self._hoc_sd_netconlist[-1].threshold = threshold
- self._hoc_sd_netconlist[-1].weight[0] = weight
- self._hoc_sd_netconlist[-1].delay = delay
- for sec in self.allseclist:
- if "soma" not in str(sec):
- # print("section2 ", (sec))
- # will need to change this to all sections using sec.nseg
- self._hoc_sd_pre_netconlist.append(neuron.h.NetCon(sec(0.5)._ref_v,
- target,
- sec=sec))
- self._hoc_sd_pre_netconlist[-1].threshold = threshold
- self._hoc_sd_pre_netconlist[-1].weight[0] = weight
- self._hoc_sd_pre_netconlist[-1].delay = delay
- class DummyCell(object):
- def __init__(self, totnsegs=0,
- x=None,
- y=None,
- z=None,
- d=None,
- area=None,
- length=None,
- somainds=None):
- """
- Dummy Cell object initialized with all attributes needed for LFP
- calculations using the LFPy.RecExtElectrode class and methods.
- This cell can be imagined as one "super" cell containing transmembrane
- currents generated by all NetworkCell segments on this RANK at once.
- Parameters
- ----------
- totnsegs: int
- total number of segments
- x, y, z: ndarray
- arrays of shape (totnsegs, 2) with (x,y,z) coordinates of start
- and end points of segments in units of (um)
- d: ndarray
- array of length totnsegs with segment diameters
- area: ndarray
- array of segment surface areas
- length: ndarray
- array of segment lengths
- """
- # set attributes
- self.totnsegs = totnsegs
- self.x = x if x is not None else np.array([])
- self.y = y if y is not None else np.array([])
- self.z = z if z is not None else np.array([])
- self.d = d if d is not None else np.array([])
- self.area = area if area is not None else np.array([])
- self.length = length if area is not None else np.array([])
- self.somainds = somainds if somainds is not None else np.array([])
- def get_idx(self, section="soma"):
- if section == "soma":
- return self.somainds
- else:
- raise ValueError('section argument must be "soma"')
- class NetworkPopulation(object):
- """
- NetworkPopulation class representing a group of Cell objects
- distributed across RANKs.
- Parameters
- ----------
- CWD: path or None
- Current working directory
- CELLPATH: path or None
- Relative path from CWD to source files for cell model
- (morphology, hoc routines etc.)
- first_gid: int
- The global identifier of the first cell created in this population
- instance. The first_gid in the first population created should be 0
- and cannot exist in previously created NetworkPopulation instances
- Cell: class
- class defining a Cell object, see class NetworkCell above
- POP_SIZE: int
- number of cells in population
- name: str
- population name reference
- cell_args: dict
- keys and values for Cell object
- pop_args: dict
- keys and values for Network.draw_rand_pos assigning cell positions
- rotation_arg: dict
- default cell rotations around x and y axis on the form
- { 'x': np.pi/2, 'y': 0 }. Can only have the keys 'x' and 'y'.
- Cells are randomly rotated around z-axis using the
- Cell.set_rotation() method.
- OUTPUTPATH: str
- path to output file destination
- """
- def __init__(self, CWD=None, CELLPATH=None, first_gid=0, Cell=NetworkCell,
- POP_SIZE=4, name='L5PC',
- cell_args=None, pop_args=None,
- rotation_args=None,
- OUTPUTPATH='example_parallel_network'):
- # set class attributes
- self.CWD = CWD
- self.CELLPATH = CELLPATH
- self.first_gid = first_gid
- self.Cell = Cell
- self.POP_SIZE = POP_SIZE
- self.name = name
- self.cell_args = cell_args if cell_args is not None else dict()
- self.pop_args = pop_args if pop_args is not None else dict()
- self.rotation_args = rotation_args if rotation_args is not None \
- else dict()
- self.OUTPUTPATH = OUTPUTPATH
- # set up ParallelContext
- self.pc = neuron.h.ParallelContext()
- self._SIZE = self.pc.nhost()
- self._RANK = self.pc.id()
- # create folder for output if it does not exist
- #if self._RANK == 0:
- # if not os.path.isdir(OUTPUTPATH):
- # os.mkdir(OUTPUTPATH)
- self.pc.barrier()
- # container of Vector objects used to record times of action potentials
- self._hoc_spike_vectors = []
- # set up population of cells on this RANK
- self.gids = [
- (i +
- first_gid) for i in range(POP_SIZE) if (
- i +
- first_gid) %
- self._SIZE == self._RANK]
- # we have to enter the cell's corresponding file directory to
- # create cell because how EPFL set their code up
- if CWD is not None:
- os.chdir(os.path.join(CWD, CELLPATH, self.name))
- self.cells = [Cell(**cell_args) for gid in self.gids]
- os.chdir(CWD)
- else:
- self.cells = [Cell(**cell_args) for gid in self.gids]
- # position each cell's soma in space
- self.soma_pos = self.draw_rand_pos(POP_SIZE=len(self.gids), **pop_args)
- for i, cell in enumerate(self.cells):
- cell.set_pos(**self.soma_pos[i])
- # assign a random rotation around the z-axis of each cell
- self.rotations = np.random.uniform(0, np.pi * 2, len(self.gids))
- assert 'z' not in self.rotation_args.keys()
- for i, cell in enumerate(self.cells):
- cell.set_rotation(z=self.rotations[i], **self.rotation_args)
- # assign gid to each cell
- for gid, cell in zip(self.gids, self.cells):
- cell.gid = gid
- # gather gids, soma positions and cell rotations to RANK 0, and write
- # as structured array.
- if self._RANK == 0:
- populationData = flattenlist(self.pc.py_allgather(
- zip(self.gids, self.soma_pos, self.rotations)))
- # create structured array for storing data
- dtype = [('gid', 'i8'), ('x', float), ('y', float), ('z', float),
- ('x_rot', float), ('y_rot', float), ('z_rot', float)]
- popDataArray = np.empty((len(populationData, )), dtype=dtype)
- for i, (gid, pos, z_rot) in enumerate(populationData):
- popDataArray[i]['gid'] = gid
- popDataArray[i]['x'] = pos['x']
- popDataArray[i]['y'] = pos['y']
- popDataArray[i]['z'] = pos['z']
- popDataArray[i]['x_rot'] = np.pi / 2
- popDataArray[i]['y_rot'] = 0.
- popDataArray[i]['z_rot'] = z_rot
- else:
- _ = self.pc.py_allgather(
- zip(self.gids, self.soma_pos, self.rotations))
- # sync
- self.pc.barrier()
- # def draw_rand_pos(self, POP_SIZE, radius, loc, scale, cap=None):
- # """
- # Draw some random location for POP_SIZE cells within radius radius,
- # at mean depth loc and standard deviation scale.
- # Returned argument is a list of dicts [{'x', 'y', 'z'},].
- # Parameters
- # ----------
- # POP_SIZE: int
- # Population size
- # radius: float
- # Radius of population.
- # loc: float
- # expected mean depth of somas of population.
- # scale: float
- # expected standard deviation of depth of somas of population.
- # cap: None, float or length to list of floats
- # if float, cap distribution between [loc-cap, loc+cap),
- # if list, cap distribution between [loc-cap[0], loc+cap[1]]
- # Returns
- # -------
- # soma_pos: list
- # List of dicts of len POP_SIZE
- # where dict have keys x, y, z specifying
- # xyz-coordinates of cell at list entry `i`.
- # """
- # x = np.empty(POP_SIZE)
- # y = np.empty(POP_SIZE)
- # z = np.empty(POP_SIZE)
- # for i in range(POP_SIZE):
- # x[i] = (np.random.rand() - 0.5) * radius * 2
- # y[i] = (np.random.rand() - 0.5) * radius * 2
- # while np.sqrt(x[i]**2 + y[i]**2) >= radius:
- # x[i] = (np.random.rand() - 0.5) * radius * 2
- # y[i] = (np.random.rand() - 0.5) * radius * 2
- # z = np.random.normal(loc=loc, scale=scale, size=POP_SIZE)
- # if cap is not None:
- # if type(cap) in [float, np.float32, np.float64]:
- # while not np.all((z >= loc - cap) & (z < loc + cap)):
- # inds = (z < loc - cap) ^ (z > loc + cap)
- # z[inds] = np.random.normal(loc=loc, scale=scale,
- # size=inds.sum())
- # elif isinstance(cap, list):
- # assert len(cap) == 2, \
- # 'cap = {} is not a length 2 list'.format(float)
- # while not np.all((z >= loc - cap[0]) & (z < loc + cap[1])):
- # inds = (z < loc - cap[0]) ^ (z > loc + cap[1])
- # z[inds] = np.random.normal(loc=loc, scale=scale,
- # size=inds.sum())
- # else:
- # raise Exception('cap = {} is not None'.format(float),
- # 'a float or length 2 list of floats')
- # soma_pos = []
- # for i in range(POP_SIZE):
- # soma_pos.append({'x': x[i], 'y': y[i], 'z': z[i]})
- # return soma_pos
- def draw_rand_pos(self, POP_SIZE, x0, y0, z0, d, h):
- """
- Draw random locations for POP_SIZE cells uniformly distributed within a cylinder.
- The cylinder is centered at (x0, y0, z0) with diameter d in the x-y plane
- and depth h in the z direction.
- Parameters
- ----------
- POP_SIZE : int
- Number of cells.
- x0 : float
- x-coordinate of the cylinder center.
- y0 : float
- y-coordinate of the cylinder center.
- z0 : float
- z-coordinate of the cylinder center.
- d : float
- Diameter of the cylinder in the x-y plane.
- h : float
- Depth of the cylinder in the z direction.
- Returns
- -------
- soma_pos : list of dict
- List of dictionaries, each with keys 'x', 'y', and 'z' specifying the coordinates.
- """
- x = np.empty(POP_SIZE)
- y = np.empty(POP_SIZE)
- z = np.empty(POP_SIZE)
- for i in range(POP_SIZE):
- # Generate x, y uniformly inside a disc of radius d/2
- while True:
- xi = (np.random.rand() - 0.5) * d + x0
- xi = 0
- zi = (np.random.rand() - 0.5) * d + z0
- if np.sqrt((xi - x0)**2 + (zi - z0)**2) <= d / 2:
- x[i] = xi
- z[i] = zi
- break
- else:
- continue
- # Generate z uniformly in the interval [z0 - h/2, z0 + h/2]
- y[i] = np.random.rand() * h + (y0 - h/2)
- soma_pos = []
- for i in range(POP_SIZE):
- soma_pos.append({'x': x[i], 'y': y[i], 'z': z[i]})
- return soma_pos
- class Network(object):
- """
- Network class, creating distributed populations of cells of
- type Cell and handling connections between cells in the respective
- populations.
- Parameters
- ----------
- dt: float
- Simulation timestep size
- tstart: float
- Start time of simulation
- tstop: float
- End time of simulation
- v_init: float
- Membrane potential set at first timestep across all cells
- celsius: float
- Global control of temperature, affect channel kinetics.
- It will also be forced when creating the different Cell objects, as
- LFPy.Cell and LFPy.TemplateCell also accept the same keyword
- argument.
- verbose: bool
- if True, print out misc. messages
- """
- def __init__(
- self,
- dt=0.1,
- tstart=0.,
- tstop=1000.,
- v_init=-65.,
- celsius=6.3,
- OUTPUTPATH='example_parallel_network',
- verbose=False):
- # set attributes
- self.dt = dt
- self.tstart = tstart
- self.tstop = tstop
- self.v_init = v_init
- self.celsius = celsius
- self.OUTPUTPATH = OUTPUTPATH
- self.verbose = verbose
- self.syn_data = []
- # we need NEURON's ParallelContext for communicating NetCon events
- self.pc = neuron.h.ParallelContext()
- self._SIZE = self.pc.nhost()
- self._RANK = self.pc.id()
- # create empty list for connections between cells (not to be confused
- # with each cell's list of netcons _hoc_netconlist)
- self._hoc_netconlist = neuron.h.List()
- # The different populations in the Network will be collected in
- # a dictionary of NetworkPopulation object, where the keys represent
- # population names. The names are also put in a list ordered according
- # to the order populations are created in (as some operations rely on
- # this particular order)
- self.populations = dict()
- self.population_names = []
- def create_population(self, CWD=None, CELLPATH=None, Cell=NetworkCell,
- POP_SIZE=4, name='L5PC',
- cell_args=None, pop_args=None,
- rotation_args=None):
- """
- Create and append a distributed POP_SIZE-sized population of cells of
- type Cell with the corresponding name. Cell-object references, gids on
- this RANK, population size POP_SIZE and names will be added to the
- lists Network.gids, Network.cells, Network.sizes and Network.names,
- respectively
- Parameters
- ----------
- CWD: path
- Current working directory
- CELLPATH: path
- Relative path from CWD to source files for cell model
- (morphology, hoc routines etc.)
- Cell: class
- class defining a Cell-like object, see class NetworkCell
- POP_SIZE: int
- number of cells in population
- name: str
- population name reference
- cell_args: dict
- keys and values for Cell object
- pop_args: dict
- keys and values for Network.draw_rand_pos assigning cell positions
- rotation_arg: dict
- default cell rotations around x and y axis on the form
- { 'x': np.pi/2, 'y': 0 }. Can only have the keys 'x' and 'y'.
- Cells are randomly rotated around z-axis using the
- Cell.set_rotation method.
- """
- assert name not in self.populations.keys(), \
- 'population name {} already taken'.format(name)
- # compute the first global id of this new population, based
- # on population sizes of existing populations
- first_gid = 0
- for p in self.populations.values():
- first_gid += p.POP_SIZE
- # create NetworkPopulation object
- population = NetworkPopulation(
- CWD=CWD,
- CELLPATH=CELLPATH,
- first_gid=first_gid,
- Cell=Cell,
- POP_SIZE=POP_SIZE,
- name=name,
- cell_args=cell_args,
- pop_args=pop_args,
- rotation_args=rotation_args,
- OUTPUTPATH=self.OUTPUTPATH)
- # associate gids of cells on this RANK such that NEURON can look up
- # at which RANK different cells are created when connecting the network
- for gid in population.gids:
- self.pc.set_gid2node(gid, self._RANK)
- # Prepare connection targets by iterating over local neurons in pop.
- for gid, cell in zip(population.gids, population.cells):
- # attach NetCon source (spike detektor) to each cell's soma with no
- # target to cell gid
- cell.create_spike_detector(None)
- # assosiate cell gid with the NetCon source
- self.pc.cell(gid, cell._hoc_sd_netconlist[-1])
- # record spike events
- population._hoc_spike_vectors.append(neuron.h.Vector())
- cell._hoc_sd_netconlist[-1].record(
- population._hoc_spike_vectors[-1])
- # add population object to dictionary of populations
- self.populations[name] = population
- # append population name to list (Network.populations.keys() not
- # unique)
- self.population_names.append(name)
- def get_connectivity_rand(self, pre='L5PC', post='L5PC', connprob=0.2):
- """
- Dummy function creating a (boolean) cell to cell connectivity matrix
- between pre and postsynaptic populations.
- Connections are drawn randomly between presynaptic cell gids in
- population 'pre' and postsynaptic cell gids in 'post' on this RANK with
- a fixed connection probability. self-connections are disabled if
- presynaptic and postsynaptic populations are the same.
- Parameters
- ----------
- pre: str
- presynaptic population name
- post: str
- postsynaptic population name
- connprob: float in [0, 1]
- connection probability, connections are drawn on random
- Returns
- -------
- ndarray, dtype bool
- n_pre x n_post array of connections between n_pre presynaptic
- neurons and n_post postsynaptic neurons on this RANK. Entries
- with True denotes a connection.
- """
- n_pre = self.populations[pre].POP_SIZE
- gids = np.array(self.populations[post].gids).astype(int)
- # first check if there are any postsyn cells on this RANK
- if gids.size > 0:
- # define incoming connections for cells on this RANK
- C = np.random.binomial(n=1, p=connprob,
- size=(n_pre, gids.size)
- ).astype(bool)
- if pre == post:
- # avoid self connections.
- gids_pre, gids_post = np.where(C)
- gids_pre += self.populations[pre].first_gid
- gids_post *= self._SIZE # assume round-robin dist. of gids
- gids_post += self.populations[post].gids[0]
- inds = gids_pre != gids_post
- gids_pre = gids_pre[inds]
- gids_pre -= self.populations[pre].first_gid
- gids_post = gids_post[inds]
- gids_post -= self.populations[post].gids[0]
- gids_post //= self._SIZE
- c = np.c_[gids_pre, gids_post]
- # create boolean matrix
- C = ss.csr_matrix((np.ones(gids_pre.shape[0], dtype=bool),
- (c[:, 0], c[:, 1])),
- shape=(n_pre, gids.size), dtype=bool)
- return C.toarray()
- else:
- return C
- else:
- return np.zeros((n_pre, 0), dtype=bool)
- def connect(self, pre, post, connectivity,
- syntype=neuron.h.ExpSyn,
- synparams=dict(tau=2., e=0.),
- weightfun=np.random.normal,
- weightargs=dict(loc=0.1, scale=0.01),
- minweight=0,
- delayfun=stats.truncnorm,
- delayargs=dict(a=0.3, b=np.inf, loc=2, scale=0.2),
- mindelay=None,
- multapsefun=stats.truncnorm,
- multapseargs=dict(a=(1 - 4) / 1.,
- b=(10 - 4) / 1,
- loc=4,
- scale=1),
- syn_pos_args=dict(section=['soma', 'axon'],
- fun=[stats.norm] * 2,
- funargs=[dict(loc=0, scale=100)] * 2,
- funweights=[0.5] * 2,
- z_min=-1E6, z_max=1E6,
- ),
- save_connections=False,
- ):
- """
- Connect presynaptic cells to postsynaptic cells. Connections are
- drawn from presynaptic cells to postsynaptic cells, hence connectivity
- array must only be specified for postsynaptic units existing on this
- RANK.
- Parameters
- ----------
- pre: str
- presynaptic population name
- post: str
- postsynaptic population name
- connectivity: ndarray / (scipy.sparse array)
- boolean connectivity matrix between pre and post.
- syntype: hoc.HocObject
- reference to NEURON synapse mechanism, e.g., ``neuron.h.ExpSyn``
- synparams: dict
- dictionary of parameters for synapse mechanism, keys 'e', 'tau'
- etc.
- weightfun: function
- function used to draw weights from a numpy.random distribution
- weightargs: dict
- parameters passed to weightfun
- minweight: float,
- minimum weight in units of nS
- delayfun: function
- function used to draw delays from a subclass of
- scipy.stats.rv_continuous or numpy.random distribution
- delayargs: dict
- parameters passed to ``delayfun``
- mindelay: float,
- minimum delay in multiples of dt. Ignored if ``delayfun`` is an
- inherited from ``scipy.stats.rv_continuous``
- multapsefun: function or None
- function reference, e.g., ``scipy.stats.rv_continuous`` used to
- draw a number of synapses for a cell-to-cell connection.
- If None, draw only one connection
- multapseargs: dict
- arguments passed to multapsefun
- syn_pos_args: dict
- arguments passed to inherited ``LFPy.Cell`` method
- ``NetworkCell.get_rand_idx_area_and_distribution_norm`` to find
- synapse locations.
- save_connections: bool
- if True (default False), save instantiated connections to HDF5 file
- ``Network.OUTPUTPATH/synapse_connections.h5`` as dataset
- ``<pre>:<post>`` using a structured ndarray with dtype
- ::
- [('gid_pre'), ('gid', 'i8'), ('weight', 'f8'), ('delay', 'f8'),
- ('sec', 'U64'), ('sec.x', 'f8'),
- ('x', 'f8'), ('y', 'f8'), ('z', 'f8')],
- where ``gid_pre`` is presynapic cell id,
- ``gid`` is postsynaptic cell id,
- ``weight`` connection weight, ``delay`` connection delay,
- ``sec`` section name, ``sec.x`` relative location on section,
- and ``x``, ``y``, ``z`` the corresponding
- midpoint coordinates of the target segment.
- Returns
- -------
- list
- Length 2 list with ndarrays [conncount, syncount] with numbers of
- instantiated connections and synapses.
- Raises
- ------
- DeprecationWarning
- if ``delayfun`` is not a subclass of ``scipy.stats.rv_continuous``
- """
- # check if delayfun is a scipy.stats.rv_continuous like function that
- # provides a function `rvs` for random variates.
- # Otherwise, raise some warnings
- if not hasattr(delayfun, 'rvs'):
- warn(f'argument delayfun={delayfun.__str__()} do not appear ' +
- 'scipy.stats.rv_continuous or scipy.stats.rv_discrete like ' +
- 'and will be deprecated in the future')
- else:
- if mindelay is not None:
- warn(f'mindelay={mindelay} not usable with ' +
- f'delayfun={delayfun.__str__()}')
- # set up connections from all cells in presynaptic to post across RANKs
- n0 = self.populations[pre].first_gid
- # gids of presynaptic neurons:
- gids_pre = np.arange(n0, n0 + self.populations[pre].POP_SIZE)
- # print(gids_pre)
- # count connections and synapses made on this RANK
- conncount = connectivity.astype(int).sum()
- syncount = 0
- # keep track of synapse positions for this connect
- # call on this rank such that these can be communicated and stored
- syn_idx_pos = []
- # iterate over gids on this RANK and create connections
- for i, (gid_post, cell) in enumerate(zip(self.populations[post].gids,
- self.populations[post].cells)
- ):
- # print("cell:" , cell)
- # do NOT iterate over all possible presynaptic neurons
- for gid_pre in gids_pre[connectivity[:, i]]:
- # print("gid pre", gid_pre,gids_pre[connectivity[:, i]] )
- # throw a warning if sender neuron is identical to receiving
- # neuron
- if gid_post == gid_pre:
- print(
- 'connecting cell w. gid {} to itself (RANK {})'.format(
- gid_post, self._RANK))
- # assess number of synapses
- #if multapsefun is None:
- nidx = 1
- """
- else:
- if hasattr(multapsefun, 'pdf'):
- # assume we're dealing with a scipy.stats.rv_continuous
- # like method. Then evaluate pdf at positive integer
- # values and feed as custom scipy.stats.rv_discrete
- # distribution
- d = multapsefun(**multapseargs)
- # number of multapses must be on interval [1, 100]
- xk = np.arange(1, 100)
- pk = d.pdf(xk)
- pk /= pk.sum()
- nidx = stats.rv_discrete(values=(xk, pk)).rvs()
- # this aint pretty:
- mssg = (
- 'multapsefun: '
- + multapsefun(**multapseargs).__str__()
- + f'w. multapseargs: {multapseargs} resulted '
- + f'in {nidx} synapses'
- )
- assert nidx >= 1, mssg
- elif hasattr(multapsefun, 'pmf'):
- # assume we're dealing with a scipy.stats.rv_discrete
- # like method that can be used to generate random
- # variates directly
- nidx = multapsefun(**multapseargs).rvs()
- mssg = (
- f'multapsefun: {multapsefun().__str__()} w. '
- + f'multapseargs: {multapseargs} resulted in '
- + f'{nidx} synapses'
- )
- assert nidx >= 1, mssg
- else:
- warn(f'multapsefun{multapsefun.__str__()} will be ' +
- 'deprecated. Use scipy.stats.rv_continuous or ' +
- 'scipy.stats.rv_discrete like methods instead')
- nidx = 0
- j = 0
- while nidx <= 0 and j < 1000:
- nidx = int(round(multapsefun(**multapseargs)))
- j += 1
- if j == 1000:
- raise Exception(
- 'change multapseargs as no positive '
- 'synapse # was found in 1000 trials')
- """
- # find synapse locations and corresponding section names
- idxs = cell.get_rand_idx_area_and_distribution_norm(
- nidx=nidx, **syn_pos_args)
- print(idxs)
- # axon_secs = [secname for secname in cell.allsecnames if 'axon' in secname]
- # last_axon_secname = axon_secs[-1]
- # idx = cell.get_idx(last_axon_secname)
- # idxs = [(idx[0], last_axon_secname, 1.0)]
- secs = cell.get_idx_name(idxs)
- # [57 'ball_and_stick_template[1].dend[1]' 0.5]
- # secs = [cell.get_idx_name(-1)]
- print("secs", secs)
- # draw weights
- weights = weightfun(size=nidx, **weightargs)
- # redraw weights less that minweight
- while np.any(weights < minweight):
- j = weights < minweight
- weights[j] = weightfun(size=j.sum(), **weightargs)
- # draw delays
- if hasattr(delayfun, 'rvs'):
- delays = delayfun(**delayargs).rvs(size=nidx)
- # check that all delays are > dt
- try:
- assert np.all(delays >= self.dt)
- except AssertionError as ae:
- raise ae(
- f'the delayfun parameter a={delayargs["a"]} '
- + f'resulted in delay less than dt={self.dt}'
- )
- else:
- delays = delayfun(size=nidx, **delayargs)
- # redraw delays shorter than mindelay
- while np.any(delays < mindelay):
- j = delays < mindelay
- delays[j] = delayfun(size=j.sum(), **delayargs)
- for i, ((idx, secname, secx), weight, delay) in enumerate(
- zip(secs, weights, delays)):
- cell.create_synapse(
- cell,
- # TODO: Find neater way of accessing
- # Section reference, this looks slow
- sec=list(
- cell.allseclist)[
- np.where(
- np.array(
- cell.allsecnames) == secname)[0][0]],
- x=secx,
- syntype=syntype,
- synparams=synparams)
- # connect up NetCon object
- # nc = self.pc.gid_connect(gid_pre, cell.netconsynapses[-1])
- # nc.weight[0] = weight
- # nc.delay = delays[i]
- # self._hoc_netconlist.append(nc)
- # Original code
- # nc = self.pc.gid_connect(gid_pre, cell.netconsynapses[-1])
- # Modified code (explicit presynaptic section spike detection):
- presyn_cell = self.populations[pre].cells[gid_pre - n0] # locate presynaptic cell
- #################
- # where in the presynaptic neuron a synapse is located
- #################
- chosen_sec = [sec for sec in presyn_cell.allseclist][1]#np.random.choice([sec for sec in presyn_cell.allseclist]) # pick random axon section
- # secpostx = 0.5
- secpostx = presyn_cell.get_closest_idx(z=syn_pos_args["z_min"])/presyn_cell.totnsegs
- # print(smt )
- presyn_nc = neuron.h.NetCon(chosen_sec(secpostx)._ref_v, None, sec=chosen_sec)
- presyn_nc.threshold = -10
- self.pc.cell(gid_pre, presyn_nc) # Register the section-level spike detector
- nc = self.pc.gid_connect(gid_pre, cell.netconsynapses[-1])
- nc.weight[0] = weight
- nc.delay = delays[i]
- self._hoc_netconlist.append(nc)
- # store also synapse indices allowing for computing LFPs
- # from syn.i
- cell.synidx.append(idx)
- # store gid and xyz-coordinate of synapse positions
- syn_idx_pos.append((gid_pre,
- cell.gid,
- weight,
- delays[i],
- secname,
- secx,
- chosen_sec,
- secpostx,
- cell.x[idx].mean(axis=-1),
- cell.y[idx].mean(axis=-1),
- cell.z[idx].mean(axis=-1)))
- syncount += nidx
- # display some connectivity stats
- conncount = self.pc.allreduce(conncount, 1)
- syncount = self.pc.allreduce(syncount, 1)
- if self._RANK == 0:
- print('Connected population {} to {}'.format(pre, post),
- 'by {} connections and {} synapses'.format(conncount,
- syncount))
- else:
- conncount = None
- syncount = None
- # gather and write syn_idx_pos data
- if save_connections:
- if self._RANK == 0:
- synData = flattenlist(self.pc.py_allgather(syn_idx_pos))
- # convert to structured array
- dtype = [('gid_pre', 'i8'),
- ('gid_post', 'i8'),
- ('weight', 'f8'),
- ('delay', 'f8'),
- ('sec_pre', 'S64'),
- ('sec_pre.x', 'f8'),
- ('sec_post', 'S64'),
- ('sec_post.x', 'f8'),
- ('x', 'f8'),
- ('y', 'f8'),
- ('z', 'f8')]
- synDataArray = np.empty((len(synData), ), dtype=dtype)
- for i, (gid_pre, gid, weight, delay, secname, secx,chosen_sec, secpostx, x, y, z
- ) in enumerate(synData):
- synDataArray[i]['gid_pre'] = gid_pre
- synDataArray[i]['gid_post'] = gid
- synDataArray[i]['weight'] = weight
- synDataArray[i]['delay'] = delay
- synDataArray[i]['sec_pre'] = secname
- synDataArray[i]['sec_pre.x'] = secx
- synDataArray[i]['sec_post'] = chosen_sec
- synDataArray[i]['sec_post.x'] = secpostx
- synDataArray[i]['x'] = x
- synDataArray[i]['y'] = y
- synDataArray[i]['z'] = z
- self.syn_data.append(synDataArray)
- # Dump to hdf5 file, append to file if entry exists
- '''
- with h5py.File(os.path.join(self.OUTPUTPATH,
- 'synapse_connections.h5'),
- 'a') as f:
- key = '{}:{}'.format(pre, post)
- if key in f.keys():
- del f[key]
- assert key not in f.keys()
- f[key] = synDataArray
- # save global connection data (synapse type/parameters)
- # equal for all synapses
- try:
- grp = f.create_group('synparams')
- except ValueError:
- grp = f['synparams']
- try:
- subgrp = grp.create_group(key)
- except ValueError:
- subgrp = grp[key]
- subgrp['mechanism'] = syntype.__str__().strip('()')
- for key, value in synparams.items():
- subgrp[key] = value
- '''
- else:
- _ = self.pc.py_allgather(syn_idx_pos)
- return self.pc.py_broadcast([conncount, syncount], 0)
- def connect_AMPA_NMDA( self, pre, post, connectivity,
- tau1_AMPA, tau2_AMPA,
- tau1_NMDA, tau2_NMDA,
- e_NMDA, e_AMPA,
- w_NMDA_mean, w_AMPA_mean,
- w_NMDA_std, w_AMPA_std,
- delay,
- syn_pos_args,
- syntype="StochasticExp2Syn",
- save_connections=False):
- """
- Connect presynaptic cells to postsynaptic cells. Connections are
- drawn from presynaptic cells to postsynaptic cells, hence connectivity
- array must only be specified for postsynaptic units existing on this
- RANK.
- Parameters
- ----------
- pre: str
- presynaptic population name
- post: str
- postsynaptic population name
- connectivity: ndarray / (scipy.sparse array)
- boolean connectivity matrix between pre and post.
- syntype: hoc.HocObject
- reference to NEURON synapse mechanism, e.g., ``neuron.h.ExpSyn``
- Returns
- -------
- list
- Length 2 list with ndarrays [conncount, syncount] with numbers of
- instantiated connections and synapses.
- Raises
- ------
- DeprecationWarning
- if ``delayfun`` is not a subclass of ``scipy.stats.rv_continuous``
- """
- # set up connections from all cells in presynaptic to post across RANKs
- n0 = self.populations[pre].first_gid
- # gids of presynaptic neurons:
- gids_pre = np.arange(n0, n0 + self.populations[pre].POP_SIZE)
- # count connections and synapses made on this RANK
- conncount = connectivity.astype(int).sum()
- syncount = 0
- # keep track of synapse positions for this connect
- # call on this rank such that these can be communicated and stored
- syn_idx_pos = []
- # iterate over gids on this RANK and create connections
- for i, (gid_post, cell) in enumerate(zip(self.populations[post].gids,
- self.populations[post].cells)
- ):
- # do NOT iterate over all possible presynaptic neurons
- for gid_pre in gids_pre[connectivity[:, i]]:
- # print("gid pre", gid_pre,gids_pre[connectivity[:, i]] )
- # throw a warning if sender neuron is identical to receiving
- # neuron
- if gid_post == gid_pre:
- print(
- 'connecting cell w. gid {} to itself (RANK {})'.format(
- gid_post, self._RANK))
- # assess number of synapses
- nidx = 2
- # find synapse locations and corresponding section names
- idxs = cell.get_rand_idx_area_and_distribution_norm(
- nidx=nidx, **syn_pos_args)
- secs = cell.get_idx_name(idxs)
- # draw weights
- weights = [0,0 ]
- # delays
- delays = [delay, delay]
- synparams = [dict(tau1 = tau1_AMPA,tau2 = tau2_AMPA, e= e_AMPA, weight_mean = w_AMPA_mean, weight_std = w_AMPA_std),
- dict(tau1 = tau1_NMDA,tau2 = tau2_NMDA, e= e_NMDA , weight_mean = w_NMDA_mean, weight_std = w_NMDA_std)]
- for i, ((idx, secname, secx), weight, delay) in enumerate(
- zip(secs, weights, delays)):
- cell.create_synapse(
- cell,
- # TODO: Find neater way of accessing
- # Section reference, this looks slow
- sec=list(
- cell.allseclist)[
- np.where(
- np.array(
- cell.allsecnames) == secname)[0][0]],
- x=secx,
- syntype=syntype,
- synparams=synparams[i])
- # Modified code (explicit presynaptic section spike detection):
- presyn_cell = self.populations[pre].cells[gid_pre - n0] # locate presynaptic cell
- #################
- # where in the presynaptic neuron a synapse is located
- #################
- chosen_sec = [sec for sec in presyn_cell.allseclist][1]
- secpostx = presyn_cell.get_closest_idx(z=syn_pos_args["z_min"])/presyn_cell.totnsegs
- presyn_nc = neuron.h.NetCon(chosen_sec(secpostx)._ref_v, None, sec=chosen_sec)
- presyn_nc.threshold = -10
- self.pc.cell(gid_pre, presyn_nc) # Register the section-level spike detector
- nc = self.pc.gid_connect(gid_pre, cell.netconsynapses[-1])
- nc.weight[0] = weight
- nc.delay = delays[i]
- self._hoc_netconlist.append(nc)
- # store also synapse indices allowing for computing LFPs
- cell.synidx.append(idx)
- # store gid and xyz-coordinate of synapse positions
- syn_idx_pos.append((gid_pre,
- cell.gid,
- weight,
- delays[i],
- secname,
- secx,
- chosen_sec,
- secpostx,
- cell.x[idx].mean(axis=-1),
- cell.y[idx].mean(axis=-1),
- cell.z[idx].mean(axis=-1)))
- syncount += nidx
- # display some connectivity stats
- conncount = self.pc.allreduce(conncount, 1)
- syncount = self.pc.allreduce(syncount, 1)
- if self._RANK == 0:
- print('Connected population {} to {}'.format(pre, post),
- 'by {} connections and {} synapses'.format(conncount,
- syncount))
- else:
- conncount = None
- syncount = None
- # gather and write syn_idx_pos data
- if save_connections:
- if self._RANK == 0:
- synData = flattenlist(self.pc.py_allgather(syn_idx_pos))
- # convert to structured array
- dtype = [('gid_pre', 'i8'),
- ('gid_post', 'i8'),
- ('weight', 'f8'),
- ('delay', 'f8'),
- ('sec_pre', 'S64'),
- ('sec_pre.x', 'f8'),
- ('sec_post', 'S64'),
- ('sec_post.x', 'f8'),
- ('x', 'f8'),
- ('y', 'f8'),
- ('z', 'f8')]
- synDataArray = np.empty((len(synData), ), dtype=dtype)
- for i, (gid_pre, gid, weight, delay, secname, secx,chosen_sec, secpostx, x, y, z
- ) in enumerate(synData):
- synDataArray[i]['gid_pre'] = gid_pre
- synDataArray[i]['gid_post'] = gid
- synDataArray[i]['weight'] = weight
- synDataArray[i]['delay'] = delay
- synDataArray[i]['sec_pre'] = secname
- synDataArray[i]['sec_pre.x'] = secx
- synDataArray[i]['sec_post'] = chosen_sec
- synDataArray[i]['sec_post.x'] = secpostx
- synDataArray[i]['x'] = x
- synDataArray[i]['y'] = y
- synDataArray[i]['z'] = z
- self.syn_data.append(synDataArray)
- else:
- _ = self.pc.py_allgather(syn_idx_pos)
- return self.pc.py_broadcast([conncount, syncount], 0)
- def enable_extracellular_stimulation(self, electrode, t_ext=None, n=1,
- model='inf'):
- """
- Enable extracellular stimulation with NEURON's `extracellular`
- mechanism. Extracellular potentials are computed from electrode
- currents using the point-source approximation.
- If ``model`` is ``'inf'`` (default), potentials are computed as
- (:math:`r_i` is the position of a segment :math:`i`,
- :math:`r_n` is the position of an electrode :math:`n`,
- :math:`\\sigma` is the conductivity of the medium):
- .. math::
- V_e(r_i) = \\sum_n \\frac{I_n}{4 \\pi \\sigma |r_i - r_n|}
- If ``model`` is ``'semi'``, the method of images is used:
- .. math::
- V_e(r_i) = \\sum_n \\frac{I_n}{2 \\pi \\sigma |r_i - r_n|}
- Parameters
- ----------
- electrode: RecExtElectrode
- Electrode object with stimulating currents
- t_ext: np.ndarray or list
- Time in ms corresponding to step changes in the provided currents.
- If None, currents are assumed to have
- the same time steps as the NEURON simulation.
- n: int
- Points per electrode for spatial averaging
- model: str
- ``'inf'`` or ``'semi'``. If ``'inf'`` the medium is assumed to be
- infinite and homogeneous. If ``'semi'``, the method of
- images is used.
- Returns
- -------
- v_ext: dict of np.ndarrays
- Computed extracellular potentials at cell mid points
- for each cell of the network's populations. Formatted as
- ``v_ext = {'pop1': np.ndarray[cell, cell_seg,t_ext]}``
- """
- v_ext = {}
- for popname in self.populations.keys():
- cells = self.populations[popname].cells
- v_ext[popname] = np.zeros(
- (len(cells), cells[0].totnsegs, len(t_ext)))
- for id_cell, cell in enumerate(cells):
- v_ext[popname][id_cell] = \
- cell.enable_extracellular_stimulation(
- electrode, t_ext, n, model)
- return v_ext
- def simulate(self, probes=None,
- rec_imem=False, rec_vmem=False,
- rec_ipas=False, rec_icap=False,
- rec_isyn=False, rec_vmemsyn=False, rec_istim=False,
- rec_pop_contributions=False,
- rec_variables=[], variable_dt=False, atol=0.001,
- to_memory=True, to_file=False,
- file_name='OUTPUT.h5',
- **kwargs):
- """
- This is the main function running the simulation of the network model.
- Parameters
- ----------
- probes: list of :obj:, optional
- None or list of LFPykit.RecExtElectrode like object instances that
- each have a public method `get_transformation_matrix` returning
- a matrix that linearly maps each segments' transmembrane
- current to corresponding measurement as
- .. math:: \\mathbf{P} = \\mathbf{M} \\mathbf{I}
- rec_imem: bool
- If true, segment membrane currents will be recorded
- If no electrode argument is given, it is necessary to
- set rec_imem=True in order to calculate LFP later on.
- Units of (nA).
- rec_vmem: bool
- record segment membrane voltages (mV)
- rec_ipas: bool
- record passive segment membrane currents (nA)
- rec_icap: bool
- record capacitive segment membrane currents (nA)
- rec_isyn: bool
- record synaptic currents of from Synapse class (nA)
- rec_vmemsyn: bool
- record membrane voltage of segments with Synapse (mV)
- rec_istim: bool
- record currents of StimIntraElectrode (nA)
- rec_pop_contributions: bool
- If True, compute and return single-population contributions to
- the extracellular potential during simulation time
- rec_variables: list of str
- variables to record, i.e arg=['cai', ]
- variable_dt: boolean
- use variable timestep in NEURON. Can not be combimed with `to_file`
- atol: float
- absolute tolerance used with NEURON variable timestep
- to_memory: bool
- Simulate to memory. Only valid with `probes=[<probe>, ...]`, which
- store measurements to -> <probe>.data
- to_file: bool
- only valid with `probes=[<probe>, ...]`, saves measurement in
- hdf5 file format.
- file_name: str
- If to_file is True, file which measurements will be
- written to. The file format is HDF5, default is "OUTPUT.h5", put
- in folder Network.OUTPUTPATH
- **kwargs: keyword argument dict values passed along to function
- `__run_simulation_with_probes()`, containing some or all of
- the boolean flags: `use_ipas`, `use_icap`, `use_isyn`
- (defaulting to `False`).
- Returns
- -------
- events
- Dictionary with keys `times` and `gids`, where values are
- ndarrays with detected spikes and global neuron identifiers
- Raises
- ------
- Exception
- if `CVode().use_fast_imem()` method not found
- AssertionError
- if rec_pop_contributions==True and probes==None
- """
- # set up integrator, use the CVode().fast_imem method by default
- # as it doesn't hurt sim speeds much if at all.
- cvode = neuron.h.CVode()
- try:
- cvode.use_fast_imem(1)
- except AttributeError:
- raise Exception('neuron.h.CVode().use_fast_imem() not found. '
- 'Please update NEURON to v.7.4 or newer')
- # test some of the inputs
- if probes is None:
- assert rec_pop_contributions is False, \
- 'rec_pop_contributions can not be True when probes is None'
- if not variable_dt:
- dt = self.dt
- else:
- dt = None
- for name in self.population_names:
- for cell in self.populations[name].cells:
- cell._set_soma_volt_recorder(dt)
- if rec_imem:
- cell._set_imem_recorders(dt)
- if rec_vmem:
- cell._set_voltage_recorders(dt)
- if rec_ipas:
- cell._set_ipas_recorders(dt)
- if rec_icap:
- cell._set_icap_recorders(dt)
- if len(rec_variables) > 0:
- cell._set_variable_recorders(rec_variables)
- # run fadvance until t >= tstop, and calculate LFP if asked for
- if probes is None and not rec_pop_contributions and not to_file:
- if not rec_imem:
- if self.verbose:
- print("rec_imem==False, not recording membrane currents!")
- self.__run_simulation(cvode, variable_dt, atol)
- else:
- self.__run_simulation_with_probes(
- cvode=cvode,
- probes=probes,
- variable_dt=variable_dt,
- atol=atol,
- to_memory=to_memory,
- to_file=to_file,
- file_name='tmp_output_RANK_{:03d}.h5',
- rec_pop_contributions=rec_pop_contributions,
- **kwargs)
- for name in self.population_names:
- for cell in self.populations[name].cells:
- # somatic trace
- cell.somav = np.array(cell.somav)
- if rec_imem:
- cell._calc_imem()
- if rec_ipas:
- cell._calc_ipas()
- if rec_icap:
- cell._calc_icap()
- if rec_vmem:
- cell._collect_vmem()
- if rec_isyn:
- cell._collect_isyn()
- if rec_vmemsyn:
- cell._collect_vsyn()
- if rec_istim:
- cell._collect_istim()
- if len(rec_variables) > 0:
- cell._collect_rec_variables(rec_variables)
- if hasattr(cell, '_hoc_netstimlist'):
- del cell._hoc_netstimlist
- # Collect spike trains across all RANKs to RANK 0
- for name in self.population_names:
- population = self.populations[name]
- population.spike_vectors = []
- for i in range(len(population._hoc_spike_vectors)):
- population.spike_vectors += \
- [population._hoc_spike_vectors[i].as_numpy()]
- # collect spike times to RANK 0
- if self._RANK == 0:
- times = []
- gids = []
- else:
- times = None
- gids = None
- for i, name in enumerate(self.population_names):
- times_send = [x for x in self.populations[name].spike_vectors]
- gids_send = [x for x in self.populations[name].gids]
- if self._RANK == 0:
- times.append([])
- gids.append([])
- times[i] += flattenlist(self.pc.py_gather(times_send))
- gids[i] += flattenlist(self.pc.py_gather(gids_send))
- assert len(times[-1]) == len(gids[-1])
- else:
- _ = self.pc.py_gather(times_send)
- _ = self.pc.py_gather(gids_send)
- # create final output file, summing up single RANK output from
- # temporary files
- if to_file and probes is not None:
- # op = MPI.SUM
- fname = os.path.join(
- self.OUTPUTPATH,
- 'tmp_output_RANK_{:03d}.h5'.format(
- self._RANK))
- f0 = h5py.File(fname, 'r')
- if self._RANK == 0:
- f1 = h5py.File(os.path.join(self.OUTPUTPATH, file_name), 'w')
- dtype = []
- for key, value in f0[list(f0.keys())[0]].items():
- dtype.append((str(key), float))
- for grp in f0.keys():
- if self._RANK == 0:
- # get shape from the first dataset
- # (they should all be equal):
- for value in f0[grp].values():
- shape = value.shape
- continue
- f1[grp] = np.zeros(shape, dtype=dtype)
- for key, value in f0[grp].items():
- recvbuf = neuron.h.Vector(
- value[()].astype(float).flatten())
- self.pc.allreduce(recvbuf, 1)
- if self._RANK == 0:
- f1[grp][key] = np.array(recvbuf).reshape(value.shape)
- else:
- recvbuf = None
- f0.close()
- if self._RANK == 0:
- f1.close()
- os.remove(fname)
- if probes is not None:
- if to_memory:
- # communicate and sum up measurements on each probe before
- # returing spike times and corresponding gids:
- for probe in probes:
- probe.data = ReduceStructArray(probe.data)
- return dict(times=times, gids=gids)
- def __create_network_dummycell(self):
- """
- set up parameters for a DummyCell object, allowing for computing
- the sum of all single-cell LFPs at each timestep, essentially
- creating one supercell with all segments of all cell objects
- present on this RANK.
- """
- # compute the total number of segments per population on this RANK
- nsegs = [[cell.totnsegs for cell in self.populations[name].cells]
- for name in self.population_names]
- for i, nseg in enumerate(nsegs):
- if nseg == []:
- nsegs[i] = [0]
- for i, y in enumerate(nsegs):
- nsegs[i] = np.sum(y)
- nsegs = np.array(nsegs, dtype=int)
- totnsegs = nsegs.sum()
- x = np.empty((0, 2))
- y = np.empty((0, 2))
- z = np.empty((0, 2))
- d = np.array([])
- area = np.array([])
- length = np.array([])
- somainds = np.array([], dtype=int)
- nseg = 0
- for name in self.population_names:
- for cell in self.populations[name].cells:
- x = np.r_[x, cell.x]
- y = np.r_[y, cell.y]
- z = np.r_[z, cell.z]
- d = np.r_[d, cell.d]
- area = np.r_[area, cell.area]
- length = np.r_[length, cell.length]
- somainds = np.r_[somainds, cell.get_idx("soma") + nseg]
- nseg += cell.totnsegs
- # return number of segments per population and DummyCell object
- return nsegs, DummyCell(totnsegs, x, y, z, d, area, length, somainds)
- def __run_simulation(self, cvode, variable_dt=False, atol=0.001):
- """
- Running the actual simulation in NEURON, simulations in NEURON
- are now interruptable.
- Parameters
- ----------
- cvode: neuron.h.CVode() object
- variable_dt: bool
- switch for variable-timestep method
- atol: float
- absolute tolerance with CVode for variable time-step method
- """
- # set maximum integration step, it is necessary for communication of
- # spikes across RANKs to occur.
- self.pc.set_maxstep(10)
- # time resolution
- neuron.h.dt = self.dt
- # needed for variable dt method
- if variable_dt:
- cvode.active(1)
- cvode.atol(atol)
- else:
- cvode.active(0)
- # initialize state
- neuron.h.finitialize(self.v_init * units.mV)
- # initialize current- and record
- if cvode.active():
- cvode.re_init()
- else:
- neuron.h.fcurrent()
- neuron.h.frecord_init()
- # Starting simulation at tstart
- neuron.h.t = self.tstart
- # only needed if LFPy.Synapse classes are used.
- for name in self.population_names:
- for cell in self.populations[name].cells:
- cell._load_spikes()
- # advance simulation until tstop
- neuron.h.continuerun(self.tstop * units.ms)
- def __run_simulation_with_probes(self, cvode,
- probes=None,
- variable_dt=False,
- atol=0.001,
- rtol=0.,
- to_memory=True,
- to_file=False,
- file_name=None,
- use_ipas=False, use_icap=False,
- use_isyn=False,
- rec_pop_contributions=False
- ):
- """
- Running the actual simulation in NEURON with list of probes.
- Each object in `probes` must have a public method
- `get_transformation_matrix` which returns a linear mapping of
- transmembrane currents to corresponding measurement.
- Parameters
- ----------
- cvode: neuron.h.CVode() object
- probes: list of :obj:, optional
- None or list of LFPykit.RecExtElectrode like object instances that
- each have a public method `get_transformation_matrix` returning
- a matrix that linearly maps each segments' transmembrane
- current to corresponding measurement as
- .. math:: \\mathbf{P} = \\mathbf{M} \\mathbf{I}
- variable_dt: bool
- switch for variable-timestep method
- atol: float
- absolute tolerance with CVode for variable time-step method
- rtol: float
- relative tolerance with CVode for variable time-step method
- to_memory: bool
- Boolean flag for computing extracellular potentials,
- default is True.
- If True, the corresponding <probe>.data attribute will be set.
- to_file: bool or None
- Boolean flag for computing extracellular potentials to file
- <OUTPUTPATH/file_name>, default is False. Raises an Exception if
- `to_memory` is True.
- file_name: formattable str
- If to_file is True, file which extracellular potentials will be
- written to. The file format is HDF5, default is
- "output_RANK_{:03d}.h5". The output is written per RANK, and the
- RANK # will be inserted into the corresponding file name.
- use_ipas: bool
- if True, compute the contribution to extracellular potentials
- across the passive leak channels embedded in the cells membranes
- summed over populations
- use_icap: bool
- if True, compute the contribution to extracellular potentials
- across the membrane capacitance embedded in the cells membranes
- summed over populations
- use_isyn: bool
- if True, compute the contribution to extracellular potentials
- across the excitatory and inhibitory synapses embedded in the cells
- membranes summed over populations
- rec_pop_contributions: bool
- if True, compute and return single-population contributions to the
- extracellular potential during each time step of the simulation
- Returns
- -------
- Raises
- ------
- Exception:
- - `if to_memory == to_file == True`
- - `if to_file == True and file_name is None`
- - `if to_file == variable_dt == True`
- - `if <probe>.cell is not None`
- """
- if to_memory and to_file:
- raise Exception('to_memory and to_file can not both be True')
- if to_file and file_name is None:
- raise Exception
- # create a dummycell object lumping together needed attributes
- # for calculation of extracellular potentials etc. The population_nsegs
- # array is used to slice indices such that single-population
- # contributions to the potential can be calculated.
- population_nsegs, network_dummycell = self.__create_network_dummycell()
- # set cell attribute on each probe, assuming that each probe was
- # instantiated with argument cell=None
- for probe in probes:
- if probe.cell is None:
- probe.cell = network_dummycell
- else:
- raise Exception('{}.cell!=None'.format(probe.__class__))
- # create list of transformation matrices; one for each probe
- transforms = []
- if probes is not None:
- for probe in probes:
- transforms.append(probe.get_transformation_matrix())
- # reset probe.cell to None, as it is no longer needed
- for probe in probes:
- probe.cell = None
- # set maximum integration step, it is necessary for communication of
- # spikes across RANKs to occur.
- # NOTE: Should this depend on the minimum delay in the network?
- self.pc.set_maxstep(10)
- # Initialize NEURON simulations of cell object
- neuron.h.dt = self.dt
- # needed for variable dt method
- if variable_dt:
- cvode.active(1)
- cvode.atol(atol)
- else:
- cvode.active(0)
- # initialize state
- neuron.h.finitialize(self.v_init * units.mV)
- # use fast calculation of transmembrane currents
- cvode.use_fast_imem(1)
- # initialize current- and record
- if cvode.active():
- cvode.re_init()
- else:
- neuron.h.fcurrent()
- neuron.h.frecord_init()
- # Starting simulation at tstart
- neuron.h.t = self.tstart
- # create list of cells across all populations to simplify loops
- cells = []
- for name in self.population_names:
- cells += self.populations[name].cells
- # load spike times from NetCon, only needed if LFPy.Synapse class
- # is used
- for cell in cells:
- cell._load_spikes()
- # define data type for structured arrays dependent on the boolean
- # arguments
- dtype = [('imem', float)]
- if use_ipas:
- dtype += [('ipas', float)]
- if use_icap:
- dtype += [('icap', float)]
- if use_isyn:
- dtype += [('isyn_e', float), ('isyn_i', float)]
- if rec_pop_contributions:
- dtype += list(zip(self.population_names,
- [float] * len(self.population_names)))
- # setup list of structured arrays for all extracellular potentials
- # at each contact from different source terms and subpopulations
- if to_memory:
- for probe, M in zip(probes, transforms):
- probe.data = np.zeros((M.shape[0],
- int(self.tstop / self.dt) + 1),
- dtype=dtype)
- # signals for each probe will be stored here during simulations
- if to_file:
- # ensure right ending:
- if file_name.split('.')[-1] != 'h5':
- file_name += '.h5'
- outputfile = h5py.File(
- os.path.join(
- self.OUTPUTPATH,
- file_name.format(
- self._RANK)),
- 'w')
- # define unique group names for each probe
- names = []
- for probe, M in zip(probes, transforms):
- name = probe.__class__.__name__
- i = 0
- while True:
- if name + '{}'.format(i) not in names:
- names.append(name + '{}'.format(i))
- break
- i += 1
- # create groups
- for i, (name, probe, M) in enumerate(zip(names, probes,
- transforms)):
- # can't do it this way until h5py issue #740
- # (https://github.com/h5py/h5py/issues/740) is fixed:
- # outputfile['{}'.format(name)] = np.zeros((M.shape[0],
- # int(network.tstop / network.dt) + 1), dtype=dtype)
- probe.data = outputfile.create_group('{}'.format(name))
- for key, val in dtype:
- probe.data[key] = np.zeros((M.shape[0],
- int(self.tstop / self.dt)
- + 1),
- dtype=val)
- # temporary vector to store membrane currents at each timestep:
- imem = np.zeros(network_dummycell.totnsegs, dtype=dtype)
- def get_imem(imem):
- '''helper function to gather currents across all cells
- on this RANK'''
- i = 0
- totnsegs = 0
- if use_isyn:
- imem['isyn_e'] = 0. # must reset these for every iteration
- imem['isyn_i'] = 0. # because we sum over synapses
- for cell in cells:
- for sec in cell.allseclist:
- for seg in sec:
- imem['imem'][i] = seg.i_membrane_
- if use_ipas:
- imem['ipas'][i] = seg.i_pas
- if use_icap:
- imem['icap'][i] = seg.i_cap
- i += 1
- if use_isyn:
- for idx, syn in zip(cell.synidx, cell.netconsynapses):
- if hasattr(syn, 'e') and syn.e > -50:
- imem['isyn_e'][idx + totnsegs] += syn.i
- else:
- imem['isyn_i'][idx + totnsegs] += syn.i
- totnsegs += cell.totnsegs
- return imem
- # run fadvance until time limit, and calculate LFPs for each timestep
- tstep = 0
- while neuron.h.t < self.tstop:
- if neuron.h.t >= 0:
- imem = get_imem(imem)
- for j, (probe, M) in enumerate(zip(probes, transforms)):
- probe.data['imem'][:, tstep] = M @ imem['imem']
- if use_ipas:
- probe.data['ipas'][:, tstep] = \
- M @ (imem['ipas'] * network_dummycell.area * 1E-2)
- if use_icap:
- probe.data['icap'][:, tstep] = \
- M @ (imem['icap'] * network_dummycell.area * 1E-2)
- if use_isyn:
- probe.data['isyn_e'][:, tstep] = M @ imem['isyn_e']
- probe.data['isyn_i'][:, tstep] = M @ imem['isyn_i']
- if rec_pop_contributions:
- for j, (probe, M) in enumerate(zip(probes, transforms)):
- k = 0 # counter
- for nsegs, pop_name in zip(population_nsegs,
- self.population_names):
- cellinds = np.arange(k, k + nsegs)
- probe.data[pop_name][:, tstep] = \
- M[:, cellinds] @ imem['imem'][cellinds, ]
- k += nsegs
- tstep += 1
- neuron.h.fadvance()
- if neuron.h.t % 1000. == 0.:
- if self._RANK == 0:
- print('t = {} ms'.format(neuron.h.t))
- try:
- # calculate LFP after final fadvance(), skipped if IndexError is
- # encountered
- imem = get_imem(imem)
- for j, (probe, M) in enumerate(zip(probes, transforms)):
- probe.data['imem'][:, tstep] = M @ imem['imem']
- if use_ipas:
- probe.data['ipas'][:, tstep] = \
- M @ (imem['ipas'] * network_dummycell.area * 1E-2)
- if use_icap:
- probe.data['icap'][:, tstep] = \
- M @ (imem['icap'] * network_dummycell.area * 1E-2)
- if use_isyn:
- probe.data['isyn_e'][:, tstep] = M @ imem['isyn_e']
- probe.data['isyn_i'][:, tstep] = M @ imem['isyn_i']
- if rec_pop_contributions:
- for j, (probe, M) in enumerate(zip(probes, transforms)):
- k = 0 # counter
- for nsegs, pop_name in zip(population_nsegs,
- self.population_names):
- cellinds = np.arange(k, k + nsegs)
- probe.data[pop_name][:, tstep] = \
- M[:, cellinds] @ imem['imem'][cellinds, ]
- k += nsegs
- except IndexError:
- pass
- if to_file:
- outputfile.close()
- def ReduceStructArray(sendbuf):
- """
- simplify MPI Reduce for structured ndarrays with floating point numbers
- Parameters
- ----------
- sendbuf: structured ndarray
- Array data to be reduced (default: summed)
- Returns
- -------
- recvbuf: structured ndarray or None
- Reduced array on RANK 0, None on all other RANKs
- """
- pc = neuron.h.ParallelContext()
- RANK = pc.id()
- if RANK == 0:
- shape = sendbuf.shape
- dtype_names = sendbuf.dtype.names
- else:
- shape = None
- dtype_names = None
- shape = pc.py_broadcast(shape, 0)
- dtype_names = pc.py_broadcast(dtype_names, 0)
- if RANK == 0:
- reduced = np.zeros(shape,
- dtype=list(zip(dtype_names,
- ['f8' for i in range(len(dtype_names)
- )])))
- else:
- reduced = None
- for name in dtype_names:
- recvbuf = neuron.h.Vector(sendbuf[name].flatten())
- pc.allreduce(recvbuf, 1)
- if RANK == 0:
- reduced[name] = np.array(recvbuf).reshape(shape)
- return reduced
network.py at commit bd3f89e, no license · at the source
Overview
Abstract
Studying synaptic transmission is facilitated in experimental systems that isolate individual neuronal connections. We developed an integrated platform combining polydimethylsiloxane (PDMS) microstructures with high-density microelectrode arrays to isolate, record, and manipulate neuronal pairs from human induced pluripotent stem cell (hiPSC)-derived neurons. The system maintained hundreds of parallel neuronal pairs for over 100 days, demonstrating functional synapses through pharmacological validation. We coupled this platform with a biophysical Hodgkin-Huxley model and simulation-based inference to extract mechanistic parameters from the electrophysiological data. As a proof-of-concept application, we analyzed shifts in model parameter distributions following a stimulation protocol. The biophysical model revealed α-amino-3-hydroxy-5-meth
Reproduced under the paper's license (CC BY), from the paper cited above.
Repositories
Its files are read in the Code ↔ Paper reader above, with 13 matches between paragraphs and lines of code.
altiki/TE_code
092f95c94506fcd434d509ce1d26c192b9ce1e49, 24 February 2026Availability: 1 check, the latest on 28 September 2026: the link answers
- 28 September 2026: the link answers
171 files
- IDtxl/
demos/ , Python, 17 linesdemo_active_information_ storage.py - IDtxl/
demos/ , Python, 26 linesdemo_bivariate_mi.py - IDtxl/
demos/ , Python, 70 linesdemo_bivariate_pid.py - IDtxl/
demos/ , Python, 26 linesdemo_bivariate_te.py - IDtxl/
demos/ , Python, 129 linesdemo_core_estimators.py - IDtxl/
demos/ , Python, 53 linesdemo_hd_estimator.py - IDtxl/
demos/ , Python, 26 linesdemo_multivariate_mi.py - IDtxl/
demos/ , Python, 374 linesdemo_multivariate_pid.py - IDtxl/
demos/ , Python, 26 linesdemo_multivariate_te.py - IDtxl/
demos/ , Python, 58 linesdemo_multivariate_te_mpi .py - IDtxl/
demos/ , Shell, 39 linesdemo_multivariate_te_mpi _slurm.sh - IDtxl/
demos/ , Python, 103 linesdemo_significant_subgrap h_mining.py - IDtxl/
demos/ , Python, 1 lineempty.py - IDtxl/
dev/ , Python, 109 linesfast_pid/ PID_analysis_cultures_si ngle_combination.py - IDtxl/
dev/ , Python, 330 linesfast_pid/ estimators_fast_pid.py - IDtxl/
dev/ , Python, 428 linesfast_pid/ estimators_fast_pid_ext_ rep.py - IDtxl/
dev/ , Python, 33 linesfast_pid/ test_and_empirical.py - IDtxl/
dev/ , Python, 31 linesfast_pid/ test_and_imposed_prob.py - IDtxl/
dev/ , Python, 76 linesfast_pid/ test_estimators_fast_pid .py - IDtxl/
dev/ , Python, 58 linesfast_pid/ test_parity_empirical.py - IDtxl/
dev/ , Python, 33 linesfast_pid/ test_single_input_copy_e mpirical.py - IDtxl/
dev/ , Python, 31 linesfast_pid/ test_single_input_copy_i mposed_prob.py - IDtxl/
dev/ , Python, 33 linesfast_pid/ test_xor_empirical.py - IDtxl/
dev/ , Python, 31 linesfast_pid/ test_xor_imposed_prob.py - IDtxl/
dev/ , Python, 62 linesimport_modwt/ import_modwt.py - IDtxl/
dev/ , C, 50 linesimport_modwt/ modwtj.c - IDtxl/
dev/ , MATLAB, 18 linesimport_modwt/ test_modwtj.m - IDtxl/
dev/ , Python, 1 linesearch_GPU/ __init__.py - IDtxl/
dev/ , CUDA, 279 linessearch_GPU/ deliverable1/ gpuKnnBF_kernel.cu - IDtxl/
dev/ , CUDA, 289 linessearch_GPU/ deliverable1/ gpuKnnLibrary.cu - IDtxl/
dev/ , CUDA, 227 linessearch_GPU/ deliverable1/ helperfunctions.cu - IDtxl/
dev/ , Python, 93 linessearch_GPU/ deliverable1/ python_to_c.py - IDtxl/
dev/ , Python, 52 linessearch_GPU/ deliverable1/ testKNN_call_multiGPU.py - IDtxl/
dev/ , Python, 115 linessearch_GPU/ deliverable1/ testRSAll_call_drop_dime nsions_cuda.py - IDtxl/
dev/ , Python, 48 linessearch_GPU/ deliverable1/ testRSAll_call_multiGPU. py - IDtxl/
dev/ , CUDA, 278 linessearch_GPU/ deliverable1_1/ gpuKnnBF_kernel.cu - IDtxl/
dev/ , CUDA, 292 linessearch_GPU/ deliverable1_1/ gpuKnnLibrary.cu - IDtxl/
dev/ , CUDA, 227 linessearch_GPU/ deliverable1_1/ helperfunctions.cu - IDtxl/
dev/ , Python, 93 linessearch_GPU/ deliverable1_1/ python_to_c.py - IDtxl/
dev/ , Python, 104 linessearch_GPU/ deliverable1_1/ test_cuda_search.py - IDtxl/
dev/ , Python, 179 linessearch_GPU/ deliverable2/ clKnnLibrary.py - IDtxl/
dev/ , Python, 50 linessearch_GPU/ deliverable2/ testKNN_call.py - IDtxl/
dev/ , Python, 78 linessearch_GPU/ deliverable2/ testKNN_callCompare.py - IDtxl/
dev/ , Python, 45 linessearch_GPU/ deliverable2/ testRSAll_call.py - IDtxl/
dev/ , Python, 65 linessearch_GPU/ deliverable2/ testRSAll_callCompare.py - IDtxl/
dev/ , Python, 128 linessearch_GPU/ deliverable2/ testRSAll_call_drop_dime nsions.py - IDtxl/
dev/ , Python, 80 linessearch_GPU/ deliverable2/ testRSAll_call_single_po ints.py - IDtxl/
dev/ , Python, 145 linessearch_GPU/ deliverable2/ testRSAll_call_single_po ints_memorder.py - IDtxl/
dev/ , Python, 181 linessearch_GPU/ deliverable2_1/ clKnnLibrary.py - IDtxl/
dev/ , Python, 130 linessearch_GPU/ deliverable2_1/ test_opencl_estimators.p y - IDtxl/
dev/ , CUDA, 279 linessearch_GPU/ gpuKnnBF_kernel.cu - IDtxl/
dev/ , Python, 109 linessearch_GPU/ neighbour_search_cuda.py - IDtxl/
dev/ , Python, 485 linessearch_GPU/ neighbour_search_opencl. py - IDtxl/
dev/ , Python, 295 linessearch_GPU/ neighbour_search_opencl_ old.py - IDtxl/
dev/ , Python, 204 linessearch_GPU/ testRSAll_call_single_po ints_new_interface.py - IDtxl/
dev/ , Python, 631 linessearch_GPU/ test_neighbour_search_cu da.py - IDtxl/
docs/ , Python, 176 linesconf.py - IDtxl/
docs/ , JavaScript, 326 lineshtml/ _static/ doctools.js - IDtxl/
docs/ , JavaScript, 12 lineshtml/ _static/ documentation_options.js - IDtxl/
docs/ , JavaScript, 7,572 lineshtml/ _static/ jquery-3.2.1.js - IDtxl/
docs/ , JavaScript, 7,429 lineshtml/ _static/ jquery-3.5.1.js - IDtxl/
docs/ , JavaScript, 2 lineshtml/ _static/ jquery.js - IDtxl/
docs/ , JavaScript, 297 lineshtml/ _static/ language_data.js - IDtxl/
docs/ , JavaScript, 529 lineshtml/ _static/ searchtools.js - IDtxl/
docs/ , JavaScript, 2,027 lineshtml/ _static/ underscore-1.12.0.js - IDtxl/
docs/ , JavaScript, 2,042 lineshtml/ _static/ underscore-1.13.1.js - IDtxl/
docs/ , JavaScript, 999 lineshtml/ _static/ underscore-1.3.1.js - IDtxl/
docs/ , JavaScript, 6 lineshtml/ _static/ underscore.js - IDtxl/
docs/ , JavaScript, 808 lineshtml/ _static/ websupport.js - IDtxl/
docs/ , JavaScript, 1 linehtml/ searchindex.js - IDtxl/
idtxl/ , Python, 29 lines__init__.py - IDtxl/
idtxl/ , Python, 667 linesactive_information_stora ge.py - IDtxl/
idtxl/ , Python, 323 linesbivariate_mi.py - IDtxl/
idtxl/ , Python, 313 linesbivariate_pid.py - IDtxl/
idtxl/ , Python, 326 lines, 1 matchbivariate_te.py - IDtxl/
idtxl/ , Python, 1,056 linesdata.py - IDtxl/
idtxl/ , Python, 737 linesdata_spiketime.py - IDtxl/
idtxl/ , Python, 1,237 lines, 1 matchembedding_optimization_a is_Rudelt.py - IDtxl/
idtxl/ , Python, 367 linesestimator.py - IDtxl/
idtxl/ , Python, 1,278 linesestimators_Rudelt.py - IDtxl/
idtxl/ , Python, 1,800 linesestimators_jidt.py - IDtxl/
idtxl/ , Python, 193 linesestimators_mpi.py - IDtxl/
idtxl/ , Python, 181 linesestimators_multivariate_ pid.py - IDtxl/
idtxl/ , Python, 815 linesestimators_opencl.py - IDtxl/
idtxl/ , Python, 638 linesestimators_pid.py - IDtxl/
idtxl/ , Python, 161 linesestimators_python.py - IDtxl/
idtxl/ , Python, 57 lineshde_fast_embedding_utils .py - IDtxl/
idtxl/ , Python, 12 lineshde_setup.py - IDtxl/
idtxl/ , Python, 392 lineshde_utils.py - IDtxl/
idtxl/ , Python, 40 linesidtxl_exceptions.py - IDtxl/
idtxl/ , Python, 264 linesidtxl_import.py - IDtxl/
idtxl/ , Python, 569 linesidtxl_io.py - IDtxl/
idtxl/ , Python, 354 linesidtxl_utils.py - IDtxl/
idtxl/ , Python, 1 lineknn/ __init__.py - IDtxl/
idtxl/ , Python, 93 linesknn/ knn_finder.py - IDtxl/
idtxl/ , Python, 25 linesknn/ knn_finder_factory.py - IDtxl/
idtxl/ , Python, 35 linesknn/ knn_finder_scipy.py - IDtxl/
idtxl/ , Python, 42 linesknn/ knn_finder_sklearn.py - IDtxl/
idtxl/ , Python, 19 linesknn/ tree_knn_finder.py - IDtxl/
idtxl/ , Python, 803 lineslattices.py - IDtxl/
idtxl/ , Python, 323 linesmultivariate_mi.py - IDtxl/
idtxl/ , Python, 320 linesmultivariate_pid.py - IDtxl/
idtxl/ , Python, 333 linesmultivariate_te.py - IDtxl/
idtxl/ , Python, 711 linesnetwork_analysis.py - IDtxl/
idtxl/ , Python, 1,041 linesnetwork_comparison.py - IDtxl/
idtxl/ , Python, 1,196 linesnetwork_inference.py - IDtxl/
idtxl/ , Python, 401 linespid_goettingen.py - IDtxl/
idtxl/ , Python, 1,652 linespostprocessing.py - IDtxl/
idtxl/ , Python, 1,202 linesresults.py - IDtxl/
idtxl/ , Python, 16 linessetup_hde_fast_embedding .py - IDtxl/
idtxl/ , Python, 8 linessingle_process_analysis. py - IDtxl/
idtxl/ , Python, 1,682 linesstats.py - IDtxl/
idtxl/ , Python, 611 linessynergy_tartu.py - IDtxl/
idtxl/ , Python, 327 linesvisualise_graph.py - IDtxl/
setup.py , Python, 31 lines - IDtxl/
source/ , Python, 280 linesconf.py - IDtxl/
test/ , Python, 236 linesgenerate_test_data.py - IDtxl/
test/ , Python, 82 linesperformancetest_lorenz_2 .py - IDtxl/
test/ , Shell, 33 linesperformancetest_lorenz_2 _mpi_slurm.sh - IDtxl/
test/ , Python, 66 linessystemtest_active_inform ation_storage.py - IDtxl/
test/ , Python, 95 linessystemtest_bivariate_pid .py - IDtxl/
test/ , Python, 611 linessystemtest_checkpointing _kraskov.py - IDtxl/
test/ , Python, 118 linessystemtest_estimators.py - IDtxl/
test/ , Python, 44 linessystemtest_lorenz_2.py - IDtxl/
test/ , Python, 44 linessystemtest_lorenz_2_open cl.py - IDtxl/
test/ , Python, 313 linessystemtest_multivariate_ te.py - IDtxl/
test/ , Python, 334 linessystemtest_multivariate_ te_discrete.py - IDtxl/
test/ , Python, 25 linessystemtest_mute.py - IDtxl/
test/ , Python, 132 linessystemtest_neighbour_sea rch_opencl.py - IDtxl/
test/ , Python, 150 linessystemtest_network_compa rison.py - IDtxl/
test/ , Python, 335 linessystemtest_optimization_ Rudelt.py - IDtxl/
test/ , Python, 36 linessystemtest_optimize_Rude lt_test_data.py - IDtxl/
test/ , Python, 140 linessystemtest_pid_sydney.py - IDtxl/
test/ , Python, 53 linessystemtest_visualise_gra ph.py - IDtxl/
test/ , Python, 316 linestest_active_information_ storage.py - IDtxl/
test/ , Python, 552 linestest_bivariate_mi.py - IDtxl/
test/ , Python, 197 linestest_bivariate_pid.py - IDtxl/
test/ , Python, 625 linestest_bivariate_te.py - IDtxl/
test/ , Python, 1,781 linestest_checkpointing.py - IDtxl/
test/ , Python, 1,950 linestest_checkpointing_mpi.p y - IDtxl/
test/ , Python, 449 linestest_data.py - IDtxl/
test/ , Python, 323 linestest_data_spiketimes.py - IDtxl/
test/ , Python, 89 linestest_estimator.py - IDtxl/
test/ , Python, 120 linestest_estimators_Rudelt.p y - IDtxl/
test/ , Python, 817 linestest_estimators_jidt.py - IDtxl/
test/ , Python, 258 linestest_estimators_multivar iate_pid.py - IDtxl/
test/ , Python, 591 linestest_estimators_opencl.p y - IDtxl/
test/ , Python, 295 linestest_estimators_pid.py - IDtxl/
test/ , Python, 184 linestest_estimators_python.p y - IDtxl/
test/ , Python, 22 linestest_fast_emb.py - IDtxl/
test/ , Python, 183 linestest_idtxl_import.py - IDtxl/
test/ , Python, 328 linestest_idtxl_io.py - IDtxl/
test/ , Python, 108 linestest_idtxl_utils.py - IDtxl/
test/ , Python, 204 linestest_mpi.py - IDtxl/
test/ , Python, 537 linestest_multivariate_mi.py - IDtxl/
test/ , Python, 308 linestest_multivariate_pid.py - IDtxl/
test/ , Python, 671 linestest_multivariate_te.py - IDtxl/
test/ , Python, 466 linestest_neighbour_search_op encl.py - IDtxl/
test/ , Python, 204 linestest_network_analysis.py - IDtxl/
test/ , Python, 524 linestest_network_comparison. py - IDtxl/
test/ , Python, 414 linestest_postprocessing.py - IDtxl/
test/ , Python, 469 linestest_results.py - IDtxl/
test/ , Python, 684 linestest_stats.py - IDtxl/
test/ , Python, 113 linestest_visualise_graph.py - run_info_metrics_Kate.py
, Python, 55 lines - run_info_metrics_Kate_si
ngle_files.py , Python, 53 lines - src/
Calculator_Class.py , Python, 988 lines, 1 match - src/
Calculator_Class_Kate.py , Python, 538 lines - src/
Converter_Class.py , Python, 123 lines, 1 match - src/
logger_functions.py , Python, 8 lines - test.ipynb, Jupyter, 1 line
altiki/cmos_toolbox_w_spike_sorter
620fb40d397d6cc20691de2e745493717b0d2f63, 11 March 2026Availability: 1 check, the latest on 28 September 2026: the link answers
- 28 September 2026: the link answers
58 files
- Paper_scripts/
Conduction_speeds_plotte , Jupyter, 128 linesr.ipynb - Paper_scripts/
Filled_channels_plotter. , Jupyter, 246 lines, 2 matchesipynb - Paper_scripts/
Firing_metrics_plotter.i , Jupyter, 143 linespynb - Paper_scripts/
Latency_plotter.ipynb , Jupyter, 833 lines - Paper_scripts/
Merging_files.ipynb , Jupyter, 204 lines - Paper_scripts/
Plasticity_firing_metric , Jupyter, 113 liness_plotter.ipynb - Paper_scripts/
Segmenting_processed_fil , Jupyter, 155 lineses.ipynb - Paper_scripts/
Synaptic_probabilities.i , Jupyter, 157 linespynb - Paper_scripts/
Waveform_files_merging_a , Jupyter, 211 linesnd_plotting.ipynb - Scripts_Shelf/
conduction_speeds.py , Python, 145 lines - Scripts_Shelf/
extract_spikes.py , Python, 63 lines - Scripts_Shelf/
filtering_by_latencies.p , Python, 68 linesy - Scripts_Shelf/
spike_sort.py , Python, 46 lines - Scripts_Shelf/
syn_probab_per_pair.py , Python, 74 lines - Scripts_Shelf/
waveform_analysis.py , Python, 130 lines, 1 match - Scripts_Shelf/
waveform_extraction.py , Python, 69 lines - src/
cmos_analyzer/ , Python, 443 linesAnalyzer_Class.py - src/
cmos_analyzer/ , Python, 432 linesAnalyzer_Class_Archive.p y - src/
cmos_analyzer/ , Python, 1 lineAnalyzer_Helper.py - src/
cmos_analyzer/ , Python, 1 line__init__.py - src/
cmos_analyzer/ , Python, 281 lines, 1 matchspikeinterface_metrics.p y - src/
cmos_analyzer/ , Python, 169 linestemplate_analysis.py - src/
cmos_analyzer/ , Python, 428 lineswaveform_metrics.py - src/
cmos_extractor/ , Python, 1,046 lines.ipynb_checkpoints/ Extractor_Class-checkpoi nt.py - src/
cmos_extractor/ , Python, 1,046 linesExtractor_Class.py - src/
cmos_extractor/ , Python, 909 linesExtractor_Class_GA.py - src/
cmos_extractor/ , Python, 133 linesExtractor_Helper.py - src/
cmos_extractor/ , Python, 1 line__init__.py - src/
cmos_plotter/ , Python, 2,870 linesConduction_speed_plotter .py - src/
cmos_plotter/ , Python, 439 linesFiring_metric_plotter.py - src/
cmos_plotter/ , Python, 185 linesHDBSCAN_clustering.py - src/
cmos_plotter/ , Python, 114 linesHierarchicalClustering.p y - src/
cmos_plotter/ , Python, 80 linesKmeans.py - src/
cmos_plotter/ , Python, 164 linesKmeans_adaptive_clusteri ng.py - src/
cmos_plotter/ , Python, 620 linesLatency_and_clustering.p y - src/
cmos_plotter/ , Python, 724 linesLatency_calculator.py - src/
cmos_plotter/ , Python, 1,203 linesPair_activity_plotter.py - src/
cmos_plotter/ , Python, 125 linesPlasticity_Helper_optimi zed.py - src/
cmos_plotter/ , Python, 789 linesPlotter_Class.py - src/
cmos_plotter/ , Python, 67 linesPlotter_Class_KV.py - src/
cmos_plotter/ , Python, 170 linesPlotter_Helper.py - src/
cmos_plotter/ , Python, 770 linesPlotter_Helper_KV.py - src/
cmos_plotter/ , Python, 539 linesWaveform_plotter.py - src/
cmos_plotter/ , Python, 1 line__init__.py - src/
cmos_preprocessor/ , Python, 160 linesPreprocessor_Class.py - src/
cmos_preprocessor/ , Python, 1 line__init__.py - src/
cmos_recorder/ , Python, 631 lines, 1 matchRecorder_Class.py - src/
cmos_recorder/ , Python, 23 linesRecorder_Helper.py - src/
cmos_recorder/ , Python, 1 line__init__.py - src/
utils/ , Python, 1 line__init__.py - src/
utils/ , Python, 14 linesconfig_functions.py - src/
utils/ , Python, 53 linesconversion_functions.py - src/
utils/ , Python, 432 lineselectrode_selection_func tions_Joel.py - src/
utils/ , Python, 8 lineslogger_functions.py - src/
utils/ , Python, 66 linesmetadata_functions.py - src/
utils/ , Python, 82 linespickle_splitting.py - src/
utils/ , Python, 302 linesui_functions.py - README.md, Text, 92 lines
gitlab.ethz.ch/vvasiliau/single_synapse
bd3f89e4312eee6fc94dad8318784d66d4866eef, 13 June 2025Availability: 1 check, the latest on 28 September 2026: the link answers
- 28 September 2026: the link answers
55 files
- HH_traub.mod, NEURON, 129 lines
- StochasticExp2Syn.mod, NEURON, 74 lines
- arm64/
DensityISyn.c , C, 425 lines - arm64/
HH_traub.c , C, 703 lines - arm64/
ISyn.c , C, 420 lines - arm64/
StochasticExp2Syn.c , C, 603 lines - arm64/
StochasticISyn.c , C, 422 lines - arm64/
TruncatedNoiseCurrent.c , C, 375 lines - arm64/
mod_func.cpp , C++, 25 lines - combine_files.py, Python, 38 lines
- generate_morphologies.py
, Python, 47 lines - morphologies/
ball_and_stick_diam_0.2. , NEURON, 37 lineshoc - morphologies/
ball_and_stick_diam_0.4. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_0.6. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_0.8. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_1.0. , NEURON, 35 lineshoc - morphologies/
ball_and_stick_diam_1.2. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_1.4. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_1.6. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_1.8. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_2.0. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_2.2. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_2.4. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_2.6. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_2.8. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_3.0. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_3.2. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_3.4. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_3.6. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_3.8. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_4.0. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_4.2. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_4.4. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_4.6. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_4.8. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_5.0. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_5.2. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_5.4. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_5.6. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_5.8. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_diam_6.0. , NEURON, 34 lineshoc - morphologies/
ball_and_stick_template. , NEURON, 12 lineshoc - network.py, Python, 1,999 lines, 2 matches
- parameter_distribution_m
ap_vs_lowprob.py , Python, 357 lines, 1 match - plot_prior.ipynb, Jupyter, 237 lines
- run_simulate_for_sbi.py, Python, 96 lines
- single_synapse_model.py, Python, 368 lines
- stimulation_parameter_di
stribution.py , Python, 336 lines, 1 match - test_processed_files.py, Python, 41 lines
- train_plot_posterior.ipy
nb , Jupyter, 372 lines - utilities.py, Python, 717 lines
- x86_64/
HH_traub.c , C, 703 lines - x86_64/
StochasticExp2Syn.c , C, 603 lines - x86_64/
mod_func.cpp , C++, 25 lines - README.md, Text, 30 lines
The paper's code and data availability statement is in the Data section.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 3 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 282 scripts, each with its path and the digest of its content;
- 13 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
No dataset and no data link were found in the paper.
Data and code availability
Data and code are publicly available at the following locations. • Data are available through the ETH Research collection: https://
Reproduced under the paper's license (CC BY), from the paper cited above.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 28 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 11 authors, 3 keywords, 2 funders, 114 references.
Cite
This paper
Amos, G., Vasiliauskaitė, V., Duru, J., Azevedo Saramago, M. L., Schmid, T., Suter, A., Torren, F. C., Küchler, J., Ruff, T., Vörös, J., & Vulić, K. (2026). An integrated &
BibTeX
@article{amos2026integra
author = {Amos, Giulia and Vasiliauskaitė, Vaiva and Duru, Jens and Azevedo Saramago, Maria Leonor and Schmid, Tim and Suter, Alexandre and Torren, Ferran Cid and Küchler, Joël and Ruff, Tobias and Vörös, János and Vulić, Katarina},
title = {{An integrated \&
journal = {iScience},
year = {2026},
month = apr,
volume = {29},
number = {5},
pages = {115488},
publisher = {Elsevier},
issn = {2589-0042},
doi = {10.1016/
url = {https://
pmid = {42016309},
pmcid = {PMC13092622}
}
RIS
TY - JOUR
AU - Amos, Giulia
AU - Vasiliauskaitė, Vaiva
AU - Duru, Jens
AU - Azevedo Saramago, Maria Leonor
AU - Schmid, Tim
AU - Suter, Alexandre
AU - Torren, Ferran Cid
AU - Küchler, Joël
AU - Ruff, Tobias
AU - Vörös, János
AU - Vulić, Katarina
TI - An integrated &
T2 - iScience
J2 - iScience
PY - 2026
DA - 2026/
VL - 29
IS - 5
SP - 115488
SN - 2589-0042
PB - Elsevier
DO - 10.1016/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1016/
"type": "article-journal",
"title": "An integrated &
"container-title": "iScience",
"author": [
{
"family": "Amos",
"given": "Giulia"
},
{
"family": "Vasiliauskaitė",
"given": "Vaiva"
},
{
"family": "Duru",
"given": "Jens"
},
{
"family": "Azevedo Saramago",
"given": "Maria Leonor"
},
{
"family": "Schmid",
"given": "Tim"
},
{
"family": "Suter",
"given": "Alexandre"
},
{
"family": "Torren",
"given": "Ferran Cid"
},
{
"family": "Küchler",
"given": "Joël"
},
{
"family": "Ruff",
"given": "Tobias"
},
{
"family": "Vörös",
"given": "János"
},
{
"family": "Vulić",
"given": "Katarina"
}
],
"container-title-short":
"volume": "29",
"issue": "5",
"page": "115488",
"DOI": "10.1016/
"PMID": "42016309",
"PMCID": "PMC13092622",
"ISSN": "2589-0042",
"publisher": "Elsevier",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
4,
1
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.1371/journal.pcbi.1014730 [code]
- A unified model of short- and long-term plasticity: Effects on network connectivity and information capacity.Journal: PLoS computational biologyIn common: Elephant, Neo, NetworkX, 6 other tools, 7 references
- [2] doi:10.1371/journal.pcbi.1014283 [code]
- Spatial richness of neural magnetic fields.Journal: PLoS computational biologyIn common: LFPy, Elephant, Neo, 7 other tools, 2 references
- [3] doi: [code]
- Naturalistic behavior and self-generated neural activity predictive of self-correctionJournal: bioRxiv : the preprint server for biologyIn common: Elephant, Neo, SpikeInterface, 10 other tools
- [4] doi:10.7554/elife.110588 [code]
- Opening the black box toward a modular approach to spike sorting.Journal: eLifeIn common: Neo, SpikeInterface, NetworkX, 9 other tools, 2 references
- [5] doi:10.1016/j.patter.2026.101590 [code]
- Density-based longitudinal neuron tracking in high-density electrophysiological recordings.Journal: Patterns (New York, N.Y.)In common: Neo, SpikeInterface, h5py, 9 other tools, 2 references
- [6] doi:10.1371/journal.pcbi.1014752 [code]
- Hierarchical feature binding in a spiking neural network model of the primate ventral visual pathway.Journal: PLoS computational biologyIn common: Elephant, Neo, OpenCV, 5 other tools, 3 references
- [7] doi:10.1038/s41593-026-02232-0 [code]
- Entorhinal cortex represents task-relevant remote locations independently of CA1.Journal: Nature neuroscienceIn common: SpikeInterface, NetworkX, OpenCV, 10 other tools
- [8] doi:10.1126/sciadv.aef0343 [code]
- Learning induces activation-mechanism-dep
endent neural plasticity in an intracortical microstimulation task. Journal: Science advancesIn common: Neo, SpikeInterface, Pillow, 7 other tools, 1 reference - [9] doi:10.1038/s41467-026-72057-9 [code]
- Sex-specific behavioral feedback modulates sensorimotor processing and drives flexible social behavior.Journal: Nature communicationsIn common: statannotations, OpenCV, h5py, 9 other tools
- [10] doi:10.1016/j.isci.2026.116825 [code]
- Social hierarchy shapes behavioral and transcriptional responses to chronic stress and ketamine in male mice.Journal: iScienceIn common: NetworkX, OpenCV, h5py, 9 other tools
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 3 repositories of the authors' code, each at its verified commit and with its license, 282 scripts, and 13 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:4eed48bfb070be99…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
