//--------------------------------------------------------------------
// Simulation of Phasic Activity
// Synapses Distributet over all apical dendrites
// synaptic activity starts after 100s
//---------------------------------------------------------------------

// ------------Definition of Parameters -------------------------------
// --------------------------------------------------------------------

// Model specific parameters
duration = 200000   // of the recording in ms
synact_start = 100000
synact_dur = 100000
ndend=107         // Number of dendrites

// Determining Parameters GABA ---------------------------
G_GABA = 0.000169   // synaptic weight according to miniature events 
DECAY_GABA = 37
P_GABA = 0.18
ngabasyn = 128 
gninputs = 2 // number of inputs per synapse
             // 2.13 Hz is the experimentally determined Freq of GABAergic inputs


gGABA_Steps = 5                           // 4 different Conductances + baseline
objref gGABA_List
gGABA_List = new Vector(gGABA_Steps)
// manually put desired G-GABA_Values in List 
  gGABA_List.x[0] = G_GABA * 0            
  gGABA_List.x[1] = G_GABA * 1    
  gGABA_List.x[2] = G_GABA * 2   
  gGABA_List.x[3] = G_GABA * 5  
  gGABA_List.x[4] = G_GABA * 10   

// Definition of various runtime parameters --------------------------

   lenghtoutputvec = 12000  // Number of Lines for output (< 32000 for Excel-Figures)



tstop = duration   // Duration
v_init = -70   // Initial voltage
dt = 0.025       // Step Interval in ms

// seed Values for random generator
seed_GABA = 1  // seed for random function


// ------------Procedures and Functions -------------------------------
// --------------------------------------------------------------------

// Function MakeShort ---------------------------------------//
// Inputs: $1 Objref to Inputvector                          //
//         $2 Objref to Outoutvector                         //
//         lenoutvec  desired lendth of Outputvector         //
//                                                           //
// Reduce Inputvec to Outputvev by averaging n elements      //
// n (reducing factor) = floor(Inputvec.size() / lenoutvec)  //
// ----------------------------------------------------------//

obfunc MakeShort() {local i, n

  n = int($o1.size()/$3)
  $o2.resize($3)
  for i=0, $3-1 {
    $o2.x[i] = $o1.mean(i*n, (i+1)*n-1)
  }
  return $o2
}   //  End of function



// ---------Definition of objects -------------------------------------
// --------------------------------------------------------------------


// Objects for Synapses ---------------------------------------------------------
objref gabasyn[ngabasyn]                            // Definition of synapse objects

// random function for localization of synapses
objref rand_gaba_loc

// random function for localization of synapses in which dendrite
objref rand_gaba_dend

// random function for synapses parameters
objref rand_gaba_t

// definition of Vectors for Gaba-Stimulation (t_vec = timestamps t_vecr = sorted timestamps, g_vec = rel conductance)
objref gabastim[ngabasyn], gaba_t_vec[ngabasyn], gaba_t_vecr[ngabasyn], synpulsegaba[ngabasyn]


// Define vectors to link modelled parameter output ---------------------------------
objref timevec, voltvec, clivec                                           // vectors linked to parameter-pointers
objref shorttimevec, shortvoltvec, shortclivec                            // shorter Vectors for output

// Matrix for output 0 = time, 1 = Voltage, 2 = Cli
objref Outmatrix

// Define Name of Output-File
strdef OutFileName

// Define Output File
objref OutFile


// Generate vectors and matrices -------------------------------------
voltvec = new Vector()
timevec = new Vector()
clivec = new Vector()
shortvoltvec = new Vector()
shorttimevec = new Vector()
shortclivec = new Vector()

Outmatrix = new Matrix()



// Start of Input generation -------------------------------------------

// Initialize Random Functions -----------
rand_gaba_loc = new Random(seed_GABA+2)
rand_gaba_dend = new Random(seed_GABA+4)
rand_gaba_t = new Random(seed_GABA+6)

