: $Id: presyn.inc,v 1.4 2005/04/12 05:32:04 billl Exp $ NEURON { RANGE maxsyn, nsyn : scalars RANGE link : PreL structure } PARAMETER { nsyn = 0 link = 0 : presyn struct points to list of pointers to postsyn cells } ASSIGNED { maxsyn : max and counter for the list of pointers } INCLUDE "snshead.inc" CONSTRUCTOR { VERBATIM { /* link allows postsyn cell to manipulate presyn list */ link = (double)((unsigned long)hoc_Ecalloc(1, sizeof(PreL))); hoc_malchk(); PRECAST->link2 = link; /* this can be queried to protect against error */ nsyn = 0.; maxsyn = 0.; if (ifarg(2)) { PRECAST->cpre = (int)*getarg(2); } else { PRECAST->cpre = -1; } } ENDVERBATIM } DESTRUCTOR { VERBATIM { nsyn = maxsyn = 0; free(PRECAST); link = 0; } ENDVERBATIM } PROCEDURE preinit () {} : globally used presynaptically to add to queue (was called pushqueu()) PROCEDURE newspike() { VERBATIM { int ii, jj, nspk, qend, head, ind, swapi; double time, swapt; SynS *psyn; /* pointer to the presynaptic structure */ QptR *qpr; QueU *qp; /* pointer to the head position in postsyn queu */ for (ii=0; ii<nsyn;ii++) { /* psyn is the pointer back to the postsyn info array (struct SynS) */ if ((psyn = PRECAST->plst[ii])==(SynS *)NULL || /* skip empties */ (t < psyn->spkt && psyn->chainlen == 1)) { /* skip if still on last one */ continue; } /* are we chaining synapses? : this means that we will treat additional spks as */ /* if they were coming from another synapse */ if (psyn->chainlen > 1) { psyn->chainptr++; /* augment the pointer */ if (psyn->chainptr >= psyn->chainlen) { /* have run out of room */ if (t < psyn->spkt) { /* can't reset yet so just drop this spk */ continue; } else { /* the whole chain is completely done so can reset */ psyn->chainptr = 0; } } ind = psyn->index + psyn->chainptr; /* add index of next one on chain */ } else { ind = psyn->index; } /* qpr = the post-syn queu pointer */ qpr = psyn->qpt; /* qp = pointer to postsyn queu */ qp = qpr->qq; nspk = (int)(*(qpr->nspk)); time = t + psyn->del; psyn->spkt = t + qpr->dead; /* when it will all end */ /* basic queu code taken from queu.inc (viz.) but now must make sure */ /* that we don't go backwards in time (different delays) */ /* should have been cleared if we are to write here */ if (qp[nspk].time != 1e20) { // -- REMOVED THIS ERROR!! printf("WARNING: QUEUE ANOMALY: %x %g %g ",qpr->qq,*(qpr->nspk),*(qpr->qln)); // hoc_execerror("Error: queue full.\n",0); } if (qpr->qterm < time) { /* queu marching forward in time: AOK */ /* push the two queu items: a time and an index */ (qp[nspk]).time = time; /* delay */ (qp[nspk]).index = ind; /* tell postsyn which presyn spiked */ qpr->qterm = time; /* keep track of largest time put on */ } else { /* move backward to insert in right place */ /* actually a heap rather than a queue since maintains order */ qend = (int)(*(qpr->qln)) - 1; /* max ind for queu */ head = (int)(*(qpr->head)) - 1; /* one in front of the head */ if (head == -1) { head = qend; } /* wrap around */ /* search backward */ for (jj=((nspk==0)?qend:nspk-1); time < qp[jj].time && jj != head; jj=((jj==0)?qend:jj-1)); /* skip over from end */ if (jj==nspk) { printf("%g %d %d ",qpr->qterm,ii,jj); hoc_execerror("ERROR: newspike search failed.\n",0); } /* move things forward */ for (jj=((jj==qend)?0:jj+1); /* start one up */ jj != nspk; /* till back where we were */ jj=((jj==qend)?0:jj+1)) { swapt = qp[jj].time; /* store temporarily */ swapi = qp[jj].index; qp[jj].time = time; /* put in the new one */ qp[jj].index = ind; time = swapt; /* swap them */ ind = swapi; } qp[jj].time = time; qp[jj].index = ind; } /* move the tail forward and reset if reached the end */ (*(qpr->nspk))++; if ((*(qpr->nspk)) == *(qpr->qln)) { (*(qpr->nspk)) = 0.; printf("Cycling around for %x\n",qpr->qq);} } } ENDVERBATIM } : eliminates empty pointers in presyn array, moving everything else down PROCEDURE clean() { VERBATIM { int ii,jj,newn; SynS** pl; pl = PRECAST->plst; for(ii=0,jj=0,newn=nsyn; ii<nsyn; ii++,jj++) { while (pl[ii] == (SynS *)NULL && ii<nsyn) { ii++; newn--; } if (ii != jj && ii<nsyn) { pl[jj] = pl[ii]; pl[jj]->back = &(pl[jj]); } } nsyn = newn; } ENDVERBATIM } : prints out some selected information from the presyn structure, synlist FUNCTION check() { VERBATIM { int ii; for (ii=0,_lcheck=0; ii<nsyn && _lcheck!=-1.; ii++) { if (PRECAST->plst[ii] != (SynS *)NULL) { _lcheck++; /* count the active pointers */ if ((&(PRECAST->plst[ii])) != (PRECAST->plst[ii]->back)) { printf("****************************************************************\n"); printf("ERROR:: %2d: Index:%3d,C%09d,Pr%09d,Po%09d, Delay:%6g (%x->%x->%x)\n", ii, PRECAST->plst[(int)ii]->index, PRECAST->plst[(int)ii]->ucode, PRECAST->cpre, PRECAST->plst[(int)ii]->qpt->cpost, PRECAST->plst[(int)ii]->del, &(PRECAST->plst[(int)ii]), PRECAST->plst[(int)ii], (PRECAST->plst[(int)ii]->back)); printf("****************************************************************\n"); _lcheck = -1.0; } } } } ENDVERBATIM } : return ucode FUNCTION code() { VERBATIM { int ii; if (ifarg(1)) { ii = (int)*getarg(1); if (ii < 0) { ii = nsyn+ii; } if (ii >= nsyn || ii < 0) {hoc_execerror("array index out of bounds", 0);} _lcode = ((PRECAST->plst[ii] == (SynS *)NULL)?-2:PRECAST->plst[ii]->ucode); } else { for (ii=0;ii<nsyn;ii++) { if (PRECAST->plst[ii] == (SynS *)NULL) { printf("%d EMPTY.\n",ii); } else { printf("%d,%09d ",ii,PRECAST->plst[ii]->ucode); } } _lcode = 1.0; } } ENDVERBATIM } : return delay FUNCTION delay() { VERBATIM { int ii; if (ifarg(1)) { ii = (int)*getarg(1); if (ii < 0) { ii = nsyn+ii; } if (ii >= nsyn || ii < 0) {hoc_execerror("array index out of bounds", 0);} _ldelay = ((PRECAST->plst[ii] == (SynS *)NULL)?-2:PRECAST->plst[ii]->del); } else { for (ii=0;ii<nsyn;ii++) { if (PRECAST->plst[ii] == (SynS *)NULL) { printf("%d EMPTY.\n",ii); } else { printf("%d,%g ",ii,PRECAST->plst[ii]->del); } } _ldelay = 1.0; } } ENDVERBATIM } : return or set cpre code FUNCTION pre() { VERBATIM { if (ifarg(2)) { PRECAST->cpre = (int)*getarg(2); } _lpre = PRECAST->cpre; } ENDVERBATIM } : return cpost code : 0 arg: prints out information from the postsyn structure : 1 arg = -1 print out the pointer structure : plst[i] remains only indication of eliminated pointer FUNCTION post() { VERBATIM { int xx,ii; xx = -2; if (ifarg(1)) { xx = (int)*getarg(1); } if (xx >= 0) { if (xx >= nsyn) {hoc_execerror("array index out of bounds", 0);} _lpost = ((PRECAST->plst[xx] == (SynS *)NULL)?-2:PRECAST->plst[xx]->qpt->cpost); } else { for (ii=0;ii<nsyn;ii++) { if (PRECAST->plst[ii] == (SynS *)NULL) { printf("%2d EMPTY.\n",ii); } else { printf("%1d (%1d) Del:%-4g Cd:%09d Pre:%09d Post:%09d\n", ii, PRECAST->plst[ii]->index, PRECAST->plst[ii]->del, PRECAST->plst[ii]->ucode, PRECAST->cpre, PRECAST->plst[ii]->qpt->cpost); if (xx == -1 || (&(PRECAST->plst[ii])) != (PRECAST->plst[ii]->back)) { printf("\t\t%s: %x -> %x\n", (((&(PRECAST->plst[ii]))==(PRECAST->plst[ii]->back))? "OK":"POINTER MISMATCH"), &(PRECAST->plst[ii]), PRECAST->plst[ii]); } } } _lpost = 1.0; } } ENDVERBATIM } : for debugging - prints out queu info from the pre side PROCEDURE prq(x) { VERBATIM { int ii; SynS *psyn; QptR *qpr; psyn = PRECAST->plst[(int)_lx]; qpr = psyn->qpt; printf("%x %g %g\n",qpr->qq,*(qpr->nspk),*(qpr->qln)); for (ii=0;ii<*(qpr->qln);ii++) { printf("%8g%8d\n", ((qpr->qq)[ii]).time, ((qpr->qq)[ii]).index); } } ENDVERBATIM }