Cortical model with reinforcement learning drives realistic virtual arm (Dura-Bernal et al 2015)

 Download zip file   Auto-launch 
Help downloading and running models
Accession:183014
We developed a 3-layer sensorimotor cortical network of consisting of 704 spiking model-neurons, including excitatory, fast-spiking and low-threshold spiking interneurons. Neurons were interconnected with AMPA/NMDA, and GABAA synapses. We trained our model using spike-timing-dependent reinforcement learning to control a virtual musculoskeletal human arm, with realistic anatomical and biomechanical properties, to reach a target. Virtual arm position was used to simultaneously control a robot arm via a network interface.
Reference:
1 . Dura-Bernal S, Zhou X, Neymotin SA, Przekwas A, Francis JT, Lytton WW (2015) Cortical Spiking Network Interfaced with Virtual Musculoskeletal Arm and Robotic Arm. Front Neurorobot 9:13 [PubMed]
2 . Dura-Bernal S, Li K, Neymotin SA, Francis JT, Principe JC, Lytton WW (2016) Restoring behavior via inverse neurocontroller in a lesioned cortical spiking model driving a virtual arm. Front. Neurosci. Neuroprosthetics 10:28
Model Information (Click on a link to find other models with that property)
Model Type: Realistic Network;
Brain Region(s)/Organism:
Cell Type(s): Neocortex M1 pyramidal pyramidal tract L5B cell; Neocortex M1 pyramidal intratelencephalic L2-5 cell; Neocortex M1 interneuron basket PV cell; Neocortex fast spiking (FS) interneuron; Neostriatum fast spiking interneuron; Neocortex spiking regular (RS) neuron; Neocortex spiking low threshold (LTS) neuron;
Channel(s):
Gap Junctions:
Receptor(s): GabaA; AMPA; NMDA;
Gene(s):
Transmitter(s): Gaba; Glutamate;
Simulation Environment: NEURON; Python (web link to model);
Model Concept(s): Synaptic Plasticity; Learning; Reinforcement Learning; STDP; Reward-modulated STDP; Sensory processing; Motor control;
Implementer(s): Neymotin, Sam [samn at neurosim.downstate.edu]; Dura, Salvador [ salvadordura at gmail.com];
Search NeuronDB for information about:  Neocortex M1 pyramidal intratelencephalic L2-5 cell; Neocortex M1 pyramidal pyramidal tract L5B cell; Neocortex M1 interneuron basket PV cell; GabaA; AMPA; NMDA; Gaba; Glutamate;
/
arm2dms_modeldb
mod
drspk.mod *
infot.mod *
intf6.mod *
intfsw.mod *
misc.mod *
mySTDP.mod
nsloc.mod
nstim.mod *
place.mod *
stats.mod *
updown.mod *
vecst.mod *
parameters.multi
                            
: $Id: intfsw.mod,v 1.50 2009/02/26 18:24:34 samn Exp $ 

:* COMMENT
COMMENT
this file contains functions/utilities for computing the network/graph-theoretic
properties of INTF and other networks represented as adjacency lists
:** clustering coefficient functions

FUNCTION GetCCR(adj,outvec,[startid,endid,subsamp]) gets the clustering coefficient on a range
         of cells
FUNCTION GetCC -- gets clustering coefficient
FUNCTION GetCCSubPop -- get the clustering coefficient between 'sub-populations' of vertices

:** path length related functions

FUNCTION GetPathR -- gets path length on a range of cells at a time
FUNCTION GetWPath -- gets weighted path length , which may be weighted by synaptic weights &
         delays
FUNCTION GetPairDist -- computes distances between all pairs of vertices, self->self distance==
           distance of shortest loop
FUNCTION GetPathSubPop -- computes path lengths between sub-populations
FUNCTION GetLoopLength -- computes distance to loop back to each node
FUNCTION GetPathEV -- gets path length
FUNCTION CountNeighborsR -- counts the # of neighbors/outputs of a specified degree on a range
         of cells

:** miscellaneous functions
FUNCTION GetRecurCount -- counts # of recurrent connections
FUNCTION Factorial -- computes factorial, if input is too large uses approximation
FUNCTION perm - count # of permutations from set of N elements with R selections
ENDCOMMENT

:* NEURON blocks
NEURON {
  SUFFIX intfsw
  GLOBAL INSTALLED
  GLOBAL verbose
  GLOBAL edgefuncid : edge-weight-function for GetWPath,0=weightdelaydist,1=weightdist,2=delaydist
}

PARAMETER {
  INSTALLED=0
  verbose=0
  edgefuncid=0
}

VERBATIM
#include "misc.h"

typedef struct {
  int isz;
  int imaxsz;
  double* p;  
} myvec;

myvec* allocmyvec (int maxsz){
  myvec* pv = (myvec*)malloc(sizeof(myvec));
  if(!pv) return 0x0;
  pv->isz=0;
  pv->imaxsz=maxsz;
  pv->p=(double*)malloc(sizeof(double)*maxsz);
  if(!pv->p) { free(pv); return 0x0; }
  return pv;
}

int freemyvec (myvec** pps) {
  if(!pps || !pps[0]) return 0;
  myvec* ps = pps[0];
  if(ps->p)free(ps->p);
  free(ps);
  pps[0]=0x0;
  return 1;
}

double popmyvec (myvec* pv) {
  if(pv->isz<1) {
    printf("popmyvec ERRA: can't pop empty stack!\n");
    return 0.0;
  }
  double d = pv->p[pv->isz-1]; pv->isz--;
  return d;
}

void popallmyvec (myvec* pv) {
  pv->isz=0;
}

double pushmyvec (myvec* ps,double d) {
  if(ps->isz==ps->imaxsz) {
    printf("pushmyvec realloc\n");
    ps->imaxsz*=2;
    ps->p=(double*)realloc(ps->p,sizeof(double)*ps->imaxsz);
    if(!ps->p){ printf("pushmyvec ERRA: myvec out of memory %d!!\n",ps->imaxsz); return 0.0; }
  }
  ps->p[ps->isz++]=d; 
  return 1.0;  
}

double appendmyvec (myvec* ps,double d) {
  return pushmyvec(ps,d);
}

typedef struct myqnode_ {
  struct myqnode_* pnext;  
  struct myqnode_* pprev;
  int dd;
} myqnode;

myqnode* allocmyqnode() {
  myqnode* p = (myqnode*)malloc(sizeof(myqnode));
  p->pnext=0x0;
  p->pprev=0x0;
  return p;
}

typedef struct {
  myqnode* pfront;
  myqnode* pback;
} myq;

myq* allocmyq() {
  myq* pq = (myq*)malloc(sizeof(myq));
  pq->pfront = pq->pback = 0x0;
  return pq;
}

int freemyq(myq** ppq) {
  myq* pq = *ppq;
  myqnode* ptmp=pq->pback;
  while(pq->pback){
    if(pq->pback->pprev==0x0){
      free(pq->pback);
      pq->pback=0x0;
      pq->pfront=0x0;
      break;
    } else {
      ptmp=pq->pback->pprev;
      free(pq->pback);    
    }
  }
  free(pq);
  ppq[0]=0;
  return 1;
}

int printfrontmyq (myq* pq) {
  if(pq && pq->pfront) {
    printf("front=%d  ",pq->pfront->dd);
    return 1;
  }
  printf("printfrontmyq ERRA: empty front!\n");
  return 0;
}

int printbackmyq (myq* pq) {
  if(pq && pq->pback) {
    printf("back=%d  ",pq->pback->dd);
    return 1;
  }
  printf("printbackmyq ERRA: empty back!\n");
  return 0;
}

int printmyq (myq* pq, int backwards) {
  if(pq){
    int i=0;
    if(backwards){
      myqnode* pnode = pq->pback;
      while(pnode){
        printf("val %d from back = %d\n",i++,pnode->dd);
        pnode = pnode->pprev;
      }
    } else {
      myqnode* pnode = pq->pfront;
      while(pnode){
        printf("val %d from front = %d\n",i++,pnode->dd);
        pnode = pnode->pnext;
      }
    }
    return 1;
  }
  printf("printmyq ERRA: null pointer!\n");
  return 0;
}

int enqmyq (myq* pq,int d) {
  if(pq->pfront==pq->pback) {
    if(!pq->pfront){
      pq->pfront = allocmyqnode();
      pq->pback = pq->pfront;
      pq->pfront->dd=d;
    } else {
      pq->pback = allocmyqnode();
      pq->pback->dd=d;
      pq->pback->pprev = pq->pfront;
      pq->pfront->pnext = pq->pback;
    }
  } else {
    myqnode* pnew = allocmyqnode();
    pnew->dd = d;
    pq->pback->pnext = pnew; 
    pnew->pprev = pq->pback;
    pq->pback = pnew;
  }
  return 1;
}

int emptymyq (myq* pq) {
  if(pq->pfront==0x0) return 1;
  return 0;
}

int deqmyq (myq* pq) {
  if(pq->pfront == pq->pback){
    if(!pq->pfront){
      printf("deqmyq ERRA: can't deq empty q!\n");
      return -1.0;
    } else {
      int d = pq->pfront->dd;
      free(pq->pfront);
      pq->pfront=pq->pback=0x0;
      return d;
    }
  } else {
    myqnode* tmp = pq->pfront;
    int d = tmp->dd;
    pq->pfront = pq->pfront->pnext;
    pq->pfront->pprev = 0x0;
    free(tmp);
    return d;
  }
}

ENDVERBATIM

FUNCTION testmystack () {
VERBATIM
  myvec* pv = allocmyvec(10);
  printf("created stack with sz %d\n",pv->imaxsz);
  int i;
  for(i=0;i<pv->imaxsz;i++) {
    double d = 41.0 * (i%32) + rand()%100;
    printf("pushing %g onto stack of sz %d\n",d,pv->isz);
    pushmyvec(pv,d);
  }
  printf("test stack realloc by pushing 123.0\n");
  pushmyvec(pv,123.0);
  printf("stack now has %d elements, %d maxsz. contents:\n",pv->isz,pv->imaxsz);
  for(i=0;i<pv->isz;i++)printf("s[%d]=%g\n",i,pv->p[i]);
  printf("popping %d elements. contents:\n",pv->isz);
  while(pv->isz){
    double d = popmyvec(pv);
    printf("popped %g, new sz = %d\n",d,pv->isz);
  }
  printf("can't pop stack now, empty test: ");
  popmyvec(pv);
  freemyvec(&pv);
  printf("freed stack\n");
  return 1.0;
ENDVERBATIM
}

FUNCTION testmyq () {
VERBATIM
  myq* pq = allocmyq();
  printf("created q, empty = %d\n",emptymyq(pq));
  printf("enqueing 10 values:\n");
  int i;
  for(i=0;i<10;i++){
    int d = 41 * (i%32) + rand()%252;
    printf("enqueuing %d...",d);
    enqmyq(pq,d);
    printfrontmyq(pq);
    printbackmyq(pq); printf("\n");
  }
  printf("printing q in forwards order:\n");
  printmyq(pq,0);
  printf("printing q in backwards order:\n");
  printmyq(pq,1);
  printf("testing deq:\n");
  while(!emptymyq(pq)){
    printf("b4 deq: ");
    printfrontmyq(pq); 
    printbackmyq(pq); printf("\n");
    int d = deqmyq(pq);
    printf("dequeued %d\n",d);
    printf("after deq: ");
    printfrontmyq(pq); 
    printbackmyq(pq); printf("\n");
  }
  freemyq(&pq);
  printf("freed myq\n");
  return 1.0;
ENDVERBATIM
}

:* utility functions: copynz(), nnmeandbl(), gzmeandbl(), gzmean(), nnmean() 
VERBATIM
//copy values in valarray who's corresponding entry in binarray != 0 into this vector
//copynz(valvec,binvec)
static double copynz (void* vv) {
  double* pV;
  int n = vector_instance_px(vv,&pV) , iCount = 0 , idx=0;
  int iStartIDx = 0, iEndIDx = n - 1;
  if(ifarg(2)){
    iStartIDx = (int)*getarg(1);
    iEndIDx = (int) *getarg(2);
  }
  if(iEndIDx < iStartIDx || iStartIDx >= n || iEndIDx >= n
                         || iStartIDx<0    || iEndIDx < 0){
    printf("copynz ERRA: invalid indices start=%d end=%d size=%d\n",iStartIDx,iEndIDx,n);
    return -1.0;
  }

  double* pVal,*pBin;

  if(vector_arg_px(1,&pVal)!=n || vector_arg_px(2,&pBin)!=n){
    printf("copynz ERRB: vec args must have size %d!",n);
    return 0.0;
  }

  int iOutSz = 0;
  for(idx=iStartIDx;idx<=iEndIDx;idx++){
    if(pBin[idx]){
      pV[iOutSz++]=pVal[idx];
    }
  }

  vector_resize(pV,iOutSz);

  return (double)iOutSz;
}

//** nnmeandbl()
static double nnmeandbl (double* p,int iStartIDX,int iEndIDX) {
  int iCount=0,idx=0;
  double dSum = 0.0;
  for(idx=iStartIDX;idx<=iEndIDX;idx++){
    if(p[idx]>=0.0){
      dSum+=p[idx];
      iCount++;
    }
  }
  if(iCount>0) return dSum / iCount;
  return -1.0;
} 

