'''
This is the netParams.py file for the single receptive field (RF) model
Code by L Medlock (Nov 15 2024)
'''

from netpyne import specs, sim
from neuron import h
import numpy as np
import json

try: 
    from __main__ import cfg
except:
    from cfg_RF import cfg

netParams = specs.NetParams()

netParams.defaultThreshold = -20    

###############################################################################
# CELL PARAMETERS
###############################################################################

##############   AdEx Models + Balachandar et al. (2018) + Ratte et al. (2015)   #####################
##Inhibitory Spinal Neurons (Tonic Spiking)
netParams.importCellParams(
        label='SpinalNeuron_AdEx_Tonic',
        conds={'cellType': 'I_tonic', 'cellModel': 'I_tonic'},
        fileName=('SpinalNeuron_AdEx.hoc'),
        cellName='SDH_Tonic_AdEx',
        importSynMechs=True)

# # # Excitatory Spinal Neurons (Single Spiking)
netParams.importCellParams(
        label='SpinalNeuron_AdEx_Single',
        conds={'cellType': 'E_single', 'cellModel': 'E_single'},
        fileName=('SpinalNeuron_AdEx.hoc'),
        cellName='SDH_Single_AdEx',
        importSynMechs=True)

# # # Excitatory Spinal Neurons (Delayed Spiking)
netParams.importCellParams(
        label='SpinalNeuron_AdEx_Delay',
        conds={'cellType': 'E_delay', 'cellModel': 'E_delay'},
        fileName=('SpinalNeuron_AdEx.hoc'),
        cellName='SDH_Delay_AdEx',
        importSynMechs=True)

# # Excitatory Spinal Neurons (Hybrid Spiking)
netParams.importCellParams(
        label='SpinalNeuron_AdEx_Hybrid',
        conds={'cellType': 'E_hybrid', 'cellModel': 'E_hybrid'},
        fileName=('SpinalNeuron_AdEx.hoc'),
        cellName='SDH_Hybrid_AdEx',
        importSynMechs=True)

# Primary Afferent (I&F Only)
netParams.importCellParams(
        label='PAN_AdEx',
        conds={'cellType': 'PAN', 'cellModel': 'PAN'},
        fileName=('SpinalNeuron_AdEx.hoc'),
        cellName='PAN_AdEx',
        importSynMechs=True)

###############################################################################
# POPULATION PARAMETERS
###############################################################################

# PANs 
netParams.popParams['PAN'] = {'cellType':'PAN', 
                                  'gridSpacing': 1750,
                                  'xRange' : [0,17500], 
                                  'yRange' : [0,17500], 
                                  'zRange' : [0,0], 
                                  'cellModel': 'PAN'}

# Tonic Pop (Inhibitory)
netParams.popParams['I_layer'] = {'cellType': 'I_tonic',
                                    'gridSpacing': 1750,
                                    'cellModel': 'I_tonic',
                                    'xRange' : [7000,10500], 
                                    'yRange' : [7000,10500], 
                                    'zRange' : [3000,3000] }

# Excitatory Pop (Delay, Single, Hybrid)
netParams.popParams['E_cell'] = {'cellType':'E_delay', 
                                  'numCells': 1, 
                                  'cellModel': 'E_delay',
                                  'xRange' : [8750,8750], 
                                  'yRange' : [8750,8750], 
                                  'zRange' : [4000,4000] }


###############################################################################
# SYNAPTIC PARAMETERS
###############################################################################

netParams.synMechParams['AMPA'] = {'mod': 'Exp2Syn', 'tau1': 0.1, 'tau2': 5.0, 'e': 0}  # excitatory synaptic mechanism
netParams.synMechParams['GABA'] = {'mod': 'Exp2Syn', 'tau1': 0.1, 'tau2': 20.0, 'e': -70}  # inhibitory synaptic mechanism

###############################################################################
# TOUCH PARAMETERS
###############################################################################

# # Cell IDs of PANs for Touch Stimulation 
netParams.stim1 = [60]
netParams.stim2 = [48,49,50,59,60,61,70,71,72]
netParams.stim3 = [36,37,38,39,40,47,48,49,50,51,58,59,60,61,62,69,70,71,72,73,80,81,82,83,84]
netParams.stim4 = [24,25,26,27,28,29,30,35,36,37,38,39,40,41,46,47,48,49,50,51,52,57,58,59,60,61,62,63,68,69,70,71,72,73,74,79,80,81,82,83,84,85,90,91,92,93,94,95,96]
netParams.stim5 = [12,13,14,15,16,17,18,19,20,23,24,25,26,27,28,29,30,31,34,35,36,37,38,39,40,41,42,45,46,47,48,49,50,51,52,53,56,57,58,59,60,61,62,63,64,67,68,69,70,71,72,73,74,75,78,79,80,81,82,83,84,85,86,89,90,91,92,93,94,95,96,97,100,101,102,103,104,105,106,107,108]
netParams.stim6 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120]

