00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "reconstructor.h"
00037 #include "plugins/reconstructor_template.h"
00038 #include "ctf.h"
00039 #include "emassert.h"
00040 #include "symmetry.h"
00041 #include <cstring>
00042 #include <fstream>
00043 #include <iomanip>
00044 #include <boost/bind.hpp>
00045 #include <boost/format.hpp>
00046
00047 #include <gsl/gsl_statistics_double.h>
00048 #include <gsl/gsl_fit.h>
00049
00050 using namespace EMAN;
00051 using std::complex;
00052
00053
00054 #include <iostream>
00055 using std::cerr;
00056 using std::endl;
00057 using std::cout;
00058
00059 #include <algorithm>
00060
00061
00062 #include <iomanip>
00063 using std::setprecision;
00064
00065 template < typename T > void checked_delete( T*& x )
00066 {
00067 typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
00068 (void) sizeof(type_must_be_complete);
00069 delete x;
00070 x = NULL;
00071 }
00072
00073 const string FourierReconstructor::NAME = "fourier";
00074 const string FourierReconstructorSimple2D::NAME = "fouriersimple2D";
00075 const string WienerFourierReconstructor::NAME = "wiener_fourier";
00076 const string BackProjectionReconstructor::NAME = "back_projection";
00077 const string nn4Reconstructor::NAME = "nn4";
00078 const string nn4_rectReconstructor::NAME = "nn4_rect";
00079 const string nnSSNR_Reconstructor::NAME = "nnSSNR";
00080 const string nn4_ctfReconstructor::NAME = "nn4_ctf";
00081 const string nn4_ctf_rectReconstructor::NAME = "nn4_ctf_rect";
00082 const string nnSSNR_ctfReconstructor::NAME = "nnSSNR_ctf";
00083
00084 template <> Factory < Reconstructor >::Factory()
00085 {
00086 force_add<FourierReconstructor>();
00087 force_add<FourierReconstructorSimple2D>();
00088
00089 force_add<WienerFourierReconstructor>();
00090 force_add<BackProjectionReconstructor>();
00091 force_add<nn4Reconstructor>();
00092 force_add<nn4_rectReconstructor>();
00093 force_add<nnSSNR_Reconstructor>();
00094 force_add<nn4_ctfReconstructor>();
00095 force_add<nn4_ctf_rectReconstructor>();
00096 force_add<nnSSNR_ctfReconstructor>();
00097
00098 }
00099
00100 void FourierReconstructorSimple2D::setup()
00101 {
00102 nx = params.set_default("nx",0);
00103
00104 if ( nx < 0 ) throw InvalidValueException(nx, "nx must be positive");
00105
00106 bool is_fftodd = (nx % 2 == 1);
00107
00108 ny = nx;
00109 nx += 2-is_fftodd;
00110
00111 image = new EMData();
00112 image->set_size(nx, ny);
00113 image->set_complex(true);
00114 image->set_fftodd(is_fftodd);
00115 image->set_ri(true);
00116
00117 tmp_data = new EMData();
00118 tmp_data->set_size(nx/2, nx);
00119 }
00120
00121 int FourierReconstructorSimple2D::insert_slice(const EMData* const slice, const Transform & euler, const float weight)
00122 {
00123
00124
00125 if (!slice) throw NullPointerException("EMData pointer (input image) is NULL");
00126
00127 if ( slice->get_ndim() != 1 ) throw ImageDimensionException("Image dimension must be 1");
00128
00129
00130 if (slice->is_complex()) throw ImageFormatException("The image is complex, expecting real");
00131
00132 EMData* working_slice = slice->process("xform.phaseorigin.tocorner");
00133
00134
00135 working_slice->do_fft_inplace();
00136
00137 float* rdata = image->get_data();
00138 float* norm = tmp_data->get_data();
00139 float* dat = working_slice->get_data();
00140
00141 float g[4];
00142 int offset[4];
00143 float dt[2];
00144 offset[0] = 0; offset[1] = 2; offset[2] = nx; offset[3] = nx+2;
00145
00146 float alt = -((float)(euler.get_rotation("2d"))["alpha"])*M_PI/180.0f;
00147 for (int x = 0; x < working_slice->get_xsize() / 2; x++) {
00148
00149 float rx = (float) x;
00150
00151 float xx = rx*cos(alt);
00152 float yy = rx*sin(alt);
00153 float cc = 1.0;
00154
00155 if (xx < 0) {
00156 xx = -xx;
00157 yy = -yy;
00158 cc = -1.0;
00159 }
00160
00161 yy += ny / 2;
00162
00163
00164 dt[0] = dat[2*x];
00165 dt[1] = cc * dat[2*x+1];
00166
00167
00168 int x0 = (int) floor(xx);
00169 int y0 = (int) floor(yy);
00170
00171 int i = 2*x0 + y0*nx;
00172
00173 float dx = xx - x0;
00174 float dy = yy - y0;
00175
00176 g[0] = Util::agauss(1, dx, dy, 0, EMConsts::I2G);
00177 g[1] = Util::agauss(1, 1 - dx, dy, 0, EMConsts::I2G);
00178 g[2] = Util::agauss(1, dx, 1 - dy, 0, EMConsts::I2G);
00179 g[3] = Util::agauss(1, 1 - dx, 1 - dy, 0, EMConsts::I2G);
00180
00181
00182 if ( x0 == nx-2 ) {
00183 int k = i + offset[0];
00184 rdata[k] += g[0] * dt[0];
00185 rdata[k + 1] += g[0] * dt[1];
00186 norm[k/2] += g[0];
00187
00188 k = i + offset[2];
00189 rdata[k] += g[2] * dt[0];
00190 rdata[k + 1] += g[2] * dt[1];
00191 norm[k/2] += g[2];
00192 continue;
00193
00194 }
00195
00196 if ( x0 > nx-2 ) {
00197 int dif = x0 - (nx-2);
00198 x0 -= dif;
00199 }
00200
00201 if ( y0 == ny -1 ) {
00202 int k = i + offset[0];
00203 rdata[k] += g[0] * dt[0];
00204 rdata[k + 1] += g[0] * dt[1];
00205 norm[k/2] += g[0];
00206
00207 k = i + offset[1];
00208 rdata[k] += g[1] * dt[0];
00209 rdata[k + 1] += g[1] * dt[1];
00210 norm[k/2] += g[1];
00211 continue;
00212 }
00213
00214 if ( y0 > ny-1) {
00215 int dif = y0 - (ny-1);
00216 y0 -= dif;
00217 }
00218
00219 if (x0 >= nx - 2 || y0 >= ny - 1) continue;
00220
00221
00222
00223
00224 for (int j = 0; j < 4; j++)
00225 {
00226 int k = i + offset[j];
00227 rdata[k] += g[j] * dt[0];
00228 rdata[k + 1] += g[j] * dt[1];
00229 norm[k/2] += g[j];
00230
00231 }
00232 }
00233
00234 return 0;
00235
00236 }
00237
00238 EMData *FourierReconstructorSimple2D::finish(bool doift)
00239 {
00240 normalize_threed();
00241
00242 image->process_inplace("xform.fourierorigin.tocorner");
00243 image->do_ift_inplace();
00244 image->depad();
00245 image->process_inplace("xform.phaseorigin.tocenter");
00246
00247 return image;
00248 }
00249
00250 void ReconstructorVolumeData::normalize_threed(const bool sqrt_damp,const bool wiener)
00251
00252 {
00253 float* norm = tmp_data->get_data();
00254 float* rdata = image->get_data();
00255
00256
00257
00258
00259 if ( 0 == norm ) throw NullPointerException("The normalization volume was null!");
00260 if ( 0 == rdata ) throw NullPointerException("The complex reconstruction volume was null!");
00261
00262
00263
00264
00265
00266 float wfilt=0.0;
00267 if (wiener) wfilt=1.0;
00268
00269 for (int i = 0; i < subnx * subny * subnz; i += 2) {
00270 float d = norm[i/2];
00271 if (sqrt_damp) d*=sqrt(d);
00272 if (d == 0) {
00273 rdata[i] = 0;
00274 rdata[i + 1] = 0;
00275 }
00276 else {
00277
00278
00279 rdata[i] /= d+wfilt;
00280 rdata[i + 1] /= d+wfilt;
00281 }
00282 }
00283
00284
00285 if (subx0==0 && subnx>1 && subny==ny && subnz==nz) {
00286 for (int z=0; z<=nz/2; z++) {
00287 for (int y=1; y<=ny; y++) {
00288 if (y==0 && z==0) continue;
00289
00290 int i=(y%ny)*subnx+(z%nz)*subnx*subny;
00291 int i2=(ny-y)*subnx+((nz-z)%nz)*subnx*subny;
00292 float ar=(rdata[i]+rdata[i2])/2.0f;
00293 float ai=(rdata[i+1]-rdata[i2+1])/2.0f;
00294 rdata[i]=ar;
00295 rdata[i2]=ar;
00296 rdata[i+1]=ai;
00297 rdata[i2+1]=-ai;
00298 }
00299 }
00300 }
00301
00302 if (subx0+subnx==nx && subnx>1 && subny==ny && subnz==nz) {
00303 for (int z=0; z<=nz/2; z++) {
00304 for (int y=1; y<=ny; y++) {
00305 if (y==0 && z==0) continue;
00306
00307 int i=(y%ny)*subnx+(z%nz)*subnx*subny+subnx-2;
00308 int i2=(ny-y)*subnx+((nz-z)%nz)*subnx*subny+subnx-2;
00309 float ar=(rdata[i]+rdata[i2])/2.0f;
00310 float ai=(rdata[i+1]-rdata[i2+1])/2.0f;
00311 rdata[i]=ar;
00312 rdata[i2]=ar;
00313 rdata[i+1]=ai;
00314 rdata[i2+1]=-ai;
00315 }
00316 }
00317 }
00318 }
00319
00320 void FourierReconstructor::load_default_settings()
00321 {
00322 inserter=0;
00323 image=0;
00324 tmp_data=0;
00325 }
00326
00327 void FourierReconstructor::free_memory()
00328 {
00329 if (image) { delete image; image=0; }
00330 if (tmp_data) { delete tmp_data; tmp_data=0; }
00331 if ( inserter != 0 )
00332 {
00333 delete inserter;
00334 inserter = 0;
00335 }
00336 }
00337
00338 #include <sstream>
00339
00340 void FourierReconstructor::load_inserter()
00341 {
00342
00343
00344 Dict parms;
00345 parms["data"] = image;
00346 parms["norm"] = tmp_data->get_data();
00347
00348
00349
00350
00351
00352
00353
00354
00355 if ( inserter != 0 )
00356 {
00357 delete inserter;
00358 }
00359
00360 inserter = Factory<FourierPixelInserter3D>::get((string)params["mode"], parms);
00361 inserter->init();
00362 }
00363
00364 void FourierReconstructor::setup()
00365 {
00366
00367 params.set_default("mode","gauss_2");
00368
00369 vector<int> size=params["size"];
00370
00371 nx = size[0];
00372 ny = size[1];
00373 nz = size[2];
00374 nx2=nx/2-1;
00375 ny2=ny/2;
00376 nz2=nz/2;
00377
00378
00379
00380 bool is_fftodd = (nx % 2 == 1);
00381
00382
00383
00384 nx += 2-is_fftodd;
00385
00386 if (params.has_key("subvolume")) {
00387 vector<int> sub=params["subvolume"];
00388 subx0=sub[0];
00389 suby0=sub[1];
00390 subz0=sub[2];
00391 subnx=sub[3];
00392 subny=sub[4];
00393 subnz=sub[5];
00394
00395 if (subx0<0 || suby0<0 || subz0<0 || subx0+subnx>nx || suby0+subny>ny || subz0+subnz>nz)
00396 throw ImageDimensionException("The subvolume cannot extend outside the reconstructed volume");
00397
00398 }
00399 else {
00400 subx0=suby0=subz0=0;
00401 subnx=nx;
00402 subny=ny;
00403 subnz=nz;
00404 }
00405
00406
00407
00408 if (image) delete image;
00409 image = new EMData();
00410 image->set_size(subnx, subny, subnz);
00411 image->set_complex(true);
00412 image->set_fftodd(is_fftodd);
00413 image->set_ri(true);
00414 image->to_zero();
00415
00416 if (params.has_key("subvolume")) {
00417 image->set_attr("subvolume_x0",subx0);
00418 image->set_attr("subvolume_y0",suby0);
00419 image->set_attr("subvolume_z0",subz0);
00420 image->set_attr("subvolume_full_nx",nx);
00421 image->set_attr("subvolume_full_ny",ny);
00422 image->set_attr("subvolume_full_nz",nz);
00423 }
00424
00425 if (tmp_data) delete tmp_data;
00426 tmp_data = new EMData();
00427 tmp_data->set_size(subnx/2, subny, subnz);
00428 tmp_data->to_zero();
00429 tmp_data->update();
00430
00431 load_inserter();
00432
00433 if ( (bool) params["quiet"] == false )
00434 {
00435 cout << "3D Fourier dimensions are " << nx << " " << ny << " " << nz << endl;
00436 cout << "3D Fourier subvolume is " << subnx << " " << subny << " " << subnz << endl;
00437 cout << "You will require approximately " << setprecision(3) << (subnx*subny*subnz*sizeof(float)*1.5)/1000000000.0 << "GB of memory to reconstruct this volume" << endl;
00438 }
00439 }
00440
00441 void FourierReconstructor::setup_seed(EMData* seed,float seed_weight) {
00442
00443 params.set_default("mode","gauss_2");
00444
00445 vector<int> size=params["size"];
00446
00447 nx = size[0];
00448 ny = size[1];
00449 nz = size[2];
00450 nx2=nx/2-1;
00451 ny2=ny/2;
00452 nz2=nz/2;
00453
00454
00455
00456 bool is_fftodd = (nx % 2 == 1);
00457
00458
00459
00460 nx += 2-is_fftodd;
00461
00462 if (params.has_key("subvolume")) {
00463 vector<int> sub=params["subvolume"];
00464 subx0=sub[0];
00465 suby0=sub[1];
00466 subz0=sub[2];
00467 subnx=sub[3];
00468 subny=sub[4];
00469 subnz=sub[5];
00470
00471 if (subx0<0 || suby0<0 || subz0<0 || subx0+subnx>nx || suby0+subny>ny || subz0+subnz>nz)
00472 throw ImageDimensionException("The subvolume cannot extend outside the reconstructed volume");
00473
00474 }
00475 else {
00476 subx0=suby0=subz0=0;
00477 subnx=nx;
00478 subny=ny;
00479 subnz=nz;
00480 }
00481
00482 if (seed->get_xsize()!=subnx || seed->get_ysize()!=subny || seed->get_zsize()!=subnz || !seed->is_complex())
00483 throw ImageDimensionException("The dimensions of the seed volume do not match the reconstruction size");
00484
00485
00486 image = seed;
00487 if (params.has_key("subvolume")) {
00488 image->set_attr("subvolume_x0",subx0);
00489 image->set_attr("subvolume_y0",suby0);
00490 image->set_attr("subvolume_z0",subz0);
00491 image->set_attr("subvolume_full_nx",nx);
00492 image->set_attr("subvolume_full_ny",ny);
00493 image->set_attr("subvolume_full_nz",nz);
00494 }
00495
00496 if (tmp_data) delete tmp_data;
00497 tmp_data = new EMData();
00498 tmp_data->set_size(subnx/2, subny, subnz);
00499 tmp_data->to_value(seed_weight);
00500
00501 load_inserter();
00502
00503 if ( (bool) params["quiet"] == false )
00504 {
00505 cout << "Seeded direct Fourier inversion";
00506 cout << "3D Fourier dimensions are " << nx << " " << ny << " " << nz << endl;
00507 cout << "3D Fourier subvolume is " << subnx << " " << subny << " " << subnz << endl;
00508 cout << "You will require approximately " << setprecision(3) << (subnx*subny*subnz*sizeof(float)*1.5)/1000000000.0 << "GB of memory to reconstruct this volume" << endl;
00509 }
00510 }
00511
00512
00513 EMData* FourierReconstructor::preprocess_slice( const EMData* const slice, const Transform& t )
00514 {
00515
00516 EMData* return_slice = 0;
00517 Transform tmp(t);
00518 tmp.set_rotation(Dict("type","eman"));
00519
00520 if (tmp.is_identity()) return_slice=slice->copy();
00521 else return_slice = slice->process("xform",Dict("transform",&tmp));
00522
00523 return_slice->process_inplace("xform.phaseorigin.tocorner");
00524
00525
00526
00527 return_slice->do_fft_inplace();
00528
00529
00530
00531 return_slice->mult((float)sqrt(1.0f/(return_slice->get_ysize())*return_slice->get_xsize()));
00532
00533
00534
00535
00536 return_slice->set_attr("reconstruct_preproc",(int)1);
00537 return return_slice;
00538 }
00539
00540
00541 int FourierReconstructor::insert_slice(const EMData* const input_slice, const Transform & arg, const float weight)
00542 {
00543
00544 if (!input_slice) throw NullPointerException("EMData pointer (input image) is NULL");
00545
00546 Transform * rotation;
00547
00548
00549
00550 rotation = new Transform(arg);
00551
00552
00553 EMData *slice;
00554 if (input_slice->get_attr_default("reconstruct_preproc",(int) 0)) slice=input_slice->copy();
00555 else slice = preprocess_slice( input_slice, *rotation);
00556
00557
00558
00559
00560 rotation->set_scale(1.0);
00561 rotation->set_mirror(false);
00562 rotation->set_trans(0,0,0);
00563
00564
00565 do_insert_slice_work(slice, *rotation, weight);
00566
00567 delete rotation; rotation=0;
00568 delete slice;
00569
00570
00571 return 0;
00572 }
00573
00574 void FourierReconstructor::do_insert_slice_work(const EMData* const input_slice, const Transform & arg,const float weight)
00575 {
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]);
00587
00588 float inx=(float)(input_slice->get_xsize());
00589 float iny=(float)(input_slice->get_ysize());
00590
00591 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) {
00592 Transform t3d = arg*(*it);
00593 for (int y = -iny/2; y < iny/2; y++) {
00594 for (int x = 0; x <= inx/2; x++) {
00595
00596 float rx = (float) x/(inx-2.0f);
00597 float ry = (float) y/iny;
00598
00599 Vec3f coord(rx,ry,0);
00600 coord = coord*t3d;
00601 float xx = coord[0];
00602 float yy = coord[1];
00603 float zz = coord[2];
00604
00605
00606 xx=xx*(nx-2);
00607 yy=yy*ny;
00608 zz=zz*nz;
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618 inserter->insert_pixel(xx,yy,zz,input_slice->get_complex_at(x,y),weight);
00619 }
00620 }
00621 }
00622 }
00623
00624 int FourierReconstructor::determine_slice_agreement(EMData* input_slice, const Transform & arg, const float weight,bool sub)
00625 {
00626
00627 if (!input_slice) throw NullPointerException("EMData pointer (input image) is NULL");
00628
00629 Transform * rotation;
00630 rotation = new Transform(arg);
00631
00632 EMData *slice;
00633 if (input_slice->get_attr_default("reconstruct_preproc",(int) 0)) slice=input_slice->copy();
00634 else slice = preprocess_slice( input_slice, *rotation);
00635
00636
00637
00638
00639 rotation->set_scale(1.0);
00640 rotation->set_mirror(false);
00641 rotation->set_trans(0,0,0);
00642
00643
00644 if (sub) do_insert_slice_work(slice, *rotation, -weight);
00645
00646
00647 do_compare_slice_work(slice, *rotation,weight);
00648
00649 input_slice->set_attr("reconstruct_norm",slice->get_attr("reconstruct_norm"));
00650 input_slice->set_attr("reconstruct_absqual",slice->get_attr("reconstruct_absqual"));
00651
00652 input_slice->set_attr("reconstruct_weight",slice->get_attr("reconstruct_weight"));
00653
00654
00655 if (sub) do_insert_slice_work(slice, *rotation, weight);
00656
00657
00658 delete rotation;
00659 delete slice;
00660
00661
00662 return 0;
00663
00664 }
00665
00666 void FourierReconstructor::do_compare_slice_work(EMData* input_slice, const Transform & arg,float weight)
00667 {
00668
00669 float dt[3];
00670 float dt2[2];
00671 float *dat = input_slice->get_data();
00672 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]);
00673
00674 float inx=(float)(input_slice->get_xsize());
00675 float iny=(float)(input_slice->get_ysize());
00676
00677 double dot=0;
00678 double vweight=0;
00679 double power=0;
00680 double power2=0;
00681 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) {
00682 Transform t3d = arg*(*it);
00683 for (int y = -iny/2; y < iny/2; y++) {
00684 for (int x = 0; x <= inx/2; x++) {
00685 if (x==0 && y==0) continue;
00686
00687 float rx = (float) x/(inx-2);
00688 float ry = (float) y/iny;
00689
00690
00691
00692
00693 Vec3f coord(rx,ry,0);
00694 coord = coord*t3d;
00695 float xx = coord[0];
00696 float yy = coord[1];
00697 float zz = coord[2];
00698
00699
00700 if (fabs(xx)>0.5 || fabs(yy)>=0.5 || fabs(zz)>=0.5) continue;
00701
00702
00703 xx=xx*(nx-2);
00704 yy=yy*ny;
00705 zz=zz*nz;
00706
00707
00708 int idx = (int)(x * 2 + inx*(y<0?iny+y:y));
00709 dt2[0] = dat[idx];
00710 dt2[1] = dat[idx+1];
00711
00712
00713 if (!pixel_at(xx,yy,zz,dt) || dt[2]==0) continue;
00714
00715
00716 dot+=(dt[0]*dt2[0]+dt[1]*dt2[1])*dt[2];
00717 vweight+=dt[2];
00718 power+=(dt[0]*dt[0]+dt[1]*dt[1])*dt[2];
00719 power2+=(dt2[0]*dt2[0]+dt2[1]*dt2[1])*dt[2];
00720 }
00721 }
00722 }
00723
00724 dot/=sqrt(power*power2);
00725
00726 input_slice->set_attr("reconstruct_norm",(float)(power2<=0?1.0:sqrt(power/power2)));
00727 input_slice->set_attr("reconstruct_absqual",(float)dot);
00728 float rw=weight<=0?1.0f:1.0f/weight;
00729 input_slice->set_attr("reconstruct_qual",(float)(dot*rw/((rw-1.0)*dot+1.0)));
00730 input_slice->set_attr("reconstruct_weight",(float)vweight/(float)(subnx*subny*subnz));
00731
00732
00733 }
00734
00735 bool FourierReconstructor::pixel_at(const float& xx, const float& yy, const float& zz, float *dt)
00736 {
00737 int x0 = (int) floor(xx);
00738 int y0 = (int) floor(yy);
00739 int z0 = (int) floor(zz);
00740
00741 float *rdata=image->get_data();
00742 float *norm=tmp_data->get_data();
00743 float normsum=0,normsum2=0;
00744
00745 dt[0]=dt[1]=dt[2]=0.0;
00746
00747 if (nx==subnx) {
00748 if (x0<-nx2-1 || y0<-ny2-1 || z0<-nz2-1 || x0>nx2 || y0>ny2 || z0>nz2 ) return false;
00749
00750
00751 int x1=x0+1;
00752 int y1=y0+1;
00753 int z1=z0+1;
00754 if (x0<-nx2) x0=-nx2;
00755 if (x1>nx2) x1=nx2;
00756 if (y0<-ny2) y0=-ny2;
00757 if (y1>ny2) y1=ny2;
00758 if (z0<-nz2) z0=-nz2;
00759 if (z1>nz2) z1=nz2;
00760
00761 size_t idx=0;
00762 float r, gg;
00763 for (int k = z0 ; k <= z1; k++) {
00764 for (int j = y0 ; j <= y1; j++) {
00765 for (int i = x0; i <= x1; i ++) {
00766 r = Util::hypot3sq((float) i - xx, j - yy, k - zz);
00767 idx=image->get_complex_index_fast(i,j,k);
00768 gg = Util::fast_exp(-r / EMConsts::I2G);
00769
00770 dt[0]+=gg*rdata[idx];
00771 dt[1]+=(i<0?-1.0f:1.0f)*gg*rdata[idx+1];
00772 dt[2]+=norm[idx/2]*gg;
00773 normsum2+=gg;
00774 normsum+=gg*norm[idx/2];
00775 }
00776 }
00777 }
00778 if (normsum==0) return false;
00779 dt[0]/=normsum;
00780 dt[1]/=normsum;
00781 dt[2]/=normsum2;
00782
00783 return true;
00784 }
00785 else {
00786 size_t idx;
00787 float r, gg;
00788 for (int k = z0 ; k <= z0 + 1; k++) {
00789 for (int j = y0 ; j <= y0 + 1; j++) {
00790 for (int i = x0; i <= x0 + 1; i ++) {
00791 r = Util::hypot3sq((float) i - xx, j - yy, k - zz);
00792 idx=image->get_complex_index(i,j,k,subx0,suby0,subz0,nx,ny,nz);
00793 gg = Util::fast_exp(-r / EMConsts::I2G)*norm[idx/2];
00794
00795 dt[0]+=gg*rdata[idx];
00796 dt[1]+=(i<0?-1.0f:1.0f)*gg*rdata[idx+1];
00797 dt[2]+=norm[idx/2];
00798 normsum+=gg;
00799 }
00800 }
00801 }
00802
00803 if (normsum==0) return false;
00804 return true;
00805 }
00806 }
00807
00808
00809 EMData *FourierReconstructor::finish(bool doift)
00810 {
00811
00812
00813
00814 bool sqrtnorm=params.set_default("sqrtnorm",false);
00815 normalize_threed(sqrtnorm);
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831 if (doift) {
00832 image->do_ift_inplace();
00833 image->depad();
00834 image->process_inplace("xform.phaseorigin.tocenter");
00835 }
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852 image->update();
00853
00854 if (params.has_key("savenorm") && strlen((const char *)params["savenorm"])>0) {
00855 if (tmp_data->get_ysize()%2==0 && tmp_data->get_zsize()%2==0) tmp_data->process_inplace("xform.fourierorigin.tocenter");
00856 tmp_data->write_image((const char *)params["savenorm"]);
00857 }
00858
00859 delete tmp_data;
00860 tmp_data=0;
00861 EMData *ret=image;
00862 image=0;
00863
00864 return ret;
00865 }
00866
00867 int WienerFourierReconstructor::insert_slice(const EMData* const input_slice, const Transform & arg, const float weight)
00868 {
00869
00870 if (!input_slice) throw NullPointerException("EMData pointer (input image) is NULL");
00871
00872 Transform * rotation;
00873
00874
00875
00876 rotation = new Transform(arg);
00877
00878
00879 if (!input_slice->has_attr("ctf_snr_total"))
00880 throw NotExistingObjectException("ctf_snr_total","No SNR information present in class-average. Must use the ctf.auto or ctfw.auto averager.");
00881
00882 EMData *slice;
00883 if (input_slice->get_attr_default("reconstruct_preproc",(int) 0)) slice=input_slice->copy();
00884 else slice = preprocess_slice( input_slice, *rotation);
00885
00886
00887
00888
00889 rotation->set_scale(1.0);
00890 rotation->set_mirror(false);
00891 rotation->set_trans(0,0,0);
00892
00893
00894 do_insert_slice_work(slice, *rotation, weight);
00895
00896 delete rotation; rotation=0;
00897 delete slice;
00898
00899
00900 return 0;
00901 }
00902
00903 void WienerFourierReconstructor::do_insert_slice_work(const EMData* const input_slice, const Transform & arg,const float inweight)
00904 {
00905
00906 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]);
00907
00908 float inx=(float)(input_slice->get_xsize());
00909 float iny=(float)(input_slice->get_ysize());
00910
00911 int undo_wiener=(int)input_slice->get_attr_default("ctf_wiener_filtered",0);
00912
00913
00914 vector<float> snr=input_slice->get_attr("ctf_snr_total");
00915 float sub=1.0;
00916 if (inweight<0) sub=-1.0;
00917 float weight;
00918
00919 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) {
00920 Transform t3d = arg*(*it);
00921 for (int y = -iny/2; y < iny/2; y++) {
00922 for (int x = 0; x <= inx/2; x++) {
00923
00924 float rx = (float) x/(inx-2.0f);
00925 float ry = (float) y/iny;
00926
00927
00928 float rn = hypot(rx,ry);
00929 if (rn>=.5) continue;
00930 rn*=snr.size()*2.0;
00931 int rni=(int)floor(rn);
00932 if (rni>=snr.size()-1) weight=snr[snr.size()-1]*sub;
00933 else {
00934 rn-=rni;
00935 weight=Util::linear_interpolate(snr[rni],snr[rni+1],rn);
00936 }
00937
00938
00939 Vec3f coord(rx,ry,0);
00940 coord = coord*t3d;
00941 float xx = coord[0];
00942 float yy = coord[1];
00943 float zz = coord[2];
00944
00945
00946 xx=xx*(nx-2);
00947 yy=yy*ny;
00948 zz=zz*nz;
00949
00950
00951 if (undo_wiener) inserter->insert_pixel(xx,yy,zz,(input_slice->get_complex_at(x,y))*((weight+1.0f)/weight),weight*sub);
00952 else inserter->insert_pixel(xx,yy,zz,input_slice->get_complex_at(x,y),weight*sub);
00953 }
00954 }
00955 }
00956 }
00957
00958 int WienerFourierReconstructor::determine_slice_agreement(EMData* input_slice, const Transform & arg, const float weight,bool sub)
00959 {
00960
00961 if (!input_slice) throw NullPointerException("EMData pointer (input image) is NULL");
00962
00963 Transform * rotation;
00964 rotation = new Transform(arg);
00965
00966 EMData *slice;
00967 if (input_slice->get_attr_default("reconstruct_preproc",(int) 0)) slice=input_slice->copy();
00968 else slice = preprocess_slice( input_slice, *rotation);
00969
00970
00971
00972
00973 rotation->set_scale(1.0);
00974 rotation->set_mirror(false);
00975 rotation->set_trans(0,0,0);
00976
00977
00978
00979
00980 if (sub) do_insert_slice_work(slice, *rotation, -weight);
00981
00982
00983 do_compare_slice_work(slice, *rotation,weight);
00984
00985 input_slice->set_attr("reconstruct_norm",slice->get_attr("reconstruct_norm"));
00986 input_slice->set_attr("reconstruct_absqual",slice->get_attr("reconstruct_absqual"));
00987
00988 input_slice->set_attr("reconstruct_weight",slice->get_attr("reconstruct_weight"));
00989
00990
00991 if (sub) do_insert_slice_work(slice, *rotation, weight);
00992
00993
00994 delete rotation;
00995 delete slice;
00996
00997
00998 return 0;
00999
01000 }
01001
01002 void WienerFourierReconstructor::do_compare_slice_work(EMData* input_slice, const Transform & arg,float weight)
01003 {
01004
01005 float dt[3];
01006 float dt2[2];
01007 float *dat = input_slice->get_data();
01008 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]);
01009
01010 float inx=(float)(input_slice->get_xsize());
01011 float iny=(float)(input_slice->get_ysize());
01012
01013 double dot=0;
01014 double vweight=0;
01015 double power=0;
01016 double power2=0;
01017 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) {
01018 Transform t3d = arg*(*it);
01019 for (int y = -iny/2; y < iny/2; y++) {
01020 for (int x = 0; x <= inx/2; x++) {
01021 if (x==0 && y==0) continue;
01022
01023 float rx = (float) x/(inx-2);
01024 float ry = (float) y/iny;
01025
01026
01027
01028
01029 Vec3f coord(rx,ry,0);
01030 coord = coord*t3d;
01031 float xx = coord[0];
01032 float yy = coord[1];
01033 float zz = coord[2];
01034
01035
01036 if (fabs(xx)>0.5 || fabs(yy)>=0.5 || fabs(zz)>=0.5) continue;
01037
01038
01039 xx=xx*(nx-2);
01040 yy=yy*ny;
01041 zz=zz*nz;
01042
01043
01044 int idx = (int)(x * 2 + inx*(y<0?iny+y:y));
01045 dt2[0] = dat[idx];
01046 dt2[1] = dat[idx+1];
01047
01048
01049 if (!pixel_at(xx,yy,zz,dt) || dt[2]<=0) continue;
01050
01051
01052 dot+=(dt[0]*dt2[0]+dt[1]*dt2[1])*dt[2];
01053 vweight+=dt[2];
01054 power+=(dt[0]*dt[0]+dt[1]*dt[1])*dt[2];
01055 power2+=(dt2[0]*dt2[0]+dt2[1]*dt2[1])*dt[2];
01056 }
01057 }
01058 }
01059
01060 dot/=sqrt(power*power2);
01061
01062 input_slice->set_attr("reconstruct_norm",(float)(power2<=0?1.0:sqrt(power/power2)));
01063 input_slice->set_attr("reconstruct_absqual",(float)dot);
01064 float rw=weight<=0?1.0f:1.0f/weight;
01065 input_slice->set_attr("reconstruct_qual",(float)(dot*rw/((rw-1.0)*dot+1.0)));
01066 input_slice->set_attr("reconstruct_weight",(float)vweight/(float)(subnx*subny*subnz));
01067
01068
01069 }
01070
01071 bool WienerFourierReconstructor::pixel_at(const float& xx, const float& yy, const float& zz, float *dt)
01072 {
01073 int x0 = (int) floor(xx);
01074 int y0 = (int) floor(yy);
01075 int z0 = (int) floor(zz);
01076
01077 float *rdata=image->get_data();
01078 float *norm=tmp_data->get_data();
01079 float normsum=0,normsum2=0;
01080
01081 dt[0]=dt[1]=dt[2]=0.0;
01082
01083 if (nx==subnx) {
01084 if (x0<-nx2-1 || y0<-ny2-1 || z0<-nz2-1 || x0>nx2 || y0>ny2 || z0>nz2 ) return false;
01085
01086
01087 int x1=x0+1;
01088 int y1=y0+1;
01089 int z1=z0+1;
01090 if (x0<-nx2) x0=-nx2;
01091 if (x1>nx2) x1=nx2;
01092 if (y0<-ny2) y0=-ny2;
01093 if (y1>ny2) y1=ny2;
01094 if (z0<-nz2) z0=-nz2;
01095 if (z1>nz2) z1=nz2;
01096
01097 size_t idx=0;
01098 float r, gg;
01099 for (int k = z0 ; k <= z1; k++) {
01100 for (int j = y0 ; j <= y1; j++) {
01101 for (int i = x0; i <= x1; i ++) {
01102 r = Util::hypot3sq((float) i - xx, j - yy, k - zz);
01103 idx=image->get_complex_index_fast(i,j,k);
01104 gg = Util::fast_exp(-r / EMConsts::I2G);
01105
01106 dt[0]+=gg*rdata[idx];
01107 dt[1]+=(i<0?-1.0f:1.0f)*gg*rdata[idx+1];
01108 dt[2]+=norm[idx/2]*gg;
01109 normsum2+=gg;
01110 normsum+=gg*norm[idx/2];
01111 }
01112 }
01113 }
01114 if (normsum==0) return false;
01115 dt[0]/=normsum;
01116 dt[1]/=normsum;
01117 dt[2]/=normsum2;
01118
01119 return true;
01120 }
01121 else {
01122 size_t idx;
01123 float r, gg;
01124 for (int k = z0 ; k <= z0 + 1; k++) {
01125 for (int j = y0 ; j <= y0 + 1; j++) {
01126 for (int i = x0; i <= x0 + 1; i ++) {
01127 r = Util::hypot3sq((float) i - xx, j - yy, k - zz);
01128 idx=image->get_complex_index(i,j,k,subx0,suby0,subz0,nx,ny,nz);
01129 gg = Util::fast_exp(-r / EMConsts::I2G)*norm[idx/2];
01130
01131 dt[0]+=gg*rdata[idx];
01132 dt[1]+=(i<0?-1.0f:1.0f)*gg*rdata[idx+1];
01133 dt[2]+=norm[idx/2];
01134 normsum+=gg;
01135 }
01136 }
01137 }
01138
01139 if (normsum==0) return false;
01140 return true;
01141 }
01142 }
01143
01144
01145 EMData *WienerFourierReconstructor::finish(bool doift)
01146 {
01147
01148 bool sqrtnorm=params.set_default("sqrtnorm",false);
01149 normalize_threed(sqrtnorm,true);
01150
01151 if (doift) {
01152 image->do_ift_inplace();
01153 image->depad();
01154 image->process_inplace("xform.phaseorigin.tocenter");
01155 }
01156
01157 image->update();
01158
01159 if (params.has_key("savenorm") && strlen((const char *)params["savenorm"])>0) {
01160 if (tmp_data->get_ysize()%2==0 && tmp_data->get_zsize()%2==0) tmp_data->process_inplace("xform.fourierorigin.tocenter");
01161 tmp_data->write_image((const char *)params["savenorm"]);
01162 }
01163
01164 delete tmp_data;
01165 tmp_data=0;
01166 EMData *ret=image;
01167 image=0;
01168
01169 return ret;
01170 }
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733 void BackProjectionReconstructor::setup()
01734 {
01735 int size = params["size"];
01736 image = new EMData();
01737 nx = size;
01738 ny = size;
01739 if ( (int) params["zsample"] != 0 ) nz = params["zsample"];
01740 else nz = size;
01741 image->set_size(nx, ny, nz);
01742 }
01743
01744 EMData* BackProjectionReconstructor::preprocess_slice(const EMData* const slice, const Transform& t)
01745 {
01746
01747 EMData* return_slice = slice->process("normalize.edgemean");
01748 return_slice->process_inplace("filter.linearfourier");
01749
01750 Transform tmp(t);
01751 tmp.set_rotation(Dict("type","eman"));
01752 Vec2f trans = tmp.get_trans_2d();
01753 float scale = tmp.get_scale();
01754 bool mirror = tmp.get_mirror();
01755 if (trans[0] != 0 || trans[1] != 0 || scale != 1.0 ) {
01756 return_slice->transform(tmp);
01757 } else if ( mirror == true ) {
01758 return_slice = slice->process("xform.flip",Dict("axis","x"));
01759 }
01760
01761 return return_slice;
01762 }
01763
01764 int BackProjectionReconstructor::insert_slice(const EMData* const input, const Transform &t, const float sliceweight)
01765 {
01766 if (!input) {
01767 LOGERR("try to insert NULL slice");
01768 return 1;
01769 }
01770
01771 if (input->get_xsize() != input->get_ysize() || input->get_xsize() != nx) {
01772 LOGERR("tried to insert image that was not correction dimensions");
01773 return 1;
01774 }
01775
01776 Transform * transform;
01777 if ( input->has_attr("xform.projection") ) {
01778 transform = (Transform*) (input->get_attr("xform.projection"));
01779 } else {
01780 transform = new Transform(t);
01781 }
01782 EMData* slice = preprocess_slice(input, t);
01783
01784 float weight = params["weight"];
01785 slice->mult(weight);
01786
01787 EMData *tmp = new EMData();
01788 tmp->set_size(nx, ny, nz);
01789
01790 float *slice_data = slice->get_data();
01791 float *tmp_data = tmp->get_data();
01792
01793 size_t nxy = nx * ny;
01794 size_t nxy_size = nxy * sizeof(float);;
01795 for (int i = 0; i < nz; ++i) {
01796 memcpy(&tmp_data[nxy * i], slice_data, nxy_size);
01797 }
01798
01799 transform->set_scale(1.0);
01800 transform->set_mirror(false);
01801 transform->set_trans(0,0,0);
01802 transform->invert();
01803
01804 tmp->transform(*transform);
01805 image->add(*tmp);
01806
01807 if(transform) {delete transform; transform=0;}
01808 delete tmp;
01809 delete slice;
01810
01811 return 0;
01812 }
01813
01814 EMData *BackProjectionReconstructor::finish(bool doift)
01815 {
01816
01817 Symmetry3D* sym = Factory<Symmetry3D>::get((string)params["sym"]);
01818 vector<Transform> syms = sym->get_syms();
01819
01820 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) {
01821
01822 EMData tmpcopy(*image);
01823 tmpcopy.transform(*it);
01824 image->add(tmpcopy);
01825 }
01826
01827 image->mult(1.0f/(float)sym->get_nsym());
01828 delete sym;
01829 return image;
01830 }
01831
01832 EMData* EMAN::padfft_slice( const EMData* const slice, const Transform& t, int npad )
01833 {
01834 int nx = slice->get_xsize();
01835 int ny = slice->get_ysize();
01836 int ndim = (ny==1) ? 1 : 2;
01837
01838 if( ndim==2 && nx!=ny )
01839 {
01840
01841 throw std::runtime_error("Tried to padfft a 2D slice which is not square.");
01842 }
01843
01844
01845 EMData* temp = slice->average_circ_sub();
01846
01847 Assert( temp != NULL );
01848 EMData* zeropadded = temp->norm_pad( false, npad );
01849 Assert( zeropadded != NULL );
01850 checked_delete( temp );
01851
01852 zeropadded->do_fft_inplace();
01853 EMData* padfftslice = zeropadded;
01854
01855
01856 Vec2f trans = t.get_trans_2d();
01857 float sx = -trans[0];
01858 float sy = -trans[1];
01859 if(sx != 0.0f || sy != 0.0)
01860 padfftslice->process_inplace("filter.shift", Dict("x_shift", sx, "y_shift", sy, "z_shift", 0.0f));
01861
01862 int remove = slice->get_attr_default("remove", 0);
01863 padfftslice->set_attr( "remove", remove );
01864
01865
01866
01867 padfftslice->center_origin_fft();
01868 return padfftslice;
01869 }
01870
01871 nn4Reconstructor::nn4Reconstructor()
01872 {
01873 m_volume = NULL;
01874 m_wptr = NULL;
01875 m_result = NULL;
01876 }
01877
01878 nn4Reconstructor::nn4Reconstructor( const string& symmetry, int size, int npad )
01879 {
01880 m_volume = NULL;
01881 m_wptr = NULL;
01882 m_result = NULL;
01883 setup( symmetry, size, npad );
01884 load_default_settings();
01885 print_params();
01886 }
01887
01888 nn4Reconstructor::~nn4Reconstructor()
01889 {
01890 if( m_delete_volume ) checked_delete(m_volume);
01891
01892 if( m_delete_weight ) checked_delete( m_wptr );
01893
01894 checked_delete( m_result );
01895 }
01896
01897 enum weighting_method { NONE, ESTIMATE, VORONOI };
01898
01899 float max2d( int kc, const vector<float>& pow_a )
01900 {
01901 float max = 0.0;
01902 for( int i=-kc; i <= kc; ++i ) {
01903 for( int j=-kc; j <= kc; ++j ) {
01904 if( i==0 && j==0 ) continue;
01905 {
01906 int c = 2*kc+1 - std::abs(i) - std::abs(j);
01907 max = max + pow_a[c];
01908 }
01909 }
01910 }
01911 return max;
01912 }
01913
01914 float max3d( int kc, const vector<float>& pow_a )
01915 {
01916 float max = 0.0;
01917 for( int i=-kc; i <= kc; ++i ) {
01918 for( int j=-kc; j <= kc; ++j ) {
01919 for( int k=-kc; k <= kc; ++k ) {
01920 if( i==0 && j==0 && k==0 ) continue;
01921
01922 {
01923 int c = 3*kc+1 - std::abs(i) - std::abs(j) - std::abs(k);
01924 max = max + pow_a[c];
01925
01926
01927 }
01928 }
01929 }
01930 }
01931 return max;
01932 }
01933
01934
01935 void nn4Reconstructor::setup()
01936 {
01937 int size = params["size"];
01938 int npad = params["npad"];
01939
01940
01941 string symmetry;
01942 if( params.has_key("symmetry") ) symmetry = params["symmetry"].to_str();
01943 else symmetry = "c1";
01944
01945 if( params.has_key("ndim") ) m_ndim = params["ndim"];
01946 else m_ndim = 3;
01947
01948 if( params.has_key( "snr" ) ) m_osnr = 1.0f/float( params["snr"] );
01949 else m_osnr = 0.0;
01950
01951 setup( symmetry, size, npad );
01952 }
01953
01954 void nn4Reconstructor::setup( const string& symmetry, int size, int npad )
01955 {
01956 m_weighting = ESTIMATE;
01957 m_wghta = 0.2f;
01958
01959 m_symmetry = symmetry;
01960 m_npad = npad;
01961 m_nsym = Transform::get_nsym(m_symmetry);
01962
01963 m_vnx = size;
01964 m_vny = size;
01965 m_vnz = (m_ndim==3) ? size : 1;
01966
01967 m_vnxp = size*npad;
01968 m_vnyp = size*npad;
01969 m_vnzp = (m_ndim==3) ? size*npad : 1;
01970
01971 m_vnxc = m_vnxp/2;
01972 m_vnyc = m_vnyp/2;
01973 m_vnzc = (m_ndim==3) ? m_vnzp/2 : 1;
01974
01975 buildFFTVolume();
01976 buildNormVolume();
01977
01978 }
01979
01980
01981 void nn4Reconstructor::buildFFTVolume() {
01982 int offset = 2 - m_vnxp%2;
01983
01984 if( params.has_key("fftvol") ) {
01985 m_volume = params["fftvol"];
01986 m_delete_volume = false;
01987 } else {
01988 m_volume = new EMData();
01989 m_delete_volume = true;
01990 }
01991
01992 if( m_volume->get_xsize() != m_vnxp+offset && m_volume->get_ysize() != m_vnyp && m_volume->get_zsize() != m_vnzp ) {
01993 m_volume->set_size(m_vnxp+offset,m_vnyp,m_vnzp);
01994 m_volume->to_zero();
01995 }
01996
01997
01998
01999
02000 if ( m_vnxp % 2 == 0 ) m_volume->set_fftodd(0);
02001 else m_volume->set_fftodd(1);
02002
02003
02004 m_volume->set_nxc(m_vnxp/2);
02005 m_volume->set_complex(true);
02006 m_volume->set_ri(true);
02007 m_volume->set_fftpad(true);
02008 m_volume->set_attr("npad", m_npad);
02009 m_volume->set_array_offsets(0,1,1);
02010 }
02011
02012 void nn4Reconstructor::buildNormVolume() {
02013
02014 if( params.has_key("weight") ) {
02015 m_wptr = params["weight"];
02016 m_delete_weight = false;
02017 } else {
02018 m_wptr = new EMData();
02019 m_delete_weight = true;
02020 }
02021
02022 if( m_wptr->get_xsize() != m_vnxc+1 &&
02023 m_wptr->get_ysize() != m_vnyp &&
02024 m_wptr->get_zsize() != m_vnzp ) {
02025 m_wptr->set_size(m_vnxc+1,m_vnyp,m_vnzp);
02026 m_wptr->to_zero();
02027 }
02028
02029 m_wptr->set_array_offsets(0,1,1);
02030 }
02031
02032 void printImage( const EMData* line )
02033 {
02034 Assert( line->get_zsize()==1 );
02035
02036
02037 int nx = line->get_xsize();
02038 int ny = line->get_ysize();
02039 for( int j=0; j < ny; ++j ) {
02040 for( int i=0; i < nx; ++i ) printf( "%10.3f ", line->get_value_at(i,j) );
02041 printf( "\n" );
02042 }
02043 }
02044
02045
02046
02047 int nn4Reconstructor::insert_slice(const EMData* const slice, const Transform& t, const float weight) {
02048
02049 if (!slice) {
02050 LOGERR("try to insert NULL slice");
02051 return 1;
02052 }
02053
02054 int padffted= slice->get_attr_default( "padffted", 0 );
02055 if( m_ndim==3 ) {
02056 if ( padffted==0 && (slice->get_xsize()!=slice->get_ysize() || slice->get_xsize()!=m_vnx) ) {
02057
02058 LOGERR("Tried to insert a slice that is the wrong size.");
02059 return 1;
02060 }
02061 } else {
02062 Assert( m_ndim==2 );
02063 if( slice->get_ysize() !=1 ) {
02064 LOGERR( "for 2D reconstruction, a line is excepted" );
02065 return 1;
02066 }
02067 }
02068
02069 EMData* padfft = NULL;
02070
02071 if( padffted != 0 ) padfft = new EMData(*slice);
02072 else padfft = padfft_slice( slice, t, m_npad );
02073
02074 int mult= slice->get_attr_default( "mult", 1 );
02075 Assert( mult > 0 );
02076
02077 if( m_ndim==3 ) {
02078 insert_padfft_slice( padfft, t, mult );
02079 } else {
02080 float alpha = padfft->get_attr( "alpha" );
02081 alpha = alpha/180.0f*M_PI;
02082 for(int i=0; i < m_vnxc+1; ++i ) {
02083 float xnew = i*cos(alpha);
02084 float ynew = -i*sin(alpha);
02085 float btqr = padfft->get_value_at( 2*i, 0, 0 );
02086 float btqi = padfft->get_value_at( 2*i+1, 0, 0 );
02087 if( xnew < 0.0 ) {
02088 xnew *= -1;
02089 ynew *= -1;
02090 btqi *= -1;
02091 }
02092
02093 int ixn = int(xnew+0.5+m_vnxp) - m_vnxp;
02094 int iyn = int(ynew+0.5+m_vnyp) - m_vnyp;
02095
02096 if(iyn < 0 ) iyn += m_vnyp;
02097
02098 (*m_volume)( 2*ixn, iyn+1, 1 ) += btqr *float(mult);
02099 (*m_volume)( 2*ixn+1, iyn+1, 1 ) += btqi * float(mult);
02100 (*m_wptr)(ixn,iyn+1, 1) += float(mult);
02101 }
02102
02103 }
02104 checked_delete( padfft );
02105 return 0;
02106 }
02107
02108 int nn4Reconstructor::insert_padfft_slice( EMData* padfft, const Transform& t, int mult )
02109 {
02110 Assert( padfft != NULL );
02111
02112
02113 for (int isym=0; isym < m_nsym; isym++) {
02114 Transform tsym = t.get_sym(m_symmetry, isym);
02115
02116 m_volume->nn( m_wptr, padfft, tsym, mult);
02117 }
02118 return 0;
02119 }
02120
02121
02122 #define tw(i,j,k) tw[ i-1 + (j-1+(k-1)*iy)*ix ]
02123
02124 void circumf( EMData* win , int npad)
02125 {
02126 float *tw = win->get_data();
02127
02128
02129 int ix = win->get_xsize();
02130 int iy = win->get_ysize();
02131 int iz = win->get_zsize();
02132 int L2 = (ix/2)*(ix/2);
02133 int L2P = (ix/2-1)*(ix/2-1);
02134
02135 int IP = ix/2+1;
02136 int JP = iy/2+1;
02137 int KP = iz/2+1;
02138
02139
02140 float* sincx = new float[IP+1];
02141 float* sincy = new float[JP+1];
02142 float* sincz = new float[KP+1];
02143
02144 sincx[0] = 1.0f;
02145 sincy[0] = 1.0f;
02146 sincz[0] = 1.0f;
02147
02148 float cdf = M_PI/float(npad*2*ix);
02149 for (int i = 1; i <= IP; ++i) sincx[i] = sin(i*cdf)/(i*cdf);
02150 cdf = M_PI/float(npad*2*iy);
02151 for (int i = 1; i <= JP; ++i) sincy[i] = sin(i*cdf)/(i*cdf);
02152 cdf = M_PI/float(npad*2*iz);
02153 for (int i = 1; i <= KP; ++i) sincz[i] = sin(i*cdf)/(i*cdf);
02154 for (int k = 1; k <= iz; ++k) {
02155 int kkp = abs(k-KP);
02156 for (int j = 1; j <= iy; ++j) {
02157 cdf = sincy[abs(j- JP)]*sincz[kkp];
02158 for (int i = 1; i <= ix; ++i) tw(i,j,k) /= (sincx[abs(i-IP)]*cdf);
02159 }
02160 }
02161
02162 delete[] sincx;
02163 delete[] sincy;
02164 delete[] sincz;
02165
02166 float TNR = 0.0f;
02167 size_t m = 0;
02168 for (int k = 1; k <= iz; ++k) {
02169 for (int j = 1; j <= iy; ++j) {
02170 for (int i = 1; i <= ix; ++i) {
02171 size_t LR = (k-KP)*(k-KP)+(j-JP)*(j-JP)+(i-IP)*(i-IP);
02172 if (LR >= (size_t)L2P && LR<=(size_t)L2) {
02173 TNR += tw(i,j,k);
02174 ++m;
02175 }
02176 }
02177 }
02178 }
02179
02180 TNR /=float(m);
02181
02182
02183 for (int k = 1; k <= iz; ++k) {
02184 for (int j = 1; j <= iy; ++j) {
02185 for (int i = 1; i <= ix; ++i) {
02186 size_t LR = (k-KP)*(k-KP)+(j-JP)*(j-JP)+(i-IP)*(i-IP);
02187 if (LR<=(size_t)L2) tw(i,j,k) -= TNR;
02188 else tw(i,j,k) = 0.0f;
02189
02190 }
02191 }
02192 }
02193
02194 }
02195
02196
02197 EMData* nn4Reconstructor::finish(bool doift)
02198 {
02199 if( m_ndim==3 ) {
02200 m_volume->symplane0(m_wptr);
02201 } else {
02202 for( int i=1; i <= m_vnyp; ++i ) {
02203
02204 if( (*m_wptr)(0, i, 1)==0.0 ) {
02205 int j = m_vnyp + 1 - i;
02206 (*m_wptr)(0, i, 1) = (*m_wptr)(0, j, 1);
02207 (*m_volume)(0, i, 1) = (*m_volume)(0, j, 1);
02208 (*m_volume)(1, i, 1) = (*m_volume)(1, j, 1);
02209 }
02210 }
02211 }
02212
02213
02214 int box = 7;
02215 int kc = (box-1)/2;
02216 vector< float > pow_a( m_ndim*kc+1, 1.0 );
02217 for( unsigned int i=1; i < pow_a.size(); ++i ) pow_a[i] = pow_a[i-1] * exp(m_wghta);
02218 pow_a.back()=0.0;
02219
02220 float alpha = 0.0;
02221 if( m_ndim==3) {
02222 int vol = box*box*box;
02223 float max = max3d( kc, pow_a );
02224 alpha = ( 1.0f - 1.0f/(float)vol ) / max;
02225 } else {
02226 int ara = box*box;
02227 float max = max2d( kc, pow_a );
02228 alpha = ( 1.0f - 1.0f/(float)ara ) / max;
02229 }
02230
02231 int ix,iy,iz;
02232 for (iz = 1; iz <= m_vnzp; iz++) {
02233 for (iy = 1; iy <= m_vnyp; iy++) {
02234 for (ix = 0; ix <= m_vnxc; ix++) {
02235 if ( (*m_wptr)(ix,iy,iz) > 0) {
02236 float tmp;
02237 tmp = (-2*((ix+iy+iz)%2)+1)/((*m_wptr)(ix,iy,iz)+m_osnr);
02238
02239 if( m_weighting == ESTIMATE ) {
02240 int cx = ix;
02241 int cy = (iy<=m_vnyc) ? iy - 1 : iy - 1 - m_vnyp;
02242 int cz = (iz<=m_vnzc) ? iz - 1 : iz - 1 - m_vnzp;
02243 float sum = 0.0;
02244 for( int ii = -kc; ii <= kc; ++ii ) {
02245 int nbrcx = cx + ii;
02246 if( nbrcx >= m_vnxc ) continue;
02247 for( int jj= -kc; jj <= kc; ++jj ) {
02248 int nbrcy = cy + jj;
02249 if( nbrcy <= -m_vnyc || nbrcy >= m_vnyc ) continue;
02250
02251 int kcz = (m_ndim==3) ? kc : 0;
02252 for( int kk = -kcz; kk <= kcz; ++kk ) {
02253 int nbrcz = cz + kk;
02254 if( nbrcz <= -m_vnyc || nbrcz >= m_vnyc ) continue;
02255 if( nbrcx < 0 ) {
02256 nbrcx = -nbrcx;
02257 nbrcy = -nbrcy;
02258 nbrcz = -nbrcz;
02259 }
02260 int nbrix = nbrcx;
02261 int nbriy = nbrcy >= 0 ? nbrcy + 1 : nbrcy + 1 + m_vnyp;
02262 int nbriz = nbrcz >= 0 ? nbrcz + 1 : nbrcz + 1 + m_vnzp;
02263 if( (*m_wptr)( nbrix, nbriy, nbriz ) == 0 ) {
02264 int c = m_ndim*kc+1 - std::abs(ii) - std::abs(jj) - std::abs(kk);
02265 sum = sum + pow_a[c];
02266 }
02267 }
02268 }
02269 }
02270 float wght = 1.0f / ( 1.0f - alpha * sum );
02271 tmp = tmp * wght;
02272 }
02273 (*m_volume)(2*ix,iy,iz) *= tmp;
02274 (*m_volume)(2*ix+1,iy,iz) *= tmp;
02275 }
02276 }
02277 }
02278 }
02279
02280
02281
02282
02283 m_volume->do_ift_inplace();
02284
02285
02286 int npad = m_volume->get_attr("npad");
02287 m_volume->depad();
02288 circumf( m_volume, npad );
02289 m_volume->set_array_offsets( 0, 0, 0 );
02290
02291 m_result = m_volume->copy();
02292 return m_result;
02293 }
02294 #undef tw
02295
02296
02297 nn4_rectReconstructor::nn4_rectReconstructor()
02298 {
02299 m_volume = NULL;
02300 m_wptr = NULL;
02301 m_result = NULL;
02302 }
02303
02304 nn4_rectReconstructor::nn4_rectReconstructor( const string& symmetry, int size, int npad )
02305 {
02306 m_volume = NULL;
02307 m_wptr = NULL;
02308 m_result = NULL;
02309 setup( symmetry, size, npad );
02310 load_default_settings();
02311 print_params();
02312 }
02313
02314 nn4_rectReconstructor::~nn4_rectReconstructor()
02315 {
02316 if( m_delete_volume ) checked_delete(m_volume);
02317
02318 if( m_delete_weight ) checked_delete( m_wptr );
02319
02320 checked_delete( m_result );
02321 }
02322
02323
02324 void nn4_rectReconstructor::setup()
02325 {
02326 m_sizeofprojection = params["sizeprojection"];
02327 int npad = params["npad"];
02328 m_count=0;
02329
02330 string symmetry;
02331 if( params.has_key("symmetry") ) symmetry = params["symmetry"].to_str();
02332 else symmetry = "c1";
02333
02334 if( params.has_key("ndim") ) m_ndim = params["ndim"];
02335 else m_ndim = 3;
02336
02337 if( params.has_key( "snr" ) ) m_osnr = 1.0f/float( params["snr"] );
02338 else m_osnr = 0.0;
02339
02340 setup( symmetry, m_sizeofprojection, npad );
02341 }
02342
02343 void nn4_rectReconstructor::setup( const string& symmetry, int sizeprojection, int npad )
02344 {
02345 m_weighting = ESTIMATE;
02346 m_wghta = 0.2f;
02347 m_symmetry = symmetry;
02348 m_npad = npad;
02349 m_nsym = Transform::get_nsym(m_symmetry);
02350
02351 if( params.has_key("sizex") ) m_vnx = params["sizex"];
02352 else if(params.has_key("xratio"))
02353 {
02354 float temp=params["xratio"];
02355 m_vnx=int(float(sizeprojection)*temp);
02356 }
02357 else m_vnx=sizeprojection;
02358
02359 if( params.has_key("sizey") ) m_vny = params["sizey"];
02360 else if (params.has_key("yratio"))
02361 {
02362 float temp=params["yratio"];
02363 m_vny=int(float(sizeprojection)*temp);
02364 }
02365 else m_vny=sizeprojection;
02366
02367 if( params.has_key("sizez") )
02368 m_vnz = params["sizez"];
02369 else
02370 m_vnz = (m_ndim==3) ? sizeprojection : 1;
02371
02372 m_xratio=float(m_vnx)/float(sizeprojection);
02373 m_yratio=float(m_vny)/float(sizeprojection);
02374
02375
02376
02377
02378
02379 m_vnxp = m_vnx*npad;
02380 m_vnyp = m_vny*npad;
02381 m_vnzp = (m_ndim==3) ? m_vnz*npad : 1;
02382
02383 m_vnxc = m_vnxp/2;
02384 m_vnyc = m_vnyp/2;
02385 m_vnzc = (m_ndim==3) ? m_vnzp/2 : 1;
02386
02387 buildFFTVolume();
02388 buildNormVolume();
02389
02390
02391 }
02392
02393
02394 void nn4_rectReconstructor::buildFFTVolume() {
02395 int offset = 2 - m_vnxp%2;
02396
02397 if( params.has_key("fftvol") ) {
02398 m_volume = params["fftvol"];
02399 m_delete_volume = false;
02400 } else {
02401 m_volume = new EMData();
02402 m_delete_volume = true;
02403 }
02404
02405 if( m_volume->get_xsize() != m_vnxp+offset && m_volume->get_ysize() != m_vnyp && m_volume->get_zsize() != m_vnzp ) {
02406 m_volume->set_size(m_vnxp+offset,m_vnyp,m_vnzp);
02407 m_volume->to_zero();
02408 }
02409
02410
02411
02412
02413 if ( m_vnxp % 2 == 0 ) m_volume->set_fftodd(0);
02414 else m_volume->set_fftodd(1);
02415
02416
02417 m_volume->set_nxc(m_vnxp/2);
02418 m_volume->set_complex(true);
02419 m_volume->set_ri(true);
02420 m_volume->set_fftpad(true);
02421 m_volume->set_attr("npad", m_npad);
02422 m_volume->set_array_offsets(0,1,1);
02423 }
02424
02425 void nn4_rectReconstructor::buildNormVolume() {
02426
02427 if( params.has_key("weight") ) {
02428 m_wptr = params["weight"];
02429 m_delete_weight = false;
02430 } else {
02431 m_wptr = new EMData();
02432 m_delete_weight = true;
02433 }
02434
02435 if( m_wptr->get_xsize() != m_vnxc+1 &&
02436 m_wptr->get_ysize() != m_vnyp &&
02437 m_wptr->get_zsize() != m_vnzp ) {
02438 m_wptr->set_size(m_vnxc+1,m_vnyp,m_vnzp);
02439 m_wptr->to_zero();
02440 }
02441
02442 m_wptr->set_array_offsets(0,1,1);
02443 }
02444
02445
02446
02447 int nn4_rectReconstructor::insert_slice(const EMData* const slice, const Transform& t, const float weight) {
02448
02449
02450
02451
02452 if (!slice) {
02453 LOGERR("try to insert NULL slice");
02454 return 1;
02455 }
02456
02457 int padffted= slice->get_attr_default( "padffted", 0 );
02458 if( m_ndim==3 ) {
02459 if ( padffted==0 && (slice->get_xsize()!=slice->get_ysize() || slice->get_xsize()!=m_sizeofprojection) ) {
02460
02461
02462 LOGERR("Tried to insert a slice that is the wrong size.");
02463 return 1;
02464 }
02465 }
02466 if (m_ndim==2) {
02467 Assert( m_ndim==2 );
02468 if( slice->get_ysize() !=1 ) {
02469 LOGERR( "for 2D reconstruction, a line is excepted" );
02470 return 1;
02471 }
02472 }
02473
02474 EMData* padfft = NULL;
02475
02476 if( padffted != 0 ) padfft = new EMData(*slice);
02477 else padfft = padfft_slice( slice, t, m_npad );
02478
02479 int mult= slice->get_attr_default( "mult", 1 );
02480 Assert( mult > 0 );
02481
02482 if( m_ndim==3 ) {
02483 insert_padfft_slice( padfft, t, mult );
02484
02485 } else {
02486 float ellipse_length,ellipse_step,cos_alpha,sin_alpha;
02487 int ellipse_length_int;
02488 float alpha = padfft->get_attr( "alpha" );
02489 alpha = alpha/180.0f*M_PI;
02490 int loop_range;
02491 float temp1,temp2;
02492 temp1=m_xratio*cos(alpha)*float(m_sizeofprojection*m_npad)/2;
02493 temp2=m_yratio*sin(alpha)*float(m_sizeofprojection*m_npad)/2;
02494 ellipse_length=sqrt(temp1*temp1+temp2*temp2);
02495 ellipse_length_int=int(ellipse_length);
02496 ellipse_step=0.5*(m_sizeofprojection*m_npad)/float(ellipse_length_int);
02497 loop_range=ellipse_length_int;
02498 cos_alpha=temp1/ellipse_length;
02499 sin_alpha=temp2/ellipse_length;
02500 if(m_count%100==0)
02501 {
02502 std::cout<<"#############################################################"<<std::endl;
02503 std::cout<<"line insert start=="<<m_count<<std::endl;
02504 std::cout<<"ellipse lenth=="<<ellipse_length_int<<"ellips step=="<<ellipse_step<<std::endl;
02505 std::cout<<"loop_range"<<loop_range<<std::endl;
02506 std::cout<<"x and y ratio=="<<m_xratio<<" "<<m_yratio<<std::endl;
02507 std::cout<<"cos sin of alpha=="<<cos(alpha)<<" "<<sin(alpha)<<std::endl;
02508 std::cout<<"cos sin of alpha_new==="<<cos_alpha<<sin_alpha<<std::endl;
02509 std::cout<<"alpah dig==="<<cos_alpha<<sin_alpha<<std::endl;
02510 std::cout<<"prjection maximum==="<<loop_range*ellipse_step<<"ideal maximum"<<m_sizeofprojection*m_npad/2<<std::endl;
02511 std::cout<<"x_size=="<<m_volume->get_xsize()<<"y_size=="<<m_volume->get_ysize()<<std::endl;
02512 std::cout<<"#############################################################"<<std::endl;
02513
02514
02515
02516
02517 }
02518 for(int i=0; i <=loop_range; ++i ) {
02519 float xnew = i*cos_alpha;
02520 float ynew = -i*sin_alpha;
02521 if(m_count%100==0&&i==loop_range)
02522 std::cout<<"x_new=="<<xnew<<"Y_new=="<<ynew<<std::endl;
02523 float btqr=0,btqi=0;
02524 float xprj=i*ellipse_step;
02525 float t=xprj-int(xprj);
02526 btqr = (1-t)*padfft->get_value_at( 2*int(xprj), 0, 0 )+t*padfft->get_value_at( 2*(1+int(xprj)), 0, 0 );
02527 btqi = (1-t)*padfft->get_value_at( 2*int(xprj)+1, 0, 0 )+t*padfft->get_value_at( 2*(1+int(xprj))+1, 0, 0 );
02528 if( xnew < 0.0 ) {
02529 xnew *= -1;
02530 ynew *= -1;
02531 btqi *= -1;
02532 }
02533
02534 int ixn = int(xnew+0.5+m_vnxp) - m_vnxp;
02535 int iyn = int(ynew+0.5+m_vnyp) - m_vnyp;
02536
02537 if(iyn < 0 ) iyn += m_vnyp;
02538 if(m_count%100==0&&i==loop_range)
02539 std::cout<<"xnn=="<<ixn<<"ynn=="<<iyn<<std::endl;
02540 (*m_volume)( 2*ixn, iyn+1, 1 ) += btqr *float(mult);
02541 (*m_volume)( 2*ixn+1, iyn+1, 1 ) += btqi * float(mult);
02542 (*m_wptr)(ixn,iyn+1, 1) += float(mult);
02543 }
02544
02545
02546 }
02547 checked_delete( padfft );
02548 return 0;
02549 }
02550
02551
02552
02553
02554 int nn4_rectReconstructor::insert_padfft_slice( EMData* padded, const Transform& t, int mult )
02555 {
02556 Assert( padfft != NULL );
02557
02558
02559 for( int isym=0; isym < m_nsym; isym++) {
02560 Transform tsym = t.get_sym( m_symmetry, isym );
02561 m_volume->insert_rect_slice(m_wptr, padded, t, m_sizeofprojection, m_xratio, m_yratio, m_npad, mult);
02562 }
02563
02564 return 0;
02565
02566 }
02567
02568 #define tw(i,j,k) tw[ i-1 + (j-1+(k-1)*iy)*ix ]
02569 void circumf_rect( EMData* win , int npad)
02570 {
02571 float *tw = win->get_data();
02572
02573
02574 int ix = win->get_xsize();
02575 int iy = win->get_ysize();
02576 int iz = win->get_zsize();
02577
02578 int IP = ix/2+1;
02579 int JP = iy/2+1;
02580 int KP = iz/2+1;
02581
02582
02583 float* sincx = new float[IP+1];
02584 float* sincy = new float[JP+1];
02585 float* sincz = new float[KP+1];
02586
02587 sincx[0] = 1.0f;
02588 sincy[0] = 1.0f;
02589 sincz[0] = 1.0f;
02590
02591 float cdf = M_PI/float(npad*2*ix);
02592 for (int i = 1; i <= IP; ++i) sincx[i] = sin(i*cdf)/(i*cdf);
02593 cdf = M_PI/float(npad*2*iy);
02594 for (int i = 1; i <= JP; ++i) sincy[i] = sin(i*cdf)/(i*cdf);
02595 cdf = M_PI/float(npad*2*iz);
02596 for (int i = 1; i <= KP; ++i) sincz[i] = sin(i*cdf)/(i*cdf);
02597 for (int k = 1; k <= iz; ++k) {
02598 int kkp = abs(k-KP);
02599 for (int j = 1; j <= iy; ++j) {
02600 cdf = sincy[abs(j- JP)]*sincz[kkp];
02601 for (int i = 1; i <= ix; ++i) tw(i,j,k) /= (sincx[abs(i-IP)]*cdf);
02602 }
02603 }
02604
02605 delete[] sincx;
02606 delete[] sincy;
02607 delete[] sincz;
02608
02609
02610
02611 float dxx = 1.0/float(0.25*ix*ix);
02612 float dyy = 1.0/float(0.25*iy*iy);
02613
02614
02615
02616 float LR2=(float(ix)/2-1)*(float(ix)/2-1)*dxx;
02617
02618 float TNR = 0.0f;
02619 size_t m = 0;
02620 for (int k = 1; k <= iz; ++k) {
02621 for (int j = 1; j <= iy; ++j) {
02622 for (int i = 1; i <= ix; ++i) {
02623 float LR = (j-JP)*(j-JP)*dyy+(i-IP)*(i-IP)*dxx;
02624 if (LR<=1.0f && LR >= LR2) {
02625 TNR += tw(i,j,k);
02626 ++m;
02627 }
02628 }
02629 }
02630 }
02631
02632 TNR /=float(m);
02633
02634
02635 for (int k = 1; k <= iz; ++k) {
02636 for (int j = 1; j <= iy; ++j) {
02637 for (int i = 1; i <= ix; ++i) {
02638 float LR = (j-JP)*(j-JP)*dyy+(i-IP)*(i-IP)*dxx;
02639 if (LR<=1.0f) tw(i,j,k)=tw(i,j,k)-TNR;
02640 else tw(i,j,k) = 0.0f;
02641 }
02642 }
02643 }
02644
02645 }
02646 #undef tw
02647
02648
02649
02650 EMData* nn4_rectReconstructor::finish(bool doift)
02651 {
02652
02653 if( m_ndim==3 ) {
02654 m_volume->symplane0_rect(m_wptr);
02655 } else {
02656 for( int i=1; i <= m_vnyp; ++i ) {
02657
02658 if( (*m_wptr)(0, i, 1)==0.0 ) {
02659 int j = m_vnyp + 1 - i;
02660 (*m_wptr)(0, i, 1) = (*m_wptr)(0, j, 1);
02661 (*m_volume)(0, i, 1) = (*m_volume)(0, j, 1);
02662 (*m_volume)(1, i, 1) = (*m_volume)(1, j, 1);
02663 }
02664 }
02665 }
02666
02667
02668 int box = 7;
02669 int kc = (box-1)/2;
02670 vector< float > pow_a( m_ndim*kc+1, 1.0 );
02671 for( unsigned int i=1; i < pow_a.size(); ++i ) pow_a[i] = pow_a[i-1] * exp(m_wghta);
02672 pow_a.back()=0.0;
02673
02674 float alpha = 0.0;
02675 if( m_ndim==3) {
02676 int vol = box*box*box;
02677 float max = max3d( kc, pow_a );
02678 alpha = ( 1.0f - 1.0f/(float)vol ) / max;
02679 } else {
02680 int ara = box*box;
02681 float max = max2d( kc, pow_a );
02682 alpha = ( 1.0f - 1.0f/(float)ara ) / max;
02683 }
02684
02685 int ix,iy,iz;
02686 for (iz = 1; iz <= m_vnzp; iz++) {
02687 for (iy = 1; iy <= m_vnyp; iy++) {
02688 for (ix = 0; ix <= m_vnxc; ix++) {
02689 if ( (*m_wptr)(ix,iy,iz) > 0) {
02690 float tmp;
02691 tmp = (-2*((ix+iy+iz)%2)+1)/((*m_wptr)(ix,iy,iz)+m_osnr);
02692
02693 if( m_weighting == ESTIMATE ) {
02694 int cx = ix;
02695 int cy = (iy<=m_vnyc) ? iy - 1 : iy - 1 - m_vnyp;
02696 int cz = (iz<=m_vnzc) ? iz - 1 : iz - 1 - m_vnzp;
02697 float sum = 0.0;
02698 for( int ii = -kc; ii <= kc; ++ii ) {
02699 int nbrcx = cx + ii;
02700 if( nbrcx >= m_vnxc ) continue;
02701 for( int jj= -kc; jj <= kc; ++jj ) {
02702 int nbrcy = cy + jj;
02703 if( nbrcy <= -m_vnyc || nbrcy >= m_vnyc ) continue;
02704
02705 int kcz = (m_ndim==3) ? kc : 0;
02706 for( int kk = -kcz; kk <= kcz; ++kk ) {
02707 int nbrcz = cz + kk;
02708 if( nbrcz <= -m_vnyc || nbrcz >= m_vnyc ) continue;
02709 if( nbrcx < 0 ) {
02710 nbrcx = -nbrcx;
02711 nbrcy = -nbrcy;
02712 nbrcz = -nbrcz;
02713 }
02714 int nbrix = nbrcx;
02715 int nbriy = nbrcy >= 0 ? nbrcy + 1 : nbrcy + 1 + m_vnyp;
02716 int nbriz = nbrcz >= 0 ? nbrcz + 1 : nbrcz + 1 + m_vnzp;
02717 if( (*m_wptr)( nbrix, nbriy, nbriz ) == 0 ) {
02718 int c = m_ndim*kc+1 - std::abs(ii) - std::abs(jj) - std::abs(kk);
02719 sum = sum + pow_a[c];
02720 }
02721 }
02722 }
02723 }
02724 float wght = 1.0f / ( 1.0f - alpha * sum );
02725 tmp = tmp * wght;
02726 }
02727 (*m_volume)(2*ix,iy,iz) *= tmp;
02728 (*m_volume)(2*ix+1,iy,iz) *= tmp;
02729 }
02730 }
02731 }
02732 }
02733
02734
02735
02736
02737 m_volume->do_ift_inplace();
02738
02739
02740 int npad = m_volume->get_attr("npad");
02741 m_volume->depad();
02742 circumf_rect( m_volume, npad );
02743
02744 m_volume->set_array_offsets( 0, 0, 0 );
02745
02746 m_result = m_volume->copy();
02747 return m_result;
02748 }
02749
02750
02751
02752
02753
02754
02755 nnSSNR_Reconstructor::nnSSNR_Reconstructor()
02756 {
02757 m_volume = NULL;
02758 m_wptr = NULL;
02759 m_wptr2 = NULL;
02760 m_result = NULL;
02761 }
02762
02763 nnSSNR_Reconstructor::nnSSNR_Reconstructor( const string& symmetry, int size, int npad)
02764 {
02765 m_volume = NULL;
02766 m_wptr = NULL;
02767 m_wptr2 = NULL;
02768 m_result = NULL;
02769
02770 setup( symmetry, size, npad );
02771 }
02772
02773 nnSSNR_Reconstructor::~nnSSNR_Reconstructor()
02774 {
02775 if( m_delete_volume ) checked_delete(m_volume);
02776
02777 if( m_delete_weight ) checked_delete( m_wptr );
02778
02779 if( m_delete_weight2 ) checked_delete( m_wptr2 );
02780
02781 checked_delete( m_result );
02782 }
02783
02784 void nnSSNR_Reconstructor::setup()
02785 {
02786 int size = params["size"];
02787 int npad = params["npad"];
02788
02789 string symmetry;
02790 if( params.has_key("symmetry") ) symmetry = params["symmetry"].to_str();
02791 else symmetry = "c1";
02792
02793 setup( symmetry, size, npad );
02794 }
02795
02796 void nnSSNR_Reconstructor::setup( const string& symmetry, int size, int npad )
02797 {
02798
02799 m_weighting = ESTIMATE;
02800 m_wghta = 0.2f;
02801 m_wghtb = 0.004f;
02802
02803 m_symmetry = symmetry;
02804 m_npad = npad;
02805 m_nsym = Transform::get_nsym(m_symmetry);
02806
02807 m_vnx = size;
02808 m_vny = size;
02809 m_vnz = size;
02810
02811 m_vnxp = size*npad;
02812 m_vnyp = size*npad;
02813 m_vnzp = size*npad;
02814
02815 m_vnxc = m_vnxp/2;
02816 m_vnyc = m_vnyp/2;
02817 m_vnzc = m_vnzp/2;
02818
02819 buildFFTVolume();
02820 buildNormVolume();
02821 buildNorm2Volume();
02822
02823 }
02824
02825 void nnSSNR_Reconstructor::buildFFTVolume() {
02826
02827 if( params.has_key("fftvol") ) {
02828 m_volume = params["fftvol"];
02829 m_delete_volume = false;
02830 } else {
02831 m_volume = new EMData();
02832 m_delete_volume = true;
02833 }
02834 m_volume->set_size(m_vnxp+ 2 - m_vnxp%2,m_vnyp,m_vnzp);
02835 m_volume->to_zero();
02836 if ( m_vnxp % 2 == 0 ) m_volume->set_fftodd(0);
02837 else m_volume->set_fftodd(1);
02838
02839 m_volume->set_nxc(m_vnxc);
02840 m_volume->set_complex(true);
02841 m_volume->set_ri(true);
02842 m_volume->set_fftpad(true);
02843 m_volume->set_attr("npad", m_npad);
02844 m_volume->set_array_offsets(0,1,1);
02845 }
02846
02847 void nnSSNR_Reconstructor::buildNormVolume() {
02848 if( params.has_key("weight") ) {
02849 m_wptr = params["weight"];
02850 m_delete_weight = false;
02851 } else {
02852 m_wptr = new EMData();
02853 m_delete_weight = true;
02854 }
02855
02856 m_wptr->set_size(m_vnxc+1,m_vnyp,m_vnzp);
02857 m_wptr->to_zero();
02858
02859 m_wptr->set_array_offsets(0,1,1);
02860 }
02861
02862 void nnSSNR_Reconstructor::buildNorm2Volume() {
02863
02864 if( params.has_key("weight2") ) {
02865 m_wptr2 = params["weight2"];
02866 m_delete_weight2 = false;
02867 } else {
02868 m_wptr2 = new EMData();
02869 m_delete_weight2 = true;
02870 }
02871 m_wptr2->set_size(m_vnxc+1,m_vnyp,m_vnzp);
02872 m_wptr2->to_zero();
02873 m_wptr2->set_array_offsets(0,1,1);
02874 }
02875
02876
02877 int nnSSNR_Reconstructor::insert_slice(const EMData* const slice, const Transform& t, const float weight) {
02878
02879 if (!slice) {
02880 LOGERR("try to insert NULL slice");
02881 return 1;
02882 }
02883
02884 int padffted=slice->get_attr_default( "padffted", 0 );
02885
02886 if ( padffted==0 && (slice->get_xsize()!=slice->get_ysize() || slice->get_xsize()!=m_vnx) ) {
02887
02888 LOGERR("Tried to insert a slice that has wrong size.");
02889 return 1;
02890 }
02891
02892 EMData* padfft = NULL;
02893
02894 if( padffted != 0 ) padfft = new EMData(*slice);
02895 else padfft = padfft_slice( slice, t, m_npad );
02896
02897 int mult = slice->get_attr_default("mult", 1);
02898
02899 Assert( mult > 0 );
02900 insert_padfft_slice( padfft, t, mult );
02901
02902 checked_delete( padfft );
02903 return 0;
02904 }
02905
02906 int nnSSNR_Reconstructor::insert_padfft_slice( EMData* padfft, const Transform& t, int mult )
02907 {
02908 Assert( padfft != NULL );
02909
02910 for (int isym=0; isym < m_nsym; isym++) {
02911 Transform tsym = t.get_sym(m_symmetry, isym);
02912 m_volume->nn_SSNR( m_wptr, m_wptr2, padfft, tsym, mult);
02913 }
02914 return 0;
02915 }
02916
02917
02918 #define tw(i,j,k) tw[ i-1 + (j-1+(k-1)*iy)*ix ]
02919 EMData* nnSSNR_Reconstructor::finish(bool doift)
02920 {
02921
02922
02923
02924
02925
02926
02927 int kz, ky;
02928
02929 int box = 7;
02930 int kc = (box-1)/2;
02931 float alpha = 0.0;
02932 float argx, argy, argz;
02933 vector< float > pow_a( 3*kc+1, 1.0 );
02934 float w = params["w"];
02935 EMData* SSNR = params["SSNR"];
02936
02937
02938
02939
02940 EMData* vol_ssnr = new EMData();
02941 vol_ssnr->set_size(m_vnxp+ 2 - m_vnxp%2, m_vnyp ,m_vnzp);
02942 vol_ssnr->to_zero();
02943 if ( m_vnxp % 2 == 0 ) vol_ssnr->set_fftodd(0);
02944 else vol_ssnr->set_fftodd(1);
02945 vol_ssnr->set_nxc(m_vnxc);
02946 vol_ssnr->set_complex(true);
02947 vol_ssnr->set_ri(true);
02948 vol_ssnr->set_fftpad(false);
02949
02950
02951 float dx2 = 1.0f/float(m_vnxc)/float(m_vnxc);
02952 float dy2 = 1.0f/float(m_vnyc)/float(m_vnyc);
02953 #ifdef _WIN32
02954 float dz2 = 1.0f/_cpp_max(float(m_vnzc),1.0f)/_cpp_max(float(m_vnzc),1.0f);
02955 int inc = Util::round(float(_cpp_max(_cpp_max(m_vnxc,m_vnyc),m_vnzc))/w);
02956 #else
02957 float dz2 = 1.0f/std::max(float(m_vnzc),1.0f)/std::max(float(m_vnzc),1.0f);
02958 int inc = Util::round(float(std::max(std::max(m_vnxc,m_vnyc),m_vnzc))/w);
02959 #endif //_WIN32
02960 SSNR->set_size(inc+1,4,1);
02961
02962 float *nom = new float[inc+1];
02963 float *denom = new float[inc+1];
02964 int *nn = new int[inc+1];
02965 int *ka = new int[inc+1];
02966 float wght = 1.0f;
02967 for (int i = 0; i <= inc; i++) {
02968 nom[i] = 0.0f;
02969 denom[i] = 0.0f;
02970 nn[i] = 0;
02971 ka[i] = 0;
02972 }
02973
02974 m_volume->symplane1(m_wptr, m_wptr2);
02975
02976 if ( m_weighting == ESTIMATE ) {
02977 int vol = box*box*box;
02978 for( unsigned int i=1; i < pow_a.size(); ++i ) pow_a[i] = pow_a[i-1] * exp(m_wghta);
02979 pow_a[3*kc] = 0.0;
02980 float max = max3d( kc, pow_a );
02981 alpha = ( 1.0f - 1.0f/(float)vol ) / max;
02982 }
02983
02984 for (int iz = 1; iz <= m_vnzp; iz++) {
02985 if ( iz-1 > m_vnzc ) kz = iz-1-m_vnzp; else kz = iz-1;
02986 argz = float(kz*kz)*dz2;
02987 for (int iy = 1; iy <= m_vnyp; iy++) {
02988 if ( iy-1 > m_vnyc ) ky = iy-1-m_vnyp; else ky = iy-1;
02989 argy = argz + float(ky*ky)*dy2;
02990 for (int ix = 0; ix <= m_vnxc; ix++) {
02991 float Kn = (*m_wptr)(ix,iy,iz);
02992 argx = std::sqrt(argy + float(ix*ix)*dx2);
02993 int r = Util::round(float(inc)*argx);
02994 if ( r >= 0 && Kn > 4.5f ) {
02995 if ( m_weighting == ESTIMATE ) {
02996 int cx = ix;
02997 int cy = (iy<=m_vnyc) ? iy - 1 : iy - 1 - m_vnyp;
02998 int cz = (iz<=m_vnzc) ? iz - 1 : iz - 1 - m_vnzp;
02999
03000 float sum = 0.0;
03001 for( int ii = -kc; ii <= kc; ++ii ) {
03002 int nbrcx = cx + ii;
03003 if( nbrcx >= m_vnxc ) continue;
03004 for ( int jj= -kc; jj <= kc; ++jj ) {
03005 int nbrcy = cy + jj;
03006 if( nbrcy <= -m_vnyc || nbrcy >= m_vnyc ) continue;
03007 for( int kk = -kc; kk <= kc; ++kk ) {
03008 int nbrcz = cz + jj;
03009 if ( nbrcz <= -m_vnyc || nbrcz >= m_vnyc ) continue;
03010 if( nbrcx < 0 ) {
03011 nbrcx = -nbrcx;
03012 nbrcy = -nbrcy;
03013 nbrcz = -nbrcz;
03014 }
03015 int nbrix = nbrcx;
03016 int nbriy = nbrcy >= 0 ? nbrcy + 1 : nbrcy + 1 + m_vnyp;
03017 int nbriz = nbrcz >= 0 ? nbrcz + 1 : nbrcz + 1 + m_vnzp;
03018 if( (*m_wptr)( nbrix, nbriy, nbriz ) == 0 ) {
03019 int c = 3*kc+1 - std::abs(ii) - std::abs(jj) - std::abs(kk);
03020 sum = sum + pow_a[c];
03021 }
03022 }
03023 }
03024 }
03025 wght = 1.0f / ( 1.0f - alpha * sum );
03026 }
03027 float nominator = std::norm(m_volume->cmplx(ix,iy,iz))/Kn;
03028 float denominator = ((*m_wptr2)(ix,iy,iz)-nominator)/(Kn-1.0f);
03029
03030 if( (ix>0 || (kz>=0 && (ky>=0 || kz!=0)))) {
03031 if ( r <= inc ) {
03032 nom[r] += nominator*wght;
03033 denom[r] += denominator/Kn*wght;
03034 nn[r] += 2;
03035 ka[r] += int(Kn);
03036 }
03037
03038
03039
03040
03041
03042
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053 }
03054 (*vol_ssnr)(2*ix, iy-1, iz-1) = denominator*wght;
03055
03056
03057 }
03058 }
03059 }
03060 }
03061
03062 for (int i = 0; i <= inc; i++) {
03063 (*SSNR)(i,0,0) = nom[i];
03064 (*SSNR)(i,1,0) = denom[i];
03065 (*SSNR)(i,2,0) = static_cast<float>(nn[i]);
03066 (*SSNR)(i,3,0) = static_cast<float>(ka[i]);
03067 }
03068 vol_ssnr->update();
03069 return vol_ssnr;
03070 }
03071 #undef tw
03072
03073
03074
03075
03076
03077
03078
03079 nn4_ctfReconstructor::nn4_ctfReconstructor()
03080 {
03081 m_volume = NULL;
03082 m_wptr = NULL;
03083 m_result = NULL;
03084 }
03085
03086 nn4_ctfReconstructor::nn4_ctfReconstructor( const string& symmetry, int size, int npad, float snr, int sign )
03087 {
03088 setup( symmetry, size, npad, snr, sign );
03089 }
03090
03091 nn4_ctfReconstructor::~nn4_ctfReconstructor()
03092 {
03093 if( m_delete_volume ) checked_delete(m_volume);
03094
03095 if( m_delete_weight ) checked_delete( m_wptr );
03096
03097 checked_delete( m_result );
03098 }
03099
03100 void nn4_ctfReconstructor::setup()
03101 {
03102 if( ! params.has_key("size") ) throw std::logic_error("Error: image size is not given");
03103
03104 int size = params["size"];
03105 int npad = params.has_key("npad") ? int(params["npad"]) : 4;
03106
03107 int sign = 1;
03108 string symmetry = params.has_key("symmetry")? params["symmetry"].to_str() : "c1";
03109
03110 float snr = params["snr"];
03111
03112 m_varsnr = params.has_key("varsnr") ? int(params["varsnr"]) : 0;
03113 setup( symmetry, size, npad, snr, sign );
03114
03115 }
03116
03117 void nn4_ctfReconstructor::setup( const string& symmetry, int size, int npad, float snr, int sign )
03118 {
03119 m_weighting = ESTIMATE;
03120 if( params.has_key("weighting") ) {
03121 int tmp = int( params["weighting"] );
03122 if( tmp==0 ) m_weighting = NONE;
03123 }
03124
03125
03126
03127 m_wghta = 0.2f;
03128 m_wghtb = 0.004f;
03129
03130 m_symmetry = symmetry;
03131 m_npad = npad;
03132 m_sign = sign;
03133 m_nsym = Transform::get_nsym(m_symmetry);
03134
03135 m_snr = snr;
03136
03137 m_vnx = size;
03138 m_vny = size;
03139 m_vnz = size;
03140
03141 m_vnxp = size*npad;
03142 m_vnyp = size*npad;
03143 m_vnzp = size*npad;
03144
03145 m_vnxc = m_vnxp/2;
03146 m_vnyc = m_vnyp/2;
03147 m_vnzc = m_vnzp/2;
03148
03149 buildFFTVolume();
03150 buildNormVolume();
03151 }
03152
03153 void nn4_ctfReconstructor::buildFFTVolume() {
03154 int offset = 2 - m_vnxp%2;
03155 if( params.has_key("fftvol") ) {
03156 m_volume = params["fftvol"];
03157 m_delete_volume = false;
03158 } else {
03159 m_volume = new EMData();
03160 m_delete_volume = true;
03161 }
03162
03163 if( m_volume->get_xsize() != m_vnxp+offset && m_volume->get_ysize() != m_vnyp && m_volume->get_zsize() != m_vnzp ) {
03164 m_volume->set_size(m_vnxp+offset,m_vnyp,m_vnzp);
03165 m_volume->to_zero();
03166 }
03167
03168 m_volume->set_nxc(m_vnxp/2);
03169 m_volume->set_complex(true);
03170 m_volume->set_ri(true);
03171 m_volume->set_fftpad(true);
03172 m_volume->set_attr("npad", m_npad);
03173 m_volume->set_array_offsets(0,1,1);
03174 }
03175
03176 void nn4_ctfReconstructor::buildNormVolume()
03177 {
03178 if( params.has_key("weight") ) {
03179 m_wptr = params["weight"];
03180 m_delete_weight = false;
03181 } else {
03182 m_wptr = new EMData();
03183 m_delete_weight = true;
03184 }
03185
03186 if( m_wptr->get_xsize() != m_vnxc+1 && m_wptr->get_ysize() != m_vnyp && m_wptr->get_zsize() != m_vnzp ) {
03187 m_wptr->set_size(m_vnxc+1,m_vnyp,m_vnzp);
03188 m_wptr->to_zero();
03189 }
03190
03191 m_wptr->set_array_offsets(0,1,1);
03192
03193 }
03194
03195 int nn4_ctfReconstructor::insert_slice(const EMData* const slice, const Transform& t, const float weight)
03196 {
03197
03198 if (!slice) {
03199 LOGERR("try to insert NULL slice");
03200 return 1;
03201 }
03202
03203 int buffed = slice->get_attr_default( "buffed", 0 );
03204 if( buffed > 0 ) {
03205 int mult = slice->get_attr_default( "mult", 1 );
03206 insert_buffed_slice( slice, mult );
03207 return 0;
03208 }
03209
03210 int padffted= slice->get_attr_default("padffted", 0);
03211 if( padffted==0 && (slice->get_xsize()!=slice->get_ysize() || slice->get_xsize()!=m_vnx) )
03212 {
03213
03214 LOGERR("Tried to insert a slice that is the wrong size.");
03215 return 1;
03216 }
03217
03218 EMData* padfft = NULL;
03219
03220 if( padffted != 0 ) padfft = new EMData(*slice);
03221 else padfft = padfft_slice( slice, t, m_npad );
03222
03223 int mult= slice->get_attr_default("mult", 1);
03224
03225 Assert( mult > 0 );
03226 insert_padfft_slice( padfft, t, mult );
03227
03228 checked_delete( padfft );
03229
03230 return 0;
03231 }
03232
03233 int nn4_ctfReconstructor::insert_buffed_slice( const EMData* buffed, int mult )
03234 {
03235 const float* bufdata = buffed->get_data();
03236 float* cdata = m_volume->get_data();
03237 float* wdata = m_wptr->get_data();
03238
03239 int npoint = buffed->get_xsize()/4;
03240 for( int i=0; i < npoint; ++i ) {
03241
03242 int pos2 = int( bufdata[4*i] );
03243 int pos1 = pos2 * 2;
03244 cdata[pos1 ] += bufdata[4*i+1]*mult;
03245 cdata[pos1+1] += bufdata[4*i+2]*mult;
03246 wdata[pos2 ] += bufdata[4*i+3]*mult;
03247
03248
03249
03250
03251
03252 }
03253 return 0;
03254 }
03255
03256 int nn4_ctfReconstructor::insert_padfft_slice( EMData* padfft, const Transform& t, int mult )
03257 {
03258 Assert( padfft != NULL );
03259 float tmp = padfft->get_attr("ctf_applied");
03260 int ctf_applied = (int) tmp;
03261
03262 for( int isym=0; isym < m_nsym; isym++) {
03263 Transform tsym = t.get_sym( m_symmetry, isym );
03264
03265 if(ctf_applied) m_volume->nn_ctf_applied(m_wptr, padfft, tsym, mult);
03266
03267 else m_volume->nn_ctf(m_wptr, padfft, tsym, mult);
03268 }
03269
03270 return 0;
03271
03272 }
03273
03274 #define tw(i,j,k) tw[ i-1 + (j-1+(k-1)*iy)*ix ]
03275 EMData* nn4_ctfReconstructor::finish(bool doift)
03276 {
03277 m_volume->set_array_offsets(0, 1, 1);
03278 m_wptr->set_array_offsets(0, 1, 1);
03279 m_volume->symplane0_ctf(m_wptr);
03280
03281 int box = 7;
03282 int vol = box*box*box;
03283 int kc = (box-1)/2;
03284 vector< float > pow_a( 3*kc+1, 1.0 );
03285 for( unsigned int i=1; i < pow_a.size(); ++i ) pow_a[i] = pow_a[i-1] * exp(m_wghta);
03286 pow_a[3*kc]=0.0;
03287
03288
03289 float max = max3d( kc, pow_a );
03290 float alpha = ( 1.0f - 1.0f/(float)vol ) / max;
03291 float osnr = 1.0f/m_snr;
03292
03293
03294 int ix,iy,iz;
03295 for (iz = 1; iz <= m_vnzp; iz++) {
03296 for (iy = 1; iy <= m_vnyp; iy++) {
03297 for (ix = 0; ix <= m_vnxc; ix++) {
03298 if ( (*m_wptr)(ix,iy,iz) > 0.0f) {
03299 int iyp = (iy<=m_vnyc) ? iy - 1 : iy-m_vnyp-1;
03300 int izp = (iz<=m_vnzc) ? iz - 1 : iz-m_vnzp-1;
03301 float tmp=0.0;
03302 if( m_varsnr )
03303 {
03304 float freq = sqrt( (float)(ix*ix+iyp*iyp+izp*izp) );
03305 tmp = (-2*((ix+iy+iz)%2)+1)/((*m_wptr)(ix,iy,iz)+freq*osnr)*m_sign;
03306 }
03307 else
03308 {
03309 tmp = (-2*((ix+iy+iz)%2)+1)/((*m_wptr)(ix,iy,iz)+osnr)*m_sign;
03310 }
03311
03312 if( m_weighting == ESTIMATE ) {
03313 int cx = ix;
03314 int cy = (iy<=m_vnyc) ? iy - 1 : iy - 1 - m_vnyp;
03315 int cz = (iz<=m_vnzc) ? iz - 1 : iz - 1 - m_vnzp;
03316 float sum = 0.0;
03317 for( int ii = -kc; ii <= kc; ++ii ) {
03318 int nbrcx = cx + ii;
03319 if( nbrcx >= m_vnxc ) continue;
03320 for( int jj= -kc; jj <= kc; ++jj ) {
03321 int nbrcy = cy + jj;
03322 if( nbrcy <= -m_vnyc || nbrcy >= m_vnyc ) continue;
03323 for( int kk = -kc; kk <= kc; ++kk ) {
03324 int nbrcz = cz + jj;
03325 if( nbrcz <= -m_vnyc || nbrcz >= m_vnyc ) continue;
03326 if( nbrcx < 0 ) {
03327 nbrcx = -nbrcx;
03328 nbrcy = -nbrcy;
03329 nbrcz = -nbrcz;
03330 }
03331
03332 int nbrix = nbrcx;
03333 int nbriy = nbrcy >= 0 ? nbrcy + 1 : nbrcy + 1 + m_vnyp;
03334 int nbriz = nbrcz >= 0 ? nbrcz + 1 : nbrcz + 1 + m_vnzp;
03335 if( (*m_wptr)( nbrix, nbriy, nbriz ) == 0.0 ) {
03336 int c = 3*kc+1 - std::abs(ii) - std::abs(jj) - std::abs(kk);
03337 sum = sum + pow_a[c];
03338
03339
03340 }
03341 }
03342 }
03343 }
03344 float wght = 1.0f / ( 1.0f - alpha * sum );
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354 tmp = tmp * wght;
03355 }
03356 (*m_volume)(2*ix,iy,iz) *= tmp;
03357 (*m_volume)(2*ix+1,iy,iz) *= tmp;
03358 }
03359 }
03360 }
03361 }
03362
03363
03364 m_volume->do_ift_inplace();
03365 int npad = m_volume->get_attr("npad");
03366 m_volume->depad();
03367 circumf( m_volume, npad );
03368 m_volume->set_array_offsets( 0, 0, 0 );
03369 m_result = m_volume->copy();
03370 return m_result;
03371 }
03372 #undef tw
03373
03374
03375
03376
03377
03378
03379 nn4_ctf_rectReconstructor::nn4_ctf_rectReconstructor()
03380 {
03381 m_volume = NULL;
03382 m_wptr = NULL;
03383 m_result = NULL;
03384 }
03385
03386 nn4_ctf_rectReconstructor::nn4_ctf_rectReconstructor( const string& symmetry, int size, int npad, float snr, int sign )
03387 {
03388 setup( symmetry, size, npad, snr, sign );
03389 }
03390
03391 nn4_ctf_rectReconstructor::~nn4_ctf_rectReconstructor()
03392 {
03393 if( m_delete_volume ) checked_delete(m_volume);
03394
03395 if( m_delete_weight ) checked_delete( m_wptr );
03396
03397 checked_delete( m_result );
03398 }
03399
03400 void nn4_ctf_rectReconstructor::setup()
03401 {
03402 if( ! params.has_key("sizeprojection") ) throw std::logic_error("Error: projection size is not given");
03403 m_sizeofprojection = params["sizeprojection"];
03404 int npad = params.has_key("npad") ? int(params["npad"]) : 4;
03405
03406 int sign = 1;
03407 string symmetry = params.has_key("symmetry")? params["symmetry"].to_str() : "c1";
03408
03409 float snr = params["snr"];
03410
03411 m_varsnr = params.has_key("varsnr") ? int(params["varsnr"]) : 0;
03412 setup( symmetry, m_sizeofprojection, npad, snr, sign );
03413
03414 }
03415
03416 void nn4_ctf_rectReconstructor::setup( const string& symmetry, int sizeprojection, int npad, float snr, int sign )
03417 {
03418 m_weighting = ESTIMATE;
03419 if( params.has_key("weighting") ) {
03420 int tmp = int( params["weighting"] );
03421 if( tmp==0 ) m_weighting = NONE;
03422 }
03423
03424
03425
03426 m_wghta = 0.2f;
03427 m_wghtb = 0.004f;
03428
03429 m_symmetry = symmetry;
03430 m_npad = npad;
03431 m_sign = sign;
03432 m_nsym = Transform::get_nsym(m_symmetry);
03433
03434 m_snr = snr;
03435 if( params.has_key("sizex") ) m_vnx = params["sizex"];
03436 else if(params.has_key("xratio"))
03437 {
03438 float temp=params["xratio"];
03439 m_vnx=int(float(sizeprojection)*temp);
03440 }
03441 else m_vnx=sizeprojection;
03442
03443 if( params.has_key("sizey") ) m_vny = params["sizey"];
03444 else if (params.has_key("yratio"))
03445 {
03446 float temp=params["yratio"];
03447 m_vny=int(float(sizeprojection)*temp);
03448 }
03449 else m_vny=sizeprojection;
03450
03451 if( params.has_key("sizez") )
03452 m_vnz = params["sizez"];
03453 else
03454 m_vnz =sizeprojection;
03455
03456 m_xratio=float(m_vnx)/float(sizeprojection);
03457 m_yratio=float(m_vny)/float(sizeprojection);
03458
03459
03460
03461
03462 m_vnxp = m_vnx*npad;
03463 m_vnyp = m_vny*npad;
03464 m_vnzp = m_vnz*npad;
03465
03466 m_vnxc = m_vnxp/2;
03467 m_vnyc = m_vnyp/2;
03468 m_vnzc = m_vnzp/2;
03469
03470 buildFFTVolume();
03471 buildNormVolume();
03472 }
03473
03474 void nn4_ctf_rectReconstructor::buildFFTVolume() {
03475 int offset = 2 - m_vnxp%2;
03476 if( params.has_key("fftvol") ) {
03477 m_volume = params["fftvol"];
03478 m_delete_volume = false;
03479 } else {
03480 m_volume = new EMData();
03481 m_delete_volume = true;
03482 }
03483
03484 if( m_volume->get_xsize() != m_vnxp+offset && m_volume->get_ysize() != m_vnyp && m_volume->get_zsize() != m_vnzp ) {
03485 m_volume->set_size(m_vnxp+offset,m_vnyp,m_vnzp);
03486 m_volume->to_zero();
03487 }
03488
03489 m_volume->set_nxc(m_vnxp/2);
03490 m_volume->set_complex(true);
03491 m_volume->set_ri(true);
03492 m_volume->set_fftpad(true);
03493 m_volume->set_attr("npad", m_npad);
03494 m_volume->set_array_offsets(0,1,1);
03495 }
03496
03497 void nn4_ctf_rectReconstructor::buildNormVolume()
03498 {
03499 if( params.has_key("weight") ) {
03500 m_wptr = params["weight"];
03501 m_delete_weight = false;
03502 } else {
03503 m_wptr = new EMData();
03504 m_delete_weight = true;
03505 }
03506
03507 if( m_wptr->get_xsize() != m_vnxc+1 && m_wptr->get_ysize() != m_vnyp && m_wptr->get_zsize() != m_vnzp ) {
03508 m_wptr->set_size(m_vnxc+1,m_vnyp,m_vnzp);
03509 m_wptr->to_zero();
03510 }
03511
03512 m_wptr->set_array_offsets(0,1,1);
03513
03514 }
03515
03516 int nn4_ctf_rectReconstructor::insert_slice(const EMData* const slice, const Transform& t, const float weight)
03517 {
03518
03519 if (!slice) {
03520 LOGERR("try to insert NULL slice");
03521 return 1;
03522 }
03523
03524 int buffed = slice->get_attr_default( "buffed", 0 );
03525 if( buffed > 0 ) {
03526 int mult = slice->get_attr_default( "mult", 1 );
03527 insert_buffed_slice( slice, mult );
03528 return 0;
03529 }
03530
03531 int padffted= slice->get_attr_default("padffted", 0);
03532
03533 if( padffted==0 && (slice->get_xsize()!=slice->get_ysize()) )
03534 {
03535
03536 LOGERR("Tried to insert a slice that is the wrong size.");
03537 return 1;
03538 }
03539
03540 EMData* padfft = NULL;
03541
03542 if( padffted != 0 ) padfft = new EMData(*slice);
03543 else padfft = padfft_slice( slice, t, m_npad );
03544
03545 int mult= slice->get_attr_default("mult", 1);
03546
03547 Assert( mult > 0 );
03548 insert_padfft_slice( padfft, t, mult );
03549
03550 checked_delete( padfft );
03551
03552 return 0;
03553 }
03554
03555 int nn4_ctf_rectReconstructor::insert_buffed_slice( const EMData* buffed, int mult )
03556 {
03557 const float* bufdata = buffed->get_data();
03558 float* cdata = m_volume->get_data();
03559 float* wdata = m_wptr->get_data();
03560
03561 int npoint = buffed->get_xsize()/4;
03562 for( int i=0; i < npoint; ++i ) {
03563
03564 int pos2 = int( bufdata[4*i] );
03565 int pos1 = pos2 * 2;
03566 cdata[pos1 ] += bufdata[4*i+1]*mult;
03567 cdata[pos1+1] += bufdata[4*i+2]*mult;
03568 wdata[pos2 ] += bufdata[4*i+3]*mult;
03569
03570
03571
03572
03573
03574 }
03575 return 0;
03576 }
03577
03578
03579 int nn4_ctf_rectReconstructor::insert_padfft_slice( EMData* padfft, const Transform& t, int mult )
03580 {
03581 Assert( padfft != NULL );
03582 float tmp = padfft->get_attr("ctf_applied");
03583 int ctf_applied = (int) tmp;
03584
03585 if (ctf_applied) m_volume->insert_rect_slice_ctf_applied(m_wptr, padfft, t, m_sizeofprojection, m_xratio,m_yratio, m_npad, mult);
03586 else m_volume->insert_rect_slice_ctf(m_wptr, padfft, t, m_sizeofprojection, m_xratio, m_yratio, m_npad, mult);
03587
03588
03589
03590 return 0;
03591
03592 }
03593
03594 #define tw(i,j,k) tw[ i-1 + (j-1+(k-1)*iy)*ix ]
03595 EMData* nn4_ctf_rectReconstructor::finish(bool doift)
03596 {
03597 m_volume->set_array_offsets(0, 1, 1);
03598 m_wptr->set_array_offsets(0, 1, 1);
03599 m_volume->symplane0_rect(m_wptr);
03600
03601 int box = 7;
03602 int vol = box*box*box;
03603 int kc = (box-1)/2;
03604 vector< float > pow_a( 3*kc+1, 1.0 );
03605 for( unsigned int i=1; i < pow_a.size(); ++i ) pow_a[i] = pow_a[i-1] * exp(m_wghta);
03606 pow_a[3*kc]=0.0;
03607
03608
03609 float max = max3d( kc, pow_a );
03610 float alpha = ( 1.0f - 1.0f/(float)vol ) / max;
03611 float osnr = 1.0f/m_snr;
03612
03613
03614 int ix,iy,iz;
03615 for (iz = 1; iz <= m_vnzp; iz++) {
03616 for (iy = 1; iy <= m_vnyp; iy++) {
03617 for (ix = 0; ix <= m_vnxc; ix++) {
03618 if ( (*m_wptr)(ix,iy,iz) > 0.0f) {
03619 int iyp = (iy<=m_vnyc) ? iy - 1 : iy-m_vnyp-1;
03620 int izp = (iz<=m_vnzc) ? iz - 1 : iz-m_vnzp-1;
03621 float tmp=0.0;
03622 if( m_varsnr )
03623 {
03624 float freq = sqrt( (float)(ix*ix/(m_xratio*m_xratio)+iyp*iyp/(m_zratio*m_yratio)+izp*izp) );
03625 tmp = (-2*((ix+iy+iz)%2)+1)/((*m_wptr)(ix,iy,iz)+freq*osnr)*m_sign;
03626 }
03627 else
03628 {
03629 tmp = (-2*((ix+iy+iz)%2)+1)/((*m_wptr)(ix,iy,iz)+osnr)*m_sign;
03630 }
03631
03632 if( m_weighting == ESTIMATE ) {
03633 int cx = ix;
03634 int cy = (iy<=m_vnyc) ? iy - 1 : iy - 1 - m_vnyp;
03635 int cz = (iz<=m_vnzc) ? iz - 1 : iz - 1 - m_vnzp;
03636 float sum = 0.0;
03637 for( int ii = -kc; ii <= kc; ++ii ) {
03638 int nbrcx = cx + ii;
03639 if( nbrcx >= m_vnxc ) continue;
03640 for( int jj= -kc; jj <= kc; ++jj ) {
03641 int nbrcy = cy + jj;
03642 if( nbrcy <= -m_vnyc || nbrcy >= m_vnyc ) continue;
03643 for( int kk = -kc; kk <= kc; ++kk ) {
03644 int nbrcz = cz + jj;
03645 if( nbrcz <= -m_vnyc || nbrcz >= m_vnyc ) continue;
03646 if( nbrcx < 0 ) {
03647 nbrcx = -nbrcx;
03648 nbrcy = -nbrcy;
03649 nbrcz = -nbrcz;
03650 }
03651
03652 int nbrix = nbrcx;
03653 int nbriy = nbrcy >= 0 ? nbrcy + 1 : nbrcy + 1 + m_vnyp;
03654 int nbriz = nbrcz >= 0 ? nbrcz + 1 : nbrcz + 1 + m_vnzp;
03655 if( (*m_wptr)( nbrix, nbriy, nbriz ) == 0.0 ) {
03656 int c = 3*kc+1 - std::abs(ii) - std::abs(jj) - std::abs(kk);
03657 sum = sum + pow_a[c];
03658
03659
03660 }
03661 }
03662 }
03663 }
03664 float wght = 1.0f / ( 1.0f - alpha * sum );
03665
03666
03667
03668
03669
03670
03671
03672
03673
03674 tmp = tmp * wght;
03675 }
03676 (*m_volume)(2*ix,iy,iz) *= tmp;
03677 (*m_volume)(2*ix+1,iy,iz) *= tmp;
03678 }
03679 }
03680 }
03681 }
03682
03683
03684 m_volume->do_ift_inplace();
03685 int npad = m_volume->get_attr("npad");
03686 m_volume->depad();
03687 circumf_rect( m_volume, npad );
03688 m_volume->set_array_offsets( 0, 0, 0 );
03689 m_result = m_volume->copy();
03690 return m_result;
03691 }
03692 #undef tw
03693
03694
03695
03696
03697
03698
03699
03700 nnSSNR_ctfReconstructor::nnSSNR_ctfReconstructor()
03701 {
03702 m_volume = NULL;
03703 m_wptr = NULL;
03704 m_wptr2 = NULL;
03705 m_wptr3 = NULL;
03706 m_result = NULL;
03707 }
03708
03709 nnSSNR_ctfReconstructor::nnSSNR_ctfReconstructor( const string& symmetry, int size, int npad, float snr, int sign)
03710 {
03711 m_volume = NULL;
03712 m_wptr = NULL;
03713 m_wptr2 = NULL;
03714 m_wptr3 = NULL;
03715 m_result = NULL;
03716
03717 setup( symmetry, size, npad, snr, sign );
03718 }
03719
03720 nnSSNR_ctfReconstructor::~nnSSNR_ctfReconstructor()
03721 {
03722
03723 if( m_delete_volume ) checked_delete(m_volume);
03724 if( m_delete_weight ) checked_delete( m_wptr );
03725 if( m_delete_weight2 ) checked_delete( m_wptr2 );
03726 if( m_delete_weight3 ) checked_delete( m_wptr3 );
03727 checked_delete( m_result );
03728 }
03729
03730 void nnSSNR_ctfReconstructor::setup()
03731 {
03732 int size = params["size"];
03733 int npad = params["npad"];
03734 int sign = params["sign"];
03735 float snr = params["snr"];
03736 string symmetry;
03737 if( params.has_key("symmetry") ) symmetry = params["symmetry"].to_str();
03738 else symmetry = "c1";
03739
03740 setup( symmetry, size, npad, snr, sign );
03741 }
03742 void nnSSNR_ctfReconstructor::setup( const string& symmetry, int size, int npad, float snr, int sign )
03743 {
03744
03745 m_weighting = ESTIMATE;
03746 m_wghta = 0.2f;
03747 m_wghtb = 0.004f;
03748 wiener = 1;
03749
03750 m_symmetry = symmetry;
03751 m_npad = npad;
03752 m_nsym = Transform::get_nsym(m_symmetry);
03753
03754 m_sign = sign;
03755 m_snr = snr;
03756
03757 m_vnx = size;
03758 m_vny = size;
03759 m_vnz = size;
03760
03761 m_vnxp = size*npad;
03762 m_vnyp = size*npad;
03763 m_vnzp = size*npad;
03764
03765 m_vnxc = m_vnxp/2;
03766 m_vnyc = m_vnyp/2;
03767 m_vnzc = m_vnzp/2;
03768
03769 buildFFTVolume();
03770 buildNormVolume();
03771 buildNorm2Volume();
03772 buildNorm3Volume();
03773 }
03774
03775 void nnSSNR_ctfReconstructor::buildFFTVolume() {
03776
03777 int offset = 2 - m_vnxp%2;
03778 if( params.has_key("fftvol") ) {
03779 m_volume = params["fftvol"];
03780 m_delete_volume = false;
03781 } else {
03782 m_volume = new EMData();
03783 m_delete_volume = true;
03784 }
03785
03786 m_volume->set_size(m_vnxp+offset,m_vnyp,m_vnzp);
03787 m_volume->to_zero();
03788
03789 m_volume->set_fftodd(m_vnxp % 2);
03790
03791 m_volume->set_nxc(m_vnxc);
03792 m_volume->set_complex(true);
03793 m_volume->set_ri(true);
03794 m_volume->set_fftpad(true);
03795 m_volume->set_attr("npad", m_npad);
03796 m_volume->set_array_offsets(0,1,1);
03797 }
03798
03799
03800 void nnSSNR_ctfReconstructor::buildNormVolume()
03801 {
03802 if( params.has_key("weight") ) {
03803 m_wptr = params["weight"];
03804 m_delete_weight = false;
03805 } else {
03806 m_wptr = new EMData();
03807 m_delete_weight = true;
03808 }
03809 m_wptr->set_size(m_vnxc+1,m_vnyp,m_vnzp);
03810 m_wptr->to_zero();
03811 m_wptr->set_array_offsets(0,1,1);
03812 }
03813
03814 void nnSSNR_ctfReconstructor::buildNorm2Volume() {
03815
03816 if( params.has_key("weight2") ) {
03817 m_wptr2 = params["weight2"];
03818 m_delete_weight2 = false;
03819 } else {
03820 m_wptr2 = new EMData();
03821 m_delete_weight2 = true;
03822 }
03823 m_wptr2->set_size(m_vnxc+1,m_vnyp,m_vnzp);
03824 m_wptr2->to_zero();
03825 m_wptr2->set_array_offsets(0,1,1);
03826 }
03827
03828 void nnSSNR_ctfReconstructor::buildNorm3Volume() {
03829
03830 if( params.has_key("weight3") ) {
03831 m_wptr3 = params["weight3"];
03832 m_delete_weight3 = false;
03833 } else {
03834 m_wptr3 = new EMData();
03835 m_delete_weight3 = true;
03836 }
03837 m_wptr3->set_size(m_vnxc+1,m_vnyp,m_vnzp);
03838 m_wptr3->to_zero();
03839 m_wptr3->set_array_offsets(0,1,1);
03840 }
03841
03842 int nnSSNR_ctfReconstructor::insert_slice(const EMData *const slice, const Transform& t, const float weight) {
03843
03844 if (!slice) {
03845 LOGERR("try to insert NULL slice");
03846 return 1;
03847 }
03848 int padffted= slice->get_attr_default("padffted", 0);
03849 if ( padffted==0 && (slice->get_xsize()!=slice->get_ysize() || slice->get_xsize()!=m_vnx) ) {
03850
03851 LOGERR("Tried to insert a slice that is the wrong size.");
03852 return 1;
03853 }
03854 EMData* padfft = NULL;
03855
03856 if( padffted != 0 ) padfft = new EMData(*slice);
03857 else padfft = padfft_slice( slice, t, m_npad );
03858
03859 int mult= slice->get_attr_default("mult", 1);
03860
03861 Assert( mult > 0 );
03862 insert_padfft_slice( padfft, t, mult );
03863
03864 checked_delete( padfft );
03865 return 0;
03866 }
03867 int nnSSNR_ctfReconstructor::insert_padfft_slice( EMData* padfft, const Transform& t, int mult )
03868 {
03869 Assert( padfft != NULL );
03870
03871
03872 for (int isym=0; isym < m_nsym; isym++) {
03873 Transform tsym = t.get_sym(m_symmetry, isym);
03874 m_volume->nn_SSNR_ctf(m_wptr, m_wptr2, m_wptr3, padfft, tsym, mult);
03875 }
03876
03877 return 0;
03878 }
03879
03880 #define tw(i,j,k) tw[ i-1 + (j-1+(k-1)*iy)*ix ]
03881 EMData* nnSSNR_ctfReconstructor::finish(bool doift)
03882 {
03883
03884
03885
03886
03887
03888
03889
03890
03891
03892
03893
03894
03895
03896
03897 int kz, ky;
03898 int box = 7;
03899 int kc = (box-1)/2;
03900 float alpha = 0.0;
03901 float argx, argy, argz;
03902 vector< float > pow_a( 3*kc+1, 1.0 );
03903 float w = params["w"];
03904 float dx2 = 1.0f/float(m_vnxc)/float(m_vnxc);
03905 float dy2 = 1.0f/float(m_vnyc)/float(m_vnyc);
03906 #ifdef _WIN32
03907 float dz2 = 1.0f/_cpp_max(float(m_vnzc),1.0f)/_cpp_max(float(m_vnzc),1.0f);
03908 int inc = Util::round(float(_cpp_max(_cpp_max(m_vnxc,m_vnyc),m_vnzc))/w);
03909 #else
03910 float dz2 = 1.0f/std::max(float(m_vnzc),1.0f)/std::max(float(m_vnzc),1.0f);
03911 int inc = Util::round(float(std::max(std::max(m_vnxc,m_vnyc),m_vnzc))/w);
03912 #endif //_WIN32
03913
03914 EMData* SSNR = params["SSNR"];
03915 SSNR->set_size(inc+1,4,1);
03916
03917
03918
03919
03920 EMData* vol_ssnr = new EMData();
03921 vol_ssnr->set_size(m_vnxp+ 2 - m_vnxp%2, m_vnyp ,m_vnzp);
03922 vol_ssnr->to_zero();
03923 if ( m_vnxp % 2 == 0 ) vol_ssnr->set_fftodd(0);
03924 else vol_ssnr->set_fftodd(1);
03925 vol_ssnr->set_nxc(m_vnxc);
03926 vol_ssnr->set_complex(true);
03927 vol_ssnr->set_ri(true);
03928 vol_ssnr->set_fftpad(false);
03929
03930 float *nom = new float[inc+1];
03931 float *denom = new float[inc+1];
03932 int *ka = new int[inc+1];
03933 int *nn = new int[inc+1];
03934 float wght = 1.f;
03935 for (int i = 0; i <= inc; i++) {
03936 nom[i] = 0.0f;
03937 denom[i] = 0.0f;
03938 nn[i] = 0;
03939 ka[i] = 0;
03940 }
03941 m_volume->symplane2(m_wptr, m_wptr2, m_wptr3);
03942 if ( m_weighting == ESTIMATE ) {
03943 int vol = box*box*box;
03944 for( unsigned int i=1; i < pow_a.size(); ++i ) pow_a[i] = pow_a[i-1] * exp(m_wghta);
03945 pow_a[3*kc] = 0.0;
03946 float max = max3d( kc, pow_a );
03947 alpha = ( 1.0f - 1.0f/(float)vol ) / max;
03948 }
03949 for (int iz = 1; iz <= m_vnzp; iz++) {
03950 if ( iz-1 > m_vnzc ) kz = iz-1-m_vnzp; else kz = iz-1;
03951 argz = float(kz*kz)*dz2;
03952 for (int iy = 1; iy <= m_vnyp; iy++) {
03953 if ( iy-1 > m_vnyc ) ky = iy-1-m_vnyp; else ky = iy-1;
03954 argy = argz + float(ky*ky)*dy2;
03955 for (int ix = 0; ix <= m_vnxc; ix++) {
03956 float Kn = (*m_wptr3)(ix,iy,iz);
03957 argx = std::sqrt(argy + float(ix*ix)*dx2);
03958 int r = Util::round(float(inc)*argx);
03959 if ( r >= 0 && Kn > 4.5f ) {
03960 if ( m_weighting == ESTIMATE ) {
03961 int cx = ix;
03962 int cy = (iy<=m_vnyc) ? iy - 1 : iy - 1 - m_vnyp;
03963 int cz = (iz<=m_vnzc) ? iz - 1 : iz - 1 - m_vnzp;
03964 float sum = 0.0;
03965 for( int ii = -kc; ii <= kc; ++ii ) {
03966 int nbrcx = cx + ii;
03967 if( nbrcx >= m_vnxc ) continue;
03968 for ( int jj= -kc; jj <= kc; ++jj ) {
03969 int nbrcy = cy + jj;
03970 if( nbrcy <= -m_vnyc || nbrcy >= m_vnyc ) continue;
03971 for( int kk = -kc; kk <= kc; ++kk ) {
03972 int nbrcz = cz + jj;
03973 if ( nbrcz <= -m_vnyc || nbrcz >= m_vnyc ) continue;
03974 if( nbrcx < 0 ) {
03975 nbrcx = -nbrcx;
03976 nbrcy = -nbrcy;
03977 nbrcz = -nbrcz;
03978 }
03979 int nbrix = nbrcx;
03980 int nbriy = nbrcy >= 0 ? nbrcy + 1 : nbrcy + 1 + m_vnyp;
03981 int nbriz = nbrcz >= 0 ? nbrcz + 1 : nbrcz + 1 + m_vnzp;
03982 if( (*m_wptr)( nbrix, nbriy, nbriz ) == 0 ) {
03983 int c = 3*kc+1 - std::abs(ii) - std::abs(jj) - std::abs(kk);
03984 sum = sum + pow_a[c];
03985 }
03986 }
03987 }
03988 }
03989
03990 wght = 1.0f / ( 1.0f - alpha * sum );
03991 }
03992 float nominator = std::norm(m_volume->cmplx(ix,iy,iz))/(*m_wptr)(ix,iy,iz);
03993 float denominator = ((*m_wptr2)(ix,iy,iz)-std::norm(m_volume->cmplx(ix,iy,iz))/(*m_wptr)(ix,iy,iz))/(Kn-1.0f);
03994
03995 if( (ix>0 || (kz>=0 && (ky>=0 || kz!=0)))) {
03996 if ( r <= inc ) {
03997 nom[r] += nominator*wght;
03998 denom[r] += denominator/(*m_wptr)(ix,iy,iz)*wght;
03999 nn[r] += 2;
04000 ka[r] += int(Kn);
04001 }
04002
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017 }
04018 (*vol_ssnr)(2*ix, iy-1, iz-1) = denominator*wght;
04019 }
04020 }
04021 }
04022 }
04023 for (int i = 0; i <= inc; i++) {
04024 (*SSNR)(i,0,0) = nom[i];
04025 (*SSNR)(i,1,0) = denom[i];
04026 (*SSNR)(i,2,0) = static_cast<float>(nn[i]);
04027 (*SSNR)(i,3,0) = static_cast<float>(ka[i]);
04028 }
04029 vol_ssnr->update();
04030 return vol_ssnr;
04031
04032 }
04033 #undef tw
04034
04035
04036
04037
04038 void EMAN::dump_reconstructors()
04039 {
04040 dump_factory < Reconstructor > ();
04041 }
04042
04043 map<string, vector<string> > EMAN::dump_reconstructors_list()
04044 {
04045 return dump_factory_list < Reconstructor > ();
04046 }
04047
04048
04049
04050
04051
04052 using std::ofstream;
04053 using std::ifstream;
04054
04055
04056 newfile_store::newfile_store( const string& filename, int npad, bool ctf )
04057 : m_bin_file( filename + ".bin" ),
04058 m_txt_file( filename + ".txt" )
04059 {
04060 m_npad = npad;
04061 m_ctf = ctf;
04062 }
04063
04064 newfile_store::~newfile_store( )
04065 {
04066 }
04067
04068 void newfile_store::add_image( EMData* emdata, const Transform& tf )
04069 {
04070 if( m_bin_of == NULL ) {
04071 m_bin_of = shared_ptr<ofstream>( new ofstream(m_bin_file.c_str(), std::ios::out|std::ios::binary) );
04072 m_txt_of = shared_ptr<ofstream>( new ofstream(m_txt_file.c_str()) );
04073 }
04074
04075
04076 EMData* padfft = padfft_slice( emdata, tf, m_npad );
04077
04078 int nx = padfft->get_xsize();
04079 int ny = padfft->get_ysize();
04080 int n2 = ny / 2;
04081 int n = ny;
04082
04083 float voltage=0.0f, pixel=0.0f, Cs=0.0f, ampcont=0.0f, bfactor=0.0f, defocus=0.0f;
04084
04085 if( m_ctf ) {
04086 Ctf* ctf = emdata->get_attr( "ctf" );
04087 Dict params = ctf->to_dict();
04088 voltage = params["voltage"];
04089 pixel = params["apix"];
04090 Cs = params["cs"];
04091 ampcont = params["ampcont"];
04092 bfactor = params["bfactor"];
04093 defocus = params["defocus"];
04094 if(ctf) {delete ctf; ctf=0;}
04095 }
04096
04097 vector<point_t> points;
04098 for( int j=-ny/2+1; j <= ny/2; j++ ) {
04099 int jp = (j>=0) ? j+1 : ny+j+1;
04100 for( int i=0; i <= n2; ++i ) {
04101 int r2 = i*i + j*j;
04102 if( (r2<ny*ny/4) && !( (i==0) && (j<0) ) ) {
04103 float ctf;
04104 if( m_ctf ) {
04105 float ak = std::sqrt( r2/float(ny*ny) )/pixel;
04106 ctf = Util::tf( defocus, ak, voltage, Cs, ampcont, bfactor, 1);
04107 } else {
04108 ctf = 1.0;
04109 }
04110
04111 float xnew = i*tf[0][0] + j*tf[1][0];
04112 float ynew = i*tf[0][1] + j*tf[1][1];
04113 float znew = i*tf[0][2] + j*tf[1][2];
04114 std::complex<float> btq;
04115 if (xnew < 0.) {
04116 xnew = -xnew;
04117 ynew = -ynew;
04118 znew = -znew;
04119 btq = conj(padfft->cmplx(i,jp-1));
04120 } else {
04121 btq = padfft->cmplx(i,jp-1);
04122 }
04123
04124 int ixn = int(xnew + 0.5 + n) - n;
04125 int iyn = int(ynew + 0.5 + n) - n;
04126 int izn = int(znew + 0.5 + n) - n;
04127 if ((ixn <= n2) && (iyn >= -n2) && (iyn <= n2) && (izn >= -n2) && (izn <= n2)) {
04128 int ixf, iyf, izf;
04129 if (ixn >= 0) {
04130 int iza, iya;
04131 if (izn >= 0)
04132 iza = izn + 1;
04133 else
04134 iza = n + izn + 1;
04135
04136 if (iyn >= 0)
04137 iya = iyn + 1;
04138 else
04139 iya = n + iyn + 1;
04140
04141 ixf = ixn;
04142 iyf = iya;
04143 izf = iza;
04144 } else {
04145 int izt, iyt;
04146 if (izn > 0)
04147 izt = n - izn + 1;
04148 else
04149 izt = -izn + 1;
04150
04151 if (iyn > 0)
04152 iyt = n - iyn + 1;
04153 else
04154 iyt = -iyn + 1;
04155
04156 ixf = -ixn;
04157 iyf = iyt;
04158 izf = izt;
04159 }
04160
04161
04162 int pos2 = ixf + (iyf-1)*nx/2 + (izf-1)*ny*nx/2;
04163 float ctfv1 = btq.real() * ctf;
04164 float ctfv2 = btq.imag() * ctf;
04165 float ctf2 = ctf*ctf;
04166
04167 point_t p;
04168 p.pos2 = pos2;
04169 p.real = ctfv1;
04170 p.imag = ctfv2;
04171 p.ctf2 = ctf2;
04172
04173 points.push_back( p );
04174 }
04175 }
04176 }
04177 }
04178
04179
04180 int npoint = points.size();
04181 std::istream::off_type offset = (m_offsets.size()==0) ? 0 : m_offsets.back();
04182 offset += npoint*sizeof(point_t);
04183 m_offsets.push_back( offset );
04184
04185 *m_txt_of << m_offsets.back() << std::endl;
04186 m_bin_of->write( (char*)(&points[0]), sizeof(point_t)*npoint );
04187 checked_delete( padfft );
04188 }
04189
04190 void newfile_store::get_image( int id, EMData* buf )
04191 {
04192 if( m_offsets.size()==0 ) {
04193 ifstream is( m_txt_file.c_str() );
04194 std::istream::off_type off;
04195 while( is >> off ) {
04196 m_offsets.push_back( off );
04197 }
04198
04199 m_bin_if = shared_ptr<std::ifstream>( new ifstream(m_bin_file.c_str(), std::ios::in|std::ios::binary) );
04200 }
04201
04202 Assert( m_bin_if != NULL );
04203
04204 std::istream::off_type offset = (id==0) ? 0 : m_offsets[id-1];
04205 Assert( offset >= 0 );
04206 m_bin_if->seekg( offset, std::ios::beg );
04207
04208
04209 if( m_bin_if->bad() || m_bin_if->fail() || m_bin_if->eof() ) {
04210 std::cout << "bad or fail or eof while fetching id, offset: " << id << " " << offset << std::endl;
04211 throw std::logic_error( "bad happen" );
04212 }
04213
04214 int bufsize = (m_offsets[id] - offset)/sizeof(float);
04215 if( buf->get_xsize() != bufsize ) {
04216 buf->set_size( bufsize, 1, 1 );
04217 }
04218
04219 char* data = (char*)(buf->get_data());
04220 m_bin_if->read( data, sizeof(float)*bufsize );
04221 buf->update();
04222 }
04223
04224 void newfile_store::read( int nprj )
04225 {
04226 if( m_offsets.size()==0 ) {
04227 ifstream is( m_txt_file.c_str() );
04228 std::istream::off_type off;
04229 while( is >> off ) {
04230 m_offsets.push_back( off );
04231 }
04232 }
04233
04234 if( m_bin_if==NULL ) {
04235 m_bin_if = shared_ptr< ifstream>( new ifstream(m_bin_file.c_str(), std::ios::in|std::ios::binary) );
04236 }
04237
04238
04239 int npoint = m_offsets[0]/sizeof(point_t);
04240 std::ios::off_type prjsize = m_offsets[0];
04241
04242 try {
04243 m_points.resize(nprj * npoint);
04244 }
04245 catch( std::exception& e ) {
04246 std::cout << "Error: " << e.what() << std::endl;
04247 }
04248
04249 int ip = 0;
04250 for( int i=0; i < nprj; ++i ) {
04251 m_bin_if->read( (char*)(&m_points[ip]), prjsize );
04252 if( m_bin_if->bad() || m_bin_if->fail() || m_bin_if->eof() ) {
04253 std::cout << "Error: file hander bad or fail or eof" << std::endl;
04254 return;
04255 }
04256 ip += npoint;
04257 }
04258 }
04259
04260 void newfile_store::add_tovol( EMData* fftvol, EMData* wgtvol, const vector<int>& mults, int pbegin, int pend )
04261 {
04262 float* vdata = fftvol->get_data();
04263 float* wdata = wgtvol->get_data();
04264
04265 int npoint = m_offsets[0]/sizeof(point_t);
04266
04267 Assert( int(m_points.size())== (pend - pbegin)*npoint );
04268
04269 for( int iprj=pbegin; iprj < pend; ++iprj ) {
04270 int m = mults[iprj];
04271 if( m==0 ) continue;
04272
04273 int ipt = (iprj-pbegin)*npoint;
04274 for( int i=0; i < npoint; ++i ) {
04275 int pos2 = m_points[ipt].pos2;
04276 int pos1 = pos2*2;
04277
04278 wdata[pos2] += m_points[ipt].ctf2*m;
04279 vdata[pos1] += m_points[ipt].real*m;
04280 vdata[pos1+1] += m_points[ipt].imag*m;
04281 ++ipt;
04282 }
04283 }
04284 }
04285
04286 void newfile_store::restart()
04287 {
04288 m_bin_if = shared_ptr< ifstream>( new ifstream(m_bin_file.c_str(), std::ios::in|std::ios::binary) );
04289 }
04290
04291 file_store::file_store(const string& filename, int npad, int write, bool ctf)
04292 : m_bin_file(filename + ".bin"),
04293 m_txt_file(filename + ".txt")
04294 {
04295 m_ctf = ctf;
04296 m_prev = -1;
04297 m_npad = npad;
04298 m_write = write;
04299 }
04300
04301 file_store::~file_store()
04302 {
04303 }
04304
04305 void file_store::add_image( EMData* emdata, const Transform& tf )
04306 {
04307
04308 EMData* padfft = padfft_slice( emdata, tf, m_npad );
04309
04310 float* data = padfft->get_data();
04311
04312 if( m_write && m_bin_ohandle == NULL )
04313 {
04314 m_bin_ohandle = shared_ptr< ofstream >( new ofstream(m_bin_file.c_str(), std::ios::out | std::ios::binary) );
04315 m_txt_ohandle = shared_ptr< ofstream >( new ofstream(m_txt_file.c_str() ) );
04316 if( m_ctf )
04317 *m_txt_ohandle << "Cs pixel voltage ctf_applied amp_contrast defocus ";
04318
04319 *m_txt_ohandle << "phi theta psi" << std::endl;
04320 }
04321
04322 m_x_out = padfft->get_xsize();
04323 m_y_out = padfft->get_ysize();
04324 m_z_out = padfft->get_zsize();
04325 m_totsize = m_x_out*m_y_out*m_z_out;
04326
04327 if( m_ctf )
04328 {
04329 Ctf* ctf = padfft->get_attr( "ctf" );
04330 Dict ctf_params = ctf->to_dict();
04331
04332 m_ctf_applied = padfft->get_attr( "ctf_applied" );
04333
04334 m_Cs = ctf_params["cs"];
04335 m_pixel = ctf_params["apix"];
04336 m_voltage = ctf_params["voltage"];
04337 m_amp_contrast = ctf_params["ampcont"];
04338 m_defocuses.push_back( ctf_params["defocus"] );
04339 if(ctf) {delete ctf; ctf=0;}
04340 }
04341
04342 Dict params = tf.get_rotation( "spider" );
04343 float phi = params.get( "phi" );
04344 float tht = params.get( "theta" );
04345 float psi = params.get( "psi" );
04346
04347
04348 m_phis.push_back( phi );
04349 m_thetas.push_back( tht );
04350 m_psis.push_back( psi );
04351
04352 if( m_write )
04353 {
04354 m_bin_ohandle->write( (char*)data, sizeof(float)*m_totsize );
04355
04356 if( m_ctf )
04357 {
04358 *m_txt_ohandle << m_Cs << " ";
04359 *m_txt_ohandle << m_pixel << " ";
04360 *m_txt_ohandle << m_voltage << " ";
04361 *m_txt_ohandle << m_ctf_applied << " ";
04362 *m_txt_ohandle << m_amp_contrast << " ";
04363 *m_txt_ohandle << m_defocuses.back() << " ";
04364 }
04365 *m_txt_ohandle << m_phis.back() << " ";
04366 *m_txt_ohandle << m_thetas.back() << " ";
04367 *m_txt_ohandle << m_psis.back() << " ";
04368 *m_txt_ohandle << m_x_out << " ";
04369 *m_txt_ohandle << m_y_out << " ";
04370 *m_txt_ohandle << m_z_out << " ";
04371 *m_txt_ohandle << m_totsize << std::endl;
04372 }
04373
04374 checked_delete(padfft);
04375
04376 }
04377
04378 void file_store::get_image( int id, EMData* padfft )
04379 {
04380
04381 if( m_phis.size() == 0 ) {
04382 ifstream m_txt_ifs( m_txt_file.c_str() );
04383
04384 if( !m_txt_ifs )
04385 {
04386 std::cerr << "Error: file " << m_txt_file << " does not exist" << std::endl;
04387 }
04388
04389 string line;
04390 std::getline( m_txt_ifs, line );
04391
04392 float first, defocus, phi, theta, psi;
04393
04394
04395
04396 while( m_txt_ifs >> first ) {
04397
04398 if( m_ctf )
04399 {
04400 m_Cs = first;
04401 m_txt_ifs >> m_pixel >> m_voltage;
04402 m_txt_ifs >> m_ctf_applied >> m_amp_contrast;
04403 m_txt_ifs >> defocus >> phi >> theta >> psi;
04404 m_defocuses.push_back( defocus );
04405 }
04406 else
04407 {
04408 phi = first;
04409 m_txt_ifs >> theta >> psi;
04410 }
04411
04412 m_txt_ifs >> m_x_out >> m_y_out >> m_z_out >> m_totsize;
04413 m_phis.push_back( phi );
04414 m_thetas.push_back( theta );
04415 m_psis.push_back( psi );
04416 }
04417 }
04418
04419 Assert( m_ihandle != NULL );
04420
04421 std::istream::off_type offset = id*sizeof(float)*m_totsize;
04422 Assert( offset >= 0 );
04423
04424 if( offset > 0 )
04425 {
04426 m_ihandle->seekg(offset, std::ios::beg);
04427 }
04428
04429 if( m_ihandle->bad() )
04430 {
04431 std::cout << "bad while fetching id, offset: " << id << " " << offset << std::endl;
04432 throw std::logic_error( "bad happen" );
04433 }
04434
04435 if( m_ihandle->fail() )
04436 {
04437 std::cout << "fail while fetching id, offset, curoff: " << id << " " << offset << std::endl;
04438 throw std::logic_error( "fail happen" );
04439 }
04440
04441 if( m_ihandle->eof() )
04442 {
04443 std::cout << "eof while fetching id, offset: " << id << " " << offset << std::endl;
04444 throw std::logic_error( "eof happen" );
04445 }
04446
04447 if( padfft->get_xsize() != m_x_out ||
04448 padfft->get_ysize() != m_y_out ||
04449 padfft->get_zsize() != m_z_out )
04450 {
04451 padfft->set_size(m_x_out, m_y_out, m_z_out);
04452 }
04453
04454 char* data = (char*)(padfft->get_data());
04455 m_ihandle->read( data, sizeof(float)*m_totsize );
04456 padfft->update();
04457
04458 if( m_ctf )
04459 {
04460 padfft->set_attr( "Cs", m_Cs );
04461 padfft->set_attr( "Pixel_size", m_pixel );
04462 padfft->set_attr( "voltage", m_voltage );
04463 padfft->set_attr( "ctf_applied", m_ctf_applied );
04464 padfft->set_attr( "amp_contrast", m_amp_contrast );
04465 padfft->set_attr( "defocus", m_defocuses[id] );
04466 }
04467
04468 padfft->set_attr( "padffted", 1 );
04469 padfft->set_attr( "phi", m_phis[id] );
04470 padfft->set_attr( "theta", m_thetas[id] );
04471 padfft->set_attr( "psi", m_psis[id] );
04472
04473 }
04474
04475 void file_store::restart( )
04476 {
04477 if( m_ihandle == NULL )
04478 {
04479 m_ihandle = shared_ptr< ifstream >( new ifstream(m_bin_file.c_str(), std::ios::in | std::ios::binary) );
04480 }
04481
04482 if( m_ihandle->bad() || m_ihandle->fail() || m_ihandle->eof() )
04483 {
04484 m_ihandle->open( m_bin_file.c_str(), std::ios::binary );
04485 }
04486
04487 m_ihandle->seekg( 0, std::ios::beg );
04488 }
04489
04490