//** gzmeandbl()
static double gzmeandbl (double* p,int iStartIDX,int iEndIDX) {
  int iCount=0,idx=0;
  double dSum = 0.0;
  for(idx=iStartIDX;idx<=iEndIDX;idx++){
    if(p[idx]>0.0){
      dSum+=p[idx];
      iCount++;
    }
  }
  if(iCount>0) return dSum / iCount;
  return -1.0;
}

//** gzmean() mean for elements in Vector > 0.0
static double gzmean (void* vv) {
  double* pV;
  int n = vector_instance_px(vv,&pV) , iCount = 0 , idx=0;
  int iStartIDx = 0, iEndIDx = n - 1;
  if(ifarg(2)){
    iStartIDx = (int)*getarg(1);
    iEndIDx = (int) *getarg(2);
  }
  if(iEndIDx < iStartIDx || iStartIDx >= n || iEndIDx >= n
                         || iStartIDx<0    || iEndIDx < 0){
    printf("gzmean ERRA: invalid indices start=%d end=%d size=%d\n",iStartIDx,iEndIDx,n);
    return -1.0;
  }
  return gzmeandbl(pV,iStartIDx,iEndIDx);
}


//** nnmean() mean for elements in Vector >= 0.0
static double nnmean (void* vv) {
  double* pV;
  int n = vector_instance_px(vv,&pV) , iCount = 0 , idx=0;
  int iStartIDx = 0, iEndIDx = n - 1;
  if(ifarg(2)){
    iStartIDx = (int)*getarg(1);
    iEndIDx = (int) *getarg(2);
  }
  if(iEndIDx < iStartIDx || iStartIDx >= n || iEndIDx >= n
                         || iStartIDx<0    || iEndIDx < 0){
    printf("nnmean ERRA: invalid indices start=%d end=%d size=%d\n",iStartIDx,iEndIDx,n);
    return -1.0;
  }
  return nnmeandbl(pV,iStartIDx,iEndIDx);
}
ENDVERBATIM

:* GetCCR(adj,outvec,[startid,endid,subsamp]) 
FUNCTION GetCCR () {
  VERBATIM
  ListVec* pList = AllocListVec(*hoc_objgetarg(1));
  if(!pList){
    printf("GetCC ERRA: problem initializing first arg!\n");
    return 0.0;
  }

  int iCells = pList->isz;
  if(iCells<2){
    printf("GetCC ERRB: size of List < 2 !\n");
    FreeListVec(&pList);
    return 0.0;
  }

  double** pLV = pList->pv;
  int* pLen = pList->plen;

  //init vector of distances to each cell , 0 == no path found
  int* pNeighbors = (int*)calloc(iCells,sizeof(int));
  int i = 0, iNeighbors = 0;
  if(!pNeighbors){
    printf("GetCCR ERRE: out of memory!\n");
    FreeListVec(&pList);
    return 0.0;
  }  

  //init vector of avg distances to each cell , 0 == no path found
  double* pCC; 
  int iVecSz = vector_arg_px(2,&pCC);
  if(!pCC || iVecSz < iCells){
    printf("GetCCR ERRE: arg 2 must be a Vector with size %d\n",iCells);
    FreeListVec(&pList);
    return 0.0;
  }  
  memset(pCC,0,sizeof(double)*iVecSz);//init to 0

  //start/end id of cells to find path to
  int iStartID = ifarg(3) ? (int)*getarg(3) : 0,
      iEndID = ifarg(4) ? (int)*getarg(4) : iCells - 1;

  if(iStartID < 0 || iStartID >= iCells ||
     iEndID < 0 || iEndID >= iCells ||
     iStartID >= iEndID){
       printf("GetCCR ERRH: invalid ids start=%d end=%d numcells=%d\n",iStartID,iEndID,iCells);
       FreeListVec(&pList);
       free(pNeighbors);
       return 0.0;
  }

  double dSubsamp = ifarg(5)?*getarg(5):1.0;
  if(dSubsamp<0.0 || dSubsamp>1.0){
    printf("GetCCR ERRH: invalid subsamp = %g , must be btwn 0 and 1\n",dSubsamp);
    FreeListVec(&pList);
    free(pNeighbors);
    return 0.0;
  }

  unsigned int iSeed = ifarg(7)?(unsigned int)*getarg(7):INT_MAX-109754;

  double* pUse = 0; 
  
  if(dSubsamp<1.0){ //if using only a fraction of the cells
     pUse = (double*)malloc(iCells*sizeof(double));
     mcell_ran4(&iSeed, pUse, iCells, 1.0);
  }

  //get id of cell to find paths from
  int myID;

  int* pNeighborID = (int*)calloc(iCells,sizeof(int));

  if( verbose > 0 ) printf("searching from id: ");

  for(myID=0;myID<iCells;myID++) pCC[myID]=-1.0; //set invalid

  for(myID=iStartID;myID<=iEndID;myID++){

    if(verbose > 0 && myID%1000==0)printf("%d ",myID);

    //only use dSubSamp fraction of cells, skip rest
    if(pUse && pUse[myID]>=dSubsamp) continue;

    int idx = 0, youID = 0, youKidID=0 , iNeighbors = 0;

    //mark neighbors of distance == 1
    for(idx=0;idx<pLen[myID];idx++){
      youID = pLV[myID][idx];
      if(youID>=iStartID && youID<=iEndID){
        pNeighbors[youID]=1;      
        pNeighborID[iNeighbors++]=youID;
      }
    }

    if(iNeighbors < 2){
      for(i=0;i<iNeighbors;i++)pNeighbors[pNeighborID[i]]=0;
      continue;
    }

    int iConns = 0 ; 
  
    //this checks # of connections between neighbors of node
    for(i=0;i<iNeighbors;i++){
      if(!pNeighbors[pNeighborID[i]])continue;
      youID=pNeighborID[i];
      for(idx=0;idx<pLen[youID];idx++){
        youKidID=pLV[youID][idx];
        if(youKidID >= iStartID && youKidID <= iEndID && pNeighbors[youKidID]){
          iConns++;
        }
      }
    }
    pCC[myID]=(double)iConns/((double)iNeighbors*(iNeighbors-1));
    for(i=0;i<iNeighbors;i++)pNeighbors[pNeighborID[i]]=0;
  }
 
  free(pNeighborID);
  free(pNeighbors);
  FreeListVec(&pList);
  if(pUse)free(pUse);

  if( verbose > 0 ) printf("\n");

  return  1.0;
  ENDVERBATIM
}

:* usage GetCentrality(adjlist,outvec)
: based on code from http://www.inf.uni-konstanz.de/algo/publications/b-fabc-01.pdf
: and python networkx centrality.py implementation (brandes betweenness centrality)
FUNCTION GetCentrality () {
  VERBATIM

  ListVec* pList = AllocListVec(*hoc_objgetarg(1));
  if(!pList){
    printf("GetCentrality ERRA: problem initializing first arg!\n");
    return 0.0;
  }

  int iCells = pList->isz;
  if(iCells<2){
    printf("GetCentrality ERRB: size of List < 2 !\n");
    FreeListVec(&pList);
    return 0.0;
  }

  double** pLV = pList->pv;
  int* pLen = pList->plen;

  //init vector of avg distances to each cell , 0 == no path found
  double* pCE; 
  int iVecSz = vector_arg_px(2,&pCE);
  if(!pCE || iVecSz < iCells){
    printf("GetCCR ERRE: arg 2 must be a Vector with size %d\n",iCells);
    FreeListVec(&pList);
    return 0.0;
  }  
  memset(pCE,0,sizeof(double)*iVecSz);//init to 0

  double dSubsamp = ifarg(3)?*getarg(3):1.0;
  if(dSubsamp<0.0 || dSubsamp>1.0){
    printf("GetCCR ERRH: invalid subsamp = %g , must be btwn 0 and 1\n",dSubsamp);
    FreeListVec(&pList);
    return 0.0;
  }

  unsigned int iSeed = ifarg(4)?(unsigned int)*getarg(4):INT_MAX-109754;

  double* pUse = 0; 
  
  if(dSubsamp<1.0){ //if using only a fraction of the cells
     pUse = (double*)malloc(iCells*sizeof(double));
     mcell_ran4(&iSeed, pUse, iCells, 1.0);
  }

  int s,w,T,v,idx;

  myvec* S = allocmyvec(iCells*2);
  myvec** P = (myvec**)malloc(sizeof(myvec*)*iCells);
  myvec* d = allocmyvec(iCells);
  myvec* sigma = allocmyvec(iCells);
  myvec* di = allocmyvec(iCells);
  for(w=0;w<iCells;w++) P[w]=allocmyvec(iCells);
  for(s=0;s<iCells;s++){
    if(verbose && s%100==0) printf("s=%d\n",s);
    S->isz=0;//empty stack    
    for(w=0;w<iCells;w++) P[w]->isz=0;//empty list
    for(T=0;T<iCells;T++) sigma->p[T]=0; sigma->p[s]=1;
    for(T=0;T<iCells;T++) d->p[T]=-1; d->p[s]=0;
    myq* Q = allocmyq();
    enqmyq(Q,s);
    while(!emptymyq(Q)){
      v = deqmyq(Q);
      pushmyvec(S,v);
      for(idx=0;idx<pLen[v];idx++){
        w = (int) pLV[v][idx];
        if(d->p[w]<0){
          enqmyq(Q,w);
          d->p[w] = d->p[v] + 1;
        }
        if(d->p[w] == d->p[v] + 1){
          sigma->p[w] = sigma->p[w] + sigma->p[v];
          appendmyvec(P[w],v);
        }
      }
    }
    freemyq(&Q);
    for(v=0;v<iCells;v++) di->p[v]=0;
    while(S->isz){
      w = popmyvec(S);
      for(idx=0;idx<P[w]->isz;idx++){
        v=P[w]->p[idx];
        di->p[v] = di->p[v] + (sigma->p[v]/sigma->p[w])*(1.0+di->p[w]);
      }
      if(w!=s) pCE[w] = pCE[w] + di->p[w];
    }
  }

  int N = 0;
  for(s=0;s<iCells;s++) if(pLen[s]) N++;
  if(N>2){
    double scale = 1.0/( (N-1.0)*(N-2.0) );
    for(v=0;v<iCells;v++) if(pLen[v]) pCE[v] *= scale;
  }
  
CEFREE:
  freemyvec(&S);
  for(w=0;w<iCells;w++) freemyvec(&P[w]);
  free(P);
  freemyvec(&d);
  freemyvec(&sigma);
  freemyvec(&di);
  if(pUse)free(pUse);  
  return 1.0;

  ENDVERBATIM
}

:* usage GetCC(adjlist,myid,[startid,endid])
: adjlist == list of vectors specifying connectivity - adjacency list : from row -> to entry in column
: myid == id of cell to get clustering coefficient for
: startid == min id of cells search can terminate on or go through
: endid   == max  '    '   '  '   '  '  '  '  ' '  '  '  '  '  ' 
FUNCTION GetCC () {
  VERBATIM
  ListVec* pList = AllocListVec(*hoc_objgetarg(1));
  if(!pList){
    printf("GetCC ERRA: problem initializing first arg!\n");
    return -1.0;
  }

  int iCells = pList->isz;
  if(iCells<2){
    printf("GetCC ERRB: size of List < 2 !\n");
    FreeListVec(&pList);
    return -1.0;
  }

  double** pLV = pList->pv;
  int* pLen = pList->plen;

  //init vector of distances to each cell , 0 == no path found
  int* pNeighbors = (int*)calloc(iCells,sizeof(int));
  int i = 0, iNeighbors = 0;
  if(!pNeighbors){
    printf("GetCC ERRE: out of memory!\n");
    FreeListVec(&pList);
    return -1.0;
  }  

  //get id of cell to find paths from
  int myID = (int) *getarg(2);
  if(myID < 0 || myID >= iCells){
    printf("GetCC ERRF: invalid id = %d\n",myID);
    FreeListVec(&pList);
    free(pNeighbors);
    return -1.0;
  }

  //start/end id of cells to find path to
  int iStartID = ifarg(3) ? (int)*getarg(3) : 0,
      iEndID = ifarg(4) ? (int)*getarg(4) : iCells - 1;

  if(iStartID < 0 || iStartID >= iCells ||
     iEndID < 0 || iEndID >= iCells ||
     iStartID >= iEndID){
       printf("GetCC ERRH: invalid ids start=%d end=%d numcells=%d\n",iStartID,iEndID,iCells);
       FreeListVec(&pList);
       free(pNeighbors);
       return -1.0;
     }

  int idx = 0, iDist = 1 , youID = 0, youKidID=0;

  int* pNeighborID = (int*)calloc(iCells,sizeof(int));

  //mark neighbors of distance == 1
  for(idx=0;idx<pLen[myID];idx++){
    youID = pLV[myID][idx];
    if(youID>=iStartID && youID<=iEndID){
      pNeighbors[youID]=1;      
      pNeighborID[iNeighbors++]=youID;
    }
  }

  if(iNeighbors < 2){
    FreeListVec(&pList);
    free(pNeighbors);
    return -1.0;
  }

  int iConns = 0; 

  //this checks # of connections between neighbors of node starting from
  for(i=0;i<iNeighbors;i++){
    if(!pNeighbors[pNeighborID[i]])continue;
    youID=pNeighborID[i];
    for(idx=0;idx<pLen[youID];idx++){
      youKidID=pLV[youID][idx];
      if(youKidID >= iStartID && youKidID <= iEndID && pNeighbors[youKidID]){
        iConns++;
      }
    }
  }
 
  free(pNeighborID);
  free(pNeighbors);
  FreeListVec(&pList);

  return  (double)iConns/((double)iNeighbors*(iNeighbors-1));
  
  ENDVERBATIM
}

