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 "ctf.h"
00038 #include "emassert.h"
00039 #include "symmetry.h"
00040 #include <cstring>
00041 #include <fstream>
00042 #include <iomanip>
00043 #include <boost/bind.hpp>
00044 #include <boost/format.hpp>
00045
00046 #include <gsl/gsl_statistics_double.h>
00047 #include <gsl/gsl_fit.h>
00048
00049 using namespace EMAN;
00050 using std::complex;
00051
00052
00053 #include <iostream>
00054 using std::cerr;
00055 using std::endl;
00056 using std::cout;
00057
00058 #include <algorithm>
00059
00060
00061 #include <iomanip>
00062 using std::setprecision;
00063
00064 template < typename T > void checked_delete( T*& x )
00065 {
00066 typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
00067 (void) sizeof(type_must_be_complete);
00068 delete x;
00069 x = NULL;
00070 }
00071
00072
00073 template <> Factory < Reconstructor >::Factory()
00074 {
00075 force_add(&FourierReconstructor::NEW);
00076 force_add(&FourierReconstructorSimple2D::NEW);
00077 force_add(&BaldwinWoolfordReconstructor::NEW);
00078 force_add(&WienerFourierReconstructor::NEW);
00079 force_add(&BackProjectionReconstructor::NEW);
00080 force_add(&nn4Reconstructor::NEW);
00081 force_add(&nnSSNR_Reconstructor::NEW);
00082 force_add(&nn4_ctfReconstructor::NEW);
00083 force_add(&nnSSNR_ctfReconstructor::NEW);
00084 }
00085
00086 void FourierReconstructorSimple2D::setup()
00087 {
00088 nx = params.set_default("nx",0);
00089
00090 if ( nx < 0 ) throw InvalidValueException(nx, "nx must be positive");
00091
00092 bool is_fftodd = (nx % 2 == 1);
00093
00094 ny = nx;
00095 nx += 2-is_fftodd;
00096
00097 image = new EMData();
00098 image->set_size(nx, ny);
00099 image->set_complex(true);
00100 image->set_fftodd(is_fftodd);
00101 image->set_ri(true);
00102
00103 tmp_data = new EMData();
00104 tmp_data->set_size(nx/2, nx);
00105 }
00106
00107 int FourierReconstructorSimple2D::insert_slice(const EMData* const slice, const Transform & euler)
00108 {
00109
00110
00111 if (!slice) throw NullPointerException("EMData pointer (input image) is NULL");
00112
00113 if ( slice->get_ndim() != 1 ) throw ImageDimensionException("Image dimension must be 1");
00114
00115
00116 if (slice->is_complex()) throw ImageFormatException("The image is complex, expecting real");
00117
00118 EMData* working_slice = slice->process("xform.phaseorigin.tocorner");
00119
00120
00121 working_slice->do_fft_inplace();
00122
00123 float* rdata = image->get_data();
00124 float* norm = tmp_data->get_data();
00125 float* dat = working_slice->get_data();
00126
00127 float g[4];
00128 int offset[4];
00129 float dt[2];
00130 offset[0] = 0; offset[1] = 2; offset[2] = nx; offset[3] = nx+2;
00131
00132 float alt = -((float)(euler.get_rotation("2d"))["alpha"])*M_PI/180.0f;
00133 for (int x = 0; x < working_slice->get_xsize() / 2; x++) {
00134
00135 float rx = (float) x;
00136
00137 float xx = rx*cos(alt);
00138 float yy = rx*sin(alt);
00139 float cc = 1.0;
00140
00141 if (xx < 0) {
00142 xx = -xx;
00143 yy = -yy;
00144 cc = -1.0;
00145 }
00146
00147 yy += ny / 2;
00148
00149
00150 dt[0] = dat[2*x];
00151 dt[1] = cc * dat[2*x+1];
00152
00153
00154 int x0 = (int) floor(xx);
00155 int y0 = (int) floor(yy);
00156
00157 int i = 2*x0 + y0*nx;
00158
00159 float dx = xx - x0;
00160 float dy = yy - y0;
00161
00162 g[0] = Util::agauss(1, dx, dy, 0, EMConsts::I2G);
00163 g[1] = Util::agauss(1, 1 - dx, dy, 0, EMConsts::I2G);
00164 g[2] = Util::agauss(1, dx, 1 - dy, 0, EMConsts::I2G);
00165 g[3] = Util::agauss(1, 1 - dx, 1 - dy, 0, EMConsts::I2G);
00166
00167
00168 if ( x0 == nx-2 ) {
00169 int k = i + offset[0];
00170 rdata[k] += g[0] * dt[0];
00171 rdata[k + 1] += g[0] * dt[1];
00172 norm[k/2] += g[0];
00173
00174 k = i + offset[2];
00175 rdata[k] += g[2] * dt[0];
00176 rdata[k + 1] += g[2] * dt[1];
00177 norm[k/2] += g[2];
00178 continue;
00179
00180 }
00181
00182 if ( x0 > nx-2 ) {
00183 int dif = x0 - (nx-2);
00184 x0 -= dif;
00185 }
00186
00187 if ( y0 == ny -1 ) {
00188 int k = i + offset[0];
00189 rdata[k] += g[0] * dt[0];
00190 rdata[k + 1] += g[0] * dt[1];
00191 norm[k/2] += g[0];
00192
00193 k = i + offset[1];
00194 rdata[k] += g[1] * dt[0];
00195 rdata[k + 1] += g[1] * dt[1];
00196 norm[k/2] += g[1];
00197 continue;
00198 }
00199
00200 if ( y0 > ny-1) {
00201 int dif = y0 - (ny-1);
00202 y0 -= dif;
00203 }
00204
00205 if (x0 >= nx - 2 || y0 >= ny - 1) continue;
00206
00207
00208
00209
00210 for (int j = 0; j < 4; j++)
00211 {
00212 int k = i + offset[j];
00213 rdata[k] += g[j] * dt[0];
00214 rdata[k + 1] += g[j] * dt[1];
00215 norm[k/2] += g[j];
00216
00217 }
00218 }
00219
00220 return 0;
00221
00222 }
00223
00224 EMData *FourierReconstructorSimple2D::finish()
00225 {
00226 normalize_threed();
00227
00228 image->process_inplace("xform.fourierorigin.tocorner");
00229 image->do_ift_inplace();
00230 image->depad();
00231 image->process_inplace("xform.phaseorigin.tocenter");
00232
00233 return image;
00234 }
00235
00236 void ReconstructorVolumeData::normalize_threed()
00237 {
00238 float* norm = tmp_data->get_data();
00239 float* rdata = image->get_data();
00240
00241
00242 if ( 0 == norm ) throw NullPointerException("The normalization volume was null!");
00243 if ( 0 == rdata ) throw NullPointerException("The complex reconstruction volume was null!");
00244
00245 for (int i = 0; i < nx * ny * nz; i += 2) {
00246 float d = norm[i/2];
00247 if (d == 0) {
00248 rdata[i] = 0;
00249 rdata[i + 1] = 0;
00250 }
00251 else {
00252 rdata[i] /= d;
00253 rdata[i + 1] /= d;
00254 }
00255 }
00256 }
00257
00258 void FourierReconstructor::free_memory()
00259 {
00260 if ( inserter != 0 )
00261 {
00262 delete inserter;
00263 inserter = 0;
00264 }
00265 if ( interp_FRC_calculator != 0 )
00266 {
00267 delete interp_FRC_calculator;
00268 interp_FRC_calculator = 0;
00269 }
00270 }
00271
00272 #include <sstream>
00273
00274 void FourierReconstructor::load_inserter()
00275 {
00276
00277
00278 stringstream ss;
00279 ss << (int)params["mode"];
00280 string mode;
00281 ss >> mode;
00282
00283
00284 Dict parms;
00285 parms["rdata"] = image->get_data();
00286 parms["norm"] = tmp_data->get_data();
00287 parms["nx"] = nx;
00288 parms["ny"] = ny;
00289 parms["nz"] = nz;
00290
00291 if ( inserter != 0 )
00292 {
00293 delete inserter;
00294 }
00295
00296 inserter = Factory<FourierPixelInserter3D>::get(mode, parms);
00297 inserter->init();
00298 }
00299
00300
00301
00302 void FourierReconstructor::load_interp_FRC_calculator()
00303 {
00304 Dict init_parms;
00305 init_parms["rdata"] = image->get_data();
00306 init_parms["norm"] = tmp_data->get_data();
00307 init_parms["nx"] = nx;
00308 init_parms["ny"] = ny;
00309 init_parms["nz"] = nz;
00310
00311 if ( x_scale_factor != 0 ) init_parms["x_scale"] = 1.0/x_scale_factor;
00312 if ( y_scale_factor != 0 ) init_parms["y_scale"] = 1.0/y_scale_factor;
00313 if ( z_scale_factor != 0 ) init_parms["z_scale"] = 1.0/z_scale_factor;
00314
00315 if ( interp_FRC_calculator != 0 )
00316 {
00317 delete interp_FRC_calculator;
00318 }
00319
00320 stringstream ss;
00321 ss << (int)params["mode"];
00322 string mode;
00323 ss >> mode;
00324
00325 interp_FRC_calculator = Factory<InterpolatedFRC>::get(mode, init_parms);
00326 }
00327
00328 void FourierReconstructor::setup()
00329 {
00330
00331 params.set_default("mode",2);
00332
00333 int x_size = params["x_in"];
00334 if ( x_size < 0 ) throw InvalidValueException(x_size, "x size of images must be greater than 0");
00335 int y_size = params["y_in"];
00336 if ( y_size < 0 ) throw InvalidValueException(y_size, "y size of images must be greater than 0");
00337
00338 if ( x_size > y_size ) max_input_dim = x_size;
00339 else max_input_dim = y_size;
00340
00341
00342 bool helical_special_behavior = false;
00343 if ( helical_special_behavior )
00344 {
00345 if ( x_size > y_size )
00346 {
00347 if ( (int) params["xsample"] == 0 ) params["xsample"] = y_size;
00348 if ( (int) params["zsample"] == 0 ) params["zsample"] = x_size;
00349 }
00350 if ( y_size > x_size )
00351 {
00352 if ( (int) params["ysample"] == 0 ) params["ysample"] = x_size;
00353 if ( (int) params["zsample"] == 0 ) params["zsample"] = y_size;
00354 }
00355 }
00356
00357 if ( (int) params["xsample"] != 0 ) output_x = (int) params["xsample"];
00358 else output_x = x_size;
00359
00360 if ( (int) params["ysample"] != 0 ) output_y = (int) params["ysample"];
00361 else output_y = y_size;
00362
00363 if ( (int) params["zsample"] != 0 ) output_z = (int) params["zsample"];
00364 else
00365 {
00366 if ( x_size == y_size ) output_z = x_size;
00367 else if ( x_size > y_size ) output_z = x_size;
00368 else output_z = y_size;
00369 }
00370
00371 nx = output_x;
00372 ny = output_y;
00373 nz = output_z;
00374
00375
00376 bool is_fftodd = (nx % 2 == 1);
00377
00378
00379
00380 nx += 2-is_fftodd;
00381
00382 if ( (int) params["zsample"] == 0 ) nz = max_input_dim;
00383
00384 if ( nz < max_input_dim ) z_scale_factor = (float) nz / (float) max_input_dim;
00385 if ( ny < max_input_dim ) y_scale_factor = (float) ny / (float) max_input_dim;
00386 if ( nx < max_input_dim ) x_scale_factor = (float) nx / (float) max_input_dim;
00387
00388
00389 image = new EMData();
00390 image->set_size(nx, ny, nz);
00391 image->set_complex(true);
00392 image->set_fftodd(is_fftodd);
00393 image->set_ri(true);
00394
00395 tmp_data = new EMData();
00396 tmp_data->set_size(nx/2, ny, nz);
00397 tmp_data->to_zero();
00398 tmp_data->update();
00399
00400 load_inserter();
00401 load_interp_FRC_calculator();
00402
00403 if ( (bool) params["quiet"] == false )
00404 {
00405 cout << "3D Fourier dimensions are " << nx << " " << ny << " " << nz << endl;
00406 cout << "You will require approximately " << setprecision(3) << (nx*ny*nz*sizeof(float)*1.5)/1000000000.0 << "GB of memory to reconstruct this volume" << endl;
00407 cout << "Scale factors are " << x_scale_factor << " " << y_scale_factor << " " << z_scale_factor << endl;
00408 cout << "Max input dim is " << max_input_dim << endl;
00409 }
00410 }
00411
00412 EMData* FourierReconstructor::preprocess_slice( const EMData* const slice, const Transform& t )
00413 {
00414
00415 EMData* return_slice = 0;
00416 Transform tmp(t);
00417 tmp.set_rotation(Dict("type","eman"));
00418
00419 Vec2f trans = tmp.get_trans_2d();
00420 float scale = tmp.get_scale();
00421 bool mirror = tmp.get_mirror();
00422 if (trans[0] != 0 || trans[1] != 0 || scale != 1.0 ) {
00423 return_slice = slice->process("math.transform",Dict("transform",&tmp));
00424 } else if ( mirror == true ) {
00425 return_slice = slice->process("xform.flip",Dict("axis","x"));
00426 }
00427
00428 if (return_slice == 0) {
00429 return_slice = slice->process("xform.phaseorigin.tocorner");
00430 } else {
00431 return_slice->process_inplace("xform.phaseorigin.tocorner");
00432 }
00433
00434
00435
00436
00437
00438 return_slice->do_fft_inplace();
00439
00440 return_slice->mult((float)sqrt(1.0f/(return_slice->get_ysize())*return_slice->get_xsize()));
00441
00442
00443 return_slice->process_inplace("xform.fourierorigin.tocenter");
00444
00445 return return_slice;
00446 }
00447
00448 void FourierReconstructor::zero_memory()
00449 {
00450 if (tmp_data != 0 ) tmp_data->to_zero();
00451 if (image != 0 ) image->to_zero();
00452
00453 EMData* start_model = params.set_default("start_model",(EMData*)0);
00454
00455 if (start_model != 0) {
00456 if (!start_model->is_complex()) {
00457 start_model->do_fft_inplace();
00458 start_model->process_inplace("xform.phaseorigin.tocenter");
00459 }
00460
00461 if (start_model->get_xsize() != nx || start_model->get_ysize() != ny || start_model->get_zsize() != nz ) {
00462 throw ImageDimensionException("The dimensions of the start_model are incorrect");
00463 }
00464
00465 if (!start_model->is_shuffled()) {
00466 start_model->process_inplace("xform.fourierorigin.tocenter");
00467 }
00468
00469 memcpy(image->get_data(),start_model->get_data(),nx*ny*nz*sizeof(float));
00470
00471 float start_model_weight = params.set_default("start_model_weight",1.0f);
00472
00473 if (start_model_weight != 1.0) {
00474 image->mult(start_model_weight);
00475 }
00476
00477 tmp_data->add(start_model_weight);
00478 }
00479 }
00480
00481 int FourierReconstructor::insert_slice(const EMData* const input_slice, const Transform & arg)
00482 {
00483
00484 if (!input_slice) throw NullPointerException("EMData pointer (input image) is NULL");
00485
00486
00487 if (input_slice->is_complex()) throw ImageFormatException("The image is complex, expecting real");
00488
00489
00490
00491
00492
00493
00494 Transform * rotation;
00495 if ( input_slice->has_attr("xform.projection") ) {
00496 rotation = (Transform*) (input_slice->get_attr("xform.projection"));
00497 } else {
00498 rotation = new Transform(arg);
00499 }
00500
00501 EMData* slice = preprocess_slice( input_slice, *rotation);
00502
00503
00504 if ( slice_insertion_flag == true )
00505 {
00506
00507 zero_memory();
00508
00509 image_idx = 0;
00510
00511 slice_agreement_flag = true;
00512 slice_insertion_flag = false;
00513
00514
00515
00516 }
00517
00518
00519
00520 if ( quality_scores.size() != 0 )
00521 {
00522 if ( quality_scores[image_idx].get_snr_normed_frc_integral() < (float) params["hard"] )
00523 {
00524 image_idx++;
00525 return 1;
00526 }
00527 slice->mult(1.f/quality_scores[image_idx].get_norm());
00528
00529 image_idx++;
00530 }
00531
00532
00533 rotation->set_scale(1.0);
00534 rotation->set_mirror(false);
00535 rotation->set_trans(0,0,0);
00536 do_insert_slice_work(slice, *rotation);
00537
00538 if(rotation) {delete rotation; rotation=0;}
00539 delete slice;
00540
00541
00542 return 0;
00543 }
00544
00545 void FourierReconstructor::do_insert_slice_work(const EMData* const input_slice, const Transform & arg)
00546 {
00547
00548 string mode = (string) params["mode"];
00549 if ( mode != inserter->get_name() ) load_inserter();
00550
00551 int rl = Util::square( max_input_dim / 2);
00552
00553 float dt[2];
00554
00555 float y_scale = 0, x_scale = 0;
00556
00557 int y_in = input_slice->get_ysize();
00558 int x_in = input_slice->get_xsize();
00559
00560 if (input_slice->is_fftodd()) x_in -= 1;
00561 else x_in -= 2;
00562
00563 if ( y_in != x_in )
00564 {
00565 if ( x_in > y_in ) y_scale = (float) x_in / (float) y_in;
00566 else x_scale = (float) y_in / (float) x_in;
00567 }
00568
00569 float *dat = input_slice->get_data();
00570 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]);
00571 float weight = params.set_default("weight",1.0f);
00572
00573 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) {
00574 Transform t3d = arg*(*it);
00575 for (int y = 0; y < input_slice->get_ysize(); y++) {
00576 for (int x = 0; x < input_slice->get_xsize() / 2; x++) {
00577
00578 float rx = (float) x;
00579 float ry = (float) y;
00580
00581 if ( y_in != x_in )
00582 {
00583 if ( x_in > y_in ) ry *= y_scale;
00584 else rx *= x_scale;
00585 }
00586
00587 if ((rx * rx + Util::square(ry - max_input_dim / 2)) > rl)
00588 continue;
00589
00590 Vec3f coord(rx,(ry - max_input_dim / 2),0);
00591 coord = coord*t3d;
00592 float xx = coord[0];
00593 float yy = coord[1];
00594 float zz = coord[2];
00595
00596 float cc = 1;
00597
00598 if (xx < 0) {
00599 xx = -xx;
00600 yy = -yy;
00601 zz = -zz;
00602 cc = -1.0;
00603 }
00604
00605 if ( z_scale_factor != 0 ) zz *= z_scale_factor;
00606 if ( y_scale_factor != 0 ) yy *= y_scale_factor;
00607 if ( x_scale_factor != 0 ) xx *= x_scale_factor;
00608
00609 yy += ny / 2;
00610 zz += nz / 2;
00611
00612 int idx = x * 2 + y * (input_slice->get_xsize());
00613 dt[0] = dat[idx];
00614 dt[1] = cc * dat[idx+1];
00615
00616 inserter->insert_pixel(xx,yy,zz,dt,weight);
00617 }
00618 }
00619 }
00620 }
00621
00622 int FourierReconstructor::determine_slice_agreement(const EMData* const input_slice, const Transform & t3d, const unsigned int num_particles_in_slice)
00623 {
00624
00625 if (!input_slice) {
00626 LOGERR("Insertion of NULL slice in FourierReconstructor::insert_slice");
00627 throw NullPointerException("EMData pointer (input image) is NULL");
00628 }
00629
00630
00631 if (input_slice->is_complex()) {
00632 LOGERR("Do not Fourier transform the image before it is passed to determine_slice_agreement in FourierReconstructor, this is performed internally");
00633 throw ImageFormatException("The image is complex, expecting real");
00634 }
00635
00636
00637 if ( slice_agreement_flag == true )
00638 {
00639
00640
00641 normalize_threed();
00642
00643 image_idx = 0;
00644
00645 prev_quality_scores = quality_scores;
00646
00647 quality_scores.clear();
00648
00649 slice_insertion_flag = true;
00650 slice_agreement_flag = false;
00651 }
00652
00653
00654
00655 Transform * rotation;
00656 if ( input_slice->has_attr("xform.projection") ) {
00657 rotation = (Transform*) (input_slice->get_attr("xform.projection"));
00658
00659 } else {
00660 rotation = new Transform(t3d);
00661 }
00662 EMData* slice = preprocess_slice( input_slice, *rotation );
00663
00664
00665
00666 if ( prev_quality_scores.size() != 0 )
00667 {
00668
00669
00670 slice->mult(1.f/prev_quality_scores[image_idx].get_norm());
00671 }
00672
00673
00674 interp_FRC_calculator->reset();
00675
00676 int rl = Util::square( max_input_dim / 2);
00677
00678 float dt[2];
00679
00680 float y_scale = 0, x_scale = 0;
00681
00682 int y_in = slice->get_ysize();
00683 int x_in = slice->get_xsize();
00684 if (input_slice->is_fftodd()) x_in -= 1;
00685 else x_in -= 2;
00686
00687 if ( y_in != x_in )
00688 {
00689 if ( x_in > y_in ) y_scale = (float) x_in / (float) y_in;
00690 else x_scale = (float) y_in / (float) x_in;
00691 }
00692 float *dat = slice->get_data();
00693
00694 float weight = params.set_default("weight",1.0f);
00695
00696
00697 rotation->set_scale(1.0);
00698 rotation->set_mirror(false);
00699 rotation->set_trans(0,0,0);
00700
00701 for (int y = 0; y < slice->get_ysize(); y++) {
00702 for (int x = 0; x < slice->get_xsize() / 2; x++) {
00703
00704 float rx = (float) x;
00705 float ry = (float) y;
00706
00707 if ( y_in != x_in )
00708 {
00709 if ( x_in > y_in ) ry *= y_scale;
00710 else rx *= x_scale;
00711 }
00712
00713 if ((rx * rx + Util::square(ry - max_input_dim / 2)) > rl)
00714 continue;
00715
00716
00717
00718
00719
00720 Vec3f coord(rx,(ry - max_input_dim / 2),0);
00721 coord = coord*(*rotation);
00722 float xx = coord[0];
00723 float yy = coord[1];
00724 float zz = coord[2];
00725
00726 float cc = 1;
00727
00728 if (xx < 0) {
00729 xx = -xx;
00730 yy = -yy;
00731 zz = -zz;
00732 cc = -1.0;
00733 }
00734
00735 if ( z_scale_factor != 0 ) zz *= z_scale_factor;
00736 if ( y_scale_factor != 0 ) yy *= y_scale_factor;
00737 if ( x_scale_factor != 0 ) xx *= x_scale_factor;
00738
00739 yy += ny / 2;
00740 zz += nz / 2;
00741
00742 int idx = x * 2 + y * (slice->get_xsize());
00743 dt[0] = dat[idx];
00744 dt[1] = cc * dat[idx+1];
00745
00746
00747 if ( prev_quality_scores.size() != 0 )
00748 {
00749
00750
00751
00752
00753
00754 if ( prev_quality_scores[image_idx].get_snr_normed_frc_integral() < (float) params["hard"] )
00755 {
00756 weight = 0;
00757 }
00758 }
00759
00760
00761
00762 interp_FRC_calculator->continue_frc_calc(xx, yy, zz, dt, weight);
00763 }
00764 }
00765
00766 InterpolatedFRC::QualityScores q_scores = interp_FRC_calculator->finish( num_particles_in_slice );
00767
00768
00769
00770 if (prev_quality_scores.size() != 0 )
00771 {
00772
00773
00774 q_scores.set_norm((q_scores.get_norm() + prev_quality_scores[image_idx].get_norm())/2.0f);
00775 image_idx++;
00776 }
00777
00778 quality_scores.push_back(q_scores);
00779
00780 if(rotation) {delete rotation; rotation=0;}
00781 delete slice;
00782 return 0;
00783 }
00784
00785 void FourierReconstructor::print_stats( const vector<InterpolatedFRC::QualityScores>& scores )
00786 {
00787 if ( prev_quality_scores.size() == 0 )
00788 {
00789
00790 return;
00791 }
00792
00793 unsigned int size = scores.size();
00794
00795 unsigned int contributing_images = 0;
00796 for( unsigned int i = 0; i < size; ++ i )
00797 {
00798 if (scores[i].get_snr_normed_frc_integral() < (float) params["hard"])
00799 continue;
00800 else contributing_images++;
00801 }
00802
00803 double* norm_frc = new double[contributing_images];
00804 double* frc = new double[contributing_images];
00805 double* norm_snr = new double[contributing_images];
00806
00807 unsigned int idx = 0;
00808 for( unsigned int i = 0; i < size; ++ i )
00809 {
00810 if (scores[i].get_snr_normed_frc_integral() < (float) params["hard"])
00811 continue;
00812
00813 norm_frc[idx] = scores[i].get_snr_normed_frc_integral();
00814 frc[idx] = scores[i].get_frc_integral();
00815 norm_snr[idx] = scores[i].get_normed_snr_integral();
00816
00817 ++idx;
00818 }
00819
00820 double mean = gsl_stats_mean(norm_frc, 1, contributing_images);
00821 double variance = gsl_stats_variance_m(norm_frc, 1, contributing_images, mean);
00822
00823 cout << "Normalized FRC mean " << mean << " std dev " << sqrt(variance) << endl;
00824
00825 mean = gsl_stats_mean(frc, 1, contributing_images);
00826 variance = gsl_stats_variance_m(frc, 1, contributing_images, mean);
00827
00828 cout << "FRC mean " << mean << " std dev " << sqrt(variance) << endl;
00829
00830 mean = gsl_stats_mean(norm_snr, 1, contributing_images);
00831 variance = gsl_stats_variance_m(norm_snr, 1, contributing_images, mean);
00832 cout << "SNR mean " << mean << " std dev " << sqrt(variance) << endl;
00833
00834 double c0, c1, cov00, cov01, cov11, sumsq;
00835 gsl_fit_linear (norm_frc, 1, frc, 1, contributing_images, &c0, &c1, &cov00, &cov01, &cov11, &sumsq);
00836 cout << "The correlation between frc and norm_frc is " << c0 << " + " << c1 << "x" << endl;
00837
00838 gsl_fit_linear (norm_frc, 1, norm_snr, 1, contributing_images, &c0, &c1, &cov00, &cov01, &cov11, &sumsq);
00839 cout << "The correlation between norm_snr and norm_frc is " << c0 << " + " << c1 << "x" << endl;
00840
00841 gsl_fit_linear (norm_snr, 1, frc, 1, contributing_images, &c0, &c1, &cov00, &cov01, &cov11, &sumsq);
00842 cout << "The correlation between frc and norm_snr is " << c0 << " + " << c1 << "x" << endl;
00843
00844 delete [] norm_frc;
00845 delete [] frc;
00846 delete [] norm_snr;
00847 }
00848
00849 EMData *FourierReconstructor::finish()
00850 {
00851 float *norm = tmp_data->get_data();
00852 float *rdata = image->get_data();
00853
00854 if (params["dlog"]) {
00855 size_t size = nx*ny*nz;
00856 for (size_t i = 0; i < size; i += 2) {
00857 float d = norm[i];
00858 if (d == 0) {
00859 rdata[i] = 0;
00860 rdata[i + 1] = 0;
00861 }
00862 else {
00863 float in = norm[i + 1] / norm[i];
00864 float cin = Util::square_sum(rdata[i], rdata[i + 1]);
00865 rdata[i] *= sqrt(in / cin);
00866 rdata[i + 1] *= sqrt(in / cin);
00867 }
00868 }
00869 }
00870 else {
00871 normalize_threed();
00872 }
00873
00874
00875
00876
00877
00878
00879 if ( tmp_data != 0 )
00880 {
00881 delete tmp_data;
00882 tmp_data = 0;
00883 }
00884
00885
00886 if ( params["3damp"]) {
00887 EMData* fftimage = image->get_fft_amplitude ();
00888 fftimage->write_image("threed_fft_amp.mrc");
00889 delete fftimage;
00890 }
00891
00892
00893 image->process_inplace("xform.fourierorigin.tocorner");
00894 image->do_ift_inplace();
00895 image->depad();
00896 image->process_inplace("xform.phaseorigin.tocenter");
00897
00898
00899
00900
00901 bool is_fftodd = (nx % 2 == 1);
00902 if ( (nx-2*(!is_fftodd)) != output_x || ny != output_y || nz != output_z )
00903 {
00904 FloatPoint origin( (nx-output_x)/2, (ny-output_y)/2, (nz-output_z)/2 );
00905 FloatSize region_size( output_x, output_y, output_z);
00906 Region clip_region( origin, region_size );
00907 image->clip_inplace( clip_region );
00908 }
00909
00910
00911
00912
00913 image->update();
00914
00915 return image;
00916 }
00917
00918
00919 void BaldwinWoolfordReconstructor::setup()
00920 {
00921
00922 params.set_default("mode",1);
00923 FourierReconstructor::setup();
00924
00925 int P = (int)((1.0+0.25)*max_input_dim+1);
00926 float r = (float)(max_input_dim+1)/(float)P;
00927 dfreq = 0.2f;
00928 if (W != 0) delete [] W;
00929 int maskwidth = params.set_default("maskwidth",2);
00930 W = Util::getBaldwinGridWeights(maskwidth, (float)P, r,dfreq,0.5f,0.2f);
00931 }
00932
00933 EMData* BaldwinWoolfordReconstructor::finish()
00934 {
00935 tmp_data->write_image("density.mrc");
00936 image->process_inplace("xform.fourierorigin.tocorner");
00937 image->do_ift_inplace();
00938 image->depad();
00939 image->process_inplace("xform.phaseorigin.tocenter");
00940
00941 if ( (bool) params.set_default("postmultiply", false) )
00942 {
00943 cout << "POST MULTIPLYING" << endl;
00944
00945 float* d = image->get_data();
00946 float N = (float) image->get_xsize()/2.0f;
00947 N *= N;
00948 size_t rnx = image->get_xsize();
00949 size_t rny = image->get_ysize();
00950 size_t rnxy = rnx*rny;
00951 int cx = image->get_xsize()/2;
00952 int cy = image->get_ysize()/2;
00953 int cz = image->get_zsize()/2;
00954 size_t idx;
00955 for (int k = 0; k < image->get_zsize(); ++k ){
00956 for (int j = 0; j < image->get_ysize(); ++j ) {
00957 for (int i =0; i < image->get_xsize(); ++i ) {
00958 float xd = (float)(i-cx); xd *= xd;
00959 float yd = (float)(j-cy); yd *= yd;
00960 float zd = (float)(k-cz); zd *= zd;
00961 float weight = exp((xd+yd+zd)/N);
00962 idx = k*rnxy + j*rnx + i;
00963 d[idx] *= weight;
00964 }
00965 }
00966 }
00967 }
00968 image->update();
00969 return image;
00970 }
00971
00972 #include <iomanip>
00973
00974 int BaldwinWoolfordReconstructor::insert_slice_weights(const Transform& t3d)
00975 {
00976 bool fftodd = image->is_fftodd();
00977 int rnx = nx-2*!fftodd;
00978
00979 float y_scale = 1.0, x_scale = 1.0;
00980
00981 if ( ny != rnx )
00982 {
00983 if ( rnx > ny ) y_scale = (float) rnx / (float) ny;
00984 else x_scale = (float) ny / (float) rnx;
00985 }
00986
00987 int tnx = tmp_data->get_xsize();
00988 int tny = tmp_data->get_ysize();
00989 int tnz = tmp_data->get_zsize();
00990
00991 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]);
00992 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) {
00993 Transform n3d = t3d*(*it);
00994
00995 for (int y = 0; y < tny; y++) {
00996 for (int x = 0; x < tnx; x++) {
00997
00998 float rx = (float) x;
00999 float ry = (float) y;
01000
01001 if ( ny != rnx )
01002 {
01003 if ( rnx > ny ) ry *= y_scale;
01004 else rx *= x_scale;
01005 }
01006
01007
01008
01009
01010 Vec3f coord(rx,(ry - tny/2),0);
01011 coord = coord*n3d;
01012 float xx = coord[0];
01013 float yy = coord[1];
01014 float zz = coord[2];
01015
01016 if (xx < 0 ){
01017 xx = -xx;
01018 yy = -yy;
01019 zz = -zz;
01020 }
01021
01022 yy += tny/2;
01023 zz += tnz/2;
01024 insert_density_at(xx,yy,zz);
01025 }
01026 }
01027 }
01028
01029 return 0;
01030 }
01031
01032 void BaldwinWoolfordReconstructor::insert_density_at(const float& x, const float& y, const float& z)
01033 {
01034 int xl = Util::fast_floor(x);
01035 int yl = Util::fast_floor(y);
01036 int zl = Util::fast_floor(z);
01037
01038
01039 int w = params.set_default("maskwidth",2);
01040 float wsquared = (float) w*w;
01041 float dw = 1.0f/w;
01042 dw *= dw;
01043
01044
01045
01046
01047 int wmox = w-1;
01048 int wmoy = w-1;
01049 int wmoz = w-1;
01050
01051
01052
01053
01054 if ( ((float) xl) == x ) wmox = w;
01055 if ( ((float) yl) == y ) wmoy = w;
01056 if ( ((float) zl) == z ) wmoz = w;
01057
01058 float* d = tmp_data->get_data();
01059 int tnx = tmp_data->get_xsize();
01060 int tny = tmp_data->get_ysize();
01061 int tnz = tmp_data->get_zsize();
01062 size_t tnxy = tnx*tny;
01063
01064 int mode = params.set_default("mode",1);
01065
01066 for(int k = zl-wmoz; k <= zl+w; ++k ) {
01067 for(int j = yl-wmoy; j <= yl+w; ++j) {
01068 for( int i = xl-wmox; i <= xl+w; ++i) {
01069 float fac = 1.0;
01070 int ic = i, jc = j, kc = k;
01071
01072
01073
01074
01075
01076 if ( i <= 0 ) {
01077
01078 if ( x != 0 && i == 0 ) fac = 1.0;
01079 else if ( x == 0 && i < 0) continue;
01080
01081 if (i < 0 ) {
01082 continue;
01083 ic = -i;
01084 jc = tny-jc;
01085 kc = tnz-kc;
01086 }
01087 }
01088 if ( ic >= tnx ) ic = 2*tnx-ic-1;
01089 if ( jc < 0 ) jc = tny+jc;
01090 if ( jc >= tny ) jc = jc-tny;
01091 if ( kc < 0 ) kc = tnz+kc;
01092 if ( kc >= tnz ) kc = kc-tnz;
01093
01094
01095
01096
01097
01098
01099
01100 if ( ic < 0 ) { cout << "wo 1" << endl; }
01101 if ( ic >= tnx ){ cout << "wo 2" << endl; }
01102 if ( jc < 0 ) { cout << "wo 3" << endl; }
01103 if ( jc >= tny ) { cout << "wo 4" << endl; }
01104 if ( kc < 0 ) { cout << "wo 5" << endl; }
01105 if ( kc >= tnz ) { cout << "wo 6" << endl; }
01106
01107
01108 float zd = (z-(float)k);
01109 float yd = (y-(float)j);
01110 float xd = (x-(float)i);
01111 zd *= zd; yd *= yd; xd *= xd;
01112 float distsquared = xd+yd+zd;
01113
01114 if ( mode == 1 && distsquared > wsquared ) continue;
01115
01116
01117 float f = fac*exp(-2.467f*(distsquared));
01118
01119 if ( (kc*tnxy+jc*tnx+ic) >= tnxy*tnz ) throw OutofRangeException(0,tnxy*tnz,kc*tnxy+jc*tnx+ic, "in density insertion" );
01120 d[kc*tnxy+jc*tnx+ic] += f;
01121 }
01122 }
01123 }
01124 }
01125
01126 int BaldwinWoolfordReconstructor::insert_slice(const EMData* const input_slice, const Transform & t)
01127 {
01128 Transform * rotation;
01129 if ( input_slice->has_attr("xform.projection") ) {
01130 rotation = (Transform*) (input_slice->get_attr("xform.projection"));
01131 } else {
01132 rotation = new Transform(t);
01133 }
01134 Transform tmp(*rotation);
01135 tmp.set_rotation(Dict("type","eman"));
01136
01137 Vec2f trans = tmp.get_trans_2d();
01138 float scale = tmp.get_scale();
01139 bool mirror = tmp.get_mirror();
01140 EMData* slice = 0;
01141 if (trans[0] != 0 || trans[1] != 0 || scale != 1.0 ) {
01142 slice = input_slice->process("math.transform",Dict("transform",&tmp));
01143 } else if ( mirror == true ) {
01144 slice = input_slice->process("xform.flip",Dict("axis","x"));
01145 }
01146 if ( slice == 0 ) {
01147 slice = input_slice->process("xform.phaseorigin.tocorner");
01148 } else {
01149 slice->process_inplace("xform.phaseorigin.tocorner");
01150 }
01151
01152 slice->do_fft_inplace();
01153 slice->process_inplace("xform.fourierorigin.tocenter");
01154 float *dat = slice->get_data();
01155 float dt[2];
01156
01157 bool fftodd = image->is_fftodd();
01158 int rnx = nx-2*!fftodd;
01159
01160 float y_scale = 1.0, x_scale = 1.0;
01161
01162 if ( ny != rnx )
01163 {
01164 if ( rnx > ny ) y_scale = (float) rnx / (float) ny;
01165 else x_scale = (float) ny / (float) rnx;
01166 }
01167
01168 int tnx = tmp_data->get_xsize();
01169 int tny = tmp_data->get_ysize();
01170 int tnz = tmp_data->get_zsize();
01171
01172 vector<Transform> syms = Symmetry3D::get_symmetries((string)params["sym"]);
01173
01174
01175 rotation->set_scale(1.0); rotation->set_mirror(false); rotation->set_trans(0,0,0);
01176 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) {
01177 Transform t3d = (*rotation)*(*it);
01178
01179 for (int y = 0; y < tny; y++) {
01180 for (int x = 0; x < tnx; x++) {
01181 float rx = (float) x;
01182 float ry = (float) y;
01183
01184 if ( ny != rnx )
01185 {
01186 if ( rnx > ny ) ry *= y_scale;
01187 else rx *= x_scale;
01188 }
01189
01190
01191
01192
01193
01194 Vec3f coord(rx,(ry - tny/2),0);
01195 coord = coord*t3d;
01196 float xx = coord[0];
01197 float yy = coord[1];
01198 float zz = coord[2];
01199
01200
01201 float cc = 1;
01202 if (xx < 0 ){
01203 xx = -xx;
01204 yy = -yy;
01205 zz = -zz;
01206 cc = -1;
01207 }
01208
01209 yy += tny/2;
01210 zz += tnz/2;
01211
01212 int idx = x * 2 + y * (slice->get_xsize());
01213 dt[0] = dat[idx];
01214 dt[1] = cc * dat[idx+1];
01215
01216 insert_pixel(xx,yy,zz,dt);
01217 }
01218 }
01219 }
01220
01221 if(rotation) {delete rotation; rotation=0;}
01222 delete slice;
01223
01224 return 0;
01225 }
01226
01227 void BaldwinWoolfordReconstructor::insert_pixel(const float& x, const float& y, const float& z, const float dt[2])
01228 {
01229 int xl = Util::fast_floor(x);
01230 int yl = Util::fast_floor(y);
01231 int zl = Util::fast_floor(z);
01232
01233
01234 int w = params.set_default("maskwidth",2);
01235 float wsquared = (float) w*w;
01236 float dw = 1.0f/w;
01237 dw *= dw;
01238
01239 int wmox = w-1;
01240 int wmoy = w-1;
01241 int wmoz = w-1;
01242
01243
01244
01245
01246 if ( ((float) xl) == x ) wmox = w;
01247 if ( ((float) yl) == y ) wmoy = w;
01248 if ( ((float) zl) == z ) wmoz = w;
01249
01250 float* we = tmp_data->get_data();
01251 int tnx = tmp_data->get_xsize();
01252 int tny = tmp_data->get_ysize();
01253 int tnz = tmp_data->get_zsize();
01254 int tnxy = tnx*tny;
01255
01256 int rnx = 2*tnx;
01257 int rnxy = 2*tnxy;
01258
01259 int mode = params.set_default("mode",1);
01260
01261 float* d = image->get_data();
01262 for(int k = zl-wmoz; k <= zl+w; ++k ) {
01263 for(int j = yl-wmoy; j <= yl+w; ++j) {
01264 for( int i = xl-wmox; i <= xl+w; ++i) {
01265 float fac = 1.0;
01266 int ic = i, jc = j, kc = k;
01267
01268
01269
01270
01271
01272 float negfac=1.0;
01273 if ( i <= 0 ) {
01274 if ( x != 0 && i == 0 ) fac = 1.0;
01275 else if ( x == 0 && i < 0) continue;
01276 if (i < 0 ) {
01277 continue;
01278 ic = -i;
01279 jc = tny-jc;
01280 kc = tnz-kc;
01281 negfac=-1.0;
01282 }
01283 }
01284 if ( ic >= tnx ) ic = 2*tnx-ic-1;
01285 if ( jc < 0 ) jc = tny+jc;
01286 if ( jc >= tny ) jc = jc-tny;
01287 if ( kc < 0 ) kc = tnz+kc;
01288 if ( kc >= tnz ) kc = kc-tnz;
01289
01290
01291
01292
01293
01294
01295 float zd = (z-(float)k);
01296 float yd = (y-(float)j);
01297 float xd = (x-(float)i);
01298 zd *= zd; yd *= yd; xd *= xd;
01299 float distsquared = xd+yd+zd;
01300
01301 float f = fac*exp(-2.467f*(distsquared));
01302 float weight = f/we[kc*tnxy+jc*tnx+ic];
01303
01304 if ( (kc*rnxy+jc*rnx+2*ic+1) >= rnxy*tnz ) throw OutofRangeException(0,rnxy*tnz,kc*rnxy+jc*rnx+2*ic+1, "in pixel insertion" );
01305 size_t k = kc*rnxy+jc*rnx+2*ic;
01306
01307 float factor, dist,residual;
01308 int sizeW,sizeWmid,idx;
01309 switch (mode) {
01310 case 0:
01311 d[k] += weight*f*dt[0];
01312 d[k+1] += negfac*weight*f*dt[1];
01313 cout << "hello" << endl;
01314 break;
01315
01316 case 1:
01317
01318 if ( distsquared > wsquared ) continue;
01319
01320 sizeW = (int)(1+2*w/dfreq);
01321 sizeWmid = sizeW/2;
01322
01323 dist = sqrtf(distsquared);
01324 idx = (int)(sizeWmid + dist/dfreq);
01325 if (idx >= sizeW) throw InvalidValueException(idx, "idx was greater than or equal to sizeW");
01326 residual = dist/dfreq - (int)(dist/dfreq);
01327 if ( fabs(residual) > 1) throw InvalidValueException(residual, "Residual was too big");
01328
01329 factor = (W[idx]*(1.0f-residual)+W[idx+1]*residual)*weight;
01330
01331 d[k] += dt[0]*factor;
01332 d[k+1] += dt[1]*factor;
01333 break;
01334
01335 default:
01336 throw InvalidValueException(mode, "The mode was unsupported in BaldwinWoolfordReconstructor::insert_pixel");
01337 break;
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 void WienerFourierReconstructor::setup()
01479 {
01480 int size = params["size"];
01481 image = new EMData();
01482 image->set_size(size + 2, size, size);
01483 image->set_complex(true);
01484 image->set_ri(true);
01485
01486 nx = image->get_xsize();
01487 ny = image->get_ysize();
01488 nz = image->get_zsize();
01489
01490 int n = nx * ny * nz;
01491 float *rdata = image->get_data();
01492
01493 for (int i = 0; i < n; i += 2) {
01494 float f = Util::get_frand(0.0, 2.0 * M_PI);
01495 rdata[i] = 1.0e-10f * sin(f);
01496 rdata[i + 1] = 1.0e-10f * cos(f);
01497 }
01498 image->update();
01499
01500 tmp_data = new EMData();
01501 tmp_data->set_size(size + 1, size, size);
01502 }
01503
01504
01505 EMData *WienerFourierReconstructor::finish()
01506 {
01507 float *norm = tmp_data->get_data();
01508 float *rdata = image->get_data();
01509
01510 size_t size = nx * ny * nz;
01511 for (size_t i = 0; i < size; i += 2) {
01512 float d = norm[i];
01513 if (d == 0) {
01514 rdata[i] = 0;
01515 rdata[i + 1] = 0;
01516 }
01517 else {
01518 float w = 1 + 1 / d;
01519 rdata[i] /= d * w;
01520 rdata[i + 1] /= d * w;
01521 }
01522 }
01523
01524 if( tmp_data ) {
01525 delete tmp_data;
01526 tmp_data = 0;
01527 }
01528 image->update();
01529 return image;
01530 }
01531
01532
01533 int WienerFourierReconstructor::insert_slice(const EMData* const slice, const Transform3D & euler)
01534 {
01535 if (!slice) {
01536 LOGERR("try to insert NULL slice");
01537 return 1;
01538 }
01539
01540 int mode = params["mode"];
01541 float padratio = params["padratio"];
01542 vector < float >snr = params["snr"];
01543
01544 if (!slice->is_complex()) {
01545 LOGERR("Only complex slice can be inserted.");
01546 return 1;
01547 }
01548 float *gimx = 0;
01549 if (mode == 5) {
01550 gimx = Interp::get_gimx();
01551 }
01552
01553 int nxy = nx * ny;
01554 int off[8] = {0,0,0,0,0,0,0,0};
01555 if (mode == 2) {
01556 off[0] = 0;
01557 off[1] = 2;
01558 off[2] = nx;
01559 off[3] = nx + 2;
01560 off[4] = nxy;
01561 off[5] = nxy + 2;
01562 off[6] = nxy + nx;
01563 off[7] = nxy + nx + 2;
01564 }
01565
01566 float *norm = tmp_data->get_data();
01567 float *dat = slice->get_data();
01568 float *rdata = image->get_data();
01569
01570 int rl = Util::square(ny / 2 - 1);
01571 float dt[2];
01572 float g[8];
01573
01574 for (int y = 0; y < ny; y++) {
01575 for (int x = 0; x < nx / 2; x++) {
01576 if ((x * x + Util::square(y - ny / 2)) >= rl)
01577 {
01578 continue;
01579 }
01580
01581 #ifdef _WIN32
01582 int r = Util::round((float)_hypot(x, (float) y - ny / 2) * Ctf::CTFOS / padratio);
01583 #else
01584 int r = Util::round((float)hypot(x, (float) y - ny / 2) * Ctf::CTFOS / padratio);
01585 #endif
01586 if (r >= Ctf::CTFOS * ny / 2) {
01587 r = Ctf::CTFOS * ny / 2 - 1;
01588 }
01589
01590 float weight = snr[r];
01591
01592 float xx = (x * euler[0][0] + (y - ny / 2) * euler[0][1]);
01593 float yy = (x * euler[1][0] + (y - ny / 2) * euler[1][1]);
01594 float zz = (x * euler[2][0] + (y - ny / 2) * euler[2][1]);
01595 float cc = 1;
01596
01597 if (xx < 0) {
01598 xx = -xx;
01599 yy = -yy;
01600 zz = -zz;
01601 cc = -1.0;
01602 }
01603
01604 yy += ny / 2;
01605 zz += nz / 2;
01606
01607 dt[0] = dat[x * 2 + y * nx] * (1 + 1.0f / weight);
01608 dt[1] = cc * dat[x * 2 + 1 + y * nx] * (1 + 1.0f / weight);
01609
01610 int x0 = 0;
01611 int y0 = 0;
01612 int z0 = 0;
01613 int i = 0;
01614 int l = 0;
01615 float dx = 0;
01616 float dy = 0;
01617 float dz = 0;
01618
01619 int mx0 = 0;
01620 int my0 = 0;
01621 int mz0 = 0;
01622
01623 size_t idx;
01624 switch (mode) {
01625 case 1:
01626 x0 = 2 * (int) floor(xx + 0.5f);
01627 y0 = (int) floor(yy + 0.5f);
01628 z0 = (int) floor(zz + 0.5f);
01629
01630 rdata[x0 + y0 * nx + z0 * nxy] += weight * dt[0];
01631 rdata[x0 + y0 * nx + z0 * nxy + 1] += weight * dt[1];
01632 norm[x0 + y0 * nx + z0 * nxy] += weight;
01633 break;
01634
01635 case 2:
01636 x0 = (int) floor(xx);
01637 y0 = (int) floor(yy);
01638 z0 = (int) floor(zz);
01639
01640 dx = xx - x0;
01641 dy = yy - y0;
01642 dz = zz - z0;
01643
01644 weight /= (float)pow((float)(EMConsts::I2G * M_PI), 1.5f);
01645
01646 if (x0 > nx - 2 || y0 > ny - 1 || z0 > nz - 1) {
01647 break;
01648 }
01649
01650 i = (int) (x0 * 2 + y0 * nx + z0 * nxy);
01651
01652
01653 g[0] = Util::agauss(1, dx, dy, dz, EMConsts::I2G);
01654 g[1] = Util::agauss(1, 1 - dx, dy, dz, EMConsts::I2G);
01655 g[2] = Util::agauss(1, dx, 1 - dy, dz, EMConsts::I2G);
01656 g[3] = Util::agauss(1, 1 - dx, 1 - dy, dz, EMConsts::I2G);
01657 g[4] = Util::agauss(1, dx, dy, 1 - dz, EMConsts::I2G);
01658 g[5] = Util::agauss(1, 1 - dx, dy, 1 - dz, EMConsts::I2G);
01659 g[6] = Util::agauss(1, dx, 1 - dy, 1 - dz, EMConsts::I2G);
01660 g[7] = Util::agauss(1, 1 - dx, 1 - dy, 1 - dz, EMConsts::I2G);
01661
01662 for (int j = 0; j < 8; j++) {
01663 int k = i + off[j];
01664 rdata[k] += weight * dt[0] * g[j];
01665 rdata[k + 1] += weight * dt[1] * g[j];
01666 norm[k] += weight * g[j];
01667 }
01668
01669 break;
01670 case 3:
01671 x0 = 2 * (int) floor(xx + 0.5f);
01672 y0 = (int) floor(yy + 0.5f);
01673 z0 = (int) floor(zz + 0.5f);
01674
01675 weight /= (float)pow((float)(EMConsts::I3G * M_PI), 1.5f);
01676
01677 if (x0 >= nx - 4 || y0 > ny - 3 || z0 > nz - 3 || y0 < 2 || z0 < 2) {
01678 break;
01679 }
01680
01681 l = x0 - 2;
01682 if (x0 == 0) {
01683 l = x0;
01684 }
01685
01686 for (int k = z0 - 1; k <= z0 + 1; k++) {
01687 for (int j = y0 - 1; j <= y0 + 1; j++) {
01688 for (int i = l; i <= x0 + 2; i += 2) {
01689 float r = Util::hypot3((float) i / 2 - xx, j - yy, k - zz);
01690 float gg = exp(-r / EMConsts::I3G);
01691
01692 idx = i + j * nx + k * nxy;
01693 rdata[idx] += weight * gg * dt[0];
01694 rdata[idx + 1] += weight * gg * dt[1];
01695 norm[idx] += weight * gg;
01696 }
01697 }
01698 }
01699 break;
01700
01701 case 4:
01702 x0 = 2 * (int) floor(xx);
01703 y0 = (int) floor(yy);
01704 z0 = (int) floor(zz);
01705
01706 weight /= (float)pow((float)(EMConsts::I4G * M_PI), 1.5f);
01707
01708 if (x0 >= nx - 4 || y0 > ny - 3 || z0 > nz - 3 || y0 < 2 || z0 < 2) {
01709 break;
01710 }
01711
01712 l = x0 - 2;
01713 if (x0 == 0) {
01714 l = x0;
01715 }
01716
01717 for (int k = z0 - 1; k <= z0 + 2; ++k) {
01718 for (int j = y0 - 1; j <= y0 + 2; ++j) {
01719 for (int i = l; i <= x0 + 4; i += 2) {
01720 float r = Util::hypot3((float) i / 2 - xx, j - yy, k - zz);
01721 float gg = exp(-r / EMConsts::I4G);
01722
01723 idx = i + j * nx + k * nxy;
01724 rdata[idx] += weight * gg * dt[0];
01725 rdata[idx + 1] += weight * gg * dt[1];
01726 norm[idx] += weight * gg;
01727 }
01728 }
01729 }
01730 break;
01731
01732 case 5:
01733 x0 = (int) floor(xx + .5);
01734 y0 = (int) floor(yy + .5);
01735 z0 = (int) floor(zz + .5);
01736
01737 weight /= (float)pow((float)(EMConsts::I5G * M_PI), 1.5f);
01738
01739 mx0 = -(int) floor((xx - x0) * 39.0f + 0.5) - 78;
01740 my0 = -(int) floor((yy - y0) * 39.0f + 0.5) - 78;
01741 mz0 = -(int) floor((zz - z0) * 39.0f + 0.5) - 78;
01742 x0 *= 2;
01743
01744 if (x0 >= nx - 4 || y0 > ny - 3 || z0 > nz - 3 || y0 < 2 || z0 < 2)
01745 break;
01746
01747 if (x0 == 0) {
01748 l = 0;
01749 mx0 += 78;
01750 }
01751 else if (x0 == 2) {
01752 l = 0;
01753 mx0 += 39;
01754 }
01755 else
01756 l = x0 - 4;
01757 for (int k = z0 - 2, mmz = mz0; k <= z0 + 2; k++, mmz += 39) {
01758 for (int j = y0 - 2, mmy = my0; j <= y0 + 2; j++, mmy += 39) {
01759 for (int i = l, mmx = mx0; i <= x0 + 4; i += 2, mmx += 39) {
01760 size_t ii = i + j * nx + k * nxy;
01761 float gg = weight * gimx[abs(mmx) + abs(mmy) * 100 + abs(mmz) * 10000];
01762
01763 rdata[ii] += gg * dt[0];
01764 rdata[ii + 1] += gg * dt[1];
01765 norm[ii] += gg;
01766 }
01767 }
01768 }
01769
01770 if (x0 <= 2) {
01771 xx = -xx;
01772 yy = -(yy - ny / 2) + ny / 2;
01773 zz = -(zz - nz / 2) + nz / 2;
01774 x0 = (int) floor(xx + 0.5f);
01775 y0 = (int) floor(yy + 0.5f);
01776 z0 = (int) floor(zz + 0.5f);
01777 int mx0 = -(int) floor((xx - x0) * 39.0f + .5);
01778 x0 *= 2;
01779
01780 if (y0 > ny - 3 || z0 > nz - 3 || y0 < 2 || z0 < 2)
01781 break;
01782
01783 for (int k = z0 - 2, mmz = mz0; k <= z0 + 2; k++, mmz += 39) {
01784 for (int j = y0 - 2, mmy = my0; j <= y0 + 2; j++, mmy += 39) {
01785 for (int i = 0, mmx = mx0; i <= x0 + 4; i += 2, mmx += 39) {
01786 size_t ii = i + j * nx + k * nxy;
01787 float gg =
01788 weight * gimx[abs(mmx) + abs(mmy) * 100 + abs(mmz) * 10000];
01789
01790 rdata[ii] += gg * dt[0];
01791 rdata[ii + 1] -= gg * dt[1];
01792 norm[ii] += gg;
01793 }
01794 }
01795 }
01796 }
01797 break;
01798
01799 case 6:
01800 x0 = 2 * (int) floor(xx + .5);
01801 y0 = (int) floor(yy + .5);
01802 z0 = (int) floor(zz + .5);
01803
01804 weight /= (float)pow((float)(EMConsts::I5G * M_PI), 1.5f);
01805
01806 if (x0 >= nx - 4 || y0 > ny - 3 || z0 > nz - 3 || y0 < 2 || z0 < 2)
01807 break;
01808
01809 if (x0 <= 2)
01810 l = 0;
01811 else
01812 l = x0 - 4;
01813 for (int k = z0 - 2; k <= z0 + 2; ++k) {
01814 for (int j = y0 - 2; j <= y0 + 2; ++j) {
01815 for (int i = l; i <= x0 + 4; i += 2) {
01816 size_t ii = i + j * nx + k * nxy;
01817 float r = Util::hypot3((float) i / 2 - xx, (float) j - yy,
01818 (float) k - zz);
01819 float gg = weight * exp(-r / EMConsts::I5G);
01820
01821 rdata[ii] += gg * dt[0];
01822 rdata[ii + 1] += gg * dt[1];
01823 norm[ii] += gg;
01824 }
01825 }
01826 }
01827
01828 if (x0 <= 2) {
01829 xx = -xx;
01830 yy = -(yy - ny / 2) + ny / 2;
01831 zz = -(zz - nz / 2) + nz / 2;
01832 x0 = 2 * (int) floor(xx + 0.5f);
01833 y0 = (int) floor(yy + 0.5f);
01834 z0 = (int) floor(zz + 0.5f);
01835
01836 if (y0 > ny - 3 || z0 > nz - 3 || y0 < 2 || z0 < 2)
01837 break;
01838
01839 for (int k = z0 - 2; k <= z0 + 2; ++k) {
01840 for (int j = y0 - 2; j <= y0 + 2; ++j) {
01841 for (int i = 0; i <= x0 + 4; i += 2) {
01842 size_t ii = i + j * nx + k * nxy;
01843 float r = Util::hypot3((float) i / 2 - xx, (float) j - yy,
01844 (float) k - zz);
01845 float gg = weight * exp(-r / EMConsts::I5G);
01846
01847 rdata[ii] += gg * dt[0];
01848 rdata[ii + 1] -= gg * dt[1];
01849 norm[ii] += gg;
01850 }
01851 }
01852 }
01853 }
01854 break;
01855
01856 case 7:
01857 x0 = 2 * (int) floor(xx + .5);
01858 y0 = (int) floor(yy + .5);
01859 z0 = (int) floor(zz + .5);
01860
01861 if (x0 >= nx - 4 || y0 > ny - 3 || z0 > nz - 3 || y0 < 2 || z0 < 2)
01862 break;
01863
01864 if (x0 <= 2)
01865 l = 0;
01866 else
01867 l = x0 - 4;
01868 for (int k = z0 - 2; k <= z0 + 2; k++) {
01869 for (int j = y0 - 2; j <= y0 + 2; j++) {
01870 for (int i = l; i <= x0 + 4; i += 2) {
01871 size_t ii = i + j * nx + k * nxy;
01872 float r = (float)sqrt(Util::hypot3((float) i / 2 - xx,
01873 (float) j - yy,
01874 (float) k - zz));
01875 float gg = weight * Interp::hyperg(r);
01876
01877 rdata[ii] += gg * dt[0];
01878 rdata[ii + 1] += gg * dt[1];
01879 norm[ii] += gg;
01880 }
01881 }
01882 }
01883
01884 if (x0 <= 2) {
01885 xx = -xx;
01886 yy = -(yy - ny / 2) + ny / 2;
01887 zz = -(zz - nz / 2) + nz / 2;
01888 x0 = 2 * (int) floor(xx + .5);
01889 y0 = (int) floor(yy + .5);
01890 z0 = (int) floor(zz + .5);
01891
01892 if (y0 > ny - 3 || z0 > nz - 3 || y0 < 2 || z0 < 2)
01893 break;
01894
01895 for (int k = z0 - 2; k <= z0 + 2; ++k) {
01896 for (int j = y0 - 2; j <= y0 + 2; ++j) {
01897 for (int i = 0; i <= x0 + 4; i += 2) {
01898 size_t ii = i + j * nx + k * nxy;
01899 float r = sqrt(Util::hypot3((float) i / 2 - xx, (float) j - yy,
01900 (float) k - zz));
01901 float gg = weight * Interp::hyperg(r);
01902
01903 rdata[ii] += gg * dt[0];
01904 rdata[ii + 1] -= gg * dt[1];
01905 norm[ii] += gg;
01906 }
01907 }
01908 }
01909 }
01910 break;
01911 }
01912
01913 }
01914 }
01915
01916 image->update();
01917 tmp_data->update();
01918
01919
01920 return 0;
01921 }
01922
01923 void BackProjectionReconstructor::setup()
01924 {
01925 int size = params["size"];
01926 image = new EMData();
01927 nx = size;
01928 ny = size;
01929 if ( (int) params["zsample"] != 0 ) nz = params["zsample"];
01930 else nz = size;
01931 image->set_size(nx, ny, nz);
01932 }
01933
01934 EMData* BackProjectionReconstructor::preprocess_slice(const EMData* const slice, const Transform& t)
01935 {
01936
01937 EMData* return_slice = slice->process("normalize.edgemean");
01938 return_slice->process_inplace("filter.linearfourier");
01939
01940 Transform tmp(t);
01941 tmp.set_rotation(Dict("type","eman"));
01942 Vec2f trans = tmp.get_trans_2d();
01943 float scale = tmp.get_scale();
01944 bool mirror = tmp.get_mirror();
01945 if (trans[0] != 0 || trans[1] != 0 || scale != 1.0 ) {
01946 return_slice->transform(tmp);
01947 } else if ( mirror == true ) {
01948 return_slice = slice->process("xform.flip",Dict("axis","x"));
01949 }
01950
01951 return return_slice;
01952 }
01953
01954 int BackProjectionReconstructor::insert_slice(const EMData* const input, const Transform &t)
01955 {
01956 if (!input) {
01957 LOGERR("try to insert NULL slice");
01958 return 1;
01959 }
01960
01961 if (input->get_xsize() != input->get_ysize() || input->get_xsize() != nx) {
01962 LOGERR("tried to insert image that was not correction dimensions");
01963 return 1;
01964 }
01965
01966 Transform * transform;
01967 if ( input->has_attr("xform.projection") ) {
01968 transform = (Transform*) (input->get_attr("xform.projection"));
01969 } else {
01970 transform = new Transform(t);
01971 }
01972 EMData* slice = preprocess_slice(input, t);
01973
01974 float weight = params["weight"];
01975 slice->mult(weight);
01976
01977 EMData *tmp = new EMData();
01978 tmp->set_size(nx, ny, nz);
01979
01980 float *slice_data = slice->get_data();
01981 float *tmp_data = tmp->get_data();
01982
01983 size_t nxy = nx * ny;
01984 size_t nxy_size = nxy * sizeof(float);;
01985 for (int i = 0; i < nz; ++i) {
01986 memcpy(&tmp_data[nxy * i], slice_data, nxy_size);
01987 }
01988
01989 transform->set_scale(1.0);
01990 transform->set_mirror(false);
01991 transform->set_trans(0,0,0);
01992 transform->invert();
01993
01994 tmp->transform(*transform);
01995 image->add(*tmp);
01996
01997 if(transform) {delete transform; transform=0;}
01998 delete tmp;
01999 delete slice;
02000
02001 return 0;
02002 }
02003
02004 EMData *BackProjectionReconstructor::finish()
02005 {
02006
02007 Symmetry3D* sym = Factory<Symmetry3D>::get((string)params["sym"]);
02008 vector<Transform> syms = sym->get_syms();
02009
02010 for ( vector<Transform>::const_iterator it = syms.begin(); it != syms.end(); ++it ) {
02011
02012 EMData tmpcopy(*image);
02013 tmpcopy.transform(*it);
02014 image->add(tmpcopy);
02015 }
02016
02017 image->mult(1.0f/(float)sym->get_nsym());
02018 delete sym;
02019 return image;
02020 }
02021
02022 EMData* EMAN::padfft_slice( const EMData* const slice, const Transform& t, int npad )
02023 {
02024 int nx = slice->get_xsize();
02025 int ny = slice->get_ysize();
02026 int ndim = (ny==1) ? 1 : 2;
02027
02028 if( ndim==2 && nx!=ny )
02029 {
02030
02031 throw std::runtime_error("Tried to padfft a 2D slice which is not square.");
02032 }
02033
02034
02035 EMData* temp = slice->average_circ_sub();
02036
02037 Assert( temp != NULL );
02038 EMData* zeropadded = temp->norm_pad( false, npad );
02039 Assert( zeropadded != NULL );
02040 checked_delete( temp );
02041
02042 zeropadded->do_fft_inplace();
02043 EMData* padfftslice = zeropadded;
02044
02045
02046 Vec2f trans = t.get_trans_2d();
02047 float sx = -trans[0];
02048 float sy = -trans[1];
02049 if(sx != 0.0f || sy != 0.0)
02050 padfftslice->process_inplace("filter.shift", Dict("x_shift", sx, "y_shift", sy, "z_shift", 0.0f));
02051
02052 int remove = slice->get_attr_default("remove", 0);
02053 padfftslice->set_attr( "remove", remove );
02054
02055
02056
02057 padfftslice->center_origin_fft();
02058 return padfftslice;
02059 }
02060
02061 nn4Reconstructor::nn4Reconstructor()
02062 {
02063 m_volume = NULL;
02064 m_wptr = NULL;
02065 m_result = NULL;
02066 }
02067
02068 nn4Reconstructor::nn4Reconstructor( const string& symmetry, int size, int npad )
02069 {
02070 m_volume = NULL;
02071 m_wptr = NULL;
02072 m_result = NULL;
02073 setup( symmetry, size, npad );
02074 load_default_settings();
02075 print_params();
02076 }
02077
02078 nn4Reconstructor::~nn4Reconstructor()
02079 {
02080 if( m_delete_volume )
02081 checked_delete(m_volume);
02082
02083 if( m_delete_weight )
02084 checked_delete( m_wptr );
02085
02086 checked_delete( m_result );
02087 }
02088
02089 enum weighting_method { NONE, ESTIMATE, VORONOI };
02090
02091 float max2d( int kc, const vector<float>& pow_a )
02092 {
02093 float max = 0.0;
02094 for( int i=-kc; i <= kc; ++i ) {
02095 for( int j=-kc; j <= kc; ++j ) {
02096 if( i==0 && j==0 ) continue;
02097 {
02098 int c = 2*kc+1 - std::abs(i) - std::abs(j);
02099 max = max + pow_a[c];
02100 }
02101 }
02102 }
02103 return max;
02104 }
02105
02106 float max3d( int kc, const vector<float>& pow_a )
02107 {
02108 float max = 0.0;
02109 for( int i=-kc; i <= kc; ++i ) {
02110 for( int j=-kc; j <= kc; ++j ) {
02111 for( int k=-kc; k <= kc; ++k ) {
02112 if( i==0 && j==0 && k==0 ) continue;
02113
02114 {
02115 int c = 3*kc+1 - std::abs(i) - std::abs(j) - std::abs(k);
02116 max = max + pow_a[c];
02117
02118
02119 }
02120 }
02121 }
02122 }
02123 return max;
02124 }
02125
02126
02127 void nn4Reconstructor::setup()
02128 {
02129 int size = params["size"];
02130 int npad = params["npad"];
02131
02132
02133 string symmetry;
02134 if( params.has_key("symmetry") ) {
02135 symmetry = params["symmetry"].to_str();
02136 } else {
02137 symmetry = "c1";
02138 }
02139
02140 if( params.has_key("ndim") ) {
02141 m_ndim = params["ndim"];
02142 } else {
02143 m_ndim = 3;
02144 }
02145
02146 if( params.has_key( "snr" ) ) {
02147 m_osnr = 1.0f/float( params["snr"] );
02148 } else {
02149 m_osnr = 0.0;
02150 }
02151
02152 setup( symmetry, size, npad );
02153 }
02154
02155 void nn4Reconstructor::setup( const string& symmetry, int size, int npad )
02156 {
02157 m_weighting = ESTIMATE;
02158 m_wghta = 0.2f;
02159
02160 m_symmetry = symmetry;
02161 m_npad = npad;
02162 m_nsym = Transform::get_nsym(m_symmetry);
02163
02164 m_vnx = size;
02165 m_vny = size;
02166 m_vnz = (m_ndim==3) ? size : 1;
02167
02168 m_vnxp = size*npad;
02169 m_vnyp = size*npad;
02170 m_vnzp = (m_ndim==3) ? size*npad : 1;
02171
02172 m_vnxc = m_vnxp/2;
02173 m_vnyc = m_vnyp/2;
02174 m_vnzc = (m_ndim==3) ? m_vnzp/2 : 1;
02175
02176 buildFFTVolume();
02177 buildNormVolume();
02178
02179 }
02180
02181
02182 void nn4Reconstructor::buildFFTVolume() {
02183 int offset = 2 - m_vnxp%2;
02184
02185 if( params.has_key("fftvol") ) {
02186 m_volume = params["fftvol"];
02187 m_delete_volume = false;
02188 } else {
02189 m_volume = new EMData();
02190 m_delete_volume = true;
02191 }
02192
02193 if( m_volume->get_xsize() != m_vnxp+offset &&
02194 m_volume->get_ysize() != m_vnyp &&
02195 m_volume->get_zsize() != m_vnzp ) {
02196 m_volume->set_size(m_vnxp+offset,m_vnyp,m_vnzp);
02197 m_volume->to_zero();
02198 }
02199
02200
02201
02202
02203 if ( m_vnxp % 2 == 0 ) m_volume->set_fftodd(0);
02204 else m_volume->set_fftodd(1);
02205
02206
02207 m_volume->set_nxc(m_vnxp/2);
02208 m_volume->set_complex(true);
02209 m_volume->set_ri(true);
02210 m_volume->set_fftpad(true);
02211 m_volume->set_attr("npad", m_npad);
02212 m_volume->set_array_offsets(0,1,1);
02213 }
02214
02215 void nn4Reconstructor::buildNormVolume() {
02216
02217 if( params.has_key("weight") ) {
02218 m_wptr = params["weight"];
02219 m_delete_weight = false;
02220 } else {
02221 m_wptr = new EMData();
02222 m_delete_weight = true;
02223 }
02224
02225 if( m_wptr->get_xsize() != m_vnxc+1 &&
02226 m_wptr->get_ysize() != m_vnyp &&
02227 m_wptr->get_zsize() != m_vnzp ) {
02228 m_wptr->set_size(m_vnxc+1,m_vnyp,m_vnzp);
02229 m_wptr->to_zero();
02230 }
02231
02232 m_wptr->set_array_offsets(0,1,1);
02233 }
02234
02235 void printImage( const EMData* line )
02236 {
02237 Assert( line->get_zsize()==1 );
02238
02239
02240 int nx = line->get_xsize();
02241 int ny = line->get_ysize();
02242 for( int j=0; j < ny; ++j ) {
02243 for( int i=0; i < nx; ++i ) printf( "%10.3f ", line->get_value_at(i,j) );
02244 printf( "\n" );
02245 }
02246 }
02247
02248
02249
02250 int nn4Reconstructor::insert_slice(const EMData* const slice, const Transform& t) {
02251
02252 if (!slice) {
02253 LOGERR("try to insert NULL slice");
02254 return 1;
02255 }
02256
02257 int padffted= slice->get_attr_default( "padffted", 0 );
02258 if( m_ndim==3 ) {
02259 if ( padffted==0 && (slice->get_xsize()!=slice->get_ysize() || slice->get_xsize()!=m_vnx) ) {
02260
02261 LOGERR("Tried to insert a slice that is the wrong size.");
02262 return 1;
02263 }
02264 } else {
02265 Assert( m_ndim==2 );
02266 if( slice->get_ysize() !=1 ) {
02267 LOGERR( "for 2D reconstruction, a line is excepted" );
02268 return 1;
02269 }
02270 }
02271
02272 EMData* padfft = NULL;
02273
02274 if( padffted != 0 ) padfft = new EMData(*slice);
02275 else padfft = padfft_slice( slice, t, m_npad );
02276
02277 int mult= slice->get_attr_default( "mult", 1 );
02278 Assert( mult > 0 );
02279
02280 if( m_ndim==3 ) {
02281 insert_padfft_slice( padfft, t, mult );
02282 } else {
02283 float alpha = padfft->get_attr( "alpha" );
02284 alpha = alpha/180.0f*M_PI;
02285 for(int i=0; i < m_vnxc+1; ++i ) {
02286 float xnew = i*cos(alpha);
02287 float ynew = -i*sin(alpha);
02288 float btqr = padfft->get_value_at( 2*i, 0, 0 );
02289 float btqi = padfft->get_value_at( 2*i+1, 0, 0 );
02290 if( xnew < 0.0 ) {
02291 xnew *= -1;
02292 ynew *= -1;
02293 btqi *= -1;
02294 }
02295
02296 int ixn = int(xnew+0.5+m_vnxp) - m_vnxp;
02297 int iyn = int(ynew+0.5+m_vnyp) - m_vnyp;
02298
02299 if(iyn < 0 ) iyn += m_vnyp;
02300
02301 (*m_volume)( 2*ixn, iyn+1, 1 ) += btqr *float(mult);
02302 (*m_volume)( 2*ixn+1, iyn+1, 1 ) += btqi * float(mult);
02303 (*m_wptr)(ixn,iyn+1, 1) += float(mult);
02304 }
02305
02306 }
02307 checked_delete( padfft );
02308 return 0;
02309 }
02310
02311 int nn4Reconstructor::insert_padfft_slice( EMData* padfft, const Transform& t, int mult )
02312 {
02313 Assert( padfft != NULL );
02314
02315 for (int isym=0; isym < m_nsym; isym++) {
02316 Transform tsym = t.get_sym(m_symmetry, isym);
02317 m_volume->nn( m_wptr, padfft, tsym, mult);
02318 }
02319 return 0;
02320 }
02321
02322 #define tw(i,j,k) tw[ i-1 + (j-1+(k-1)*iy)*ix ]
02323
02324 void circumference( EMData* win )
02325 {
02326 float *tw = win->get_data();
02327
02328 int ix = win->get_xsize();
02329 int iy = win->get_ysize();
02330 int iz = win->get_zsize();
02331 int L2 = (ix/2)*(ix/2);
02332 int L2P = (ix/2-1)*(ix/2-1);
02333
02334 int IP = ix/2+1;
02335 int JP = iy/2+1;
02336 int KP = iz/2+1;
02337
02338 float TNR = 0.0f;
02339 size_t m = 0;
02340 for (int k = 1; k <= iz; ++k) {
02341 for (int j = 1; j <= iy; ++j) {
02342 for (int i = 1; i <= ix; ++i) {
02343 size_t LR = (k-KP)*(k-KP)+(j-JP)*(j-JP)+(i-IP)*(i-IP);
02344 if (LR<=(size_t)L2) {
02345 if(LR >= (size_t)L2P && LR <= (size_t)L2) {
02346 TNR += tw(i,j,k);
02347 ++m;
02348 }
02349 }
02350 }
02351 }
02352 }
02353
02354 TNR /=float(m);
02355 for (int k = 1; k <= iz; ++k) {
02356 for (int j = 1; j <= iy; ++j) {
02357 for (int i = 1; i <= ix; ++i) {
02358 size_t LR = (k-KP)*(k-KP)+(j-JP)*(j-JP)+(i-IP)*(i-IP);
02359 if (LR<=(size_t)L2) tw(i,j,k) -= TNR; else tw(i,j,k) = 0.0f;
02360 }
02361 }
02362 }
02363
02364 }
02365
02366
02367 EMData* nn4Reconstructor::finish()
02368 {
02369 if( m_ndim==3 ) {
02370 m_volume->symplane0(m_wptr);
02371 } else {
02372 for( int i=1; i <= m_vnyp; ++i ) {
02373
02374 if( (*m_wptr)(0, i, 1)==0.0 ) {
02375 int j = m_vnyp + 1 - i;
02376 (*m_wptr)(0, i, 1) = (*m_wptr)(0, j, 1);
02377 (*m_volume)(0, i, 1) = (*m_volume)(0, j, 1);
02378 (*m_volume)(1, i, 1) = (*m_volume)(1, j, 1);
02379 }
02380 }
02381 }
02382
02383
02384 int box = 7;
02385 int kc = (box-1)/2;
02386 vector< float > pow_a( m_ndim*kc+1, 1.0 );
02387 for( unsigned int i=1; i < pow_a.size(); ++i ) pow_a[i] = pow_a[i-1] * exp(m_wghta);
02388 pow_a.back()=0.0;
02389
02390 float alpha = 0.0;
02391 if( m_ndim==3) {
02392 int vol = box*box*box;
02393 float max = max3d( kc, pow_a );
02394 alpha = ( 1.0f - 1.0f/(float)vol ) / max;
02395 } else {
02396 int ara = box*box;
02397 float max = max2d( kc, pow_a );
02398 alpha = ( 1.0f - 1.0f/(float)ara ) / max;
02399 }
02400
02401 int ix,iy,iz;
02402 for (iz = 1; iz <= m_vnzp; iz++) {
02403 for (iy = 1; iy <= m_vnyp; iy++) {
02404 for (ix = 0; ix <= m_vnxc; ix++) {
02405 if ( (*m_wptr)(ix,iy,iz) > 0) {
02406 float tmp;
02407 tmp = (-2*((ix+iy+iz)%2)+1)/((*m_wptr)(ix,iy,iz)+m_osnr);
02408
02409 if( m_weighting == ESTIMATE ) {
02410 int cx = ix;
02411 int cy = (iy<=m_vnyc) ? iy - 1 : iy - 1 - m_vnyp;
02412 int cz = (iz<=m_vnzc) ? iz - 1 : iz - 1 - m_vnzp;
02413 float sum = 0.0;
02414 for( int ii = -kc; ii <= kc; ++ii ) {
02415 int nbrcx = cx + ii;
02416 if( nbrcx >= m_vnxc ) continue;
02417 for( int jj= -kc; jj <= kc; ++jj ) {
02418 int nbrcy = cy + jj;
02419 if( nbrcy <= -m_vnyc || nbrcy >= m_vnyc ) continue;
02420
02421 int kcz = (m_ndim==3) ? kc : 0;
02422 for( int kk = -kcz; kk <= kcz; ++kk ) {
02423 int nbrcz = cz + kk;
02424 if( nbrcz <= -m_vnyc || nbrcz >= m_vnyc ) continue;
02425 if( nbrcx < 0 ) {
02426 nbrcx = -nbrcx;
02427 nbrcy = -nbrcy;
02428 nbrcz = -nbrcz;
02429 }
02430 int nbrix = nbrcx;
02431 int nbriy = nbrcy >= 0 ? nbrcy + 1 : nbrcy + 1 + m_vnyp;
02432 int nbriz = nbrcz >= 0 ? nbrcz + 1 : nbrcz + 1 + m_vnzp;
02433 if( (*m_wptr)( nbrix, nbriy, nbriz ) == 0 ) {
02434 int c = m_ndim*kc+1 - std::abs(ii) - std::abs(jj) - std::abs(kk);
02435 sum = sum + pow_a[c];
02436 }
02437 }
02438 }
02439 }
02440 float wght = 1.0f / ( 1.0f - alpha * sum );
02441 tmp = tmp * wght;
02442 }
02443 (*m_volume)(2*ix,iy,iz) *= tmp;
02444 (*m_volume)(2*ix+1,iy,iz) *= tmp;
02445 }
02446 }
02447 }
02448 }
02449
02450
02451
02452
02453 m_volume->do_ift_inplace();
02454
02455
02456 m_volume->depad();
02457 circumference( m_volume );
02458 m_volume->set_array_offsets( 0, 0, 0 );
02459
02460 m_result = m_volume->copy();
02461 return m_result;
02462 }
02463 #undef tw
02464
02465
02466
02467
02468
02469 nnSSNR_Reconstructor::nnSSNR_Reconstructor()
02470 {
02471 m_volume = NULL;
02472 m_wptr = NULL;
02473 m_wptr2 = NULL;
02474 m_result = NULL;
02475 }
02476
02477 nnSSNR_Reconstructor::nnSSNR_Reconstructor( const string& symmetry, int size, int npad)
02478 {
02479 m_volume = NULL;
02480 m_wptr = NULL;
02481 m_wptr2 = NULL;
02482 m_result = NULL;
02483
02484 setup( symmetry, size, npad );
02485 }
02486
02487 nnSSNR_Reconstructor::~nnSSNR_Reconstructor()
02488 {
02489 if( m_delete_volume ) checked_delete(m_volume);
02490
02491 if( m_delete_weight ) checked_delete( m_wptr );
02492
02493 if( m_delete_weight2 ) checked_delete( m_wptr2 );
02494
02495 checked_delete( m_result );
02496 }
02497
02498 void nnSSNR_Reconstructor::setup()
02499 {
02500 int size = params["size"];
02501 int npad = params["npad"];
02502
02503 string symmetry;
02504 if( params.has_key("symmetry") ) symmetry = params["symmetry"].to_str();
02505 else symmetry = "c1";
02506
02507 setup( symmetry, size, npad );
02508 }
02509
02510 void nnSSNR_Reconstructor::setup( const string& symmetry, int size, int npad )
02511 {
02512
02513 m_weighting = ESTIMATE;
02514 m_wghta = 0.2f;
02515 m_wghtb = 0.004f;
02516
02517 m_symmetry = symmetry;
02518 m_npad = npad;
02519 m_nsym = Transform::get_nsym(m_symmetry);
02520
02521 m_vnx = size;
02522 m_vny = size;
02523 m_vnz = size;
02524
02525 m_vnxp = size*npad;
02526 m_vnyp = size*npad;
02527 m_vnzp = size*npad;
02528
02529 m_vnxc = m_vnxp/2;
02530 m_vnyc = m_vnyp/2;
02531 m_vnzc = m_vnzp/2;
02532
02533 buildFFTVolume();
02534 buildNormVolume();
02535 buildNorm2Volume();
02536
02537 }
02538
02539 void nnSSNR_Reconstructor::buildFFTVolume() {
02540
02541 if( params.has_key("fftvol") ) {
02542 m_volume = params["fftvol"];
02543 m_delete_volume = false;
02544 } else {
02545 m_volume = new EMData();
02546 m_delete_volume = true;
02547 }
02548 m_volume->set_size(m_vnxp+ 2 - m_vnxp%2,m_vnyp,m_vnzp);
02549 m_volume->to_zero();
02550 if ( m_vnxp % 2 == 0 ) m_volume->set_fftodd(0);
02551 else m_volume->set_fftodd(1);
02552
02553 m_volume->set_nxc(m_vnxc);
02554 m_volume->set_complex(true);
02555 m_volume->set_ri(true);
02556 m_volume->set_fftpad(true);
02557 m_volume->set_attr("npad", m_npad);
02558 m_volume->set_array_offsets(0,1,1);
02559 }
02560
02561 void nnSSNR_Reconstructor::buildNormVolume() {
02562 if( params.has_key("weight") ) {
02563 m_wptr = params["weight"];
02564 m_delete_weight = false;
02565 } else {
02566 m_wptr = new EMData();
02567 m_delete_weight = true;
02568 }
02569
02570 m_wptr->set_size(m_vnxc+1,m_vnyp,m_vnzp);
02571 m_wptr->to_zero();
02572
02573 m_wptr->set_array_offsets(0,1,1);
02574 }
02575
02576 void nnSSNR_Reconstructor::buildNorm2Volume() {
02577
02578 if( params.has_key("weight2") ) {
02579 m_wptr2 = params["weight2"];
02580 m_delete_weight2 = false;
02581 } else {
02582 m_wptr2 = new EMData();
02583 m_delete_weight2 = true;
02584 }
02585 m_wptr2->set_size(m_vnxc+1,m_vnyp,m_vnzp);
02586 m_wptr2->to_zero();
02587 m_wptr2->set_array_offsets(0,1,1);
02588 }
02589
02590
02591 int nnSSNR_Reconstructor::insert_slice(const EMData* const slice, const Transform& t) {
02592
02593 if (!slice) {
02594 LOGERR("try to insert NULL slice");
02595 return 1;
02596 }
02597
02598 int padffted=slice->get_attr_default( "padffted", 0 );
02599
02600 if ( padffted==0 && (slice->get_xsize()!=slice->get_ysize() || slice->get_xsize()!=m_vnx) ) {
02601
02602 LOGERR("Tried to insert a slice that has wrong size.");
02603 return 1;
02604 }
02605
02606 EMData* padfft = NULL;
02607
02608 if( padffted != 0 ) padfft = new EMData(*slice);
02609 else padfft = padfft_slice( slice, t, m_npad );
02610
02611 int mult = slice->get_attr_default("mult", 1);
02612
02613 Assert( mult > 0 );
02614 insert_padfft_slice( padfft, t, mult );
02615
02616 checked_delete( padfft );
02617 return 0;
02618 }
02619
02620 int nnSSNR_Reconstructor::insert_padfft_slice( EMData* padfft, const Transform& t, int mult )
02621 {
02622 Assert( padfft != NULL );
02623
02624 for (int isym=0; isym < m_nsym; isym++) {
02625 Transform tsym = t.get_sym(m_symmetry, isym);
02626 m_volume->nn_SSNR( m_wptr, m_wptr2, padfft, tsym, mult);
02627 }
02628 return 0;
02629 }
02630
02631
02632 #define tw(i,j,k) tw[ i-1 + (j-1+(k-1)*iy)*ix ]
02633 EMData* nnSSNR_Reconstructor::finish()
02634 {
02635
02636
02637
02638
02639
02640
02641 int kz, ky;
02642
02643 int box = 7;
02644 int kc = (box-1)/2;
02645 float alpha = 0.0;
02646 float argx, argy, argz;
02647 vector< float > pow_a( 3*kc+1, 1.0 );
02648 float w = params["w"];
02649 EMData* SSNR = params["SSNR"];
02650
02651
02652
02653
02654 EMData* vol_ssnr = new EMData();
02655 vol_ssnr->set_size(m_vnxp+ 2 - m_vnxp%2, m_vnyp ,m_vnzp);
02656 vol_ssnr->to_zero();
02657 if ( m_vnxp % 2 == 0 ) vol_ssnr->set_fftodd(0);
02658 else vol_ssnr->set_fftodd(1);
02659 vol_ssnr->set_nxc(m_vnxc);
02660 vol_ssnr->set_complex(true);
02661 vol_ssnr->set_ri(true);
02662 vol_ssnr->set_fftpad(false);
02663
02664
02665 float dx2 = 1.0f/float(m_vnxc)/float(m_vnxc);
02666 float dy2 = 1.0f/float(m_vnyc)/float(m_vnyc);
02667 #ifdef _WIN32
02668 float dz2 = 1.0f/_cpp_max(float(m_vnzc),1.0f)/_cpp_max(float(m_vnzc),1.0f);
02669 int inc = Util::round(float(_cpp_max(_cpp_max(m_vnxc,m_vnyc),m_vnzc))/w);
02670 #else
02671 float dz2 = 1.0f/std::max(float(m_vnzc),1.0f)/std::max(float(m_vnzc),1.0f);
02672 int inc = Util::round(float(std::max(std::max(m_vnxc,m_vnyc),m_vnzc))/w);
02673 #endif //_WIN32
02674 SSNR->set_size(inc+1,4,1);
02675
02676 float *nom = new float[inc+1];
02677 float *denom = new float[inc+1];
02678 int *nn = new int[inc+1];
02679 int *ka = new int[inc+1];
02680 float wght = 1.0f;
02681 for (int i = 0; i <= inc; i++) {
02682 nom[i] = 0.0f;
02683 denom[i] = 0.0f;
02684 nn[i] = 0;
02685 ka[i] = 0;
02686 }
02687
02688 m_volume->symplane1(m_wptr, m_wptr2);
02689
02690 if ( m_weighting == ESTIMATE ) {
02691 int vol = box*box*box;
02692 for( unsigned int i=1; i < pow_a.size(); ++i ) pow_a[i] = pow_a[i-1] * exp(m_wghta);
02693 pow_a[3*kc] = 0.0;
02694 float max = max3d( kc, pow_a );
02695 alpha = ( 1.0f - 1.0f/(float)vol ) / max;
02696 }
02697
02698 for (int iz = 1; iz <= m_vnzp; iz++) {
02699 if ( iz-1 > m_vnzc ) kz = iz-1-m_vnzp; else kz = iz-1;
02700 argz = float(kz*kz)*dz2;
02701 for (int iy = 1; iy <= m_vnyp; iy++) {
02702 if ( iy-1 > m_vnyc ) ky = iy-1-m_vnyp; else ky = iy-1;
02703 argy = argz + float(ky*ky)*dy2;
02704 for (int ix = 0; ix <= m_vnxc; ix++) {
02705 float Kn = (*m_wptr)(ix,iy,iz);
02706 argx = std::sqrt(argy + float(ix*ix)*dx2);
02707 int r = Util::round(float(inc)*argx);
02708 if ( r >= 0 && Kn > 4.5f ) {
02709 if ( m_weighting == ESTIMATE ) {
02710 int cx = ix;
02711 int cy = (iy<=m_vnyc) ? iy - 1 : iy - 1 - m_vnyp;
02712 int cz = (iz<=m_vnzc) ? iz - 1 : iz - 1 - m_vnzp;
02713
02714 float sum = 0.0;
02715 for( int ii = -kc; ii <= kc; ++ii ) {
02716 int nbrcx = cx + ii;
02717 if( nbrcx >= m_vnxc ) continue;
02718 for ( int jj= -kc; jj <= kc; ++jj ) {
02719 int nbrcy = cy + jj;
02720 if( nbrcy <= -m_vnyc || nbrcy >= m_vnyc ) continue;
02721 for( int kk = -kc; kk <= kc; ++kk ) {
02722 int nbrcz = cz + jj;
02723 if ( nbrcz <= -m_vnyc || nbrcz >= m_vnyc ) continue;
02724 if( nbrcx < 0 ) {
02725 nbrcx = -nbrcx;
02726 nbrcy = -nbrcy;
02727 nbrcz = -nbrcz;
02728 }
02729 int nbrix = nbrcx;
02730 int nbriy = nbrcy >= 0 ? nbrcy + 1 : nbrcy + 1 + m_vnyp;
02731 int nbriz = nbrcz >= 0 ? nbrcz + 1 : nbrcz + 1 + m_vnzp;
02732 if( (*m_wptr)( nbrix, nbriy, nbriz ) == 0 ) {
02733 int c = 3*kc+1 - std::abs(ii) - std::abs(jj) - std::abs(kk);
02734 sum = sum + pow_a[c];
02735 }
02736 }
02737 }
02738 }
02739 wght = 1.0f / ( 1.0f - alpha * sum );
02740 }
02741 float nominator = std::norm(m_volume->cmplx(ix,iy,iz))/Kn;
02742 float denominator = ((*m_wptr2)(ix,iy,iz)-nominator)/(Kn-1.0f);
02743
02744 if( (ix>0 || (kz>=0 && (ky>=0 || kz!=0)))) {
02745 if ( r <= inc ) {
02746 nom[r] += nominator*wght;
02747 denom[r] += denominator/Kn*wght;
02748 nn[r] += 2;
02749 ka[r] += int(Kn);
02750 }
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767 }
02768 (*vol_ssnr)(2*ix, iy-1, iz-1) = denominator*wght;
02769
02770
02771 }
02772 }
02773 }
02774 }
02775
02776 for (int i = 0; i <= inc; i++) {
02777 (*SSNR)(i,0,0) = nom[i];
02778 (*SSNR)(i,1,0) = denom[i];
02779 (*SSNR)(i,2,0) = static_cast<float>(nn[i]);
02780 (*SSNR)(i,3,0) = static_cast<float>(ka[i]);
02781 }
02782 vol_ssnr->update();
02783 return vol_ssnr;
02784 }
02785 #undef tw
02786
02787
02788
02789
02790
02791
02792
02793 nn4_ctfReconstructor::nn4_ctfReconstructor()
02794 {
02795 m_volume = NULL;
02796 m_wptr = NULL;
02797 m_result = NULL;
02798 }
02799
02800 nn4_ctfReconstructor::nn4_ctfReconstructor( const string& symmetry, int size, int npad, float snr, int sign )
02801 {
02802 setup( symmetry, size, npad, snr, sign );
02803 }
02804
02805 nn4_ctfReconstructor::~nn4_ctfReconstructor()
02806 {
02807 if( m_delete_volume ) checked_delete(m_volume);
02808
02809 if( m_delete_weight ) checked_delete( m_wptr );
02810
02811 checked_delete( m_result );
02812 }
02813
02814 void nn4_ctfReconstructor::setup()
02815 {
02816 if( ! params.has_key("size") ) throw std::logic_error("Error: image size is not given");
02817
02818 int size = params["size"];
02819 int npad = params.has_key("npad") ? int(params["npad"]) : 4;
02820
02821 int sign = 1;
02822 string symmetry = params.has_key("symmetry")? params["symmetry"].to_str() : "c1";
02823
02824 float snr = params["snr"];
02825
02826 m_varsnr = params.has_key("varsnr") ? int(params["varsnr"]) : 0;
02827 setup( symmetry, size, npad, snr, sign );
02828
02829 }
02830
02831 void nn4_ctfReconstructor::setup( const string& symmetry, int size, int npad, float snr, int sign )
02832 {
02833 m_weighting = ESTIMATE;
02834 if( params.has_key("weighting") ) {
02835 int tmp = int( params["weighting"] );
02836 if( tmp==0 ) m_weighting = NONE;
02837 }
02838
02839
02840
02841 m_wghta = 0.2f;
02842 m_wghtb = 0.004f;
02843
02844 m_symmetry = symmetry;
02845 m_npad = npad;
02846 m_sign = sign;
02847 m_nsym = Transform::get_nsym(m_symmetry);
02848
02849 m_snr = snr;
02850
02851 m_vnx = size;
02852 m_vny = size;
02853 m_vnz = size;
02854
02855 m_vnxp = size*npad;
02856 m_vnyp = size*npad;
02857 m_vnzp = size*npad;
02858
02859 m_vnxc = m_vnxp/2;
02860 m_vnyc = m_vnyp/2;
02861 m_vnzc = m_vnzp/2;
02862
02863 buildFFTVolume();
02864 buildNormVolume();
02865 }
02866
02867 void nn4_ctfReconstructor::buildFFTVolume() {
02868 int offset = 2 - m_vnxp%2;
02869 if( params.has_key("fftvol") ) {
02870 m_volume = params["fftvol"];
02871 m_delete_volume = false;
02872 } else {
02873 m_volume = new EMData();
02874 m_delete_volume = true;
02875 }
02876
02877 if( m_volume->get_xsize() != m_vnxp+offset &&
02878 m_volume->get_ysize() != m_vnyp &&
02879 m_volume->get_zsize() != m_vnzp )
02880 {
02881 m_volume->set_size(m_vnxp+offset,m_vnyp,m_vnzp);
02882 m_volume->to_zero();
02883 }
02884
02885 m_volume->set_nxc(m_vnxp/2);
02886 m_volume->set_complex(true);
02887 m_volume->set_ri(true);
02888 m_volume->set_fftpad(true);
02889 m_volume->set_attr("npad", m_npad);
02890 m_volume->set_array_offsets(0,1,1);
02891 }
02892
02893 void nn4_ctfReconstructor::buildNormVolume()
02894 {
02895 if( params.has_key("weight") )
02896 {
02897 m_wptr = params["weight"];
02898 m_delete_weight = false;
02899 } else {
02900 m_wptr = new EMData();
02901 m_delete_weight = true;
02902 }
02903
02904 if( m_wptr->get_xsize() != m_vnxc+1 &&
02905 m_wptr->get_ysize() != m_vnyp &&
02906 m_wptr->get_zsize() != m_vnzp )
02907 {
02908 m_wptr->set_size(m_vnxc+1,m_vnyp,m_vnzp);
02909 m_wptr->to_zero();
02910 }
02911
02912 m_wptr->set_array_offsets(0,1,1);
02913
02914 }
02915
02916 int nn4_ctfReconstructor::insert_slice(const EMData* const slice, const Transform& t)
02917 {
02918
02919 if (!slice) {
02920 LOGERR("try to insert NULL slice");
02921 return 1;
02922 }
02923
02924 int buffed = slice->get_attr_default( "buffed", 0 );
02925 if( buffed > 0 )
02926 {
02927 int mult = slice->get_attr_default( "mult", 1 );
02928 insert_buffed_slice( slice, mult );
02929 return 0;
02930 }
02931
02932 int padffted= slice->get_attr_default("padffted", 0);
02933 if( padffted==0 && (slice->get_xsize()!=slice->get_ysize() || slice->get_xsize()!=m_vnx) )
02934 {
02935
02936 LOGERR("Tried to insert a slice that is the wrong size.");
02937 return 1;
02938 }
02939
02940 EMData* padfft = NULL;
02941
02942 if( padffted != 0 ) padfft = new EMData(*slice);
02943 else padfft = padfft_slice( slice, t, m_npad );
02944
02945 int mult= slice->get_attr_default("mult", 1);
02946
02947 Assert( mult > 0 );
02948 insert_padfft_slice( padfft, t, mult );
02949
02950 checked_delete( padfft );
02951
02952 return 0;
02953 }
02954
02955 int nn4_ctfReconstructor::insert_buffed_slice( const EMData* buffed, int mult )
02956 {
02957 const float* bufdata = buffed->get_data();
02958 float* cdata = m_volume->get_data();
02959 float* wdata = m_wptr->get_data();
02960
02961 int npoint = buffed->get_xsize()/4;
02962 for( int i=0; i < npoint; ++i ) {
02963
02964 int pos2 = int( bufdata[4*i] );
02965 int pos1 = pos2 * 2;
02966 cdata[pos1 ] += bufdata[4*i+1]*mult;
02967 cdata[pos1+1] += bufdata[4*i+2]*mult;
02968 wdata[pos2 ] += bufdata[4*i+3]*mult;
02969
02970
02971
02972
02973
02974 }
02975 return 0;
02976 }
02977
02978 int nn4_ctfReconstructor::insert_padfft_slice( EMData* padfft, const Transform& t, int mult )
02979 {
02980 Assert( padfft != NULL );
02981 float tmp = padfft->get_attr("ctf_applied");
02982 int ctf_applied = (int) tmp;
02983
02984 for( int isym=0; isym < m_nsym; isym++) {
02985 Transform tsym = t.get_sym( m_symmetry, isym );
02986
02987 if(ctf_applied) m_volume->nn_ctf_applied(m_wptr, padfft, tsym, mult);
02988 else m_volume->nn_ctf(m_wptr, padfft, tsym, mult);
02989 }
02990
02991 return 0;
02992
02993 }
02994
02995 #define tw(i,j,k) tw[ i-1 + (j-1+(k-1)*iy)*ix ]
02996 EMData* nn4_ctfReconstructor::finish()
02997 {
02998 m_volume->set_array_offsets(0, 1, 1);
02999 m_wptr->set_array_offsets(0, 1, 1);
03000 m_volume->symplane0_ctf(m_wptr);
03001
03002 int box = 7;
03003 int vol = box*box*box;
03004 int kc = (box-1)/2;
03005 vector< float > pow_a( 3*kc+1, 1.0 );
03006 for( unsigned int i=1; i < pow_a.size(); ++i ) pow_a[i] = pow_a[i-1] * exp(m_wghta);
03007 pow_a[3*kc]=0.0;
03008
03009
03010 float max = max3d( kc, pow_a );
03011 float alpha = ( 1.0f - 1.0f/(float)vol ) / max;
03012 float osnr = 1.0f/m_snr;
03013
03014
03015 int ix,iy,iz;
03016 for (iz = 1; iz <= m_vnzp; iz++) {
03017 for (iy = 1; iy <= m_vnyp; iy++) {
03018 for (ix = 0; ix <= m_vnxc; ix++) {
03019 if ( (*m_wptr)(ix,iy,iz) > 0.0f) {
03020 int iyp = (iy<=m_vnyc) ? iy - 1 : iy-m_vnyp-1;
03021 int izp = (iz<=m_vnzc) ? iz - 1 : iz-m_vnzp-1;
03022 float tmp=0.0;
03023 if( m_varsnr )
03024 {
03025 float freq = sqrt( (float)(ix*ix+iyp*iyp+izp*izp) );
03026 tmp = (-2*((ix+iy+iz)%2)+1)/((*m_wptr)(ix,iy,iz)+freq*osnr)*m_sign;
03027 }
03028 else
03029 {
03030 tmp = (-2*((ix+iy+iz)%2)+1)/((*m_wptr)(ix,iy,iz)+osnr)*m_sign;
03031 }
03032
03033 if( m_weighting == ESTIMATE ) {
03034 int cx = ix;
03035 int cy = (iy<=m_vnyc) ? iy - 1 : iy - 1 - m_vnyp;
03036 int cz = (iz<=m_vnzc) ? iz - 1 : iz - 1 - m_vnzp;
03037 float sum = 0.0;
03038 for( int ii = -kc; ii <= kc; ++ii ) {
03039 int nbrcx = cx + ii;
03040 if( nbrcx >= m_vnxc ) continue;
03041 for( int jj= -kc; jj <= kc; ++jj ) {
03042 int nbrcy = cy + jj;
03043 if( nbrcy <= -m_vnyc || nbrcy >= m_vnyc ) continue;
03044 for( int kk = -kc; kk <= kc; ++kk ) {
03045 int nbrcz = cz + jj;
03046 if( nbrcz <= -m_vnyc || nbrcz >= m_vnyc ) continue;
03047 if( nbrcx < 0 ) {
03048 nbrcx = -nbrcx;
03049 nbrcy = -nbrcy;
03050 nbrcz = -nbrcz;
03051 }
03052
03053 int nbrix = nbrcx;
03054 int nbriy = nbrcy >= 0 ? nbrcy + 1 : nbrcy + 1 + m_vnyp;
03055 int nbriz = nbrcz >= 0 ? nbrcz + 1 : nbrcz + 1 + m_vnzp;
03056 if( (*m_wptr)( nbrix, nbriy, nbriz ) == 0.0 ) {
03057 int c = 3*kc+1 - std::abs(ii) - std::abs(jj) - std::abs(kk);
03058 sum = sum + pow_a[c];
03059
03060
03061 }
03062 }
03063 }
03064 }
03065 float wght = 1.0f / ( 1.0f - alpha * sum );
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075 tmp = tmp * wght;
03076 }
03077 (*m_volume)(2*ix,iy,iz) *= tmp;
03078 (*m_volume)(2*ix+1,iy,iz) *= tmp;
03079 }
03080 }
03081 }
03082 }
03083
03084
03085 m_volume->do_ift_inplace();
03086 m_volume->depad();
03087 circumference( m_volume );
03088 m_volume->set_array_offsets( 0, 0, 0 );
03089 m_result = m_volume->copy();
03090 return m_result;
03091 }
03092 #undef tw
03093
03094
03095
03096
03097
03098
03099
03100
03101 nnSSNR_ctfReconstructor::nnSSNR_ctfReconstructor()
03102 {
03103 m_volume = NULL;
03104 m_wptr = NULL;
03105 m_wptr2 = NULL;
03106 m_wptr3 = NULL;
03107 m_result = NULL;
03108 }
03109
03110 nnSSNR_ctfReconstructor::nnSSNR_ctfReconstructor( const string& symmetry, int size, int npad, float snr, int sign)
03111 {
03112 m_volume = NULL;
03113 m_wptr = NULL;
03114 m_wptr2 = NULL;
03115 m_wptr3 = NULL;
03116 m_result = NULL;
03117
03118 setup( symmetry, size, npad, snr, sign );
03119 }
03120
03121 nnSSNR_ctfReconstructor::~nnSSNR_ctfReconstructor()
03122 {
03123
03124 if( m_delete_volume )
03125 checked_delete(m_volume);
03126 if( m_delete_weight )
03127 checked_delete( m_wptr );
03128 if ( m_delete_weight2 )
03129 checked_delete( m_wptr2 );
03130 if ( m_delete_weight3 )
03131 checked_delete( m_wptr3 );
03132 checked_delete( m_result );
03133 }
03134
03135 void nnSSNR_ctfReconstructor::setup()
03136 {
03137 int size = params["size"];
03138 int npad = params["npad"];
03139 int sign = params["sign"];
03140 float snr = params["snr"];
03141 string symmetry;
03142 if( params.has_key("symmetry") ) {
03143 symmetry = params["symmetry"].to_str();
03144 } else {
03145 symmetry = "c1";
03146 }
03147 setup( symmetry, size, npad, snr, sign );
03148 }
03149 void nnSSNR_ctfReconstructor::setup( const string& symmetry, int size, int npad, float snr, int sign )
03150 {
03151
03152 m_weighting = ESTIMATE;
03153 m_wghta = 0.2f;
03154 m_wghtb = 0.004f;
03155 wiener = 1;
03156
03157 m_symmetry = symmetry;
03158 m_npad = npad;
03159 m_nsym = Transform::get_nsym(m_symmetry);
03160
03161 m_sign = sign;
03162 m_snr = snr;
03163
03164 m_vnx = size;
03165 m_vny = size;
03166 m_vnz = size;
03167
03168 m_vnxp = size*npad;
03169 m_vnyp = size*npad;
03170 m_vnzp = size*npad;
03171
03172 m_vnxc = m_vnxp/2;
03173 m_vnyc = m_vnyp/2;
03174 m_vnzc = m_vnzp/2;
03175
03176 buildFFTVolume();
03177 buildNormVolume();
03178 buildNorm2Volume();
03179 buildNorm3Volume();
03180 }
03181
03182 void nnSSNR_ctfReconstructor::buildFFTVolume() {
03183
03184 int offset = 2 - m_vnxp%2;
03185 if( params.has_key("fftvol") ) {
03186 m_volume = params["fftvol"];
03187 m_delete_volume = false;
03188 } else {
03189 m_volume = new EMData();
03190 m_delete_volume = true;
03191 }
03192
03193 m_volume->set_size(m_vnxp+offset,m_vnyp,m_vnzp);
03194 m_volume->to_zero();
03195
03196 if ( m_vnxp % 2 == 0 ) {
03197 m_volume->set_fftodd(0);
03198 } else {
03199 m_volume->set_fftodd(1);
03200 }
03201
03202 m_volume->set_nxc(m_vnxc);
03203 m_volume->set_complex(true);
03204 m_volume->set_ri(true);
03205 m_volume->set_fftpad(true);
03206 m_volume->set_attr("npad", m_npad);
03207 m_volume->set_array_offsets(0,1,1);
03208 }
03209
03210
03211 void nnSSNR_ctfReconstructor::buildNormVolume()
03212 {
03213 if( params.has_key("weight") ) {
03214 m_wptr = params["weight"];
03215 m_delete_weight = false;
03216 } else {
03217 m_wptr = new EMData();
03218 m_delete_weight = true;
03219 }
03220 m_wptr->set_size(m_vnxc+1,m_vnyp,m_vnzp);
03221