Skip to content

Commit

Permalink
All RNG usages except Random123 are removed. All non-Random123 config…
Browse files Browse the repository at this point in the history
…uration options removed
  • Loading branch information
atemerev committed Feb 29, 2024
1 parent 12634ef commit 1ff86d3
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 274 deletions.
164 changes: 4 additions & 160 deletions core/hoc/RNGSettings.hoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
*/
{load_file("fileUtils.hoc")}

rngMode = 0 // corresponds to COMPATIBILITY defined below
ionchannelSeed = 0
synapseSeed = 0
stimulusSeed = 0
Expand All @@ -16,16 +15,11 @@ globalSeed = 0

begintemplate RNGSettings

public init, interpret, getRNGMode, getIonChannelSeed, getSynapseSeed, getStimulusSeed, getMinisSeed, getGlobalSeed
public COMPATIBILITY, RANDOM123, UPMCELLRAN4
public init, interpret, getIonChannelSeed, getSynapseSeed, getStimulusSeed, getMinisSeed, getGlobalSeed

external rngMode, ionchannelSeed, synapseSeed, stimulusSeed, minisSeed, globalSeed, terminate
external ionchannelSeed, synapseSeed, stimulusSeed, minisSeed, globalSeed, terminate

proc init() {
// consts for random number handling
COMPATIBILITY = 0
RANDOM123 = 1
UPMCELLRAN4 = 2
}

/**
Expand All @@ -37,7 +31,6 @@ proc init() {
proc interpret() { local coreNeuronUsed localobj runInfo, pc, rng
strdef rngModeField
runInfo = $o1
rngMode = RANDOM123
coreNeuronUsed = $2
if (numarg() < 2) {
coreNeuronUsed = 0
Expand All @@ -48,42 +41,14 @@ proc interpret() { local coreNeuronUsed localobj runInfo, pc, rng
print "As of Oct 2020 Neurodamus uses Random123 as default"
}

if( runInfo.exists( "RNGMode" ) ) {
rngModeField = runInfo.get( "RNGMode" ).s
if( strcmp( rngModeField, "Compatibility" ) == 0 ) {
rngMode = COMPATIBILITY
} else if( strcmp( rngModeField, "UpdatedMCell" ) == 0 ) {
rngMode = UPMCELLRAN4
} else if( strcmp( rngModeField, "Random123" ) == 0 ) {
rngMode = RANDOM123
} else {
terminate( "Invalid RNGMode ", rngModeField )
}
if( pc.id() == 0 ) {
print "RNGMode set to ", rngMode, " [COMPATIBILITY=0, RANDOM123=1, UPMCELLRAN4=2]"
}
}

if( coreNeuronUsed && rngMode != RANDOM123) {
// Given R123 is now the default there's no sense to allow an explicit invalid option
terminate( "Config Error: CoreNEURON requires Random123 RNG" )
}

if( runInfo.exists("BaseSeed") ) {
globalSeed = runInfo.valueOf( "BaseSeed" )

// random123 can set the global index now
if( rngMode == RANDOM123 ) {
rng = new Random()
rng.Random123_globalindex( globalSeed )
}
rng = new Random()
rng.Random123_globalindex( globalSeed )
}

// don't search for indicidual seeds if we are in compatibility mode
if( rngMode == COMPATIBILITY ) {
return
}

if( runInfo.exists("IonChannelSeed") ) {
ionchannelSeed = runInfo.valueOf( "IonChannelSeed" )
}
Expand All @@ -98,10 +63,6 @@ proc interpret() { local coreNeuronUsed localobj runInfo, pc, rng
}
}

func getRNGMode() {
return rngMode
}

func getIonChannelSeed() {
return ionchannelSeed
}
Expand All @@ -123,120 +84,3 @@ func getGlobalSeed() {
}

endtemplate RNGSettings


///////////////////////////////////////////////////////////////////////
///
/// These are legacy functions to keep compaltibility
///
///////////////////////////////////////////////////////////////////////

/*!
* In place of using a CCell's re_init_rng function, we will check for cells that define the re_init_rng function,
* but then setRNG using global seed as well
*
* @param $o1 CCell which is to be checked for setRNG
*/
obfunc rngForStochKvInit() { local channelID, hasStochKv localobj CCell, rng, rngInfo, rngList, pc
CCell = $o1
//print "Replace rng for stochKv in gid ", CCell.CellRef.gid

// quick check to verify this object contains StochKv
hasStochKv = 0
CCell.CellRef.soma {
if( ismembrane( "StochKv" ) ) {
hasStochKv = 1
}
}

if( !hasStochKv ) {
return
}

rngList = new List()

channelID = 0
forsec CCell.CellRef.somatic {
for (x, 0) {
setdata_StochKv(x)
rng = new Random()
rng.MCellRan4( channelID*10000+100, globalSeed + ionchannelSeed + CCell.CellRef.gid*10000+250+1 )
channelID = channelID + 1
rng.uniform(0,1)
setRNG_StochKv(rng)
rngList.append(rng)
}
}
forsec CCell.CellRef.basal {
for (x, 0) {
setdata_StochKv(x)
rng = new Random()
rng.MCellRan4( channelID*10000+100, globalSeed + ionchannelSeed + CCell.CellRef.gid*10000+250+1 )
channelID = channelID + 1
rng.uniform(0,1)
setRNG_StochKv(rng)
rngList.append(rng)
}
}
forsec CCell.CellRef.apical {
for (x, 0) {
setdata_StochKv(x)
rng = new Random()
rng.MCellRan4( channelID*10000+100, globalSeed + ionchannelSeed + CCell.CellRef.gid*10000+250+1 )
channelID = channelID + 1
rng.uniform(0,1)
setRNG_StochKv(rng)
rngList.append(rng)
}
}

return rngList
}

