Welcome to Patch’s documentation!

https://badge.fury.io/gh/Helveg%2Fpatch.svg https://travis-ci.com/Helveg/patch.svg?branch=master https://codecov.io/gh/Helveg/patch/branch/master/graph/badge.svg https://img.shields.io/badge/code%20style-black-000000.svg Documentation Status

Usage

Inline replacement of NEURON by Patch

Be aware that the interface is currently incomplete, this means that most parts are still “just” NEURON. I’ve only patched holes I frequently encounter myself when using the h.Section, h.NetStim and h.NetCon functions. Feel free to open an issue or fork this project and open a pull request for missing or broken parts of the interface.

Philosophy

Python interfaces should be Pythonic, this wrapper offers just that:

  • Full Python objects: each wonky C-like NEURON object is wrapped in a full fledged Python object, easily handled and extended through inheritance.

  • Duck typed interface: take a look at the magic methods I use and any object you create with those methods present will work just fine with Patch.

  • Correct garbage collection, objects connected to eachother don’t dissapear: Objects that rely on eachother store a reference to eachother. As is the basis for any sane object oriented interface.

Basic usage

Use it like you would use NEURON. The wrapper doesn’t make any changes to the interface, it just patches up some of the more frequent and ridiculous gotchas.

Patch supplies a new HOC interpreter p, the PythonHocInterpreter which wraps the standard HOC interpreter h provided by NEURON. Any objects returned will either be PythonHocObject’s wrapping their corresponding NEURON object, or whatever NEURON returns.

When using just Patch the difference between NEURON and Patch objects is handled transparently, but if you wish to mix interpreters you can transform all Patch objects back to NEURON objects with obj.__neuron__() or the helper function patch.transform.

from patch import p, transform
import glia as g

section = p.Section()
point_process = g.insert(section, "AMPA")
stim = p.NetStim()
stim.start = 10
stim.number = 5
stim.interval = 10

# And here comes the magic! This explicitly defined connection
# isn't immediatly garbage collected! What a crazy world we live in.
# Has science gone too far?
p.NetCon(stim, point_process)

# It's fully compatible using __neuron__
from neuron import h
nrn_section = h.Section()
nrn_section.connect(transform(section))
nrn_section.connect(section.__neuron__())

Sections

Sections are cilindrical representations of pieces of a cell. They have a length and a diameter. Sections are the main building block of a simulation in NEURON.

You can use the .connect method to connect Sections together.

Sections can be subdivided into Segments by specifying nseg, the simulator calculates the voltage for each segment, thereby affecting the spatial resolution of the simulation. The position of a segment is represented by its normalized position along the axis of the Segment. This means that a Segment at x=0.5 is in the middle of the Section. By default every section consists of 1 segment and the potential will be calculated for 3 points: At the start (0) and end (1) of the section, and in the middle of every segment (0.5). For 2 segments the simulator would calculate at 0, 0.333…, 0.666… and 1.

Patch

from patch import p
s = p.Section()
s.L = 40
s.diam = 0.4
s.nseg = 11

s2 = p.Section()
s.connect(s2)

NEURON

from neuron import h
s = h.Section()
s.L = 40
s.diam = 0.4
s.nseg = 11

s2 = h.Section()
s.connect(s2)

Retrieving segments

Sections can be called with an x to retrieve the segment at that x. The segments of a Section can also be iterated over.

Patch

s.nseg = 5
seg05 = s(0.5)
print(seg05)
for seg in s:
    print(seg)

NEURON

s.nseg = 5
seg05 = s(0.5)
print(seg05)
for seg in s:
    print(seg)

Recording

You can tell Patch to record the membrane potential of your Section at one or multiple locations by calling the .record function and giving it an x. If x is omitted 0.5 is used.

In NEURON you’d have to create a Vector and keep track of it somewhere and find a way to link it back to the Section it recorded, in Patch a section automatically stores its recording vectors in section.recordings.

Patch

s.record(x=1.0)

NEURON

v = h.Vector()
v.record(s(1.0))
all_recorders.append(v)

Position in space

