projector.cpp

Go to the documentation of this file.
00001 
00005 /*
00006  * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
00007  * Copyright (c) 2000-2006 Baylor College of Medicine
00008  *
00009  * This software is issued under a joint BSD/GNU license. You may use the
00010  * source code in this file under either license. However, note that the
00011  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00012  * so you are responsible for compliance with the licenses of these packages
00013  * if you opt to use BSD licensing. The warranty disclaimer below holds
00014  * in either instance.
00015  *
00016  * This complete copyright notice must be included in any revised version of the
00017  * source code. Additional authorship citations may be added, but existing
00018  * author citations must be preserved.
00019  *
00020  * This program is free software; you can redistribute it and/or modify
00021  * it under the terms of the GNU General Public License as published by
00022  * the Free Software Foundation; either version 2 of the License, or
00023  * (at your option) any later version.
00024  *
00025  * This program is distributed in the hope that it will be useful,
00026  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00028  * GNU General Public License for more details.
00029  *
00030  * You should have received a copy of the GNU General Public License
00031  * along with this program; if not, write to the Free Software
00032  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00033  *
00034  * */
00035 
00036 #include "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 //      force_add<XYZProjector>();
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 //      throw InvalidParameterException("Error, unkown mode");
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                                         // first pixel on this line
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                                         // second or later pixel on this line
00563                                         if (ipcube != NULL) {
00564                                                 if (rc <= r) ipcube[nn].end = i3;
00565                                         }
00566                                 }
00567                         }
00568                 }
00569         }
00570 }
00571 
00572 // EMData *PawelProjector::project3d(EMData * image) const
00573 // {
00574 //      if (!image) {
00575 //              return 0;
00576 //      }
00577 //      int ri;
00578 //      int nx = image->get_xsize();
00579 //      int ny = image->get_ysize();
00580 //      int nz = image->get_zsize();
00581 //      int dim = Util::get_min(nx,ny,nz);
00582 //      if (nz == 1) {
00583 //              LOGERR("The PawelProjector needs a volume!");
00584 //              return 0;
00585 //      }
00586 //      Vec3i origin(0,0,0);
00587 //      // If a sensible origin isn't passed in, choose the middle of
00588 //      // the cube.
00589 //      if (params.has_key("origin_x")) {origin[0] = params["origin_x"];}
00590 //      else {origin[0] = nx/2;}
00591 //      if (params.has_key("origin_y")) {origin[1] = params["origin_y"];}
00592 //      else {origin[1] = ny/2;}
00593 //      if (params.has_key("origin_z")) {origin[2] = params["origin_z"];}
00594 //      else {origin[2] = nz/2;}
00595 //
00596 //      if (params.has_key("radius")) {ri = params["radius"];}
00597 //      else {ri = dim/2 - 1;}
00598 //
00599 //      // Determine the number of rows (x-lines) within the radius
00600 //      int nn = -1;
00601 //      prepcubes(nx, ny, nz, ri, origin, nn);
00602 //      // nn is now the number of rows-1 within the radius
00603 //      // so we can create and fill the ipcubes
00604 //      IPCube* ipcube = new IPCube[nn+1];
00605 //      prepcubes(nx, ny, nz, ri, origin, nn, ipcube);
00606 //
00607 //      int nangles = 0;
00608 //      vector<float> anglelist;
00609 //      // Do we have a list of angles?
00610 //      if (params.has_key("anglelist")) {
00611 //              anglelist = params["anglelist"];
00612 //              nangles = anglelist.size() / 3;
00613 //      } else {
00614 //              Transform3D* t3d = params["t3d"];
00615 //              if ( t3d == NULL ) throw NullPointerException("The transform3d object (required for projection), was not specified");
00616 //
00617 //              // This part was modified by David Woolford -
00618 //              // Before this the code worked only for SPIDER and EMAN angles,
00619 //              // but the framework of the Transf      orm3D allows for a generic implementation
00620 //              // as specified here.
00621 //              Dict p = t3d->get_rotation(Transform3D::SPIDER);
00622 //
00623 //              string angletype = "SPIDER";
00624 //              float phi = p["phi"];
00625 //              float theta = p["theta"];
00626 //              float psi = p["psi"];
00627 //              anglelist.push_back(phi);
00628 //              anglelist.push_back(theta);
00629 //              anglelist.push_back(psi);
00630 //              nangles = 1;
00631 //      }
00632 //
00633 //      // End David Woolford modifications
00634 //
00635 //      // initialize return object
00636 //      EMData* ret = new EMData();
00637 //      ret->set_size(nx, ny, nangles);
00638 //      ret->to_zero();
00639 //
00640 //      // loop over sets of angles
00641 //      for (int ia = 0; ia < nangles; ia++) {
00642 //              int indx = 3*ia;
00643 //              Transform3D rotation(Transform3D::SPIDER, anglelist[indx],anglelist[indx+1], anglelist[indx+2]);
00644 //              if (2*(ri+1)+1 > dim) {
00645 //                      // Must check x and y boundaries
00646 //                      for (int i = 0 ; i <= nn; i++) {
00647 //                              int k = ipcube[i].loc[1] + origin[1];
00648 //                              Vec3f vb = ipcube[i].loc*rotation + origin;
00649 //                              for (int j = ipcube[i].start; j <= ipcube[i].end; j++) {
00650 //                                      // check for pixels out-of-bounds
00651 //                                      int iox = int(vb[0]);
00652 //                                      if ((iox >= 0) && (iox < nx-1)) {
00653 //                                              int ioy = int(vb[1]);
00654 //                                              if ((ioy >= 0) && (ioy < ny-1)) {
00655 //                                                      int ioz = int(vb[2]);
00656 //                                                      if ((ioz >= 0) && (ioz < nz-1)) {
00657 //                                                              // real work for pixels in bounds
00658 //                                                              float dx = vb[0] - iox;
00659 //                                                              float dy = vb[1] - ioy;
00660 //                                                              float dz = vb[2] - ioz;
00661 //                                                              float a1 = (*image)(iox,ioy,ioz);
00662 //                                                              float a2 = (*image)(iox+1,ioy,ioz) - a1;
00663 //                                                              float a3 = (*image)(iox,ioy+1,ioz) - a1;
00664 //                                                              float a4 = (*image)(iox,ioy,ioz+1) - a1;
00665 //                                                              float a5 = -a2 -(*image)(iox,ioy+1,ioz)
00666 //                                                                      + (*image)(iox+1,ioy+1,ioz);
00667 //                                                              float a61 = -(*image)(iox,ioy,ioz+1)
00668 //                                                                      + (*image)(iox+1,ioy,ioz+1);
00669 //                                                              float a6 = -a2 + a61;
00670 //                                                              float a7 = -a3 - (*image)(iox,ioy,ioz+1)
00671 //                                                                      + (*image)(iox,ioy+1,ioz+1);
00672 //                                                              float a8 = -a5 - a61 - (*image)(iox,ioy+1,ioz+1)
00673 //                                                                      + (*image)(iox+1,ioy+1,ioz+1);
00674 //                                                              (*ret)(j,k,ia) += a1 + dz*(a4 + a6*dx
00675 //                                                                      + (a7 + a8*dx)*dy)
00676 //                                                                      + a3*dy + dx*(a2 + a5*dy);
00677 //                                                      }
00678 //                                              }
00679 //                                      }
00680 //                                      vb += rotation.get_matrix3_row(0);
00681 //                              }
00682 //                      }
00683 //
00684 //              } else {
00685 //                      // No need to check x and y boundaries
00686 //                      for (int i = 0 ; i <= nn; i++) {
00687 //                              int k = ipcube[i].loc[1] + origin[1];
00688 //                              Vec3f vb = ipcube[i].loc*rotation + origin;
00689 //                              for (int j = ipcube[i].start; j <= ipcube[i].end; j++) {
00690 //                                      int iox = int(vb[0]);
00691 //                                      int ioy = int(vb[1]);
00692 //                                      int ioz = int(vb[2]);
00693 //                                      float dx = vb[0] - iox;
00694 //                                      float dy = vb[1] - ioy;
00695 //                                      float dz = vb[2] - ioz;
00696 //                                      float a1 = (*image)(iox,ioy,ioz);
00697 //                                      float a2 = (*image)(iox+1,ioy,ioz) - a1;
00698 //                                      float a3 = (*image)(iox,ioy+1,ioz) - a1;
00699 //                                      float a4 = (*image)(iox,ioy,ioz+1) - a1;
00700 //                                      float a5 = -a2 -(*image)(iox,ioy+1,ioz)
00701 //                                              + (*image)(iox+1,ioy+1,ioz);
00702 //                                      float a61 = -(*image)(iox,ioy,ioz+1)
00703 //                                              + (*image)(iox+1,ioy,ioz+1);
00704 //                                      float a6 = -a2 + a61;
00705 //                                      float a7 = -a3 - (*image)(iox,ioy,ioz+1)
00706 //                                              + (*image)(iox,ioy+1,ioz+1);
00707 //                                      float a8 = -a5 - a61 - (*image)(iox,ioy+1,ioz+1)
00708 //                                              + (*image)(iox+1,ioy+1,ioz+1);
00709 //                                      (*ret)(j,k,ia) += a1 + dz*(a4 + a6*dx
00710 //                                                      + (a7 + a8*dx)*dy)
00711 //                                              + a3*dy + dx*(a2 + a5*dy);
00712 //                                      vb += rotation.get_matrix3_row(0);
00713 //                              }
00714 //                      }
00715 //              }
00716 //      }
00717 //      ret->update();
00718 //      EMDeleteArray(ipcube);
00719 //      return ret;
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         // If a sensible origin isn't passed in, choose the middle of
00739         // the cube.
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         // Determine the number of rows (x-lines) within the radius
00751         int nn = -1;
00752         prepcubes(nx, ny, nz, ri, origin, nn);
00753         // nn is now the number of rows-1 within the radius
00754         // so we can create and fill the ipcubes
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         // Do we have a list of angles?
00762         /*
00763         if (params.has_key("anglelist")) {
00764                 anglelist = params["anglelist"];
00765                 nangles = anglelist.size() / 3;
00766         } else {*/
00767 
00768                 if ( rotation == NULL ) throw NullPointerException("The transform object (required for projection), was not specified");
00769                 /*
00770                 Dict p = t3d->get_rotation("spider");
00771 
00772                 string angletype = "SPIDER";
00773                 float phi = p["phi"];
00774                 float theta = p["theta"];
00775                 float psi = p["psi"];
00776                 anglelist.push_back(phi);
00777                 anglelist.push_back(theta);
00778                 anglelist.push_back(psi);
00779                 */
00780                 nangles = 1;
00781         //}
00782 
00783         // initialize return object
00784         EMData* ret = new EMData();
00785         ret->set_size(nx, ny, nangles);
00786         ret->to_zero();
00787 
00788         // loop over sets of angles
00789         for (int ia = 0; ia < nangles; ia++) {
00790                 //int indx = 3*ia;
00791                 //Dict d("type","spider","phi",anglelist[indx],"theta",anglelist[indx+1],"psi",anglelist[indx+2]);
00792                 //Transform rotation(d);
00793                 if (2*(ri+1)+1 > dim) {
00794                         // Must check x and y boundaries
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                                         // check for pixels out-of-bounds
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                                                                 // real work for pixels in bounds
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                         // No need to check x and y boundaries
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 //      Dict p = t3d->get_rotation();
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                         //cout << "CUDA PROJ" << endl;
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                         //EMData *e = new EMData();
00891                         //e->set_size(image->get_xsize(), image->get_ysize(), 1);
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                         //e_>copy_from_device();
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 //              Transform3D r(Transform3D::EMAN, az, alt, phi);
00909                 Transform r = t3d->inverse(); // The inverse is taken here because we are rotating the coordinate system, not the image
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 //                                      printf(" ");
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(); // The inverse is taken here because we are rotating the coordinate system, not the image
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++) { // j represents a column of pixels in the direction of the angle
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 // EMData *FourierGriddingProjector::project3d(EMData * image) const
01049 // {
01050 //      if (!image) {
01051 //              return 0;
01052 //      }
01053 //      if (3 != image->get_ndim())
01054 //              throw ImageDimensionException(
01055 //                              "FourierGriddingProjector needs a 3-D volume");
01056 //      if (image->is_complex())
01057 //              throw ImageFormatException(
01058 //                              "FourierGriddingProjector requires a real volume");
01059 //      const int npad = params.has_key("npad") ? int(params["npad"]) : 2;
01060 //      const int nx = image->get_xsize();
01061 //      const int ny = image->get_ysize();
01062 //      const int nz = image->get_zsize();
01063 //      if (nx != ny || nx != nz)
01064 //              throw ImageDimensionException(
01065 //                              "FourierGriddingProjector requires nx==ny==nz");
01066 //      const int m = Util::get_min(nx,ny,nz);
01067 //      const int n = m*npad;
01068 //
01069 //      int K = params["kb_K"];
01070 //      if ( K == 0 ) K = 6;
01071 //      float alpha = params["kb_alpha"];
01072 //      if ( alpha == 0 ) alpha = 1.25;
01073 //      Util::KaiserBessel kb(alpha, K, (float)(m/2), K/(2.0f*n), n);
01074 //
01075 //      // divide out gridding weights
01076 //      EMData* tmpImage = image->copy();
01077 //      tmpImage->divkbsinh(kb);
01078 //      // pad and center volume, then FFT and multiply by (-1)**(i+j+k)
01079 //      //EMData* imgft = tmpImage->pad_fft(npad);
01080 //      //imgft->center_padded();
01081 //      EMData* imgft = tmpImage->norm_pad(false, npad);
01082 //      imgft->do_fft_inplace();
01083 //      imgft->center_origin_fft();
01084 //      imgft->fft_shuffle();
01085 //      delete tmpImage;
01086 //
01087 //      // Do we have a list of angles?
01088 //      int nangles = 0;
01089 //      vector<float> anglelist;
01090 //      // Do we have a list of angles?
01091 //      if (params.has_key("anglelist")) {
01092 //              anglelist = params["anglelist"];
01093 //              nangles = anglelist.size() / 3;
01094 //      } else {
01095 //              // This part was modified by David Woolford -
01096 //              // Before this the code worked only for SPIDER and EMAN angles,
01097 //              // but the framework of the Transform3D allows for a generic implementation
01098 //              // as specified here.
01099 //              Transform3D* t3d = params["t3d"];
01100 //              if ( t3d == NULL ) throw NullPointerException("The transform3d object (required for projection), was not specified");
01101 //              Dict p = t3d->get_rotation(Transform3D::SPIDER);
01102 //
01103 //              string angletype = "SPIDER";
01104 //              float phi = p["phi"];
01105 //              float theta = p["theta"];
01106 //              float psi = p["psi"];
01107 //              anglelist.push_back(phi);
01108 //              anglelist.push_back(theta);
01109 //              anglelist.push_back(psi);
01110 //              nangles = 1;
01111 //      }
01112 //
01113 //      // End David Woolford modifications
01114 //
01115 //      // initialize return object
01116 //      EMData* ret = new EMData();
01117 //      ret->set_size(nx, ny, nangles);
01118 //      ret->to_zero();
01119 //      // loop over sets of angles
01120 //      for (int ia = 0; ia < nangles; ia++) {
01121 //              int indx = 3*ia;
01122 //              Transform3D tf(Transform3D::SPIDER, anglelist[indx],anglelist[indx+1],anglelist[indx+2]);
01123 //              EMData* proj = imgft->extractplane(tf, kb);
01124 //              if (proj->is_shuffled()) proj->fft_shuffle();
01125 //              proj->center_origin_fft();
01126 //              proj->do_ift_inplace();
01127 //              EMData* winproj = proj->window_center(m);
01128 //              delete proj;
01129 //              for (int iy=0; iy < ny; iy++)
01130 //                      for (int ix=0; ix < nx; ix++)
01131 //                              (*ret)(ix,iy,ia) = (*winproj)(ix,iy);
01132 //              delete winproj;
01133 //      }
01134 //      delete imgft;
01135 //      ret->update();
01136 //
01137 //      return ret;
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         // divide out gridding weights
01169         EMData* tmpImage = image->copy();
01170         tmpImage->divkbsinh(kb);
01171         // pad and center volume, then FFT and multiply by (-1)**(i+j+k)
01172         //EMData* imgft = tmpImage->pad_fft(npad);
01173         //imgft->center_padded();
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         // Do we have a list of angles?
01181         int nangles = 0;
01182         vector<float> anglelist;
01183         // Do we have a list of angles?
01184         if (params.has_key("anglelist")) {
01185                 anglelist = params["anglelist"];
01186                 nangles = anglelist.size() / 3;
01187         } else {
01188                 // This part was modified by David Woolford -
01189                 // Before this the code worked only for SPIDER and EMAN angles,
01190                 // but the framework of the Transform3D allows for a generic implementation
01191                 // as specified here.
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         // End David Woolford modifications
01208 
01209         // initialize return object
01210         EMData* ret = new EMData();
01211         ret->set_size(nx, ny, nangles);
01212         ret->to_zero();
01213         // loop over sets of angles
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 // BEGIN Chao projectors and backprojector addition (04/25/06)
01241 int ChaoProjector::getnnz(Vec3i volsize, int ri, Vec3i origin, int *nrays, int *nnz) const
01242 /*
01243    purpose: count the number of voxels within a sphere centered
01244             at origin and with a radius ri.
01245 
01246      input:
01247      volsize contains the size information (nx,ny,nz) about the volume
01248      ri      radius of the object embedded in the cube.
01249      origin  coordinates for the center of the volume
01250 
01251      output:
01252      nnz    total number of voxels within the sphere (of radius ri)
01253      nrays  number of rays in z-direction.
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         // need to add some error checking
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             } // end for iy
01291         } // end for ix
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            // not the most efficient implementation
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                   //  record the coordinates of the first nonzero ===
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             } // end for (iz..)
01350             if (jnz > 0) {
01351                 ptrs(nrays+1) = ptrs(nrays) + jnz;
01352             }  // endif (jnz)
01353        } // end for iy
01354     } // end for ix
01355     if (nnz != nnz0) status = -1;
01356     return status;
01357 }
01358 
01359 // decompress sphere into a cube
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     // int nz = (int)volsize[2];
01369 
01370     r2      = ri*ri;
01371     nnz     = 0;
01372     ptrs(1) = 1;
01373 
01374     // no need to initialize
01375     // for (i = 0; i<nx*ny*nz; i++) cube[i]=0.0;
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 // project from 3D to 2D (single image)
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         purpose:  y <--- proj(x)
01401         input  :  volsize  the size (nx,ny,nz) of the volume
01402                   nrays    number of rays within the compact spherical
01403                            representation
01404                   nnz      number of voxels within the sphere
01405                   dm       an array of size 9 storing transformation
01406                            associated with the projection direction
01407                   origin   coordinates of the center of the volume
01408                   ri       radius of the sphere
01409                   ptrs     the beginning address of each ray
01410                   cord     the coordinates of the first point in each ray
01411                   x        3d input volume
01412                   y        2d output image
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 // backproject from 2D to 3D for a single image
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 c               y(j) = y(j) + dx1m*dy1m*x(iqx  , iqy)
01505 c     &                     + dx1m*dy  *x(iqx  , iqy+1)
01506 c     &                     + dx  *dy1m*x(iqx+1, iqy)
01507 c     &                     + dx  *dy  *x(iqx+1, iqy+1)
01508 c
01509 c              --- faster version of the above commented out
01510 c                  code (derived by summing the following table
01511 c                  of coefficients along  the colunms) ---
01512 c
01513 c                        1         dx        dy      dxdy
01514 c                     ------   --------  --------  -------
01515 c                      x(i,j)   -x(i,j)   -x(i,j)    x(i,j)
01516 c                                        x(i,j+1) -x(i,j+1)
01517 c                              x(i+1,j)           -x(i+1,j)
01518 c                                                x(i+1,j+1)
01519 c
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             } // end for j
01530         } // end for i
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 // funny F90 style strange rounding function
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 // SPIDER stype transformation
01561 void ChaoProjector::setdm(vector<float> anglelist, string const , float *dm) const
01562 { // convert Euler angles to transformations, dm is an 9 by nangles array
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         // now convert all angles
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                 //              cout << phi << " " << theta << " " << psi << endl;
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         // If a sensible origin isn't passed in, choose the middle of
01619         // the cube.
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         // retrieve the voxel values
01632         float *cube = vol->get_data();
01633 
01634         // count the number of voxels within a sphere centered at icent,
01635         // with radius ri
01636         status = getnnz(volsize, ri, origin, &nrays, &nnz);
01637         // need to check status...
01638 
01639         // convert from cube to sphere
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         // check status
01653 
01654         int nangles = 0;
01655         vector<float> anglelist;
01656         string angletype = "SPIDER";
01657         // Do we have a list of angles?
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                 // This part was modified by David Woolford -
01665                 // Before this the code worked only for SPIDER and EMAN angles,
01666                 // but the framework of the Transform3D allows for a generic implementation
01667                 // as specified here.
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         // End David Woolford modifications
01680 
01681         dm = new float[nangles*9];
01682         setdm(anglelist, angletype, dm);
01683 
01684                 // return images
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         // check status?
01696         }
01697 
01698         // deallocate all temporary work space
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 // backproject from 2D to 3D (multiple images)
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         // If a sensible origin isn't passed in, choose the middle of
01734         // the cube.
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         // retrieve the voxel values
01747         images = imagestack->get_data();
01748 
01749         // count the number of voxels within a sphere centered at icent,
01750         // with radius ri
01751         status = getnnz(volsize, ri, origin, &nrays, &nnz);
01752         // need to check status...
01753 
01754         // convert from cube to sphere
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         // Do we have a list of angles?
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                 // This part was modified by David Woolford -
01777                 // Before this the code worked only for SPIDER and EMAN angles,
01778                 // but the framework of the Transform3D allows for a generic implementation
01779                 // as specified here.
01780                 //  This was broken by david.  we need here a loop over all projections and put all angles on stack  PAP 06/28/09
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         // End David Woolford modifications
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         // return volume
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         // cb2sph should be replaced by something that touches only ptrs and cord
01812         status = cb2sph(cube, volsize, ri, origin, nnz, ptrs, cord, sphere);
01813         // check status
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         // check status?
01819         }
01820 
01821         status = sph2cb(sphere, volsize, nrays, ri, nnz, ptrs, cord, cube);
01822         // check status?
01823 
01824         // deallocate all temporary work space
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     // no implementation yet
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 // EMData *PawelProjector::backproject3d(EMData * imagestack) const
01851 // {
01852 //
01853 //     float *images;
01854 //
01855 //     if (!imagestack) {
01856 //      return 0;
01857 //     }
01858 //     int ri;
01859 //     int nx      = imagestack->get_xsize();
01860 //     int ny      = imagestack->get_ysize();
01861 // //     int nslices = imagestack->get_zsize();
01862 //     int dim = Util::get_min(nx,ny);
01863 //     images  = imagestack->get_data();
01864 //
01865 //     Vec3i origin(0,0,0);
01866 //     // If a sensible origin isn't passed in, choose the middle of
01867 //     // the cube.
01868 //     if (params.has_key("origin_x")) {origin[0] = params["origin_x"];}
01869 //     else {origin[0] = nx/2;}
01870 //     if (params.has_key("origin_y")) {origin[1] = params["origin_y"];}
01871 //     else {origin[1] = ny/2;}
01872 //     if (params.has_key("origin_z")) {origin[1] = params["origin_z"];}
01873 //     else {origin[2] = dim/2;}
01874 //
01875 //     if (params.has_key("radius")) {ri = params["radius"];}
01876 //     else {ri = dim/2 - 1;}
01877 //
01878 //     // Determine the number of rows (x-lines) within the radius
01879 //     int nn = -1;
01880 //     prepcubes(nx, ny, dim, ri, origin, nn);
01881 //     // nn is now the number of rows-1 within the radius
01882 //     // so we can create and fill the ipcubes
01883 //     IPCube* ipcube = new IPCube[nn+1];
01884 //     prepcubes(nx, ny, dim, ri, origin, nn, ipcube);
01885 //
01886 //      int nangles = 0;
01887 //      vector<float> anglelist;
01888 //      // Do we have a list of angles?
01889 //      if (params.has_key("anglelist")) {
01890 //              anglelist = params["anglelist"];
01891 //              nangles = anglelist.size() / 3;
01892 //      } else {
01893 //              Transform3D* t3d = params["t3d"];
01894 //              if ( t3d == NULL ) throw NullPointerException("The transform3d object (required for projection), was not specified");
01895 //              // This part was modified by David Woolford -
01896 //              // Before this the code worked only for SPIDER and EMAN angles,
01897 //              // but the framework of the Transform3D allows for a generic implementation
01898 //              // as specified here.
01899 //              Dict p = t3d->get_rotation(Transform3D::SPIDER);
01900 //
01901 //              string angletype = "SPIDER";
01902 //              float phi = p["phi"];
01903 //              float theta = p["theta"];
01904 //              float psi = p["psi"];
01905 //              anglelist.push_back(phi);
01906 //              anglelist.push_back(theta);
01907 //              anglelist.push_back(psi);
01908 //              nangles = 1;
01909 //      }
01910 //
01911 //      // End David Woolford modifications
01912 //
01913 //     // initialize return object
01914 //     EMData* ret = new EMData();
01915 //     ret->set_size(nx, ny, dim);
01916 //     ret->to_zero();
01917 //
01918 //     // loop over sets of angles
01919 //     for (int ia = 0; ia < nangles; ia++) {
01920 //        int indx = 3*ia;
01921 //         Transform3D rotation(Transform3D::SPIDER, float(anglelist[indx]),
01922 //                             float(anglelist[indx+1]),
01923 //                             float(anglelist[indx+2]));
01924 //        float dm1 = rotation.at(0,0);
01925 //        float dm4 = rotation.at(1,0);
01926 //
01927 //        if (2*(ri+1)+1 > dim) {
01928 //           // Must check x and y boundaries
01929 //           LOGERR("backproject3d, pawel, 2*(ri+1)+1 > dim\n");
01930 //           return 0;
01931 //        } else {
01932 //           // No need to check x and y boundaries
01933 //           for (int i = 0 ; i <= nn; i++) {
01934 //              int iox = (int)ipcube[i].loc[0]+origin[0];
01935 //              int ioy = (int)ipcube[i].loc[1]+origin[1];
01936 //              int ioz = (int)ipcube[i].loc[2]+origin[2];
01937 //
01938 //              Vec3f vb = rotation*ipcube[i].loc + origin;
01939 //              for (int j = ipcube[i].start; j <= ipcube[i].end; j++) {
01940 //                 float xbb = (j-ipcube[i].start)*dm1 + vb[0];
01941 //                 int   iqx = (int)floor(xbb);
01942 //
01943 //                 float ybb = (j-ipcube[i].start)*dm4 + vb[1];
01944 //                 int   iqy = (int)floor(ybb);
01945 //
01946 //                 float dipx = xbb - iqx;
01947 //                 float dipy = ybb - iqy;
01948 //
01949 //                 (*ret)(iox,ioy,ioz) += images(iqx,iqy,ia)
01950 //                     + dipy*(images(iqx,iqy+1,ia)-images(iqx,iqy,ia))
01951 //                     + dipx*(images(iqx+1,iqy,ia)-images(iqx,iqy,ia)
01952 //                     + dipy*(images(iqx+1,iqy+1,ia)-images(iqx+1,iqy,ia)
01953 //                     - images(iqx,iqy+1,ia)+images(iqx,iqy,ia)));
01954 //                 iox++;
01955 //              } // end for j
01956 //        } // end for i
01957 //        } // end if
01958 //     } // end for ia
01959 //
01960 //     ret->update();
01961 //     EMDeleteArray(ipcube);
01962 //     return ret;
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 //     int nslices = imagestack->get_zsize();
01976         int dim = Util::get_min(nx,ny);
01977         images  = imagestack->get_data();
01978 
01979         Vec3i origin(0,0,0);
01980     // If a sensible origin isn't passed in, choose the middle of
01981     // the cube.
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     // Determine the number of rows (x-lines) within the radius
01993         int nn = -1;
01994         prepcubes(nx, ny, dim, ri, origin, nn);
01995     // nn is now the number of rows-1 within the radius
01996     // so we can create and fill the ipcubes
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         // Do we have a list of angles?
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                 // This part was modified by David Woolford -
02010                 // Before this the code worked only for SPIDER and EMAN angles,
02011                 // but the framework of the Transform3D allows for a generic implementation
02012                 // as specified here.
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         // End David Woolford modifications
02027 
02028     // initialize return object
02029         EMData* ret = new EMData();
02030         ret->set_size(nx, ny, dim);
02031         ret->to_zero();
02032 
02033     // loop over sets of angles
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           // Must check x and y boundaries
02043                         LOGERR("backproject3d, pawel, 2*(ri+1)+1 > dim\n");
02044                         return 0;
02045                 } else {
02046           // No need to check x and y boundaries
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                                 } // end for j
02070                         } // end for i
02071                 } // end if
02072         } // end for ia
02073 
02074         ret->update();
02075         EMDeleteArray(ipcube);
02076         return ret;
02077 }
02078 #undef images
02079 
02080 EMData *StandardProjector::backproject3d(EMData * ) const
02081 {
02082    // no implementation yet
02083    EMData *ret = new EMData();
02084    return ret;
02085 }
02086 
02087 EMData *FourierGriddingProjector::backproject3d(EMData * ) const
02088 {
02089    // no implementation yet
02090    EMData *ret = new EMData();
02091    return ret;
02092 }
02093 
02094 // End Chao's projector addition 4/25/06
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 /* vim: set ts=4 noet nospell: */

Generated on Mon May 2 13:26:55 2011 for EMAN2 by  doxygen 1.4.7