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

Generated on Sat Nov 21 02:19:16 2009 for EMAN2 by  doxygen 1.5.6