: $Id: tsa.mod,v 1.18 2011/10/25 21:45:39 billl Exp $ NEURON { SUFFIX tsa GLOBAL INSTALLED GLOBAL verbose } PARAMETER { INSTALLED=0 verbose=0 } VERBATIM #include "misc.h" static double *x1x, *y1y, *z1z; //void spctrm(double data[], double p[], int m, int k); extern double dfftpow(double* x,int n,double* ppow,int powlen,int* fftlen); #define WINDOW(j,a,b) (1.0-fabs((((j)-1)-(a))*(b))) /* Bartlett */ double *nrvector(long nl, long nh) /* allocate a double vector with subscript range v[nl..nh] */ { double *v; v=(double *)malloc((size_t) ((nh-nl+1+1)*sizeof(double))); if (!v) { nrerror("allocation failure in vector()"); return 0x0;} return v-nl+1; } void nrfree_vector(double *v, long nl, long nh) /* free a double vector allocated with vector() */ { free((char*) (v+nl-1)); } #define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr static double nrsqrarg; #define SQR(a) ((nrsqrarg=(a)) == 0.0 ? 0.0 : nrsqrarg*nrsqrarg) void nrfour1(double mdata[], unsigned long nn, int isign) { unsigned long n,mmax,m,j,istep,i; double wtemp,wr,wpr,wpi,wi,theta; double tempr,tempi; n=nn << 1; j=1; for (i=1;i i) { SWAP(mdata[j],mdata[i]); SWAP(mdata[j+1],mdata[i+1]); } m=n >> 1; while (m >= 2 && j > m) { j -= m; m >>= 1; } j += m; } mmax=2; while (n > mmax) { istep=mmax << 1; theta=isign*(6.28318530717959/mmax); wtemp=sin(0.5*theta); wpr = -2.0*wtemp*wtemp; wpi=sin(theta); wr=1.0; wi=0.0; for (m=1;m y ? x : y; } /* ********************************************************************* */ void mysvd(int m, int n, double** u, double w[], double** v, int* ierr) /* * This subroutine is a translation of the Algol procedure svd, * Num. Math. 14, 403-420(1970) by Golub and Reinsch. * Handbook for Auto. Comp., Vol II-Linear Algebra, 134-151(1971). * * This subroutine determines the singular value decomposition * t * A=usv of a real m by n rectangular matrix, where m is greater * then or equal to n. Householder bidiagonalization and a variant * of the QR algorithm are used. * * * On input. * * m is the number of rows of A (and u). * * n is the number of columns of A (and u) and the order of v. * * u contains the rectangular input matrix A to be decomposed. * * On output. * * w contains the n (non-negative) singular values of a (the * diagonal elements of s). they are unordered. if an * error exit is made, the singular values should be correct * for indices ierr+1,ierr+2,...,n. * * u contains the matrix u (orthogonal column vectors) of the * decomposition. * if an error exit is made, the columns of u corresponding * to indices of correct singular values should be correct. * * v contains the matrix v (orthogonal) of the decomposition. * if an error exit is made, the columns of v corresponding * to indices of correct singular values should be correct. * * ierr is set to * zero for normal return, * k if the k-th singular value has not been * determined after 30 iterations, * -1 if memory allocation fails. * * Questions and comments should be directed to B. S. Garbow, * Applied Mathematics division, Argonne National Laboratory * * Modified to eliminate machep * * Translated to C by Michiel de Hoon, Human Genome Center, * University of Tokyo, for inclusion in the C Clustering Library. * This routine is less general than the original svd routine, as * it focuses on the singular value decomposition as needed for * clustering. In particular, * - We require m >= n * - We calculate both u and v in all cases * - We pass the input array A via u; this array is subsequently * overwritten. * - We allocate for the array rv1, used as a working space, * internally in this routine, instead of passing it as an * argument. If the allocation fails, svd sets *ierr to -1 * and returns. * 2003.06.05 */ { int i, j, k, i1, k1, l1, its; double c,f,h,s,x,y,z; int l = 0; double g = 0.0; double scale = 0.0; double anorm = 0.0; double* rv1 = (double*)malloc(n*sizeof(double)); if (!rv1) { *ierr = -1; return; } *ierr = 0; /* Householder reduction to bidiagonal form */ for (i = 0; i < n; i++) { l = i + 1; rv1[i] = scale * g; g = 0.0; s = 0.0; scale = 0.0; for (k = i; k < m; k++) scale += fabs(u[k][i]); if (scale != 0.0) { for (k = i; k < m; k++) { u[k][i] /= scale; s += u[k][i]*u[k][i]; } f = u[i][i]; g = (f >= 0) ? -sqrt(s) : sqrt(s); h = f * g - s; u[i][i] = f - g; if (i < n-1) { for (j = l; j < n; j++) { s = 0.0; for (k = i; k < m; k++) s += u[k][i] * u[k][j]; f = s / h; for (k = i; k < m; k++) u[k][j] += f * u[k][i]; } } for (k = i; k < m; k++) u[k][i] *= scale; } w[i] = scale * g; g = 0.0; s = 0.0; scale = 0.0; if (i= 0) ? -sqrt(s) : sqrt(s); h = f * g - s; u[i][l] = f - g; for (k = l; k < n; k++) rv1[k] = u[i][k] / h; for (j = l; j < m; j++) { s = 0.0; for (k = l; k < n; k++) s += u[j][k] * u[i][k]; for (k = l; k < n; k++) u[j][k] += s * rv1[k]; } for (k = l; k < n; k++) u[i][k] *= scale; } } anorm = mymax(anorm,fabs(w[i])+fabs(rv1[i])); } /* accumulation of right-hand transformations */ for (i = n-1; i>=0; i--) { if (i < n-1) { if (g != 0.0) { for (j = l; j < n; j++) v[j][i] = (u[i][j] / u[i][l]) / g; /* double division avoids possible underflow */ for (j = l; j < n; j++) { s = 0.0; for (k = l; k < n; k++) s += u[i][k] * v[k][j]; for (k = l; k < n; k++) v[k][j] += s * v[k][i]; } } } for (j = l; j < n; j++) { v[i][j] = 0.0; v[j][i] = 0.0; } v[i][i] = 1.0; g = rv1[i]; l = i; } /* accumulation of left-hand transformations */ for (i = n-1; i >= 0; i--) { l = i + 1; g = w[i]; if (i!=n-1) for (j = l; j < n; j++) u[i][j] = 0.0; if (g!=0.0) { if (i!=n-1) { for (j = l; j < n; j++) { s = 0.0; for (k = l; k < m; k++) s += u[k][i] * u[k][j]; /* double division avoids possible underflow */ f = (s / u[i][i]) / g; for (k = i; k < m; k++) u[k][j] += f * u[k][i]; } } for (j = i; j < m; j++) u[j][i] /= g; } else for (j = i; j < m; j++) u[j][i] = 0.0; u[i][i] += 1.0; } /* diagonalization of the bidiagonal form */ for (k = n-1; k >= 0; k--) { k1 = k-1; its = 0; while(1) /* test for splitting */ { for (l = k; l >= 0; l--) { l1 = l-1; if (fabs(rv1[l]) + anorm == anorm) break; /* rv1[0] is always zero, so there is no exit * through the bottom of the loop */ if (fabs(w[l1]) + anorm == anorm) /* cancellation of rv1[l] if l greater than 0 */ { c = 0.0; s = 1.0; for (i = l; i <= k; i++) { f = s * rv1[i]; rv1[i] *= c; if (fabs(f) + anorm == anorm) break; g = w[i]; h = sqrt(f*f+g*g); w[i] = h; c = g / h; s = -f / h; for (j = 0; j < m; j++) { y = u[j][l1]; z = u[j][i]; u[j][l1] = y * c + z * s; u[j][i] = -y * s + z * c; } } break; } } /* test for convergence */ z = w[k]; if (l==k) /* convergence */ { if (z < 0.0) /* w[k] is made non-negative */ { w[k] = -z; for (j = 0; j < n; j++) v[j][k] = -v[j][k]; } break; } else if (its==30) { *ierr = k; break; } else /* shift from bottom 2 by 2 minor */ { its++; x = w[l]; y = w[k1]; g = rv1[k1]; h = rv1[k]; f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y); g = sqrt(f*f+1.0); f = ((x - z) * (x + z) + h * (y / (f + (f >= 0 ? g : -g)) - h)) / x; /* next qr transformation */ c = 1.0; s = 1.0; for (i1 = l; i1 <= k1; i1++) { i = i1 + 1; g = rv1[i]; y = w[i]; h = s * g; g = c * g; z = sqrt(f*f+h*h); rv1[i1] = z; c = f / z; s = h / z; f = x * c + g * s; g = -x * s + g * c; h = y * s; y = y * c; for (j = 0; j < n; j++) { x = v[j][i1]; z = v[j][i]; v[j][i1] = x * c + z * s; v[j][i] = -x * s + z * c; } z = sqrt(f*f+h*h); w[i1] = z; /* rotation can be arbitrary if z is zero */ if (z!=0.0) { c = f / z; s = h / z; } f = c * g + s * y; x = -s * g + c * y; for (j = 0; j < m; j++) { y = u[j][i1]; z = u[j][i]; u[j][i1] = y * c + z * s; u[j][i] = -y * s + z * c; } } rv1[l] = 0.0; rv1[k] = f; w[k] = x; } } } free(rv1); return; } int mycompare( const void* a, const void* b ) { double* arg1 = (double*) a; double* arg2 = (double*) b; if( *arg1 < *arg2 ) return -1; else if( *arg1 == *arg2 ) return 0; else return 1; } double* myspectrum(double* v1,int dc,int* anslen){ // n data pts will be divided into k partitions of size m // the spectrum will have m values from 0 to m/2 cycles/dt. // n = (2*k+1)*m // data set // Vect* v1 = vector_arg(1); // int dc = v1->capacity(); int mr; // if (ifarg(2)) mr = (int)(*getarg(2)); else mr = dc/8; mr = dc / 8; // make sure the length of partitions is integer power of 2 int m = 1; while(melem(i); //if (ans->capacity() < m) ans->resize(m); double* ans = (double *)calloc(m,(unsigned)sizeof(double)); //spctrm(&mdata[0], &ans->elem(0)-1, m, k); nrspctrm(&mdata[0], &ans[0], m, k); free((char *)mdata); return ans; } double myspct(void* v){ double* x; int n = vector_instance_px(v,&x) , anslen = 0 , i = 0; double* ans = myspectrum(x,n,&anslen); for(i=0;i=dmin && x[i]<=dmax) cnt++; return cnt; } double inrange(void* v){ double* x , dmin, dmax; int sz = vector_instance_px(v,&x) , i , cnt = 0; return (double) iinrange(x,sz,*getarg(1),*getarg(2)); } extern double dfftpow(double* x,int n,double* ppow,int powlen,int* fftlen); ENDVERBATIM : get averagecorrelations between channels, but first bandpass filter them : tscoravgband(output vector,vec-list of eeg time series,window size,increment,vec:60/120Hz power,vec:saturation, : vec:delta power,vec:theta,vec:beta,vec:gamma,vec:ripple,sampling rate,vec:low-cutoffs,vec:high-cutoffs, [optional : output list of vectors for filtered time-series] : -- : low and high cutoffs are different bands that will be kept, so can do theta+gamma, i.e. lo=4,31 , hi=12,100 : or can just do theta : lo=4 , hi=12 FUNCTION tscoravgband () { VERBATIM int i; double dRet = 0.0; ListVec* pTS = 0; double* pcvin = 0; double** pfilter = 0x0; double** pTSN = 0; // normalized time series double* vTCor = 0; //correlation matrix abs sum avg for a time point int corsz = vector_arg_px(1,&vTCor); double* pTMP = 0x0; ListVec* pTSOut = 0; pTS = AllocListVec(*hoc_objgetarg(2)); //list of eeg time series if(!pTS){ printf("tscoravg ERRA: problem initializing 1st 2 args!\n"); goto CLEANUP; } int iChans = pTS->isz; // # of channels if(iChans < 2) { printf("tscoravg ERRB: must have at least 2 EEG channels!\n"); goto CLEANUP; } int iWinSz = (int) *getarg(3); //window size for analysis int iSamples = pTS->plen[0]; //make sure all time series have same length int iINC = ifarg(4)?(int)*getarg(4):1; double *phz = 0, *psat = 0, *pfft = 0; int sz = 0 , iNoiseTest = 0; if(ifarg(5) && ifarg(6)){ //do saturation and 60/120 Hz Frequency test if((sz=vector_arg_px(5,&phz))!=corsz){ printf("tscoravg ERRG: invalid size for phz should be %d, is %d!\n",corsz,sz); goto CLEANUP; } else if((sz=vector_arg_px(6,&psat))!=corsz){ printf("tscoravg ERRH: invalid size for psat should be %d, is %d!\n",corsz,sz); goto CLEANUP; } else { iNoiseTest = 1; pfft = (double*)calloc(iWinSz+1,sizeof(double)); } } int iOutSz = (iSamples - iWinSz + 1) / iINC;//output List size double *pdelta=0,*ptheta=0,*pbeta=0,*pgamma=0,*pripple=0; if(ifarg(7) && vector_arg_px(7,&pdelta)M) M=N+1; pfilter = getdouble2D(iFilters,N); //normalize low/high cutoff frequencies by sampling rate (should be between 0 and 0.5) for(i=0;iplen[i] != iSamples){ printf("tscoravg ERRC: time series of unequal size %d %d!\n",iSamples,pTS->plen[i]); goto CLEANUP; } } if(corsz < iOutSz){ printf("tscoravg ERRD: need output vector of at least %d as arg 1, have only %d!\n",iOutSz,corsz); goto CLEANUP; } if(verbose) printf("iOutSz=%d\n",iOutSz); pTSN = getdouble2D(iChans,2*N); if(verbose) printf("got pTSN\n"); if(!pTSN){ printf("tscor ERRD: out of memory!\n"); goto CLEANUP; } if(ifarg(15) && (pTSOut = AllocListVec(*hoc_objgetarg(15)))) { //optional - copy filtered output if(pTSOut->isz!=iChans) { printf("incorrect output vec-list size: %d %d\n",pTSOut->isz,iChans); goto CLEANUP; } for(i=0;iplen[i] < iSamples) { printf("incorrect output vec-size %d %d\n",pTSOut->plen[i],iSamples); goto CLEANUP; }} pTMP = (double*) calloc(2*N,sizeof(double)); double* psums = (double*)calloc(iChans,sizeof(double)); //stores sum of values in channel's time window double* psums2 = (double*)calloc(iChans,sizeof(double));//stores sum of squared values in channel's time window double dVal = 0.0; int iStartIDX = 0 , ierr = 0 , iOutIDX = 0 , iFilt = 0; for(iOutIDX=0;iOutIDXpv[iChan][iStartIDX]; //saturation test for(IDX=iStartIDX;IDX=900. && *pc<=1010.) || (*pc>=-1010. && *pc<=-900.)) iSat++; dsatavg += (double)iSat/ (double)iWinSz; int fftlen = 0; memset(pfft,0,sizeof(double)*(iWinSz+1)); if(dfftpow(&pTS->pv[iChan][iStartIDX],iWinSz,pfft,iWinSz+1,&fftlen)){ //60,120 Hz Frequency test int f = 0; pfft[0]=0.0; double fsum = 0.0; double* ppf = pfft; for(f=0;fpv[iChan][iStartIDX], *pIN = pcvin; if(0) for(IDX=iStartIDX;IDXpv[iChan][iStartIDX]; for(IDX=iStartIDX;IDXplen[iChan];IDX++) pTSOut->pv[iChan][iStartIDX+IDX]=pTSN[iChan][IDX]; psums[iChan]=psums2[iChan]=0.; pC = pTSN[iChan]; //pointer to start of channel for(i=0;i 0. ) dstdev = sqrt(dstdev); else dstdev=1.; //make sure no problems with nan if(dstdev <= 0.) dstdev = 1.0; pC = pTSN[iChan]; //pointer to start of channel for(i=0;i 1.0 || dpsum < -1.0) printf("out of bounds = %g!\n",dpsum); vTCor[iOutIDX] = dpsum; } dRet = 1.0; printf("\n"); CLEANUP: if(pTS) FreeListVec(&pTS); if(pTSN) freedouble2D(&pTSN,iChans); free(psums); free(psums2); if(pfft) free(pfft); if(pfilter) freedouble2D(&pfilter,iFilters); if(pcvin) free(pcvin); if(pTMP) free(pTMP); if(pTSOut) FreeListVec(&pTSOut); return dRet; ENDVERBATIM } : normalize values in list of vectors FUNCTION tsnorm () { VERBATIM double dRet = 0.0; ListVec* pEIG = AllocListVec(*hoc_objgetarg(1)); if(!pEIG || pEIG->isz < 1 || pEIG->plen[0]<1){ printf("tsnorm ERRA: problem initializing 1st arg!\n"); goto TSNCLEANUP; } double* dmean = 0, *dstdev = 0; int cols = vector_arg_px(2,&dmean); if(cols!=vector_arg_px(3,&dstdev) || cols!=pEIG->plen[0]){ printf("tsnorm ERRB: problem initializing 2nd,3rd arg!\n"); goto TSNCLEANUP; } int i,j; double val; for(i=0;iisz;i++)for(j=0;jpv[i][j]=(pEIG->pv[i][j]-dmean[j])/dstdev[j]; dRet = 1.0; TSNCLEANUP: if(pEIG) FreeListVec(&pEIG); return dRet; ENDVERBATIM } VERBATIM int ddiff(double* pin,double* pout,int sz){ int i; for(i=0;i phzt : pfctr not used currently : 13 vector of file ids so can selectively clean up particular files : 14 file id to clean up -- iff == -1, do all : 15 % of 'bad' channels for each time period -- channels excluded for "avgC" / # of channels FUNCTION tsgetmeans () { VERBATIM int iC1,iC2,iChans,idx,jdx; double dRet = 0.0; ListVec *plvcor = 0, *plvhz = 0, *plvsat = 0, *plvderiv = 0; double* pavgA=0,*pavgB=0,*pavgC=0,*pprctbadch=0,*pfid=0,*pbadc=0; int vsz = 0, fid=-1; //////////////////////////////////////////////////////////////////////////////////////////////// // // set up input args. // if(!(plvcor = AllocListVec(*hoc_objgetarg(1)))){ printf("tsgetmeans ERRA: couldn't get cor vec list!\n"); goto MCLEANUP; } if(!(plvhz = AllocListVec(*hoc_objgetarg(2)))){ printf("tsgetmeans ERRB: couldn't get phz vec list!\n"); goto MCLEANUP; } if(plvhz->isz < plvcor->isz){ printf("tsgetmeans ERRC: phz vec list size < cor vec list size : %d %d\n",plvhz->isz,plvcor->isz); goto MCLEANUP; } if(!(plvsat = AllocListVec(*hoc_objgetarg(3)))){ printf("tsgetmeans ERRD: couldn't get psat vec list!\n"); goto MCLEANUP; } if(plvsat->isz < plvcor->isz){ printf("tsgetmeans ERRE: psat vec list size < cor vec list size : %d %d\n",plvsat->isz,plvcor->isz); goto MCLEANUP; } if(!(plvderiv = AllocListVec(*hoc_objgetarg(4)))){ printf("tsgetmeans ERRF: couldn't get pderiv vec list!\n"); goto MCLEANUP; } if(plvderiv->isz < plvcor->isz){ printf("tsgetmeans ERRG: pderiv vec list size < cor vec list size : %d %d\n",plvderiv->isz,plvcor->isz); goto MCLEANUP; } if(vector_arg_px(5,&pavgA) < plvcor->isz || vector_arg_px(6,&pavgB) < plvcor->isz || vector_arg_px(7,&pavgC) < plvcor->isz || vector_arg_px(13,&pfid) < plvcor->isz || vector_arg_px(15,&pprctbadch)< plvcor->isz){ printf("tsgetmeans ERRH: output vecs must have size >= %d!\n",plvcor->isz); goto MCLEANUP; } double phzt = *getarg(8), psatt = *getarg(9) , pderivt = *getarg(10); iChans = (int)*getarg(11); double pfctr = *getarg(12); fid = (int)*getarg(14); pbadc = (double*) malloc(iChans*sizeof(double)); // // //////////////////////////////////////////////////////////////////////////////////////////////// ///////// // do the calculations double dSumA,dSumB,dSumC; int cntA,cntB,cntC,cntBadCh; for(idx=0;idxisz;idx++){ if(fid>=0 && pfid[idx]!=fid) continue; cntA=cntB=cntC=jdx=0; dSumA=dSumB=dSumC=0.; for(iC1=0;iC1pv[idx][iC1] >= psatt || plvderiv->pv[idx][iC1] >= pderivt) pbadc[iC1]=1; else pbadc[iC1]=0; } for(iC1=0;iC1pv[idx][jdx]; cntA++; if(pbadc[iC2]) continue; dSumB += plvcor->pv[idx][jdx]; cntB++; } } pavgA[idx] = dSumA / (double) cntA; if(cntB) pavgB[idx] = dSumB / (double) cntB; else pavgB[idx] = -666.; jdx=0; for(iC1=0;iC1pv[idx][iC1] >= phzt) pbadc[iC1]=1; //mark bad channels for(iC1=0;iC1pv[idx][jdx]; cntC++; } } if(cntC) pavgC[idx] = dSumC / (double) cntC; else pavgC[idx] = -666.; cntBadCh=0; for(iC1=0;iC1isz)<1){ printf("tscorfull ERRA: problem initializing arg1 plvcor!\n"); goto FCLEANUP; } pTS = AllocListVec(*hoc_objgetarg(2)); //list of eeg time series if(!pTS){ printf("tscorfull ERRA: problem initializing arg2 pTS!\n"); goto FCLEANUP; } int iChans = pTS->isz; // # of channels if(iChans < 2) { printf("tscorfull ERRB: must have at least 2 timeseries!\n"); goto FCLEANUP; } int iMatSz = iChans*(iChans-1)/2; for(i=0;iplen[i]= %d, [%d] has only %d\n",iMatSz,i,plvcor->plen[i]); goto FCLEANUP; } } int iWinSz = (int) *getarg(3); //window size for analysis int iINC = ifarg(4)?(int)*getarg(4):1; //increment size for analysis plvhz = AllocListVec(*hoc_objgetarg(5)); plvsat = AllocListVec(*hoc_objgetarg(6)); plvderiv = AllocListVec(*hoc_objgetarg(7)); pfft = (double*)calloc(iWinSz+1,sizeof(double)); pdiff = (double*)calloc(iWinSz,sizeof(double)); int iSamples = pTS->plen[0]; //make sure all time series have same length int iOutSz = (iSamples - iWinSz + 1) / iINC;//output List size if(verbose) printf("iWinSz=%d iINC=%d iSamples=%d\n",iWinSz,iINC,iSamples); for(i=1;iplen[i] != iSamples){ printf("tscorfull ERRD: time series of unequal size %d %d!\n",iSamples,pTS->plen[i]); goto FCLEANUP; } } if(corsz < iOutSz){ printf("tscorfull ERRE: need output list vector of at least sz %d as arg 1, have only %d!\n",iOutSz,corsz); goto FCLEANUP; } if(verbose) printf("iOutSz=%d\n",iOutSz); if(plvhz->iszisziszplen[i]plen[i]plen[i]= %d!\n",iChans); goto FCLEANUP; } } pTSN = getdouble2D(iChans,iWinSz); if(verbose) printf("got pTSN\n"); //normalized time series if(!pTSN){ printf("tscor ERRD: out of memory!\n"); goto FCLEANUP; } psums = (double*)calloc(iChans,sizeof(double)); //for sum(X) psums2 = (double*)calloc(iChans,sizeof(double)); //for sum(X^2) double* pc = 0; double dVal = 0.0; int iStartIDX = 0 , ierr = 0 , iOutIDX = 0; FillListVec(plvcor,0.0); FillListVec(plvhz,0.); FillListVec(plvsat,0.); FillListVec(plvderiv,0.);//zero results for(iStartIDX=0;iOutIDXpv[iChan][iStartIDX]; for(IDX=iStartIDX;IDX 0. ) dstdev = sqrt(dstdev); else dstdev=1.; //make sure no problems with nan if(dstdev <= 0.) dstdev = 1.0; //saturation test int iSat = 0; pc = &pTS->pv[iChan][iStartIDX]; for(IDX=iStartIDX;IDX=900. && *pc<=1010.) || (*pc>=-1010. && *pc<=-900.)) iSat++; pTSN[iChan][i] = (*pc - davg) / dstdev; //normalization } plvsat->pv[iOutIDX][iChan] = (double)iSat/ (double)iWinSz; //60,120 Hz Frequency test int fftlen = 0; memset(pfft,0,sizeof(double)*(iWinSz+1)); if(dfftpow(&pTS->pv[iChan][iStartIDX],iWinSz,pfft,iWinSz+1,&fftlen)){ int f = 0; pfft[0]=0.0; double fsum = 0.0; for(f=0;fpv[iOutIDX][iChan]; for(f=55;f<=65 && fpv[iChan][iStartIDX],pdiff,iWinSz); plvderiv->pv[iOutIDX][iChan] = (double)iinrange(pdiff, iWinSz-1, -1.0, 1.0) / (double)(iWinSz-1.0); } //form correlation vector int iC1,iC2; pc = &plvcor->pv[iOutIDX][0]; for(iC1=0;iC1isz; // # of channels if(iChans < 2) { printf("tscoravg ERRB: must have at least 2 EEG channels!\n"); goto CLEANUP; } int iWinSz = (int) *getarg(3); //window size for analysis int iSamples = pTS->plen[0]; //make sure all time series have same length int iINC = ifarg(4)?(int)*getarg(4):1; double *phz = 0, *psat = 0, *pfft = 0; int sz = 0 , iNoiseTest = 0; if(ifarg(5) && ifarg(6)){ //do saturation and 60/120 Hz Frequency test if((sz=vector_arg_px(5,&phz))!=corsz){ printf("tscoravg ERRG: invalid size for phz should be %d, is %d!\n",corsz,sz); goto CLEANUP; } else if((sz=vector_arg_px(6,&psat))!=corsz){ printf("tscoravg ERRH: invalid size for psat should be %d, is %d!\n",corsz,sz); goto CLEANUP; } else { iNoiseTest = 1; pfft = (double*)calloc(iWinSz+1,sizeof(double)); } } int idoabs = ifarg(7)?(int)*getarg(7):0; //do abs or not int iOutSz = (iSamples - iWinSz + 1) / iINC;//output List size double *pdelta=0,*ptheta=0,*pbeta=0,*pgamma=0,*pripple=0; if(ifarg(8) && vector_arg_px(8,&pdelta)plen[i] != iSamples){ printf("tscoravg ERRC: time series of unequal size %d %d!\n",iSamples,pTS->plen[i]); goto CLEANUP; } } if(corsz < iOutSz){ printf("tscoravg ERRD: need output vector of at least %d as arg 1, have only %d!\n",iOutSz,corsz); goto CLEANUP; } if(verbose) printf("iOutSz=%d\n",iOutSz); pCorrel = getdouble2D(iChans,iChans); if(verbose) printf("got pCorrel\n"); pTSN = getdouble2D(iChans,iWinSz); if(verbose) printf("got pTSN\n"); if(!pCorrel || !pTSN){ printf("tscor ERRD: out of memory!\n"); goto CLEANUP; } double* psums = (double*)calloc(iChans,sizeof(double)); double* psums2 = (double*)calloc(iChans,sizeof(double)); double dVal = 0.0; int iStartIDX = 0 , ierr = 0 , iOutIDX = 0; for(iOutIDX=0;iOutIDX 1){ for(iChan=0;iChanpv[iChan][IDX]; psums[iChan] += dVal; psums2[iChan] += dVal*dVal; } } } else { for(iChan=0;iChanpv[iChan][iStartIDX-1]; psums[iChan] -= dVal; psums2[iChan] -= dVal*dVal; dVal = pTS->pv[iChan][iEndIDX-1]; psums[iChan] += dVal; psums2[iChan] += dVal*dVal; } } double dsatavg = 0., dhzavg = 0.; for(iChan=0;iChan 0. ) dstdev = sqrt(dstdev); else dstdev=1.; //make sure no problems with nan if(dstdev <= 0.) dstdev = 1.0; if(iNoiseTest){ //saturation test int iSat = 0; for(IDX=iStartIDX;IDXpv[iChan][IDX]; if((dVal>=900. && dVal<=1010.) || (dVal>=-1010. && dVal<=-900.)) iSat++; pTSN[iChan][i] = (dVal - davg) / dstdev; } dsatavg += (double)iSat/ (double)iWinSz; //60,120 Hz Frequency test int fftlen = 0; memset(pfft,0,sizeof(double)*(iWinSz+1)); if(dfftpow(&pTS->pv[iChan][iStartIDX],iWinSz,pfft,iWinSz+1,&fftlen)){ int f = 0; pfft[0]=0.0; double fsum = 0.0; for(f=0;fpv[iChan][IDX]; pTSN[iChan][i] = (dVal - davg) / dstdev; } } } if(iNoiseTest){ phz[iOutIDX] = dhzavg / (double)iChans; psat[iOutIDX] = dsatavg / (double)iChans; if(pdelta) pdelta[iOutIDX] /= (double)iChans; if(ptheta) ptheta[iOutIDX] /= (double)iChans; if(pbeta) pbeta[iOutIDX] /= (double)iChans; if(pgamma) pgamma[iOutIDX] /= (double)iChans; if(pripple) pripple[iOutIDX] /= (double)iChans; } //form correlation matrix int iC1,iC2; for(iC1=0;iC1 1. || dpsum < -1.){ printf("out of bounds = %g!\n",dpsum); } vTCor[iOutIDX] = dpsum; } dRet = 1.0; printf("\n"); CLEANUP: if(pTS) FreeListVec(&pTS); if(pCorrel) freedouble2D(&pCorrel,iChans); if(pTSN) freedouble2D(&pTSN,iChans); free(psums); free(psums2); if(pfft) free(pfft); return dRet; ENDVERBATIM } FUNCTION tscor () { VERBATIM int i; double dRet = 0.0; ListVec* pEIG = 0, *pTS = 0; double** pTSN = 0; // normalized time series double** pCorrel = 0; //correlation matrix double** pV = 0; double* pW = 0; // eigs pEIG = AllocListVec(*hoc_objgetarg(1)); //list of eigenvalue vectors, one for each time pTS = AllocListVec(*hoc_objgetarg(2)); //list of eeg time series if(!pEIG || !pTS){ printf("tscor ERRA: problem initializing 1st 2 args!\n"); goto CLEANUP; } int iChans = pTS->isz; // # of channels if(iChans < 2) { printf("tscor ERRB: must have at least 2 EEG channels!\n"); goto CLEANUP; } int iWinSz = (int) *getarg(3); //window size for analysis int iINC = (int) *getarg(4); //increment for analysis int iSamples = pTS->plen[0]; //make sure all time series have same length if(verbose) printf("iWinSz=%d iINC=%d iSamples=%d\n",iWinSz,iINC,iSamples); for(i=1;iplen[i] != iSamples){ printf("tscor ERRC: time series of unequal size %d %d!\n",iSamples,pTS->plen[i]); goto CLEANUP; } } int iOutSz = (iSamples - iWinSz + 1) / iINC;//output List size if(pEIG->isz < iOutSz){ printf("tscor ERRD: need List of size at least %d as arg 1, have only %d!\n",iOutSz,pEIG->isz); goto CLEANUP; } if(verbose) printf("iOutSz=%d\n",iOutSz); pCorrel = getdouble2D(iChans,iChans); if(verbose) printf("got pCorrel\n"); pTSN = getdouble2D(iChans,iWinSz); if(verbose) printf("got pTSN\n"); pV = getdouble2D(iChans,iChans); if(verbose) printf("got pV\n"); pW = (double*) malloc(sizeof(double)*iChans); if(verbose) printf("got pW\n"); if(!pCorrel || !pTSN || !pV || !pW){ printf("tscor ERRD: out of memory!\n"); goto CLEANUP; } double dVal = 0.0; int iStartIDX = 0 , ierr = 0 , iTIDX = 0; for(iStartIDX=0;iStartIDX+iWinSzpv[iChan][IDX]; dSum += dVal; dSum2 += dVal*dVal; } dSum /= iCurSz; //mean dSum2 /= iCurSz; dSum2 -= dSum*dSum; dSum2 = sqrt(dSum2); //standard deviation i=0; for(IDX=iStartIDX;IDXpv[iChan][IDX] - dSum) / dSum2; } } //form correlation matrix int iC1,iC2; for(iC1=0;iC1pv[iTIDX][i] = pW[i]; //store sorted eigenvalues memcpy(pEIG->pv[iTIDX],pW,sizeof(double)*iChans); //store sorted eigenvalues } dRet = 1.0; printf("\n"); CLEANUP: if(pEIG) FreeListVec(&pEIG); if(pTS) FreeListVec(&pTS); if(pCorrel) freedouble2D(&pCorrel,iChans); if(pTSN) freedouble2D(&pTSN,iChans); if(pW) free(pW); if(pV) freedouble2D(&pV,iChans); return dRet; ENDVERBATIM } VERBATIM double getmean(double* p,int n) { if(n<1) return 0.0; int i = 0; double sum = 0.0, *pp=p; for(i=0;i0.) return sqrt(X2); return 0.; } double dnormv(double* p,int n) { if(n<1) return 0.0; double X = getmean(p,n); double s = getstd(p,n,X); double* pp = p; int i; if(s>0.) for(i=0;i