#include "mrilib.h" void usage_1ddot(int detail) { printf("Usage: 1ddot [options] 1Dfile 1Dfile ...\n" "* Prints out correlation matrix of the 1D files and\n" " their inverse correlation matrix.\n" "* Output appears on stdout.\n" "* Program 1dCorrelate does something similar-ish.\n" "\n" "Options:\n" " -one = Make 1st vector be all 1's.\n" " -dem = Remove mean from all vectors (conflicts with '-one')\n" " -cov = Compute with covariance matrix instead of correlation\n" " -inn = Computed with inner product matrix instead\n" " -rank = Compute Spearman rank correlation instead\n" " (also implies '-terse')\n" " -terse= Output only the correlation or covariance matrix\n" " and without any of the garnish. \n" " -okzero= Do not quit if a vector is all zeros.\n" " The correlation matrix will have 0 where NaNs ought to go.\n" " Expect rubbish in the inverse matrices if all zero \n" " vectors exist.\n" ) ; PRINT_COMPILE_DATE ; return; } /*----------------------------------------------------------------------------*/ int main( int argc , char *argv[] ) { int iarg , ii,jj,kk,mm , nvec , do_one=0 , nx=0,ny , ff, doterse = 0 ; MRI_IMAGE *tim ; MRI_IMARR *tar ; double sum , *eval , *amat , **tvec , *bmat , *svec ; float *far ; int demean=0 , docov=0 ; char *matname ; int okzero = 0; mainENTRY("1ddot main"); machdep(); /* options */ iarg = 1 ; nvec = 0 ; while( iarg < argc && argv[iarg][0] == '-' ){ if (strcmp(argv[iarg],"-help") == 0 || strcmp(argv[iarg],"-h") == 0){ usage_1ddot(strlen(argv[iarg])>3 ? 2:1); exit(0); } if( strcmp(argv[iarg],"-one") == 0 ){ demean = 0 ; do_one = 1 ; iarg++ ; continue ; } if( strcmp(argv[iarg],"-okzero") == 0 ){ okzero = 1 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-dem",4) == 0 ){ demean = 1 ; do_one = 0 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-cov",4) == 0 ){ docov = 1 ; iarg++ ; continue ; } if( strncmp(argv[iarg],"-inn",4) == 0 ){ docov = 2 ; iarg++ ; continue ; } if( strcasecmp(argv[iarg],"-rank") == 0 || strcasecmp(argv[iarg],"-spearman") == 0 ){ do_one = 0; docov = 3; demean = 0; doterse = 1; iarg++; continue; } if( strncmp(argv[iarg],"-terse",4) == 0 ){ doterse = 1 ; iarg++ ; continue ; } fprintf(stderr,"** Unknown option: %s\n",argv[iarg]); suggest_best_prog_option(argv[0], argv[iarg]); exit(1); } if( argc < 2 ){ usage_1ddot(1); exit(0) ; } if( iarg == argc ) ERROR_exit("No 1D files on command line!?") ; /* input 1D files */ ff = iarg ; INIT_IMARR(tar) ; if( do_one ) nvec = 1 ; for( ; iarg < argc ; iarg++ ){ tim = mri_read_1D( argv[iarg] ) ; if( tim == NULL ){ fprintf(stderr,"** Can't read 1D file %s\n",argv[iarg]); exit(1); } if( nx == 0 ){ nx = tim->nx ; } else if( tim->nx != nx ){ fprintf(stderr,"** 1D file %s doesn't match first file in length!\n", argv[iarg]); exit(1); } nvec += tim->ny ; ADDTO_IMARR(tar,tim) ; } if (!doterse) { printf("\n") ; printf("++ 1ddot input vectors:\n") ; } jj = 0 ; if( do_one ){ if (!doterse) printf("00..00: all ones\n") ; jj = 1 ; } for( mm=0 ; mm < IMARR_COUNT(tar) ; mm++ ){ tim = IMARR_SUBIM(tar,mm) ; if (!doterse) printf("%02d..%02d: %s\n", jj,jj+tim->ny-1, argv[ff+mm] ) ; jj += tim->ny ; } /* create vectors from 1D files */ tvec = (double **) malloc( sizeof(double *)*nvec ) ; svec = (double * ) malloc( sizeof(double )*nvec ) ; for( jj=0 ; jj < nvec ; jj++ ) tvec[jj] = (double *) malloc( sizeof(double)*nx ) ; kk = 0 ; if( do_one ){ svec[0] = 1.0 / sqrt((double)nx) ; for( ii=0 ; ii < nx ; ii++ ) tvec[0][ii] = 1.0 ; kk = 1 ; } for( mm=0 ; mm < IMARR_COUNT(tar) ; mm++ ){ tim = IMARR_SUBIM(tar,mm) ; far = MRI_FLOAT_PTR(tim) ; for( jj=0 ; jj < tim->ny ; jj++,kk++ ){ for( ii=0 ; ii < nx ; ii++ ) tvec[kk][ii] = far[ii+jj*nx] ; if( demean ){ sum = 0.0 ; for( ii=0 ; ii < nx ; ii++ ) sum += tvec[kk][ii] ; sum /= nx ; for( ii=0 ; ii < nx ; ii++ ) tvec[kk][ii] -= sum ; } sum = 0.0 ; for( ii=0 ; ii < nx ; ii++ ) sum += tvec[kk][ii] * tvec[kk][ii] ; if( sum == 0.0 ) { if (okzero) svec[kk] = 0.0; else ERROR_exit("Input column %02d is all zero!",kk) ; } else { svec[kk] = 1.0 / sqrt(sum) ; } } } DESTROY_IMARR(tar) ; /* normalize vectors? (for ordinary correlation) */ if( !docov ){ for( kk=0 ; kk < nvec ; kk++ ){ sum = svec[kk] ; for( ii=0 ; ii < nx ; ii++ ) tvec[kk][ii] *= sum ; } } switch(docov){ default: case 3: matname = "Spearman" ; break ; case 2: matname = "InnerProduct" ; break ; case 1: matname = "Covariance" ; break ; case 0: matname = "Correlation" ; break ; } /* create matrix from dot product of vectors */ amat = (double *) calloc( sizeof(double) , nvec*nvec ) ; if( docov != 3 ){ for( kk=0 ; kk < nvec ; kk++ ){ for( jj=0 ; jj <= kk ; jj++ ){ sum = 0.0 ; for( ii=0 ; ii < nx ; ii++ ) sum += tvec[jj][ii] * tvec[kk][ii] ; amat[jj+nvec*kk] = sum ; if( jj < kk ) amat[kk+nvec*jj] = sum ; } } } else { /* Spearman */ for( kk=0 ; kk < nvec ; kk++ ){ for( jj=0 ; jj <= kk ; jj++ ){ amat[jj+nvec*kk] = THD_spearman_corr_dble( nx , tvec[jj] , tvec[kk] ) ; if( jj < kk ) amat[kk+nvec*jj] = amat[jj+nvec*kk] ; } } } /* normalize */ if (docov==1) { for( kk=0 ; kk < nvec ; kk++ ){ for( jj=0 ; jj <= kk ; jj++ ){ sum = amat[jj+nvec*kk] / (double) (nx-1); amat[jj+nvec*kk] = sum; if( jj < kk ) amat[kk+nvec*jj] = sum ; } } } /* print matrix out */ if (!doterse) { printf("\n" "++ %s Matrix:\n ",matname) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %02d ",jj) ; printf("\n ") ; for( jj=0 ; jj < nvec ; jj++ ) printf(" ---------") ; printf("\n") ; } for( kk=0 ; kk < nvec ; kk++ ){ if (!doterse) printf("%02d:",kk) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %9.5f",amat[jj+kk*nvec]) ; printf("\n") ; } if (doterse) exit(0) ; /* au revoir */ /* compute eigendecomposition */ eval = (double *) malloc( sizeof(double)*nvec ) ; symeig_double( nvec , amat , eval ) ; printf("\n" "++ Eigensolution of %s Matrix:\n " , matname ) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %9.5f",eval[jj]) ; printf("\n ") ; for( jj=0 ; jj < nvec ; jj++ ) printf(" ---------") ; printf("\n") ; for( kk=0 ; kk < nvec ; kk++ ){ printf("%02d:",kk) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %9.5f",amat[kk+jj*nvec]) ; printf("\n") ; } /* compute matrix inverse */ if ( eval[0]/eval[nvec-1] < 1.0e-10) { printf("\n" "-- WARNING: Matrix is near singular,\n" " rubbish likely for inverses ahead.\n"); } for( jj=0 ; jj < nvec ; jj++ ) eval[jj] = 1.0 / eval[jj] ; bmat = (double *) calloc( sizeof(double) , nvec*nvec ) ; for( ii=0 ; ii < nvec ; ii++ ){ for( jj=0 ; jj < nvec ; jj++ ){ sum = 0.0 ; for( kk=0 ; kk < nvec ; kk++ ) sum += amat[ii+kk*nvec] * amat[jj+kk*nvec] * eval[kk] ; bmat[ii+jj*nvec] = sum ; } } printf("\n") ; printf("++ %s Matrix Inverse:\n " , matname ) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %02d ",jj) ; printf("\n ") ; for( jj=0 ; jj < nvec ; jj++ ) printf(" ---------") ; printf("\n") ; for( kk=0 ; kk < nvec ; kk++ ){ printf("%02d:",kk) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %9.5f",bmat[jj+kk*nvec]) ; printf("\n") ; } /* square roots of diagonals of the above */ printf("\n") ; printf("++ %s sqrt(diagonal)\n ",matname) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %9.5f",sqrt(bmat[jj+jj*nvec])) ; printf("\n") ; /* normalize matrix inverse */ for( ii=0 ; ii < nvec ; ii++ ){ for( jj=0 ; jj < nvec ; jj++ ){ sum = bmat[ii+ii*nvec] * bmat[jj+jj*nvec] ; if( sum > 0.0 ) amat[ii+jj*nvec] = bmat[ii+jj*nvec] / sqrt(sum) ; else amat[ii+jj*nvec] = 0.0 ; } } printf("\n") ; printf("++ %s Matrix Inverse Normalized:\n " , matname ) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %02d ",jj) ; printf("\n ") ; for( jj=0 ; jj < nvec ; jj++ ) printf(" ---------") ; printf("\n") ; for( kk=0 ; kk < nvec ; kk++ ){ printf("%02d:",kk) ; for( jj=0 ; jj < nvec ; jj++ ) printf(" %9.5f",amat[jj+kk*nvec]) ; printf("\n") ; } /* done */ exit(0) ; }