//Define properties of random Function
rand_gaba_t.uniform(0, synact_dur)

// generate Vectors --- (gniputs, aninputs defines number of inputs per synapse) ------
for i = 0, ngabasyn-1 {
  gaba_t_vec[i] = new Vector(gninputs)
  gaba_t_vecr[i] = new Vector(gninputs)
}


// Distribute GABA synapses -----------------------------------------------------------
for k=0, ngabasyn-1 {
    pos = rand_gaba_loc.uniform(0,ndend-1)
    pos2 = rand_gaba_dend.uniform (0.0001, 0.999)
    apic[pos]{
      gabasyn[k] = new gaba(pos2)
      gabasyn[k].tau1 = 0.1
      gabasyn[k].tau2 = DECAY_GABA
      gabasyn[k].P = P_GABA
      }
    }

                                         

//-- Simulation starts here -----------------------------------------------------------------
//-------------------------------------------------------------------------------------------

//-- Outer Loop Variation of gGABA -------------------

gGABA_Step = 0

while (gGABA_Step < gGABA_Steps){
  
    printf("Simlation F(PSC) = %.2g, Sequence %g of %g - g_GABA = %g \n", (gninputs*ndend/100), (gGABA_Step+1), (gGABA_Steps), gGABA_List.x[gGABA_Step])

    // 2a. Generate timestamps/conductances for GABA synapses --------------------------------------
    for f=0, ngabasyn-1 {
      for i=0, gninputs-1 {
          t = rand_gaba_t.repick()
          gaba_t_vec[f].x[i]=t + synact_start
      }
    }

    for f=0, ngabasyn-1 {
      gaba_t_vecr[f] = gaba_t_vec[f].sort()
    }


  // 3. generate Vecstim-vectors from the sorted timestamp-vectors -------------------------------
      for i=0, ngabasyn-1 {
        gabastim[i] = new VecStim()
        gabastim[i].play(gaba_t_vecr[i])    // GABA stimulator
      }                                               


  // 4. Play the Vecstim objects to the synapses ---------------------------------------------
      for i=0, ngabasyn-1 {
        synpulsegaba[i] = new NetCon(gabastim[i], gabasyn[i], 0, 0, gGABA_List.x[gGABA_Step])
      }                                                  // GABA NetCon


  // 5. Link Objects to Output-Vectors -----------------------------------
        timevec.record(&t)   // Time vector
        voltvec.record(&v(.5)) // Volt vector in soma
        clivec.record(&soma.cli(0.5))
 

  // 6. Run Simulation --------------------------------------------------------

     run()


  // 7. Put Data in Output Vector ------------------------------------------------------  
   
 
     MakeShort(timevec, shorttimevec, lenghtoutputvec)
     Outmatrix.resize(shorttimevec.size()+1, 3)
     Outmatrix.setcol(0, shorttimevec)
        
     MakeShort(voltvec, shortvoltvec, lenghtoutputvec)
     Outmatrix.setcol(1 , shortvoltvec)


     MakeShort(clivec, shortclivec, lenghtoutputvec)
     Outmatrix.setcol(2, shortclivec)

     // Save the Data --------------------------------------------------------------------
     OutFile = new File()
     if (gninputs <= 10) {
        sprint(OutFileName, "Result_Phasic-GABA-currents-2.17Hz-GABA=%g.asc",gGABA_List.x[gGABA_Step]*1000)
     }else{
         sprint(OutFileName, "Result_Phasic-GABA-currents-10Hz-GABA=%g.asc",gGABA_List.x[gGABA_Step]*1000)
     }
     OutFile.wopen(OutFileName) 
     Outmatrix.fprint(OutFile, "\t%g")     
     OutFile.close

     printf("-finished \n")

  // Goto next gGABA
     gGABA_Step+=1
} // End of outer loop
printf("Simulation complete \n")