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