:* usage CountNeighborsR(adjlist,outvec,startid,endid,degree,subsamp])
: adjlist == list of vectors specifying connectivity - adjacency list : from row -> to entry in column
: outvec == vector of distances
: startid == min id of cells search can terminate on or go through
: endid   == max  '    '   '  '   '  '  '  '  ' '  '  '  '  '  ' 
: degree == distance of neighbors -- counts # of neighbors of EXACT distance specified ONLY
: subsamp == specifies fraction btwn 0 and 1 of starting nodes to search
FUNCTION CountNeighborsR () {
  VERBATIM
  ListVec* pList = AllocListVec(*hoc_objgetarg(1));
  if(!pList){
    printf("CountNeighborsR ERRA: problem initializing first arg!\n");
    return 0.0;
  }
 
  int iCells = pList->isz; 
  if(iCells < 2){
    printf("CountNeighborsR ERRB: size of List < 2 !\n");
    FreeListVec(&pList);
    return 0.0;
  }

  double** pLV = pList->pv;
  int* pLen = pList->plen;

  //init vector of avg distances to each cell , 0 == no path found
  double* pVD; 
  int iVecSz = vector_arg_px(2,&pVD) , i = 0;
  if(!pVD || iVecSz < iCells){
    printf("CountNeighborsR ERRE: arg 2 must be a Vector with size %d\n",iCells);
    FreeListVec(&pList);
    return 0.0;
  }  
  memset(pVD,0,sizeof(double)*iVecSz);//init to 0

  //get id of cell to find paths from
  int myID = (int) *getarg(3);
  if(myID < 0 || myID >= iCells){
    printf("CountNeighborsR ERRF: invalid id = %d\n",myID);
    FreeListVec(&pList);
    return 0.0;
  }

  //start/end id of cells to search for neighbors of degree iDist 
  int iStartID = (int)*getarg(3),
      iEndID =   (int)*getarg(4),
      iSearchDegree =    (int)*getarg(5);

  double dSubsamp = ifarg(6)?*getarg(6):1.0;

  unsigned int iSeed = ifarg(7)?(unsigned int)*getarg(7):INT_MAX-109754;

  if(iStartID < 0 || iStartID >= iCells ||
     iEndID < 0 || iEndID >= iCells ||
     iStartID >= iEndID){
       printf("CountNeighborsR ERRH: invalid ids start=%d end=%d numcells=%d\n",iStartID,iEndID,iCells);
       FreeListVec(&pList);
       return 0.0;
     }

  //check search degree
  if(iSearchDegree<=0){
    printf("CountNeighborsR ERRI: invalid searchdegree=%d\n",iSearchDegree);
    FreeListVec(&pList);
    return 0.0;
  }

  //init array of cells/neighbors to check
  int* pCheck = (int*)malloc(sizeof(int)*iCells);
  if(!pCheck){
    printf("CountNeighborsR ERRG: out of memory!\n");
    FreeListVec(&pList);
    return 0.0;
  }

  int iCheckSz = 0, idx = 0, iDist = 1 , youID = 0, youKidID=0, iTmpSz = 0, jdx = 0, iMatches = 0;

  double* pVDTmp = 0, dgzt = 0.0; 
  int* pTmp = 0;
  double* pUse = 0; 
  
  if(dSubsamp<1.0){ //if using only a fraction of the cells
     pUse = (double*)malloc(iCells*sizeof(double));
     mcell_ran4(&iSeed, pUse, iCells, 1.0);
  }

  if( verbose > 0 ) printf("searching from id: ");

  pVDTmp = (double*)calloc(iCells,sizeof(double));
  pTmp = (int*)calloc(iCells,sizeof(int)); 

  for(myID=iStartID;myID<=iEndID;myID++){

    if(verbose > 0 && myID%1000==0)printf("%d ",myID); 

    //only use dSubSamp fraction of cells, skip rest
    if(pUse && pUse[myID]>=dSubsamp) continue;

    iMatches = 0;

    iCheckSz = 0; idx = 0; iDist = 1; youID = 0; youKidID = 0;

    //mark neighbors of distance == 1
    for(idx=0;idx<pLen[myID];idx++){
      youID = pLV[myID][idx];
      if(youID>=iStartID && youID<=iEndID && !pVDTmp[youID]){
        pVDTmp[youID]=(double)iDist;
        pCheck[iCheckSz++]=youID;
      }
    }

    if(iSearchDegree == iDist){
      pVD[myID] = iCheckSz;
      for(idx=0;idx<iCheckSz;idx++) pVDTmp[pCheck[idx]]=0; //reset for next cell
      continue;
    }

    pVDTmp[myID]=1;

    iTmpSz = 0;  jdx=0;

    iDist++;
  
    //this does a breadth-first search but avoids recursion
    while(iCheckSz>0 && iDist<=iSearchDegree){
      iTmpSz = 0;
      for(idx=0;idx<iCheckSz;idx++){
        youID=pCheck[idx];
        for(jdx=0;jdx<pLen[youID];jdx++){
          youKidID=pLV[youID][jdx];
          if(youKidID >= iStartID && youKidID <=iEndID && !pVDTmp[youKidID]){ 
            pTmp[iTmpSz++] = youKidID; //save id of cell to search it's kids on next iteration
            pVDTmp[youKidID]=(double)iDist; //this cell is at iDist away, even if it is also @ a shorter distance
          }
        }
      }
      iCheckSz = iTmpSz;
      
      if(iSearchDegree == iDist){
        pVD[myID] = iCheckSz;
        memset(pVDTmp,0,sizeof(double)*iCells); //reset to 0 for next cell
        break;
      } 

      if(iCheckSz) memcpy(pCheck,pTmp,sizeof(int)*iCheckSz);
      iDist++;
    }
  }

  if(pUse) free(pUse); 
  free(pCheck);
  FreeListVec(&pList);  
  free(pVDTmp); free(pTmp);

  if( verbose > 0 ) printf("\n");

  return 1.0;
  ENDVERBATIM
}

:* utility functions: maxval(), weightdelaydist(), weightdist(), delaydist(), printedgefunc()
VERBATIM
double maxval(double* p,int sz)
{
  double dmax = p[0];
  int i = 1;
  for(;i<sz;i++) if(p[i]>dmax) dmax = p[i];
  return dmax;
}

double weightdelaydist(double w,double d)
{
  if(w < 0)
    return -w/d;
  if(w > 0)
    return d/w;
  return DBL_MAX; // no connection means infinite distance
}

double weightdist(double w,double d)
{
  if(w < 0)
    return -w;
  if(w > 0)
    return 1/w;
  return DBL_MAX; // no connection means infinite distance
}

double delaydist(double w,double d)
{
  return d;
}

void printedgefunc(int id)
{
  switch(id){
    case 0:
     printf("weightdelaydist\n");
     break;
    case 1:
     printf("weightdist\n");
     break;
    case 2:
     printf("delaydist\n");
     break;
    default:
     printf("unknown!\n");
     break;
  }
}

ENDVERBATIM

:* FUNCTION predgefunc()
FUNCTION predgefunc () {
  VERBATIM
  int i;
  if(ifarg(1)){ printf("%d=",(int)*getarg(1)); printedgefunc((int)*getarg(1)); printf("\n"); }    
  else for(i=0;i<3;i++){ printf("%d=",i); printedgefunc(i); printf("\n"); }
  return 0.0;
  ENDVERBATIM
}

:* usage GetWPath(preid,poid,weights,delays,outvec,[subsamp])
: preid == list of presynaptic IDs
: poid == list of postsynaptic IDs
: weights == list of weights, excit > 0 , inhib < 0
: delays == list of delays 
: outvec == vector of distances
: subsamp == only use specified fraction of synapses , optional
FUNCTION GetWPath () {
  VERBATIM

  double* ppre = 0, *ppo = 0, *pwght = 0, *pdel = 0, *pout = 0;
  int iSz,iTmp,i,j,k,l;
  void* voi;

  iSz = vector_arg_px(1,&ppre);

  if(iSz < 1)
  { printf("GetWPath ERRO: invalid size for presynaptic ID Vector (arg 1) %d!\n",iSz);
    return -666.666;
  }

  if( (iTmp=vector_arg_px(2,&ppo)) != iSz)
  { printf("GetWPath ERRA: incorrectly sized postsynaptic ID Vector (arg 2) %d %d!",iSz,iTmp);
    return -666.666;
  }
  if( (iTmp=vector_arg_px(3,&pwght)) != iSz)
  { printf("GetWPath ERRB: incorrectly sized weight Vector (arg 3) %d %d!\n",iSz,iTmp);
    return -666.666;
  }
  if( (iTmp=vector_arg_px(4,&pdel)) != iSz)
  { printf("GetWPath ERRC: incorrectly sized delay Vector (arg 4) %d %d!\n",iSz,iTmp);
    return -666.666;
  }

  int maxid = maxval(ppre,iSz);

  iTmp = maxval(ppo,iSz);
  if(iTmp > maxid) maxid=iTmp;

  voi = vector_arg(5);

  if( (iTmp=vector_arg_px(5,&pout))!= maxid+1 && 0)
  { printf("GetWPath ERRD: incorrectly sized output Vector (arg 5) %d %d!\n",maxid+1,iTmp);
    return -666.666;
  }
  memset(pout,0,sizeof(double)*iTmp);//init to 0

  double (*EdgeFunc)(double,double) = &weightdelaydist;
  int iEdgeFuncID = (int)edgefuncid; 
  if(iEdgeFuncID < 0 || iEdgeFuncID > 2)
  {  printf("GetWPath ERRK: invalid edgedfunc id %d!\n",iEdgeFuncID);
     return -666.666;
  } else if(iEdgeFuncID == 1) EdgeFunc = &weightdist;
    else if(iEdgeFuncID == 2) EdgeFunc = &delaydist;
  if(verbose) printedgefunc(iEdgeFuncID);

 int** adj = (int**) calloc(maxid+1,sizeof(int*));
 if(!adj)
 { printf("GetWPath ERRE: out of memory!\n");
   return -666.666;
 }

 //stores weight of each edge
 //incident from edge is index into pdist
 //incident to edge id is stored in ppo
 double** pdist = (double**) calloc(maxid+1,sizeof(double*));

 int* pcounts = (int*) calloc(maxid+1,sizeof(int));

 //count divergence from each presynaptic cell
 for(i=0;i<iSz;i++)
 { //check for multiple synapses from same source to same target
   if(i+1<iSz && ppre[i]==ppre[i+1] && ppo[i]==ppo[i+1])
   { if(verbose>1) printf("first check double synapse i=%d\n",i);
     while(1)
     { if(i+1>=iSz) break;
       if(ppre[i]!=ppre[i+1] || ppo[i]!=ppo[i+1])
       { //new synapse?
         i--;//move back 1 so get this synapse on next for loop step
         break;
       }
       i++; //move to next synapse
     }      
   }
   pcounts[(int)ppre[i]]++;    //count this one and continue
 }

 //allocate memory for adjacency & distance lists
 for(i=0;i<maxid+1;i++){
   if(pcounts[i]){
     adj[i] = (int*)calloc(pcounts[i],sizeof(int));
     pdist[i] = (double*)calloc(pcounts[i],sizeof(double));
   }
 }

 //index for locations into adjacency lists
 int* pidx = (int*) calloc(maxid+1,sizeof(int));

 //set distance values based on weights and neighbors in adjacency lists based on postsynaptic ids
 for(i=0;i<iSz;i++)
 { int myID = (int)ppre[i];
   if(!pcounts[myID]) continue;//skip cells with 0 divergence
   double dist = EdgeFunc(pwght[i],pdel[i]);
   j=i; //store index of current synapse
   //check for multiple synapses from same source to same target
   if(i+1<iSz && ppre[i]==ppre[i+1] && ppo[i]==ppo[i+1])
   { if(verbose>1) printf("check double syn i=%d\n",i);
     while(1)
     { if(i+1>=iSz) break;
       if(ppre[i]!=ppre[i+1] || ppo[i]!=ppo[i+1])
       { //new synapse?
         i--;//move back 1 so get right synapse on next for loop step
         break;
       }
       if(j!=i) //if didn't count this synapse yet
         dist += EdgeFunc(pwght[i],pdel[i]);
       i++; //move to next synapse to see if it's the same pre,post pair
     }      
   }
   pdist[myID][pidx[myID]] = dist;
   adj[myID][pidx[myID]] = ppo[i];
   pidx[myID]++;
 }

 free(pidx);

 //perform bellman-ford single source shortest path algorithm once for each vertex
 //can improve efficiency by using johnson's algorithm, which uses dijkstra's alg  -- will do later
 double* d = (double*) malloc( (maxid+1)*sizeof(double) ); //distance vector for bellman ford algorithm
 for(i=0;i<=maxid;i++)
 { if(i%100==0) printf("%d ",i);
   if(!pcounts[i])continue;
   for(j=0;j<=maxid;j++) d[j] = DBL_MAX; //initialize distances to +infiniti
   d[i] = 0.0; //distance to self == 0.0
   int changed = 0;
   for(j=0;j<maxid;j++)//apply edge relaxation loop # of vertex-1 times
   { changed=0;
     for(k=0;k<=maxid;k++) //this is just to go thru all edges
     { for(l=0;l<pcounts[k];l++) //go thru all edges of vertex k
       {  if(d[adj[k][l]] > d[k] + pdist[k][l]){//perform edge relaxation
            d[adj[k][l]] = d[k] + pdist[k][l];
            changed=1;
          }
       }
     }
     if(!changed){ if(verbose>1) printf("early term @ j=%d\n",j); break; }
   }

//  int ok = 1;   //make sure no negative cycles
//  for(j=0;j<=maxid && ok;j++)
//  { for(k=0;k<=maxid && ok;k++)
//    { for(l=0;l<pcounts[k];l++)
//      { if( d[adj[k][l]] > d[k] + pdist[k][l] )
//        { ok = 0;
//          break;
//        }
//      }
//    }
//   }
   double avg = 0.0;   //get average distance from vertex i to all other vertices
   int N = 0;
   for(j=0;j<=maxid;j++)
   { if(j!=i && d[j] < DBL_MAX)
     { avg += d[j];
       N++;
     }
   }
   if(N) pout[i] = avg / (double) N;
 }

 free(d);

 //free memory
 free(pcounts);

 for(i=0;i<=maxid;i++){
   if(adj[i]) free(adj[i]);
   if(pdist[i]) free(pdist[i]);
 }

 free(adj);
 free(pdist);

 vector_resize(voi,maxid+1); // pass void* (Vect* ) instead of double*

 return gzmeandbl(pout,0,maxid);

 ENDVERBATIM
}

