MRI_IMAGE * DES_get_psinv( int ntim , int nref , float **ref ) { MRI_IMAGE *refim , *psinv ; float *refar , *jar ; int ii , jj ; refim = mri_new(ntim,nref,MRI_float) ; refar = MRI_FLOAT_PTR(refim) ; for( jj=0 ; jj < nref ; jj++ ){ jar = refar + jj*ntim ; for( ii=0 ; ii < ntim ; ii++ ) jar[ii] = ref[jj][ii] ; } mri_matrix_psinv_svd(1) ; psinv = mri_matrix_psinv(refim,NULL,0.0f) ; mri_free(refim) ; return psinv ; }
MRI_IMAGE * LSS_setup( MRI_IMAGE *ima , MRI_IMAGE *imc ) { int nn, mm, nc, ii, jj, ic , nwarn=0 ; float *cc, *pp, *qq, *qj, *vv, *ss, *pv , cj, cvdot, pc ; MRI_IMAGE *ims , *imp , *imq ; MRI_IMARR *imar ; ENTRY("LSS_setup") ; if( ima == NULL || imc == NULL ){ /* bad user */ ERROR_message("LSS_setup: NULL input image?!") ; RETURN(NULL) ; } /* [A] is nn X mm ; [C] is nn x nc */ nn = ima->nx ; mm = ima->ny ; nc = imc->ny ; cc = MRI_FLOAT_PTR(imc) ; if( imc->nx != nn || nn <= mm+2 ){ /* stoopid user */ ERROR_message("LSS_setup: ima->nx=%d does not equal imc->nx=%d :-(" , ima->nx,imc->nx) ; RETURN(NULL) ; } /* get imp = [P] = psinv of [A] = mm X nn matrix imq = [Q] = ortproj onto column null space of [A] = nn X nn matrix */ mri_matrix_psinv_svd(1) ; imar = mri_matrix_psinv_ortproj( ima , 1 ) ; if( imar == NULL ){ /* should not happen */ ERROR_message("LSS_setup: cannot compute pseudo-inverse :-(") ; RETURN(NULL) ; } imp = IMARR_SUBIM(imar,0) ; pp = MRI_FLOAT_PTR(imp) ; imq = IMARR_SUBIM(imar,1) ; qq = MRI_FLOAT_PTR(imq) ; /* create output image = [S] = nn X nc Each column of [S] is the vector that we dot into a data vector [z] to get the estimate of gamma+delta for the corresponding column from [C] */ ims = mri_new(nn,nc,MRI_float) ; ss = MRI_FLOAT_PTR(ims) ; /* workspace vectors */ vv = (float *)malloc(sizeof(float)*nn) ; /* will be [Q] [c] */ pv = (float *)malloc(sizeof(float)*nn) ; /* last row of [P] */ for( ii=0 ; ii < nn ; ii++ ) pv[ii] = pp[ mm-1 + ii*mm ] ; /* loop over columns of [C] (and [S]) */ for( ic=0 ; ic < nc ; ic++,cc+=nn,ss+=nn ){ /* compute [v] = [Q] [c] */ for( ii=0 ; ii < nn ; ii++ ) vv[ii] = 0.0f ; /* initialize [v] to 0 */ for( jj=0 ; jj < nn ; jj++ ){ /* loop over columns of Q */ qj = qq + jj*nn ; /* ptr to jj-th column of Q */ cj = cc[jj] ; /* jj-th value of [c] */ for( ii=0 ; ii < nn ; ii++ ) vv[ii] += qj[ii] * cj ; /* sum into [v] */ } /* compute cvdot = [c] *dot* [v] cj = [c] *dot* [c] pc = [c] *dot* {last row of [P] = pv} */ for( pc=cj=cvdot=ii=0 ; ii < nn ; ii++ ){ cvdot += cc[ii]*vv[ii] ; cj += cc[ii]*cc[ii] ; pc += pv[ii]*cc[ii] ; } /* initialize [s] = last row of [P] */ for( ii=0 ; ii < nn ; ii++ ) ss[ii] = pv[ii] ; /* If cvdot is zero(ish), this means that the extra column [c] is collinear(ish) with the columns of [A], and we skip the next step. Note that since [Q] is an orthogonal matrix, we are guaranteed that L2norm([Q][c]) == L2norm([c]), which implies that abs(cvdot) <= abs(cj), by the triangle inequality. */ if( fabsf(cvdot) >= 1.e-5*cj ){ /* add the proper fraction of [v] into [s] */ pc = (1.0f - pc) / cvdot ; for( ii=0 ; ii < nn ; ii++ ) ss[ii] += pc * vv[ii] ; } else { nwarn++ ; } } /* end of loop over columns of [C] */ if( verb && nwarn > 0 ) INFO_message("%d (out of %d) LSS individual estimators were collinear", nwarn , nc ) ; /* toss the trash and return the output set of columns */ free(pv) ; free(vv) ; DESTROY_IMARR(imar) ; RETURN(ims) ; }