analyzer.cpp

Go to the documentation of this file.
00001 
00006 /*
00007  * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
00008  * Copyright (c) 2000-2006 Baylor College of Medicine
00009  *
00010  * This software is issued under a joint BSD/GNU license. You may use the
00011  * source code in this file under either license. However, note that the
00012  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00013  * so you are responsible for compliance with the licenses of these packages
00014  * if you opt to use BSD licensing. The warranty disclaimer below holds
00015  * in either instance.
00016  *
00017  * This complete copyright notice must be included in any revised version of the
00018  * source code. Additional authorship citations may be added, but existing
00019  * author citations must be preserved.
00020  *
00021  * This program is free software; you can redistribute it and/or modify
00022  * it under the terms of the GNU General Public License as published by
00023  * the Free Software Foundation; either version 2 of the License, or
00024  * (at your option) any later version.
00025  *
00026  * This program is distributed in the hope that it will be useful,
00027  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00028  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00029  * GNU General Public License for more details.
00030  *
00031  * You should have received a copy of the GNU General Public License
00032  * along with this program; if not, write to the Free Software
00033  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00034  *
00035  * */
00036 
00037 #include <ctime>
00038 #include <memory>
00039 #include "emdata.h"
00040 #include "analyzer.h"
00041 #include "sparx/analyzer_sparx.h"
00042 #include "util.h"
00043 #include "cmp.h"
00044 #include "sparx/lapackblas.h"
00045 #include "sparx/varimax.h"
00046 
00047 using namespace EMAN;
00048 
00049 namespace EMAN {
00050 
00051         template <> Factory < Analyzer >::Factory()
00052         {
00053                 force_add(&PCAsmall::NEW);
00054                 force_add(&PCAlarge::NEW);
00055                 force_add(&varimax::NEW);
00056                 force_add(&KMeansAnalyzer::NEW);
00057                 force_add(&SVDAnalyzer::NEW);
00058         }
00059 
00060 }
00061 
00062 int Analyzer::insert_images_list(vector<EMData *> image_list)
00063 {
00064         vector<EMData *>::const_iterator iter;
00065                 for(iter=image_list.begin(); iter!=image_list.end(); ++iter) {
00066                         insert_image(*iter);
00067                 }
00068         return 0;
00069 }
00070 
00071 void KMeansAnalyzer::set_params(const Dict & new_params)
00072 {
00073         params = new_params;
00074         if (params.has_key("ncls")) ncls = params["ncls"];
00075         if (params.has_key("maxiter"))maxiter = params["maxiter"];
00076         if (params.has_key("minchange"))minchange = params["minchange"];
00077         if (params.has_key("mininclass"))mininclass = params["mininclass"];
00078         if (params.has_key("slowseed"))slowseed = params["slowseed"];
00079         if (params.has_key("verbose"))verbose = params["verbose"];
00080         if (params.has_key("calcsigmamean")) calcsigmamean=params["calcsigmamean"];
00081 
00082 }
00083 
00084 vector<EMData *> KMeansAnalyzer::analyze()
00085 {
00086 if (ncls<=1) return vector<EMData *>();
00087 //srandom(time(0));
00088 
00089 // These are the class centers, start each with a random image
00090 int nptcl=images.size();
00091 int nclstot=ncls;
00092 if (calcsigmamean) centers.resize(nclstot*2);
00093 else centers.resize(nclstot);
00094 if (mininclass<1) mininclass=1;
00095 
00096 if (slowseed) {
00097         if (maxiter<ncls*3+20) maxiter=ncls*3+20;       // We need to make sure we have enough iterations to seed all of the classes
00098         ncls=2;
00099 }
00100 
00101 for (int i=0; i<ncls; i++) {
00102         // Fixed by d.woolford, Util.get_irand is inclusive (added a -1)
00103         centers[i]=images[Util::get_irand(0,nptcl-1)]->copy();
00104 
00105 }
00106 
00107 if (calcsigmamean) {
00108         for (int i=nclstot; i<nclstot*2; i++) centers[i]=new EMData(images[0]->get_xsize(),images[0]->get_ysize(),images[0]->get_zsize());
00109 }
00110 
00111 
00112 for (int i=0; i<maxiter; i++) {
00113         nchanged=0;
00114         reclassify();
00115         if (verbose) printf("iter %d>  %d (%d)\n",i,nchanged,ncls);
00116         if (nchanged<minchange && ncls==nclstot) break;
00117         update_centers();
00118 
00119         if (slowseed && i%3==2 && ncls<nclstot) {
00120                 centers[ncls]=0;
00121                 ncls++;
00122                 reseed();
00123         }
00124 }
00125 update_centers(calcsigmamean);
00126 
00127 return centers;
00128 }
00129 
00130 void KMeansAnalyzer::update_centers(int sigmas) {
00131 int nptcl=images.size();
00132 //int repr[ncls];
00133 int * repr = new int[ncls];
00134 
00135 for (int i=0; i<ncls; i++) {
00136         centers[i]->to_zero();
00137         if (sigmas) centers[i+ncls]->to_zero();
00138         repr[i]=0;
00139 }
00140 
00141 for (int i=0; i<nptcl; i++) {
00142         int cid=images[i]->get_attr("class_id");
00143         centers[cid]->add(*images[i]);
00144         if (sigmas) centers[cid+ncls]->addsquare(*images[i]);
00145         repr[cid]++;
00146 }
00147 
00148 for (int i=0; i<ncls; i++) {
00149         if (repr[i]<mininclass) {
00150                 delete centers[i];
00151                 centers[i]=0;
00152                 repr[i]=0;
00153         }
00154         else {
00155                 centers[i]->mult((float)1.0/(float)(repr[i]));
00156                 centers[i]->set_attr("ptcl_repr",repr[i]);
00157                 if (sigmas) {
00158                         centers[i+ncls]->mult((float)1.0/(float)(repr[i]));             // sum of squares over n
00159                         centers[i+ncls]->subsquare(*centers[i]);                                        // subtract the mean value squared
00160                         centers[i+ncls]->process("math.sqrt");                                  // square root
00161                         centers[i+ncls]->mult((float)1.0/(float)sqrt((float)repr[i]));          // divide by sqrt(N) to get std. dev. of mean
00162                 }
00163 
00164         }
00165         if (verbose>1) printf("%d(%d)\t",i,(int)repr[i]);
00166 }
00167 
00168 if (verbose>1) printf("\n");
00169 
00170 reseed();
00171 
00172 delete [] repr;
00173 }
00174 
00175 // This will look for any unassigned points and reseed each inside the class with the broadest distribution widely distributed
00176 void KMeansAnalyzer::reseed() {
00177 // if no classes need reseeding just return
00178 int nptcl=images.size();
00179 int i,j;
00180 for (i=0; i<ncls; i++) {
00181         if (!centers[i]) break;
00182 }
00183 if (i==ncls) return;
00184 
00185 int * best = new int[ncls];     // particles in the average
00186 float *sigmas = new float[ncls]; // array of deviations
00187 
00188 for (int i=0; i<ncls; i++) { sigmas[i]=0; best[i]=0; }
00189 
00190 // compute the deviation of each class
00191 Cmp *c = Factory < Cmp >::get("sqeuclidean");
00192 for (int i=0; i<nptcl; i++) {
00193         int cid=images[i]->get_attr("class_id");
00194         if (!centers[cid]) continue;
00195 //      sigmas[cid]+=(float)imc->get_attr("square_sum");
00196         float d=c->cmp(images[i],centers[cid]);
00197         if (d>sigmas[cid]) {
00198                 sigmas[cid]=d;  // Instead of using sigma, use the largest distance in the class
00199                 best[cid]=i;
00200         }
00201 }
00202 delete c;
00203 //for (i=0; i<ncls; i++) sigmas[i]/=repr[i];    //since we aren't doing a sigma now...
00204 
00205 //we could sort the list, but for this use we just search
00206 for (i=0; i<ncls; i++) {
00207         if (centers[i]) continue;
00208 
00209         float maxsig=0;
00210         int maxi=0;
00211         // find the class with the largest sigma
00212         for (j=0; j<ncls; j++) {
00213                 if (sigmas[j]>maxsig) { maxsig=sigmas[j]; maxi=j; }
00214         }
00215 
00216         // find an image in that class
00217         for (j=0; j<ncls; j++) if ((int)images[j]->get_attr("class_id")==maxi) break;
00218         if (Util::get_irand(0,1)==0) centers[i]=images[best[maxi]]->copy();
00219         else centers[i]=images[j]->copy();
00220         centers[i]->set_attr("ptcl_repr",1);
00221         sigmas[maxi]=0;         // if we get another one to reseed, pick the next largest set (zero out the current one)
00222         printf("reseed %d -> %d (%d or %d)\n",i,maxi,best[maxi],j);
00223 }
00224 
00225 delete [] sigmas;
00226 delete [] best;
00227 }
00228 
00229 
00230 void KMeansAnalyzer::reclassify() {
00231 int nptcl=images.size();
00232 
00233 Cmp *c = Factory < Cmp >::get("sqeuclidean");
00234 for (int i=0; i<nptcl; i++) {
00235         float best=1.0e38f;
00236         int bestn=0;
00237         for (int j=0; j<ncls; j++) {
00238                 float d=c->cmp(images[i],centers[j]);
00239 //images[i]->cmp("sqeuclidean",centers[j]);
00240                 if (d<best) { best=d; bestn=j; }
00241         }
00242         int oldn=images[i]->get_attr_default("class_id",0);
00243         if (oldn!=bestn) nchanged++;
00244         images[i]->set_attr("class_id",bestn);
00245 }
00246 delete c;
00247 }
00248 
00249 #define covmat(i,j) covmat[ ((j)-1)*nx + (i)-1 ]
00250 #define imgdata(i)  imgdata[ (i)-1 ]
00251 int PCAsmall::insert_image(EMData * image)
00252 {
00253         if(mask==0)
00254                 throw NullPointerException("Null mask image pointer, set_params() first");
00255 
00256    EMData *maskedimage = Util::compress_image_mask(image,mask);
00257 
00258    int nx = maskedimage->get_xsize();
00259    float *imgdata = maskedimage->get_data();
00260    if (nx != ncov) {
00261       fprintf(stderr,"insert_image: something is wrong...\n");
00262       exit(1);
00263    }
00264 
00265    // there is a faster version of the following rank-1 update
00266    nimages++;
00267    for (int j = 1; j <= nx; j++)
00268        for (int i = 1; i<=nx; i++) {
00269            covmat(i,j) += imgdata(i)*imgdata(j);
00270    }
00271 
00272    EMDeletePtr(maskedimage);
00273    return 0;
00274 }
00275 #undef covmat
00276 
00277 #define eigvec(i,j) eigvec[(j)*ncov + (i)]
00278 vector<EMData*> PCAsmall::analyze()
00279 {
00280         float *eigvec;
00281         int status = 0;
00282 //              printf("start analyzing..., ncov = %d\n", ncov);
00283         eigval = (float*)calloc(ncov,sizeof(float));
00284         eigvec = (float*)calloc(ncov*ncov,sizeof(float));
00285         status = Util::coveig(ncov, covmat, eigval, eigvec);
00286 //       for (int i=1; i<=nvec; i++) printf("eigval = %11.4e\n",
00287 //            eigval[ncov-i]);
00288 
00289         // pack eigenvectors into the return imagelist
00290         EMData *eigenimage = new EMData();
00291         eigenimage->set_size(ncov,1,1);
00292         float *rdata = eigenimage->get_data();
00293         for (int j = 1; j<= nvec; j++) {
00294             for (int i = 0; i < ncov; i++) rdata[i] = eigvec(i,ncov-j);
00295 
00296                 EMData* recons_eigvec = Util::reconstitute_image_mask(eigenimage,mask);
00297                 recons_eigvec->set_attr( "eigval", eigval[j-1] );
00298             images.push_back(recons_eigvec);
00299         }
00300 
00301         free(eigvec);
00302         EMDeletePtr(eigenimage);
00303 
00304         return images;
00305 }
00306 #undef eigvec
00307 
00308 void PCAsmall::set_params(const Dict & new_params)
00309 {
00310         params = new_params;
00311         mask = params["mask"];
00312         nvec = params["nvec"];
00313 
00314         // count the number of pixels under the mask
00315         // (this is really ugly!!!)
00316         EMData *dummy = new EMData();
00317 
00318         int nx = mask->get_xsize();
00319         int ny = mask->get_ysize();
00320         int nz = mask->get_zsize();
00321 
00322         dummy->set_size(nx,ny,nz);
00323 
00324         EMData *dummy1d = Util::compress_image_mask(dummy,mask);
00325         ncov = dummy1d->get_xsize();
00326         EMDeletePtr(dummy);
00327         EMDeletePtr(dummy1d);
00328 
00329         // allocate and set up the covriance matrix
00330         nimages = 0;
00331         covmat = (float*)calloc(ncov*ncov,sizeof(float));
00332 }
00333 
00334 //------------------------------------------------------------------
00335 // for large-scale PCA incore
00336 
00337 int PCAlarge::insert_image(EMData * image)
00338 {
00339         if(mask==0)
00340                 throw NullPointerException("Null mask image pointer, set_params() first");
00341 
00342    EMData *maskedimage = Util::compress_image_mask(image,mask);
00343 
00344    FILE *fp;
00345    string scratchfile = string("maskedimages.scratch");
00346 
00347    fp = fopen(scratchfile.c_str(),"a");
00348 
00349    int nx = maskedimage->get_xsize();
00350    float *imgdata = maskedimage->get_data();
00351    fwrite(imgdata, sizeof(float), nx, fp);
00352    nimages++;
00353 
00354    fclose(fp);
00355 
00356    EMDeletePtr(maskedimage);
00357 
00358    return 0;
00359 }
00360 
00361 void PCAlarge::set_params(const Dict & new_params)
00362 {
00363         params = new_params;
00364         mask = params["mask"];
00365         nvec = params["nvec"];
00366 
00367         // count the number of pixels under the mask
00368         // (this is really ugly!!!)
00369         EMData *dummy = new EMData();
00370 
00371         int nx = mask->get_xsize();
00372         int ny = mask->get_ysize();
00373         int nz = mask->get_zsize();
00374 
00375         dummy->set_size(nx,ny,nz);
00376 
00377         EMData *dummy1d = Util::compress_image_mask(dummy,mask);
00378 
00379         ncov = dummy1d->get_xsize();
00380 
00381         EMDeletePtr(dummy);
00382         EMDeletePtr(dummy1d);
00383         // no need to allocate the covariance matrix
00384         nimages = 0;
00385 }
00386 
00387 #define qmat(i,j)   qmat[((j)-1)*kstep + (i) -1]
00388 #define diag(i)     diag[(i)-1]
00389 #define rdata(i)    rdata[(i)-1]
00390 #define eigvec(i,j) eigvec[((j)-1)*ncov + (i)-1]
00391 #define eigval(i)   eigval[(i)-1]
00392 
00393 vector<EMData*> PCAlarge::analyze()
00394 {
00395         int status = 0;
00396         int ione = 1;
00397         float one = 1.0, zero = 0.0;
00398         char trans;
00399         float *eigvec;
00400         string scratchfile = string("maskedimages.scratch");
00401         char command[100];
00402 
00403         printf("start analyzing..., ncov = %d\n", ncov);
00404 
00405         float resnrm = 0.0;
00406 
00407         if ( nvec > nimages || nvec ==0 ) nvec = nimages;
00408         int nx = ncov;
00409 
00410         // the definition of kstep is purely a heuristic for right now
00411         int kstep = nvec + 20;
00412         if (kstep > nimages) kstep = nimages;
00413 
00414         float *diag    = new float[kstep];
00415         float *subdiag = new float[kstep-1];
00416         float *vmat    = new float[nx*kstep];
00417 
00418         // run kstep-step Lanczos factorization
00419         status = Lanczos(scratchfile, &kstep, diag, subdiag,
00420                          vmat, &resnrm);
00421 
00422         // remove scratch file
00423         sprintf(command,"rm -f %s\n", scratchfile.c_str());
00424         status = system(command);
00425         if (status != 0) {
00426             fprintf(stderr,"PCAlarge: cannot remove scratchfile\n");
00427         }
00428 
00429         char jobz[2] = "V";
00430         float *qmat  = new float[kstep*kstep];
00431         // workspace size will be optimized later
00432         int   lwork  = 100 + 4*kstep + kstep*kstep;
00433         int   liwork = 3+5*kstep;
00434 
00435         float *work  = new float[lwork];
00436         int   *iwork = new int[liwork];
00437         int   info = 0;
00438 
00439         // call LAPACK tridiagonal eigensolver
00440         sstevd_(jobz, &kstep, diag, subdiag, qmat, &kstep, work, &lwork,
00441                 iwork, &liwork, &info);
00442 
00443         // store eigenvalues
00444         eigval = (float*)calloc(ncov,sizeof(float));
00445         eigvec = (float*)calloc(ncov*nvec,sizeof(float));
00446 
00447         for (int j = 0; j < nvec; j++) {
00448             eigval[j] = diag(kstep-j);
00449         }
00450 
00451 //         for (int i=0; i<nvec; i++) printf("eigval = %11.4e\n",
00452 //             eigval[i]);
00453 
00454         // compute eigenvectors
00455         for (int j=1; j<=nvec; j++) {
00456             trans = 'N';
00457             sgemv_(&trans, &nx,  &kstep, &one, vmat, &nx, &qmat(1,kstep-j+1),
00458                    &ione, &zero, &eigvec(1,j), &ione);
00459         }
00460 
00461         // pack eigenvectors into the return imagelist
00462         EMData *eigenimage = new EMData();
00463         eigenimage->set_size(ncov,1,1);
00464         float *rdata = eigenimage->get_data();
00465         for (int j = 1; j<= nvec; j++) {
00466             for (int i = 1; i <= ncov; i++)
00467                 rdata(i) = eigvec(i,j);
00468 
00469             EMData* recons_eigvec = Util::reconstitute_image_mask(eigenimage,mask);
00470 
00471             recons_eigvec->set_attr( "eigval", eigval[j-1] );
00472 
00473             images.push_back( recons_eigvec );
00474         }
00475 
00476         free(eigvec);
00477         EMDeletePtr(eigenimage);
00478 
00479         return images;
00480 }
00481 #undef qmat
00482 #undef diag
00483 #undef rdata
00484 #undef eigvec
00485 #undef eigval
00486 
00487 #define TOL 1e-7
00488 #define V(i,j)      V[((j)-1)*imgsize + (i) - 1]
00489 #define v0(i)       v0[(i)-1]
00490 #define Av(i)       Av[(i)-1]
00491 #define subdiag(i)  subdiag[(i)-1]
00492 #define diag(i)     diag[(i)-1]
00493 #define hvec(i)     hvec[(i)-1]
00494 
00495 int PCAlarge::Lanczos(const string &maskedimages, int *kstep,
00496                       float  *diag, float *subdiag, float *V,
00497                       float  *beta)
00498 {
00499     /*
00500         Purpose: Compute a kstep-step Lanczos factorization
00501                  on the covariant matrix X*trans(X), where
00502                  X (imgstack) contains a set of images;
00503 
00504         Input:
00505            imgstack (vector <EMData*>) a set of images on which PCA is
00506                                        to be performed;
00507 
00508            kstep (int*) The maximum number of Lanczos iterations allowed.
00509                           If Lanczos terminates before kstep steps
00510                           is reached (an invariant subspace is found),
00511                           kstep returns the number of steps taken;
00512 
00513         Output:
00514            diag (float *) The projection of the covariant matrix into a
00515                           Krylov subspace of dimension at most kstep.
00516                           The projection is a tridiagonal matrix. The
00517                           diagonal elements of this matrix is stored in
00518                           the diag array.
00519 
00520            subdiag (float*) The subdiagonal elements of the projection
00521                             is stored here.
00522 
00523            V (float *)    an imgsize by kstep array that contains a
00524                           set of orthonormal Lanczos basis vectors;
00525 
00526            beta (float *) the residual norm of the factorization;
00527     */
00528     int i, iter;
00529 
00530     float alpha;
00531     int   ione = 1;
00532     float zero = 0.0, one = 1.0, mone = -1.0;
00533     int   status = 0;
00534 
00535     char trans;
00536     int  imgsize = 0;
00537     float *v0, *Av, *hvec, *htmp, *imgdata;
00538     FILE  *fp=NULL;
00539 
00540     if (nimages <= 0) {
00541         status = 2; // no image in the stack
00542         goto EXIT;
00543     }
00544 
00545     imgsize = ncov;
00546     if (nimages <= 0) {
00547         status = 3; // no image in the stack
00548         goto EXIT;
00549     }
00550 
00551     v0   = new float[imgsize];
00552     Av   = new float[imgsize];
00553     hvec = new float[*kstep];
00554     htmp = new float[*kstep];
00555     imgdata = new float[imgsize];
00556 
00557     if (v0 == NULL || Av == NULL || hvec == NULL ||
00558         htmp == NULL || imgdata == NULL) {
00559         fprintf(stderr, "Lanczos: failed to allocate v0,Av,hvec,htmp\n");
00560         status = -1;
00561         goto EXIT;
00562     }
00563 
00564     // may choose a random starting guess here
00565     for ( i = 1; i <= imgsize; i++)
00566     {
00567         v0(i) = 1.0;
00568         Av(i) = 0.0;
00569     }
00570 
00571     // normalize the starting vector
00572     *beta  = snrm2_(&imgsize, v0, &ione);
00573     for (i = 1; i<=imgsize; i++)
00574         V(i,1) = v0(i) / (*beta);
00575 
00576     // do Av <-- A*v0, where A is a cov matrix
00577     fp = fopen(maskedimages.c_str(),"r");
00578     if (fp==NULL) {
00579         fprintf(stderr,"Lanczos: cannot open %s\n", maskedimages.c_str());
00580     }
00581     for (i = 0; i < nimages; i++) {
00582        fread(imgdata, sizeof(float), imgsize, fp);
00583        alpha = sdot_(&imgsize, imgdata, &ione, V, &ione);
00584        saxpy_(&imgsize, &alpha, imgdata, &ione, Av, &ione);
00585     }
00586     fclose(fp);
00587 
00588 
00589     // Av <--- Av - V(:,1)*V(:,1)'*Av
00590     diag(1) = sdot_(&imgsize, V, &ione, Av, &ione);
00591     alpha   = -diag(1);
00592     saxpy_(&imgsize, &alpha, V, &ione, Av, &ione);
00593 
00594     // main loop
00595     for ( iter = 2 ; iter <= *kstep ; iter++ ) {
00596         *beta = snrm2_(&imgsize, Av, &ione);
00597 
00598         if (*beta < TOL) {
00599             // found an invariant subspace, exit
00600             *kstep = iter;
00601             break;
00602         }
00603 
00604         subdiag(iter-1) = *beta;
00605         for ( i = 1 ; i <= imgsize ; i++ ) {
00606             V(i,iter) = Av(i) / (*beta);
00607         }
00608 
00609         // do Av <-- A*V(:,iter), where A is a cov matrix
00610         for (i = 0; i < imgsize; i++) Av[i] = 0;
00611         fp = fopen(maskedimages.c_str(),"r");
00612         for (i = 0; i < nimages; i++) {
00613            fread(imgdata, sizeof(float), imgsize, fp);
00614            alpha = sdot_(&imgsize, imgdata, &ione, &V(1,iter), &ione);
00615            saxpy_(&imgsize, &alpha, imgdata, &ione, Av, &ione);
00616         }
00617         fclose(fp);
00618 
00619         // f <--- Av - V(:,1:iter)*V(:,1:iter)'*Av
00620         trans = 'T';
00621         status = sgemv_(&trans, &imgsize, &iter, &one, V, &imgsize, Av, &ione,
00622                         &zero , hvec    , &ione);
00623         trans = 'N';
00624         status = sgemv_(&trans, &imgsize, &iter, &mone, V, &imgsize, hvec,
00625                         &ione , &one    , Av, &ione);
00626 
00627         // one step of reorthogonalization
00628         trans = 'T';
00629         status = sgemv_(&trans, &imgsize, &iter, &one, V, &imgsize, Av, &ione,
00630                         &zero , htmp    , &ione);
00631         saxpy_(&iter, &one, htmp, &ione, hvec, &ione);
00632         trans = 'N';
00633         status = sgemv_(&trans, &imgsize, &iter, &mone, V, &imgsize, htmp,
00634                         &ione , &one    , Av, &ione);
00635         diag(iter) = hvec(iter);
00636     }
00637 
00638     EMDeleteArray(v0);
00639     EMDeleteArray(Av);
00640     EMDeleteArray(hvec);
00641     EMDeleteArray(htmp);
00642     EMDeleteArray(imgdata);
00643 
00644 EXIT:
00645     return status;
00646 
00647 }
00648 #undef v0
00649 #undef Av
00650 #undef V
00651 #undef hvec
00652 #undef diag
00653 #undef subdiag
00654 #undef TOL
00655 
00656 void varimax::set_params(const Dict & new_params)
00657 {
00658         params = new_params;
00659         m_mask = params["mask"];
00660 
00661         // count the number of pixels under the mask
00662         // (this is really ugly!!!)
00663         EMData *dummy = new EMData();
00664 
00665         int nx = m_mask->get_xsize();
00666         int ny = m_mask->get_ysize();
00667         int nz = m_mask->get_zsize();
00668 
00669         dummy->set_size(nx,ny,nz);
00670 
00671         EMData *dummy1d = Util::compress_image_mask(dummy,m_mask);
00672 
00673         m_nlen = dummy1d->get_xsize();
00674         m_nfac = 0;
00675 
00676         EMDeletePtr(dummy);
00677         EMDeletePtr(dummy1d);
00678 }
00679 
00680 int varimax::insert_image(EMData* image)
00681 {
00682         if(m_mask==0)
00683                 throw NullPointerException("Null mask image pointer, set_params() first");
00684 
00685     EMData* img1d = Util::compress_image_mask(image,m_mask);
00686 
00687     m_data.insert( m_data.end(), img1d->get_data(), img1d->get_data() + m_nlen );
00688 
00689     m_nfac++;
00690 
00691     Assert( (int)m_data.size() == m_nfac*m_nlen);
00692 
00693     return 0;
00694 }
00695 
00696 vector<EMData*> varimax::analyze()
00697 {
00698     int itmax = 10000;
00699     float eps = 1e-4f;
00700     int verbose = 1;
00701     float params[4];
00702     params[0] = 1.0;
00703     varmx( &m_data[0], m_nlen, m_nfac, IVARIMAX, params, NULL, itmax, eps, verbose);
00704 
00705     vector<EMData*> images;
00706 
00707     EMData* img1d = new EMData();
00708     img1d->set_size(m_nlen, 1, 1);
00709     for( int i=0; i < m_nfac; ++i )
00710     {
00711         float* imgdata = img1d->get_data();
00712 
00713         int offset = i * m_nlen;
00714         for( int i=0; i < m_nlen; ++i )
00715         {
00716             imgdata[i] = m_data[offset+i];
00717         }
00718 
00719         EMData* img = Util::reconstitute_image_mask(img1d,m_mask);
00720         images.push_back(img);
00721     }
00722 
00723     EMDeletePtr(img1d);
00724 
00725     return images;
00726 }
00727 
00728 int SVDAnalyzer::insert_image(EMData * image)
00729 {
00730         if (mask==0)
00731                 throw NullPointerException("Null mask image pointer, set_params() first");
00732 
00733         // count pixels under mask
00734         size_t totpix=mask->get_xsize()*mask->get_ysize()*mask->get_zsize();
00735         float  *d=image->get_data();
00736         float *md=mask ->get_data();
00737         for (size_t i=0,j=0; i<totpix; ++i) {
00738                 if (md[i]) {
00739                         gsl_matrix_set(A,j,nsofar,d[i]);
00740                         j++;
00741                 }
00742         }
00743         nsofar++;
00744 
00745    return 0;
00746 }
00747 #undef covmat
00748 
00749 #define eigvec(i,j) eigvec[(j)*ncov + (i)]
00750 vector<EMData*> SVDAnalyzer::analyze()
00751 {
00752 // Allocate the working space
00753 gsl_vector *work=gsl_vector_alloc(nimg);
00754 gsl_vector *S=gsl_vector_alloc(nimg);
00755 gsl_matrix *V=gsl_matrix_alloc(nimg,nimg);
00756 gsl_matrix *X=gsl_matrix_alloc(nimg,nimg);
00757 
00758 
00759 // Do the decomposition. All the real work is here
00760 gsl_linalg_SV_decomp_mod (A,X, V, S, work);
00761 //else gsl_linalg_SV_decomp_jacobi(A,V,S);
00762 
00763 vector<EMData*> ret;
00764 //unpack the results and write the output file
00765 float *md=mask->get_data();
00766 size_t totpix=mask->get_xsize()*mask->get_ysize()*mask->get_zsize();
00767 for (int k=0; k<nvec; k++) {
00768         EMData *img = new EMData;
00769         img->set_size(mask->get_xsize(),mask->get_ysize(),mask->get_zsize());
00770 
00771         float  *d=img->get_data();
00772         for (size_t i=0,j=0; i<totpix; ++i) {
00773                 if (md[i]) {
00774                         d[i]=(float)gsl_matrix_get(A,j,k);
00775                         j++;
00776                 }
00777         }
00778         img->set_attr( "eigval", gsl_vector_get(S,k));
00779         ret.push_back(img);
00780 }
00781 
00782 gsl_vector_free(work);
00783 gsl_vector_free(S);
00784 gsl_matrix_free(V);
00785 gsl_matrix_free(X);
00786 
00787 gsl_matrix_free(A);
00788 A=NULL;
00789 mask=NULL;
00790 
00791 return ret;
00792 }
00793 
00794 void SVDAnalyzer::set_params(const Dict & new_params)
00795 {
00796         params = new_params;
00797         mask = params["mask"];
00798         nvec = params["nvec"];
00799         nimg = params["nimg"];
00800 
00801         // count pixels under mask
00802         pixels=0;
00803         size_t totpix=mask->get_xsize()*mask->get_ysize()*mask->get_zsize();
00804         float *d=mask->get_data();
00805         for (size_t i=0; i<totpix; ++i) if (d[i]) ++pixels;
00806 
00807         printf("%d,%d\n",pixels,nimg);
00808         A=gsl_matrix_alloc(pixels,nimg);
00809         nsofar=0;
00810 }
00811 
00812 
00813 void EMAN::dump_analyzers()
00814 {
00815         dump_factory < Analyzer > ();
00816 }
00817 
00818 map<string, vector<string> > EMAN::dump_analyzers_list()
00819 {
00820         return dump_factory_list < Analyzer > ();
00821 }
00822 
00823 
00824 
00825 
00826 
00827 
00828 

Generated on Sat Nov 7 02:18:55 2009 for EMAN2 by  doxygen 1.5.6