:* usage GetPathR(adjlist,outvec,[startid,endid,maxdist,subsamp])
: adjlist == list of vectors specifying connectivity - adjacency list : from row -> to entry in column
: outvec == vector of distances
: startid == min id of cells search can terminate on or go through
: endid   == max  '    '   '  '   '  '  '  '  ' '  '  '  '  '  ' 
: maxdist == max # of connections to allow hops over
: subsamp == perform calculation on % of cells, default == 1
FUNCTION GetPathR () {
  VERBATIM
  ListVec* pList = AllocListVec(*hoc_objgetarg(1));
  if(!pList){
    printf("GetPathEV ERRA: problem initializing first arg!\n");
    return 0.0;
  }
 
  int iCells = pList->isz; 
  if(iCells < 2){
    printf("GetPathEV ERRB: size of List < 2 !\n");
    FreeListVec(&pList);
    return 0.0;
  }

  double** pLV = pList->pv;
  int* pLen = pList->plen;

  //init vector of avg distances to each cell , 0 == no path found
  double* pVD; 
  int iVecSz = vector_arg_px(2,&pVD) , i = 0;
  if(!pVD || iVecSz < iCells){
    printf("GetPathEV ERRE: arg 2 must be a Vector with size %d\n",iCells);
    FreeListVec(&pList);
    return 0.0;
  }  
  memset(pVD,0,sizeof(double)*iVecSz);//init to 0

  //start/end id of cells to find path to
  int iStartID = ifarg(3) ? (int)*getarg(3) : 0,
      iEndID = ifarg(4) ? (int)*getarg(4) : iCells - 1,
      iMaxDist = ifarg(5)? (int)*getarg(5): -1;

  double dSubsamp = ifarg(6)?*getarg(6):1.0;

  unsigned int iSeed = ifarg(7)?(unsigned int)*getarg(7):INT_MAX-109754;

  if(iStartID < 0 || iStartID >= iCells ||
     iEndID < 0 || iEndID >= iCells ||
     iStartID >= iEndID){
       printf("GetPathEV ERRH: invalid ids start=%d end=%d numcells=%d\n",iStartID,iEndID,iCells);
       FreeListVec(&pList);
       return 0.0;
     }

  //check max distance
  if(iMaxDist==0){
    printf("GetPathEV ERRI: invalid maxdist=%d\n",iMaxDist);
    FreeListVec(&pList);
    return 0.0;
  }

  //init array of cells/neighbors to check
  int* pCheck;
  pCheck = (int*)malloc(sizeof(int)*iCells);
  if(!pCheck){
    printf("GetPathEV ERRG: out of memory!\n");
    FreeListVec(&pList);
    return 0.0;
  }

  int iCheckSz = 0, idx = 0, iDist = 1 , youID = 0, youKidID=0, iTmpSz = 0, jdx = 0;

  double* pVDTmp = 0, dgzt = 0.0; 
  int* pTmp = 0;
  double* pUse = 0; 
  
  if(dSubsamp<1.0){ //if using only a fraction of the cells
     pUse = (double*)malloc(iCells*sizeof(double));
     mcell_ran4(&iSeed, pUse, iCells, 1.0);
  }

  pTmp = (int*)calloc(iCells,sizeof(int)); 

  if( verbose > 0 ) printf("searching from id: ");

  pVDTmp = (double*)calloc(iCells,sizeof(double));

  int myID;

  for(myID=iStartID;myID<=iEndID;myID++){

    if(verbose > 0 && myID%1000==0)printf("%d ",myID); 

    //only use dSubSamp fraction of cells, skip rest
    if(pUse && pUse[myID]>=dSubsamp) continue;

    iCheckSz = 0; idx = 0; iDist = 1; youID = 0; youKidID = 0;

    pVDTmp[myID]=1;

    //mark neighbors of distance == 1
    for(idx=0;idx<pLen[myID];idx++){
      youID = pLV[myID][idx];
      if(youID>=iStartID && youID<=iEndID && !pVDTmp[youID]){
        pVDTmp[youID]=(double)iDist;
        pCheck[iCheckSz++]=youID;
      }
    }

    iTmpSz = 0;  jdx=0;

    iDist++;
  
    //this does a breadth-first search but avoids recursion
    while(iCheckSz>0 && (iMaxDist==-1 || iDist<=iMaxDist)){
      iTmpSz = 0;
      for(idx=0;idx<iCheckSz;idx++){
        youID=pCheck[idx];
        for(jdx=0;jdx<pLen[youID];jdx++){
          youKidID=pLV[youID][jdx];
          if(youKidID >= iStartID && youKidID <=iEndID && !pVDTmp[youKidID]){ //found a new connection
            pTmp[iTmpSz++] = youKidID; //save id of cell to search it's kids on next iteration
            pVDTmp[youKidID]=(double)iDist;
          }
        }
      }
      iCheckSz = iTmpSz;
      if(iCheckSz) memcpy(pCheck,pTmp,sizeof(int)*iCheckSz);
      iDist++;
    }

    pVDTmp[myID]=0.0; // distance to self == 0.0
    if((dgzt=gzmeandbl(pVDTmp,iStartID,iEndID))>0.0) pVD[myID]=dgzt;// save mean path length for given cell

    memset(pVDTmp,0,sizeof(double)*iCells);
  }
  
  free(pTmp);
  if(pUse) free(pUse); 
  free(pCheck);
  FreeListVec(&pList);  
  free(pVDTmp);

  if( verbose > 0 ) printf("\n");

  return 1.0;
  ENDVERBATIM
}

:* usage GetCCSubPop(adjlist,outvec,startids,endids[,subsamp])
: computes clustering cofficient between sub-populations
: adjlist == list of vectors specifying connectivity - adjacency list : from row -> to entry in column
: outvec == vector of distances
: startid == binary vector of ids of cells to start search from (from population)
: endid   == binary vector of ids of cells to terminate search on (to population)
: subsamp == perform calculation on ratio of cells btwn 0-1, default == 1
FUNCTION GetCCSubPop () {
  VERBATIM
  ListVec* pList = AllocListVec(*hoc_objgetarg(1));
  if(!pList){
    printf("GetCCSubPop ERRA: problem initializing first arg!\n");
    return 0.0;
  }
 
  int iCells = pList->isz; 
  if(iCells < 2){
    printf("GetCCSubPop ERRB: size of List < 2 !\n");
    FreeListVec(&pList);
    return 0.0;
  }

  double** pLV = pList->pv;
  int* pLen = pList->plen;

  //init vector of distances to each cell , 0 == no path found
  int* pNeighbors = (int*)calloc(iCells,sizeof(int));
  int i = 0, iNeighbors = 0;
  if(!pNeighbors){
    printf("GetCCSubPop ERRE: out of memory!\n");
    FreeListVec(&pList);
    return 0.0;
  }  

  //init vector of avg distances to each cell , 0 == no path found
  double* pCC; 
  int iVecSz = vector_arg_px(2,&pCC);
  if(!pCC || iVecSz < iCells){
    printf("GetCCSubPop ERRE: arg 2 must be a Vector with size %d\n",iCells);
    FreeListVec(&pList);
    return 0.0;
  }  
  memset(pCC,0,sizeof(double)*iVecSz);

  double* pStart,  // bin vec of ids to search from 
          *pEnd;   // bin vec of ids to terminate search on

  if( vector_arg_px(3,&pStart) < iCells || vector_arg_px(4,&pEnd) < iCells){
    printf("GetCCSubPop ERRF: arg 3,4 must be Vectors with size >= %d\n",iCells);
    FreeListVec(&pList);
    return 0.0;
  }
  double dSubsamp = ifarg(5)?*getarg(5):1.0;

  unsigned int iSeed = ifarg(6)?(unsigned int)*getarg(6):INT_MAX-109754;

  double* pUse = 0; 
  
  if(dSubsamp<1.0){ //if using only a fraction of the cells
     pUse = (double*)malloc(iCells*sizeof(double));
     mcell_ran4(&iSeed, pUse, iCells, 1.0);
  }

  //get id of cell to find paths from
  int myID;

  int* pNeighborID = (int*)calloc(iCells,sizeof(int));

  if( verbose > 0 ) printf("searching from id: ");

  for(myID=0;myID<iCells;myID++) pCC[myID]=-1.0; //set invalid

  for(myID=0;myID<iCells;myID++){

    if(!pStart[myID]) continue;

    if(verbose > 0 && myID%1000==0)printf("%d ",myID);

    //only use dSubSamp fraction of cells, skip rest
    if(pUse && pUse[myID]>=dSubsamp) continue;

    int idx = 0, youID = 0, youKidID=0 , iNeighbors = 0;

    //mark neighbors of distance == 1
    for(idx=0;idx<pLen[myID];idx++){
      youID = pLV[myID][idx];
      if(pEnd[youID] && !pNeighbors[youID]){
        pNeighbors[youID]=1;      
        pNeighborID[iNeighbors++]=youID;
      }
    }

    if(iNeighbors < 2){
      for(i=0;i<iNeighbors;i++)pNeighbors[pNeighborID[i]]=0;
      continue;
    }

    int iConns = 0 ; 
  
    //this checks # of connections between neighbors of node
    for(i=0;i<iNeighbors;i++){
      if(!pNeighbors[pNeighborID[i]])continue;
      youID=pNeighborID[i];
      for(idx=0;idx<pLen[youID];idx++){
        youKidID=pLV[youID][idx];
        if(pEnd[youKidID] && pNeighbors[youKidID]){
          iConns++;
        }
      }
    }
    pCC[myID]=(double)iConns/((double)iNeighbors*(iNeighbors-1));
    for(i=0;i<iNeighbors;i++)pNeighbors[pNeighborID[i]]=0;
  }
 
  free(pNeighborID);
  free(pNeighbors);
  FreeListVec(&pList);
  if(pUse)free(pUse);

  if( verbose > 0 ) printf("\n");

  return  1.0;

  ENDVERBATIM
}
:* usage GetRecurCount(adjlist,outvec,fromids,thruids)
: counts # of A -> B -> A patterns in adj adjacency list , using from ids as A
: and thruids as B. fromids/thruids should have size of adjacency list and have a 
: 1 in index iff using that cell, same with thruids
FUNCTION GetRecurCount () {
  VERBATIM
  ListVec* pList;
  int iCells,*pLen,iFromSz,iThruSz,idx,myID,youID,jdx,iCheckSz,*pVisited,*pCheck;
  double **pLV,*pFrom,*pThru,*pR;

  pList = AllocListVec(*hoc_objgetarg(1));
  if(!pList){
    printf("GetRecurCount ERRA: problem initializing first arg!\n");
    return 0.0;
  }
 
  iCells = pList->isz; 
  if(iCells < 2){
    printf("GetRecurCount ERRB: size of List < 2 !\n");
    FreeListVec(&pList);
    return 0.0;
  }

  pLV = pList->pv;
  pLen = pList->plen;

  pFrom=pThru=0;
  iFromSz = vector_arg_px(3,&pFrom); iThruSz = vector_arg_px(4,&pThru);
  
  if( iFromSz <= 0 || iThruSz <= 0){
    printf("GetRecurCount ERRF: arg 3,4 bad (fromsz,thrusz)=(%d,%d)\n",iFromSz,iThruSz);
    FreeListVec(&pList);
    return 0.0;
  }

  pVisited = (int*)calloc(iCells,sizeof(int));//which vertices already marked to have children expanded

  pCheck = (int*)malloc(sizeof(int)*iCells);

  pR = vector_newsize(vector_arg(2),iCells);
  memset(pR,0,sizeof(double)*iCells); //zero out output first

  for(myID=0;myID<iCells;myID++) {
    if(!pFrom[myID]) continue;
    iCheckSz = 0; 
    for(idx=0;idx<pLen[myID];idx++){//mark neighbors of distance == 1
      youID = pLV[myID][idx];
      if(!pThru[youID] || pVisited[youID]) continue;
      pCheck[iCheckSz++]=youID;
      pVisited[youID]=1;
    }
    for(idx=0;idx<iCheckSz;idx++) {
      youID = pCheck[idx];
      for(jdx=0;jdx<pLen[youID];jdx++) {
        if(pLV[youID][jdx]==myID) pR[myID]++;
      }
    }
    memset(pVisited,0,sizeof(int)*iCells);
  }
  

  free(pCheck);
  FreeListVec(&pList);  
  free(pVisited);

  if( verbose > 0) printf("\n");

  return 1.0;

  ENDVERBATIM
}

