import os
from threading import Thread
from sys import argv
system = os.system
import numpy as np
from numpy.random import rand, seed
from time import sleep

SLOW=0 # 1 = do runs serially
DRAW=0 # create rebound calcium/voltage images for a single run (high overhead)
CONV=0 # 0 = mNACc (not implemented here), 1 = DMS, 2 = DLS, 3=lNAcc 
	# set elsewhere, initialization so python doesn't complain
GRAPH=1 # if 0, will not return voltage traces, but will return rasters, individual histograms
DISTAL=5 # which dendrite is stimulated/recorded from for a couple functions
SUMMATE=0 # whether recorded variables (defined in main.py) will be summed over all compartments
BALANCED=0
  #1 for array parms balanced
PRC=0
RANDOM=0
PYTHON_VER = 'python3.9' # change as needed.  Outside of a stable install for a custom version of neuron, python or python3 should be sufficient

TOG=1
today = 'Kv4_run_1101' 
REBOUND80=1 # current steps to -80
MORPHO='KomandontovTemplate_2branch.hoc'
import numpy as np

#print today
name2 = 'None'
RUN=1

dur = 10000
name2 = 'vslow'
#paint = 'init_cell_cicr.py'
paint = 'init_cell_beyond.py'
tasks = []
OFF=1
parent = os.getcwd()
path = os.path.join(parent,today)
#print(parent,path)

if not os.path.exists(path):
	os.mkdir(path)

import shutil

stuff = [__file__.lstrip(parent),'main.py',paint,MORPHO,'paramsdict.py']


for things in stuff:
	#print(things, '%s' % (path+os.sep+things))
	shutil.copy(things, path+os.sep+things)	

rfile = 'randomvals_%s.dat' % today