With Patch it’s very straightforward to define the 3D path of your Section through space. Call the .add_3d function with a 2D array containing the xyz data of your points. Optionally, you can pass another array of diameters.

Patch

s.add_3d([[0, 0, 0], [2, 2, 2]], diameters)

NEURON

s.push()
points = [[0, 0, 0], [2, 2, 2]]
for point, diameter in zip(points, diameters):
    h.pt3dadd(*point, diameter)
h.pop_section()

Magic methods

__neuron__

Get the object’s NEURON pointer

Whenever an object with this method present is sent to the NEURON HOC interpreter, the result of this method is passed instead. This allows Python methods to encapsulate NEURON pointers transparently

__netcon__

Get the object’s NetCon pointer

Whenever an object with this method present is used in a NetCon call, the result of this method is passed instead. The connection is stored on the original object. This allows to simplify the calls to NetCon, or to add more elegant default behavior. For example inserting a connection on a section might connect it to a random segment and you’d be able to use p.NetCon(section, synapse).

patch package

patch.core module

patch.core.transform(obj)[source]

Transforms an object to its NEURON representation, if the __neuron__ magic method is present.

patch.core.transform_netcon(obj)[source]
patch.core.transform_record(obj)[source]

patch.interpreter module

class patch.interpreter.PythonHocInterpreter[source]

Bases: object

NetCon(source, target, *args, **kwargs)[source]
PointProcess(factory, target, *args, **kwargs)[source]

Creates a point process from a h.MyMechanism factory.

Parameters
  • factory (function) – A point process method from the HocInterpreter.

  • target (objects.Segment) – The Segment this point process has to be inserted into.

VecStim(pattern=None, *args, **kwargs)[source]
continuerun(time_stop)[source]
finitialize(initial=None)[source]
load_extension(extension)[source]
run()[source]
property time
wrap(factory, name)[source]

patch.objects module

class patch.objects.NetCon(interpreter, ptr)[source]

Bases: patch.objects.PythonHocObject

class patch.objects.NetStim(*args, **kwargs)[source]

Bases: patch.objects.PythonHocObject, patch.objects.connectable

class patch.objects.PointProcess(*args, **kwargs)[source]

Bases: patch.objects.PythonHocObject, patch.objects.connectable

Wrapper for all point processes (membrane and synapse mechanisms). Use PythonHocInterpreter.PointProcess to construct these objects.

stimulate(pattern=None, **kwargs)[source]
class patch.objects.PythonHocObject(interpreter, ptr)[source]

Bases: object

class patch.objects.Section(*args, **kwargs)[source]

Bases: patch.objects.PythonHocObject, patch.objects.connectable

add_3d(points, diameters=None)[source]

Add a new 3D point to this section xyz data.

Parameters
  • points – A 2D array of xyz points.

  • diameters (float or array) – A scalar or array of diameters corresponding to the points. Default value is the section diameter.

connect(target, *args, **kwargs)[source]
connect_points(target, x=None)[source]
insert(*args, **kwargs)[source]
record(x=None)[source]
set_dimensions(length, diameter)[source]
set_segments(segments)[source]
wholetree()[source]
class patch.objects.Segment(*args, **kwargs)[source]

Bases: patch.objects.PythonHocObject, patch.objects.connectable

class patch.objects.VecStim(*args, **kwargs)[source]

Bases: patch.objects.PythonHocObject, patch.objects.connectable

property pattern
property vector
class patch.objects.Vector(interpreter, ptr)[source]

Bases: patch.objects.PythonHocObject

record(target, *args, **kwargs)[source]
class patch.objects.connectable[source]

Bases: object

Module contents

patch.connection(source, target, strict=True)[source]
patch.get_data_file(*dirs)[source]

Retrieve a file from the data directory that is installed together with the package.

Installation

Patch can be installed using:

pip install nrn-patch

Known unpatched holes

  • When creating point processes the returned object is unwrapped. This can be resolved using Glia, or by using this syntax:

# In neuron
process = h.MyMechanismName(my_section(0.5), *args, **kwargs)
# In patch
point_process = p.PointProcess(p.MyMechanismName, my_section(0.5), *args, **kwargs)

Indices and tables