:* usage GetPairDist(adjlist,outvec,startid,endid[subsamp,seed])
: computes distances between all pairs of vertices, self->self distance == distance of shortest loop
: adjlist == list of vectors specifying connectivity - adjacency list : from row -> to entry in column
: outvec == vector of distances from vertex i in outvec.x(i)
: startid == first id to check
: endid   == last id to check
FUNCTION GetPairDist () {
  VERBATIM
  ListVec* pList = AllocListVec(*hoc_objgetarg(1));
  if(!pList){
    printf("GetPairDist ERRA: problem initializing first arg!\n");
    return 0.0;
  }
 
  int iCells = pList->isz; 
  if(iCells < 2){
    printf("GetPairDist ERRB: size of List < 2 !\n");
    FreeListVec(&pList);
    return 0.0;
  }

  double** pLV = pList->pv;
  int* pLen = pList->plen;

  double* pFrom = 0, *pTo = 0;
  int iFromSz = vector_arg_px(3,&pFrom) , iToSz = vector_arg_px(4,&pTo);
  
  if( iFromSz <= 0 || iToSz <= 0){
    printf("GetPairDist ERRF: arg 3,4 bad (fromsz,tosz)=(%d,%d)\n",iFromSz,iToSz);
    FreeListVec(&pList);
    return 0.0;
  }

  int iMinSz = iFromSz * iToSz;

  //init vector of avg distances to each cell , 0 == no path found
  double* pVD; 
  pVD = vector_newsize(vector_arg(2),iMinSz);
  memset(pVD,0,sizeof(double)*iMinSz); //zero out output first

  //init array of cells/neighbors to check
  int* pCheck;
  pCheck = (int*)malloc(sizeof(int)*iCells);
  if(!pCheck){
    printf("GetPairDist ERRG: out of memory!\n");
    FreeListVec(&pList);
    return 0.0;
  }

  int iCheckSz = 0, idx = 0, iDist = 1 , youID = 0, youKidID=0, iTmpSz = 0, jdx = 0;

  int* pTmp = (int*)calloc(iCells,sizeof(int)); 

  if( verbose > 0 ) printf("searching from id: ");

  int myID , iOff = 0 , kdx = 0;

  int* pVisited = (int*)calloc(iCells,sizeof(int)); //which vertices already marked to have children expanded
  int* pUse = (int*)calloc(iCells,sizeof(int)); //which 'TO' vertices
  int* pMap = (int*)calloc(iCells,sizeof(int)); //index of 'TO' vertices to output index
  for(idx=0;idx<iToSz;idx++){
    pUse[(int)pTo[idx]]=1;
    pMap[(int)pTo[idx]]=idx;
  }

  for(kdx=0;kdx<iFromSz;kdx++,iOff+=iToSz){
    myID=pFrom[kdx];
    if(verbose > 0 && myID%100==0)printf("%d\n",myID);

    iCheckSz = 0; idx = 0; iDist = 1; youID = 0; youKidID = 0;
      
    //mark neighbors of distance == 1
    for(idx=0;idx<pLen[myID];idx++){
      youID = pLV[myID][idx];
      if(pUse[youID]) pVD[ iOff + pMap[youID]  ] = 1; //mark 1st degree neighbor distance as 1
      if(!pVisited[youID]){ 
        pCheck[iCheckSz++]=youID;
        pVisited[youID]=1;
      }
    }

    iTmpSz = 0;  jdx=0;
      
    iDist++;
  
    //this does a breadth-first search but avoids recursion
    while(iCheckSz>0){
      iTmpSz = 0;
      for(idx=0;idx<iCheckSz;idx++){
        youID=pCheck[idx];
        for(jdx=0;jdx<pLen[youID];jdx++){
          youKidID=pLV[youID][jdx];
          if(pUse[youKidID] && !pVD[iOff + pMap[youKidID]])
            pVD[iOff + pMap[youKidID]] = iDist; 
          if(!pVisited[youKidID]){ //found a new connection
            pTmp[iTmpSz++] = youKidID; //save id of cell to search it's kids on next iteration
            pVisited[youKidID]=1;
          }
        }
      }
      iCheckSz = iTmpSz;
      if(iCheckSz) memcpy(pCheck,pTmp,sizeof(int)*iCheckSz);
      iDist++;
    }
    memset(pVisited,0,sizeof(int)*iCells);
  }
  
  free(pTmp);
  free(pCheck);
  FreeListVec(&pList);  
  free(pUse);
  free(pMap);
  free(pVisited);

  if( verbose > 0) printf("\n");

  return 1.0;
  ENDVERBATIM
}

:* usage GetPathSubPop(adjlist,outvec,startids,endids[subsamp,loop,seed])
: computes path lengths between sub-populations
: adjlist == list of vectors specifying connectivity - adjacency list : from row -> to entry in column
: outvec == vector of distances from vertex i in outvec.x(i)
: startid == binary vector of ids of cells to start search from (from population)
: endid   == binary vector of ids of cells to terminate search on (to population)
: subsamp == perform calculation on ratio of cells btwn 0-1, default == 1
: loop == check self-loops , default == 0
: seed == random # seed when using subsampling
FUNCTION GetPathSubPop () {
  VERBATIM
  ListVec* pList = AllocListVec(*hoc_objgetarg(1));
  if(!pList){
    printf("GetPathEV ERRA: problem initializing first arg!\n");
    return 0.0;
  }
 
  int iCells = pList->isz; 
  if(iCells < 2){
    printf("GetPathEV ERRB: size of List < 2 !\n");
    FreeListVec(&pList);
    return 0.0;
  }

  double** pLV = pList->pv;
  int* pLen = pList->plen;

  //init vector of avg distances to each cell , 0 == no path found
  double* pVD; 
  int iVecSz = vector_arg_px(2,&pVD) , i = 0;
  if(!pVD || iVecSz < iCells){
    printf("GetPathEV ERRE: arg 2 must be a Vector with size %d\n",iCells);
    FreeListVec(&pList);
    return 0.0;
  }  
  memset(pVD,0,sizeof(double)*iVecSz);

  double* pStart,  // bin vec of ids to search from 
          *pEnd;   // bin vec of ids to terminate search on

  if( vector_arg_px(3,&pStart) < iCells || vector_arg_px(4,&pEnd) < iCells){
    printf("GetPathSubPop ERRF: arg 3,4 must be Vectors with size >= %d\n",iCells);
    FreeListVec(&pList);
    return 0.0;
  }
  double dSubsamp = ifarg(5)?*getarg(5):1.0;

  int bSelfLoop = ifarg(6)?(int)*getarg(6):0;

  unsigned int iSeed = ifarg(7)?(unsigned int)*getarg(7):INT_MAX-109754;

  //init array of cells/neighbors to check
  int* pCheck = (int*)malloc(sizeof(int)*iCells);
  if(!pCheck){
    printf("GetPathEV ERRG: out of memory!\n");
    FreeListVec(&pList);
    return 0.0;
  }

  int iCheckSz = 0, idx = 0, iDist = 1 , youID = 0, youKidID=0, iTmpSz = 0, jdx = 0;

  double  dgzt = 0.0; 
  int* pTmp = 0;
  double* pUse = 0; 
  
  if(dSubsamp<1.0){ //if using only a fraction of the cells
     pUse = (double*)malloc(iCells*sizeof(double));
     mcell_ran4(&iSeed, pUse, iCells, 1.0);
  }

  pTmp = (int*)calloc(iCells,sizeof(int)); 

  if( verbose > 0 ) printf("searching from id: ");

  int* pVDTmp = (int*)calloc(iCells,sizeof(int)) , myID;

  for(myID=0;myID<iCells;myID++){

    if(!pStart[myID]) continue;

    if(verbose > 0 && myID%1000==0)printf("%d ",myID); 

    //only use dSubSamp fraction of cells, skip rest
    if(pUse && pUse[myID]>=dSubsamp) continue;

    unsigned long int iSelfLoopDist = LONG_MAX;
    int bFindThisSelfLoop = bSelfLoop && pEnd[myID]; // search for self loop for this vertex?

    iCheckSz = 0; idx = 0; iDist = 1; youID = 0; youKidID = 0;

    pVDTmp[myID]=1;

    //mark neighbors of distance == 1
    for(idx=0;idx<pLen[myID];idx++){
      youID = pLV[myID][idx];
      if(bFindThisSelfLoop && youID==myID && iDist<iSelfLoopDist) iSelfLoopDist = iDist; //found a self-loop? 
      if(!pVDTmp[youID]){
        pVDTmp[youID]=iDist;
        pCheck[iCheckSz++]=youID;
      }
    }

    iTmpSz = 0;  jdx=0;

    iDist++;
  
    //this does a breadth-first search but avoids recursion
    while(iCheckSz>0){
      iTmpSz = 0;
      for(idx=0;idx<iCheckSz;idx++){
        youID=pCheck[idx];
        for(jdx=0;jdx<pLen[youID];jdx++){
          youKidID=pLV[youID][jdx];
          if(bFindThisSelfLoop && youKidID==myID && iDist<iSelfLoopDist) iSelfLoopDist = iDist; //found a self-loop? 
          if(!pVDTmp[youKidID]){ //found a new connection
            pTmp[iTmpSz++] = youKidID; //save id of cell to search it's kids on next iteration
            pVDTmp[youKidID]=iDist;
          }
        }
      }
      iCheckSz = iTmpSz;
      if(iCheckSz) memcpy(pCheck,pTmp,sizeof(int)*iCheckSz);
      iDist++;
    }

    if(bFindThisSelfLoop && iSelfLoopDist<LONG_MAX){//if checking for this vertex's self-loop dist. and found a self-loop
      pVDTmp[myID] = iSelfLoopDist;
    } else {
      pVDTmp[myID]=0; // distance to self == 0.0
    }
    pVD[myID] = 0.0;
    int N = 0; //take average path length (+ self-loop length if needed) from myID to pEnd cells
    for(idx=0;idx<iCells;idx++){
      if(pEnd[idx] && pVDTmp[idx]){
        pVD[myID] += pVDTmp[idx];
        N++;
      }
    }

    if(N) pVD[myID] /= (double) N; // save mean path (and maybe self-loop) length for given cell

    memset(pVDTmp,0,sizeof(int)*iCells);
  }
  
  free(pTmp);
  if(pUse) free(pUse); 
  free(pCheck);
  FreeListVec(&pList);  
  free(pVDTmp);

  if( verbose > 0 ) printf("\n");

  return 1.0;
  ENDVERBATIM
}