###############################################################################
# RECEPTIVE FIELD STRUCTURE
###############################################################################
# PANs --> Output Neuron 
netParams.RFE = [24,25,26,27,28,29,30,35,36,37,38,39,40,41,46,47,48,49,50,51,52,57,58,59,60,61,62,63,68,69,70,71,72,73,74,79,80,81,82,83,84,85,90,91,92,93,94,95,96]  # Index of PANs in E1 Receptive Field 
netParams.E1 = np.zeros(len(netParams.RFE), dtype='int8')                                     # Index of E1 Neuron
netParams.Pre2PostRF1 = []
netParams.Pre2PostRF1 = list(zip(netParams.RFE, netParams.E1))                            # Zip PANs indexes with E1 index (for connectivity)              

# PANs --> Inhibitory Layer
netParams.RF1 = [36,37,38,39,40,47,48,49,50,51,58,59,60,61,62,69,70,71,72,73,80,81,82,83,84]
netParams.RF1_ICenter = netParams.RF1                                                     # Indexing same as E1
netParams.ICenter = np.ones(len(netParams.RF1_ICenter), dtype='int8') * 4                 # Cell index for center neuron (ICenter) of inhibitory layer
netParams.P2P_RF1_ICenter = []
netParams.P2P_RF1_ICenter = list(zip(netParams.RF1_ICenter, netParams.ICenter))           # Zip PANs indexes with ICenter index (for connectivity)    

netParams.RF1_ITop = [x-3 for x in netParams.RF1]                                         # Shift indexing down by 2 for ITop
netParams.ITop = np.ones(len(netParams.RF1_ITop), dtype='int8') * 3                       # Cell index for top neuron (ITop) of inhibitory layer
netParams.P2P_RF1_ITop = []
netParams.P2P_RF1_ITop = list(zip(netParams.RF1_ITop, netParams.ITop))                    # Zip PANs indexes with ITop index (for connectivity)   

netParams.RF1_IBottom = [x+3 for x in netParams.RF1]                                      # Shift indexing up by 2 for IBottom
netParams.IBottom = np.ones(len(netParams.RF1_IBottom), dtype='int8') * 5                 # Cell index for bottom neuron (IBottom) of inhibitory layer
netParams.P2P_RF1_IBottom = []
netParams.P2P_RF1_IBottom = list(zip(netParams.RF1_IBottom, netParams.IBottom))           # Zip PANs indexes with IBottom index (for connectivity)   

netParams.RF1_ILeft = [x-33 for x in netParams.RF1]                                       # Shift indexing down by 18 for ILeft
netParams.ILeft = np.ones(len(netParams.RF1_ILeft), dtype='int8')                         # Cell index for left neuron (ILeft) of inhibitory layer
netParams.P2P_RF1_ILeft = []
netParams.P2P_RF1_ILeft = list(zip(netParams.RF1_ILeft, netParams.ILeft))                 # Zip PANs indexes with ILeft index (for connectivity)   

netParams.RF1_IRight = [x+33 for x in netParams.RF1]                                      # Shift indexing up by 18 for IRight
netParams.IRight = np.ones(len(netParams.RF1_IRight), dtype='int8') * 7                   # Cell index for right neuron (IRight) of inhibitory layer
netParams.P2P_RF1_IRight = []
netParams.P2P_RF1_IRight = list(zip(netParams.RF1_IRight, netParams.IRight))              # Zip PANs indexes with IRight index (for connectivity)   

###############################################################################
# CONNECTIVITY PARAMETERS
###############################################################################

## ----------------- Connectivity for E Cell 1 ----------------- ##

netParams.connParams['PAN->E1'] = {    #  PAN --> E_delay1
        'preConds': {'pop':'PAN'},
        'postConds': {'pop':'E_cell'},
        'sec': 'soma',                  # target postsyn section
        'synMech': 'AMPA',              # target synaptic mechanism
        'weight': 'max(0,0.001*(0.9*exp(-((pre_x-8750)**2 + (pre_y-8750)**2)/8100000)+0.1*exp(-((pre_x-8750)**2 + (pre_y-8750)**2)/65000000)))',  # Max 0.0010 for E cells
        #'weight': 'max(0,0.0005*exp(-((pre_x-8750)**2 + (pre_y-8750)**2)/12500000))',   # Max 0.0005 for tonic
        'prob': 0.2,                      # synaptic probability
        'delay': 10,                      # transmission delay (ms)
        'connList': netParams.Pre2PostRF1 # connection between specific neurons
        }

netParams.connParams['PAN->I_Center'] = {    #  PAN --> I_Center
        'preConds': {'pop': 'PAN'},
        'postConds': {'pop': 'I_layer'},
        'sec': 'soma',                  # target postsyn section
        'synMech': 'AMPA',              # target synaptic mechanism
        'weight': 'max(0,0.0005*exp(-((pre_x-8750)**2 + (pre_y-8750)**2)/12500000))',  # Gaussian with center at [8750,8750]          
        'prob': 0.2,                    # synaptic probability
        'delay': 10,                     # transmission delay (ms)
        'connList': netParams.P2P_RF1_ICenter # connection between specific neurons
        }

