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 "projector.h"
00037 #include "emdata.h"
00038 #include "interp.h"
00039 #include "emutil.h"
00040 #include "plugins/projector_template.h"
00041
00042 #ifdef WIN32
00043 #define M_PI 3.14159265358979323846f
00044 #endif //WIN32
00045
00046 #ifdef EMAN2_USING_CUDA
00047 #include "cuda/cuda_util.h"
00048 #include "cuda/cuda_projector.h"
00049 #endif
00050
00051 using namespace std;
00052 using namespace EMAN;
00053
00054 const string GaussFFTProjector::NAME = "gauss_fft";
00055 const string FourierGriddingProjector::NAME = "fourier_gridding";
00056 const string PawelProjector::NAME = "pawel";
00057 const string StandardProjector::NAME = "standard";
00058 const string ChaoProjector::NAME = "chao";
00059
00060 template <> Factory < Projector >::Factory()
00061 {
00062 force_add<GaussFFTProjector>();
00063 force_add<PawelProjector>();
00064 force_add<StandardProjector>();
00065 force_add<FourierGriddingProjector>();
00066 force_add<ChaoProjector>();
00067
00068
00069 }
00070
00071 EMData *GaussFFTProjector::project3d(EMData * image) const
00072 {
00073 Transform* t3d = params["transform"];
00074 if ( t3d == NULL ) throw NullPointerException("The transform object (required for projection), was not specified");
00075 if ( image->get_ndim() != 3 ) throw ImageDimensionException("Error, the projection volume must be 3D");
00076
00077 EMData *f = image;
00078 if (!image->is_complex()) {
00079 image->process_inplace("xform.phaseorigin.tocorner");
00080 f = image->do_fft();
00081 f->process_inplace("xform.fourierorigin.tocenter");
00082 image->process_inplace("xform.phaseorigin.tocenter");
00083 }
00084
00085 int f_nx = f->get_xsize();
00086 int f_ny = f->get_ysize();
00087 int f_nz = f->get_zsize();
00088
00089 if (!f->is_complex() || f_nz != f_ny || f_nx != f_ny + 2) {
00090 LOGERR("Cannot project this image");
00091 return 0;
00092 }
00093
00094 f->ap2ri();
00095
00096 EMData *tmp = new EMData();
00097 tmp->set_size(f_nx, f_ny, 1);
00098 tmp->set_complex(true);
00099 tmp->set_ri(true);
00100
00101 float *data = tmp->get_data();
00102
00103 Transform r = t3d->get_rotation_transform();
00104 r.invert();
00105 float scale = t3d->get_scale();
00106
00107 int mode = params["mode"];
00108 float gauss_width = 1;
00109 if ( mode == 0 ) mode = 2;
00110 if (mode == 2 ) {
00111 gauss_width = EMConsts::I2G;
00112 }
00113 else if (mode == 3) {
00114 gauss_width = EMConsts::I3G;
00115 }
00116 else if (mode == 4) {
00117 gauss_width = EMConsts::I4G;
00118 }
00119 else if (mode == 6 || mode == 7) {
00120 gauss_width = EMConsts::I5G;
00121 }
00122
00123 for (int y = 0; y < f_ny; y++) {
00124 for (int x = 0; x < f_nx / 2; x++) {
00125 int ii = x * 2 + y * f_nx;
00126 #ifdef _WIN32
00127 if (_hypot(x, y - f_ny / 2) >= f_ny / 2 - 1) {
00128 #else
00129 if (hypot(x, y - f_ny / 2) >= f_ny / 2 - 1) {
00130 #endif //_WIN32
00131 data[ii] = 0;
00132 data[ii + 1] = 0;
00133 }
00134 else {
00135 Vec3f coord(x,(y - f_ny / 2),0);
00136 Vec3f soln = r*coord;
00137 float xx = soln[0];
00138 float yy = soln[1];
00139 float zz = soln[2];
00140
00141 int cc = 1;
00142 if (xx < 0) {
00143 xx = -xx;
00144 yy = -yy;
00145 zz = -zz;
00146 cc = -1;
00147 }
00148
00149 if (scale != 1.0) {
00150 xx *= scale;
00151 yy *= scale;
00152 zz *= scale;
00153 }
00154
00155 yy += f_ny / 2;
00156 zz += f_nz / 2;
00157
00158 if (yy < 0 || xx < 0 || zz < 0) {
00159 data[ii] = 0;
00160 data[ii+1] = 0;
00161 continue;
00162 }
00163
00164 if (interp_ft_3d(mode, f, xx, yy, zz, data + ii, gauss_width)) {
00165 data[ii + 1] *= cc;
00166 } else {
00167 data[ii] = 0;
00168 data[ii+1] = 0;
00169 }
00170 }
00171 }
00172 }
00173
00174 f->update();
00175 tmp->update();
00176
00177 tmp->process_inplace("xform.fourierorigin.tocorner");
00178 EMData *ret = tmp->do_ift();
00179 ret->process_inplace("xform.phaseorigin.tocenter");
00180
00181 ret->translate(t3d->get_trans());
00182
00183 if (t3d->get_mirror() ) ret->process_inplace("xform.flip",Dict("axis","x"));
00184
00185 Dict filter_d;
00186 filter_d["gauss_width"] = gauss_width;
00187 filter_d["ring_width"] = ret->get_xsize() / 2;
00188 ret->process_inplace("math.gausskernelfix", filter_d);
00189
00190 if( tmp )
00191 {
00192 delete tmp;
00193 tmp = 0;
00194 }
00195
00196 ret->set_attr("xform.projection",t3d);
00197 ret->update();
00198
00199 if(t3d) {delete t3d; t3d=0;}
00200
00201 return ret;
00202 }
00203
00204
00205
00206 bool GaussFFTProjector::interp_ft_3d(int mode, EMData * image, float x, float y,
00207 float z, float *data, float gw) const
00208 {
00209 float *rdata = image->get_data();
00210 int nx = image->get_xsize();
00211 int ny = image->get_ysize();
00212 int nz = image->get_zsize();
00213
00214 if ( mode == 0 ) mode = 2;
00215
00216 if (mode == 1) {
00217 int x0 = 2 * (int) floor(x + 0.5f);
00218 int y0 = (int) floor(y + 0.5f);
00219 int z0 = (int) floor(z + 0.5f);
00220
00221 data[0] = rdata[x0 + y0 * nx + z0 * nx * ny];
00222 data[1] = rdata[x0 + y0 * nx + z0 * nx * ny + 1];
00223 return true;
00224 }
00225 else if (mode == 2) {
00226 int x0 = (int) floor(x);
00227 int y0 = (int) floor(y);
00228 int z0 = (int) floor(z);
00229
00230 float dx = x - x0;
00231 float dy = y - y0;
00232 float dz = z - z0;
00233
00234 if (x0 <= nx/2- 2 && y0 <= ny - 1 && z0 <= nz - 1) {
00235 int i = (int) (x0 * 2 + y0 * nx + z0 * nx * ny);
00236
00237 float n = Util::agauss(1, dx, dy, dz, gw) +
00238 Util::agauss(1, 1 - dx, dy, dz, gw) +
00239 Util::agauss(1, dx, 1 - dy, dz, gw) +
00240 Util::agauss(1, 1 - dx, 1 - dy, dz, gw) +
00241 Util::agauss(1, dx, dy, 1 - dz, gw) +
00242 Util::agauss(1, 1 - dx, dy, 1 - dz, gw) +
00243 Util::agauss(1, dx, 1 - dy, 1 - dz, gw) + Util::agauss(1, 1 - dx, 1 - dy, 1 - dz, gw);
00244
00245 data[0] = Util::agauss(rdata[i], dx, dy, dz, gw) +
00246 Util::agauss(rdata[i + 2], 1 - dx, dy, dz, gw) +
00247 Util::agauss(rdata[i + nx], dx, 1 - dy, dz, gw) +
00248 Util::agauss(rdata[i + nx + 2], 1 - dx, 1 - dy, dz, gw) +
00249 Util::agauss(rdata[i + nx * ny], dx, dy, 1 - dz, gw) +
00250 Util::agauss(rdata[i + 2 + nx * ny], 1 - dx, dy, 1 - dz, gw) +
00251 Util::agauss(rdata[i + nx + nx * ny], dx, 1 - dy, 1 - dz, gw) +
00252 Util::agauss(rdata[i + 2 + nx + nx * ny], 1 - dx, 1 - dy, 1 - dz, gw) / n;
00253
00254 i++;
00255
00256 data[1] = Util::agauss(rdata[i], dx, dy, dz, gw) +
00257 Util::agauss(rdata[i + 2], 1 - dx, dy, dz, gw) +
00258 Util::agauss(rdata[i + nx], dx, 1 - dy, dz, gw) +
00259 Util::agauss(rdata[i + nx + 2], 1 - dx, 1 - dy, dz, gw) +
00260 Util::agauss(rdata[i + nx * ny], dx, dy, 1 - dz, gw) +
00261 Util::agauss(rdata[i + 2 + nx * ny], 1 - dx, dy, 1 - dz, gw) +
00262 Util::agauss(rdata[i + nx + nx * ny], dx, 1 - dy, 1 - dz, gw) +
00263 Util::agauss(rdata[i + 2 + nx + nx * ny], 1 - dx, 1 - dy, 1 - dz, gw) / n;
00264 return true;
00265 }
00266 return false;
00267 }
00268 else if (mode == 3) {
00269 int x0 = 2 * (int) floor(x + .5);
00270 int y0 = (int) floor(y + .5);
00271 int z0 = (int) floor(z + .5);
00272
00273 float *supp = image->setup4slice();
00274
00275 if (x0 < nx - 4 && y0 <= ny - 3 && z0 <= nz - 3 && y0 >= 2 && z0 >= 2) {
00276 float n = 0;
00277
00278 if (x0 == 0) {
00279 x0 += 4;
00280 size_t idx;
00281 float r, g;
00282 for (int k = z0 - 1; k <= z0 + 1; k++) {
00283 for (int j = y0 - 1; j <= y0 + 1; j++) {
00284 for (int i = x0 - 2; i <= x0 + 2; i += 2) {
00285 r = Util::hypot3sq(i / 2.0f - x - 2.0f, j - y, k - z);
00286 g = exp(-r / gw);
00287 n += g;
00288 idx = i + j * 12 + (size_t)k * 12 * ny;
00289 data[0] += supp[idx] * g;
00290 data[1] += supp[idx + 1] * g;
00291 }
00292 }
00293 }
00294 }
00295 else {
00296 size_t idx;
00297 float r, g;
00298 for (int k = z0 - 1; k <= z0 + 1; k++) {
00299 for (int j = y0 - 1; j <= y0 + 1; j++) {
00300 for (int i = x0 - 2; i <= x0 + 2; i += 2) {
00301 r = Util::hypot3sq(i / 2.0f - x, j - y, k - z);
00302 g = exp(-r / gw);
00303 n += g;
00304 idx = i + j * nx + (size_t)k * nx * ny;
00305 data[0] += rdata[idx] * g;
00306 data[1] += rdata[idx + 1] * g;
00307 }
00308 }
00309 }
00310 }
00311
00312 data[0] /= n;
00313 data[1] /= n;
00314 return true;
00315 }
00316 return false;
00317 }
00318 else if (mode == 4) {
00319 int x0 = 2 * (int) floor(x);
00320 int y0 = (int) floor(y);
00321 int z0 = (int) floor(z);
00322
00323 float *supp = image->setup4slice();
00324
00325 if (x0 < nx - 4 && y0 <= ny - 3 && z0 <= nz - 3 && y0 >= 2 && z0 >= 2) {
00326 float n = 0;
00327
00328 if (x0 == 0) {
00329 x0 += 4;
00330 size_t idx;
00331 float r, g;
00332 for (int k = z0 - 1; k <= z0 + 2; k++) {
00333 for (int j = y0 - 1; j <= y0 + 2; j++) {
00334 for (int i = x0 - 2; i <= x0 + 4; i += 2) {
00335 r = Util::hypot3sq(i / 2.0f - x - 2.0f, j - y, k - z);
00336 g = exp(-r / gw);
00337 n += g;
00338 idx = i + j * 12 + (size_t)k * 12 * ny;
00339 data[0] += supp[idx] * g;
00340 data[1] += supp[idx + 1] * g;
00341 }
00342 }
00343 }
00344 }
00345 else {
00346 float r, g;
00347 size_t idx;
00348 for (int k = z0 - 1; k <= z0 + 2; k++) {
00349 for (int j = y0 - 1; j <= y0 + 2; j++) {
00350 for (int i = x0 - 2; i <= x0 + 4; i += 2) {
00351 r = Util::hypot3sq(i / 2.0f - x, j - y, k - z);
00352 g = exp(-r / gw);
00353 n += g;
00354 idx = i + j * nx + (size_t)k * nx * ny;
00355 data[0] += rdata[idx] * g;
00356 data[1] += rdata[idx + 1] * g;
00357 }
00358 }
00359 }
00360 }
00361 data[0] /= n;
00362 data[1] /= n;
00363 return true;
00364 }
00365 return false;
00366 }
00367 else if (mode == 5) {
00368 int x0 = 2 * (int) floor(x + .5);
00369 int y0 = (int) floor(y + .5);
00370 int z0 = (int) floor(z + .5);
00371
00372 float *supp = image->setup4slice();
00373 float *gimx = Interp::get_gimx();
00374
00375 if (x0 < nx - 4 && y0 <= ny - 3 && z0 <= nz - 3 && y0 >= 2 && z0 >= 2) {
00376 int mx0 = -(int) floor((x - x0 / 2) * 39.0 + .5) - 78;
00377 int my0 = -(int) floor((y - y0) * 39.0 + .5) - 78;
00378 int mz0 = -(int) floor((z - z0) * 39.0 + .5) - 78;
00379
00380 float n = 0;
00381 int mmz = mz0;
00382 int mmy = my0;
00383 int mmx = mx0;
00384
00385 if (x0 < 4) {
00386 x0 += 4;
00387
00388 size_t idx;
00389 float g;
00390 for (int k = z0 - 2; k <= z0 + 2; k++, mmz += 39) {
00391 for (int j = y0 - 2; j <= y0 + 2; j++, mmy += 39) {
00392 for (int i = x0 - 4; i <= x0 + 4; i += 2, mmx += 39) {
00393 g = gimx[abs(mmx) + abs(mmy) * 100 + abs(mmz) * 10000];
00394 n += g;
00395 idx = i + j * 12 + (size_t)k * 12 * ny;
00396 data[0] += supp[idx] * g;
00397 data[1] += supp[idx + 1] * g;
00398 }
00399 }
00400 }
00401 }
00402 else {
00403 size_t ii;
00404 float g;
00405 for (int k = z0 - 2; k <= z0 + 2; k++, mmz += 39) {
00406 for (int j = y0 - 2; j <= y0 + 2; j++, mmy += 39) {
00407 for (int i = x0 - 4; i <= x0 + 4; i += 2, mmx += 39) {
00408 ii = i + j * nx + (size_t)k * nx * ny;
00409 g = gimx[abs(mmx) + abs(mmy) * 100 + abs(mmz) * 10000];
00410 n += g;
00411 data[0] += rdata[ii] * g;
00412 data[1] += rdata[ii + 1] * g;
00413 }
00414 }
00415 }
00416 }
00417
00418 data[0] /= n;
00419 data[1] /= n;
00420 return true;
00421 }
00422 return false;
00423 }
00424 else if (mode == 6) {
00425
00426 int x0 = 2 * (int) floor(x + .5);
00427 int y0 = (int) floor(y + .5);
00428 int z0 = (int) floor(z + .5);
00429
00430 float *supp = image->setup4slice();
00431
00432 if (x0 < nx - 4 && y0 <= ny - 3 && z0 <= nz - 3 && y0 >= 2 && z0 >= 2) {
00433 float n = 0;
00434
00435 if (x0 < 4) {
00436 x0 += 4;
00437 float r, g;
00438 size_t idx;
00439 for (int k = z0 - 2; k <= z0 + 2; k++) {
00440 for (int j = y0 - 2; j <= y0 + 2; j++) {
00441 for (int i = x0 - 4; i <= x0 + 4; i += 2) {
00442 r = Util::hypot3sq(i / 2.0f - x - 2.0f, j - y, k - z);
00443 g = exp(-r / gw);
00444 n += g;
00445 idx = i + j * 12 + (size_t)k * 12 * ny;
00446 data[0] += supp[idx] * g;
00447 data[1] += supp[idx + 1] * g;
00448 }
00449 }
00450 }
00451 }
00452 else {
00453 float r, g;
00454 size_t idx;
00455 for (int k = z0 - 2; k <= z0 + 2; k++) {
00456 for (int j = y0 - 2; j <= y0 + 2; j++) {
00457 for (int i = x0 - 4; i <= x0 + 4; i += 2) {
00458 r = Util::hypot3sq(i / 2.0f - x, j - y, k - z);
00459 g = exp(-r / gw);
00460 n += g;
00461 idx = i + j * nx + (size_t)k * nx * ny;
00462 data[0] += rdata[idx] * g;
00463 data[1] += rdata[idx + 1] * g;
00464 }
00465
00466 }
00467 }
00468 }
00469
00470 data[0] /= n;
00471 data[1] /= n;
00472
00473 return true;
00474 }
00475 return false;
00476 }
00477 else if (mode == 7) {
00478 int x0 = 2 * (int) floor(x + .5);
00479 int y0 = (int) floor(y + .5);
00480 int z0 = (int) floor(z + .5);
00481
00482 float *supp = image->setup4slice();
00483
00484 if (x0 < nx - 4 && y0 <= ny - 3 && z0 <= nz - 3 && y0 >= 2 && z0 >= 2) {
00485 float n = 0;
00486 if (x0 < 4) {
00487 x0 += 4;
00488 float r, g;
00489 size_t idx;
00490 for (int k = z0 - 2; k <= z0 + 2; k++) {
00491 for (int j = y0 - 2; j <= y0 + 2; j++) {
00492 for (int i = x0 - 4; i <= x0 + 4; i += 2) {
00493 r = sqrt(Util::hypot3sq(i / 2.0f - x - 2.0f, j - y, k - z));
00494 g = Interp::hyperg(r);
00495 n += g;
00496 idx = i + j * 12 + (size_t)k * 12 * ny;
00497 data[0] += supp[idx] * g;
00498 data[1] += supp[idx + 1] * g;
00499 }
00500 }
00501 }
00502 }
00503 else {
00504 float r, g;
00505 size_t idx;
00506 for (int k = z0 - 2; k <= z0 + 2; k++) {
00507 for (int j = y0 - 2; j <= y0 + 2; j++) {
00508 for (int i = x0 - 4; i <= x0 + 4; i += 2) {
00509 r = sqrt(Util::hypot3sq(i / 2.0f - x, j - y, k - z));
00510 g = Interp::hyperg(r);
00511 n += g;
00512 idx = i + j * nx + (size_t)k * nx * ny;
00513 data[0] += rdata[idx] * g;
00514 data[1] += rdata[idx + 1] * g;
00515 }
00516
00517 }
00518 }
00519 }
00520 data[0] /= n;
00521 data[1] /= n;
00522 return true;
00523 }
00524 return false;
00525
00526 }
00527
00528 return false;
00529 }
00530
00531 void PawelProjector::prepcubes(int, int ny, int nz, int ri, Vec3i origin,
00532 int& nn, IPCube* ipcube) const {
00533 const float r = float(ri*ri);
00534 const int ldpx = origin[0];
00535 const int ldpy = origin[1];
00536 const int ldpz = origin[2];
00537 float t;
00538 nn = -1;
00539 for (int i1 = 0; i1 < nz; i1++) {
00540 t = float(i1 - ldpz);
00541 const float xx = t*t;
00542 for (int i2 = 0; i2 < ny; i2++) {
00543 t = float(i2 - ldpy);
00544 const float yy = t*t + xx;
00545 bool first = true;
00546 for (int i3 = 0; i3 < nz; i3++) {
00547 t = float(i3 - ldpx);
00548 const float rc = t*t + yy;
00549 if (first) {
00550
00551 if (rc > r) continue;
00552 first = false;
00553 nn++;
00554 if (ipcube != NULL) {
00555 ipcube[nn].start = i3;
00556 ipcube[nn].end = i3;
00557 ipcube[nn].loc[0] = i3 - ldpx;
00558 ipcube[nn].loc[1] = i2 - ldpy;
00559 ipcube[nn].loc[2] = i1 - ldpz;
00560 }
00561 } else {
00562
00563 if (ipcube != NULL) {
00564 if (rc <= r) ipcube[nn].end = i3;
00565 }
00566 }
00567 }
00568 }
00569 }
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 EMData *PawelProjector::project3d(EMData * image) const
00724 {
00725 if (!image) {
00726 return 0;
00727 }
00728 int ri;
00729 int nx = image->get_xsize();
00730 int ny = image->get_ysize();
00731 int nz = image->get_zsize();
00732 int dim = Util::get_min(nx,ny,nz);
00733 if (nz == 1) {
00734 LOGERR("The PawelProjector needs a volume!");
00735 return 0;
00736 }
00737 Vec3i origin(0,0,0);
00738
00739
00740 if (params.has_key("origin_x")) {origin[0] = params["origin_x"];}
00741 else {origin[0] = nx/2;}
00742 if (params.has_key("origin_y")) {origin[1] = params["origin_y"];}
00743 else {origin[1] = ny/2;}
00744 if (params.has_key("origin_z")) {origin[2] = params["origin_z"];}
00745 else {origin[2] = nz/2;}
00746
00747 if (params.has_key("radius")) {ri = params["radius"];}
00748 else {ri = dim/2 - 1;}
00749
00750
00751 int nn = -1;
00752 prepcubes(nx, ny, nz, ri, origin, nn);
00753
00754
00755 IPCube* ipcube = new IPCube[nn+1];
00756 prepcubes(nx, ny, nz, ri, origin, nn, ipcube);
00757
00758 Transform* rotation = params["transform"];
00759 int nangles = 0;
00760 vector<float> anglelist;
00761
00762
00763
00764
00765
00766
00767
00768 if ( rotation == NULL ) throw NullPointerException("The transform object (required for projection), was not specified");
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780 nangles = 1;
00781
00782
00783
00784 EMData* ret = new EMData();
00785 ret->set_size(nx, ny, nangles);
00786 ret->to_zero();
00787
00788
00789 for (int ia = 0; ia < nangles; ia++) {
00790
00791
00792
00793 if (2*(ri+1)+1 > dim) {
00794
00795 for (int i = 0 ; i <= nn; i++) {
00796 int k = ipcube[i].loc[1] + origin[1];
00797 Vec3f vb = ipcube[i].loc*(*rotation) + origin;
00798 for (int j = ipcube[i].start; j <= ipcube[i].end; j++) {
00799
00800 int iox = int(vb[0]);
00801 if ((iox >= 0) && (iox < nx-1)) {
00802 int ioy = int(vb[1]);
00803 if ((ioy >= 0) && (ioy < ny-1)) {
00804 int ioz = int(vb[2]);
00805 if ((ioz >= 0) && (ioz < nz-1)) {
00806
00807 float dx = vb[0] - iox;
00808 float dy = vb[1] - ioy;
00809 float dz = vb[2] - ioz;
00810 float a1 = (*image)(iox,ioy,ioz);
00811 float a2 = (*image)(iox+1,ioy,ioz) - a1;
00812 float a3 = (*image)(iox,ioy+1,ioz) - a1;
00813 float a4 = (*image)(iox,ioy,ioz+1) - a1;
00814 float a5 = -a2 -(*image)(iox,ioy+1,ioz)
00815 + (*image)(iox+1,ioy+1,ioz);
00816 float a61 = -(*image)(iox,ioy,ioz+1)
00817 + (*image)(iox+1,ioy,ioz+1);
00818 float a6 = -a2 + a61;
00819 float a7 = -a3 - (*image)(iox,ioy,ioz+1)
00820 + (*image)(iox,ioy+1,ioz+1);
00821 float a8 = -a5 - a61 - (*image)(iox,ioy+1,ioz+1)
00822 + (*image)(iox+1,ioy+1,ioz+1);
00823 (*ret)(j,k,ia) += a1 + dz*(a4 + a6*dx
00824 + (a7 + a8*dx)*dy)
00825 + a3*dy + dx*(a2 + a5*dy);
00826 }
00827 }
00828 }
00829 vb += rotation->get_matrix3_row(0);
00830 }
00831 }
00832
00833 } else {
00834
00835 for (int i = 0 ; i <= nn; i++) {
00836 int k = ipcube[i].loc[1] + origin[1];
00837 Vec3f vb = ipcube[i].loc*(*rotation) + origin;
00838 for (int j = ipcube[i].start; j <= ipcube[i].end; j++) {
00839 int iox = int(vb[0]);
00840 int ioy = int(vb[1]);
00841 int ioz = int(vb[2]);
00842 float dx = vb[0] - iox;
00843 float dy = vb[1] - ioy;
00844 float dz = vb[2] - ioz;
00845 float a1 = (*image)(iox,ioy,ioz);
00846 float a2 = (*image)(iox+1,ioy,ioz) - a1;
00847 float a3 = (*image)(iox,ioy+1,ioz) - a1;
00848 float a4 = (*image)(iox,ioy,ioz+1) - a1;
00849 float a5 = -a2 -(*image)(iox,ioy+1,ioz)
00850 + (*image)(iox+1,ioy+1,ioz);
00851 float a61 = -(*image)(iox,ioy,ioz+1)
00852 + (*image)(iox+1,ioy,ioz+1);
00853 float a6 = -a2 + a61;
00854 float a7 = -a3 - (*image)(iox,ioy,ioz+1)
00855 + (*image)(iox,ioy+1,ioz+1);
00856 float a8 = -a5 - a61 - (*image)(iox,ioy+1,ioz+1)
00857 + (*image)(iox+1,ioy+1,ioz+1);
00858 (*ret)(j,k,ia) += a1 + dz*(a4 + a6*dx
00859 + (a7 + a8*dx)*dy)
00860 + a3*dy + dx*(a2 + a5*dy);
00861 vb += rotation->get_matrix3_row(0);
00862 }
00863 }
00864 }
00865 }
00866 ret->update();
00867 EMDeleteArray(ipcube);
00868 if(rotation) {delete rotation; rotation=0;}
00869 return ret;
00870 }
00871
00872 EMData *StandardProjector::project3d(EMData * image) const
00873 {
00874 Transform* t3d = params["transform"];
00875 if ( t3d == NULL ) throw NullPointerException("The transform object containing the angles(required for projection), was not specified");
00876
00877 if ( image->get_ndim() == 3 )
00878 {
00879
00880 #ifdef EMAN2_USING_CUDA
00881 if(EMData::usecuda == 1) {
00882 if(!image->isrodataongpu()) image->copy_to_cudaro();
00883
00884 Transform* t3d = params["transform"];
00885 if ( t3d == NULL ) throw NullPointerException("The transform object containing the angles(required for projection), was not specified");
00886 float * m = new float[12];
00887 t3d->copy_matrix_into_array(m);
00888 image->bindcudaarrayA(true);
00889 EMData* e = new EMData(0,0,image->get_xsize(),image->get_ysize(),1);
00890
00891
00892 e->rw_alloc();
00893 standard_project(m,e->getcudarwdata(), e->get_xsize(), e->get_ysize());
00894 image->unbindcudaarryA();
00895 delete [] m;
00896
00897 e->update();
00898 e->set_attr("xform.projection",t3d);
00899
00900 if(t3d) {delete t3d; t3d=0;}
00901 return e;
00902 }
00903 #endif
00904 int nx = image->get_xsize();
00905 int ny = image->get_ysize();
00906 int nz = image->get_zsize();
00907
00908
00909 Transform r = t3d->inverse();
00910 int xy = nx * ny;
00911
00912 EMData *proj = new EMData();
00913 proj->set_size(nx, ny, 1);
00914
00915 Vec3i offset(nx/2,ny/2,nz/2);
00916
00917 float *sdata = image->get_data();
00918 float *ddata = proj->get_data();
00919 for (int k = -nz / 2; k < nz - nz / 2; k++) {
00920 int l = 0;
00921 for (int j = -ny / 2; j < ny - ny / 2; j++) {
00922 ddata[l]=0;
00923 for (int i = -nx / 2; i < nx - nx / 2; i++,l++) {
00924
00925 Vec3f coord(i,j,k);
00926 Vec3f soln = r*coord;
00927 soln += offset;
00928
00932
00933
00934 float x2 = soln[0];
00935 float y2 = soln[1];
00936 float z2 = soln[2];
00937
00938 float x = (float)Util::fast_floor(x2);
00939 float y = (float)Util::fast_floor(y2);
00940 float z = (float)Util::fast_floor(z2);
00941
00942 float t = x2 - x;
00943 float u = y2 - y;
00944 float v = z2 - z;
00945
00946 size_t ii = (size_t) ((size_t)x + (size_t)y * nx + (size_t)z * xy);
00947
00948 if (x2 < 0 || y2 < 0 || z2 < 0 ) continue;
00949 if (x2 > (nx-1) || y2 > (ny-1) || z2 > (nz-1) ) continue;
00950
00951 if (x2 < (nx - 1) && y2 < (ny - 1) && z2 < (nz - 1)) {
00952 ddata[l] +=
00953 Util::trilinear_interpolate(sdata[ii], sdata[ii + 1], sdata[ii + nx],
00954 sdata[ii + nx + 1], sdata[ii + xy], sdata[ii + xy + 1], sdata[ii + xy + nx],
00955 sdata[ii + xy + nx + 1], t, u, v);
00956 }
00957 else if ( x2 == (nx - 1) && y2 == (ny - 1) && z2 == (nz - 1) ) {
00958 ddata[l] += sdata[ii];
00959 }
00960 else if ( x2 == (nx - 1) && y2 == (ny - 1) ) {
00961 ddata[l] += Util::linear_interpolate(sdata[ii], sdata[ii + xy],v);
00962 }
00963 else if ( x2 == (nx - 1) && z2 == (nz - 1) ) {
00964 ddata[l] += Util::linear_interpolate(sdata[ii], sdata[ii + nx],u);
00965 }
00966 else if ( y2 == (ny - 1) && z2 == (nz - 1) ) {
00967 ddata[l] += Util::linear_interpolate(sdata[ii], sdata[ii + 1],t);
00968 }
00969 else if ( x2 == (nx - 1) ) {
00970 ddata[l] += Util::bilinear_interpolate(sdata[ii], sdata[ii + nx], sdata[ii + xy], sdata[ii + xy + nx],u,v);
00971 }
00972 else if ( y2 == (ny - 1) ) {
00973 ddata[l] += Util::bilinear_interpolate(sdata[ii], sdata[ii + 1], sdata[ii + xy], sdata[ii + xy + 1],t,v);
00974 }
00975 else if ( z2 == (nz - 1) ) {
00976 ddata[l] += Util::bilinear_interpolate(sdata[ii], sdata[ii + 1], sdata[ii + nx], sdata[ii + nx + 1],t,u);
00977 }
00978 }
00979 }
00980 }
00981 proj->update();
00982 proj->set_attr("xform.projection",t3d);
00983 proj->set_attr("apix_x",(float)image->get_attr("apix_x"));
00984 proj->set_attr("apix_y",(float)image->get_attr("apix_y"));
00985 proj->set_attr("apix_z",(float)image->get_attr("apix_z"));
00986
00987 if(t3d) {delete t3d; t3d=0;}
00988 return proj;
00989 }
00990 else if ( image->get_ndim() == 2 ) {
00991
00992 Transform r = t3d->inverse();
00993
00994 int nx = image->get_xsize();
00995 int ny = image->get_ysize();
00996
00997 EMData *proj = new EMData();
00998 proj->set_size(nx, 1, 1);
00999 proj->to_zero();
01000
01001 float *sdata = image->get_data();
01002 float *ddata = proj->get_data();
01003
01004 Vec2f offset(nx/2,ny/2);
01005 for (int j = -ny / 2; j < ny - ny / 2; j++) {
01006 int l = 0;
01007 for (int i = -nx / 2; i < nx - nx / 2; i++,l++) {
01008
01009 Vec2f coord(i,j);
01010 Vec2f soln = r*coord;
01011 soln += offset;
01012
01013 float x2 = soln[0];
01014 float y2 = soln[1];
01015
01016 float x = (float)Util::fast_floor(x2);
01017 float y = (float)Util::fast_floor(y2);
01018
01019 int ii = (int) (x + y * nx);
01020 float u = x2 - x;
01021 float v = y2 - y;
01022
01023 if (x2 < 0 || y2 < 0 ) continue;
01024 if (x2 > (nx-1) || y2 > (ny-1) ) continue;
01025
01026 if ( x2 < (nx - 1) && y2 < (ny - 1) ) {
01027 ddata[l] += Util::bilinear_interpolate(sdata[ii], sdata[ii + 1], sdata[ii + nx],sdata[ii + nx + 1], u, v);
01028 }
01029 else if (x2 == (nx-1) && y2 == (ny-1) ) {
01030 ddata[l] += sdata[ii];
01031 }
01032 else if (x2 == (nx-1) ) {
01033 ddata[l] += Util::linear_interpolate(sdata[ii],sdata[ii + nx], v);
01034 }
01035 else if (y2 == (ny-1) ) {
01036 ddata[l] += Util::linear_interpolate(sdata[ii],sdata[ii + 1], u);
01037 }
01038 }
01039 }
01040 proj->set_attr("xform.projection",t3d);
01041 proj->update();
01042 if(t3d) {delete t3d; t3d=0;}
01043 return proj;
01044 }
01045 else throw ImageDimensionException("Standard projection works only for 2D and 3D images");
01046 }
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141 EMData *FourierGriddingProjector::project3d(EMData * image) const
01142 {
01143 if (!image) {
01144 return 0;
01145 }
01146 if (3 != image->get_ndim())
01147 throw ImageDimensionException(
01148 "FourierGriddingProjector needs a 3-D volume");
01149 if (image->is_complex())
01150 throw ImageFormatException(
01151 "FourierGriddingProjector requires a real volume");
01152 const int npad = params.has_key("npad") ? int(params["npad"]) : 2;
01153 const int nx = image->get_xsize();
01154 const int ny = image->get_ysize();
01155 const int nz = image->get_zsize();
01156 if (nx != ny || nx != nz)
01157 throw ImageDimensionException(
01158 "FourierGriddingProjector requires nx==ny==nz");
01159 const int m = Util::get_min(nx,ny,nz);
01160 const int n = m*npad;
01161
01162 int K = params["kb_K"];
01163 if ( K == 0 ) K = 6;
01164 float alpha = params["kb_alpha"];
01165 if ( alpha == 0 ) alpha = 1.25;
01166 Util::KaiserBessel kb(alpha, K, (float)(m/2), K/(2.0f*n), n);
01167
01168
01169 EMData* tmpImage = image->copy();
01170 tmpImage->divkbsinh(kb);
01171
01172
01173
01174 EMData* imgft = tmpImage->norm_pad(false, npad);
01175 imgft->do_fft_inplace();
01176 imgft->center_origin_fft();
01177 imgft->fft_shuffle();
01178 delete tmpImage;
01179
01180
01181 int nangles = 0;
01182 vector<float> anglelist;
01183
01184 if (params.has_key("anglelist")) {
01185 anglelist = params["anglelist"];
01186 nangles = anglelist.size() / 3;
01187 } else {
01188
01189
01190
01191
01192 Transform* t3d = params["transform"];
01193 if ( t3d == NULL ) throw NullPointerException("The transform object (required for projection), was not specified");
01194 Dict p = t3d->get_rotation("spider");
01195
01196 string angletype = "SPIDER";
01197 float phi = p["phi"];
01198 float theta = p["theta"];
01199 float psi = p["psi"];
01200 anglelist.push_back(phi);
01201 anglelist.push_back(theta);
01202 anglelist.push_back(psi);
01203 nangles = 1;
01204 if(t3d) {delete t3d; t3d=0;}
01205 }
01206
01207
01208
01209
01210 EMData* ret = new EMData();
01211 ret->set_size(nx, ny, nangles);
01212 ret->to_zero();
01213
01214 for (int ia = 0; ia < nangles; ia++) {
01215 int indx = 3*ia;
01216 Dict d("type","spider","phi",anglelist[indx],"theta",anglelist[indx+1],"psi",anglelist[indx+2]);
01217 Transform tf(d);
01218 EMData* proj = imgft->extract_plane(tf, kb);
01219 if (proj->is_shuffled()) proj->fft_shuffle();
01220 proj->center_origin_fft();
01221 proj->do_ift_inplace();
01222 EMData* winproj = proj->window_center(m);
01223 delete proj;
01224 for (int iy=0; iy < ny; iy++)
01225 for (int ix=0; ix < nx; ix++)
01226 (*ret)(ix,iy,ia) = (*winproj)(ix,iy);
01227 delete winproj;
01228 }
01229 delete imgft;
01230
01231 if (!params.has_key("anglelist")) {
01232 Transform* t3d = params["transform"];
01233 ret->set_attr("xform.projection",t3d);
01234 if(t3d) {delete t3d; t3d=0;}
01235 }
01236 ret->update();
01237 return ret;
01238 }
01239
01240
01241 int ChaoProjector::getnnz(Vec3i volsize, int ri, Vec3i origin, int *nrays, int *nnz) const
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255 {
01256 int ix, iy, iz, rs, r2, xs, ys, zs, xx, yy, zz;
01257 int ftm=0, status = 0;
01258
01259 r2 = ri*ri;
01260 *nnz = 0;
01261 *nrays = 0;
01262 int nx = (int)volsize[0];
01263 int ny = (int)volsize[1];
01264 int nz = (int)volsize[2];
01265
01266 int xcent = (int)origin[0];
01267 int ycent = (int)origin[1];
01268 int zcent = (int)origin[2];
01269
01270
01271 for (ix = 1; ix <=nx; ix++) {
01272 xs = ix-xcent;
01273 xx = xs*xs;
01274 for (iy = 1; iy <= ny; iy++) {
01275 ys = iy-ycent;
01276 yy = ys*ys;
01277 ftm = 1;
01278 for (iz = 1; iz <= nz; iz++) {
01279 zs = iz-zcent;
01280 zz = zs*zs;
01281 rs = xx + yy + zz;
01282 if (rs <= r2) {
01283 (*nnz)++;
01284 if (ftm) {
01285 (*nrays)++;
01286 ftm = 0;
01287 }
01288 }
01289 }
01290 }
01291 }
01292 return status;
01293 }
01294
01295 #define cube(i,j,k) cube[ ((k-1)*ny + j-1)*nx + i-1 ]
01296 #define sphere(i) sphere[(i)-1]
01297 #define cord(i,j) cord[((j)-1)*3 + (i) -1]
01298 #define ptrs(i) ptrs[(i)-1]
01299 #define dm(i) dm[(i)-1]
01300
01301 int ChaoProjector:: cb2sph(float *cube, Vec3i volsize, int ri, Vec3i origin,
01302 int nnz0, int *ptrs, int *cord, float *sphere) const
01303 {
01304 int xs, ys, zs, xx, yy, zz, rs, r2;
01305 int ix, iy, iz, jnz, nnz, nrays;
01306 int ftm = 0, status = 0;
01307
01308 int xcent = (int)origin[0];
01309 int ycent = (int)origin[1];
01310 int zcent = (int)origin[2];
01311
01312 int nx = (int)volsize[0];
01313 int ny = (int)volsize[1];
01314 int nz = (int)volsize[2];
01315
01316 r2 = ri*ri;
01317 nnz = 0;
01318 nrays = 0;
01319 ptrs(1) = 1;
01320
01321 for (ix = 1; ix <= nx; ix++) {
01322 xs = ix-xcent;
01323 xx = xs*xs;
01324 for ( iy = 1; iy <= ny; iy++ ) {
01325 ys = iy-ycent;
01326 yy = ys*ys;
01327 jnz = 0;
01328
01329 ftm = 1;
01330
01331 for (iz = 1; iz <= nz; iz++) {
01332 zs = iz-zcent;
01333 zz = zs*zs;
01334 rs = xx + yy + zz;
01335 if (rs <= r2) {
01336 jnz++;
01337 nnz++;
01338 sphere(nnz) = cube(iz, iy, ix);
01339
01340
01341 if (ftm) {
01342 nrays++;
01343 cord(1,nrays) = iz;
01344 cord(2,nrays) = iy;
01345 cord(3,nrays) = ix;
01346 ftm = 0;
01347 }
01348 }
01349 }
01350 if (jnz > 0) {
01351 ptrs(nrays+1) = ptrs(nrays) + jnz;
01352 }
01353 }
01354 }
01355 if (nnz != nnz0) status = -1;
01356 return status;
01357 }
01358
01359
01360 int ChaoProjector::sph2cb(float *sphere, Vec3i volsize, int nrays, int ri,
01361 int nnz0, int *ptrs, int *cord, float *cube) const
01362 {
01363 int status=0;
01364 int r2, i, j, ix, iy, iz, nnz;
01365
01366 int nx = (int)volsize[0];
01367 int ny = (int)volsize[1];
01368
01369
01370 r2 = ri*ri;
01371 nnz = 0;
01372 ptrs(1) = 1;
01373
01374
01375
01376
01377 nnz = 0;
01378 for (j = 1; j <= nrays; j++) {
01379 iz = cord(1,j);
01380 iy = cord(2,j);
01381 ix = cord(3,j);
01382 for (i = ptrs(j); i<=ptrs(j+1)-1; i++, iz++) {
01383 nnz++;
01384 cube(iz,iy,ix) = sphere(nnz);
01385 }
01386 }
01387 if (nnz != nnz0) status = -1;
01388 return status;
01389 }
01390
01391 #define x(i) x[(i)-1]
01392 #define y(i,j) y[(j-1)*nx + i - 1]
01393
01394
01395 int ChaoProjector::fwdpj3(Vec3i volsize, int nrays, int , float *dm,
01396 Vec3i origin, int ri, int *ptrs, int *cord,
01397 float *x, float *y) const
01398 {
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415 int iqx, iqy, i, j, xc, yc, zc;
01416 float ct, dipx, dipy, dipx1m, dipy1m, xb, yb, dm1, dm4;
01417 int status = 0;
01418
01419 int xcent = origin[0];
01420 int ycent = origin[1];
01421 int zcent = origin[2];
01422
01423 int nx = volsize[0];
01424
01425 dm1 = dm(1);
01426 dm4 = dm(4);
01427
01428 if ( nx > 2*ri ) {
01429 for (i = 1; i <= nrays; i++) {
01430 zc = cord(1,i)-zcent;
01431 yc = cord(2,i)-ycent;
01432 xc = cord(3,i)-xcent;
01433
01434 xb = zc*dm(1)+yc*dm(2)+xc*dm(3) + xcent;
01435 yb = zc*dm(4)+yc*dm(5)+xc*dm(6) + ycent;
01436
01437 for (j = ptrs(i); j< ptrs(i+1); j++) {
01438 iqx = ifix(xb);
01439 iqy = ifix(yb);
01440
01441 ct = x(j);
01442 dipx = xb - (float)(iqx);
01443 dipy = (yb - (float)(iqy)) * ct;
01444
01445 dipy1m = ct - dipy;
01446 dipx1m = 1.0f - dipx;
01447
01448 y(iqx ,iqy) = y(iqx ,iqy) + dipx1m*dipy1m;
01449 y(iqx+1,iqy) = y(iqx+1,iqy) + dipx*dipy1m;
01450 y(iqx+1,iqy+1) = y(iqx+1,iqy+1) + dipx*dipy;
01451 y(iqx ,iqy+1) = y(iqx ,iqy+1) + dipx1m*dipy;
01452
01453 xb += dm1;
01454 yb += dm4;
01455 }
01456 }
01457 }
01458 else {
01459 fprintf(stderr, " nx must be greater than 2*ri\n");
01460 exit(1);
01461 }
01462 return status;
01463 }
01464 #undef x
01465 #undef y
01466
01467 #define y(i) y[(i)-1]
01468 #define x(i,j) x[((j)-1)*nx + (i) - 1]
01469
01470
01471 int ChaoProjector::bckpj3(Vec3i volsize, int nrays, int , float *dm,
01472 Vec3i origin, int ri, int *ptrs, int *cord,
01473 float *x, float *y) const
01474 {
01475 int i, j, iqx,iqy, xc, yc, zc;
01476 float xb, yb, dx, dy, dx1m, dy1m, dxdy;
01477 int status = 0;
01478
01479 int xcent = origin[0];
01480 int ycent = origin[1];
01481 int zcent = origin[2];
01482
01483 int nx = volsize[0];
01484
01485 if ( nx > 2*ri) {
01486 for (i = 1; i <= nrays; i++) {
01487 zc = cord(1,i) - zcent;
01488 yc = cord(2,i) - ycent;
01489 xc = cord(3,i) - xcent;
01490
01491 xb = zc*dm(1)+yc*dm(2)+xc*dm(3) + xcent;
01492 yb = zc*dm(4)+yc*dm(5)+xc*dm(6) + ycent;
01493
01494 for (j = ptrs(i); j <ptrs(i+1); j++) {
01495 iqx = ifix((float)(xb));
01496 iqy = ifix((float)(yb));
01497
01498 dx = xb - (float)(iqx);
01499 dy = yb - (float)(iqy);
01500 dx1m = 1.0f - dx;
01501 dy1m = 1.0f - dy;
01502 dxdy = dx*dy;
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521 y(j) += x(iqx,iqy)
01522 + dx*(-x(iqx,iqy)+x(iqx+1,iqy))
01523 + dy*(-x(iqx,iqy)+x(iqx,iqy+1))
01524 + dxdy*( x(iqx,iqy) - x(iqx,iqy+1)
01525 -x(iqx+1,iqy) + x(iqx+1,iqy+1) );
01526
01527 xb += dm(1);
01528 yb += dm(4);
01529 }
01530 }
01531 }
01532 else {
01533 fprintf(stderr, "bckpj3: nx must be greater than 2*ri\n");
01534 }
01535
01536 return status;
01537 }
01538
01539 #undef x
01540 #undef y
01541 #undef dm
01542
01543
01544 int ChaoProjector::ifix(float a) const
01545 {
01546 int ia;
01547
01548 if (a>=0) {
01549 ia = (int)floor(a);
01550 }
01551 else {
01552 ia = (int)ceil(a);
01553 }
01554 return ia;
01555 }
01556
01557 #define dm(i,j) dm[((j)-1)*9 + (i) -1]
01558 #define anglelist(i,j) anglelist[((j)-1)*3 + (i) - 1]
01559
01560
01561 void ChaoProjector::setdm(vector<float> anglelist, string const , float *dm) const
01562 {
01563
01564 float psi, theta, phi;
01565 double cthe, sthe, cpsi, spsi, cphi, sphi;
01566 int j;
01567
01568 int nangles = anglelist.size() / 3;
01569
01570
01571 for (j = 1; j <= nangles; j++) {
01572 phi = static_cast<float>(anglelist(1,j)*dgr_to_rad);
01573 theta = static_cast<float>(anglelist(2,j)*dgr_to_rad);
01574 psi = static_cast<float>(anglelist(3,j)*dgr_to_rad);
01575
01576
01577 cthe = cos(theta);
01578 sthe = sin(theta);
01579 cpsi = cos(psi);
01580 spsi = sin(psi);
01581 cphi = cos(phi);
01582 sphi = sin(phi);
01583
01584 dm(1,j)=static_cast<float>(cphi*cthe*cpsi-sphi*spsi);
01585 dm(2,j)=static_cast<float>(sphi*cthe*cpsi+cphi*spsi);
01586 dm(3,j)=static_cast<float>(-sthe*cpsi);
01587 dm(4,j)=static_cast<float>(-cphi*cthe*spsi-sphi*cpsi);
01588 dm(5,j)=static_cast<float>(-sphi*cthe*spsi+cphi*cpsi);
01589 dm(6,j)=static_cast<float>(sthe*spsi);
01590 dm(7,j)=static_cast<float>(sthe*cphi);
01591 dm(8,j)=static_cast<float>(sthe*sphi);
01592 dm(9,j)=static_cast<float>(cthe);
01593 }
01594 }
01595 #undef anglelist
01596
01597 #define images(i,j,k) images[ ((k-1)*nyvol + j-1)*nxvol + i-1 ]
01598
01599 EMData *ChaoProjector::project3d(EMData * vol) const
01600 {
01601
01602 int nrays, nnz, status, j;
01603 float *dm;
01604 int *ptrs, *cord;
01605 float *sphere, *images;
01606
01607 int nxvol = vol->get_xsize();
01608 int nyvol = vol->get_ysize();
01609 int nzvol = vol->get_zsize();
01610 Vec3i volsize(nxvol,nyvol,nzvol);
01611
01612 int dim = Util::get_min(nxvol,nyvol,nzvol);
01613 if (nzvol == 1) {
01614 LOGERR("The ChaoProjector needs a volume!");
01615 return 0;
01616 }
01617 Vec3i origin(0,0,0);
01618
01619
01620 if (params.has_key("origin_x")) {origin[0] = params["origin_x"];}
01621 else {origin[0] = nxvol/2+1;}
01622 if (params.has_key("origin_y")) {origin[1] = params["origin_y"];}
01623 else {origin[1] = nyvol/2+1;}
01624 if (params.has_key("origin_z")) {origin[2] = params["origin_z"];}
01625 else {origin[2] = nzvol/2+1;}
01626
01627 int ri;
01628 if (params.has_key("radius")) {ri = params["radius"];}
01629 else {ri = dim/2 - 1;}
01630
01631
01632 float *cube = vol->get_data();
01633
01634
01635
01636 status = getnnz(volsize, ri, origin, &nrays, &nnz);
01637
01638
01639
01640 sphere = new float[nnz];
01641 ptrs = new int[nrays+1];
01642 cord = new int[3*nrays];
01643 if (sphere == NULL || ptrs == NULL || cord == NULL) {
01644 fprintf(stderr,"ChaoProjector::project3d, failed to allocate!\n");
01645 exit(1);
01646 }
01647 for (int i = 0; i<nnz; i++) sphere[i] = 0.0;
01648 for (int i = 0; i<nrays+1; i++) ptrs[i] = 0;
01649 for (int i = 0; i<3*nrays; i++) cord[i] = 0;
01650
01651 status = cb2sph(cube, volsize, ri, origin, nnz, ptrs, cord, sphere);
01652
01653
01654 int nangles = 0;
01655 vector<float> anglelist;
01656 string angletype = "SPIDER";
01657
01658 if (params.has_key("anglelist")) {
01659 anglelist = params["anglelist"];
01660 nangles = anglelist.size() / 3;
01661 } else {
01662 Transform* t3d = params["transform"];
01663 if ( t3d == NULL ) throw NullPointerException("The transform object (required for projection), was not specified");
01664
01665
01666
01667
01668 Dict p = t3d->get_rotation("spider");
01669 if(t3d) {delete t3d; t3d=0;}
01670
01671 float phi = p["phi"];
01672 float theta = p["theta"];
01673 float psi = p["psi"];
01674 anglelist.push_back(phi);
01675 anglelist.push_back(theta);
01676 anglelist.push_back(psi);
01677 nangles = 1;
01678 }
01679
01680
01681 dm = new float[nangles*9];
01682 setdm(anglelist, angletype, dm);
01683
01684
01685 EMData *ret = new EMData();
01686 ret->set_size(nxvol, nyvol, nangles);
01687 ret->set_complex(false);
01688 ret->set_ri(true);
01689
01690 images = ret->get_data();
01691
01692 for (j = 1; j <= nangles; j++) {
01693 status = fwdpj3(volsize, nrays, nnz , &dm(1,j), origin, ri,
01694 ptrs , cord, sphere, &images(1,1,j));
01695
01696 }
01697
01698
01699 EMDeleteArray(dm);
01700 EMDeleteArray(ptrs);
01701 EMDeleteArray(cord);
01702 EMDeleteArray(sphere);
01703
01704 if (!params.has_key("anglelist")) {
01705 Transform* t3d = params["transform"];
01706 ret->set_attr("xform.projection",t3d);
01707 if(t3d) {delete t3d; t3d=0;}
01708 }
01709 ret->update();
01710 return ret;
01711 }
01712
01713
01714 #undef images
01715
01716 #define images(i,j,k) images[ ((k)-1)*nximg*nyimg + ((j)-1)*nximg + (i)-1 ]
01717
01718 EMData *ChaoProjector::backproject3d(EMData * imagestack) const
01719 {
01720 int nrays, nnz, status, j;
01721 float *dm;
01722 int *ptrs, *cord;
01723 float *sphere, *images, *cube;
01724
01725 int nximg = imagestack->get_xsize();
01726 int nyimg = imagestack->get_ysize();
01727 int nslices = imagestack->get_zsize();
01728
01729 int dim = Util::get_min(nximg,nyimg);
01730 Vec3i volsize(nximg,nyimg,dim);
01731
01732 Vec3i origin(0,0,0);
01733
01734
01735 if (params.has_key("origin_x")) {origin[0] = params["origin_x"];}
01736 else {origin[0] = nximg/2+1;}
01737 if (params.has_key("origin_y")) {origin[1] = params["origin_y"];}
01738 else {origin[1] = nyimg/2+1;}
01739 if (params.has_key("origin_z")) {origin[1] = params["origin_z"];}
01740 else {origin[2] = dim/2+1;}
01741
01742 int ri;
01743 if (params.has_key("radius")) {ri = params["radius"];}
01744 else {ri = dim/2 - 1;}
01745
01746
01747 images = imagestack->get_data();
01748
01749
01750
01751 status = getnnz(volsize, ri, origin, &nrays, &nnz);
01752
01753
01754
01755 sphere = new float[nnz];
01756 ptrs = new int[nrays+1];
01757 cord = new int[3*nrays];
01758 if (sphere == NULL || ptrs == NULL || cord == NULL) {
01759 fprintf(stderr,"ChaoProjector::backproject3d, failed to allocate!\n");
01760 exit(1);
01761 }
01762 for (int i = 0; i<nnz; i++) sphere[i] = 0.0;
01763 for (int i = 0; i<nrays+1; i++) ptrs[i] = 0;
01764 for (int i = 0; i<3*nrays; i++) cord[i] = 0;
01765
01766 int nangles = 0;
01767 vector<float> anglelist;
01768 string angletype = "SPIDER";
01769
01770 if (params.has_key("anglelist")) {
01771 anglelist = params["anglelist"];
01772 nangles = anglelist.size() / 3;
01773 } else {
01774 Transform* t3d = params["transform"];
01775 if ( t3d == NULL ) throw NullPointerException("The transform object (required for projection), was not specified");
01776
01777
01778
01779
01780
01781 Dict p = t3d->get_rotation("spider");
01782 if(t3d) {delete t3d; t3d=0;}
01783
01784 float phi = p["phi"];
01785 float theta = p["theta"];
01786 float psi = p["psi"];
01787 anglelist.push_back(phi);
01788 anglelist.push_back(theta);
01789 anglelist.push_back(psi);
01790 nangles = 1;
01791 }
01792
01793
01794
01795 if (nslices != nangles) {
01796 LOGERR("the number of images does not match the number of angles");
01797 return 0;
01798 }
01799
01800 dm = new float[nangles*9];
01801 setdm(anglelist, angletype, dm);
01802
01803
01804 EMData *ret = new EMData();
01805 ret->set_size(nximg, nyimg, dim);
01806 ret->set_complex(false);
01807 ret->set_ri(true);
01808 ret->to_zero();
01809
01810 cube = ret->get_data();
01811
01812 status = cb2sph(cube, volsize, ri, origin, nnz, ptrs, cord, sphere);
01813
01814
01815 for (j = 1; j <= nangles; j++) {
01816 status = bckpj3(volsize, nrays, nnz, &dm(1,j), origin, ri,
01817 ptrs , cord , &images(1,1,j), sphere);
01818
01819 }
01820
01821 status = sph2cb(sphere, volsize, nrays, ri, nnz, ptrs, cord, cube);
01822
01823
01824
01825 EMDeleteArray(dm);
01826 EMDeleteArray(ptrs);
01827 EMDeleteArray(cord);
01828 EMDeleteArray(sphere);
01829
01830 ret->update();
01831 return ret;
01832 }
01833
01834 #undef images
01835 #undef cube
01836 #undef sphere
01837 #undef cord
01838 #undef ptrs
01839 #undef dm
01840
01841 EMData *GaussFFTProjector::backproject3d(EMData * ) const
01842 {
01843
01844 EMData *ret = new EMData();
01845 return ret;
01846 }
01847
01848 #define images(i,j,k) images[ (k)*nx*ny + ((j)-1)*nx + (i)-1 ]
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964 EMData *PawelProjector::backproject3d(EMData * imagestack) const
01965 {
01966
01967 float *images;
01968
01969 if (!imagestack) {
01970 return 0;
01971 }
01972 int ri;
01973 int nx = imagestack->get_xsize();
01974 int ny = imagestack->get_ysize();
01975
01976 int dim = Util::get_min(nx,ny);
01977 images = imagestack->get_data();
01978
01979 Vec3i origin(0,0,0);
01980
01981
01982 if (params.has_key("origin_x")) {origin[0] = params["origin_x"];}
01983 else {origin[0] = nx/2;}
01984 if (params.has_key("origin_y")) {origin[1] = params["origin_y"];}
01985 else {origin[1] = ny/2;}
01986 if (params.has_key("origin_z")) {origin[1] = params["origin_z"];}
01987 else {origin[2] = dim/2;}
01988
01989 if (params.has_key("radius")) {ri = params["radius"];}
01990 else {ri = dim/2 - 1;}
01991
01992
01993 int nn = -1;
01994 prepcubes(nx, ny, dim, ri, origin, nn);
01995
01996
01997 IPCube* ipcube = new IPCube[nn+1];
01998 prepcubes(nx, ny, dim, ri, origin, nn, ipcube);
01999
02000 int nangles = 0;
02001 vector<float> anglelist;
02002
02003 if (params.has_key("anglelist")) {
02004 anglelist = params["anglelist"];
02005 nangles = anglelist.size() / 3;
02006 } else {
02007 Transform* t3d = params["transform"];
02008 if ( t3d == NULL ) throw NullPointerException("The transform object (required for projection), was not specified");
02009
02010
02011
02012
02013 Dict p = t3d->get_rotation("spider");
02014 if(t3d) {delete t3d; t3d=0;}
02015
02016 string angletype = "SPIDER";
02017 float phi = p["phi"];
02018 float theta = p["theta"];
02019 float psi = p["psi"];
02020 anglelist.push_back(phi);
02021 anglelist.push_back(theta);
02022 anglelist.push_back(psi);
02023 nangles = 1;
02024 }
02025
02026
02027
02028
02029 EMData* ret = new EMData();
02030 ret->set_size(nx, ny, dim);
02031 ret->to_zero();
02032
02033
02034 for (int ia = 0; ia < nangles; ia++) {
02035 int indx = 3*ia;
02036 Dict d("type","spider","phi",anglelist[indx],"theta",anglelist[indx+1],"psi",anglelist[indx+2]);
02037 Transform rotation(d);
02038 float dm1 = rotation.at(0,0);
02039 float dm4 = rotation.at(1,0);
02040
02041 if (2*(ri+1)+1 > dim) {
02042
02043 LOGERR("backproject3d, pawel, 2*(ri+1)+1 > dim\n");
02044 return 0;
02045 } else {
02046
02047 for (int i = 0 ; i <= nn; i++) {
02048 int iox = (int)ipcube[i].loc[0]+origin[0];
02049 int ioy = (int)ipcube[i].loc[1]+origin[1];
02050 int ioz = (int)ipcube[i].loc[2]+origin[2];
02051
02052 Vec3f vb = rotation*ipcube[i].loc + origin;
02053 for (int j = ipcube[i].start; j <= ipcube[i].end; j++) {
02054 float xbb = (j-ipcube[i].start)*dm1 + vb[0];
02055 int iqx = (int)floor(xbb);
02056
02057 float ybb = (j-ipcube[i].start)*dm4 + vb[1];
02058 int iqy = (int)floor(ybb);
02059
02060 float dipx = xbb - iqx;
02061 float dipy = ybb - iqy;
02062
02063 (*ret)(iox,ioy,ioz) += images(iqx,iqy,ia)
02064 + dipy*(images(iqx,iqy+1,ia)-images(iqx,iqy,ia))
02065 + dipx*(images(iqx+1,iqy,ia)-images(iqx,iqy,ia)
02066 + dipy*(images(iqx+1,iqy+1,ia)-images(iqx+1,iqy,ia)
02067 - images(iqx,iqy+1,ia)+images(iqx,iqy,ia)));
02068 iox++;
02069 }
02070 }
02071 }
02072 }
02073
02074 ret->update();
02075 EMDeleteArray(ipcube);
02076 return ret;
02077 }
02078 #undef images
02079
02080 EMData *StandardProjector::backproject3d(EMData * ) const
02081 {
02082
02083 EMData *ret = new EMData();
02084 return ret;
02085 }
02086
02087 EMData *FourierGriddingProjector::backproject3d(EMData * ) const
02088 {
02089
02090 EMData *ret = new EMData();
02091 return ret;
02092 }
02093
02094
02095
02096 void EMAN::dump_projectors()
02097 {
02098 dump_factory < Projector > ();
02099 }
02100
02101 map<string, vector<string> > EMAN::dump_projectors_list()
02102 {
02103 return dump_factory_list < Projector > ();
02104 }
02105
02106