/* $Id: synmap.hoc,v 2.4 2000/03/08 22:04:29 karchie Exp $
* synmap.hoc
* Distribute synapses on a neuron. Reads an array to determine which
* of the evenly distributed possible sites should actually have
* synapses. The map is more or less locally distance-preserving, in
* that two synapses close to each other in the array are probably
* close to each other on the neuron.
*
* Copyright (c) 1996,1998 Kevin A. Archie
* Send comments to: karchie@lnc.usc.edu
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
synmap_verbose = 0
/*
* synm_set_secname()
* Set the section name used by the default check mechanism to weed
* out sections that can't have synapses.
*/
strdef synm_secname_string
synm_secname_string = ""
proc synm_set_secname() {
// Assign the string.
synm_secname_string = $s1
// Reset the cached cell length so it will be recomputed.
synm_total_length = 0
}
/*
* synm_sections()
* Iterate over the set of sections on which synapses can be placed.
* Redefine this iterator to control synapse site selection.
*
* Note that "forsec" might not be the best way to do this; what we
* really want is a depth-first traversal of the sections. In
* practice, this gives more or less depth-first for j4. If we come
* across a cell for which it doesn't work, or if we need to extend
* this to work with multiple cells, we can dig out Hines's tree
* traversal scheme.
*/
iterator synm_sections() {
forsec synm_secname_string {
iterator_statement
}
}
/*
* synm_get_total_length()
* Determine the total length of all sections.
*
* BUGS: This function allows only a single length group.
*/
synm_total_length = 0 // Cached cell length
func synm_get_total_length() {
if (synm_total_length == 0) {
for synm_sections() {
synm_total_length = synm_total_length + L
}
}
return(synm_total_length)
}
/*
* synm_place_synapses(tot_nsites, fileobjref)
* Distribute synapses on the cell.
*
* tot_nsites is the total number of sites on the cell.
* fileobjref is the object reference to the input vector file.
*
* BUGS: This procedure relies on synm_get_total_length(), so it
* supports only one length group.
*/
proc synm_place_synapses() {local running_L, last_L, nsites, site_idx, \
L_per_site, next_loc, f, nsyns
// Reset the running L total. last_L is the running length at the
// 0.0 end of the current segment; running_L is the running length
// at the 1.0 end.
running_L = 0
last_L = 0
// How many synapse sites?
nsites = $1
if (nsites == 0) {
return
}
// How far apart are sites?
L_per_site = synm_get_total_length() / nsites
if (synmap_verbose) {
print nsites, "synapse sites ", L_per_site, "um apart."
}
// The first site (site 0) is half a site distance from the origin..
site_idx = 0
next_loc = L_per_site / 2
nsyns = 0
// Use synm_sections() to iterate over all suitable segments.
for synm_sections() {
// Include the length of the current segment in the running total.
running_L = running_L + L
// Is there a next site? Is it in the current section?
while (site_idx < nsites && running_L >= next_loc) {
// Yes. Read the frequency and relative strength for the
// synapse and place it in the next site if f > 0. The location
// argument is between 0 and 1 because:
// last_L <= next_loc <= running_L and last_L+L=running_L,
// so (next_loc - last_L) is in the range [0..L].
f = $o2.scanvar() * 100 // convert to Hz in the range [0, 100]
w = $o2.scanvar() // use weight factor to set initial value.
if (f * tstop / 1000 > 0.1) { // If > 0.1 spikes, make a synapse.
synm_insert_synapse((next_loc - last_L) / L, f, w, site_idx)
nsyns = nsyns + 1
}
// Get the next location.
next_loc = next_loc + L_per_site
site_idx = site_idx + 1
}
// We're done with this section.
last_L = running_L
}
if (synmap_verbose) {
print "Placed ", nsyns, "synapses."
}
}
/*
* synm_insert_synapse()
* Insert a single synapse at the given position on the current
* segment. This is a placeholder function; it must be redefined in
* another file to perform the actual insertion.
*/
proc synm_insert_synapse() {
print "Error: No mechanism for inserting synapses is available."
print " A procedure synm_insert_synapse() must be defined."
stop // We're probably in a modified section stack, so this command
// may aggravate a NEURON bug. But who cares -- it's an error
// anyway.
}