netParams.connParams['PAN->I_Top'] = {    #  PAN --> I_Top
        'preConds': {'pop': 'PAN'},
        'postConds': {'pop': 'I_layer'},
        'sec': 'soma',                  # target postsyn section
        'synMech': 'AMPA',              # target synaptic mechanism
        'weight': 'max(0,0.0005*exp(-((pre_x-8750)**2 + (pre_y-3500)**2)/12500000))',    # Gaussian with center at [8750,3500]              
        'prob': 0.2,                    # synaptic probability
        'delay': 10,                     # transmission delay (ms)
        'connList': netParams.P2P_RF1_ITop # connection between specific neurons
        }

netParams.connParams['PAN->I_Bottom'] = {    #  PAN --> I_Bottom
        'preConds': {'pop': 'PAN'},
        'postConds': {'pop': 'I_layer'},
        'sec': 'soma',                  # target postsyn section
        'synMech': 'AMPA',              # target synaptic mechanism
        'weight': 'max(0,0.0005*exp(-((pre_x-8750)**2 + (pre_y-14000)**2)/12500000))',   # Gaussian with center at [8750,14000]                 
        'prob': 0.2,                    # synaptic probability
        'delay': 10,                     # transmission delay (ms)
        'connList': netParams.P2P_RF1_IBottom # connection between specific neurons
        }

netParams.connParams['PAN->I_Left'] = {    #  PAN --> I_Left
        'preConds': {'pop': 'PAN'},
        'postConds': {'pop': 'I_layer'},
        'sec': 'soma',                  # target postsyn section
        'synMech': 'AMPA',              # target synaptic mechanism
        'weight': 'max(0,0.0005*exp(-((pre_x-3500)**2 + (pre_y-8750)**2)/12500000))',     # Gaussian with center at [3500,8750]                  
        'prob': 0.2,                    # synaptic probability
        'delay': 10,                     # transmission delay (ms)
        'connList': netParams.P2P_RF1_ILeft # connection between specific neurons
        }

netParams.connParams['PAN->I_Right'] = {    #  PAN --> I_Right
        'preConds': {'pop': 'PAN'},
        'postConds': {'pop': 'I_layer'},
        'sec': 'soma',                  # target postsyn section
        'synMech': 'AMPA',              # target synaptic mechanism
        'weight': 'max(0,0.0005*exp(-((pre_x-14000)**2 + (pre_y-8750)**2)/12500000))',     # Gaussian with center at [14000,8750]         
        'prob': 0.2,                    # synaptic probability
        'delay': 10,                     # transmission delay (ms)
        'connList': netParams.P2P_RF1_IRight # connection between specific neurons
        }

netParams.connParams['I_layer->E_cell'] = {    #  I_layer --> E_cell  
        'preConds': {'pop': 'I_layer'},
        'postConds': {'pop': 'E_cell'},
        'sec': 'soma',                  # target postsyn section
        'synMech': 'GABA',              # target synaptic mechanism
        'weight':'max(0,0.002*exp(-((pre_x-8750)**2 + (pre_y-8750)**2)/12500000))',      # (Max = 0.001 when tonic; Max = 0.002 when delay, single, gap)                                                         
        'prob': 0.2,                    # synaptic probability
        'delay': 2,                     # transmission delay (ms)
        'connList': [[1,0],[3,0],[4,0],[5,0],[7,0]]       # connections between I_Layer neurons and E1
        }

###############################################################################
# STIMULATION PARAMETERS
###############################################################################

# ------------ Touch Stimuli --------------##
netParams.stimSourceParams['Mech'] = {'type': 'NetStim',  # NETSTIM
                                        'rate' : 50,
                                        'start': 0,
                                        'noise': 0.6 }   # 0 = sync, 0.6 = async

netParams.stimTargetParams['Input->PAN'] = {'source': 'Mech',  # Mech --> PAN
                                                  'sec':'soma',
                                                  'loc': 0.5,
                                                  'weight': 0.2,
                                                  'delay' : 1,
                                                  'conds': {'pop':'PAN','cellList':netParams.stim3}}     # stim1, stim2, stim3, stim4, stim5, stim6


# ------------ IClamp Stimuli (for single neurons) --------------##
# netParams.stimSourceParams['IClamp1'] = {'type': 'IClamp', 
#                                        'del': 250,
#                                        'dur': 500,
#                                        'amp': 0.1 } #  [nA] (point process) 
# netParams.stimTargetParams['Stim1'] = {'source': 'IClamp1', 'conds': {'pop': 'E_cell'},'sec': 'soma', 'loc': 0.5}