:* usage GetLoopLength(adjlist,outvec,loopids,thruids[,subsamp,seed])
: computes distance to loop back to each node
: adjlist == list of vectors specifying connectivity - adjacency list : from row -> to entry in column
: outvec == vector of distances
: loopids == binary vector of ids of cells to start/end search from/to
: thruids == binary vector of ids of cells thru which loop can pass
: subsamp == perform calculation on ratio of cells btwn 0-1, default == 1
: seed == random # seed when using subsampling
FUNCTION GetLoopLength () {
  VERBATIM
  ListVec* pList = AllocListVec(*hoc_objgetarg(1));
  if(!pList){
    printf("GetLoopLength ERRA: problem initializing first arg!\n");
    return 0.0;
  }
 
  int iCells = pList->isz; 
  if(iCells < 2){
    printf("GetLoopLength ERRB: size of List < 2 !\n");
    FreeListVec(&pList);
    return 0.0;
  }

  double** pLV = pList->pv;
  int* pLen = pList->plen;

  //init vector of avg distances to each cell , 0 == no path found
  double* pVD; 
  int iVecSz = vector_arg_px(2,&pVD) , i = 0;
  if(!pVD || iVecSz < iCells){
    printf("GetLoopLength ERRE: arg 2 must be a Vector with size %d\n",iCells);
    FreeListVec(&pList);
    return 0.0;
  }  
  memset(pVD,0,sizeof(double)*iVecSz);//init to 0

  double* pLoop,  // bin vec of ids to search from 
          *pThru;   // bin vec of ids to terminate search on

  if( vector_arg_px(3,&pLoop) < iCells || vector_arg_px(4,&pThru) < iCells){
    printf("GetLoopLength ERRF: arg 3,4 must be Vectors with size >= %d\n",iCells);
    FreeListVec(&pList);
    return 0.0;
  }
  double dSubsamp = ifarg(5)?*getarg(5):1.0;

  unsigned int iSeed = ifarg(6)?(unsigned int)*getarg(6):INT_MAX-109754;

  //init array of cells/neighbors to check
  int* pCheck = (int*)malloc(sizeof(int)*iCells);
  if(!pCheck){
    printf("GetLoopLength ERRG: out of memory!\n");
    FreeListVec(&pList);
    return 0.0;
  }

  int iCheckSz = 0, idx = 0, iDist = 1 , youID = 0, youKidID=0, iTmpSz = 0, jdx = 0;

  double  dgzt = 0.0; 
  int* pTmp = 0 , found = 0;
  double* pUse = 0; 
  
  if(dSubsamp<1.0){ //if using only a fraction of the cells
     pUse = (double*)malloc(iCells*sizeof(double));
     mcell_ran4(&iSeed, pUse, iCells, 1.0);
  }

  pTmp = (int*)calloc(iCells,sizeof(int)); 

  if( verbose > 0 ) printf("searching loops from id: ");

  int* pVDTmp = (int*)calloc(iCells,sizeof(int)) , myID;

  for(myID=0;myID<iCells;myID++){

    if(!pLoop[myID]) continue;

    if(verbose > 0 && myID%1000==0)printf("%d ",myID); 

    //only use dSubSamp fraction of cells, skip rest
    if(pUse && pUse[myID]>=dSubsamp) continue;

    iCheckSz = 0; idx = 0; iDist = 1; youID = 0; youKidID = 0; found = 0;

    pVDTmp[myID]=1;

    //mark neighbors of distance == 1
    for(idx=0;idx<pLen[myID];idx++){
      youID = pLV[myID][idx];
      if(youID==myID) {
        found = 1;
        pVD[myID]=iDist;
        iCheckSz=0;
        break;
      }
      if(pThru[youID] && !pVDTmp[youID]){
        pVDTmp[youID]=iDist;
        pCheck[iCheckSz++]=youID;
      }
    }

    iTmpSz = 0;  jdx=0;

    iDist++;
  
    //this does a breadth-first search but avoids recursion
    while(iCheckSz>0){
      iTmpSz = 0;
      for(idx=0;idx<iCheckSz;idx++){
        youID=pCheck[idx];
        for(jdx=0;jdx<pLen[youID];jdx++){
          youKidID=pLV[youID][jdx];
          if(youKidID==myID){
            pVD[myID]=iDist;
            found = 1;
            break;
          }
          if(pThru[youKidID] && !pVDTmp[youKidID]){ //found a new connection
            pTmp[iTmpSz++] = youKidID; //save id of cell to search it's kids on next iteration
            pVDTmp[youKidID]=iDist;
          }
        }
      }
      if(found) break;
      iCheckSz = iTmpSz;
      if(iCheckSz) memcpy(pCheck,pTmp,sizeof(int)*iCheckSz);
      iDist++;
    }
    memset(pVDTmp,0,sizeof(int)*iCells);
  }
  
  free(pTmp);
  if(pUse) free(pUse); 
  free(pCheck);
  FreeListVec(&pList);  
  free(pVDTmp);

  if( verbose > 0 ) printf("\n");

  return 1.0;
  ENDVERBATIM
}

:* usage GetPathEV(adjlist,outvec,myid,[startid,endid,maxdist])
: adjlist == list of vectors specifying connectivity - adjacency list : from row -> to entry in column
: outvec == vector of distances
: myid == id of cell to start search from
: startid == min id of cells search can terminate on or go through
: endid   == max  '    '   '  '   '  '  '  '  ' '  '  '  '  '  ' 
FUNCTION GetPathEV () {
  VERBATIM
  ListVec* pList = AllocListVec(*hoc_objgetarg(1));
  if(!pList){
    printf("GetPathEV ERRA: problem initializing first arg!\n");
    return 0.0;
  }
 
  int iCells = pList->isz; 
  if(iCells < 2){
    printf("GetPathEV ERRB: size of List < 2 !\n");
    FreeListVec(&pList);
    return 0.0;
  }

  double** pLV = pList->pv;
  int* pLen = pList->plen;

  //init vector of distances to each cell , 0 == no path found
  double* pVD; 
  int iVecSz = vector_arg_px(2,&pVD) , i = 0;
  if(!pVD || iVecSz < iCells){
    printf("GetPathEV ERRE: arg 2 must be a Vector with size %d\n",iCells);
    FreeListVec(&pList);
    return 0.0;
  }  
  memset(pVD,0,sizeof(double)*iVecSz);//init to 0

  //get id of cell to find paths from
  int myID = (int) *getarg(3);
  if(myID < 0 || myID >= iCells){
    printf("GetPathEV ERRF: invalid id = %d\n",myID);
    FreeListVec(&pList);
    return 0.0;
  }

  //start/end id of cells to find path to
  int iStartID = ifarg(4) ? (int)*getarg(4) : 0,
      iEndID = ifarg(5) ? (int)*getarg(5) : iCells - 1,
      iMaxDist = ifarg(6)? (int)*getarg(6): -1;

  if(iStartID < 0 || iStartID >= iCells ||
     iEndID < 0 || iEndID >= iCells ||
     iStartID >= iEndID){
       printf("GetPathEV ERRH: invalid ids start=%d end=%d numcells=%d\n",iStartID,iEndID,iCells);
       FreeListVec(&pList);
       return 0.0;
     }

  //check max distance
  if(iMaxDist==0){
    printf("GetPathEV ERRI: invalid maxdist=%d\n",iMaxDist);
    FreeListVec(&pList);
    return 0.0;
  }

  //init array of cells/neighbors to check
  int* pCheck = (int*)malloc(sizeof(int)*iCells);
  if(!pCheck){
    printf("GetPathEV ERRG: out of memory!\n");
    FreeListVec(&pList);
    return 0.0;
  }
  int iCheckSz = 0, idx = 0, iDist = 1 , youID = 0, youKidID=0;

  pVD[myID]=1;

  //mark neighbors of distance == 1
  for(idx=0;idx<pLen[myID];idx++){
    youID = pLV[myID][idx];
    if(youID>=iStartID && youID<=iEndID && !pVD[youID]){
      pVD[youID]=(double)iDist;
      pCheck[iCheckSz++]=youID;
    }
  }

  int* pTmp = (int*)malloc(sizeof(int)*iCells);
  int iTmpSz = 0 , jdx=0;

  iDist++;
  
  //this does a breadth-first search but avoids deep nesting of recursive version
  while(iCheckSz>0 && (iMaxDist==-1 || iDist<=iMaxDist)){
    iTmpSz = 0;
    for(idx=0;idx<iCheckSz;idx++){
      youID=pCheck[idx];
      for(jdx=0;jdx<pLen[youID];jdx++){
        youKidID=pLV[youID][jdx];
        if(youKidID >= iStartID && youKidID <=iEndID && !pVD[youKidID]){ //found a new connection
          pTmp[iTmpSz++] = youKidID; //save id of cell to search it's kids on next iteration
          pVD[youKidID]=(double)iDist;
        }
      }
    }
    iCheckSz = iTmpSz;
    if(iCheckSz) memcpy(pCheck,pTmp,sizeof(int)*iCheckSz);
    iDist++;
  }

  pVD[myID]=0.0;
 
  free(pCheck);
  free(pTmp);
  FreeListVec(&pList);

  return 1.0;
  ENDVERBATIM
}

:* FUNCTION Factorial()
FUNCTION Factorial () {
  VERBATIM
  double N = (int)*getarg(1) , i = 0.0;
  double val = 1.0;
  if(N<=1) return 1.0;
  if(N>=171){
    double PI=3.1415926535897932384626433832795;
    double E=2.71828183;
    val=sqrt(2*PI*N)*(pow(N,N)/pow(E,N));
  } else {
    for(i=2.0;i<=N;i++) val*=i;
  }
  return (double) val;  
  ENDVERBATIM
}

:* FUNCTION perm()
:count # of permutations from set of N elements with R selections
FUNCTION perm () {
  VERBATIM
  if(ifarg(3)){
    double N = (int)*getarg(1);
    double R = (int)*getarg(2);
    double b = *getarg(3);
    double val = N/b;
    int i = 0;
    for(i=1;i<R;i++){
      N--;
      val*=(N/b);
    }
    return val;
  } else {
    int N = (int)*getarg(1);
    int R = (int)*getarg(2);
    int val = N;
    int i = 0;
    for(i=1;i<R;i++){
      N--;
      val*=N;
    }
    return (double)val;
  }
  ENDVERBATIM
}

:* install_intfsw
PROCEDURE install () {
 if(INSTALLED==1){
   printf("Already installed $Id: intfsw.mod,v 1.50 2009/02/26 18:24:34 samn Exp $ \n")
 } else {
 INSTALLED=1
 VERBATIM
 install_vector_method("gzmean" ,gzmean);
 install_vector_method("nnmean" ,nnmean);
 install_vector_method("copynz" ,copynz);
 ENDVERBATIM
 printf("Installed $Id: intfsw.mod,v 1.50 2009/02/26 18:24:34 samn Exp $ \n")
 }
}

Dura-Bernal S, Zhou X, Neymotin SA, Przekwas A, Francis JT, Lytton WW (2015) Cortical Spiking Network Interfaced with Virtual Musculoskeletal Arm and Robotic Arm. Front Neurorobot 9:13[PubMed]

References and models cited by this paper

References and models that cite this paper

Almassy N, Edelman GM, Sporns O (1998) Behavioral constraints in the development of neuronal properties: a cortical model embedded in a real-world device. Cereb Cortex 8:346-61 [PubMed]

Alstermark B, Isa T (2012) Circuits for skilled reaching and grasping. Annu Rev Neurosci 35:559-78 [Journal] [PubMed]

Barrett Tech (2012) WAM Training Documentation

Bergenheim M, Ribot-Ciscar E, Roll JP (2000) Proprioceptive population coding of two-dimensional limb movements in humans: I. Muscle spindle feedback during spatially oriented movements. Exp Brain Res 134:301-10 [PubMed]

Berger DJ, d'Avella A (2014) Effective force control by muscle synergies. Front Comput Neurosci 8:46 [Journal] [PubMed]

Carmena JM (2013) Advances in neuroprosthetic learning and control. PLoS Biol 11:e1001561 [Journal] [PubMed]

Carnevale NT, Hines ML (2006) The NEURON Book

Carrillo RR, Ros E, Boucheny C, Coenen OJ (2009) A real-time spiking cerebellum model for learning robot control. Biosystems 94:18-27 [PubMed]

Chadderdon GL, Neymotin SA, Kerr CC, Lytton WW (2012) Reinforcement learning of targeted movement in a spiking neuronal model of motor cortex. PLoS One 7:e47251-57 [PubMed]

Demandt E, Mehring C, Vogt K, Schulze-Bonhage A, Aertsen A, Ball T (2012) Reaching movement onset- and end-related characteristics of EEG spectral power modulations. Front Neurosci 6:65 [Journal] [PubMed]

DeWolf T, Eliasmith C (2011) The neural optimal control hierarchy for motor control. J Neural Eng 8:065009 [Journal] [PubMed]

Dura-Bernal lS,Chadderdon GL,Neymotin SA,Francis JT,Lytton WW (2014) Towards a real-time interface between a biomimetic model of sensorimotor cortex and a robotic arm Pattern Recognition Lett. 36:204-212

Dura-Bernal S,Prins N,Neymotin S,Prasad A,Sanchez J,Francis J,et al (1887) Evaluating hebbian reinforcement learning bmi using an in silico brain model and a virtual musculoskeletal arm Neural Control of Movement

Edelman GM (1987) Neural Darwinism: The Theory of Neuronal Group Selection

Fagg AH, Hatsopoulos NG, de Lafuente V, Moxon KA, Nemati S, Rebesco JM, Romo R, Solla SA, Rei (2007) Biomimetic brain machine interfaces for the control of movement. J Neurosci 27:11842-6 [Journal] [PubMed]

Featherstone R,Orin D (2000) Robot dynamics: Equations and algorithms In ICRA (International Conference Robotics and Automation) :826-834

Flint RD, Lindberg EW, Jordan LR, Miller LE, Slutzky MW (2012) Accurate decoding of reaching movements from field potentials in the absence of spikes. J Neural Eng 9:046006 [Journal] [PubMed]

Francis JT (2009) The neural representation of kinematics and dynamics in multiple brain regions: the use of force field reaching paradigms in the primate and rat Mechanosensitivity of the Nervous System, Mechanosensitivity in Cells and Tissues, Kamkim A:Kiseleva I, ed. pp.215

Hatsopoulos N, Joshi J, O'Leary JG (2004) Decoding continuous and discrete motor behaviors using motor and premotor cortical ensembles. J Neurophysiol 92:1165-74 [Journal] [PubMed]

Hines ML, Carnevale NT (2001) NEURON: a tool for neuroscientists. Neuroscientist 7:123-35 [Journal] [PubMed]

   Spatial gridding and temporal accuracy in NEURON (Hines and Carnevale 2001) [Model]

Hogan N, Sternad D (2009) Sensitivity of smoothness measures to movement duration, amplitude, and arrests. J Mot Behav 41:529-34 [Journal] [PubMed]

Holzbaur KR,Murray WM,Delp SL (2005) A model of the upper extremity for simulating musculoskeletal surgery and analyzing neuromuscular control Ann. Biomed. Eng. 33:829-840

Izhikevich EM (2007) Solving the Distal Reward Problem through Linkage of STDP and Dopamine Signaling. Cereb Cortex 17(10):2443-2452 [Journal] [PubMed]

   Linking STDP and Dopamine action to solve the distal reward problem (Izhikevich 2007) [Model]

Kerr CC, Neymotin SA, Chadderdon GL, Fietkiewicz CT, Francis JT, Lytton WW (2012) Electrostimulation as a prosthesis for repair of information flow in a computer model of neocortex IEEE Transactions on Neural Systems & Rehabilitation Engineering 20(2):153-60 [Journal] [PubMed]

   Prosthetic electrostimulation for information flow repair in a neocortical simulation (Kerr 2012) [Model]

