{load_file("autoThresholdMap.hoc")}
objref attDv[36]
attTotalCells = 0
/////////////////////////////////////////////////////////////////////
// Tiled version of spike detector
func hasSpike() { local idx, i, hyp // parameter: cell ID to check
idx = $1
//index of 1st threshold crossing
for i = (del+dur*2+0.5)/dt,(del+35)/dt {
if (attDv[idx].x[i] >= 0) {
return i
}
}
//excessive stim causes transient hyp after stimulus
hyp = 1
for i = (del+dur*2+1.0)/dt,(del+dur*2+4.0)/dt {
if (attDv[idx].x[i] >= attDv[idx].x[0]) {
hyp = 0
break
}
}
if (hyp) { return -1 }
return 0
}
// Tally the ID of cell(s) that spiked in the tile, a -ve return value indicates
// over-stim occured.
func countActivity() { local actvCells, overStimMark, c, latency
actvCells = 0
overStimMark = 1
for c = 0,attTotalCells-1 {
latency = hasSpike(c)
if (latency < 0) {
overStimMark = -1 // -ve multiplier to note overstim
} else if (latency > 0) {
actvCells += 2^c // actvCells uses 1-based cell ID
}
}
return overStimMark * actvCells
}
// Re-implement original procedure for cell tile
func findThresholdInRange() { local xPos, yPos, aMin, aMax, actvCells
xPos = $1
yPos = $2
aMin = $3
aMax = $4
setelec(xPos, yPos, stimZ)
while (aMax - aMin > rangingResolution) {
stimAmp = (aMax+aMin)/2 * -0.001
setstim(stimDel, stimDur, stimAmp)
run()
actvCells = countActivity()
// print "> ", stimAmp, " ", actvCells
if (actvCells < 0) {
return actvCells //excessive stim
} else if (actvCells > 0) {
aMax = (aMax+aMin)/2 //over-stim
} else {
aMin = (aMax+aMin)/2 //under-stim
}
}
if (actvCells == 0) {
// re-run if last did not spike
stimAmp = aMax * -0.001
setstim(stimDel, stimDur, stimAmp)
run()
actvCells = countActivity()
}
return actvCells
}
// Re-implement original procedure for cell tile
proc findThreshold() { local id, aMin, aMax, firstRun, actvCells
xPos = $1
yPos = $2
aMax = STIM_AMP_MAX
aMin = STIM_AMP_MIN
overStimLoop = 0
while (overStimLoop < 3) {
actvCells = findThresholdInRange(xPos, yPos, aMin, aMax)
if (actvCells >= 0) {
break
}
aMax = aMax / 2
overStimLoop += 1
// print "> overstim ", actvCells
}
printf("%d %d %.5f %d\n", $1, $2, stimAmp, actvCells)
if (pc.nhost == 1) {
aFile.printf("%d %d %.5f %d\n", $1, $2, stimAmp, actvCells)
aFile.flush()
} else {
id = hoc_ac_
pc.post(id, $1, $2, stimAmp, actvCells)
}
}
// Re-implement original procedure for cell tile
proc runRegion() { local id, xpos, ypos, amp, actvCells
if (pc.nhost == 1) {
// sequential execution
for aX = $1,$2 {
for aY = $3,$4 {
findThreshold(aX * 10, aY * 10)
}
}
} else {
// parallel execution
printf("INFO: ParallelContext.host = %d\n", pc.nhost)
pc.runworker()
for aX = $1,$2 {
for aY = $3,$4 {
pc.submit("findThreshold", aX * 10, aY * 10)
}
}
while ((id = pc.working) != 0) {
pc.take(id, &xpos, &ypos, &, &actvCells)
aFile.printf("%d %d %.5f %d\n", xpos, ypos, amp, actvCells)
aFile.flush()
}
pc.done
}
}
/////////////////////////////////////////////////////////////////////
// Initialization for off cell tile
proc atmInitOffCells() { local c
for c = 0,offCells-1 {
attDv[c] = new Vector()
attDv[c].record(&off[c].soma.v(0.5))
}
attTotalCells += offCells
}
// Initialization for on cell tile
proc atmInitOnCells() { local c
for c = 0,onCells-1 {
attDv[c] = new Vector()
attDv[c].record(&on[c].soma.v(0.5))
}
attTotalCells += onCells
}