fp = open(rfile,'w')
rands = rand(10)
seed(0)
for CONV in [1,2,3]:#range(1,4,1):
	#for MUSC in range(1):

	for M in range(0,11,1): # loop over cells
		if BALANCED: # fixes random parameters for model, but not synaptic noise
			rands = rand(10)
		else:
			dump = rand(10) # still need to generate random numbers
		
		if CONV in [1,2,3]: #removes sets to not use without changing random seeds for later sets
			pass
		else:
			continue

		for K in [0]: # 0 for Fixed GIRK in vitro
			TOG=K
			fp.write('%d  %d  ' %(M, K))
			for r in rands:
				fp.write('%e   ' % r)
			fp.write('\n')			

			if DRAW:
				if M in [1] and CONV in [2] and K in [1]:
					pass
				else:
					continue

			print(M,K,DRAW)
			MUSC = 0#0.1*M
			iamp=0#M*-10e-3 # -40 for atypical
			K2=0.5
			# atyp 5 GABA 5 nmda
			# dms 5/5 is balanced, but may not be strong enough
			# 5/5 is fine for everything, lets run single pulse GABAa, GABAb and 10 pulse GABAa, GABAb
			P=4.5+2*TOG+4*BALANCED #Input resistence is nearly halfed
			if CONV in [1,3]:
				P+=1.5 # different input resistence
				#continue
			#K = K%2
			rlist =[-40e-3,-10e-3*P,-10e-3*P,-10e-3*P]

			if REBOUND80:
				try:
					iamp = rlist[CONV]
				except:
					print('CONV out of range, iamp=0')
					iamp=0
		
			if PRC:
				iamp = 10e-3				
			
			chrhamp = 1e-6
			name_bits = ['atyp','dms','dls','lNacc']
			name = '%s%s' %(name_bits[CONV],today)
				

			
			basic_string = '%s main.py' % PYTHON_VER# 
			basic_string2 = 'CURRENT_TEMPLATE=%s gcan=0 nshift=%d nspeed=3 nslope=14 fast=%.2f ra=%.2f gnmda=%e kasv=0 na_shift=%.2f na_hshift=%.2f girk=%.2f control=%d' %(paint,0,3,2, 0e-6,2,0,25*(1-TOG),(M)*BALANCED) # K-ATP provides ~ 1 additional conductance # lower girk for 'in vitro'
			
			if not CONV:
				basic_string2 = 'CURRENT_TEMPLATE=%s gcan=0 nshift=%d nspeed=%.2f nslope=12 fast=%.2f ra=%.2f gnmda=%e kasv=0 na_shift=%.2f na_hshift=%.2f girk=%.2f control=%d' %(paint,0,2, 1,12, 0e-6,0,0,3+3*BALANCED,M) # K-ATP provides ~ 1 additional conductance # lower girk for 'in vitro'
				if MORPHO=='KomandontovTemplate.hoc':
					MORPHO = 'KomandontovTemplate_2branch.hoc'

			atypstring = 'aiscor=%.2f ais_na=%d ais_k=45 fchip=0.38 kchip=0.62 glk=2 gkhh=%.2f gbk=0.0 ghcn=0.01 gcal=%e gnahh=%d slow=%.2f gcat=0 gkca=%.2f glna=%.2f gkerg=%.2f capump=0.2 gkatp=0.0 gkm=%.3f gka=0.75' %(0.0,50,1.5,1,5,0.05,0.05*OFF,4,0.15*OFF,(0.7)*OFF)#,40*K) # dynamic
						
			if CONV:
				convstring = 'aiscor=%.2f ais_na=%d gcal=%.2f gkm=0.5 gkhh=8 gbk=0 local=1 glk=%.2f capump=1.25 meta=0.06 skatp=%.2f dense=%d kmatp=2 dcicr=0.05 cicrtog=%.1f' % (1,60,2,7-rands[0], 0.05,2, 0.6) # K=1 gives the better response gKL+1 for AmmTX to restore 'window' current
				if CONV == 1: #	DMS																														# no touch!
					convstring+= ' glna=%.2f gnahh=20 gkatp=0 fchip=1 kchip=0 gkerg=0.1 tfast=%d taperkv4=0 catbuff=%.2f coup=%.2f slow=%.3f gcat=%.2f gkca=%.2f gka=%.2f dsk=0.25 dca=0.4 ghcn=%.2f' % (4+rands[0],75+50*rands[1],0.3,0.5,0,(0.2+0.1*rands[3]),(1-0*BALANCED)*(0.75+0.75*rands[4]),TOG*(0.5+0.3*rands[5]),0.3+0.2*rands[7]) #.3 may still be too high # replace with something proportional to M or K to vary
				elif CONV == 2:	 # DLS
                    #                                                													           					#	glna gna tsk lsk nas gcat gsk ka hcn
					convstring+=' glna=%.2f gnahh=%d gkatp=0 fchip=1 kchip=0 gkerg=0.1 tfast=%d taperkv4=0 catbuff=%.2f tcicr=%.2f tausk=10 coup=0 slow=0 gcat=%.3f gkca=%.2f gka=%.2f dsk=0.7 dca=0.4 ghcn=%.2f' % (3.5+rands[0],20 ,25+50*rands[1] ,0.35,1,(0.3+0.2*rands[3]) ,(1-0*BALANCED)*(0.6+0.4*rands[4]),TOG*(0.3+0.2*rands[5]),0.3+0.1*rands[7]) # this one is kind of broken atm
				elif CONV == 3:	# lNAcc
					convstring+= ' glna=%.2f gnahh=20 gkatp=0 fchip=1 kchip=0 gkerg=0.1 tfast=%d taperkv4=0 catbuff=%.2f coup=%.2f slow=%.3f gcat=%.2f gkca=%.2f gka=%.2f dsk=0.25 dca=0.4 ghcn=%.2f' % (4+rands[0],75+50*rands[1],0.3,0.5,0,(0.2+0.1*rands[3]),(1-0*BALANCED)*(0.75+0.75*rands[4]),TOG*(0.5+0.3*rands[5]),0.3+0.2*rands[7]) #.3 may still be too high # replace with something proportional to M or K to vary

			name2 = '%.2f_%.2f' % (M,K)#% (i,j)

			#runstring = 'GABARUN=1 idur=8000 idel=1000 GRAPH=0 custom_name=%s DOCUMENT=0'	% (name2)
			noise_string = 'gabaamp=0 fon=100 foff=100 NMDAFUNC=1 nmdaamp=0 knmda=3 rtype=nexp won=100 woff=9900'  # 5 3
			
			
			blah=3
			regtypes = ['gabaa','gabab','gabaa','gabab']
			try:
				regtype = regtypes[blah]
				if blah > 1:
					number=5*K
					if regtype == 'gabaa':
						number*=20
				else:
					number=1
			except:
				regtype = 'gabaa'
				number=1
				freq = 50
				
				
			if regtype == 'gabab':
				mul = 0.01
				freq=5*K
				mul = 0#mul # the difference in activation time, reversal potential is huge
			else:
				mul =0.1
				freq=100*K
				mul = 0


			runstring = 'GABARUN=1 iamp=%e GRAPH=0 custom_name=%s DOCUMENT=0'	% (iamp, name2)			
			#runstring = 'DINGRUN=1 iamp=%e GRAPH=0 custom_name=%s DOCUMENT=0'	% (iamp, name2)			

			if BALANCED:
				noise_string =''
				#runstring += ' DOCUMENT=0 DRAW=%d DISTAL=%d SUMMATE=0 UNIFORM=0 DISTRIBUTE=1 HISTO=1 idur=12000 idel=0 won=500 woff=5500 gabaamp=%e nmdaamp=%e ampa_ratio=%e fon=%d foff=%d regamp=%e NMDAFUNC=1 rtype=nexp number=%d freq=200 regtype=%s' %(DRAW,DISTAL,8e-3, 2.0e-4,0.5, 50 ,50,(mul*0.1*(K+1)), number, regtype )
				runstring += ' DOCUMENT=0 DRAW=%d DISTAL=%d SUMMATE=0 UNIFORM=0 DISTRIBUTE=1 HISTO=1 nprint=50 idur=2000 idel=20000 won=500 woff=6500 gabaamp=%e nmdaamp=%e ampa_ratio=%e fon=%d foff=%d regamp=%e NMDAFUNC=1 rtype=nexp number=%d freq=%d regtype=%s' %(DRAW,DISTAL,1e-3, 2.0e-5*(0.75+0.25*rands[6]),0.5, 1600 ,1600,(mul*0.1), number,freq, regtype )

			else:
				runstring += ' DRAW=%d idur=2000 idel=4000 DISTRIBUTE=0 SUMMATE=%d nprint=100' % (DRAW,SUMMATE)
					
			if CONV:
				if SLOW:
					system('%s %s %s MORPHO=%s %s %s %s' % (basic_string, name, basic_string2,MORPHO, convstring, noise_string, runstring))
				else:
					tasks.append('%s %s %s MORPHO=%s %s %s %s' % (basic_string, name, basic_string2,MORPHO, convstring, noise_string, runstring))
			else:
				if SLOW:
					system('%s %s %s MORPHO=%s %s %s %s' % (basic_string, name, basic_string2,MORPHO, atypstring, noise_string, runstring))
				else:
					tasks.append('%s %s %s MORPHO=%s %s %s %s' % (basic_string, name, basic_string2,MORPHO, atypstring, noise_string, runstring))
		
			

fp.close()
MAX=48 # limited by memory, diminishing returns over ncores # check mem usage of single run.
if PRC:
	MAX = 2
if RUN:
	ACTIVE=0
	if len(tasks) == 1:
		os.system('%s' % tasks[0])
	else :
		active=[]
		for things in tasks:	
			if ACTIVE >= MAX:
				ACTIVE=0
				#print(things)
				while any(x.is_alive() for x in active): # check if threads are running every now and then
					sleep(5)  # this is all kludgy, use multiprocessing next time
				t = Thread(target=os.system,args=(str(things),))
				t.start()
				active=[t]
				ACTIVE+=1
			else:
				#print(things)
				#quit()

				t = Thread(target=os.system,args=(str(things),))
				t.start()
				active.append(t)
				ACTIVE+=1


if len(tasks) > 1:
	while any(x.is_alive() for x in active):
		sleep(5) # use 
		

#os.system('%s %s/.' %(__file__,path))
os.system('mv *%s*.* %s/.' % (today, path))

"""
os.system('cp ParaScript_NMDA.py %s/.' % (path))
os.system('cp NaGoldfarb.mod %s/.' % (path))
os.system('cp NaMarkov.mod %s/.' % (path))
os.system('cp %s %s/.' %(paint,path))"""