circuit.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. #===========================================================================
  2. # Import, Set up MPI Variables, Load Necessary Files
  3. #===========================================================================
  4. from mpi4py import MPI
  5. import time
  6. tic_0 = time.perf_counter() #script runtime calculation value
  7. import os
  8. from os.path import join
  9. import sys
  10. import numpy as np
  11. np.seterr(divide='ignore', invalid='ignore')
  12. from scipy import stats as st
  13. import neuron
  14. from neuron import h, gui
  15. import LFPy
  16. from LFPy import NetworkCell, Network, Synapse, RecExtElectrode, StimIntElectrode
  17. from matplotlib.collections import PolyCollection
  18. import matplotlib.pyplot as plt
  19. import pandas as pd
  20. #MPI variables:
  21. COMM = MPI.COMM_WORLD
  22. SIZE = COMM.Get_size()
  23. RANK = COMM.Get_rank()
  24. GLOBALSEED = int(sys.argv[1])
  25. # Create new RandomState for each RANK
  26. SEED = GLOBALSEED*10000
  27. np.random.seed(SEED + RANK)
  28. local_state = np.random.RandomState(SEED + RANK)
  29. halfnorm_rv = st.halfnorm
  30. halfnorm_rv.random_state = local_state
  31. uniform_rv = st.uniform
  32. uniform_rv.random_state = local_state
  33. #from net_params import *
  34. #Mechanisms and files
  35. print('Mechanisms found: ', os.path.isfile('mod/x86_64/special')) if RANK==0 else None
  36. neuron.h('forall delete_section()')
  37. neuron.load_mechanisms('mod/')
  38. h.load_file('net_functions.hoc')
  39. #===========================================================================
  40. # Simulation, Analysis, and Plotting Controls
  41. #===========================================================================
  42. TESTING = False # i.e.g generate 1 cell/pop, with 0.1 s runtime
  43. no_connectivity = False
  44. stimulate = False # Add a stimulus
  45. MDD = False #decrease PN GtonicApic and MN2PN weight by 40%
  46. DRUG = False
  47. rec_LFP = False #record LFP from center of layer
  48. rec_DIPOLES = False #record population - wide dipoles
  49. run_circuit_functions = True
  50. #===========================================================================
  51. # Params
  52. #===========================================================================
  53. dt = 0.025 #for both cell and network
  54. tstart = 0.
  55. tstop = 4500.
  56. celsius = 34.
  57. v_init = -80. #for both cell and network
  58. ###################### Load and organize Excel file ################################
  59. circuit_params = {}
  60. #Import Excel file
  61. circuit_params = pd.read_excel('Circuit_param.xls', sheet_name = None, index_col = 0)
  62. #Get cell names and import biophys
  63. cell_names = [i for i in circuit_params['conn_probs'].axes[0]]
  64. for name in cell_names:
  65. h.load_file('models/biophys_'+name+'.hoc')
  66. circuit_params["syn_params"] = {'none':{'tau_r_AMPA': 0,'tau_d_AMPA': 0,'tau_r_NMDA': 0,
  67. 'tau_d_NMDA': 0, 'e': 0,'Dep': 0,'Fac': 0,'Use': 0,'u0':0,'gmax': 0}}
  68. circuit_params["multi_syns"] = {'none':{'loc':0,'scale':0}}
  69. # organizing dictionary for LFPY input
  70. for pre in cell_names:
  71. for post in cell_names:
  72. if "PYR" in pre:
  73. circuit_params["syn_params"][pre+post] = {'tau_r_AMPA': 0.3, 'tau_d_AMPA': 3, 'tau_r_NMDA': 2,
  74. 'tau_d_NMDA': 65, 'e': 0, 'u0':0,
  75. 'Dep': circuit_params["Depression"].at[pre, post],
  76. 'Fac': circuit_params["Facilitation"].at[pre, post],
  77. 'Use': circuit_params["Use"].at[pre, post],
  78. 'gmax': circuit_params["syn_cond"].at[pre, post]}
  79. else:
  80. circuit_params["syn_params"][pre+post] = {'tau_r': 1, 'tau_d': 10, 'e': -80, 'u0':0,
  81. 'Dep': circuit_params["Depression"].at[pre, post],
  82. 'Fac': circuit_params["Facilitation"].at[pre, post],
  83. 'Use': circuit_params["Use"].at[pre, post],
  84. 'gmax': circuit_params["syn_cond"].at[pre, post]}
  85. circuit_params["multi_syns"][pre+post] = {'loc':int(circuit_params["n_cont"].at[pre, post]),'scale':0}
  86. stimuli = []
  87. for stimulus in circuit_params['STIM_PARAM'].axes[0]:
  88. stimuli.append({})
  89. for param_name in circuit_params['STIM_PARAM'].axes[1]:
  90. stimuli[-1][param_name] = circuit_params['STIM_PARAM'].at[stimulus, param_name]
  91. new_param = circuit_params["syn_params"][stimuli[-1]['syn_params']].copy()
  92. new_param['gmax'] = stimuli[-1]['gmax']
  93. stimuli[-1]['new_param'] = new_param
  94. COMM.Barrier()
  95. print('Importing, setting up MPI variables and loading necessary files took ', str((time.perf_counter() - tic_0)/60)[:5], 'minutes') if RANK==0 else None
  96. #################################################################################
  97. if TESTING:
  98. OUTPUTPATH = 'Circuit_output_testing'
  99. for name in cell_names:
  100. circuit_params['SING_CELL_PARAM'].at['cell_num',name] = 1
  101. tstop = 100
  102. print('Running test...') if RANK ==0 else None
  103. else:
  104. OUTPUTPATH = 'Circuit_output'
  105. print('Running full simulation...') if RANK==0 else None
  106. COMM.Barrier()
  107. ##################################################################################
  108. networkParams = {
  109. 'dt' : dt,
  110. 'tstart': tstart,
  111. 'tstop' : tstop,
  112. 'v_init' : v_init,
  113. 'celsius' : celsius,
  114. 'OUTPUTPATH' : OUTPUTPATH,
  115. 'verbose': False}
  116. # L2/3 L4 L5
  117. PYRmaxApics = [550 ,1550 ,1900]
  118. uppers = [-250 ,-1200 ,-1600]
  119. lowers = [-1200 ,-1580 ,-2300]
  120. depths = []
  121. rangedepths = []
  122. minSynLocs = []
  123. syn_pos = []
  124. pop_args = {}
  125. for i in range (3):
  126. depths.append((lowers[i]-uppers[i])/2-PYRmaxApics[i])
  127. rangedepths.append(abs(lowers[i]-uppers[i])/2)
  128. minSynLocs.append((lowers[i]-uppers[i])/2*3-PYRmaxApics[i])
  129. syn_pos.append({'section' : ['apic', 'dend'],
  130. 'fun' : [uniform_rv, halfnorm_rv],
  131. 'funargs' : [{'loc':minSynLocs[i], 'scale':abs(minSynLocs[i])},{'loc':minSynLocs[i], 'scale':abs(minSynLocs[i])}],
  132. 'funweights' : [1, 1.]})
  133. syn_pos.append({'section' : ['apic'],
  134. 'fun' : [uniform_rv],
  135. 'funargs' : [{'loc':minSynLocs[i], 'scale':abs(minSynLocs[i])}],
  136. 'funweights' : [1.]})
  137. syn_pos.append({'section' : ['dend'],
  138. 'fun' : [uniform_rv],
  139. 'funargs' : [{'loc':minSynLocs[i], 'scale':abs(minSynLocs[i])}],
  140. 'funweights' : [1.]})
  141. syn_pos.append({'section' : ['dend'],
  142. 'fun' : [halfnorm_rv],
  143. 'funargs' : [{'loc':minSynLocs[i], 'scale':abs(minSynLocs[i])}],
  144. 'funweights' : [1.]})
  145. names = ['HL2','HL4','HL5']
  146. pop_args[names[i]]={'radius':250,
  147. 'loc':depths[i],
  148. 'scale':rangedepths[i]*4,
  149. 'cap':rangedepths[i]}
  150. # class RecExtElectrode parameters:
  151. L23_size = abs(uppers[1] - lowers[1])
  152. e1 = 5 #-725
  153. LFPelectrodeParameters = dict(
  154. x=np.zeros(1),
  155. y=np.zeros(1),
  156. z=[e1],
  157. N=np.array([[0., 1., 0.] for _ in range(1)]),
  158. r=5.,
  159. n=50,
  160. sigma=0.3,
  161. method="soma_as_point")
  162. #method Network.simulate() parameters
  163. simargs = {'rec_imem': False,
  164. 'rec_vmem': False,
  165. 'rec_ipas': False,
  166. 'rec_icap': False,
  167. 'rec_isyn': False,
  168. 'rec_vmemsyn': False,
  169. 'rec_istim': False,
  170. 'rec_current_dipole_moment':rec_DIPOLES,
  171. 'rec_pop_contributions': False,
  172. 'rec_variables': [],
  173. 'to_memory': True,
  174. 'to_file': False,
  175. 'file_name':'OUTPUT.h5',
  176. 'dotprodcoeffs': None}
  177. #===========================================================================
  178. # Functions
  179. #===========================================================================
  180. def generateSubPop(popsize,mname,popargs,Gou,Gtonic,GtonicApic):
  181. print('Initiating ' + mname + ' population...') if RANK==0 else None
  182. morphpath = 'morphologies/' + mname + '.swc'
  183. templatepath = 'models/NeuronTemplate.hoc'
  184. templatename = 'NeuronTemplate'
  185. pt3d = True
  186. cellParams = {
  187. 'morphology': morphpath,
  188. 'templatefile': templatepath,
  189. 'templatename': templatename,
  190. 'templateargs': morphpath,
  191. 'v_init': v_init, #initial membrane potential, d=-65
  192. 'passive': False,#initialize passive mechs, d=T, should be overwritten by biophys
  193. 'dt': dt,
  194. 'tstart': 0.,
  195. 'tstop': tstop,#defaults to 100
  196. 'nsegs_method': None,
  197. 'pt3d': pt3d,#use pt3d-info of the cell geometries switch, d=F
  198. 'delete_sections': False,
  199. 'verbose': False}#verbose output switch, for some reason doens't work, figure out why}
  200. rotation = {'x':circuit_params['SING_CELL_PARAM'].at['rotate_x', mname],'y':circuit_params['SING_CELL_PARAM'].at['rotate_y', mname]}
  201. popParams = {
  202. 'CWD': None,
  203. 'CELLPATH': None,
  204. 'Cell' : LFPy.NetworkCell, #play around with this, maybe put popargs into here
  205. 'POP_SIZE': int(popsize),
  206. 'name': mname,
  207. 'cell_args' : {**cellParams},
  208. 'pop_args' : popargs,
  209. 'rotation_args' : rotation}
  210. network.create_population(**popParams)
  211. # Add biophys, OU processes, & tonic inhibition to cells
  212. for cellind in range(0,len(network.populations[mname].cells)):
  213. rseed = int(local_state.uniform()*SEED)
  214. biophys = 'h.biophys_' + mname + '(network.populations[\'' + mname + '\'].cells[' + str(cellind) + '].template)'
  215. exec(biophys)
  216. h.createArtificialSyn(rseed,network.populations[mname].cells[cellind].template,Gou)
  217. h.addTonicInhibition(network.populations[mname].cells[cellind].template,Gtonic,GtonicApic)
  218. def addStimulus():
  219. cell_nums=[circuit_params['SING_CELL_PARAM'].at['cell_num',name] for name in cell_names]
  220. for stim in stimuli:
  221. stim_index = sum(cell_nums[:cell_names.index(stim['cell_name'])]) + stim['num_cells'] + stim['start_index']
  222. for gid, cell in zip(network.populations[stim['cell_name']].gids, network.populations[stim['cell_name']].cells):
  223. if gid < stim_index and gid >= sum(cell_nums[:cell_names.index(stim['cell_name'])]) + stim['start_index']:
  224. idx = cell.get_rand_idx_area_norm(section=stim['loc'], nidx=stim['loc_num'])
  225. for i in idx:
  226. time_d=0
  227. syn = Synapse(cell=cell, idx=i, syntype=stim['stim_type'], weight=1,**stim['new_param'])
  228. while time_d <= 0:
  229. time_d = np.random.uniform(low = stim['delay'], high = stim['delay']+stim['delay_range'])
  230. syn.set_spike_times_w_netstim(noise=0, start=(stim['start_time']+time_d), number=stim['num_stim'], interval=stim['interval'], seed=GLOBALSEED)
  231. #===========================================================================
  232. # Sim
  233. #===========================================================================
  234. network = Network(**networkParams)
  235. if MDD:
  236. # synaptic reduction
  237. for pre in cell_names:
  238. for post in cell_names:
  239. if 'SST' in pre:
  240. circuit_params["syn_params"][pre+post]["gmax"] = circuit_params["syn_cond"].at[pre, post]*0.6 # Synaptic reduction
  241. # tonic reduction
  242. for post in cell_names:
  243. if 'PYR' in post:
  244. circuit_params['SING_CELL_PARAM'].at['apic_tonic',post] = circuit_params['SING_CELL_PARAM'].at['apic_tonic',post]*0.6
  245. circuit_params['SING_CELL_PARAM'].at["drug_apic_tonic",post] = circuit_params['SING_CELL_PARAM'].at["drug_apic_tonic",post]*0.6
  246. else:
  247. sst = 0
  248. total = 0
  249. for pre in cell_names:
  250. if 'SST' in pre:
  251. sst += circuit_params["syn_cond"].at[pre, post]*circuit_params["n_cont"].at[pre,post]*circuit_params["conn_probs"].at[pre, post]
  252. total += circuit_params["syn_cond"].at[pre, post]*circuit_params["n_cont"].at[pre,post]*circuit_params["conn_probs"].at[pre, post]
  253. elif 'PV' in pre or 'VIP' in pre:
  254. total += circuit_params["syn_cond"].at[pre, post]*circuit_params["n_cont"].at[pre, post]*circuit_params["conn_probs"].at[pre, post]
  255. circuit_params['SING_CELL_PARAM'].at['norm_tonic',post] -= circuit_params['SING_CELL_PARAM'].at['norm_tonic',post]*sst/total*0.4
  256. print(post, '_tonic reduced by: ', sst/total*100*0.4, '%') if RANK == 0 else None
  257. # Generate Populations
  258. tic = time.perf_counter()
  259. for cell_name in cell_names:
  260. if DRUG:
  261. generateSubPop(circuit_params['SING_CELL_PARAM'].at['cell_num',cell_name],
  262. cell_name,pop_args[cell_name[:3]],
  263. circuit_params['SING_CELL_PARAM'].at['GOU',cell_name],
  264. circuit_params['SING_CELL_PARAM'].at['drug_tonic',cell_name],
  265. circuit_params['SING_CELL_PARAM'].at['drug_apic_tonic',cell_name])
  266. else:
  267. generateSubPop(circuit_params['SING_CELL_PARAM'].at['cell_num',cell_name],
  268. cell_name,pop_args[cell_name[:3]],
  269. circuit_params['SING_CELL_PARAM'].at['GOU',cell_name],
  270. circuit_params['SING_CELL_PARAM'].at['norm_tonic',cell_name],
  271. circuit_params['SING_CELL_PARAM'].at['apic_tonic',cell_name])
  272. COMM.Barrier()
  273. print('Instantiating all populations took ', str((time.perf_counter() - tic_0)/60)[:5], 'minutes') if RANK==0 else None
  274. tic = time.perf_counter()
  275. # Synaptic Connection Parameters
  276. E_syn = neuron.h.ProbAMPANMDA
  277. I_syn = neuron.h.ProbUDFsyn
  278. for i, pre in enumerate(network.population_names):
  279. for j, post in enumerate(network.population_names):
  280. connectivity = network.get_connectivity_rand(
  281. pre=pre,
  282. post=post,
  283. connprob=0 if no_connectivity else circuit_params["conn_probs"].at[pre, post])
  284. (conncount, syncount) = network.connect(
  285. pre=pre, post=post,
  286. connectivity=connectivity,
  287. syntype=E_syn if "PYR" in pre else I_syn,
  288. synparams=circuit_params["syn_params"][pre+post],
  289. weightfun=local_state.normal,
  290. weightargs={'loc':1, 'scale':0},
  291. minweight=1,
  292. delayfun=local_state.normal,
  293. delayargs={'loc':0.5, 'scale':0},
  294. mindelay=0.5,
  295. multapsefun=local_state.normal,
  296. multapseargs=circuit_params["multi_syns"][pre+post],
  297. syn_pos_args=syn_pos[circuit_params["Syn_pos"].at[pre,post]])
  298. print('Connecting populations took ', str((time.perf_counter() - tic_0)/60)[:5], 'minutes') if RANK==0 else None
  299. # Setup Extracellular Recording Device
  300. COMM.Barrier()
  301. if stimulate:
  302. addStimulus()
  303. COMM.Barrier()
  304. # Run Simulation
  305. tic = time.perf_counter()
  306. if rec_LFP and not rec_DIPOLES:
  307. LFPelectrode = RecExtElectrode(**LFPelectrodeParameters)
  308. print('Simulating, recording SPIKES and LFP ... ') if RANK==0 else None
  309. SPIKES, OUTPUT, _ = network.simulate(electrode=LFPelectrode,**simargs)
  310. elif rec_LFP and rec_DIPOLES:
  311. print('Simulating, recording SPIKES, LFP, and DIPOLEMOMENTS ... ') if RANK==0 else None
  312. LFPelectrode = RecExtElectrode(**LFPelectrodeParameters)
  313. SPIKES, OUTPUT, DIPOLEMOMENT = network.simulate(electrode=LFPelectrode,**simargs)
  314. elif not rec_LFP and rec_DIPOLES:
  315. print('Simulating, recording SPIKES and DIPOLEMOMENTS ... ') if RANK==0 else None
  316. SPIKES, _, DIPOLEMOMENT = network.simulate(**simargs)
  317. elif not rec_LFP and not rec_DIPOLES:
  318. print('Simulating, recording SPIKES ... ') if RANK==0 else None
  319. SPIKES = network.simulate(**simargs)
  320. print('Simulation took ', str((time.perf_counter() - tic_0)/60)[:5], 'minutes') if RANK==0 else None
  321. COMM.Barrier()
  322. if RANK==0:
  323. tic = time.perf_counter()
  324. print('Saving simulation output ...')
  325. np.save(os.path.join(OUTPUTPATH,'SPIKES_Seed'+str(GLOBALSEED)+'.npy'), SPIKES)
  326. np.save(os.path.join(OUTPUTPATH,'OUTPUT_Seed'+str(GLOBALSEED)+'.npy'), OUTPUT) if rec_LFP else None
  327. np.save(os.path.join(OUTPUTPATH,'DIPOLEMOMENT_Seed'+str(GLOBALSEED)+'.npy'), DIPOLEMOMENT) if rec_DIPOLES else None
  328. print('Saving simulation took', str((time.perf_counter() - tic_0)/60)[:5], 'minutes')
  329. #===========================================================================
  330. # Plotting
  331. #===========================================================================
  332. if run_circuit_functions:
  333. tstart_plot = 2000
  334. tstop_plot = tstop
  335. print('Creating/saving plots...') if RANK==0 else None
  336. exec(open("circuit_functions.py").read())
  337. #===============
  338. #Final printouts
  339. #===============
  340. if TESTING:
  341. print('Test complete, switch TESTING to False for full simulation') if RANK==0 else None
  342. elif not TESTING:
  343. print('Simulation complete') if RANK==0 else None
  344. print('Script completed in ', str((time.perf_counter() - tic_0)/60)[:5], 'minutes') if RANK==0 else None