
"""
nnNetwork.py

Created by Daniel Wuellner on 2007-05-15.
Last edited on 2007-06-08

neuronalNetwork class for simulation
"""

import sys
import os
from numpy import *
from numpy.random import *
import time


# connectivityMatrix
# totalConnections
# thresholdValue
# inhibitoryWeight
# currentState(t): vector of currently active neurons
# refractoryStatusArray(t): vector of currently 'refracting' neurons


class neuronalNetwork:
	# class variables
	NN_DEFAULT=30
	THRESHOLD_DEFAULT=1.0
	PERCENT_INHIBITORY_DEFAULT=0.1
	INHIBITORY_WEIGHT_DEFAULT=2.0
	INITIAL_ACTIVITY_PERCENTAGE_DEFAULT=0.1
	CONNECTION_STRENGTH_MEAN_DEFAULT=0.5
	CONNECTION_STRENGTH_SD_DEFAULT=0.1
	CONNECTIONS_MEAN_PERCENT_DEFAULT=0.6
	CONNECTIONS_SD_PERCENT_DEFAULT=0.1	
	
	

	def __init__(self,numberOfNeurons=NN_DEFAULT,threshold=THRESHOLD_DEFAULT,percentInhibitory=PERCENT_INHIBITORY_DEFAULT,
			inhibitoryWeight=INHIBITORY_WEIGHT_DEFAULT,connectionStrengthMean=CONNECTION_STRENGTH_MEAN_DEFAULT,
			connectionStrengthSD=CONNECTION_STRENGTH_SD_DEFAULT,connectionsMeanPercent=CONNECTIONS_MEAN_PERCENT_DEFAULT,
			connectionsSDPercent=CONNECTIONS_SD_PERCENT_DEFAULT,sourceConnectivityMatrix=None):
		self.numberOfNeurons=int(numberOfNeurons)
		self.threshold=threshold
		self.percentInhibitory=percentInhibitory
		self.inhibitoryWeight=inhibitoryWeight
		self.NI=int(self.numberOfNeurons*self.percentInhibitory)
		self.NE=self.numberOfNeurons-self.NI
		self.connectionStrengthMean=connectionStrengthMean
		self.connectionStrengthSD=connectionStrengthSD
		self.connectionsMeanPercent=connectionsMeanPercent
		self.connectionsSDPercent=connectionsSDPercent
		#generate array of neurons
		if sourceConnectivityMatrix==None:
			self.generateConnections()
		else:	#copy original matrix
			self.connectivityMatrix=sourceConnectivityMatrix
		self.currentState=[]
		self.currentPSP=[]
                for i in range(self.numberOfNeurons):
                    self.currentPSP.append('')
		self.refractoryStatusArray=[]
		for i in range(self.numberOfNeurons):
			self.refractoryStatusArray.append(0)
		self.PSPHistory=[]
		for i in range(self.numberOfNeurons):
			self.PSPHistory.append([])
		self.PSPVarHistory=[]
		for i in range(self.numberOfNeurons):
			self.PSPVarHistory.append([])
		self.AvePSPHistory=[]
		for i in range(self.numberOfNeurons):
			self.AvePSPHistory.append([])
		
		#free presynaptic matrix fpr[i][j]: 1 if ith neuron offers output to jth
		self.fpr=[]
		for i in range(self.numberOfNeurons):
			self.fpr.append([])
			for j in range(self.numberOfNeurons):
				self.fpr[i].append(0)
		
		#free postsynaptic matrix fpo[i][j]: 1 if ith neuron offers input from jth
		self.fpo=[]
		for i in range(self.numberOfNeurons):
			self.fpo.append([])
			for j in range(self.numberOfNeurons):
				self.fpo[i].append(0)

	def copy(self,templateCM):
		networkCopy=neuronalNetwork(self.numberOfNeurons,self.threshold,self.percentInhibitory,
					self.inhibitoryWeight,self.connectionStrengthMean,self.connectionStrengthSD, 						self.connectionsMeanPercent,self.connectionsSDPercent,
					templateCM)
		
		return networkCopy

	def getConnectionStrength(self):
		return abs(normal(self.connectionStrengthMean,self.connectionStrengthSD))	
	
	def generateConnections(self):		
		connectionsMean=self.connectionsMeanPercent*self.numberOfNeurons
		connectionsSD=self.connectionsSDPercent*self.numberOfNeurons
		self.connectivityMatrix=[]
		for i in range(self.numberOfNeurons):
			self.connectivityMatrix.append([])
			for j in range(self.numberOfNeurons):
				self.connectivityMatrix[i].append(0)
		self.totalConnections=0
		for i in range(self.numberOfNeurons):
			thisNeuronsConnections=int(normal(connectionsMean,connectionsSD))
			thisNeuronsConnectionsArray=resize(array([]),self.numberOfNeurons)
			#self.totalConnections=self.totalConnections+thisNeuronsConnections
			for j in range(thisNeuronsConnections):
				strength=self.getConnectionStrength()
				match=0
				while not(match):
					testTargetNeuron=int(uniform(0,self.numberOfNeurons))
					# check that there isn't an entry and don't allow self stimulation
					if (thisNeuronsConnectionsArray[testTargetNeuron]==0) and (testTargetNeuron!=i):
						self.connectivityMatrix[i][testTargetNeuron]=strength
						match=1

		self.connectivityMatrix=array(self.connectivityMatrix)
				
	
	