Lee G,Matsunaga A,Dura-Bernal S,Zhang W,Lytton W,Francis J,Et AL (2014) Towards real-time communication between in vivo neurophysiological data sources and simulator-based brain biomimetic models. J Comput Surg

Li K,Dura-Bernal S,Francis J,Lytton W,Principe J (2015) Repairing lesions via kernel adaptive inverse control in a biomimetic model of sensorimotor cortex Neural Engineering (NER), 2015 7th International IEEE/EMBS Conference. (Montpellier)

Luque NR, Garrido JA, Carrillo RR, Coenen OJ, Ros E (2011) Cerebellar input configuration toward object model abstraction in manipulation tasks. IEEE Trans Neural Netw 22:1321-8 [PubMed]

Lytton WW, Neymotin SA, Hines ML (2008) The virtual slice setup. J Neurosci Methods 171:309-15 [Journal] [PubMed]

   The virtual slice setup (Lytton et al. 2008) [Model]

Lytton WW, Omurtag A (2007) Tonic-clonic transitions in computer simulation. J Clin Neurophysiol 24:175-81 [PubMed]

   Tonic-clonic transitions in a seizure simulation (Lytton and Omurtag 2007) [Model]

Lytton WW, Omurtag A, Neymotin SA, Hines ML (2008) Just in time connectivity for large spiking networks Neural Comput 20(11):2745-56 [Journal] [PubMed]

   JitCon: Just in time connectivity for large spiking networks (Lytton et al. 2008) [Model]

Lytton WW, Stewart M (2005) A rule-based firing model for neural networks Int J Bioelectromagn 7:47-50

Lytton WW, Stewart M (2006) Rule-based firing for network simulations. Neurocomputing 69:1160-1164

Mahmoudi B, Pohlmeyer EA, Prins NW, Geng S, Sanchez JC (2013) Towards autonomous neuroprosthetic control using Hebbian reinforcement learning. J Neural Eng 10:066005 [Journal] [PubMed]

Marsh BT, Tarigoppula VS, Chen C, Francis JT (2015) Toward an autonomous brain machine interface: integrating sensorimotor reward modulation and reinforcement learning. J Neurosci 35:7374-87 [Journal] [PubMed]

Neymotin SA, Chadderdon GL, Kerr CC, Francis JT, Lytton WW (2013) Reinforcement learning of 2-joint virtual arm reaching in a computer model of sensorimotor cortex Neural Computation 25(12):3263-93 [Journal] [PubMed]

   Sensorimotor cortex reinforcement learning of 2-joint virtual arm reaching (Neymotin et al. 2013) [Model]

Neymotin SA, Lee H, Park E, Fenton AA, Lytton WW (2011) Emergence of physiological oscillation frequencies in a computer model of neocortex. Front Comput Neurosci 5:19-75 [Journal] [PubMed]

   Emergence of physiological oscillation frequencies in neocortex simulations (Neymotin et al. 2011) [Model]

Prins NW, Sanchez JC, Prasad A (2014) A confidence metric for using neurobiological feedback in actor-critic reinforcement learning based brain-machine interfaces. Front Neurosci 8:111 [Journal] [PubMed]

Roll JP, Albert F, Ribot-Ciscar E, Bergenheim M (2004) "Proprioceptive signature" of cursive writing in humans: a multi-population coding. Exp Brain Res 157:359-68 [Journal] [PubMed]

Sanchez J, Lytton W, Carmena J, Principe J, Fortes J, Barbour R, Francis J (2012) Dynamically repairing and replacing neural networks: using hybrid computational and biological tools. IEEE Pulse 3:57-9 [Journal] [PubMed]

Sanchez J, Tarigoppula A, Choi J, Marsh B, Chhatbar P (2011) Control of a center-out reaching task using a reinforcement learning brain-machine interface Neural Engineering (NER), 2011 5th International IEEE-EMBS Conference on. IEEE :525-528

Sartori M, Gizzi L, Lloyd DG, Farina D (2013) A musculoskeletal model of human locomotion driven by a low dimensional set of impulsive excitation primitives. Front Comput Neurosci 7:79 [Journal] [PubMed]

Schutte LM,Rodgers MM,Zajac F,Glaser RM (1993) Improving the efficacy of electrical stimulation-induced leg cycle ergometry: an analysis based on a dynamic musculoskeletal model Rehabil. Eng. IEEE Trans. 1:109-125

Shadmehr R, Mussa-Ivaldi FA (1994) Adaptive representation of dynamics during learning of a motor task. J Neurosci 14:3208-24 [PubMed]

Song W, Kerr CC, Lytton WW, Francis JT (2013) Cortical plasticity induced by spike-triggered microstimulation in primate somatosensory cortex. PLoS One 8:e57453-18 [PubMed]

Sussillo D, Churchland MM, Kaufman MT, Shenoy KV (2015) A neural network that finds a naturalistic solution for the production of muscle activity. Nat Neurosci 18:1025-33 [Journal] [PubMed]

Teulings HL, Contreras-Vidal JL, Stelmach GE, Adler CH (1997) Parkinsonism reduces coordination of fingers, wrist, and arm in fine motor control. Exp Neurol 146:159-70 [Journal] [PubMed]

Thelen DG, Anderson FC, Delp SL (2003) Generating dynamic simulations of movement using computed muscle control. J Biomech 36:321-8 [PubMed]

Wolpert DM, Diedrichsen J, Flanagan JR (2011) Principles of sensorimotor learning. Nat Rev Neurosci 12:739-51 [Journal] [PubMed]

Zajac FE (1989) Muscle and tendon: properties, models, scaling, and application to biomechanics and motor control. Crit Rev Biomed Eng 17:359-411 [PubMed]

Dura-Bernal S, Li K, Neymotin SA, Francis JT, Principe JC, Lytton WW (2016) Restoring behavior via inverse neurocontroller in a lesioned cortical spiking model driving a virtual arm. Front. Neurosci. Neuroprosthetics 10:28 [Journal]

   Cortical model with reinforcement learning drives realistic virtual arm (Dura-Bernal et al 2015) [Model]

Dura-Bernal S, Neymotin SA, Kerr CC, Sivagnanam S, Majumdar A, Francis JT, Lytton WW (2017) Evolutionary algorithm optimization of biological learning parameters in a biomimetic neuroprosthesis. IBM Journal of Research and Development (Computational Neuroscience special issue) 61(2/3):6:1-6:14 [Journal]

   Motor system model with reinforcement learning drives virtual arm (Dura-Bernal et al 2017) [Model]

(51 refs)

Dura-Bernal S, Li K, Neymotin SA, Francis JT, Principe JC, Lytton WW (2016) Restoring behavior via inverse neurocontroller in a lesioned cortical spiking model driving a virtual arm. Front. Neurosci. Neuroprosthetics 10:28

References and models cited by this paper

References and models that cite this paper

Alstermark B, Isa T (2012) Circuits for skilled reaching and grasping. Annu Rev Neurosci 35:559-78 [Journal] [PubMed]

Arle JE, Shils JL (2008) Motor cortex stimulation for pain and movement disorders. Neurotherapeutics 5:37-49 [Journal] [PubMed]

Bensmaia SJ, Miller LE (2014) Restoring sensorimotor function through intracortical interfaces: progress and looming challenges. Nat Rev Neurosci 15:313-25 [Journal] [PubMed]

Calvin WH (1988) Neural Darwinism. The Theory of Neuronal Group Selection. Gerald M. Edelman. Basic Books, New York, 1987. xxii, 371 pp., illus. $29.95. Science 240:1802 [Journal] [PubMed]

Carandini M (2012) From circuits to behavior: a bridge too far? Nat Neurosci 15:507-9 [PubMed]

Chadderdon GL, Mohan A, Suter BA, Neymotin SA, Kerr CC, Francis JT, Shepherd GM, Lytton WW (2014) Motor cortex microcircuit simulation based on brain activity mapping. Neural Comput 26:1239-62 [Journal] [PubMed]

   Motor cortex microcircuit simulation based on brain activity mapping (Chadderdon et al. 2014) [Model]

Chen B, Zhao S, Zhu P, Príncipe JC (2012) Quantized kernel least mean square algorithm. IEEE Trans Neural Netw Learn Syst 23:22-32 [Journal] [PubMed]

Ching S, Ritt JT (2013) Control strategies for underactuated neural ensembles driven by optogenetic stimulation. Front Neural Circuits 7:54 [Journal] [PubMed]

Choi JS,DiStasio MM,Brockmeier AJ,Francis JT (2012) An electric field model for prediction of somatosensory (s1) cortical field potentials induced by ventral posterior lateral (vpl) thalamic microstimulation Neural Systems and Rehabilitation Engineering, IEEE Transactions on 20:161-169

Clark KL, Armstrong KM, Moore T (2011) Probing neural circuitry and function with electrical microstimulation. Proc Biol Sci 278:1121-30 [Journal] [PubMed]

Douglas RJ, Martin KA (2012) Behavioral architecture of the cortical sheet. Curr Biol 22:R1033-8 [Journal] [PubMed]

Dura-Bernal S, Chadderdon GL, Neymotin SA, Francis JT, Lytton WW (2014) Towards a real-time interface between a biomimetic model of sensorimotor cortex and a robotic arm. Pattern Recognit Lett 36:204-212 [Journal] [PubMed]

Dura-Bernal S, Zhou X, Neymotin SA, Przekwas A, Francis JT, Lytton WW (2015) Cortical Spiking Network Interfaced with Virtual Musculoskeletal Arm and Robotic Arm. Front Neurorobot 9:13 [Journal] [PubMed]

   Cortical model with reinforcement learning drives realistic virtual arm (Dura-Bernal et al 2015) [Model]

Dura-Bernal S,Kerr C,Neymotin S,Suter B,Shepherd G,Francis J,Lytton W (2015) Large-scale m1 microcircuit model with plastic input connections from biological pmd neurons used for prosthetic arm control 24th Annual Computational Neuroscience Meeting (CNS15) BMC Neuroscience

Featherstone R,Orin D (2000) Robot dynamics: Equations and algorithms In ICRA (International Conference Robotics and Automation) :826-834

Grahn PJ, Mallory GW, Berry BM, Hachmann JT, Lobel DA, Lujan JL (2014) Restoration of motor function following spinal cord injury via optimal control of intraspinal microstimulation: toward a next generation closed-loop neural prosthesis. Front Neurosci 8:296 [Journal] [PubMed]

Grammont F, Riehle A (1999) Precise spike synchronization in monkey motor cortex involved in preparation for movement. Exp Brain Res 128:118-22 [PubMed]

Gupta RK, Przekwas A (2013) Mathematical Models of Blast-Induced TBI: Current Status, Challenges, and Prospects. Front Neurol 4:59 [Journal] [PubMed]

Hampson RE, Gerhardt GA, Marmarelis V, Song D, Opris I, Santos L, Berger TW, Deadwyler SA (2012) Facilitation and restoration of cognitive function in primate prefrontal cortex by a neuroprosthesis that utilizes minicolumn-specific neural firing. J Neural Eng 9:056012 [Journal] [PubMed]

Hampson RE, Song D, Opris I, Santos LM, Shin DC, Gerhardt GA, Marmarelis VZ, Berger TW, Deadw (2013) Facilitation of memory encoding in primate hippocampus by a neuroprosthesis that promotes task-specific neural firing. J Neural Eng 10:066013 [Journal] [PubMed]

Harris KD, Shepherd GM (2015) The neocortical circuit: themes and variations. Nat Neurosci 18:170-81 [Journal] [PubMed]

Hartmann CJ, Chaturvedi A, Lujan JL (2015) Quantitative analysis of axonal fiber activation evoked by deep brain stimulation via activation density heat maps. Front Neurosci 9:28 [Journal] [PubMed]

Hatsopoulos N, Joshi J, O'Leary JG (2004) Decoding continuous and discrete motor behaviors using motor and premotor cortical ensembles. J Neurophysiol 92:1165-74 [Journal] [PubMed]

Hiscott R (2014) Darpa: On the hunt for neuroprosthetics to enhance memory Neurology Today

Holzbaur KR,Murray WM,Delp SL (2005) A model of the upper extremity for simulating musculoskeletal surgery and analyzing neuromuscular control Ann. Biomed. Eng. 33:829-840

Hwang EJ, Shadmehr R (2005) Internal models of limb dynamics and the encoding of limb state. J Neural Eng 2:S266-78 [PubMed]

Jackson A, Mavoori J, Fetz EE (2006) Long-term motor cortex plasticity induced by an electronic neural implant. Nature 444:56-60 [Journal] [PubMed]

Jefferson SC, Clayton ER, Donlan NA, Kozlowski DA, Jones TA, Adkins DL (2015) Cortical Stimulation Concurrent With Skilled Motor Training Improves Forelimb Function and Enhances Motor Cortical Reorganization Following Controlled Cortical Impact. Neurorehabil Neural Repair [Journal] [PubMed]

Kasthuri N, Hayworth KJ, Berger DR, Schalek RL, Conchello JA, Knowles-Barley S, Lee D, Vázque (2015) Saturated Reconstruction of a Volume of Neocortex. Cell 162:648-61 [Journal] [PubMed]