//-----------------------------------------------------------------------------------------------

/*!
* In place of using a CCell's re_init_rng function, we will check for cells that define the re_init_rng function,
* but then setRNG using random123
*
* @param $o1 CCell which is to be checked for setRNG
*/
proc rng123ForStochKvInit() { local channelID, hasStochKv localobj CCell
CCell = $o1
//print "Replace rng for stochKv in gid ", CCell.CellRef.gid

// quick check to verify this object contains StochKv
hasStochKv = 0
CCell.CellRef.soma {
if( ismembrane( "StochKv" ) ) {
hasStochKv = 1
}
}

if( !hasStochKv ) {
return
}

channelID = 0
forsec CCell.CellRef.somatic {
for (x, 0) {
setdata_StochKv(x)
setRNG_StochKv(ionchannelSeed, channelID, CCell.CellRef.gid + 1)
channelID = channelID + 1
}
}
forsec CCell.CellRef.basal {
for (x, 0) {
setdata_StochKv(x)
setRNG_StochKv(ionchannelSeed, channelID, CCell.CellRef.gid + 1)
channelID = channelID + 1
}
}
forsec CCell.CellRef.apical {
for (x, 0) {
setdata_StochKv(x)
setRNG_StochKv(ionchannelSeed, channelID, CCell.CellRef.gid + 1)
channelID = channelID + 1
}
}
}
30 changes: 3 additions & 27 deletions neurodamus/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -714,36 +714,12 @@ def create_on(self, conn, sec, position, syn_obj, syn_params, base_seed, _rate_v
self._store(ips, netcon)

src_pop_id, dst_pop_id = conn.population_id
rng_mode = self._rng_info.getRNGMode()
rng_seed = self._rng_info.getMinisSeed()
tgid_seed = conn.tgid + 250

if rng_mode == self._rng_info.RANDOM123:
seed2 = (src_pop_id * 65536 + dst_pop_id + rng_seed)
ips.setRNGs(syn_obj.synapseID + 200, tgid_seed, seed2 + 300,
syn_obj.synapseID + 200, tgid_seed, seed2 + 350)
else:
seed2 = src_pop_id * 16777216
exprng = Nd.Random()
if rng_mode == self._rng_info.COMPATIBILITY:
exprng.MCellRan4(syn_obj.synapseID * 100000 + 200,
tgid_seed + base_seed + rng_seed)
else: # if ( rngIndo.getRNGMode()== rng_info.UPMCELLRAN4 ):
exprng.MCellRan4(syn_obj.synapseID * 1000 + 200,
seed2 + tgid_seed + base_seed + rng_seed)

exprng.negexp(1)
uniformrng = Nd.Random()
if rng_mode == self._rng_info.COMPATIBILITY:
uniformrng.MCellRan4(syn_obj.synapseID * 100000 + 300,
tgid_seed + base_seed + rng_seed)
else: # if ( rngIndo.getRNGMode()== rng_info.UPMCELLRAN4 ):
uniformrng.MCellRan4(syn_obj.synapseID * 1000 + 300,
seed2 + tgid_seed + base_seed + rng_seed)

uniformrng.uniform(0.0, 1.0)
ips.setRNGs(exprng, uniformrng)
self._keep_alive += (exprng, uniformrng)
seed2 = (src_pop_id * 65536 + dst_pop_id + rng_seed)
ips.setRNGs(syn_obj.synapseID + 200, tgid_seed, seed2 + 300,
syn_obj.synapseID + 200, tgid_seed, seed2 + 350)

def __bool__(self):
"""object is considered False in case rate is not positive"""
Expand Down
2 changes: 0 additions & 2 deletions neurodamus/core/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,6 @@ class CircuitConfig(ConfigT):


class RNGConfig(ConfigT):
Modes = Enum("Mode", "COMPATIBILITY RANDOM123 UPMCELLRAN4")
mode = Modes.COMPATIBILITY
global_seed = None
IonChannelSeed = None
StimulusSeed = None
Expand Down
37 changes: 8 additions & 29 deletions neurodamus/core/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,36 @@
"""
from __future__ import absolute_import
from . import Neuron
from neurodamus.core.configuration import RNGConfig


# NOTE: These are pure wrappers, in the sense they dont create Python objects. Instead
# NOTE: These are pure wrappers, in the sense they don't create Python objects. Instead
# Neuron objects are returned (using __new__)


class RNG(object):
def __new__(cls, *ids, **kw):
"""Creates a default RNG, currently based on ACG"""
"""Creates a default RNG (Random123) """
seed = kw.get("seed")
return Neuron.h.Random() if seed is None else Neuron.h.Random(seed)
return Random123(ids[0], ids[1], ids[2], seed)

@classmethod
def create(cls, rng_mode, ids, seed=None):
# type: (RNGConfig, tuple, object) -> RNG
if rng_mode == RNGConfig.Modes.RANDOM123:
assert len(ids) == 3, "Random123 requires three ids (as a tuple)"
obj = Random123(ids[0], ids[1], ids[2], seed)
elif rng_mode == RNGConfig.Modes.UPMCELLRAN4:
assert len(ids) == 1
obj = MCellRan4(ids[0], seed)
else:
obj = RNG(seed)
def create(cls, ids, seed=None):
# type: (tuple, object) -> RNG
assert len(ids) == 3, "Random123 requires three ids (as a tuple)"
obj = Random123(ids[0], ids[1], ids[2], seed)

return obj


class ACG(RNG):
def __new__(cls, size=None, seed=None):
rng = RNG(seed=seed)
rng.ACG(seed, size)
return rng


class Random123(RNG):
def __new__(cls, id1, id2, id3, seed=None):
rng = RNG()
rng = Neuron.h.Random() if seed is None else Neuron.h.Random(seed)
if seed is not None:
rng.Random123_globalindex(seed)
rng.Random123(id1, id2, id3)
return rng


class MCellRan4(RNG):
def __new__(cls, high_i, seed=None, low_i=0):
rng = RNG(seed=seed)
rng.MCellRan4(high_i, low_i)
return rng


# Gamma-distributed sample generator (not available in NEURON)
def gamma(rng, a, b, N=1):
"""
Expand Down
Loading

0 comments on commit 1ff86d3

Please sign in to comment.