: $Id: updown.mod,v 1.16 2009/02/16 22:56:52 billl Exp $ NEURON { SUFFIX nothing : BVBASE is bit vector base number (typically 0 or -1) GLOBAL UPDOWN_INSTALLED, SHM_UPDOWN, NOV_UPDOWN, DEBUG_UPDOWN } PARAMETER { UPDOWN_INSTALLED=0 DEBUG_UPDOWN=0 SHM_UPDOWN=4 : used in updown() for measuring sharpness NOV_UPDOWN=1 : used in updown() to eliminate overlap of spikes CREEP_UPDOWN=0 : used in updown() to allow left/right "creep" to local minima } VERBATIM #include #include #include // contains LONG_MAX #include extern double* hoc_pgetarg(); extern double hoc_call_func(Symbol*, int narg); extern FILE* hoc_obj_file_arg(int narg); extern Object** hoc_objgetarg(); extern void vector_resize(); extern int vector_instance_px(); extern void* vector_arg(); extern double* vector_vec(); extern double hoc_epsilon; extern double chkarg(); extern void set_seed(); extern int ivoc_list_count(Object*); extern Object* ivoc_list_item(Object*, int); extern int hoc_is_double_arg(int narg); extern char* hoc_object_name(Object*); char ** hoc_pgargstr(); int list_vector_px(); int list_vector_px2(); int list_vector_px3(); double *list_vector_resize(); int ismono1(); static void hxe() { hoc_execerror("",0); } static void hxf(void *ptr) { free(ptr); hoc_execerror("",0); } ENDVERBATIM :* src.updown(thresh,dlist,nqslist) : dest.updown(src) -- default thresh=0; returns indices : look for multiple threshold crossings to define peaks : creates multiple parallel vectors for an NQS db : counts peaks pointing upward -- should be all pos : see eg decnqs.hoc:fudup() for usage VERBATIM //** declarations #define UDSL 500 #define UDNQ 11 // nq=new NQS("LOC","PEAK","WIDTH","BASE","HEIGHT","START","SLICES","SHARP","INDEX","FILE","NESTED") #define LOC nq[0] // loc of peak of spike #define PEAK nq[1] // value at peak (absolute height) #define WIDTH nq[2] // rt flank - lt flanks (? isn't it rt flank - LOC ?) #define BASE nq[3] // height at base #define HEIGHT nq[4] // peak - base #define START nq[5] // left flank of spike? #define SLICES nq[6] // how many slices found this spike #define SHARP nq[7] // 2nd deriv at peak #define INDEX nq[8] // consecutive numbering of spikes // nq[9] // will use to fill in trace's file name at hoc level #define NESTED nq[10] // how many bumps are nested within this one //** procedure updown() static double updown (void* vv) { int i, k, m, n, nqsz, nsrc, jj[UDSL], f[UDSL], lc, dsz[UDSL], nqmax, thsz, lc2, done, dbn; double *src, *tvec, *th, *dest[UDSL], *nq[UDNQ], *tmp, *dbx, lt, thdist; Object *ob, *ob2; void *vvd[UDSL], *vvth, *vnq[UDNQ]; //** read in vectors and verify sizes, etc nsrc = vector_instance_px(vv, &src); // trace to analyze thsz = vector_arg_px(1, &th); // vector of thresholds to check ob = *hoc_objgetarg(2); // storage for values for each threshold ob2 = *hoc_objgetarg(3); // list of NQS vectors for returning values tmp = (double *)ecalloc(nsrc, sizeof(double)); // tmp is size of trace lc = ivoc_list_count(ob); lc2 = ivoc_list_count(ob2); if (lc>UDSL) {printf("updown ERRF mismatch: max slice list:%d %d\n",UDSL,lc); hxf(tmp);} if (lc2!=UDNQ){printf("updown ERRB mismatch: NQS sz is %d (%d in list)\n",UDNQ,lc2);hxf(tmp);} if (nsrcth[k];i++) {} // start somewhere below this thresh th[k] for (; ith[k]) { if (f[k]==0) { // ? passing thresh if (jj[k]>=dsz[k]){printf("(%d,%d,%d) :: ",k,jj[k],dsz[k]); hoc_execerror("Dest vec too small in updown ", 0); } dest[k][jj[k]++] = (i-1) + (th[k]-src[i-1])/(src[i]-src[i-1]); // interpolate f[k]=1; tmp[k]=-1e9; dest[k][jj[k]]=-1.; // flag in tmp says that a thresh found here } if (f[k]==1 && src[i]>tmp[k]) { // use tmp[] even more temporarily tmp[k]=src[i]; // pick out max dest[k][jj[k]] = (double)i; // location of this peak } } else { // below thresh if (f[k]==1) { // just passed going down jj[k]++; // triplet will be indices of cross-up/peak/cross-down dest[k][jj[k]++] = (i-1) + (src[i-1]-th[k])/(src[i-1]-src[i]); f[k]=0; } } } } //** truncate dest vectors to multiples of 3: for (k=0;k=nqmax) { printf("updown ERRG OOR in NQ db: %d %d\n",k,nqmax); hxf(tmp); } LOC[k]=(double)i; // approx location of the peak of the spike WIDTH[k]=tmp[i+1]; // location of right side -- temp storage START[k]=tmp[i-1]; // start of spike (left side) SLICES[k]=-tmp[i]; // # of slices k++; } nqsz=k; // k ends up as size of NQS db if (DEBUG_UPDOWN && ifarg(4)) { dbn=vector_arg_px(4, &dbx); // DEBUG -- save tmp vector if (dbn0 && START[i] < LOC[i-1]) { // flank is to left of prior center if (DEBUG_UPDOWN) printf("LT problem %d %g %g<%g\n",i,LOC[i],START[i],LOC[i-1]); for (m=lc-1,done=0;m>=0 && !done;m--) { // m:go from bottom (widest) to top for (n=1;nLOC[i-1]) { // ??[i]=START[i]; // temp storage for L end of this overlap // replace both left and right flanks at this level -- #1 above START[i]=dest[m][n-1]; WIDTH[i]=dest[m][n+1]; done=1; } } } } //*** now look at RT side if ((i+1)LOC[i+1]) { if (DEBUG_UPDOWN) printf("RT problem %d %g %g>%g\n",i,LOC[i],WIDTH[i],LOC[i+1]); for (m=lc-1,done=0;m>=0 && !done;m--) { // m: go from bottom to top for (n=1;n= 1 && src[idx] >= src[idx-1]) idx--; START[k] = idx; //move right side to local minima idx = (int)WIDTH[k]; while(idx < nsrc-1 && src[idx] >= src[idx+1]) idx++; WIDTH[k] = idx; k++; } //** 2nd loop through tmp[] used to fill in the rest of NQS // needed to split into 2 loops so that could check for overlaps and correct those // before filling in the rest of nq for (i=0,k=0; i= START[i] && LOC[j] <= START[i]+WIDTH[i]){ NESTED[i]+=1.0; } } } } else for(i=0;i