Kerr CC, Neymotin SA, Chadderdon GL, Fietkiewicz CT, Francis JT, Lytton WW (2012) Electrostimulation as a prosthesis for repair of information flow in a computer model of neocortex IEEE Transactions on Neural Systems & Rehabilitation Engineering 20(2):153-60 [Journal] [PubMed]

   Prosthetic electrostimulation for information flow repair in a neocortical simulation (Kerr 2012) [Model]

Kerr CC,O`Shea DJ,Goo W,Dura-Bernal S,Francis JT,Diester I,Kalanithi P,Deisseroth K,Shenoy KV (2014) Network-level effects of optogenetic stimulation in a computer model of macaque primary motor cortex BMC Neuroscience 15:p107

Klaes C, Shi Y, Kellis S, Minxha J, Revechkis B, Andersen RA (2014) A cognitive neuroprosthetic that uses cortical stimulation for somatosensory feedback. J Neural Eng 11:056024 [Journal] [PubMed]

Kleim JA, Bruneau R, VandenBerg P, MacDonald E, Mulrooney R, Pocock D (2003) Motor cortex stimulation enhances motor recovery and reduces peri-infarct dysfunction following ischemic insult. Neurol Res 25:789-93 [Journal] [PubMed]

Kocaturk M, Gulcur HO, Canbeyli R (2015) Toward Building Hybrid Biological/in silico Neural Networks for Motor Neuroprosthetic Control. Front Neurorobot 9:8 [Journal] [PubMed]

Koch C, Buice MA (2015) A Biological Imitation Game. Cell 163:277-80 [Journal] [PubMed]

Koralek AC, Jin X, Long JD, Costa RM, Carmena JM (2012) Corticostriatal plasticity is necessary for learning intentional neuroprosthetic skills. Nature 483:331-5 [Journal] [PubMed]

Kreuz T, Chicharro D, Greschner M, Andrzejak RG (2011) Time-resolved and time-scale adaptive measures of spike train synchrony. J Neurosci Methods 195:92-106 [PubMed]

Kreuz T, Mulansky M, Bozanic N (2015) SPIKY: a graphical user interface for monitoring spike train synchrony. J Neurophysiol 113:3432-45 [Journal] [PubMed]

Lee G, Matsunaga A, Dura-Bernal S, Zhang W, Lytton WW, Francis JT, Fortes JA (2014) Towards real-time communication between in vivo neurophysiological data sources and simulator-based brain biomimetic models. J Comput Surg 3:1-23 [Journal] [PubMed]

Li K,Dura-Bernal S,Francis J,Lytton W,Principe J (2015) Repairing lesions via kernel adaptive inverse control in a biomimetic model of sensorimotor cortex Neural Engineering (NER), 2015 7th International IEEE/EMBS Conference. (Montpellier)

Li L, Park IM, Brockmeier A, Chen B, Seth S, Francis JT, Sanchez JC, Príncipe JC (2013) Adaptive inverse control of neural spatiotemporal spike patterns with a reproducing kernel Hilbert space (RKHS) framework. IEEE Trans Neural Syst Rehabil Eng 21:532-43 [Journal] [PubMed]

Ling G (2013) Newsmaker interview: Geoffrey Ling. DARPA aims to rebuild brains. Interview by Emily Underwood. Science 342:1029-30 [Journal] [PubMed]

Liu W,Pokharel P,Principe JC (2008) The kernel least mean square algorithm 56:543-554

Liu W,Principe JC,Haykin S (2010) Kernel Adaptive Filtering: A Comprehensive Introduction

Loeb GE, Tsianos GA (2015) Major remaining gaps in models of sensorimotor systems. Front Comput Neurosci 9:70 [Journal] [PubMed]

Lytton W,Stark J,Yamasaki D,Sober S (1999) Computer models of stroke recovery: Implications for neurorehabilitation. The Neuroscientist 5:100-111

Lytton WW, Neymotin SA, Hines ML (2008) The virtual slice setup. J Neurosci Methods 171:309-15 [Journal] [PubMed]

   The virtual slice setup (Lytton et al. 2008) [Model]

Lytton WW, Omurtag A, Neymotin SA, Hines ML (2008) Just in time connectivity for large spiking networks Neural Comput 20(11):2745-56 [Journal] [PubMed]

   JitCon: Just in time connectivity for large spiking networks (Lytton et al. 2008) [Model]

Lytton WW, Stewart M (2006) Rule-based firing for network simulations. Neurocomputing 69:1160-1164

Mante V, Sussillo D, Shenoy KV, Newsome WT (2013) Context-dependent computation by recurrent dynamics in prefrontal cortex. Nature 503:78-84 [Journal] [PubMed]

Marcus G, Marblestone A, Dean T (2014) Neuroscience. The atoms of neural computation. Science 346:551-2 [PubMed]

Markram H, Muller E, Ramaswamy S, Reimann MW, Abdellah M, Sanchez CA, Ailamaki A, Alonso-Nanclares L, Antille N, Arsever S, Kahou GA, Berger TK, Bilgili A, Buncic N, Chalimourda A, Chindemi G, Courcol JD, Delalondre F, Delattre V, Druckmann S, Dumusc R, Dynes J, Eilemann S, Gal E, Gevaert ME, Ghobril JP, Gidon A, Graham JW, Gupta A, Haenel V, Hay E, Heinis T, Hernando JB, Hines M, Kanari L, Keller D, Kenyon J, Khazen G, Kim Y, King JG, Kisvarday Z, Kumbhar P, Lasserre S, Le Be JV, Magalhães BR, Merchan-Perez A, Meystre J, Morrice BR, Muller J, Muñoz-Cespedes A, et al. (2015) Reconstruction and Simulation of Neocortical Microcircuitry. Cell 163:456-92 [Journal] [PubMed]

   [5 reconstructed morphologies on NeuroMorpho.Org]

McIntyre CC, Mori S, Sherman DL, Thakor NV, Vitek JL (2004) Electric field and stimulating influence generated by deep brain stimulation of the subthalamic nucleus. Clin Neurophysiol 115:589-95 [PubMed]

Miranda RA, Casebeer WD, Hein AM, Judy JW, Krotkov EP, Laabs TL, Manzo JE, Pankratz KG, Pratt (2015) DARPA-funded efforts in the development of novel brain-computer interface technologies. J Neurosci Methods 244:52-67 [Journal] [PubMed]

Nelson JT, Tepe V () Neuromodulation research and application in the U.S. Department of Defense. Brain Stimul 8:247-52 [Journal] [PubMed]

Neymotin SA, Chadderdon GL, Kerr CC, Francis JT, Lytton WW (2013) Reinforcement learning of 2-joint virtual arm reaching in a computer model of sensorimotor cortex Neural Computation 25(12):3263-93 [Journal] [PubMed]

   Sensorimotor cortex reinforcement learning of 2-joint virtual arm reaching (Neymotin et al. 2013) [Model]

Neymotin SA, Lee H, Park E, Fenton AA, Lytton WW (2011) Emergence of physiological oscillation frequencies in a computer model of neocortex. Front Comput Neurosci 5:19-75 [Journal] [PubMed]

   Emergence of physiological oscillation frequencies in neocortex simulations (Neymotin et al. 2011) [Model]

Neymotin SA,Fenton AA,Lytton WW (2015) Tracking recurrence of correlation structure in neuronal ensembles

Nirenberg S, Pandarinath C (2012) Retinal prosthetic strategy with the capacity to restore normal vision. Proc Natl Acad Sci U S A 109:15012-7 [Journal] [PubMed]

Nishimura Y, Perlmutter SI, Fetz EE (2013) Restoration of upper limb movement via artificial corticospinal and musculospinal connections in a monkey with spinal cord injury. Front Neural Circuits 7:57 [Journal] [PubMed]

O'Doherty JE, Lebedev MA, Ifft PJ, Zhuang KZ, Shokur S, Bleuler H, Nicolelis MA (2011) Active tactile exploration using a brain-machine-brain interface. Nature 479:228-31 [Journal] [PubMed]

Overduin SA, d'Avella A, Carmena JM, Bizzi E (2012) Microstimulation activates a handful of muscle synergies. Neuron 76:1071-7 [Journal] [PubMed]

Overstreet CK, Klein JD, Helms Tillery SI (2013) Computational modeling of direct neuronal recruitment during intracortical microstimulation in somatosensory cortex J Neural Eng. 10(6):066016 [Journal]

   Direct recruitment of S1 pyramidal cells and interneurons via ICMS (Overstreet et al., 2013) [Model]

Paiva AR, Park I, Príncipe JC (2009) A reproducing kernel Hilbert space framework for spike train signal processing. Neural Comput 21:424-49 [Journal] [PubMed]

Palop JJ, Mucke L (2010) Amyloid-beta-induced neuronal dysfunction in Alzheimer's disease: from synapses toward neural networks. Nat Neurosci 13:812-8 [PubMed]

Potjans TC, Diesmann M (2014) The cell-type specific cortical microcircuit: relating structure and activity in a full-scale spiking network model. Cereb Cortex 24:785-806 [Journal] [PubMed]

Ramanathan D, Conner JM, Tuszynski MH (2006) A form of motor cortical plasticity that correlates with recovery of function after brain injury. Proc Natl Acad Sci U S A 103:11370-5 [Journal] [PubMed]

Rickgauer JP, Deisseroth K, Tank DW (2014) Simultaneous cellular-resolution optical perturbation and imaging of place cell firing fields. Nat Neurosci 17:1816-24 [Journal] [PubMed]

Riehle A, Grun S, Diesmann M, Aertsen A (1997) Spike synchronization and rate modulation differentially involved in motor cortical function. Science 278:1950-3 [PubMed]

Rowan MS, Neymotin SA, Lytton WW (2014) Electrostimulation to reduce synaptic scaling driven progression of Alzheimer's disease. Front Comput Neurosci 8:39 [Journal] [PubMed]

   Electrostimulation to reduce synaptic scaling driven progression of Alzheimers (Rowan et al. 2014) [Model]

Rubino D, Robbins KA, Hatsopoulos NG (2006) Propagating waves mediate information transfer in the motor cortex. Nat Neurosci 9:1549-57 [Journal] [PubMed]

Sanchez J, Lytton W, Carmena J, Principe J, Fortes J, Barbour R, Francis J (2012) Dynamically repairing and replacing neural networks: using hybrid computational and biological tools. IEEE Pulse 3:57-9 [Journal] [PubMed]

Sanchez J, Tarigoppula A, Choi J, Marsh B, Chhatbar P (2011) Control of a center-out reaching task using a reinforcement learning brain-machine interface Neural Engineering (NER), 2011 5th International IEEE-EMBS Conference on. IEEE :525-528

Scholkopf B, Smola AJ (2001) Learning with kernels: Support vector machines, regularization, optimization, and beyond

Scholkopf B,Herbrich R,Smola AJ (2001) A generalized representer theorem Proc. 14th Annual Conf. on Comput. Learn. Theory 2111:416-426

Schutte LM,Rodgers MM,Zajac F,Glaser RM (1993) Improving the efficacy of electrical stimulation-induced leg cycle ergometry: an analysis based on a dynamic musculoskeletal model Rehabil. Eng. IEEE Trans. 1:109-125

Song W, Kerr CC, Lytton WW, Francis JT (2013) Cortical plasticity induced by spike-triggered microstimulation in primate somatosensory cortex. PLoS One 8:e57453-18 [PubMed]

Spuler M,Nagel S,Rosenstiel W () A Spiking Neuronal Model Learning a Motor Control Task by Reinforcement Learning and Structural Synaptic Plasticity

Stanley GB (2013) Reading and writing the neural code. Nat Neurosci 16:259-63 [Journal] [PubMed]

Sussillo D, Churchland MM, Kaufman MT, Shenoy KV (2015) A neural network that finds a naturalistic solution for the production of muscle activity. Nat Neurosci 18:1025-33 [Journal] [PubMed]

Suter BA, Migliore M, Shepherd GM (2013) Intrinsic electrophysiology of mouse corticospinal neurons: a class-specific triad of spike-related properties. Cereb Cortex 23:1965-77 [PubMed]

Suter BA, Yamawaki N, Borges K, Li X, Kiritani T, Hooks BM, Shepherd GM (2014) Neurophotonics applications to motor cortex research. Neurophotonics [Journal] [PubMed]

Tessadori J, Bisio M, Martinoia S, Chiappalone M (2012) Modular neuronal assemblies embodied in a closed-loop environment: toward future integration of brains and machines. Front Neural Circuits 6:99 [Journal] [PubMed]

Thelen DG, Anderson FC, Delp SL (2003) Generating dynamic simulations of movement using computed muscle control. J Biomech 36:321-8 [PubMed]

Van Acker GM, Amundsen SL, Messamore WG, Zhang HY, Luchies CW, Kovac A, Cheney PD (2013) Effective intracortical microstimulation parameters applied to primary motor cortex for evoking forelimb movements to stable spatial end points. J Neurophysiol 110:1180-9 [Journal] [PubMed]

Warden MR, Cardin JA, Deisseroth K (2014) Optical neural interfaces. Annu Rev Biomed Eng 16:103-29 [Journal] [PubMed]

Wolpert DM, Diedrichsen J, Flanagan JR (2011) Principles of sensorimotor learning. Nat Rev Neurosci 12:739-51 [Journal] [PubMed]

Zajac FE (1989) Muscle and tendon: properties, models, scaling, and application to biomechanics and motor control. Crit Rev Biomed Eng 17:359-411 [PubMed]

(88 refs)