Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

averager.cpp

Go to the documentation of this file.
00001 
00005 /*
00006  * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
00007  * Copyright (c) 2000-2006 Baylor College of Medicine
00008  *
00009  * This software is issued under a joint BSD/GNU license. You may use the
00010  * source code in this file under either license. However, note that the
00011  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00012  * so you are responsible for compliance with the licenses of these packages
00013  * if you opt to use BSD licensing. The warranty disclaimer below holds
00014  * in either instance.
00015  *
00016  * This complete copyright notice must be included in any revised version of the
00017  * source code. Additional authorship citations may be added, but existing
00018  * author citations must be preserved.
00019  *
00020  * This program is free software; you can redistribute it and/or modify
00021  * it under the terms of the GNU General Public License as published by
00022  * the Free Software Foundation; either version 2 of the License, or
00023  * (at your option) any later version.
00024  *
00025  * This program is distributed in the hope that it will be useful,
00026  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00028  * GNU General Public License for more details.
00029  *
00030  * You should have received a copy of the GNU General Public License
00031  * along with this program; if not, write to the Free Software
00032  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00033  *
00034  * */
00035 
00036 #include "averager.h"
00037 #include "emdata.h"
00038 #include "xydata.h"
00039 #include "ctf.h"
00040 #include <cstring>
00041 #include "plugins/averager_template.h"
00042 
00043 using namespace EMAN;
00044 
00045 const string ImageAverager::NAME = "mean";
00046 const string MinMaxAverager::NAME = "minmax";
00047 const string IterationAverager::NAME = "iteration";
00048 const string WeightingAverager::NAME = "snr_weight";
00049 const string CtfCAverager::NAME = "ctfc";
00050 const string CtfCWAverager::NAME = "ctfcw";
00051 const string CtfCWautoAverager::NAME = "ctfw.auto";
00052 const string CtfCAutoAverager::NAME = "ctf.auto";
00053 
00054 template <> Factory < Averager >::Factory()
00055 {
00056         force_add<ImageAverager>();
00057         force_add<MinMaxAverager>();
00058         force_add<IterationAverager>();
00059 //      force_add<WeightingAverager>();
00060         // These commented out until we're happy they're working. (d.woolford, Feb 3rd 2009)
00061 //      force_add(&CtfCAverager::NEW);
00062 //      force_add(&CtfCWAverager::NEW);
00063         force_add<CtfCWautoAverager>();
00064         force_add<CtfCAutoAverager>();
00065 //      force_add<XYZAverager>();
00066 }
00067 
00068 void Averager::mult(const float& s)
00069 {
00070         if ( result != 0 )
00071         {
00072                 result->mult(s);
00073         }
00074         else throw NullPointerException("Error, attempted to multiply the result image, which is NULL");
00075 }
00076 
00077 
00078 void Averager::add_image_list(const vector<EMData*> & image_list)
00079 {
00080         for (size_t i = 0; i < image_list.size(); i++) {
00081                 add_image(image_list[i]);
00082         }
00083 }
00084 
00085 ImageAverager::ImageAverager()
00086         : sigma_image(0), nimg_n0(0), ignore0(0), nimg(0)
00087 {
00088 
00089 }
00090 
00091 void ImageAverager::add_image(EMData * image)
00092 {
00093         if (!image) {
00094                 return;
00095         }
00096 
00097         if (nimg >= 1 && !EMUtil::is_same_size(image, result)) {
00098                 LOGERR("%sAverager can only process same-size Image",
00099                            get_name().c_str());
00100                 return;
00101         }
00102 
00103         nimg++;
00104 
00105         int nx = image->get_xsize();
00106         int ny = image->get_ysize();
00107         int nz = image->get_zsize();
00108         size_t image_size = nx * ny * nz;
00109 
00110         if (nimg == 1) {
00111                 result = new EMData();
00112                 result->set_size(nx, ny, nz);
00113                 sigma_image = params.set_default("sigma", (EMData*)0);
00114                 ignore0 = params["ignore0"];
00115 
00116                 nimg_n0 = new int[image_size];
00117                 for (size_t i = 0; i < image_size; i++) {
00118                         nimg_n0[i] = 0;
00119                 }
00120         }
00121 
00122         float *result_data = result->get_data();
00123         float *sigma_image_data = 0;
00124         if (sigma_image) {
00125                 sigma_image->set_size(nx, ny, nz);
00126                 sigma_image_data = sigma_image->get_data();
00127         }
00128 
00129         float * image_data = image->get_data();
00130 
00131         if (!ignore0) {
00132                 for (size_t j = 0; j < image_size; j++) {
00133                         float f = image_data[j];
00134                         result_data[j] += f;
00135                         if (sigma_image_data) {
00136                                 sigma_image_data[j] += f * f;
00137                         }
00138                 }
00139         }
00140         else {
00141                 for (size_t j = 0; j < image_size; j++) {
00142                         float f = image_data[j];
00143                         if (f) {
00144                                 result_data[j] += f;
00145                                 if (sigma_image_data) {
00146                                         sigma_image_data[j] += f * f;
00147                                 }
00148                                 nimg_n0[j]++;
00149                         }
00150                 }
00151         }
00152 }
00153 
00154 EMData * ImageAverager::finish()
00155 {
00156         if (result && nimg > 1) {
00157                 size_t image_size = result->get_xsize() * result->get_ysize() * result->get_zsize();
00158                 float * result_data = result->get_data();
00159 
00160                 if (!ignore0) {
00161                         for (size_t j = 0; j < image_size; j++) {
00162                                 result_data[j] /= nimg;
00163                         }
00164 
00165                         if (sigma_image) {
00166                                 float * sigma_image_data = sigma_image->get_data();
00167 
00168                                 for (size_t j = 0; j < image_size; j++) {
00169                                         float f1 = sigma_image_data[j] / nimg;
00170                                         float f2 = result_data[j];
00171                                         sigma_image_data[j] = sqrt(f1 - f2 * f2);
00172                                 }
00173 
00174                                 sigma_image->update();
00175                         }
00176                 }
00177                 else {
00178                         for (size_t j = 0; j < image_size; j++) {
00179                                 result_data[j] /= nimg_n0[j];
00180                         }
00181                         if (sigma_image) {
00182                                 float * sigma_image_data = sigma_image->get_data();
00183 
00184                                 for (size_t j = 0; j < image_size; j++) {
00185                                         float f1 = sigma_image_data[j] / nimg_n0[j];
00186                                         float f2 = result_data[j];
00187                                         sigma_image_data[j] = sqrt(f1 - f2 * f2);
00188                                 }
00189 
00190                                 sigma_image->update();
00191                         }
00192                 }
00193 
00194                 result->update();
00195         }
00196 
00197         if( nimg_n0 )
00198         {
00199                 delete [] nimg_n0;
00200                 nimg_n0 = 0;
00201         }
00202 
00203         return result;
00204 }
00205 
00206 #if 0
00207 EMData *ImageAverager::average(const vector < EMData * >&image_list) const
00208 {
00209         if (image_list.size() == 0) {
00210                 return 0;
00211         }
00212 
00213         EMData *sigma_image = params["sigma"];
00214         int ignore0 = params["ignore0"];
00215 
00216         EMData *image0 = image_list[0];
00217 
00218         int nx = image0->get_xsize();
00219         int ny = image0->get_ysize();
00220         int nz = image0->get_zsize();
00221         size_t image_size = nx * ny * nz;
00222 
00223         EMData *result = new EMData();
00224         result->set_size(nx, ny, nz);
00225 
00226         float *result_data = result->get_data();
00227         float *sigma_image_data = 0;
00228 
00229         if (sigma_image) {
00230                 sigma_image->set_size(nx, ny, nz);
00231                 sigma_image_data = sigma_image->get_data();
00232         }
00233 
00234         int c = 1;
00235         if (ignore0) {
00236                 for (size_t j = 0; j < image_size; j++) {
00237                         int g = 0;
00238                         for (size_t i = 0; i < image_list.size(); i++) {
00239                                 float f = image_list[i]->get_value_at(j);
00240                                 if (f) {
00241                                         g++;
00242                                         result_data[j] += f;
00243                                         if (sigma_image_data) {
00244                                                 sigma_image_data[j] += f * f;
00245                                         }
00246                                 }
00247                         }
00248                         if (g) {
00249                                 result_data[j] /= g;
00250                         }
00251                 }
00252         }
00253         else {
00254                 float *image0_data = image0->get_data();
00255                 if (sigma_image_data) {
00256                         memcpy(sigma_image_data, image0_data, image_size * sizeof(float));
00257 
00258                         for (size_t j = 0; j < image_size; j++) {
00259                                 sigma_image_data[j] *= sigma_image_data[j];
00260                         }
00261                 }
00262 
00263                 image0->update();
00264                 memcpy(result_data, image0_data, image_size * sizeof(float));
00265 
00266                 for (size_t i = 1; i < image_list.size(); i++) {
00267                         EMData *image = image_list[i];
00268 
00269                         if (EMUtil::is_same_size(image, result)) {
00270                                 float *image_data = image->get_data();
00271 
00272                                 for (size_t j = 0; j < image_size; j++) {
00273                                         result_data[j] += image_data[j];
00274                                 }
00275 
00276                                 if (sigma_image_data) {
00277                                         for (size_t j = 0; j < image_size; j++) {
00278                                                 sigma_image_data[j] += image_data[j] * image_data[j];
00279                                         }
00280                                 }
00281 
00282                                 image->update();
00283                                 c++;
00284                         }
00285                 }
00286 
00287                 for (size_t j = 0; j < image_size; j++) {
00288                         result_data[j] /= static_cast < float >(c);
00289                 }
00290         }
00291 
00292         if (sigma_image_data) {
00293                 for (size_t j = 0; j < image_size; j++) {
00294                         float f1 = sigma_image_data[j] / c;
00295                         float f2 = result_data[j];
00296                         sigma_image_data[j] = sqrt(f1 - f2 * f2);
00297                 }
00298         }
00299 
00300         if (sigma_image_data) {
00301                 sigma_image->update();
00302         }
00303 
00304         result->update();
00305         return result;
00306 }
00307 #endif
00308 
00309 MinMaxAverager::MinMaxAverager()
00310         : nimg(0)
00311 {
00312         /*move max out of initializer list, since this max(0) is considered as a macro
00313          * in Visual Studio, which we defined somewhere else*/
00314         max = 0;
00315 }
00316 
00317 void MinMaxAverager::add_image(EMData * image)
00318 {
00319         if (!image) {
00320                 return;
00321         }
00322 
00323         if (nimg >= 1 && !EMUtil::is_same_size(image, result)) {
00324                 LOGERR("%sAverager can only process same-size Image",
00325                            get_name().c_str());
00326                 return;
00327         }
00328 
00329         nimg++;
00330 
00331         int nx = image->get_xsize();
00332         int ny = image->get_ysize();
00333         int nz = image->get_zsize();
00334 
00335         if (nimg == 1) {
00336                 result = image->copy();
00337                 max = params["max"];
00338                 return;
00339         }
00340 
00341         for (int z=0; z<nz; z++) {
00342                 for (int y=0; y<ny; y++) {
00343                         for (int x=0; x<nx; x++) {
00344                                 if (result->get_value_at(x,y,z)>image->get_value_at(x,y,z))
00345                                         { if (!max) result->set_value_at(x,y,z,image->get_value_at(x,y,z)); }
00346                                 else { if (max) result->set_value_at(x,y,z,image->get_value_at(x,y,z)); }
00347                         }
00348                 }
00349         }
00350 
00351 }
00352 
00353 EMData *MinMaxAverager::finish()
00354 {
00355         result->update();
00356         if (result && nimg > 1) return result;
00357 
00358         return NULL;
00359 }
00360 
00361 
00362 IterationAverager::IterationAverager() : nimg(0)
00363 {
00364 
00365 }
00366 
00367 void IterationAverager::add_image( EMData * image)
00368 {
00369         if (!image) {
00370                 return;
00371         }
00372 
00373         if (nimg >= 1 && !EMUtil::is_same_size(image, result)) {
00374                 LOGERR("%sAverager can only process same-size Image",
00375                                                          get_name().c_str());
00376                 return;
00377         }
00378 
00379         nimg++;
00380 
00381         int nx = image->get_xsize();
00382         int ny = image->get_ysize();
00383         int nz = image->get_zsize();
00384         size_t image_size = nx * ny * nz;
00385 
00386         if (nimg == 1) {
00387                 result = new EMData();
00388                 result->set_size(nx, ny, nz);
00389                 sigma_image = new EMData();
00390                 sigma_image->set_size(nx, ny, nz);
00391         }
00392 
00393         float *image_data = image->get_data();
00394         float *result_data = result->get_data();
00395         float *sigma_image_data = sigma_image->get_data();
00396 
00397         for (size_t j = 0; j < image_size; j++) {
00398                 float f = image_data[j];
00399                 result_data[j] += f;
00400                 sigma_image_data[j] += f * f;
00401         }
00402 
00403 
00404 }
00405 
00406 EMData * IterationAverager::finish()
00407 {
00408         if (nimg < 1) {
00409                 return result;
00410         }
00411 
00412         int nx = result->get_xsize();
00413         int ny = result->get_ysize();
00414         int nz = result->get_zsize();
00415         size_t image_size = nx * ny * nz;
00416 
00417         float *result_data = result->get_data();
00418         float *sigma_image_data = sigma_image->get_data();
00419 
00420         for (size_t j = 0; j < image_size; j++) {
00421                 result_data[j] /= nimg;
00422                 float f1 = sigma_image_data[j] / nimg;
00423                 float f2 = result_data[j];
00424                 sigma_image_data[j] = sqrt(f1 - f2 * f2) / sqrt((float)nimg);
00425         }
00426 
00427         result->update();
00428         sigma_image->update();
00429 
00430         result->append_image("iter.hed");
00431         float sigma = sigma_image->get_attr("sigma");
00432         float *sigma_image_data2 = sigma_image->get_data();
00433         float *result_data2 = result->get_data();
00434         float *d2 = new float[nx * ny];
00435         size_t sec_size = nx * ny * sizeof(float);
00436 
00437         memcpy(d2, result_data2, sec_size);
00438         memcpy(sigma_image_data2, result_data2, sec_size);
00439 
00440         printf("Iter sigma=%f\n", sigma);
00441 
00442         for (int k = 0; k < 1000; k++) {
00443                 for (int i = 1; i < nx - 1; i++) {
00444                         for (int j = 1; j < ny - 1; j++) {
00445                                 int l = i + j * nx;
00446                                 float c1 = (d2[l - 1] + d2[l + 1] + d2[l - nx] + d2[l + nx]) / 4.0f - d2[l];
00447                                 float c2 = fabs(result_data2[l] - sigma_image_data2[l]) / sigma;
00448                                 result_data2[l] += c1 * Util::eman_erfc(c2) / 100.0f;
00449                         }
00450                 }
00451 
00452                 memcpy(d2, result_data2, sec_size);
00453         }
00454 
00455         if( d2 )
00456         {
00457                 delete[]d2;
00458                 d2 = 0;
00459         }
00460 
00461         sigma_image->update();
00462         if( sigma_image )
00463         {
00464                 delete sigma_image;
00465                 sigma_image = 0;
00466         }
00467 
00468         result->update();
00469         result->append_image("iter.hed");
00470 
00471 
00472         return result;
00473 }
00474 
00475 CtfCWautoAverager::CtfCWautoAverager()
00476         : nimg(0)
00477 {
00478 
00479 }
00480 
00481 
00482 void CtfCWautoAverager::add_image(EMData * image)
00483 {
00484         if (!image) {
00485                 return;
00486         }
00487 
00488 
00489 
00490         EMData *fft=image->do_fft();
00491 
00492         if (nimg >= 1 && !EMUtil::is_same_size(fft, result)) {
00493                 LOGERR("%s Averager can only process images of the same size", get_name().c_str());
00494                 return;
00495         }
00496 
00497         nimg++;
00498         if (nimg == 1) {
00499                 result = fft->copy_head();
00500                 result->to_zero();
00501         }
00502 
00503         Ctf *ctf = (Ctf *)image->get_attr("ctf");
00504         float b=ctf->bfactor;
00505         ctf->bfactor=100.0;                     // FIXME - this is a temporary fixed B-factor which does a (very) little sharpening
00506 
00507         EMData *snr = result -> copy();
00508         ctf->compute_2d_complex(snr,Ctf::CTF_SNR);
00509         EMData *ctfi = result-> copy();
00510         ctf->compute_2d_complex(ctfi,Ctf::CTF_AMP);
00511 
00512         ctf->bfactor=b; // return to its original value
00513 
00514         float *outd = result->get_data();
00515         float *ind = fft->get_data();
00516         float *snrd = snr->get_data();
00517         float *ctfd = ctfi->get_data();
00518 
00519         size_t sz=snr->get_xsize()*snr->get_ysize();
00520         for (size_t i = 0; i < sz; i+=2) {
00521                 if (snrd[i]<0) snrd[i]=0;
00522                 ctfd[i]=fabs(ctfd[i]);
00523                 if (ctfd[i]<.05) {
00524                         if (snrd[i]<=0) ctfd[i]=.05f;
00525                         else ctfd[i]=snrd[i]*10.0f;
00526                 }
00527                 outd[i]+=ind[i]*snrd[i]/ctfd[i];
00528                 outd[i+1]+=ind[i+1]*snrd[i]/ctfd[i];
00529         }
00530 
00531         if (nimg==1) {
00532                 snrsum=snr->copy_head();
00533                 float *ssnrd=snrsum->get_data();
00534                 // we're only using the real component, and we need to start with 1.0
00535                 for (size_t i = 0; i < sz; i+=2) { ssnrd[i]=1.0; ssnrd[i+1]=0.0; }
00536         }
00537         snrsum->add(*snr);
00538 
00539         delete ctf;
00540         delete fft;
00541         delete snr;
00542         delete ctfi;
00543 }
00544 
00545 EMData * CtfCWautoAverager::finish()
00546 {
00547 /*      EMData *tmp=result->do_ift();
00548         tmp->write_image("ctfcw.hdf",0);
00549         delete tmp;
00550 
00551         tmp=snrsum->do_ift();
00552         tmp->write_image("ctfcw.hdf",1);
00553         delete tmp;*/
00554 
00555 //      snrsum->write_image("snrsum.hdf",-1);
00556         size_t sz=result->get_xsize()*result->get_ysize();
00557         float *snrsd=snrsum->get_data();
00558         float *outd=result->get_data();
00559 
00560         for (size_t i=0; i<sz; i+=2) {
00561                 outd[i]/=snrsd[i];              // snrsd contains total SNR+1
00562                 outd[i+1]/=snrsd[i];
00563         }
00564         result->update();
00565         result->set_attr("ptcl_repr",nimg);
00566         result->set_attr("ctf_snr_total",snrsum->calc_radial_dist(snrsum->get_ysize()/2,0,1,false));
00567         result->set_attr("ctf_wiener_filtered",1);
00568         
00569         delete snrsum;
00570         EMData *ret=result->do_ift();
00571         delete result;
00572         result=NULL;
00573         return ret;
00574 }
00575 
00576 CtfCAutoAverager::CtfCAutoAverager()
00577         : nimg(0)
00578 {
00579 
00580 }
00581 
00582 
00583 void CtfCAutoAverager::add_image(EMData * image)
00584 {
00585         if (!image) {
00586                 return;
00587         }
00588 
00589 
00590 
00591         EMData *fft=image->do_fft();
00592 
00593         if (nimg >= 1 && !EMUtil::is_same_size(fft, result)) {
00594                 LOGERR("%s Averager can only process images of the same size", get_name().c_str());
00595                 return;
00596         }
00597 
00598         nimg++;
00599         if (nimg == 1) {
00600                 result = fft->copy_head();
00601                 result->to_zero();
00602         }
00603 
00604         Ctf *ctf = (Ctf *)image->get_attr("ctf");
00605         float b=ctf->bfactor;
00606         ctf->bfactor=0;                 // NO B-FACTOR CORRECTION !
00607 
00608         EMData *snr = result -> copy();
00609         ctf->compute_2d_complex(snr,Ctf::CTF_SNR);
00610         EMData *ctfi = result-> copy();
00611         ctf->compute_2d_complex(ctfi,Ctf::CTF_AMP);
00612 
00613         ctf->bfactor=b; // return to its original value
00614 
00615         float *outd = result->get_data();
00616         float *ind = fft->get_data();
00617         float *snrd = snr->get_data();
00618         float *ctfd = ctfi->get_data();
00619 
00620         size_t sz=snr->get_xsize()*snr->get_ysize();
00621         for (size_t i = 0; i < sz; i+=2) {
00622                 if (snrd[i]<0) snrd[i]=0;
00623                 ctfd[i]=fabs(ctfd[i]);
00624                 
00625                 // This limits the maximum possible amplification in CTF correction to 10x
00626                 if (ctfd[i]<.05) {
00627                         if (snrd[i]<=0) ctfd[i]=.05f;
00628                         else ctfd[i]=snrd[i]*10.0f;
00629                 }
00630                 
00631                 // SNR weight and CTF correction
00632                 outd[i]+=ind[i]*snrd[i]/ctfd[i];
00633                 outd[i+1]+=ind[i+1]*snrd[i]/ctfd[i];
00634         }
00635 
00636         if (nimg==1) {
00637                 snrsum=snr->copy_head();
00638                 float *ssnrd=snrsum->get_data();
00639                 // we're only using the real component, for Wiener filter we put 1.0 in R, but for just SNR weight we use 0
00640                 for (size_t i = 0; i < sz; i+=2) { ssnrd[i]=0.0; ssnrd[i+1]=0.0; }
00641         }
00642         snrsum->add(*snr);
00643 
00644         delete ctf;
00645         delete fft;
00646         delete snr;
00647         delete ctfi;
00648 }
00649 
00650 EMData * CtfCAutoAverager::finish()
00651 {
00652 /*      EMData *tmp=result->do_ift();
00653         tmp->write_image("ctfcw.hdf",0);
00654         delete tmp;
00655 
00656         tmp=snrsum->do_ift();
00657         tmp->write_image("ctfcw.hdf",1);
00658         delete tmp;*/
00659 
00660 //      snrsum->write_image("snrsum.hdf",-1);
00661         size_t sz=result->get_xsize()*result->get_ysize();
00662         float *snrsd=snrsum->get_data();
00663         float *outd=result->get_data();
00664 
00665         for (size_t i=0; i<sz; i+=2) {
00666                 if (snrsd[i]==0) outd[i]=outd[i+1]=0;
00667                 // we aren't wiener filtering, but if the total SNR is too low, we don't want TOO much exaggeration of noise
00668                 if (snrsd[i]<.05) {             
00669                         outd[i]*=20.0;          // 1/0.05
00670                         outd[i+1]*=20.0;
00671                 }
00672                 else {
00673                         outd[i]/=snrsd[i];              // snrsd contains total SNR
00674                         outd[i+1]/=snrsd[i];
00675                 }
00676         }
00677         result->update();
00678         result->set_attr("ptcl_repr",nimg);
00679         result->set_attr("ctf_snr_total",snrsum->calc_radial_dist(snrsum->get_ysize()/2,0,1,false));
00680         result->set_attr("ctf_wiener_filtered",0);
00681         
00682 /*      snrsum->write_image("snr.hdf",-1);
00683         result->write_image("avg.hdf",-1);*/
00684         
00685         delete snrsum;
00686         EMData *ret=result->do_ift();
00687         delete result;
00688         result=NULL;
00689         return ret;
00690 }
00691 
00692 #if 0
00693 EMData *IterationAverager::average(const vector < EMData * >&image_list) const
00694 {
00695         if (image_list.size() == 0) {
00696                 return 0;
00697         }
00698 
00699         EMData *image0 = image_list[0];
00700 
00701         int nx = image0->get_xsize();
00702         int ny = image0->get_ysize();
00703         int nz = image0->get_zsize();
00704         size_t image_size = nx * ny * nz;
00705 
00706         EMData *result = new EMData();
00707         result->set_size(nx, ny, nz);
00708 
00709         EMData *sigma_image = new EMData();
00710         sigma_image->set_size(nx, ny, nz);
00711 
00712         float *image0_data = image0->get_data();
00713         float *result_data = result->get_data();
00714         float *sigma_image_data = sigma_image->get_data();
00715 
00716         memcpy(result_data, image0_data, image_size * sizeof(float));
00717         memcpy(sigma_image_data, image0_data, image_size * sizeof(float));
00718 
00719         for (size_t j = 0; j < image_size; j++) {
00720                 sigma_image_data[j] *= sigma_image_data[j];
00721         }
00722 
00723         image0->update();
00724 
00725         int nc = 1;
00726         for (size_t i = 1; i < image_list.size(); i++) {
00727                 EMData *image = image_list[i];
00728 
00729                 if (EMUtil::is_same_size(image, result)) {
00730                         float *image_data = image->get_data();
00731 
00732                         for (size_t j = 0; j < image_size; j++) {
00733                                 result_data[j] += image_data[j];
00734                                 sigma_image_data[j] += image_data[j] * image_data[j];
00735                         }
00736 
00737                         image->update();
00738                         nc++;
00739                 }
00740         }
00741 
00742         float c = static_cast < float >(nc);
00743         for (size_t j = 0; j < image_size; j++) {
00744                 float f1 = sigma_image_data[j] / c;
00745                 float f2 = result_data[j] / c;
00746                 sigma_image_data[j] = sqrt(f1 - f2 * f2) / sqrt(c);
00747         }
00748 
00749 
00750         for (size_t j = 0; j < image_size; j++) {
00751                 result_data[j] /= c;
00752         }
00753 
00754         result->update();
00755         sigma_image->update();
00756 
00757         result->append_image("iter.hed");
00758 
00759         float sigma = sigma_image->get_attr("sigma");
00760         float *sigma_image_data2 = sigma_image->get_data();
00761         float *result_data2 = result->get_data();
00762         float *d2 = new float[nx * ny];
00763         size_t sec_size = nx * ny * sizeof(float);
00764 
00765         memcpy(d2, result_data2, sec_size);
00766         memcpy(sigma_image_data2, result_data2, sec_size);
00767 
00768         printf("Iter sigma=%f\n", sigma);
00769 
00770         for (int k = 0; k < 1000; k++) {
00771                 for (int i = 1; i < nx - 1; i++) {
00772                         for (int j = 1; j < ny - 1; j++) {
00773                                 int l = i + j * nx;
00774                                 float c1 = (d2[l - 1] + d2[l + 1] + d2[l - nx] + d2[l + nx]) / 4.0f - d2[l];
00775                                 float c2 = fabs(result_data2[l] - sigma_image_data2[l]) / sigma;
00776                                 result_data2[l] += c1 * Util::eman_erfc(c2) / 100.0f;
00777                         }
00778                 }
00779 
00780                 memcpy(d2, result_data2, sec_size);
00781         }
00782 
00783         if( d2 )
00784         {
00785                 delete[]d2;
00786                 d2 = 0;
00787         }
00788 
00789         sigma_image->update();
00790         if( sigma_image )
00791         {
00792                 delete sigma_image;
00793                 sigma_image = 0;
00794         }
00795 
00796         result->update();
00797         result->append_image("iter.hed");
00798 
00799         return result;
00800 }
00801 #endif
00802 
00803 
00804 CtfAverager::CtfAverager() :
00805         sf(0), curves(0), need_snr(false), outfile(0),
00806         image0_fft(0), image0_copy(0), snri(0), snrn(0),
00807         tdr(0), tdi(0), tn(0),
00808         filter(0), nimg(0), nx(0), ny(0), nz(0)
00809 {
00810 
00811 }
00812 
00813 void CtfAverager::add_image(EMData * image)
00814 {
00815         if (!image) {
00816                 return;
00817         }
00818 
00819         if (nimg >= 1 && !EMUtil::is_same_size(image, result)) {
00820                 LOGERR("%sAverager can only process same-size Image",
00821                                                          get_name().c_str());
00822                 return;
00823         }
00824 
00825         if (image->get_zsize() != 1) {
00826                 LOGERR("%sAverager: Only 2D images are currently supported",
00827                                                          get_name().c_str());
00828         }
00829 
00830         string alg_name = get_name();
00831 
00832         if (alg_name == "CtfCW" || alg_name == "CtfCWauto") {
00833                 if (image->get_ctf() != 0 && !image->has_ctff()) {
00834                         LOGERR("%sAverager: Attempted CTF Correction with no ctf parameters",
00835                                                                  get_name().c_str());
00836                 }
00837         }
00838         else {
00839                 if (image->get_ctf() != 0) {
00840                         LOGERR("%sAverager: Attempted CTF Correction with no ctf parameters",
00841                                                                  get_name().c_str());
00842                 }
00843         }
00844 
00845         nimg++;
00846 
00847 
00848         if (nimg == 1) {
00849                 image0_fft = image->do_fft();
00850 
00851                 nx = image0_fft->get_xsize();
00852                 ny = image0_fft->get_ysize();
00853                 nz = image0_fft->get_zsize();
00854 
00855                 result = new EMData();
00856                 result->set_size(nx - 2, ny, nz);
00857 
00858 
00859                 if (alg_name == "Weighting" && curves) {
00860                         if (!sf) {
00861                                 LOGWARN("CTF curve in file will contain relative, not absolute SNR!");
00862                         }
00863                         curves->set_size(Ctf::CTFOS * ny / 2, 3, 1);
00864                         curves->to_zero();
00865                 }
00866 
00867 
00868                 if (alg_name == "CtfC") {
00869                         filter = params["filter"];
00870                         if (filter == 0) {
00871                                 filter = 22.0f;
00872                         }
00873                         float apix_y = image->get_attr_dict().get("apix_y");
00874                         float ds = 1.0f / (apix_y * ny * Ctf::CTFOS);
00875                         filter = 1.0f / (filter * ds);
00876                 }
00877 
00878                 if (alg_name == "CtfCWauto") {
00879                         int nxy2 = nx * ny/2;
00880 
00881                         snri = new float[ny / 2];
00882                         snrn = new float[ny / 2];
00883                         tdr = new float[nxy2];
00884                         tdi = new float[nxy2];
00885                         tn = new float[nxy2];
00886 
00887                         for (int i = 0; i < ny / 2; i++) {
00888                                 snri[i] = 0;
00889                                 snrn[i] = 0;
00890                         }
00891 
00892                         for (int i = 0; i < nxy2; i++) {
00893                                 tdr[i] = 1;
00894                                 tdi[i] = 1;
00895                                 tn[i] = 1;
00896                         }
00897                 }
00898 
00899                 image0_copy = image0_fft->copy_head();
00900                 image0_copy->ap2ri();
00901                 image0_copy->to_zero();
00902         }
00903 
00904         Ctf::CtfType curve_type = Ctf::CTF_AMP;
00905         if (alg_name == "CtfCWauto") {
00906                 curve_type = Ctf::CTF_AMP;
00907         }
00908 
00909         float *src = image->get_data();
00910         image->ap2ri();
00911         Ctf *image_ctf = image->get_ctf();
00912         int ny2 = image->get_ysize();
00913 
00914         vector<float> ctf1 = image_ctf->compute_1d(ny2,1.0f/(image_ctf->apix*image->get_ysize()), curve_type);
00915 
00916         if (ctf1.size() == 0) {
00917                 LOGERR("Unexpected CTF correction problem");
00918         }
00919 
00920         ctf.push_back(ctf1);
00921 
00922         vector<float> ctfn1;
00923         if (sf) {
00924                 ctfn1 = image_ctf->compute_1d(ny2,1.0f/(image_ctf->apix*image->get_ysize()), Ctf::CTF_SNR, sf);
00925         }
00926         else {
00927                 ctfn1 = image_ctf->compute_1d(ny2,1.0f/(image_ctf->apix*image->get_ysize()), Ctf::CTF_SNR);
00928         }
00929 
00930         ctfn.push_back(ctfn1);
00931 
00932         if (alg_name == "CtfCWauto") {
00933                 int j = 0;
00934                 for (int y = 0; y < ny; y++) {
00935                         for (int x = 0; x < nx / 2; x++, j += 2) {
00936 #ifdef  _WIN32
00937                                 float r = (float)_hypot((float)x, (float)(y - ny / 2.0f));
00938 #else
00939                                 float r = (float)hypot((float)x, (float)(y - ny / 2.0f));
00940 #endif  //_WIN32
00941                                 int l = static_cast < int >(Util::fast_floor(r));
00942 
00943                                 if (l >= 0 && l < ny / 2) {
00944                                         int k = y*nx/2 + x;
00945                                         tdr[k] *= src[j];
00946                                         tdi[k] *= src[j + 1];
00947 #ifdef  _WIN32
00948                                         tn[k] *= (float)_hypot(src[j], src[j + 1]);
00949 #else
00950                                         tn[k] *= (float)hypot(src[j], src[j + 1]);
00951 #endif  //_WIN32
00952                                 }
00953                         }
00954                 }
00955         }
00956 
00957 
00958         float *tmp_data = image0_copy->get_data();
00959 
00960         int j = 0;
00961         for (int y = 0; y < ny; y++) {
00962                 for (int x = 0; x < nx / 2; x++, j += 2) {
00963                         float r = Ctf::CTFOS * sqrt(x * x + (y - ny / 2.0f) * (y - ny / 2.0f));
00964                         int l = static_cast < int >(Util::fast_floor(r));
00965                         r -= l;
00966 
00967                         float f = 0;
00968                         if (l <= Ctf::CTFOS * ny / 2 - 2) {
00969                                 f = (ctf1[l] * (1 - r) + ctf1[l + 1] * r);
00970                         }
00971                         tmp_data[j] += src[j] * f;
00972                         tmp_data[j + 1] += src[j + 1] * f;
00973                 }
00974         }
00975 
00976         EMData *image_fft = image->do_fft();
00977         image_fft->update();
00978         if(image_ctf) {delete image_ctf; image_ctf=0;}
00979 }
00980 
00981 EMData * CtfAverager::finish()
00982 {
00983         int j = 0;
00984         for (int y = 0; y < ny; y++) {
00985                 for (int x = 0; x < nx / 2; x++, j += 2) {
00986 #ifdef  _WIN32
00987                         float r = (float) _hypot(x, y - ny / 2.0f);
00988 #else
00989                         float r = (float) hypot(x, y - ny / 2.0f);
00990 #endif
00991                         int l = static_cast < int >(Util::fast_floor(r));
00992                         if (l >= 0 && l < ny / 2) {
00993                                 int k = y*nx/2 + x;
00994                                 snri[l] += (tdr[k] + tdi[k]/tn[k]);
00995                                 snrn[l] += 1;
00996                         }
00997                 }
00998         }
00999 
01000         for (int i = 0; i < ny / 2; i++) {
01001                 snri[i] *= nimg / snrn[i];
01002         }
01003 
01004         if(strcmp(outfile, "") != 0) {
01005                 Util::save_data(0, 1, snri, ny / 2, outfile);
01006         }
01007 
01008 
01009         float *cd = 0;
01010         if (curves) {
01011                 cd = curves->get_data();
01012         }
01013 
01014         for (int i = 0; i < Ctf::CTFOS * ny / 2; i++) {
01015                 float ctf0 = 0;
01016                 for (int j = 0; j < nimg; j++) {
01017                         ctf0 += ctfn[j][i];
01018                         if (ctf[j][i] == 0) {
01019                                 ctf[j][i] = 1.0e-12f;
01020                         }
01021 
01022                         if (curves) {
01023                                 cd[i] += ctf[j][i] * ctfn[j][i];
01024                                 cd[i + Ctf::CTFOS * ny / 2] += ctfn[j][i];
01025                                 cd[i + 2 * Ctf::CTFOS * ny / 2] += ctfn[j][i];
01026                         }
01027                 }
01028 
01029                 string alg_name = get_name();
01030 
01031                 if (alg_name == "CtfCW" && need_snr) {
01032                         snr[i] = ctf0;
01033                 }
01034 
01035                 float ctf1 = ctf0;
01036                 if (alg_name == "CtfCWauto") {
01037                         ctf1 = snri[i / Ctf::CTFOS];
01038                 }
01039 
01040                 if (ctf1 <= 0.0001f) {
01041                         ctf1 = 0.1f;
01042                 }
01043 
01044                 if (alg_name == "CtfC") {
01045                         for (int j = 0; j < nimg; j++) {
01046                                 ctf[j][i] = exp(-i * i / (filter * filter)) * ctfn[j][i] / (fabs(ctf[j][i]) * ctf1);
01047                         }
01048                 }
01049                 else if (alg_name == "Weighting") {
01050                         for (int j = 0; j < nimg; j++) {
01051                                 ctf[j][i] = ctfn[j][i] / ctf1;
01052                         }
01053                 }
01054                 else if (alg_name == "CtfCW") {
01055                         for (int j = 0; j < nimg; j++) {
01056                                 ctf[j][i] = (ctf1 / (ctf1 + 1)) * ctfn[j][i] / (ctf[j][i] * ctf1);
01057                         }
01058                 }
01059                 else if (alg_name == "CtfCWauto") {
01060                         for (int j = 0; j < nimg; j++) {
01061                                 ctf[j][i] = ctf1 * ctfn[j][i] / (fabs(ctf[j][i]) * ctf0);
01062                         }
01063                 }
01064         }
01065 
01066 
01067         if (curves) {
01068                 for (int i = 0; i < Ctf::CTFOS * ny / 2; i++) {
01069                         cd[i] /= cd[i + Ctf::CTFOS * ny / 2];
01070                 }
01071                 curves->update();
01072         }
01073 
01074         image0_copy->update();
01075 
01076         float *result_data = result->get_data();
01077         EMData *tmp_ift = image0_copy->do_ift();
01078         float *tmp_ift_data = tmp_ift->get_data();
01079         memcpy(result_data, tmp_ift_data, (nx - 2) * ny * sizeof(float));
01080 
01081         tmp_ift->update();
01082         result->update();
01083 
01084         if( image0_copy )
01085         {
01086                 delete image0_copy;
01087                 image0_copy = 0;
01088         }
01089 
01090         if (snri) {
01091                 delete[]snri;
01092                 snri = 0;
01093         }
01094 
01095         if (snrn) {
01096                 delete[]snrn;
01097                 snrn = 0;
01098         }
01099 
01100         if( snri )
01101         {
01102                 delete [] snri;
01103                 snri = 0;
01104         }
01105         if( snrn )
01106         {
01107                 delete [] snrn;
01108                 snrn = 0;
01109         }
01110         if( tdr )
01111         {
01112                 delete [] tdr;
01113                 tdr = 0;
01114         }
01115         if( tdi )
01116         {
01117                 delete [] tdi;
01118                 tdi = 0;
01119         }
01120         if( tn )
01121         {
01122                 delete [] tn;
01123                 tn = 0;
01124         }
01125 
01126         return result;
01127 }
01128 
01129 #if 0
01130 EMData *CtfAverager::average(const vector < EMData * >&image_list) const
01131 {
01132         if (image_list.size() == 0) {
01133                 return 0;
01134         }
01135 
01136         EMData *image0 = image_list[0];
01137         if (image0->get_zsize() != 1) {
01138                 LOGERR("Only 2D images are currently supported");
01139                 return 0;
01140         }
01141 
01142         string alg_name = get_name();
01143 
01144         if (alg_name == "CtfCW" || alg_name == "CtfCWauto") {
01145                 if (image0->get_ctf() != 0 && !image0->has_ctff()) {
01146                         LOGERR("Attempted CTF Correction with no ctf parameters");
01147                         return 0;
01148                 }
01149         }
01150         else {
01151                 if (image0->get_ctf() != 0) {
01152                         LOGERR("Attempted CTF Correction with no ctf parameters");
01153                         return 0;
01154                 }
01155         }
01156 
01157         size_t num_images = image_list.size();
01158         vector < float >*ctf = new vector < float >[num_images];
01159         vector < float >*ctfn = new vector < float >[num_images];
01160         float **src = new float *[num_images];
01161 
01162         Ctf::CtfType curve_type = Ctf::CTF_ABS_AMP;
01163         if (alg_name == "CtfCWauto") {
01164                 curve_type = Ctf::CTF_AMP;
01165         }
01166 
01167         for (size_t i = 0; i < num_images; i++) {
01168                 EMData *image = image_list[i]->do_fft();
01169                 image->ap2ri();
01170                 src[i] = image->get_data();
01171                 Ctf *image_ctf = image->get_ctf();
01172                 int ny = image->get_ysize();
01173                 ctf[i] = image_ctf->compute_1d(ny, curve_type);
01174 
01175                 if (ctf[i].size() == 0) {
01176                         LOGERR("Unexpected CTF correction problem");
01177                         return 0;
01178                 }
01179 
01180                 if (sf) {
01181                         ctfn[i] = image_ctf->compute_1d(ny, Ctf::CTF_ABS_SNR, sf);
01182                 }
01183                 else {
01184                         ctfn[i] = image_ctf->compute_1d(ny, Ctf::CTF_RELATIVE_SNR);
01185                 }
01186 
01187                 if(image_ctf) {delete image_ctf; image_ctf=0;}
01188         }
01189 
01190         EMData *image0_fft = image0->do_fft();
01191 
01192         int nx = image0_fft->get_xsize();
01193         int ny = image0_fft->get_ysize();
01194         int nz = image0_fft->get_zsize();
01195 
01196         EMData *result = new EMData();
01197         result->set_size(nx - 2, ny, nz);
01198 
01199         float *cd = 0;
01200         if (alg_name == "Weighting" && curves) {
01201                 if (!sf) {
01202                         LOGWARN("CTF curve in file will contain relative, not absolute SNR!");
01203                 }
01204                 curves->set_size(Ctf::CTFOS * ny / 2, 3, 1);
01205                 curves->to_zero();
01206                 cd = curves->get_data();
01207         }
01208 
01209         float filter = 0;
01210         if (alg_name == "CtfC") {
01211                 filter = params["filter"];
01212                 if (filter == 0) {
01213                         filter = 22.0f;
01214                 }
01215                 float apix_y = image0->get_attr_dict().get("apix_y");
01216                 float ds = 1.0f / (apix_y * ny * Ctf::CTFOS);
01217                 filter = 1.0f / (filter * ds);
01218         }
01219 
01220         float *snri = 0;
01221         float *snrn = 0;
01222 
01223         if (alg_name == "CtfCWauto") {
01224                 snri = new float[ny / 2];
01225                 snrn = new float[ny / 2];
01226 
01227                 for (int i = 0; i < ny / 2; i++) {
01228                         snri[i] = 0;
01229                         snrn[i] = 0;
01230                 }
01231 
01232                 int j = 0;
01233                 for (int y = 0; y < ny; y++) {
01234                         for (int x = 0; x < nx / 2; x++, j += 2) {
01235                                 float r = hypot(x, y - ny / 2.0f);
01236                                 int l = static_cast < int >(Util::fast_floor(r));
01237 
01238                                 if (l >= 0 && l < ny / 2) {
01239                                         float tdr = 1;
01240                                         float tdi = 1;
01241                                         float tn = 1;
01242 
01243                                         for (size_t i = 0; i < num_images; i++) {
01244                                                 tdr *= src[i][j];
01245                                                 tdi *= src[i][j + 1];
01246                                                 tn *= hypot(src[i][j], src[i][j + 1]);
01247                                         }
01248 
01249                                         tdr += tdi / tn;
01250                                         snri[l] += tdr;
01251                                         snrn[l] += 1;
01252                                 }
01253                         }
01254                 }
01255 
01256                 for (int i = 0; i < ny / 2; i++) {
01257                         snri[i] *= num_images / snrn[i];
01258                 }
01259                 if (outfile != "") {
01260                         Util::save_data(0, 1, snri, ny / 2, outfile);
01261                 }
01262         }
01263 
01264         for (int i = 0; i < Ctf::CTFOS * ny / 2; i++) {
01265                 float ctf0 = 0;
01266                 for (size_t j = 0; j < num_images; j++) {
01267                         ctf0 += ctfn[j][i];
01268                         if (ctf[j][i] == 0) {
01269                                 ctf[j][i] = 1.0e-12;
01270                         }
01271 
01272                         if (curves) {
01273                                 cd[i] += ctf[j][i] * ctfn[j][i];
01274                                 cd[i + Ctf::CTFOS * ny / 2] += ctfn[j][i];
01275                                 cd[i + 2 * Ctf::CTFOS * ny / 2] += ctfn[j][i];
01276                         }
01277                 }
01278 
01279                 if (alg_name == "CtfCW" && need_snr) {
01280                         snr[i] = ctf0;
01281                 }
01282 
01283                 float ctf1 = ctf0;
01284                 if (alg_name == "CtfCWauto") {
01285                         ctf1 = snri[i / Ctf::CTFOS];
01286                 }
01287 
01288                 if (ctf1 <= 0.0001f) {
01289                         ctf1 = 0.1f;
01290                 }
01291 
01292                 if (alg_name == "CtfC") {
01293                         for (size_t j = 0; j < num_images; j++) {
01294                                 ctf[j][i] = exp(-i * i / (filter * filter)) * ctfn[j][i] / (fabs(ctf[j][i]) * ctf1);
01295                         }
01296                 }
01297                 else if (alg_name == "Weighting") {
01298                         for (size_t j = 0; j < num_images; j++) {
01299                                 ctf[j][i] = ctfn[j][i] / ctf1;
01300                         }
01301                 }
01302                 else if (alg_name == "CtfCW") {
01303                         for (size_t j = 0; j < num_images; j++) {
01304                                 ctf[j][i] = (ctf1 / (ctf1 + 1)) * ctfn[j][i] / (ctf[j][i] * ctf1);
01305                         }
01306                 }
01307                 else if (alg_name == "CtfCWauto") {
01308                         for (size_t j = 0; j < num_images; j++) {
01309                                 ctf[j][i] = ctf1 * ctfn[j][i] / (fabs(ctf[j][i]) * ctf0);
01310                         }
01311                 }
01312         }
01313 
01314 
01315         if (curves) {
01316                 for (int i = 0; i < Ctf::CTFOS * ny / 2; i++) {
01317                         cd[i] /= cd[i + Ctf::CTFOS * ny / 2];
01318                 }
01319                 curves->update();
01320         }
01321 
01322         EMData *image0_copy = image0_fft->copy_head();
01323         image0_copy->ap2ri();
01324 
01325         float *tmp_data = image0_copy->get_data();
01326 
01327         int j = 0;
01328         for (int y = 0; y < ny; y++) {
01329                 for (int x = 0; x < nx / 2; x++, j += 2) {
01330                         float r = Ctf::CTFOS * sqrt(x * x + (y - ny / 2.0f) * (y - ny / 2.0f));
01331                         int l = static_cast < int >(Util::fast_floor(r));
01332                         r -= l;
01333 
01334                         tmp_data[j] = 0;
01335                         tmp_data[j + 1] = 0;
01336 
01337                         for (size_t i = 0; i < num_images; i++) {
01338                                 float f = 0;
01339                                 if (l <= Ctf::CTFOS * ny / 2 - 2) {
01340                                         f = (ctf[i][l] * (1 - r) + ctf[i][l + 1] * r);
01341                                 }
01342                                 tmp_data[j] += src[i][j] * f;
01343                                 tmp_data[j + 1] += src[i][j + 1] * f;
01344                         }
01345                 }
01346         }
01347 
01348         image0_copy->update();
01349 
01350         float *result_data = result->get_data();
01351         EMData *tmp_ift = image0_copy->do_ift();
01352         float *tmp_ift_data = tmp_ift->get_data();
01353         memcpy(result_data, tmp_ift_data, (nx - 2) * ny * sizeof(float));
01354 
01355         tmp_ift->update();
01356 
01357         if( image0_copy )
01358         {
01359                 delete image0_copy;
01360                 image0_copy = 0;
01361         }
01362 
01363         for (size_t i = 0; i < num_images; i++) {
01364                 EMData *img = image_list[i]->do_fft();
01365                 img->update();
01366         }
01367 
01368         if( src )
01369         {
01370                 delete[]src;
01371                 src = 0;
01372         }
01373 
01374         if( ctf )
01375         {
01376                 delete[]ctf;
01377                 ctf = 0;
01378         }
01379 
01380         if( ctfn )
01381         {
01382                 delete[]ctfn;
01383                 ctfn = 0;
01384         }
01385 
01386         if (snri) {
01387                 delete[]snri;
01388                 snri = 0;
01389         }
01390 
01391         if (snrn) {
01392                 delete[]snrn;
01393                 snrn = 0;
01394         }
01395 
01396         result->update();
01397         return result;
01398 }
01399 #endif
01400 
01401 
01402 void EMAN::dump_averagers()
01403 {
01404         dump_factory < Averager > ();
01405 }
01406 
01407 map<string, vector<string> > EMAN::dump_averagers_list()
01408 {
01409         return dump_factory_list < Averager > ();
01410 }

Generated on Mon Jul 19 13:03:42 2010 for EMAN2 by  doxygen 1.4.4